Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix text direction auto format detection and undo #191

Merged
merged 4 commits into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions packages/fleather/lib/src/widgets/autoformats.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ class AutoFormats {
/// The position at which the active suggestion can be deactivated
int get undoPosition => _activeSuggestion!.undoPositionCandidate;

/// `true` if there is an active suggestion; `false` otherwise
bool get hasActiveSuggestion => _activeSuggestion != null;
/// `true` if there is an active suggestion and undo delta is not empty;
/// `false` otherwise
bool get canUndo => _activeSuggestion?.undo.isNotEmpty == true;

/// Perform detection of auto formats and apply changes to [document].
///
Expand Down Expand Up @@ -335,7 +336,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) =>
Expand All @@ -348,6 +349,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;
Expand Down
2 changes: 1 addition & 1 deletion packages/fleather/lib/src/widgets/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class FleatherController extends ChangeNotifier {
// document; `false` otherwise
bool _captureAutoFormatCancellationOrUndo(
ParchmentDocument document, int position, int length, Object data) {
if (!_autoFormats.hasActiveSuggestion) return true;
if (!_autoFormats.canUndo) return true;
Amir-P marked this conversation as resolved.
Show resolved Hide resolved

final isDeletionOfOneChar = data is String && data.isEmpty && length == 1;
if (isDeletionOfOneChar) {
Expand Down
47 changes: 40 additions & 7 deletions packages/fleather/test/widgets/autoformats_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void main() {
]);
final performed = autoformats.run(document, 54, 'p');
expect(performed, false);
expect(autoformats.hasActiveSuggestion, isFalse);
expect(autoformats.canUndo, isFalse);
});

test('Deleting at candidate position, undoes link formatting', () {
Expand All @@ -67,7 +67,7 @@ void main() {
]);
autoformats.run(document, 54, ' ');
autoformats.cancelActive();
expect(autoformats.hasActiveSuggestion, isFalse);
expect(autoformats.canUndo, isFalse);
});
});

Expand Down Expand Up @@ -138,7 +138,7 @@ void main() {
]);
final performed = autoformats.run(document, 16, 'p');
expect(performed, false);
expect(autoformats.hasActiveSuggestion, isFalse);
expect(autoformats.canUndo, isFalse);
});

test('Deleting at candidate position, undoes link formatting', () {
Expand All @@ -160,16 +160,16 @@ void main() {
]);
autoformats.run(document, 54, ' ');
autoformats.cancelActive();
expect(autoformats.hasActiveSuggestion, isFalse);
expect(autoformats.canUndo, isFalse);
});
});

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'}
{'insert': 'some ltr text\\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;
Expand All @@ -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);
});
});
}