From ff78b7c113ea6109f6a57c4886212b0895eefc39 Mon Sep 17 00:00:00 2001 From: Dmytro Popov Date: Thu, 25 May 2023 11:48:34 +0100 Subject: [PATCH 1/3] Added `dispose` to the `LanguageCheckService` This should fix the potential memory leaks from using the `Throttling` and `Debounce` classes. --- lib/core/controllers/colored_text_editing_controller.dart | 6 ++++++ lib/domain/language_check_service.dart | 6 ++++++ lib/implementations/debounce_lang_tool_service.dart | 7 +++++++ lib/implementations/throttling_lang_tool_service.dart | 7 +++++++ 4 files changed, 26 insertions(+) diff --git a/lib/core/controllers/colored_text_editing_controller.dart b/lib/core/controllers/colored_text_editing_controller.dart index f499d50..ff62ea2 100644 --- a/lib/core/controllers/colored_text_editing_controller.dart +++ b/lib/core/controllers/colored_text_editing_controller.dart @@ -53,6 +53,12 @@ class ColoredTextEditingController extends TextEditingController { ); } + @override + void dispose() { + languageCheckService.dispose(); + super.dispose(); + } + /// Replaces mistake with given replacement void replaceMistake(Mistake mistake, String replacement) { text = text.replaceRange(mistake.offset, mistake.endOffset, replacement); diff --git a/lib/domain/language_check_service.dart b/lib/domain/language_check_service.dart index 16843d9..5632f1b 100644 --- a/lib/domain/language_check_service.dart +++ b/lib/domain/language_check_service.dart @@ -7,4 +7,10 @@ abstract class LanguageCheckService { /// Returns found mistakes in the given [text]. Future> findMistakes(String text); + + /// Disposes resources of this [LanguageCheckService]. + Future dispose() async { + // does nothing by default, but implementations may need to use it + return; + } } diff --git a/lib/implementations/debounce_lang_tool_service.dart b/lib/implementations/debounce_lang_tool_service.dart index 7aabc2d..982931a 100644 --- a/lib/implementations/debounce_lang_tool_service.dart +++ b/lib/implementations/debounce_lang_tool_service.dart @@ -24,4 +24,11 @@ class DebounceLangToolService extends LanguageCheckService { return value ?? []; } + + @override + Future dispose() async { + await debouncing.close(); + + return baseService.dispose(); + } } diff --git a/lib/implementations/throttling_lang_tool_service.dart b/lib/implementations/throttling_lang_tool_service.dart index 139358c..505d20f 100644 --- a/lib/implementations/throttling_lang_tool_service.dart +++ b/lib/implementations/throttling_lang_tool_service.dart @@ -21,4 +21,11 @@ class ThrottlingLangToolService extends LanguageCheckService { Future> findMistakes(String text) => throttling.throttle(() => baseService.findMistakes(text)) as Future>; + + @override + Future dispose() async { + await throttling.close(); + + return baseService.dispose(); + } } From 1dc2ae7607d211d5a6a2adcfe4f52d5b72922abd Mon Sep 17 00:00:00 2001 From: Dmytro Popov Date: Thu, 25 May 2023 13:18:01 +0100 Subject: [PATCH 2/3] Changed `return` to `await` in `dispose` methods Applied the recommended change --- lib/implementations/debounce_lang_tool_service.dart | 3 +-- lib/implementations/throttling_lang_tool_service.dart | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/implementations/debounce_lang_tool_service.dart b/lib/implementations/debounce_lang_tool_service.dart index 982931a..b637844 100644 --- a/lib/implementations/debounce_lang_tool_service.dart +++ b/lib/implementations/debounce_lang_tool_service.dart @@ -28,7 +28,6 @@ class DebounceLangToolService extends LanguageCheckService { @override Future dispose() async { await debouncing.close(); - - return baseService.dispose(); + await baseService.dispose(); } } diff --git a/lib/implementations/throttling_lang_tool_service.dart b/lib/implementations/throttling_lang_tool_service.dart index 505d20f..9563587 100644 --- a/lib/implementations/throttling_lang_tool_service.dart +++ b/lib/implementations/throttling_lang_tool_service.dart @@ -25,7 +25,6 @@ class ThrottlingLangToolService extends LanguageCheckService { @override Future dispose() async { await throttling.close(); - - return baseService.dispose(); + await baseService.dispose(); } } From fabe0392d6891b41b14acbc297a3ccb8a755a33c Mon Sep 17 00:00:00 2001 From: Dmytro Popov Date: Fri, 26 May 2023 11:40:50 +0100 Subject: [PATCH 3/3] Added mistake range guards Resolves #39 --- .../controllers/colored_text_editing_controller.dart | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/core/controllers/colored_text_editing_controller.dart b/lib/core/controllers/colored_text_editing_controller.dart index ff62ea2..63a4efd 100644 --- a/lib/core/controllers/colored_text_editing_controller.dart +++ b/lib/core/controllers/colored_text_editing_controller.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:languagetool_textfield/core/enums/mistake_type.dart'; @@ -98,7 +100,7 @@ class ColoredTextEditingController extends TextEditingController { yield TextSpan( text: text.substring( currentOffset, - mistake.offset, + min(mistake.offset, text.length), ), style: style, ); @@ -119,7 +121,10 @@ class ColoredTextEditingController extends TextEditingController { yield TextSpan( children: [ TextSpan( - text: text.substring(mistake.offset, mistake.endOffset), + text: text.substring( + mistake.offset, + min(mistake.endOffset, text.length), + ), mouseCursor: MaterialStateMouseCursor.clickable, style: style?.copyWith( backgroundColor: mistakeColor.withOpacity( @@ -134,7 +139,7 @@ class ColoredTextEditingController extends TextEditingController { ], ); - currentOffset = mistake.endOffset; + currentOffset = min(mistake.endOffset, text.length); } /// TextSpan after mistake