Skip to content

Commit

Permalink
added enableClipboardPaste to QuillSimpleToolbarConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
Maksim-Nikolaev committed Jan 5, 2025
1 parent dc4019a commit f2f3d86
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 20 deletions.
102 changes: 82 additions & 20 deletions lib/src/toolbar/buttons/clipboard_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,59 @@ 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));
const Duration(seconds: 5),
(timer) => _update(listener),
);
} else {
_timer?.cancel();
}
}

Future<void> _update(void Function() listener) async {
// If the clipboard is already being checked, return early.
if (_isCheckingClipboard) {
return;
}

// Prevent multiple clipboard checks at the same time.
_isCheckingClipboard = true;

// Initialize the clipboard service.
final clipboardService = ClipboardServiceProvider.instance;

// Check if the clipboard has content.
if (await clipboardService.hasClipboardContent) {
// If the clipboard has content, set the flag to true.
_canPaste = true;

// Notify the listener that the clipboard has content.
listener();
}

// Prevent multiple clipboard checks at the same time.
_isCheckingClipboard = false;
}
}

class QuillToolbarClipboardButton extends QuillToolbarToggleStyleBaseButton {
QuillToolbarClipboardButton({
const QuillToolbarClipboardButton({
required super.controller,
required this.clipboardAction,
super.options = const QuillToolbarToggleStyleButtonOptions(),

// If null, uses in-built [ClipboardMonitor]
// If true, paste button is enabled (if true & not readonly)
// If false, paste button is disabled
final bool? canPaste,
this.enableClipboardPaste,

/// Shares common options between all buttons, prefer the [options]
/// over the [baseOptions].
super.baseOptions,
Expand All @@ -49,7 +77,7 @@ class QuillToolbarClipboardButton extends QuillToolbarToggleStyleBaseButton {

final ClipboardAction clipboardAction;

final ClipboardMonitor _monitor = ClipboardMonitor();
final bool? enableClipboardPaste;

@override
State<StatefulWidget> createState() => QuillToolbarClipboardButtonState();
Expand All @@ -58,6 +86,8 @@ class QuillToolbarClipboardButton extends QuillToolbarToggleStyleBaseButton {
class QuillToolbarClipboardButtonState
extends QuillToolbarToggleStyleBaseButtonState<
QuillToolbarClipboardButton> {
final ClipboardMonitor _monitor = ClipboardMonitor();

@override
bool get currentStateValue {
switch (widget.clipboardAction) {
Expand All @@ -66,23 +96,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.enableClipboardPaste ?? _monitor.canPaste));
}
}

void _listenClipboardStatus() => didChangeEditingValue();
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;
}
// If controller didn't change, but something else did (enableClipboardPaste)
else if (widget.clipboardAction == ClipboardAction.paste) {
// If enableClipboardPaste is not null, disable monitors
if (widget.enableClipboardPaste != null) {
_monitor.monitorClipboard(false, _listenClipboardStatus);
currentValue = currentStateValue;
} else {
// Otherwise remove old listener and add a new one
_monitor.monitorClipboard(true, _listenClipboardStatus);
currentValue = currentStateValue;
}
}
}

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

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

Expand Down Expand Up @@ -131,16 +192,17 @@ class QuillToolbarClipboardButtonState
}

return UtilityWidgets.maybeTooltip(
message: tooltip,
child: QuillToolbarIconButton(
icon: Icon(
iconData,
size: iconSize * iconButtonFactor,
),
isSelected: false,
onPressed: currentValue ? _onPressed : null,
afterPressed: afterButtonPressed,
iconTheme: iconTheme,
));
message: tooltip,
child: QuillToolbarIconButton(
icon: Icon(
iconData,
size: iconSize * iconButtonFactor,
),
isSelected: false,
onPressed: currentValue ? _onPressed : null,
afterPressed: afterButtonPressed,
iconTheme: iconTheme,
),
);
}
}
6 changes: 6 additions & 0 deletions lib/src/toolbar/config/simple_toolbar_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class QuillSimpleToolbarConfig {
this.showClipboardCut = false,
this.showClipboardCopy = false,
this.showClipboardPaste = false,
this.enableClipboardPaste,
this.linkStyleType = LinkStyleType.original,
this.headerStyleType = HeaderStyleType.original,

Expand Down Expand Up @@ -183,6 +184,11 @@ class QuillSimpleToolbarConfig {
final bool showClipboardCopy;
final bool showClipboardPaste;

/// If null, uses in-built [ClipboardMonitor]
/// If true, paste button is enabled (if true & not readonly)
/// If false, paste button is disabled
final bool? enableClipboardPaste;

/// This activates a functionality that is only implemented in [flutter_quill] and is NOT originally
/// used in the [Quill Js API]. So it could cause conflicts if you use this attribute with the original Delta format of Quill Js
final bool showLineHeightButton;
Expand Down
1 change: 1 addition & 0 deletions lib/src/toolbar/simple_toolbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ class QuillSimpleToolbar extends StatelessWidget
options: config.buttonOptions.clipboardPaste,
controller: controller,
clipboardAction: ClipboardAction.paste,
enableClipboardPaste: config.enableClipboardPaste,
),
],
[
Expand Down

0 comments on commit f2f3d86

Please sign in to comment.