@@ -22,8 +22,11 @@ class ClipboardMonitor {
2222 bool get canPaste => _canPaste;
2323 Timer ? _timer;
2424
25+ bool _isCheckingClipboard = false ;
26+
2527 void monitorClipboard (bool add, void Function () listener) {
2628 if (kIsWeb) return ;
29+
2730 if (add) {
2831 _timer = Timer .periodic (
2932 const Duration (seconds: 1 ), (timer) => _update (listener));
@@ -33,17 +36,27 @@ class ClipboardMonitor {
3336 }
3437
3538 Future <void > _update (void Function () listener) async {
39+ if (_isCheckingClipboard) {
40+ return ;
41+ }
42+
43+ _isCheckingClipboard = true ;
44+
3645 final clipboardService = ClipboardServiceProvider .instance;
46+
3747 if (await clipboardService.hasClipboardContent) {
3848 _canPaste = true ;
49+
3950 listener ();
4051 }
52+
53+ _isCheckingClipboard = false ;
4154 }
4255}
4356
4457@experimental
4558class QuillToolbarClipboardButton extends QuillToolbarToggleStyleBaseButton {
46- QuillToolbarClipboardButton ({
59+ const QuillToolbarClipboardButton ({
4760 required super .controller,
4861 required this .clipboardAction,
4962 QuillToolbarClipboardButtonOptions ? options,
@@ -55,21 +68,19 @@ class QuillToolbarClipboardButton extends QuillToolbarToggleStyleBaseButton {
5568 }) : _options = options,
5669 super (options: options ?? const QuillToolbarClipboardButtonOptions ());
5770
58- // TODO: This field will be used by the PR: https://github.com/singerdmx/flutter-quill/pull/2427
59- // ignore: unused_field
6071 final QuillToolbarClipboardButtonOptions ? _options;
6172
6273 final ClipboardAction clipboardAction;
6374
64- final ClipboardMonitor _monitor = ClipboardMonitor ();
65-
6675 @override
6776 State <StatefulWidget > createState () => QuillToolbarClipboardButtonState ();
6877}
6978
7079class QuillToolbarClipboardButtonState
7180 extends QuillToolbarToggleStyleBaseButtonState <
7281 QuillToolbarClipboardButton > {
82+ final ClipboardMonitor _monitor = ClipboardMonitor ();
83+
7384 @override
7485 bool get currentStateValue {
7586 switch (widget.clipboardAction) {
@@ -78,23 +89,54 @@ class QuillToolbarClipboardButtonState
7889 case ClipboardAction .copy:
7990 return ! controller.selection.isCollapsed;
8091 case ClipboardAction .paste:
81- return ! controller.readOnly && (kIsWeb || widget._monitor.canPaste);
92+ return ! controller.readOnly &&
93+ (kIsWeb ||
94+ (widget._options? .enableClipboardPaste ?? _monitor.canPaste));
8295 }
8396 }
8497
8598 void _listenClipboardStatus () => didChangeEditingValue ();
8699
100+ @override
101+ void didUpdateWidget (QuillToolbarClipboardButton oldWidget) {
102+ super .didUpdateWidget (oldWidget);
103+
104+ // Default didUpdateWidget handler, otherwise simple flag change didn't stop the monitor.
105+ if (oldWidget.controller != controller) {
106+ oldWidget.controller.removeListener (didChangeEditingValue);
107+ removeExtraListener (oldWidget);
108+ controller.addListener (didChangeEditingValue);
109+ addExtraListener ();
110+ currentValue = currentStateValue;
111+ }
112+ // The controller didn't change, but enableClipboardPaste did.
113+ else if (widget.clipboardAction == ClipboardAction .paste) {
114+ final isTimerActive = _monitor._timer? .isActive ?? false ;
115+
116+ // Enable clipboard monitoring if not active and should be monitored.
117+ if (_shouldUseClipboardMonitor && ! isTimerActive) {
118+ _monitor.monitorClipboard (true , _listenClipboardStatus);
119+ }
120+ // Disable clipboard monitoring if active and should not be monitored.
121+ else if (! _shouldUseClipboardMonitor && isTimerActive) {
122+ _monitor.monitorClipboard (false , _listenClipboardStatus);
123+ }
124+
125+ currentValue = currentStateValue;
126+ }
127+ }
128+
87129 @override
88130 void addExtraListener () {
89- if (widget.clipboardAction == ClipboardAction .paste ) {
90- widget. _monitor.monitorClipboard (true , _listenClipboardStatus);
131+ if (_shouldUseClipboardMonitor ) {
132+ _monitor.monitorClipboard (true , _listenClipboardStatus);
91133 }
92134 }
93135
94136 @override
95137 void removeExtraListener (covariant QuillToolbarClipboardButton oldWidget) {
96- if (widget.clipboardAction == ClipboardAction .paste ) {
97- oldWidget. _monitor.monitorClipboard (false , _listenClipboardStatus);
138+ if (_shouldUseClipboardMonitor ) {
139+ _monitor.monitorClipboard (false , _listenClipboardStatus);
98140 }
99141 }
100142
@@ -112,6 +154,11 @@ class QuillToolbarClipboardButtonState
112154 ClipboardAction .paste => Icons .paste_outlined,
113155 };
114156
157+ bool get _shouldUseClipboardMonitor {
158+ return widget.clipboardAction == ClipboardAction .paste &&
159+ (widget._options? .enableClipboardPaste == null );
160+ }
161+
115162 void _onPressed () {
116163 switch (widget.clipboardAction) {
117164 case ClipboardAction .cut:
0 commit comments