From 6cd43c4db676999e7591840b0b8ab50d78093df9 Mon Sep 17 00:00:00 2001 From: Amir Panahandeh Date: Sun, 10 Dec 2023 14:57:40 +0330 Subject: [PATCH] Fix text direction auto format detection and undo (#191) * Fix text direction auto format detection and undo --- .../fleather/lib/src/widgets/autoformats.dart | 7 +++- .../fleather/lib/src/widgets/controller.dart | 18 +++++---- .../test/widgets/autoformats_test.dart | 39 +++++++++++++++++-- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/packages/fleather/lib/src/widgets/autoformats.dart b/packages/fleather/lib/src/widgets/autoformats.dart index aa563f6e..99144a2d 100644 --- a/packages/fleather/lib/src/widgets/autoformats.dart +++ b/packages/fleather/lib/src/widgets/autoformats.dart @@ -50,6 +50,10 @@ class AutoFormats { /// `true` if there is an active suggestion; `false` otherwise bool get hasActiveSuggestion => _activeSuggestion != null; + /// `true` if hasActiveSuggestion and undo delta is not empty; + /// `false` otherwise + bool get canUndo => hasActiveSuggestion && _activeSuggestion!.undo.isNotEmpty; + /// Perform detection of auto formats and apply changes to [document]. /// /// Inserted data must be of type [String]. @@ -335,7 +339,7 @@ class _AutoTextDirection extends AutoFormat { bool _isBeforeEmptyLine(Operation next, String data) { final nextData = next.data; - return nextData is String ? nextData.startsWith('$data\n') : false; + return nextData is String ? nextData.startsWith('\n') : false; } bool _isInEmptyLine(Operation? previous, Operation next, String data) => @@ -348,6 +352,7 @@ class _AutoTextDirection extends AutoFormat { final documentDelta = document.toDelta(); final iter = DeltaIterator(document.toDelta()); final previous = iter.skip(position); + iter.skip(data.length); final next = iter.next(); if (!_isInEmptyLine(previous, next, data)) return null; diff --git a/packages/fleather/lib/src/widgets/controller.dart b/packages/fleather/lib/src/widgets/controller.dart index d3f998d0..a28c15ac 100644 --- a/packages/fleather/lib/src/widgets/controller.dart +++ b/packages/fleather/lib/src/widgets/controller.dart @@ -173,15 +173,17 @@ class FleatherController extends ChangeNotifier { ParchmentDocument document, int position, int length, Object data) { if (!_autoFormats.hasActiveSuggestion) return true; - final isDeletionOfOneChar = data is String && data.isEmpty && length == 1; - if (isDeletionOfOneChar) { - // Undo if deleting 1 character after retain of auto-format - if (position == _autoFormats.undoPosition) { - final undoSelection = _autoFormats.undoActive(document); - if (undoSelection != null) { - _updateSelectionSilent(undoSelection, source: ChangeSource.local); + if (_autoFormats.canUndo) { + final isDeletionOfOneChar = data is String && data.isEmpty && length == 1; + if (isDeletionOfOneChar) { + // Undo if deleting 1 character after retain of auto-format + if (position == _autoFormats.undoPosition) { + final undoSelection = _autoFormats.undoActive(document); + if (undoSelection != null) { + _updateSelectionSilent(undoSelection, source: ChangeSource.local); + } + return false; } - return false; } } // Cancel active nevertheless diff --git a/packages/fleather/test/widgets/autoformats_test.dart b/packages/fleather/test/widgets/autoformats_test.dart index 1e440e30..b0e971ea 100644 --- a/packages/fleather/test/widgets/autoformats_test.dart +++ b/packages/fleather/test/widgets/autoformats_test.dart @@ -165,11 +165,11 @@ void main() { }); group('RTL detection', () { - test('Detection of RTL', () { + test('Detects RTL text when applied with no line style', () { final document = ParchmentDocument.fromJson([ - {'insert': 'some ltr text\nש\n'} + {'insert': 'some ltr text\nب\n'}, ]); - final performed = autoformats.run(document, 14, 'ש'); + final performed = autoformats.run(document, 14, 'ب'); expect(performed, true); expect(autoformats.selection, isNull); final attributes = document.toDelta().toList()[1].attributes; @@ -178,5 +178,38 @@ void main() { expect(attributes[ParchmentAttribute.direction.key], ParchmentAttribute.direction.rtl.value); }); + + test('Detects RTL text when applied on an already styled line', () { + final document = ParchmentDocument.fromJson([ + {'insert': 'some ltr text\nب'}, + { + 'insert': '\n', + 'attributes': {'checked': true} + } + ]); + final performed = autoformats.run(document, 14, 'ب'); + expect(performed, true); + expect(autoformats.selection, isNull); + final attributes = document.toDelta().toList()[1].attributes; + expect(attributes, isNotNull); + expect(attributes!.containsKey(ParchmentAttribute.direction.key), isTrue); + expect(attributes[ParchmentAttribute.direction.key], + ParchmentAttribute.direction.rtl.value); + expect(autoformats.canUndo, isTrue); + }); + + test('canUndo is false when line was already correctly styled', () { + final document = ParchmentDocument.fromJson([ + {'insert': 'some ltr text\nب'}, + { + 'insert': '\n', + 'attributes': {'direction': 'rtl', 'alignment': 'right'} + } + ]); + final performed = autoformats.run(document, 14, 'ب'); + expect(performed, true); + expect(autoformats.selection, isNull); + expect(autoformats.canUndo, isFalse); + }); }); }