Skip to content

Commit d3de671

Browse files
committed
feat: first commit, part of singerdmx/flutter-quill#2230
0 parents  commit d3de671

File tree

10 files changed

+305
-0
lines changed

10 files changed

+305
-0
lines changed

.gitignore

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.buildlog/
9+
.history
10+
.svn/
11+
migrate_working_dir/
12+
13+
# IntelliJ related
14+
*.iml
15+
*.ipr
16+
*.iws
17+
.idea/
18+
19+
# The .vscode folder contains launch configuration and tasks you configure in
20+
# VS Code which you may wish to be included in version control, so this line
21+
# is commented out by default.
22+
#.vscode/
23+
24+
# Flutter/Dart/Pub related
25+
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
26+
/pubspec.lock
27+
**/doc/api/
28+
.dart_tool/
29+
build/
30+
.flutter-plugins
31+
.flutter-plugins-dependencies

.metadata

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: "2663184aa79047d0a33a14a3b607954f8fdd8730"
8+
channel: "stable"
9+
10+
project_type: package

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 0.0.1
2+
3+
* initial release.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Flutter Quill project and open source contributors.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# 🪶 Quill Super Clipboard
2+
3+
A package for integrating the package [`super_clipboard`](https://pub.dev/packages/super_clipboard) with [`flutter_quill`](https://pub.dev/packages/flutter_quill)
4+
to provide seamless access to the system clipboard for rich text operations.
5+
6+
> **Caution**
7+
>
8+
> The support of this package might be discontinued in the future versions of [flutter_quill](https://pub.dev/packages/flutter_quill).
9+
10+
## Usage
11+
12+
To use the `super_clipboard` implementation with this package:
13+
14+
```dart
15+
import 'package:quill_super_clipboard/quill_super_clipboard.dart';
16+
17+
QuillSuperClipboard.use();
18+
```
19+
20+
> **Note**
21+
>
22+
> The default clipboard implementation for `flutter_quill` is now [`quill_native_bridge`](https://pub.dev/packages/quill_native_bridge). It provides full support for all system clipboard features used by `flutter_quill`.

analysis_options.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
include: package:flutter_lints/flutter.yaml
2+

lib/quill_super_clipboard.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/// A library for integrating the package [`super_clipboard`](https://pub.dev/packages/super_clipboard) with [`flutter_quill`](https://pub.dev/packages/flutter_quill)
2+
/// to provide seamless access to the system clipboard for rich text operations.
3+
@experimental
4+
library;
5+
6+
import 'package:flutter_quill/flutter_quill_internal.dart';
7+
import 'package:meta/meta.dart' show experimental;
8+
9+
import 'src/super_clipboard_service.dart';
10+
11+
/// Provides integration of the [`super_clipboard`](https://pub.dev/packages/super_clipboard)
12+
/// package with [`flutter_quill`](https://pub.dev/packages/flutter_quill) package
13+
/// to the system clipboard for rich text operations.
14+
@experimental
15+
class QuillSuperClipboard {
16+
/// Private constructor
17+
QuillSuperClipboard._();
18+
19+
/// Use the [`super_clipboard`](https://pub.dev/packages/super_clipboard)
20+
/// plugin as clipboard implementation for [`flutter_quill`](https://pub.dev/packages/flutter_quill)
21+
/// to access the system clipboard for rich text operations.
22+
///
23+
/// See also: [`quill_native_bridge`](https://pub.dev/packages/quill_native_bridge)
24+
/// which is the default clipboard implementation for [flutter_quill](https://pub.dev/packages/flutter_quill).
25+
@experimental
26+
static void use() {
27+
ClipboardServiceProvider.setInstance(SuperClipboardService());
28+
}
29+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import 'dart:async' show Completer;
2+
import 'dart:convert' show utf8;
3+
4+
import 'package:flutter/foundation.dart';
5+
import 'package:flutter_quill/flutter_quill_internal.dart';
6+
import 'package:meta/meta.dart' show experimental;
7+
8+
import 'package:super_clipboard/super_clipboard.dart';
9+
10+
/// Implementation using the [super_clipboard](https://pub.dev/packages/super_clipboard) plugin.
11+
@experimental
12+
class SuperClipboardService extends ClipboardService {
13+
/// [Null] if the Clipboard API is not supported on this platform
14+
/// https://pub.dev/packages/super_clipboard#usage
15+
SystemClipboard? _getSuperClipboard() {
16+
return SystemClipboard.instance;
17+
}
18+
19+
SystemClipboard _getSuperClipboardOrThrow() {
20+
final clipboard = _getSuperClipboard();
21+
if (clipboard == null) {
22+
// To avoid getting this exception, use _canProvide()
23+
throw UnsupportedError(
24+
'Clipboard API is not supported on this platform.',
25+
);
26+
}
27+
return clipboard;
28+
}
29+
30+
Future<bool> _canProvide({required DataFormat format}) async {
31+
final clipboard = _getSuperClipboard();
32+
if (clipboard == null) {
33+
return false;
34+
}
35+
final reader = await clipboard.read();
36+
return reader.canProvide(format);
37+
}
38+
39+
Future<Uint8List> _provideFileAsBytes({
40+
required SimpleFileFormat format,
41+
}) async {
42+
final clipboard = _getSuperClipboardOrThrow();
43+
final reader = await clipboard.read();
44+
final completer = Completer<Uint8List>();
45+
46+
reader.getFile(
47+
format,
48+
(file) async {
49+
final bytes = await file.readAll();
50+
completer.complete(bytes);
51+
},
52+
onError: completer.completeError,
53+
);
54+
final bytes = await completer.future;
55+
return bytes;
56+
}
57+
58+
Future<String> _provideFileAsString({
59+
required SimpleFileFormat format,
60+
}) async {
61+
final fileBytes = await _provideFileAsBytes(format: format);
62+
final fileText = utf8.decode(fileBytes);
63+
return fileText;
64+
}
65+
66+
/// According to super_clipboard docs, will return `null` if the value
67+
/// is not available or the data is virtual (macOS and Windows)
68+
Future<String?> _provideSimpleValueFormatAsString({
69+
required SimpleValueFormat<String> format,
70+
}) async {
71+
final clipboard = _getSuperClipboardOrThrow();
72+
final reader = await clipboard.read();
73+
final value = await reader.readValue<String>(format);
74+
return value;
75+
}
76+
77+
@override
78+
Future<String?> getHtmlText() async {
79+
if (!(await _canProvide(format: Formats.htmlText))) {
80+
return null;
81+
}
82+
return _provideSimpleValueFormatAsString(format: Formats.htmlText);
83+
}
84+
85+
@override
86+
Future<String?> getHtmlFile() async {
87+
if (!(await _canProvide(format: Formats.htmlFile))) {
88+
return null;
89+
}
90+
return await _provideFileAsString(format: Formats.htmlFile);
91+
}
92+
93+
@override
94+
Future<Uint8List?> getGifFile() async {
95+
if (!(await _canProvide(format: Formats.gif))) {
96+
return null;
97+
}
98+
return await _provideFileAsBytes(format: Formats.gif);
99+
}
100+
101+
@override
102+
Future<Uint8List?> getImageFile() async {
103+
final canProvidePngFile = await _canProvide(format: Formats.png);
104+
if (canProvidePngFile) {
105+
return _provideFileAsBytes(format: Formats.png);
106+
}
107+
final canProvideJpegFile = await _canProvide(format: Formats.jpeg);
108+
if (canProvideJpegFile) {
109+
return _provideFileAsBytes(format: Formats.jpeg);
110+
}
111+
return null;
112+
}
113+
114+
@override
115+
Future<String?> getMarkdownFile() async {
116+
// Formats.md is for markdown files
117+
if (!(await _canProvide(format: Formats.md))) {
118+
return null;
119+
}
120+
return await _provideFileAsString(format: Formats.md);
121+
}
122+
123+
@override
124+
Future<void> copyImageToClipboard(Uint8List imageBytes) async {
125+
final clipboard = SystemClipboard.instance;
126+
if (clipboard == null) {
127+
return;
128+
}
129+
final item = DataWriterItem()..add(Formats.png(imageBytes));
130+
await clipboard.write([item]);
131+
}
132+
133+
@override
134+
Future<bool> get hasClipboardContent async {
135+
final clipboard = _getSuperClipboard();
136+
if (clipboard == null) {
137+
return false;
138+
}
139+
final reader = await clipboard.read();
140+
final availablePlatformFormats = reader.platformFormats;
141+
return availablePlatformFormats.isNotEmpty;
142+
}
143+
}

pubspec.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: quill_super_clipboard
2+
description: "A package for integrating the package super_clipboard with flutter_quill to provide access to the system clipboard."
3+
version: 0.0.1
4+
homepage: https://github.com/FlutterQuill/quill-super-clipboard
5+
repository: https://github.com/FlutterQuill/quill-super-clipboard
6+
issue_tracker: https://github.com/FlutterQuill/quill-super-clipboard/issues
7+
documentation: https://github.com/FlutterQuill/quill-super-clipboard
8+
9+
environment:
10+
sdk: '>=3.0.0 <4.0.0'
11+
flutter: ">=3.0.0"
12+
13+
dependencies:
14+
flutter:
15+
sdk: flutter
16+
super_clipboard: ^0.8.24
17+
# TODO: Publish the package and use latest version of flutter_quill once https://github.com/singerdmx/flutter-quill/pull/2230 is published
18+
flutter_quill:
19+
path: /Users/ellet/Developer/playground/framework_based/flutter/flutter-quill/
20+
meta: ^1.10.0
21+
22+
dev_dependencies:
23+
test: ^1.25.8
24+
flutter_lints: ^5.0.0
25+
26+
flutter:
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import 'package:flutter_quill/flutter_quill_internal.dart';
2+
import 'package:quill_super_clipboard/quill_super_clipboard.dart';
3+
import 'package:test/test.dart';
4+
5+
import 'package:quill_super_clipboard/src/super_clipboard_service.dart';
6+
7+
void main() {
8+
test(
9+
'Calling QuillSuperClipboard.use() should set the instance to SuperClipboardService',
10+
() {
11+
QuillSuperClipboard.use();
12+
expect(
13+
ClipboardServiceProvider.instance,
14+
isA<SuperClipboardService>(),
15+
);
16+
},
17+
);
18+
}

0 commit comments

Comments
 (0)