Skip to content

Commit

Permalink
Add an option for ClipboardPaste button to disable ClipboardMonitor (#…
Browse files Browse the repository at this point in the history
…2427)

---------

Co-authored-by: Ellet <echo.ellet@gmail.com>
  • Loading branch information
Maksim-Nikolaev and EchoEllet authored Jan 21, 2025
1 parent 9c0faef commit bfbbfc0
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added

- `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).

## [11.0.0-dev.20] - 2025-01-19

### Changed
Expand Down
67 changes: 57 additions & 10 deletions lib/src/toolbar/buttons/clipboard_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ class ClipboardMonitor {
bool get canPaste => _canPaste;
Timer? _timer;

bool _isCheckingClipboard = false;

void monitorClipboard(bool add, void Function() listener) {
if (kIsWeb) return;

if (add) {
_timer = Timer.periodic(
const Duration(seconds: 1), (timer) => _update(listener));
Expand All @@ -33,17 +36,27 @@ class ClipboardMonitor {
}

Future<void> _update(void Function() listener) async {
if (_isCheckingClipboard) {
return;
}

_isCheckingClipboard = true;

final clipboardService = ClipboardServiceProvider.instance;

if (await clipboardService.hasClipboardContent) {
_canPaste = true;

listener();
}

_isCheckingClipboard = false;
}
}

@experimental
class QuillToolbarClipboardButton extends QuillToolbarToggleStyleBaseButton {
QuillToolbarClipboardButton({
const QuillToolbarClipboardButton({
required super.controller,
required this.clipboardAction,
QuillToolbarClipboardButtonOptions? options,
Expand All @@ -55,21 +68,19 @@ class QuillToolbarClipboardButton extends QuillToolbarToggleStyleBaseButton {
}) : _options = options,
super(options: options ?? const QuillToolbarClipboardButtonOptions());

// TODO: This field will be used by the PR: https://github.com/singerdmx/flutter-quill/pull/2427
// ignore: unused_field
final QuillToolbarClipboardButtonOptions? _options;

final ClipboardAction clipboardAction;

final ClipboardMonitor _monitor = ClipboardMonitor();

@override
State<StatefulWidget> createState() => QuillToolbarClipboardButtonState();
}

class QuillToolbarClipboardButtonState
extends QuillToolbarToggleStyleBaseButtonState<
QuillToolbarClipboardButton> {
final ClipboardMonitor _monitor = ClipboardMonitor();

@override
bool get currentStateValue {
switch (widget.clipboardAction) {
Expand All @@ -78,23 +89,54 @@ class QuillToolbarClipboardButtonState
case ClipboardAction.copy:
return !controller.selection.isCollapsed;
case ClipboardAction.paste:
return !controller.readOnly && (kIsWeb || widget._monitor.canPaste);
return !controller.readOnly &&
(kIsWeb ||
(widget._options?.enableClipboardPaste ?? _monitor.canPaste));
}
}

void _listenClipboardStatus() => didChangeEditingValue();

@override
void didUpdateWidget(QuillToolbarClipboardButton oldWidget) {
super.didUpdateWidget(oldWidget);

// Default didUpdateWidget handler, otherwise simple flag change didn't stop the monitor.
if (oldWidget.controller != controller) {
oldWidget.controller.removeListener(didChangeEditingValue);
removeExtraListener(oldWidget);
controller.addListener(didChangeEditingValue);
addExtraListener();
currentValue = currentStateValue;
}
// The controller didn't change, but enableClipboardPaste did.
else if (widget.clipboardAction == ClipboardAction.paste) {
final isTimerActive = _monitor._timer?.isActive ?? false;

// Enable clipboard monitoring if not active and should be monitored.
if (_shouldUseClipboardMonitor && !isTimerActive) {
_monitor.monitorClipboard(true, _listenClipboardStatus);
}
// Disable clipboard monitoring if active and should not be monitored.
else if (!_shouldUseClipboardMonitor && isTimerActive) {
_monitor.monitorClipboard(false, _listenClipboardStatus);
}

currentValue = currentStateValue;
}
}

@override
void addExtraListener() {
if (widget.clipboardAction == ClipboardAction.paste) {
widget._monitor.monitorClipboard(true, _listenClipboardStatus);
if (_shouldUseClipboardMonitor) {
_monitor.monitorClipboard(true, _listenClipboardStatus);
}
}

@override
void removeExtraListener(covariant QuillToolbarClipboardButton oldWidget) {
if (widget.clipboardAction == ClipboardAction.paste) {
oldWidget._monitor.monitorClipboard(false, _listenClipboardStatus);
if (_shouldUseClipboardMonitor) {
_monitor.monitorClipboard(false, _listenClipboardStatus);
}
}

Expand All @@ -112,6 +154,11 @@ class QuillToolbarClipboardButtonState
ClipboardAction.paste => Icons.paste_outlined,
};

bool get _shouldUseClipboardMonitor {
return widget.clipboardAction == ClipboardAction.paste &&
(widget._options?.enableClipboardPaste == null);
}

void _onPressed() {
switch (widget.clipboardAction) {
case ClipboardAction.cut:
Expand Down

0 comments on commit bfbbfc0

Please sign in to comment.