Skip to content

Commit bfbbfc0

Browse files
Add an option for ClipboardPaste button to disable ClipboardMonitor (#2427)
--------- Co-authored-by: Ellet <[email protected]>
1 parent 9c0faef commit bfbbfc0

File tree

2 files changed

+61
-10
lines changed

2 files changed

+61
-10
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
1111
## [Unreleased]
1212

13+
### Added
14+
15+
- `enableClipboardPaste` flag in `QuillToolbarClipboardButton` to determine if the button defaults to `null,` which will use `ClipboardMonitor`, which checks every second if the clipboard has content to paste [#2427](https://github.com/singerdmx/flutter-quill/pull/2427).
16+
1317
## [11.0.0-dev.20] - 2025-01-19
1418

1519
### Changed

lib/src/toolbar/buttons/clipboard_button.dart

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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
4558
class 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

7079
class 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

Comments
 (0)