diff --git a/packages/flutter/lib/src/cupertino/desktop_text_selection.dart b/packages/flutter/lib/src/cupertino/desktop_text_selection.dart index 7ed14958dcd..6c129c6f685 100644 --- a/packages/flutter/lib/src/cupertino/desktop_text_selection.dart +++ b/packages/flutter/lib/src/cupertino/desktop_text_selection.dart @@ -2,7 +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' show ValueListenable, clampDouble; +import 'package:flutter/foundation.dart' show clampDouble; import 'package:flutter/gestures.dart'; import 'package:flutter/widgets.dart'; @@ -51,7 +51,7 @@ class CupertinoDesktopTextSelectionControls extends TextSelectionControls { Offset selectionMidpoint, List endpoints, TextSelectionDelegate delegate, - ValueListenable? clipboardStatus, + ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition, ) { return _CupertinoDesktopTextSelectionControlsToolbar( @@ -106,7 +106,7 @@ class _CupertinoDesktopTextSelectionControlsToolbar extends StatefulWidget { required this.lastSecondaryTapDownPosition, }); - final ValueListenable? clipboardStatus; + final ClipboardStatusNotifier? clipboardStatus; final List endpoints; final Rect globalEditableRegion; final VoidCallback? handleCopy; diff --git a/packages/flutter/lib/src/cupertino/text_selection.dart b/packages/flutter/lib/src/cupertino/text_selection.dart index 06db922ba52..3bebdac7618 100644 --- a/packages/flutter/lib/src/cupertino/text_selection.dart +++ b/packages/flutter/lib/src/cupertino/text_selection.dart @@ -4,7 +4,7 @@ import 'dart:math' as math; -import 'package:flutter/foundation.dart' show ValueListenable, clampDouble; +import 'package:flutter/foundation.dart' show clampDouble; import 'package:flutter/widgets.dart'; import 'localizations.dart'; @@ -36,7 +36,7 @@ class _CupertinoTextSelectionControlsToolbar extends StatefulWidget { required this.textLineHeight, }); - final ValueListenable? clipboardStatus; + final ClipboardStatusNotifier? clipboardStatus; final List endpoints; final Rect globalEditableRegion; final VoidCallback? handleCopy; @@ -213,7 +213,7 @@ class CupertinoTextSelectionControls extends TextSelectionControls { Offset selectionMidpoint, List endpoints, TextSelectionDelegate delegate, - ValueListenable? clipboardStatus, + ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition, ) { return _CupertinoTextSelectionControlsToolbar( diff --git a/packages/flutter/lib/src/material/desktop_text_selection.dart b/packages/flutter/lib/src/material/desktop_text_selection.dart index a6be9d276ee..d5e1802def2 100644 --- a/packages/flutter/lib/src/material/desktop_text_selection.dart +++ b/packages/flutter/lib/src/material/desktop_text_selection.dart @@ -2,7 +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' show ValueListenable, clampDouble; +import 'package:flutter/foundation.dart' show clampDouble; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -38,7 +38,7 @@ class DesktopTextSelectionControls extends TextSelectionControls { Offset selectionMidpoint, List endpoints, TextSelectionDelegate delegate, - ValueListenable? clipboardStatus, + ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition, ) { return _DesktopTextSelectionControlsToolbar( @@ -103,7 +103,7 @@ class _DesktopTextSelectionControlsToolbar extends StatefulWidget { required this.lastSecondaryTapDownPosition, }); - final ValueListenable? clipboardStatus; + final ClipboardStatusNotifier? clipboardStatus; final List endpoints; final Rect globalEditableRegion; final VoidCallback? handleCopy; diff --git a/packages/flutter/lib/src/material/text_selection.dart b/packages/flutter/lib/src/material/text_selection.dart index fc8d86be7b5..33da727aec0 100644 --- a/packages/flutter/lib/src/material/text_selection.dart +++ b/packages/flutter/lib/src/material/text_selection.dart @@ -4,7 +4,6 @@ import 'dart:math' as math; -import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'debug.dart'; @@ -38,7 +37,7 @@ class MaterialTextSelectionControls extends TextSelectionControls { Offset selectionMidpoint, List endpoints, TextSelectionDelegate delegate, - ValueListenable? clipboardStatus, + ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition, ) { return _TextSelectionControlsToolbar( @@ -145,7 +144,7 @@ class _TextSelectionControlsToolbar extends StatefulWidget { required this.textLineHeight, }); - final ValueListenable? clipboardStatus; + final ClipboardStatusNotifier? clipboardStatus; final TextSelectionDelegate delegate; final List endpoints; final Rect globalEditableRegion; diff --git a/packages/flutter/lib/src/widgets/text_selection.dart b/packages/flutter/lib/src/widgets/text_selection.dart index 81f0515e6b0..5319625900a 100644 --- a/packages/flutter/lib/src/widgets/text_selection.dart +++ b/packages/flutter/lib/src/widgets/text_selection.dart @@ -119,7 +119,9 @@ abstract class TextSelectionControls { Offset selectionMidpoint, List endpoints, TextSelectionDelegate delegate, - ValueListenable? clipboardStatus, + // TODO(chunhtai): Change to ValueListenable? once + // mirgration is done. https://github.com/flutter/flutter/issues/99360 + ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition, ); @@ -176,7 +178,9 @@ abstract class TextSelectionControls { /// /// This is called by subclasses when their cut affordance is activated by /// the user. - void handleCut(TextSelectionDelegate delegate) { + // 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); } @@ -184,7 +188,9 @@ abstract class TextSelectionControls { /// /// This is called by subclasses when their copy affordance is activated by /// the user. - void handleCopy(TextSelectionDelegate delegate) { + // 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); } @@ -2472,8 +2478,18 @@ class ClipboardStatusNotifier extends ValueNotifier with Widget ClipboardStatus value = ClipboardStatus.unknown, }) : 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; + /// Check the [Clipboard] and update [value] if needed. Future update() async { + if (_disposed) { + return; + } + final bool hasStrings; try { hasStrings = await Clipboard.hasStrings(); @@ -2486,7 +2502,7 @@ class ClipboardStatusNotifier extends ValueNotifier with Widget )); // In the case of an error from the Clipboard API, set the value to // unknown so that it will try to update again later. - if (value == ClipboardStatus.unknown) { + if (_disposed || value == ClipboardStatus.unknown) { return; } value = ClipboardStatus.unknown; @@ -2497,7 +2513,7 @@ class ClipboardStatusNotifier extends ValueNotifier with Widget ? ClipboardStatus.pasteable : ClipboardStatus.notPasteable; - if (nextStatus == value) { + if (_disposed || nextStatus == value) { return; } value = nextStatus; @@ -2517,7 +2533,7 @@ class ClipboardStatusNotifier extends ValueNotifier with Widget @override void removeListener(VoidCallback listener) { super.removeListener(listener); - if (!hasListeners) { + if (!_disposed && !hasListeners) { WidgetsBinding.instance.removeObserver(this); } } @@ -2538,6 +2554,7 @@ class ClipboardStatusNotifier extends ValueNotifier with Widget @override void dispose() { WidgetsBinding.instance.removeObserver(this); + _disposed = true; super.dispose(); } } diff --git a/packages/flutter/test/cupertino/text_field_test.dart b/packages/flutter/test/cupertino/text_field_test.dart index 8eaba6219d9..51a9ccef4ae 100644 --- a/packages/flutter/test/cupertino/text_field_test.dart +++ b/packages/flutter/test/cupertino/text_field_test.dart @@ -44,7 +44,7 @@ class MockTextSelectionControls extends TextSelectionControls { Offset position, List endpoints, TextSelectionDelegate delegate, - ValueListenable? clipboardStatus, + ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition, ) { throw UnimplementedError(); diff --git a/packages/flutter/test/cupertino/text_selection_toolbar_test.dart b/packages/flutter/test/cupertino/text_selection_toolbar_test.dart index a64a694b6a6..9a46e76f98e 100644 --- a/packages/flutter/test/cupertino/text_selection_toolbar_test.dart +++ b/packages/flutter/test/cupertino/text_selection_toolbar_test.dart @@ -23,7 +23,7 @@ class _CustomCupertinoTextSelectionControls extends CupertinoTextSelectionContro Offset selectionMidpoint, List endpoints, TextSelectionDelegate delegate, - ValueListenable? clipboardStatus, + ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition, ) { final MediaQueryData mediaQuery = MediaQuery.of(context); diff --git a/packages/flutter/test/material/text_selection_toolbar_test.dart b/packages/flutter/test/material/text_selection_toolbar_test.dart index 6e6b9ec88db..8ab72e63073 100644 --- a/packages/flutter/test/material/text_selection_toolbar_test.dart +++ b/packages/flutter/test/material/text_selection_toolbar_test.dart @@ -21,7 +21,7 @@ class _CustomMaterialTextSelectionControls extends MaterialTextSelectionControls Offset selectionMidpoint, List endpoints, TextSelectionDelegate delegate, - ValueListenable? clipboardStatus, + ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition, ) { final TextSelectionPoint startTextSelectionPoint = endpoints[0]; diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index c2ff5de5c8c..584be02aff2 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -12734,7 +12734,7 @@ class MockTextSelectionControls extends Fake implements TextSelectionControls { Offset position, List endpoints, TextSelectionDelegate delegate, - ValueListenable? clipboardStatus, + ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition, ) { return const SizedBox(); @@ -12763,8 +12763,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) { + void handleCopy(TextSelectionDelegate delegate, [ClipboardStatusNotifier? clipboardStatus]) { copyCount += 1; } @@ -12773,8 +12775,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) { + void handleCut(TextSelectionDelegate delegate, [ClipboardStatusNotifier? clipboardStatus]) { cutCount += 1; } @@ -12815,7 +12819,7 @@ class _CustomTextSelectionControls extends TextSelectionControls { Offset position, List endpoints, TextSelectionDelegate delegate, - ValueListenable? clipboardStatus, + ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition, ) { final Offset selectionMidpoint = position; @@ -12871,9 +12875,9 @@ class _CustomTextSelectionControls extends TextSelectionControls { } @override - void handleCut(TextSelectionDelegate delegate) { + void handleCut(TextSelectionDelegate delegate, [ClipboardStatusNotifier? clipboardStatus]) { onCut?.call(); - return super.handleCut(delegate); + return super.handleCut(delegate, clipboardStatus); } } diff --git a/packages/flutter/test/widgets/text_selection_test.dart b/packages/flutter/test/widgets/text_selection_test.dart index eed975c4732..09980cd9626 100644 --- a/packages/flutter/test/widgets/text_selection_test.dart +++ b/packages/flutter/test/widgets/text_selection_test.dart @@ -2,7 +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' show ValueListenable, defaultTargetPlatform; +import 'package:flutter/foundation.dart' show defaultTargetPlatform; import 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -1456,7 +1456,7 @@ class TextSelectionControlsSpy extends TextSelectionControls { Offset position, List endpoints, TextSelectionDelegate delegate, - ValueListenable? clipboardStatus, + ClipboardStatusNotifier? clipboardStatus, Offset? lastSecondaryTapDownPosition, ) { return Text('dummy', key: toolBarKey);