Skip to content

Commit

Permalink
Hide collapsed selection handle when editor is read-only
Browse files Browse the repository at this point in the history
  • Loading branch information
Amir-P committed Mar 25, 2024
1 parent a79d6d0 commit 6431e42
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 6 deletions.
53 changes: 47 additions & 6 deletions packages/fleather/lib/src/widgets/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ class _FleatherEditorState extends State<FleatherEditor>
implements EditorTextSelectionGestureDetectorBuilderDelegate {
GlobalKey<EditorState>? _editorKey;

bool _showSelectionHandles = false;

@override
GlobalKey<EditorState> get editableTextKey => widget.editorKey ?? _editorKey!;

Expand Down Expand Up @@ -342,10 +344,42 @@ class _FleatherEditorState extends State<FleatherEditor>
_FleatherEditorSelectionGestureDetectorBuilder(state: this);
}

static const Set<TargetPlatform> _mobilePlatforms = {
TargetPlatform.iOS,
TargetPlatform.android
};
void _handleSelectionChanged(
TextSelection selection, SelectionChangedCause? cause) {
final bool willShowSelectionHandles = _shouldShowSelectionHandles(cause);
if (willShowSelectionHandles != _showSelectionHandles) {
setState(() {
_showSelectionHandles = willShowSelectionHandles;
});
}
}

bool _shouldShowSelectionHandles(SelectionChangedCause? cause) {
// When the editor is activated by something that doesn't trigger the
// selection overlay, we shouldn't show the handles either.
if (!_selectionGestureDetectorBuilder.shouldShowSelectionToolbar) {
return false;
}

if (cause == SelectionChangedCause.keyboard) {
return false;
}

if (widget.readOnly && widget.controller.selection.isCollapsed) {
return false;
}

if (cause == SelectionChangedCause.longPress ||
cause == SelectionChangedCause.scribble) {
return true;
}

if (widget.controller.document.toPlainText().length > 2) {
return true;
}

return false;
}

@override
Widget build(BuildContext context) {
Expand All @@ -360,7 +394,6 @@ class _FleatherEditorState extends State<FleatherEditor>
Color selectionColor;
Radius? cursorRadius;

final showSelectionHandles = _mobilePlatforms.contains(theme.platform);
final keyboardAppearance = widget.keyboardAppearance ?? theme.brightness;

switch (theme.platform) {
Expand Down Expand Up @@ -445,7 +478,8 @@ class _FleatherEditorState extends State<FleatherEditor>
opacityAnimates: cursorOpacityAnimates,
),
selectionColor: selectionColor,
showSelectionHandles: showSelectionHandles,
showSelectionHandles: _showSelectionHandles,
onSelectionChanged: _handleSelectionChanged,
selectionControls: textSelectionControls,
);

Expand Down Expand Up @@ -532,6 +566,7 @@ class RawEditor extends StatefulWidget {
required this.clipboardManager,
this.showSelectionHandles = false,
this.selectionControls,
this.onSelectionChanged,
this.contextMenuBuilder = defaultContextMenuBuilder,
this.spellCheckConfiguration,
this.embedBuilder = defaultFleatherEmbedBuilder,
Expand Down Expand Up @@ -600,6 +635,10 @@ class RawEditor extends StatefulWidget {
/// * [showCursor], which controls the visibility of the cursor..
final bool showSelectionHandles;

/// Called when the user changes the selection of text (including the cursor
/// location).
final SelectionChangedCallback? onSelectionChanged;

/// Whether to show cursor.
///
/// The cursor refers to the blinking caret when the editor is focused.
Expand Down Expand Up @@ -1431,6 +1470,8 @@ class RawEditorState extends EditorState
bringIntoView(selection.extent);
}
}

widget.onSelectionChanged?.call(selection, cause);
}

EditorTextSelectionOverlay _createSelectionOverlay() {
Expand Down
15 changes: 15 additions & 0 deletions packages/fleather/test/widgets/editor_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@ void main() {
expect(widget.readOnly, true);
});

testWidgets('Selection handle is hidden when editor is read-only',
(tester) async {
final editor = EditorSandBox(
tester: tester,
document: ParchmentDocument.fromDelta(Delta()..insert('Text\n')));
await editor.pump();
await editor.disable();
await tester.tapAt(
tester.getTopLeft(find.byType(RawEditor)) + const Offset(15, 5));
await tester.pumpAndSettle();
final handle = tester.widget(editor.findSelectionHandles().first)
as SelectionHandleOverlay;
expect(handle.visibility?.value, false);
}, variant: TargetPlatformVariant.only(TargetPlatform.android));

testWidgets('ability to paste upon long press on an empty document',
(tester) async {
// if Clipboard not initialize (status 'unknown'), an shrunken toolbar appears
Expand Down

0 comments on commit 6431e42

Please sign in to comment.