mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge pull request #1550 from LucasXu0/fix_windows_copy_paste
fix: Clipboard does not work in Windows #1406
This commit is contained in:
commit
a507fb8ec6
@ -0,0 +1,54 @@
|
|||||||
|
import 'dart:io' show Platform;
|
||||||
|
|
||||||
|
import 'package:rich_clipboard/rich_clipboard.dart';
|
||||||
|
|
||||||
|
class AppFlowyClipboardData {
|
||||||
|
const AppFlowyClipboardData({
|
||||||
|
required this.text,
|
||||||
|
required this.html,
|
||||||
|
});
|
||||||
|
final String? text;
|
||||||
|
final String? html;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppFlowyClipboard {
|
||||||
|
static Future<void> setData({
|
||||||
|
String? text,
|
||||||
|
String? html,
|
||||||
|
}) async {
|
||||||
|
// https://github.com/BringingFire/rich_clipboard/issues/13
|
||||||
|
// Wrapping a `<html><body>` tag for html in Windows,
|
||||||
|
// otherwise it will raise an exception
|
||||||
|
if (Platform.isWindows && html != null) {
|
||||||
|
if (!html.startsWith('<html><body>')) {
|
||||||
|
html = '<html><body>$html</body></html>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RichClipboard.setData(
|
||||||
|
RichClipboardData(
|
||||||
|
text: text,
|
||||||
|
html: html,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<AppFlowyClipboardData> getData() async {
|
||||||
|
final data = await RichClipboard.getData();
|
||||||
|
final text = data.text;
|
||||||
|
var html = data.html;
|
||||||
|
|
||||||
|
// https://github.com/BringingFire/rich_clipboard/issues/13
|
||||||
|
// Remove all the fragment symbol in Windows.
|
||||||
|
if (Platform.isWindows && html != null) {
|
||||||
|
html = html
|
||||||
|
.replaceAll('<!--StartFragment-->', '')
|
||||||
|
.replaceAll('<!--EndFragment-->', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppFlowyClipboardData(
|
||||||
|
text: text,
|
||||||
|
html: html,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:appflowy_editor/src/core/document/node.dart';
|
import 'package:appflowy_editor/src/core/document/node.dart';
|
||||||
|
import 'package:appflowy_editor/src/infra/clipboard.dart';
|
||||||
import 'package:appflowy_editor/src/service/render_plugin_service.dart';
|
import 'package:appflowy_editor/src/service/render_plugin_service.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:rich_clipboard/rich_clipboard.dart';
|
|
||||||
|
|
||||||
import 'image_node_widget.dart';
|
import 'image_node_widget.dart';
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ class ImageNodeBuilder extends NodeWidgetBuilder<Node> {
|
|||||||
width: width,
|
width: width,
|
||||||
alignment: _textToAlignment(align),
|
alignment: _textToAlignment(align),
|
||||||
onCopy: () {
|
onCopy: () {
|
||||||
RichClipboard.setData(RichClipboardData(text: src));
|
AppFlowyClipboard.setData(text: src);
|
||||||
},
|
},
|
||||||
onDelete: () {
|
onDelete: () {
|
||||||
final transaction = context.editorState.transaction
|
final transaction = context.editorState.transaction
|
||||||
|
@ -2,6 +2,7 @@ import 'package:appflowy_editor/appflowy_editor.dart';
|
|||||||
import 'package:appflowy_editor/src/commands/text/text_commands.dart';
|
import 'package:appflowy_editor/src/commands/text/text_commands.dart';
|
||||||
import 'package:appflowy_editor/src/extensions/url_launcher_extension.dart';
|
import 'package:appflowy_editor/src/extensions/url_launcher_extension.dart';
|
||||||
import 'package:appflowy_editor/src/flutter/overlay.dart';
|
import 'package:appflowy_editor/src/flutter/overlay.dart';
|
||||||
|
import 'package:appflowy_editor/src/infra/clipboard.dart';
|
||||||
import 'package:appflowy_editor/src/infra/flowy_svg.dart';
|
import 'package:appflowy_editor/src/infra/flowy_svg.dart';
|
||||||
import 'package:appflowy_editor/src/render/link_menu/link_menu.dart';
|
import 'package:appflowy_editor/src/render/link_menu/link_menu.dart';
|
||||||
import 'package:appflowy_editor/src/extensions/text_node_extensions.dart';
|
import 'package:appflowy_editor/src/extensions/text_node_extensions.dart';
|
||||||
@ -9,7 +10,6 @@ import 'package:appflowy_editor/src/extensions/editor_state_extensions.dart';
|
|||||||
import 'package:appflowy_editor/src/service/default_text_operations/format_rich_text_style.dart';
|
import 'package:appflowy_editor/src/service/default_text_operations/format_rich_text_style.dart';
|
||||||
|
|
||||||
import 'package:flutter/material.dart' hide Overlay, OverlayEntry;
|
import 'package:flutter/material.dart' hide Overlay, OverlayEntry;
|
||||||
import 'package:rich_clipboard/rich_clipboard.dart';
|
|
||||||
|
|
||||||
typedef ToolbarItemEventHandler = void Function(
|
typedef ToolbarItemEventHandler = void Function(
|
||||||
EditorState editorState, BuildContext context);
|
EditorState editorState, BuildContext context);
|
||||||
@ -363,7 +363,7 @@ void showLinkMenu(
|
|||||||
_dismissLinkMenu();
|
_dismissLinkMenu();
|
||||||
},
|
},
|
||||||
onCopyLink: () {
|
onCopyLink: () {
|
||||||
RichClipboard.setData(RichClipboardData(text: linkText));
|
AppFlowyClipboard.setData(text: linkText);
|
||||||
_dismissLinkMenu();
|
_dismissLinkMenu();
|
||||||
},
|
},
|
||||||
onRemoveLink: () {
|
onRemoveLink: () {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
import 'package:appflowy_editor/src/infra/clipboard.dart';
|
||||||
import 'package:appflowy_editor/src/infra/html_converter.dart';
|
import 'package:appflowy_editor/src/infra/html_converter.dart';
|
||||||
import 'package:appflowy_editor/src/core/document/node_iterator.dart';
|
import 'package:appflowy_editor/src/core/document/node_iterator.dart';
|
||||||
import 'package:appflowy_editor/src/service/internal_key_event_handlers/number_list_helper.dart';
|
import 'package:appflowy_editor/src/service/internal_key_event_handlers/number_list_helper.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:rich_clipboard/rich_clipboard.dart';
|
|
||||||
|
|
||||||
int _textLengthOfNode(Node node) {
|
int _textLengthOfNode(Node node) {
|
||||||
if (node is TextNode) {
|
if (node is TextNode) {
|
||||||
@ -38,14 +38,15 @@ void _handleCopy(EditorState editorState) async {
|
|||||||
startOffset: selection.start.offset,
|
startOffset: selection.start.offset,
|
||||||
endOffset: selection.end.offset)
|
endOffset: selection.end.offset)
|
||||||
.toHTMLString();
|
.toHTMLString();
|
||||||
Log.keyboard.debug('copy html: $htmlString');
|
final textString = textNode.toPlainText().substring(
|
||||||
RichClipboard.setData(RichClipboardData(
|
|
||||||
html: htmlString,
|
|
||||||
text: textNode.toPlainText().substring(
|
|
||||||
selection.startIndex,
|
selection.startIndex,
|
||||||
selection.endIndex,
|
selection.endIndex,
|
||||||
),
|
);
|
||||||
));
|
Log.keyboard.debug('copy html: $htmlString');
|
||||||
|
AppFlowyClipboard.setData(
|
||||||
|
text: textString,
|
||||||
|
html: htmlString,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
Log.keyboard.debug('unimplemented: copy non-text');
|
Log.keyboard.debug('unimplemented: copy non-text');
|
||||||
}
|
}
|
||||||
@ -79,7 +80,10 @@ void _handleCopy(EditorState editorState) async {
|
|||||||
}
|
}
|
||||||
text += '\n';
|
text += '\n';
|
||||||
}
|
}
|
||||||
RichClipboard.setData(RichClipboardData(html: html, text: text));
|
AppFlowyClipboard.setData(
|
||||||
|
text: text,
|
||||||
|
html: html,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pasteHTML(EditorState editorState, String html) {
|
void _pasteHTML(EditorState editorState, String html) {
|
||||||
@ -186,7 +190,7 @@ void _pasteMultipleLinesInText(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _handlePaste(EditorState editorState) async {
|
void _handlePaste(EditorState editorState) async {
|
||||||
final data = await RichClipboard.getData();
|
final data = await AppFlowyClipboard.getData();
|
||||||
|
|
||||||
if (editorState.cursorSelection?.isCollapsed ?? false) {
|
if (editorState.cursorSelection?.isCollapsed ?? false) {
|
||||||
_pastRichClipboard(editorState, data);
|
_pastRichClipboard(editorState, data);
|
||||||
@ -200,7 +204,7 @@ void _handlePaste(EditorState editorState) async {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pastRichClipboard(EditorState editorState, RichClipboardData data) {
|
void _pastRichClipboard(EditorState editorState, AppFlowyClipboardData data) {
|
||||||
if (data.html != null) {
|
if (data.html != null) {
|
||||||
_pasteHTML(editorState, data.html!);
|
_pasteHTML(editorState, data.html!);
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user