Unverified Commit f7b9d1ce authored by chunhtai's avatar chunhtai Committed by GitHub

Reland clean up clipboard. (#99363)

parent f8e4486d
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
......@@ -48,15 +49,15 @@ class _CupertinoDesktopTextSelectionControls extends TextSelectionControls {
Offset selectionMidpoint,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
ClipboardStatusNotifier? clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
return _CupertinoDesktopTextSelectionControlsToolbar(
clipboardStatus: clipboardStatus,
endpoints: endpoints,
globalEditableRegion: globalEditableRegion,
handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate) : null,
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
selectionMidpoint: selectionMidpoint,
......@@ -114,8 +115,6 @@ class _CupertinoDesktopTextSelectionControlsToolbar extends StatefulWidget {
}
class _CupertinoDesktopTextSelectionControlsToolbarState extends State<_CupertinoDesktopTextSelectionControlsToolbar> {
ClipboardStatusNotifier? _clipboardStatus;
void _onChangedClipboardStatus() {
setState(() {
// Inform the widget that the value of clipboardStatus has changed.
......@@ -125,46 +124,28 @@ class _CupertinoDesktopTextSelectionControlsToolbarState extends State<_Cupertin
@override
void initState() {
super.initState();
if (widget.handlePaste != null) {
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
_clipboardStatus!.addListener(_onChangedClipboardStatus);
_clipboardStatus!.update();
}
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
}
@override
void didUpdateWidget(_CupertinoDesktopTextSelectionControlsToolbar oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.clipboardStatus != widget.clipboardStatus) {
if (_clipboardStatus != null) {
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
_clipboardStatus!.dispose();
}
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
_clipboardStatus!.addListener(_onChangedClipboardStatus);
if (widget.handlePaste != null) {
_clipboardStatus!.update();
}
oldWidget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
}
}
@override
void dispose() {
super.dispose();
// When used in an Overlay, this can be disposed after its creator has
// already disposed _clipboardStatus.
if (_clipboardStatus != null && !_clipboardStatus!.disposed) {
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
if (widget.clipboardStatus == null) {
_clipboardStatus!.dispose();
}
}
widget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
}
@override
Widget build(BuildContext context) {
// Don't render the menu until the state of the clipboard is known.
if (widget.handlePaste != null && _clipboardStatus!.value == ClipboardStatus.unknown) {
if (widget.handlePaste != null && widget.clipboardStatus?.value == ClipboardStatus.unknown) {
return const SizedBox(width: 0.0, height: 0.0);
}
......@@ -206,7 +187,7 @@ class _CupertinoDesktopTextSelectionControlsToolbarState extends State<_Cupertin
addToolbarButton(localizations.copyButtonLabel, widget.handleCopy!);
}
if (widget.handlePaste != null
&& _clipboardStatus!.value == ClipboardStatus.pasteable) {
&& widget.clipboardStatus?.value == ClipboardStatus.pasteable) {
addToolbarButton(localizations.pasteButtonLabel, widget.handlePaste!);
}
if (widget.handleSelectAll != null) {
......
......@@ -4,6 +4,7 @@
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
......@@ -52,8 +53,6 @@ class _CupertinoTextSelectionControlsToolbar extends StatefulWidget {
}
class _CupertinoTextSelectionControlsToolbarState extends State<_CupertinoTextSelectionControlsToolbar> {
ClipboardStatusNotifier? _clipboardStatus;
void _onChangedClipboardStatus() {
setState(() {
// Inform the widget that the value of clipboardStatus has changed.
......@@ -63,47 +62,28 @@ class _CupertinoTextSelectionControlsToolbarState extends State<_CupertinoTextSe
@override
void initState() {
super.initState();
if (widget.handlePaste != null) {
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
_clipboardStatus!.addListener(_onChangedClipboardStatus);
_clipboardStatus!.update();
}
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
}
@override
void didUpdateWidget(_CupertinoTextSelectionControlsToolbar oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.clipboardStatus != widget.clipboardStatus) {
if (_clipboardStatus != null) {
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
_clipboardStatus!.dispose();
}
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
_clipboardStatus!.addListener(_onChangedClipboardStatus);
if (widget.handlePaste != null) {
_clipboardStatus!.update();
}
oldWidget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
}
}
@override
void dispose() {
super.dispose();
// When used in an Overlay, this can be disposed after its creator has
// already disposed _clipboardStatus.
if (_clipboardStatus != null && !_clipboardStatus!.disposed) {
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
if (widget.clipboardStatus == null) {
_clipboardStatus!.dispose();
}
}
widget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
}
@override
Widget build(BuildContext context) {
// Don't render the menu until the state of the clipboard is known.
if (widget.handlePaste != null
&& _clipboardStatus!.value == ClipboardStatus.unknown) {
if (widget.handlePaste != null && widget.clipboardStatus?.value == ClipboardStatus.unknown) {
return const SizedBox(width: 0.0, height: 0.0);
}
......@@ -157,7 +137,7 @@ class _CupertinoTextSelectionControlsToolbarState extends State<_CupertinoTextSe
addToolbarButton(localizations.copyButtonLabel, widget.handleCopy!);
}
if (widget.handlePaste != null
&& _clipboardStatus!.value == ClipboardStatus.pasteable) {
&& widget.clipboardStatus?.value == ClipboardStatus.pasteable) {
addToolbarButton(localizations.pasteButtonLabel, widget.handlePaste!);
}
if (widget.handleSelectAll != null) {
......@@ -229,15 +209,15 @@ class CupertinoTextSelectionControls extends TextSelectionControls {
Offset selectionMidpoint,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
ClipboardStatusNotifier? clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
return _CupertinoTextSelectionControlsToolbar(
clipboardStatus: clipboardStatus,
endpoints: endpoints,
globalEditableRegion: globalEditableRegion,
handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate) : null,
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
selectionMidpoint: selectionMidpoint,
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
......@@ -34,15 +35,15 @@ class _DesktopTextSelectionControls extends TextSelectionControls {
Offset selectionMidpoint,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
ClipboardStatusNotifier? clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
return _DesktopTextSelectionControlsToolbar(
clipboardStatus: clipboardStatus,
endpoints: endpoints,
globalEditableRegion: globalEditableRegion,
handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate) : null,
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
selectionMidpoint: selectionMidpoint,
......@@ -110,8 +111,6 @@ class _DesktopTextSelectionControlsToolbar extends StatefulWidget {
}
class _DesktopTextSelectionControlsToolbarState extends State<_DesktopTextSelectionControlsToolbar> {
ClipboardStatusNotifier? _clipboardStatus;
void _onChangedClipboardStatus() {
setState(() {
// Inform the widget that the value of clipboardStatus has changed.
......@@ -121,46 +120,28 @@ class _DesktopTextSelectionControlsToolbarState extends State<_DesktopTextSelect
@override
void initState() {
super.initState();
if (widget.handlePaste != null) {
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
_clipboardStatus!.addListener(_onChangedClipboardStatus);
_clipboardStatus!.update();
}
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
}
@override
void didUpdateWidget(_DesktopTextSelectionControlsToolbar oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.clipboardStatus != widget.clipboardStatus) {
if (_clipboardStatus != null) {
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
_clipboardStatus!.dispose();
}
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
_clipboardStatus!.addListener(_onChangedClipboardStatus);
if (widget.handlePaste != null) {
_clipboardStatus!.update();
}
oldWidget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
}
}
@override
void dispose() {
super.dispose();
// When used in an Overlay, this can be disposed after its creator has
// already disposed _clipboardStatus.
if (_clipboardStatus != null && !_clipboardStatus!.disposed) {
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
if (widget.clipboardStatus == null) {
_clipboardStatus!.dispose();
}
}
widget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
}
@override
Widget build(BuildContext context) {
// Don't render the menu until the state of the clipboard is known.
if (widget.handlePaste != null && _clipboardStatus!.value == ClipboardStatus.unknown) {
if (widget.handlePaste != null && widget.clipboardStatus?.value == ClipboardStatus.unknown) {
return const SizedBox(width: 0.0, height: 0.0);
}
......@@ -197,7 +178,7 @@ class _DesktopTextSelectionControlsToolbarState extends State<_DesktopTextSelect
addToolbarButton(localizations.copyButtonLabel, widget.handleCopy!);
}
if (widget.handlePaste != null
&& _clipboardStatus!.value == ClipboardStatus.pasteable) {
&& widget.clipboardStatus?.value == ClipboardStatus.pasteable) {
addToolbarButton(localizations.pasteButtonLabel, widget.handlePaste!);
}
if (widget.handleSelectAll != null) {
......
......@@ -4,6 +4,7 @@
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
......@@ -35,7 +36,7 @@ class MaterialTextSelectionControls extends TextSelectionControls {
Offset selectionMidpoint,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
ClipboardStatusNotifier? clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
return _TextSelectionControlsToolbar(
......@@ -45,8 +46,8 @@ class MaterialTextSelectionControls extends TextSelectionControls {
endpoints: endpoints,
delegate: delegate,
clipboardStatus: clipboardStatus,
handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate) : null,
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
);
......@@ -143,7 +144,7 @@ class _TextSelectionControlsToolbar extends StatefulWidget {
required this.textLineHeight,
}) : super(key: key);
final ClipboardStatusNotifier clipboardStatus;
final ClipboardStatusNotifier? clipboardStatus;
final TextSelectionDelegate delegate;
final List<TextSelectionPoint> endpoints;
final Rect globalEditableRegion;
......@@ -168,28 +169,22 @@ class _TextSelectionControlsToolbarState extends State<_TextSelectionControlsToo
@override
void initState() {
super.initState();
widget.clipboardStatus.addListener(_onChangedClipboardStatus);
widget.clipboardStatus.update();
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
}
@override
void didUpdateWidget(_TextSelectionControlsToolbar oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.clipboardStatus != oldWidget.clipboardStatus) {
widget.clipboardStatus.addListener(_onChangedClipboardStatus);
oldWidget.clipboardStatus.removeListener(_onChangedClipboardStatus);
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
oldWidget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
}
widget.clipboardStatus.update();
}
@override
void dispose() {
super.dispose();
// When used in an Overlay, it can happen that this is disposed after its
// creator has already disposed _clipboardStatus.
if (!widget.clipboardStatus.disposed) {
widget.clipboardStatus.removeListener(_onChangedClipboardStatus);
}
widget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
}
@override
......@@ -202,7 +197,7 @@ class _TextSelectionControlsToolbarState extends State<_TextSelectionControlsToo
// If the paste button is desired, don't render anything until the state of
// the clipboard is known, since it's used to determine if paste is shown.
if (widget.handlePaste != null
&& widget.clipboardStatus.value == ClipboardStatus.unknown) {
&& widget.clipboardStatus?.value == ClipboardStatus.unknown) {
return const SizedBox.shrink();
}
......@@ -238,7 +233,7 @@ class _TextSelectionControlsToolbarState extends State<_TextSelectionControlsToo
onPressed: widget.handleCopy!,
),
if (widget.handlePaste != null
&& widget.clipboardStatus.value == ClipboardStatus.pasteable)
&& widget.clipboardStatus?.value == ClipboardStatus.pasteable)
_TextSelectionToolbarItemData(
label: localizations.pasteButtonLabel,
onPressed: widget.handlePaste!,
......
......@@ -1671,6 +1671,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
break;
}
}
_clipboardStatus?.update();
}
/// Cut current selection to [Clipboard].
......@@ -1694,6 +1695,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
});
hideToolbar();
}
_clipboardStatus?.update();
}
/// Paste text from [Clipboard].
......@@ -2919,7 +2921,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if (_selectionOverlay == null || _selectionOverlay!.toolbarIsVisible) {
return false;
}
_clipboardStatus?.update();
_selectionOverlay!.showToolbar();
return true;
}
......@@ -3026,7 +3028,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
&& copyEnabled
&& _hasFocus
&& (controls?.canCopy(this) ?? false)
? () => controls!.handleCopy(this, _clipboardStatus)
? () => controls!.handleCopy(this)
: null;
}
......@@ -3035,7 +3037,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
&& cutEnabled
&& _hasFocus
&& (controls?.canCut(this) ?? false)
? () => controls!.handleCut(this, _clipboardStatus)
? () => controls!.handleCut(this)
: null;
}
......
......@@ -142,7 +142,9 @@ abstract class TextSelectionControls {
Offset position,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
// TODO(chunhtai): Change to ValueListenable<ClipboardStatus>? once
// mirgration is done. https://github.com/flutter/flutter/issues/99360
ClipboardStatusNotifier? clipboardStatus,
Offset? lastSecondaryTapDownPosition,
);
......@@ -199,18 +201,20 @@ abstract class TextSelectionControls {
///
/// This is called by subclasses when their cut affordance is activated by
/// the user.
void handleCut(TextSelectionDelegate delegate, ClipboardStatusNotifier? clipboardStatus) {
// TODO(chunhtai): remove optional parameter once migration is done.
// https://github.com/flutter/flutter/issues/99360
void handleCut(TextSelectionDelegate delegate, [ClipboardStatusNotifier? clipboardStatus]) {
delegate.cutSelection(SelectionChangedCause.toolbar);
clipboardStatus?.update();
}
/// Call [TextSelectionDelegate.copySelection] to copy current selection.
///
/// This is called by subclasses when their copy affordance is activated by
/// the user.
void handleCopy(TextSelectionDelegate delegate, ClipboardStatusNotifier? clipboardStatus) {
// TODO(chunhtai): remove optional parameter once migration is done.
// https://github.com/flutter/flutter/issues/99360
void handleCopy(TextSelectionDelegate delegate, [ClipboardStatusNotifier? clipboardStatus]) {
delegate.copySelection(SelectionChangedCause.toolbar);
clipboardStatus?.update();
}
/// Call [TextSelectionDelegate.pasteText] to paste text.
......@@ -1080,7 +1084,7 @@ class _SelectionToolbarOverlayState extends State<_SelectionToolbarOverlay> with
widget.midpoint,
widget.selectionEndpoints,
widget.selectionDelegate!,
widget.clipboardStatus!,
widget.clipboardStatus,
widget.toolbarLocation,
);
},
......@@ -2131,6 +2135,8 @@ class ClipboardStatusNotifier extends ValueNotifier<ClipboardStatus> with Widget
}) : super(value);
bool _disposed = false;
// TODO(chunhtai): remove this getter once migration is done.
// https://github.com/flutter/flutter/issues/99360
/// True if this instance has been disposed.
bool get disposed => _disposed;
......@@ -2183,7 +2189,7 @@ class ClipboardStatusNotifier extends ValueNotifier<ClipboardStatus> with Widget
@override
void removeListener(VoidCallback listener) {
super.removeListener(listener);
if (!hasListeners) {
if (!_disposed && !hasListeners) {
WidgetsBinding.instance.removeObserver(this);
}
}
......@@ -2203,9 +2209,9 @@ class ClipboardStatusNotifier extends ValueNotifier<ClipboardStatus> with Widget
@override
void dispose() {
super.dispose();
WidgetsBinding.instance.removeObserver(this);
_disposed = true;
super.dispose();
}
}
......
......@@ -43,7 +43,7 @@ class MockTextSelectionControls extends TextSelectionControls {
Offset position,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
ClipboardStatusNotifier? clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
throw UnimplementedError();
......
......@@ -24,7 +24,7 @@ class _CustomCupertinoTextSelectionControls extends CupertinoTextSelectionContro
Offset selectionMidpoint,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
ClipboardStatusNotifier? clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
final MediaQueryData mediaQuery = MediaQuery.of(context);
......
......@@ -22,7 +22,7 @@ class _CustomMaterialTextSelectionControls extends MaterialTextSelectionControls
Offset selectionMidpoint,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
ClipboardStatusNotifier? clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
final TextSelectionPoint startTextSelectionPoint = endpoints[0];
......
......@@ -11782,7 +11782,7 @@ class MockTextFormatter extends TextInputFormatter {
class MockTextSelectionControls extends Fake implements TextSelectionControls {
@override
Widget buildToolbar(BuildContext context, Rect globalEditableRegion, double textLineHeight, Offset position, List<TextSelectionPoint> endpoints, TextSelectionDelegate delegate, ClipboardStatusNotifier clipboardStatus, Offset? lastSecondaryTapDownPosition) {
Widget buildToolbar(BuildContext context, Rect globalEditableRegion, double textLineHeight, Offset position, List<TextSelectionPoint> endpoints, TextSelectionDelegate delegate, ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition) {
return Container();
}
......@@ -11809,8 +11809,10 @@ class MockTextSelectionControls extends Fake implements TextSelectionControls {
int pasteCount = 0;
int copyCount = 0;
// TODO(chunhtai): remove optional parameter once migration is done.
// https://github.com/flutter/flutter/issues/99360
@override
void handleCopy(TextSelectionDelegate delegate, ClipboardStatusNotifier? clipboardStatus) {
void handleCopy(TextSelectionDelegate delegate, [ClipboardStatusNotifier? clipboardStatus]) {
copyCount += 1;
}
......@@ -11819,8 +11821,10 @@ class MockTextSelectionControls extends Fake implements TextSelectionControls {
pasteCount += 1;
}
// TODO(chunhtai): remove optional parameter once migration is done.
// https://github.com/flutter/flutter/issues/99360
@override
void handleCut(TextSelectionDelegate delegate, ClipboardStatusNotifier? clipboardStatus) {
void handleCut(TextSelectionDelegate delegate, [ClipboardStatusNotifier? clipboardStatus]) {
cutCount += 1;
}
......
......@@ -1034,28 +1034,6 @@ void main() {
});
});
});
group('TextSelectionControls', () {
test('ClipboardStatusNotifier is updated on handleCut', () async {
final FakeClipboardStatusNotifier clipboardStatus = FakeClipboardStatusNotifier();
final FakeTextSelectionDelegate delegate = FakeTextSelectionDelegate();
final CustomTextSelectionControls textSelectionControls = CustomTextSelectionControls();
expect(clipboardStatus.updateCalled, false);
textSelectionControls.handleCut(delegate, clipboardStatus);
expect(clipboardStatus.updateCalled, true);
});
test('ClipboardStatusNotifier is updated on handleCopy', () async {
final FakeClipboardStatusNotifier clipboardStatus = FakeClipboardStatusNotifier();
final FakeTextSelectionDelegate delegate = FakeTextSelectionDelegate();
final CustomTextSelectionControls textSelectionControls = CustomTextSelectionControls();
expect(clipboardStatus.updateCalled, false);
textSelectionControls.handleCopy(delegate, clipboardStatus);
expect(clipboardStatus.updateCalled, true);
});
});
}
class FakeTextSelectionGestureDetectorBuilderDelegate implements TextSelectionGestureDetectorBuilderDelegate {
......@@ -1184,7 +1162,7 @@ class CustomTextSelectionControls extends TextSelectionControls {
Offset position,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
ClipboardStatusNotifier? clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
throw UnimplementedError();
......@@ -1221,15 +1199,15 @@ class TextSelectionControlsSpy extends TextSelectionControls {
@override
Widget buildToolbar(
BuildContext context,
Rect globalEditableRegion,
double textLineHeight,
Offset position,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
BuildContext context,
Rect globalEditableRegion,
double textLineHeight,
Offset position,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier? clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
return Text('dummy', key: toolBarKey);
}
......@@ -1247,9 +1225,6 @@ class TextSelectionControlsSpy extends TextSelectionControls {
class FakeClipboardStatusNotifier extends ClipboardStatusNotifier {
FakeClipboardStatusNotifier() : super(value: ClipboardStatus.unknown);
@override
bool get disposed => false;
bool updateCalled = false;
@override
Future<void> update() async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment