@capawesome/capacitor-clipboard 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CapawesomeCapacitorClipboard.podspec +17 -0
  2. package/LICENSE +21 -0
  3. package/Package.swift +28 -0
  4. package/README.md +220 -0
  5. package/android/build.gradle +58 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/java/io/capawesome/capacitorjs/plugins/clipboard/Clipboard.java +141 -0
  8. package/android/src/main/java/io/capawesome/capacitorjs/plugins/clipboard/ClipboardPlugin.java +96 -0
  9. package/android/src/main/java/io/capawesome/capacitorjs/plugins/clipboard/classes/ClipboardContentType.java +22 -0
  10. package/android/src/main/java/io/capawesome/capacitorjs/plugins/clipboard/classes/CustomException.java +20 -0
  11. package/android/src/main/java/io/capawesome/capacitorjs/plugins/clipboard/classes/CustomExceptions.java +12 -0
  12. package/android/src/main/java/io/capawesome/capacitorjs/plugins/clipboard/classes/options/WriteOptions.java +60 -0
  13. package/android/src/main/java/io/capawesome/capacitorjs/plugins/clipboard/classes/results/ReadResult.java +29 -0
  14. package/android/src/main/java/io/capawesome/capacitorjs/plugins/clipboard/interfaces/Callback.java +5 -0
  15. package/android/src/main/java/io/capawesome/capacitorjs/plugins/clipboard/interfaces/EmptyCallback.java +5 -0
  16. package/android/src/main/java/io/capawesome/capacitorjs/plugins/clipboard/interfaces/NonEmptyResultCallback.java +7 -0
  17. package/android/src/main/java/io/capawesome/capacitorjs/plugins/clipboard/interfaces/Result.java +7 -0
  18. package/android/src/main/res/.gitkeep +0 -0
  19. package/dist/docs.json +249 -0
  20. package/dist/esm/definitions.d.ts +144 -0
  21. package/dist/esm/definitions.js +57 -0
  22. package/dist/esm/definitions.js.map +1 -0
  23. package/dist/esm/index.d.ts +4 -0
  24. package/dist/esm/index.js +7 -0
  25. package/dist/esm/index.js.map +1 -0
  26. package/dist/esm/web.d.ts +16 -0
  27. package/dist/esm/web.js +109 -0
  28. package/dist/esm/web.js.map +1 -0
  29. package/dist/plugin.cjs.js +179 -0
  30. package/dist/plugin.cjs.js.map +1 -0
  31. package/dist/plugin.js +182 -0
  32. package/dist/plugin.js.map +1 -0
  33. package/ios/Plugin/Classes/Options/WriteOptions.swift +19 -0
  34. package/ios/Plugin/Classes/Results/ReadResult.swift +19 -0
  35. package/ios/Plugin/Clipboard.swift +74 -0
  36. package/ios/Plugin/ClipboardPlugin.swift +62 -0
  37. package/ios/Plugin/Enums/ClipboardContentType.swift +8 -0
  38. package/ios/Plugin/Enums/CustomError.swift +36 -0
  39. package/ios/Plugin/Info.plist +24 -0
  40. package/ios/Plugin/Protocols/Result.swift +5 -0
  41. package/package.json +94 -0
@@ -0,0 +1,109 @@
1
+ import { CapacitorException, WebPlugin } from '@capacitor/core';
2
+ import { ClipboardContentType, ErrorCode } from './definitions';
3
+ export class ClipboardWeb extends WebPlugin {
4
+ async read() {
5
+ if (navigator.clipboard.read) {
6
+ try {
7
+ const items = await navigator.clipboard.read();
8
+ for (const item of items) {
9
+ const imageType = item.types.find(type => type.startsWith('image/'));
10
+ if (imageType) {
11
+ const blob = await item.getType(imageType);
12
+ const value = await ClipboardWeb.convertBlobToDataUrl(blob);
13
+ return { type: ClipboardContentType.Image, value };
14
+ }
15
+ }
16
+ for (const item of items) {
17
+ if (item.types.includes('text/html')) {
18
+ const blob = await item.getType('text/html');
19
+ const value = await blob.text();
20
+ return { type: ClipboardContentType.Html, value };
21
+ }
22
+ }
23
+ }
24
+ catch (error) {
25
+ throw ClipboardWeb.createException(ClipboardWeb.errorReadFailed, ErrorCode.ReadFailed);
26
+ }
27
+ }
28
+ let value;
29
+ try {
30
+ value = await navigator.clipboard.readText();
31
+ }
32
+ catch (error) {
33
+ throw ClipboardWeb.createException(ClipboardWeb.errorReadFailed, ErrorCode.ReadFailed);
34
+ }
35
+ if (!value) {
36
+ throw ClipboardWeb.createException(ClipboardWeb.errorEmptyClipboard, ErrorCode.EmptyClipboard);
37
+ }
38
+ return { type: ClipboardWeb.resolveTextType(value), value };
39
+ }
40
+ async write(options) {
41
+ if (options.html === undefined &&
42
+ options.image === undefined &&
43
+ options.text === undefined &&
44
+ options.url === undefined) {
45
+ throw new Error(ClipboardWeb.errorContentMissing);
46
+ }
47
+ try {
48
+ if (options.image !== undefined) {
49
+ await ClipboardWeb.writeRichContent({
50
+ 'image/png': await ClipboardWeb.convertDataUrlToBlob(options.image),
51
+ });
52
+ }
53
+ else if (options.html !== undefined) {
54
+ const data = {
55
+ 'text/html': new Blob([options.html], { type: 'text/html' }),
56
+ };
57
+ if (options.text !== undefined) {
58
+ data['text/plain'] = new Blob([options.text], { type: 'text/plain' });
59
+ }
60
+ await ClipboardWeb.writeRichContent(data);
61
+ }
62
+ else if (options.url !== undefined) {
63
+ await navigator.clipboard.writeText(options.url);
64
+ }
65
+ else if (options.text !== undefined) {
66
+ await navigator.clipboard.writeText(options.text);
67
+ }
68
+ }
69
+ catch (error) {
70
+ if (error instanceof CapacitorException) {
71
+ throw error;
72
+ }
73
+ throw ClipboardWeb.createException(ClipboardWeb.errorWriteFailed, ErrorCode.WriteFailed);
74
+ }
75
+ }
76
+ static convertBlobToDataUrl(blob) {
77
+ return new Promise((resolve, reject) => {
78
+ const reader = new FileReader();
79
+ reader.onloadend = () => resolve(reader.result);
80
+ reader.onerror = () => reject(reader.error);
81
+ reader.readAsDataURL(blob);
82
+ });
83
+ }
84
+ static async convertDataUrlToBlob(dataUrl) {
85
+ const response = await fetch(dataUrl);
86
+ return response.blob();
87
+ }
88
+ static createException(message, code) {
89
+ return new CapacitorException(message, undefined, { code });
90
+ }
91
+ static resolveTextType(value) {
92
+ if (value.startsWith('http://') || value.startsWith('https://')) {
93
+ return ClipboardContentType.Url;
94
+ }
95
+ return ClipboardContentType.Text;
96
+ }
97
+ static async writeRichContent(data) {
98
+ if (typeof ClipboardItem === 'undefined') {
99
+ throw ClipboardWeb.createException(ClipboardWeb.errorRichContentNotSupported, ErrorCode.WriteFailed);
100
+ }
101
+ await navigator.clipboard.write([new ClipboardItem(data)]);
102
+ }
103
+ }
104
+ ClipboardWeb.errorContentMissing = 'One of text, html, image or url must be provided.';
105
+ ClipboardWeb.errorEmptyClipboard = 'The clipboard is empty.';
106
+ ClipboardWeb.errorReadFailed = 'The clipboard content could not be read.';
107
+ ClipboardWeb.errorRichContentNotSupported = 'This browser does not support writing rich content to the clipboard.';
108
+ ClipboardWeb.errorWriteFailed = 'The content could not be written to the clipboard.';
109
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"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","sourcesContent":["import { CapacitorException, WebPlugin } from '@capacitor/core';\n\nimport { ClipboardContentType, ErrorCode } from './definitions';\nimport type { ClipboardPlugin, ReadResult, WriteOptions } from './definitions';\n\nexport class ClipboardWeb extends WebPlugin implements ClipboardPlugin {\n private static readonly errorContentMissing =\n 'One of text, html, image or url must be provided.';\n private static readonly errorEmptyClipboard = 'The clipboard is empty.';\n private static readonly errorReadFailed =\n 'The clipboard content could not be read.';\n private static readonly errorRichContentNotSupported =\n 'This browser does not support writing rich content to the clipboard.';\n private static readonly errorWriteFailed =\n 'The content could not be written to the clipboard.';\n\n async read(): Promise<ReadResult> {\n if (navigator.clipboard.read) {\n try {\n const items = await navigator.clipboard.read();\n for (const item of items) {\n const imageType = item.types.find(type => type.startsWith('image/'));\n if (imageType) {\n const blob = await item.getType(imageType);\n const value = await ClipboardWeb.convertBlobToDataUrl(blob);\n return { type: ClipboardContentType.Image, value };\n }\n }\n for (const item of items) {\n if (item.types.includes('text/html')) {\n const blob = await item.getType('text/html');\n const value = await blob.text();\n return { type: ClipboardContentType.Html, value };\n }\n }\n } catch (error) {\n throw ClipboardWeb.createException(\n ClipboardWeb.errorReadFailed,\n ErrorCode.ReadFailed,\n );\n }\n }\n let value: string;\n try {\n value = await navigator.clipboard.readText();\n } catch (error) {\n throw ClipboardWeb.createException(\n ClipboardWeb.errorReadFailed,\n ErrorCode.ReadFailed,\n );\n }\n if (!value) {\n throw ClipboardWeb.createException(\n ClipboardWeb.errorEmptyClipboard,\n ErrorCode.EmptyClipboard,\n );\n }\n return { type: ClipboardWeb.resolveTextType(value), value };\n }\n\n async write(options: WriteOptions): Promise<void> {\n if (\n options.html === undefined &&\n options.image === undefined &&\n options.text === undefined &&\n options.url === undefined\n ) {\n throw new Error(ClipboardWeb.errorContentMissing);\n }\n try {\n if (options.image !== undefined) {\n await ClipboardWeb.writeRichContent({\n 'image/png': await ClipboardWeb.convertDataUrlToBlob(options.image),\n });\n } else if (options.html !== undefined) {\n const data: Record<string, Blob> = {\n 'text/html': new Blob([options.html], { type: 'text/html' }),\n };\n if (options.text !== undefined) {\n data['text/plain'] = new Blob([options.text], { type: 'text/plain' });\n }\n await ClipboardWeb.writeRichContent(data);\n } else if (options.url !== undefined) {\n await navigator.clipboard.writeText(options.url);\n } else if (options.text !== undefined) {\n await navigator.clipboard.writeText(options.text);\n }\n } catch (error) {\n if (error instanceof CapacitorException) {\n throw error;\n }\n throw ClipboardWeb.createException(\n ClipboardWeb.errorWriteFailed,\n ErrorCode.WriteFailed,\n );\n }\n }\n\n private static convertBlobToDataUrl(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => resolve(reader.result as string);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(blob);\n });\n }\n\n private static async convertDataUrlToBlob(dataUrl: string): Promise<Blob> {\n const response = await fetch(dataUrl);\n return response.blob();\n }\n\n private static createException(\n message: string,\n code: ErrorCode,\n ): CapacitorException {\n return new CapacitorException(message, undefined, { code });\n }\n\n private static resolveTextType(value: string): ClipboardContentType {\n if (value.startsWith('http://') || value.startsWith('https://')) {\n return ClipboardContentType.Url;\n }\n return ClipboardContentType.Text;\n }\n\n private static async writeRichContent(\n data: Record<string, Blob>,\n ): Promise<void> {\n if (typeof ClipboardItem === 'undefined') {\n throw ClipboardWeb.createException(\n ClipboardWeb.errorRichContentNotSupported,\n ErrorCode.WriteFailed,\n );\n }\n await navigator.clipboard.write([new ClipboardItem(data)]);\n }\n}\n"]}
@@ -0,0 +1,179 @@
1
+ 'use strict';
2
+
3
+ var core = require('@capacitor/core');
4
+
5
+ /**
6
+ * The type of content stored on the clipboard.
7
+ *
8
+ * @since 0.1.0
9
+ */
10
+ exports.ClipboardContentType = void 0;
11
+ (function (ClipboardContentType) {
12
+ /**
13
+ * The content is HTML.
14
+ *
15
+ * @since 0.1.0
16
+ */
17
+ ClipboardContentType["Html"] = "HTML";
18
+ /**
19
+ * The content is an image, returned as a Base64-encoded data URL.
20
+ *
21
+ * @since 0.1.0
22
+ */
23
+ ClipboardContentType["Image"] = "IMAGE";
24
+ /**
25
+ * The content is plain text.
26
+ *
27
+ * @since 0.1.0
28
+ */
29
+ ClipboardContentType["Text"] = "TEXT";
30
+ /**
31
+ * The content is a URL.
32
+ *
33
+ * @since 0.1.0
34
+ */
35
+ ClipboardContentType["Url"] = "URL";
36
+ })(exports.ClipboardContentType || (exports.ClipboardContentType = {}));
37
+ /**
38
+ * @since 0.1.0
39
+ */
40
+ exports.ErrorCode = void 0;
41
+ (function (ErrorCode) {
42
+ /**
43
+ * The clipboard is empty.
44
+ *
45
+ * @since 0.1.0
46
+ */
47
+ ErrorCode["EmptyClipboard"] = "EMPTY_CLIPBOARD";
48
+ /**
49
+ * The clipboard content could not be read.
50
+ *
51
+ * @since 0.1.0
52
+ */
53
+ ErrorCode["ReadFailed"] = "READ_FAILED";
54
+ /**
55
+ * The content could not be written to the clipboard.
56
+ *
57
+ * @since 0.1.0
58
+ */
59
+ ErrorCode["WriteFailed"] = "WRITE_FAILED";
60
+ })(exports.ErrorCode || (exports.ErrorCode = {}));
61
+
62
+ const Clipboard = core.registerPlugin('Clipboard', {
63
+ web: () => Promise.resolve().then(function () { return web; }).then(m => new m.ClipboardWeb()),
64
+ });
65
+
66
+ class ClipboardWeb extends core.WebPlugin {
67
+ async read() {
68
+ if (navigator.clipboard.read) {
69
+ try {
70
+ const items = await navigator.clipboard.read();
71
+ for (const item of items) {
72
+ const imageType = item.types.find(type => type.startsWith('image/'));
73
+ if (imageType) {
74
+ const blob = await item.getType(imageType);
75
+ const value = await ClipboardWeb.convertBlobToDataUrl(blob);
76
+ return { type: exports.ClipboardContentType.Image, value };
77
+ }
78
+ }
79
+ for (const item of items) {
80
+ if (item.types.includes('text/html')) {
81
+ const blob = await item.getType('text/html');
82
+ const value = await blob.text();
83
+ return { type: exports.ClipboardContentType.Html, value };
84
+ }
85
+ }
86
+ }
87
+ catch (error) {
88
+ throw ClipboardWeb.createException(ClipboardWeb.errorReadFailed, exports.ErrorCode.ReadFailed);
89
+ }
90
+ }
91
+ let value;
92
+ try {
93
+ value = await navigator.clipboard.readText();
94
+ }
95
+ catch (error) {
96
+ throw ClipboardWeb.createException(ClipboardWeb.errorReadFailed, exports.ErrorCode.ReadFailed);
97
+ }
98
+ if (!value) {
99
+ throw ClipboardWeb.createException(ClipboardWeb.errorEmptyClipboard, exports.ErrorCode.EmptyClipboard);
100
+ }
101
+ return { type: ClipboardWeb.resolveTextType(value), value };
102
+ }
103
+ async write(options) {
104
+ if (options.html === undefined &&
105
+ options.image === undefined &&
106
+ options.text === undefined &&
107
+ options.url === undefined) {
108
+ throw new Error(ClipboardWeb.errorContentMissing);
109
+ }
110
+ try {
111
+ if (options.image !== undefined) {
112
+ await ClipboardWeb.writeRichContent({
113
+ 'image/png': await ClipboardWeb.convertDataUrlToBlob(options.image),
114
+ });
115
+ }
116
+ else if (options.html !== undefined) {
117
+ const data = {
118
+ 'text/html': new Blob([options.html], { type: 'text/html' }),
119
+ };
120
+ if (options.text !== undefined) {
121
+ data['text/plain'] = new Blob([options.text], { type: 'text/plain' });
122
+ }
123
+ await ClipboardWeb.writeRichContent(data);
124
+ }
125
+ else if (options.url !== undefined) {
126
+ await navigator.clipboard.writeText(options.url);
127
+ }
128
+ else if (options.text !== undefined) {
129
+ await navigator.clipboard.writeText(options.text);
130
+ }
131
+ }
132
+ catch (error) {
133
+ if (error instanceof core.CapacitorException) {
134
+ throw error;
135
+ }
136
+ throw ClipboardWeb.createException(ClipboardWeb.errorWriteFailed, exports.ErrorCode.WriteFailed);
137
+ }
138
+ }
139
+ static convertBlobToDataUrl(blob) {
140
+ return new Promise((resolve, reject) => {
141
+ const reader = new FileReader();
142
+ reader.onloadend = () => resolve(reader.result);
143
+ reader.onerror = () => reject(reader.error);
144
+ reader.readAsDataURL(blob);
145
+ });
146
+ }
147
+ static async convertDataUrlToBlob(dataUrl) {
148
+ const response = await fetch(dataUrl);
149
+ return response.blob();
150
+ }
151
+ static createException(message, code) {
152
+ return new core.CapacitorException(message, undefined, { code });
153
+ }
154
+ static resolveTextType(value) {
155
+ if (value.startsWith('http://') || value.startsWith('https://')) {
156
+ return exports.ClipboardContentType.Url;
157
+ }
158
+ return exports.ClipboardContentType.Text;
159
+ }
160
+ static async writeRichContent(data) {
161
+ if (typeof ClipboardItem === 'undefined') {
162
+ throw ClipboardWeb.createException(ClipboardWeb.errorRichContentNotSupported, exports.ErrorCode.WriteFailed);
163
+ }
164
+ await navigator.clipboard.write([new ClipboardItem(data)]);
165
+ }
166
+ }
167
+ ClipboardWeb.errorContentMissing = 'One of text, html, image or url must be provided.';
168
+ ClipboardWeb.errorEmptyClipboard = 'The clipboard is empty.';
169
+ ClipboardWeb.errorReadFailed = 'The clipboard content could not be read.';
170
+ ClipboardWeb.errorRichContentNotSupported = 'This browser does not support writing rich content to the clipboard.';
171
+ ClipboardWeb.errorWriteFailed = 'The content could not be written to the clipboard.';
172
+
173
+ var web = /*#__PURE__*/Object.freeze({
174
+ __proto__: null,
175
+ ClipboardWeb: ClipboardWeb
176
+ });
177
+
178
+ exports.Clipboard = Clipboard;
179
+ //# sourceMappingURL=plugin.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["/**\n * The type of content stored on the clipboard.\n *\n * @since 0.1.0\n */\nexport var ClipboardContentType;\n(function (ClipboardContentType) {\n /**\n * The content is HTML.\n *\n * @since 0.1.0\n */\n ClipboardContentType[\"Html\"] = \"HTML\";\n /**\n * The content is an image, returned as a Base64-encoded data URL.\n *\n * @since 0.1.0\n */\n ClipboardContentType[\"Image\"] = \"IMAGE\";\n /**\n * The content is plain text.\n *\n * @since 0.1.0\n */\n ClipboardContentType[\"Text\"] = \"TEXT\";\n /**\n * The content is a URL.\n *\n * @since 0.1.0\n */\n ClipboardContentType[\"Url\"] = \"URL\";\n})(ClipboardContentType || (ClipboardContentType = {}));\n/**\n * @since 0.1.0\n */\nexport var ErrorCode;\n(function (ErrorCode) {\n /**\n * The clipboard is empty.\n *\n * @since 0.1.0\n */\n ErrorCode[\"EmptyClipboard\"] = \"EMPTY_CLIPBOARD\";\n /**\n * The clipboard content could not be read.\n *\n * @since 0.1.0\n */\n ErrorCode[\"ReadFailed\"] = \"READ_FAILED\";\n /**\n * The content could not be written to the clipboard.\n *\n * @since 0.1.0\n */\n ErrorCode[\"WriteFailed\"] = \"WRITE_FAILED\";\n})(ErrorCode || (ErrorCode = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst Clipboard = registerPlugin('Clipboard', {\n web: () => import('./web').then(m => new m.ClipboardWeb()),\n});\nexport * from './definitions';\nexport { Clipboard };\n//# sourceMappingURL=index.js.map","import { CapacitorException, WebPlugin } from '@capacitor/core';\nimport { ClipboardContentType, ErrorCode } from './definitions';\nexport class ClipboardWeb extends WebPlugin {\n async read() {\n if (navigator.clipboard.read) {\n try {\n const items = await navigator.clipboard.read();\n for (const item of items) {\n const imageType = item.types.find(type => type.startsWith('image/'));\n if (imageType) {\n const blob = await item.getType(imageType);\n const value = await ClipboardWeb.convertBlobToDataUrl(blob);\n return { type: ClipboardContentType.Image, value };\n }\n }\n for (const item of items) {\n if (item.types.includes('text/html')) {\n const blob = await item.getType('text/html');\n const value = await blob.text();\n return { type: ClipboardContentType.Html, value };\n }\n }\n }\n catch (error) {\n throw ClipboardWeb.createException(ClipboardWeb.errorReadFailed, ErrorCode.ReadFailed);\n }\n }\n let value;\n try {\n value = await navigator.clipboard.readText();\n }\n catch (error) {\n throw ClipboardWeb.createException(ClipboardWeb.errorReadFailed, ErrorCode.ReadFailed);\n }\n if (!value) {\n throw ClipboardWeb.createException(ClipboardWeb.errorEmptyClipboard, ErrorCode.EmptyClipboard);\n }\n return { type: ClipboardWeb.resolveTextType(value), value };\n }\n async write(options) {\n if (options.html === undefined &&\n options.image === undefined &&\n options.text === undefined &&\n options.url === undefined) {\n throw new Error(ClipboardWeb.errorContentMissing);\n }\n try {\n if (options.image !== undefined) {\n await ClipboardWeb.writeRichContent({\n 'image/png': await ClipboardWeb.convertDataUrlToBlob(options.image),\n });\n }\n else if (options.html !== undefined) {\n const data = {\n 'text/html': new Blob([options.html], { type: 'text/html' }),\n };\n if (options.text !== undefined) {\n data['text/plain'] = new Blob([options.text], { type: 'text/plain' });\n }\n await ClipboardWeb.writeRichContent(data);\n }\n else if (options.url !== undefined) {\n await navigator.clipboard.writeText(options.url);\n }\n else if (options.text !== undefined) {\n await navigator.clipboard.writeText(options.text);\n }\n }\n catch (error) {\n if (error instanceof CapacitorException) {\n throw error;\n }\n throw ClipboardWeb.createException(ClipboardWeb.errorWriteFailed, ErrorCode.WriteFailed);\n }\n }\n static convertBlobToDataUrl(blob) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => resolve(reader.result);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(blob);\n });\n }\n static async convertDataUrlToBlob(dataUrl) {\n const response = await fetch(dataUrl);\n return response.blob();\n }\n static createException(message, code) {\n return new CapacitorException(message, undefined, { code });\n }\n static resolveTextType(value) {\n if (value.startsWith('http://') || value.startsWith('https://')) {\n return ClipboardContentType.Url;\n }\n return ClipboardContentType.Text;\n }\n static async writeRichContent(data) {\n if (typeof ClipboardItem === 'undefined') {\n throw ClipboardWeb.createException(ClipboardWeb.errorRichContentNotSupported, ErrorCode.WriteFailed);\n }\n await navigator.clipboard.write([new ClipboardItem(data)]);\n }\n}\nClipboardWeb.errorContentMissing = 'One of text, html, image or url must be provided.';\nClipboardWeb.errorEmptyClipboard = 'The clipboard is empty.';\nClipboardWeb.errorReadFailed = 'The clipboard content could not be read.';\nClipboardWeb.errorRichContentNotSupported = 'This browser does not support writing rich content to the clipboard.';\nClipboardWeb.errorWriteFailed = 'The content could not be written to the clipboard.';\n//# sourceMappingURL=web.js.map"],"names":["ClipboardContentType","ErrorCode","registerPlugin","WebPlugin","CapacitorException"],"mappings":"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"}
package/dist/plugin.js ADDED
@@ -0,0 +1,182 @@
1
+ var capacitorClipboard = (function (exports, core) {
2
+ 'use strict';
3
+
4
+ /**
5
+ * The type of content stored on the clipboard.
6
+ *
7
+ * @since 0.1.0
8
+ */
9
+ exports.ClipboardContentType = void 0;
10
+ (function (ClipboardContentType) {
11
+ /**
12
+ * The content is HTML.
13
+ *
14
+ * @since 0.1.0
15
+ */
16
+ ClipboardContentType["Html"] = "HTML";
17
+ /**
18
+ * The content is an image, returned as a Base64-encoded data URL.
19
+ *
20
+ * @since 0.1.0
21
+ */
22
+ ClipboardContentType["Image"] = "IMAGE";
23
+ /**
24
+ * The content is plain text.
25
+ *
26
+ * @since 0.1.0
27
+ */
28
+ ClipboardContentType["Text"] = "TEXT";
29
+ /**
30
+ * The content is a URL.
31
+ *
32
+ * @since 0.1.0
33
+ */
34
+ ClipboardContentType["Url"] = "URL";
35
+ })(exports.ClipboardContentType || (exports.ClipboardContentType = {}));
36
+ /**
37
+ * @since 0.1.0
38
+ */
39
+ exports.ErrorCode = void 0;
40
+ (function (ErrorCode) {
41
+ /**
42
+ * The clipboard is empty.
43
+ *
44
+ * @since 0.1.0
45
+ */
46
+ ErrorCode["EmptyClipboard"] = "EMPTY_CLIPBOARD";
47
+ /**
48
+ * The clipboard content could not be read.
49
+ *
50
+ * @since 0.1.0
51
+ */
52
+ ErrorCode["ReadFailed"] = "READ_FAILED";
53
+ /**
54
+ * The content could not be written to the clipboard.
55
+ *
56
+ * @since 0.1.0
57
+ */
58
+ ErrorCode["WriteFailed"] = "WRITE_FAILED";
59
+ })(exports.ErrorCode || (exports.ErrorCode = {}));
60
+
61
+ const Clipboard = core.registerPlugin('Clipboard', {
62
+ web: () => Promise.resolve().then(function () { return web; }).then(m => new m.ClipboardWeb()),
63
+ });
64
+
65
+ class ClipboardWeb extends core.WebPlugin {
66
+ async read() {
67
+ if (navigator.clipboard.read) {
68
+ try {
69
+ const items = await navigator.clipboard.read();
70
+ for (const item of items) {
71
+ const imageType = item.types.find(type => type.startsWith('image/'));
72
+ if (imageType) {
73
+ const blob = await item.getType(imageType);
74
+ const value = await ClipboardWeb.convertBlobToDataUrl(blob);
75
+ return { type: exports.ClipboardContentType.Image, value };
76
+ }
77
+ }
78
+ for (const item of items) {
79
+ if (item.types.includes('text/html')) {
80
+ const blob = await item.getType('text/html');
81
+ const value = await blob.text();
82
+ return { type: exports.ClipboardContentType.Html, value };
83
+ }
84
+ }
85
+ }
86
+ catch (error) {
87
+ throw ClipboardWeb.createException(ClipboardWeb.errorReadFailed, exports.ErrorCode.ReadFailed);
88
+ }
89
+ }
90
+ let value;
91
+ try {
92
+ value = await navigator.clipboard.readText();
93
+ }
94
+ catch (error) {
95
+ throw ClipboardWeb.createException(ClipboardWeb.errorReadFailed, exports.ErrorCode.ReadFailed);
96
+ }
97
+ if (!value) {
98
+ throw ClipboardWeb.createException(ClipboardWeb.errorEmptyClipboard, exports.ErrorCode.EmptyClipboard);
99
+ }
100
+ return { type: ClipboardWeb.resolveTextType(value), value };
101
+ }
102
+ async write(options) {
103
+ if (options.html === undefined &&
104
+ options.image === undefined &&
105
+ options.text === undefined &&
106
+ options.url === undefined) {
107
+ throw new Error(ClipboardWeb.errorContentMissing);
108
+ }
109
+ try {
110
+ if (options.image !== undefined) {
111
+ await ClipboardWeb.writeRichContent({
112
+ 'image/png': await ClipboardWeb.convertDataUrlToBlob(options.image),
113
+ });
114
+ }
115
+ else if (options.html !== undefined) {
116
+ const data = {
117
+ 'text/html': new Blob([options.html], { type: 'text/html' }),
118
+ };
119
+ if (options.text !== undefined) {
120
+ data['text/plain'] = new Blob([options.text], { type: 'text/plain' });
121
+ }
122
+ await ClipboardWeb.writeRichContent(data);
123
+ }
124
+ else if (options.url !== undefined) {
125
+ await navigator.clipboard.writeText(options.url);
126
+ }
127
+ else if (options.text !== undefined) {
128
+ await navigator.clipboard.writeText(options.text);
129
+ }
130
+ }
131
+ catch (error) {
132
+ if (error instanceof core.CapacitorException) {
133
+ throw error;
134
+ }
135
+ throw ClipboardWeb.createException(ClipboardWeb.errorWriteFailed, exports.ErrorCode.WriteFailed);
136
+ }
137
+ }
138
+ static convertBlobToDataUrl(blob) {
139
+ return new Promise((resolve, reject) => {
140
+ const reader = new FileReader();
141
+ reader.onloadend = () => resolve(reader.result);
142
+ reader.onerror = () => reject(reader.error);
143
+ reader.readAsDataURL(blob);
144
+ });
145
+ }
146
+ static async convertDataUrlToBlob(dataUrl) {
147
+ const response = await fetch(dataUrl);
148
+ return response.blob();
149
+ }
150
+ static createException(message, code) {
151
+ return new core.CapacitorException(message, undefined, { code });
152
+ }
153
+ static resolveTextType(value) {
154
+ if (value.startsWith('http://') || value.startsWith('https://')) {
155
+ return exports.ClipboardContentType.Url;
156
+ }
157
+ return exports.ClipboardContentType.Text;
158
+ }
159
+ static async writeRichContent(data) {
160
+ if (typeof ClipboardItem === 'undefined') {
161
+ throw ClipboardWeb.createException(ClipboardWeb.errorRichContentNotSupported, exports.ErrorCode.WriteFailed);
162
+ }
163
+ await navigator.clipboard.write([new ClipboardItem(data)]);
164
+ }
165
+ }
166
+ ClipboardWeb.errorContentMissing = 'One of text, html, image or url must be provided.';
167
+ ClipboardWeb.errorEmptyClipboard = 'The clipboard is empty.';
168
+ ClipboardWeb.errorReadFailed = 'The clipboard content could not be read.';
169
+ ClipboardWeb.errorRichContentNotSupported = 'This browser does not support writing rich content to the clipboard.';
170
+ ClipboardWeb.errorWriteFailed = 'The content could not be written to the clipboard.';
171
+
172
+ var web = /*#__PURE__*/Object.freeze({
173
+ __proto__: null,
174
+ ClipboardWeb: ClipboardWeb
175
+ });
176
+
177
+ exports.Clipboard = Clipboard;
178
+
179
+ return exports;
180
+
181
+ })({}, capacitorExports);
182
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["/**\n * The type of content stored on the clipboard.\n *\n * @since 0.1.0\n */\nexport var ClipboardContentType;\n(function (ClipboardContentType) {\n /**\n * The content is HTML.\n *\n * @since 0.1.0\n */\n ClipboardContentType[\"Html\"] = \"HTML\";\n /**\n * The content is an image, returned as a Base64-encoded data URL.\n *\n * @since 0.1.0\n */\n ClipboardContentType[\"Image\"] = \"IMAGE\";\n /**\n * The content is plain text.\n *\n * @since 0.1.0\n */\n ClipboardContentType[\"Text\"] = \"TEXT\";\n /**\n * The content is a URL.\n *\n * @since 0.1.0\n */\n ClipboardContentType[\"Url\"] = \"URL\";\n})(ClipboardContentType || (ClipboardContentType = {}));\n/**\n * @since 0.1.0\n */\nexport var ErrorCode;\n(function (ErrorCode) {\n /**\n * The clipboard is empty.\n *\n * @since 0.1.0\n */\n ErrorCode[\"EmptyClipboard\"] = \"EMPTY_CLIPBOARD\";\n /**\n * The clipboard content could not be read.\n *\n * @since 0.1.0\n */\n ErrorCode[\"ReadFailed\"] = \"READ_FAILED\";\n /**\n * The content could not be written to the clipboard.\n *\n * @since 0.1.0\n */\n ErrorCode[\"WriteFailed\"] = \"WRITE_FAILED\";\n})(ErrorCode || (ErrorCode = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst Clipboard = registerPlugin('Clipboard', {\n web: () => import('./web').then(m => new m.ClipboardWeb()),\n});\nexport * from './definitions';\nexport { Clipboard };\n//# sourceMappingURL=index.js.map","import { CapacitorException, WebPlugin } from '@capacitor/core';\nimport { ClipboardContentType, ErrorCode } from './definitions';\nexport class ClipboardWeb extends WebPlugin {\n async read() {\n if (navigator.clipboard.read) {\n try {\n const items = await navigator.clipboard.read();\n for (const item of items) {\n const imageType = item.types.find(type => type.startsWith('image/'));\n if (imageType) {\n const blob = await item.getType(imageType);\n const value = await ClipboardWeb.convertBlobToDataUrl(blob);\n return { type: ClipboardContentType.Image, value };\n }\n }\n for (const item of items) {\n if (item.types.includes('text/html')) {\n const blob = await item.getType('text/html');\n const value = await blob.text();\n return { type: ClipboardContentType.Html, value };\n }\n }\n }\n catch (error) {\n throw ClipboardWeb.createException(ClipboardWeb.errorReadFailed, ErrorCode.ReadFailed);\n }\n }\n let value;\n try {\n value = await navigator.clipboard.readText();\n }\n catch (error) {\n throw ClipboardWeb.createException(ClipboardWeb.errorReadFailed, ErrorCode.ReadFailed);\n }\n if (!value) {\n throw ClipboardWeb.createException(ClipboardWeb.errorEmptyClipboard, ErrorCode.EmptyClipboard);\n }\n return { type: ClipboardWeb.resolveTextType(value), value };\n }\n async write(options) {\n if (options.html === undefined &&\n options.image === undefined &&\n options.text === undefined &&\n options.url === undefined) {\n throw new Error(ClipboardWeb.errorContentMissing);\n }\n try {\n if (options.image !== undefined) {\n await ClipboardWeb.writeRichContent({\n 'image/png': await ClipboardWeb.convertDataUrlToBlob(options.image),\n });\n }\n else if (options.html !== undefined) {\n const data = {\n 'text/html': new Blob([options.html], { type: 'text/html' }),\n };\n if (options.text !== undefined) {\n data['text/plain'] = new Blob([options.text], { type: 'text/plain' });\n }\n await ClipboardWeb.writeRichContent(data);\n }\n else if (options.url !== undefined) {\n await navigator.clipboard.writeText(options.url);\n }\n else if (options.text !== undefined) {\n await navigator.clipboard.writeText(options.text);\n }\n }\n catch (error) {\n if (error instanceof CapacitorException) {\n throw error;\n }\n throw ClipboardWeb.createException(ClipboardWeb.errorWriteFailed, ErrorCode.WriteFailed);\n }\n }\n static convertBlobToDataUrl(blob) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => resolve(reader.result);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(blob);\n });\n }\n static async convertDataUrlToBlob(dataUrl) {\n const response = await fetch(dataUrl);\n return response.blob();\n }\n static createException(message, code) {\n return new CapacitorException(message, undefined, { code });\n }\n static resolveTextType(value) {\n if (value.startsWith('http://') || value.startsWith('https://')) {\n return ClipboardContentType.Url;\n }\n return ClipboardContentType.Text;\n }\n static async writeRichContent(data) {\n if (typeof ClipboardItem === 'undefined') {\n throw ClipboardWeb.createException(ClipboardWeb.errorRichContentNotSupported, ErrorCode.WriteFailed);\n }\n await navigator.clipboard.write([new ClipboardItem(data)]);\n }\n}\nClipboardWeb.errorContentMissing = 'One of text, html, image or url must be provided.';\nClipboardWeb.errorEmptyClipboard = 'The clipboard is empty.';\nClipboardWeb.errorReadFailed = 'The clipboard content could not be read.';\nClipboardWeb.errorRichContentNotSupported = 'This browser does not support writing rich content to the clipboard.';\nClipboardWeb.errorWriteFailed = 'The content could not be written to the clipboard.';\n//# sourceMappingURL=web.js.map"],"names":["ClipboardContentType","ErrorCode","registerPlugin","WebPlugin","CapacitorException"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import Foundation
2
+ import Capacitor
3
+
4
+ @objc public class WriteOptions: NSObject {
5
+ let html: String?
6
+ let image: String?
7
+ let text: String?
8
+ let url: String?
9
+
10
+ init(_ call: CAPPluginCall) throws {
11
+ self.html = call.getString("html")
12
+ self.image = call.getString("image")
13
+ self.text = call.getString("text")
14
+ self.url = call.getString("url")
15
+ if html == nil && image == nil && text == nil && url == nil {
16
+ throw CustomError.contentMissing
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,19 @@
1
+ import Foundation
2
+ import Capacitor
3
+
4
+ @objc public class ReadResult: NSObject, Result {
5
+ let type: ClipboardContentType
6
+ let value: String
7
+
8
+ init(type: ClipboardContentType, value: String) {
9
+ self.type = type
10
+ self.value = value
11
+ }
12
+
13
+ @objc public func toJSObject() -> AnyObject {
14
+ var result = JSObject()
15
+ result["type"] = type.rawValue
16
+ result["value"] = value
17
+ return result as AnyObject
18
+ }
19
+ }
@@ -0,0 +1,74 @@
1
+ import Foundation
2
+ import Capacitor
3
+ import UIKit
4
+ import UniformTypeIdentifiers
5
+
6
+ @objc public class Clipboard: NSObject {
7
+ private let plugin: ClipboardPlugin
8
+
9
+ init(plugin: ClipboardPlugin) {
10
+ self.plugin = plugin
11
+ }
12
+
13
+ @objc public func read(completion: @escaping (ReadResult?, Error?) -> Void) {
14
+ DispatchQueue.main.async {
15
+ let pasteboard = UIPasteboard.general
16
+ if let image = pasteboard.image, let data = image.pngData() {
17
+ let value = "data:image/png;base64," + data.base64EncodedString()
18
+ completion(ReadResult(type: .image, value: value), nil)
19
+ return
20
+ }
21
+ if let data = pasteboard.data(forPasteboardType: UTType.html.identifier), let html = String(data: data, encoding: .utf8) {
22
+ completion(ReadResult(type: .html, value: html), nil)
23
+ return
24
+ }
25
+ if let string = pasteboard.string {
26
+ let type: ClipboardContentType = string.hasPrefix("http://") || string.hasPrefix("https://") ? .url : .text
27
+ completion(ReadResult(type: type, value: string), nil)
28
+ return
29
+ }
30
+ if let url = pasteboard.url {
31
+ completion(ReadResult(type: .url, value: url.absoluteString), nil)
32
+ return
33
+ }
34
+ completion(nil, CustomError.emptyClipboard)
35
+ }
36
+ }
37
+
38
+ @objc public func write(_ options: WriteOptions, completion: @escaping (Error?) -> Void) {
39
+ DispatchQueue.main.async {
40
+ let pasteboard = UIPasteboard.general
41
+ if let image = options.image {
42
+ guard let decodedImage = self.decodeDataUrl(image) else {
43
+ completion(CustomError.writeFailed)
44
+ return
45
+ }
46
+ pasteboard.image = decodedImage
47
+ } else if let html = options.html {
48
+ var item: [String: Any] = [UTType.html.identifier: html]
49
+ item[UTType.utf8PlainText.identifier] = options.text ?? html
50
+ pasteboard.items = [item]
51
+ } else if let url = options.url {
52
+ guard let url = URL(string: url) else {
53
+ completion(CustomError.writeFailed)
54
+ return
55
+ }
56
+ pasteboard.url = url
57
+ } else if let text = options.text {
58
+ pasteboard.string = text
59
+ }
60
+ completion(nil)
61
+ }
62
+ }
63
+
64
+ private func decodeDataUrl(_ dataUrl: String) -> UIImage? {
65
+ var base64 = dataUrl
66
+ if let range = dataUrl.range(of: ",") {
67
+ base64 = String(dataUrl[range.upperBound...])
68
+ }
69
+ guard let data = Data(base64Encoded: base64) else {
70
+ return nil
71
+ }
72
+ return UIImage(data: data)
73
+ }
74
+ }