- Fix selection handles show/hide after paste, backspace, copy (#769)

pull/783/head
Michael Allen 3 years ago committed by GitHub
parent 67381cf311
commit 2b3fa606ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      lib/src/widgets/delegate.dart
  2. 26
      lib/src/widgets/raw_editor.dart
  3. 2
      lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart
  4. 17
      lib/src/widgets/text_selection.dart

@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import '../../flutter_quill.dart'; import '../../flutter_quill.dart';
import 'text_selection.dart'; import 'text_selection.dart';
@ -252,9 +253,17 @@ class EditorTextSelectionGestureDetectorBuilder {
void onDoubleTapDown(TapDownDetails details) { void onDoubleTapDown(TapDownDetails details) {
if (delegate.selectionEnabled) { if (delegate.selectionEnabled) {
renderEditor!.selectWord(SelectionChangedCause.tap); renderEditor!.selectWord(SelectionChangedCause.tap);
if (shouldShowSelectionToolbar) { // allow the selection to get updated before trying to bring up
editor!.showToolbar(); // toolbars.
} //
// if double tap happens on an editor that doesn't
// have focus, selection hasn't been set when the toolbars
// get added
SchedulerBinding.instance!.addPostFrameCallback((_) {
if (shouldShowSelectionToolbar) {
editor!.showToolbar();
}
});
} }
} }

@ -759,10 +759,10 @@ class RawEditorState extends EditorState
void _updateOrDisposeSelectionOverlayIfNeeded() { void _updateOrDisposeSelectionOverlayIfNeeded() {
if (_selectionOverlay != null) { if (_selectionOverlay != null) {
if (!_hasFocus) { if (!_hasFocus || textEditingValue.selection.isCollapsed) {
_selectionOverlay!.dispose(); _selectionOverlay!.dispose();
_selectionOverlay = null; _selectionOverlay = null;
} else if (!textEditingValue.selection.isCollapsed) { } else {
_selectionOverlay!.update(textEditingValue); _selectionOverlay!.update(textEditingValue);
} }
} else if (_hasFocus) { } else if (_hasFocus) {
@ -929,10 +929,6 @@ class RawEditorState extends EditorState
if (cause == SelectionChangedCause.toolbar) { if (cause == SelectionChangedCause.toolbar) {
bringIntoView(textEditingValue.selection.extent); bringIntoView(textEditingValue.selection.extent);
// on iOS, Safari does not hide the selection after copy
// however, most other iOS apps do as well as other platforms
// so we'll hide toolbar & selection after copy
hideToolbar(false);
// Collapse the selection and hide the toolbar and handles. // Collapse the selection and hide the toolbar and handles.
userUpdateTextEditingValue( userUpdateTextEditingValue(
@ -1008,13 +1004,17 @@ class RawEditorState extends EditorState
_replaceText( _replaceText(
ReplaceTextIntent(textEditingValue, data.text!, selection, cause)); ReplaceTextIntent(textEditingValue, data.text!, selection, cause));
if (cause == SelectionChangedCause.toolbar) { bringIntoView(textEditingValue.selection.extent);
try {
// ignore exception when paste window is at end of document // Collapse the selection and hide the toolbar and handles.
bringIntoView(textEditingValue.selection.extent); userUpdateTextEditingValue(
} catch (_) {} TextEditingValue(
hideToolbar(); text: textEditingValue.text,
} selection: TextSelection.collapsed(
offset: textEditingValue.selection.end),
),
cause,
);
} }
/// Select the entire text value. /// Select the entire text value.

@ -136,7 +136,7 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState
void hideToolbar([bool hideHandles = true]) { void hideToolbar([bool hideHandles = true]) {
// If the toolbar is currently visible. // If the toolbar is currently visible.
if (selectionOverlay?.toolbar != null) { if (selectionOverlay?.toolbar != null) {
selectionOverlay?.hideToolbar(); hideHandles ? selectionOverlay?.hide() : selectionOverlay?.hideToolbar();
} }
} }

@ -4,6 +4,7 @@ import 'dart:math' as math;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import '../models/documents/nodes/node.dart'; import '../models/documents/nodes/node.dart';
@ -224,6 +225,11 @@ class EditorTextSelectionOverlay {
Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor)! Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor)!
.insert(toolbar!); .insert(toolbar!);
_toolbarController.forward(from: 0); _toolbarController.forward(from: 0);
// make sure handles are visible as well
if (_handles == null) {
showHandles();
}
} }
Widget _buildHandle( Widget _buildHandle(
@ -308,7 +314,16 @@ class EditorTextSelectionOverlay {
Widget _buildToolbar(BuildContext context) { Widget _buildToolbar(BuildContext context) {
// Find the horizontal midpoint, just above the selected text. // Find the horizontal midpoint, just above the selected text.
final endpoints = renderObject.getEndpointsForSelection(_selection); List<TextSelectionPoint> endpoints;
try {
// building with an invalid selection with throw an exception
// This happens where the selection has changed, but the toolbar
// hasn't been dismissed yet.
endpoints = renderObject.getEndpointsForSelection(_selection);
} catch (_) {
return Container();
}
final editingRegion = Rect.fromPoints( final editingRegion = Rect.fromPoints(
renderObject.localToGlobal(Offset.zero), renderObject.localToGlobal(Offset.zero),

Loading…
Cancel
Save