fix: support native clipboard image paste on mobile (#181)
Co-authored-by: Khushvendra <khushvendras99@gmail.com> Co-committed-by: Khushvendra <khushvendras99@gmail.com>
This commit is contained in:
parent
90f86b833d
commit
f6d9e52c6e
4 changed files with 85 additions and 0 deletions
|
|
@ -48,6 +48,7 @@
|
|||
"@capacitor/android": "^8.0.1",
|
||||
"@capacitor/app": "^8.0.0",
|
||||
"@capacitor/cli": "^8.0.1",
|
||||
"@capacitor/clipboard": "^8.0.1",
|
||||
"@capacitor/core": "^8.0.1",
|
||||
"@capacitor/filesystem": "^8.1.0",
|
||||
"@capacitor/ios": "^8.0.1",
|
||||
|
|
@ -63,6 +64,7 @@
|
|||
"@poppanator/sveltekit-svg": "^4.2.1",
|
||||
"@sveltejs/adapter-static": "^3.0.10",
|
||||
"@tiptap/core": "^2.27.2",
|
||||
"@tiptap/pm": "^2.27.2",
|
||||
"@types/qrcode": "^1.5.6",
|
||||
"@types/throttle-debounce": "^5.0.2",
|
||||
"@vite-pwa/assets-generator": "^0.2.6",
|
||||
|
|
|
|||
BIN
pnpm-lock.yaml
BIN
pnpm-lock.yaml
Binary file not shown.
81
src/app/editor/clipboard.ts
Normal file
81
src/app/editor/clipboard.ts
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import {Clipboard} from "@capacitor/clipboard"
|
||||
import {Capacitor} from "@capacitor/core"
|
||||
import {Extension} from "@tiptap/core"
|
||||
import {Plugin, PluginKey} from "@tiptap/pm/state"
|
||||
|
||||
const nativeClipboardAvailable = () =>
|
||||
Capacitor.isNativePlatform() && Capacitor.isPluginAvailable("Clipboard")
|
||||
|
||||
const hasStandardPastePayload = (event: ClipboardEvent) => {
|
||||
const clipboardData = event.clipboardData
|
||||
|
||||
if (!clipboardData) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (Array.from(clipboardData.items).some(item => item.kind === "file")) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (clipboardData.types.includes("text/html")) {
|
||||
return true
|
||||
}
|
||||
|
||||
return clipboardData.getData("text/plain") !== ""
|
||||
}
|
||||
|
||||
const getNativeClipboardImage = async () => {
|
||||
try {
|
||||
const {type, value} = await Clipboard.read()
|
||||
|
||||
if (!type.startsWith("image/") || value === "") {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const imageData = value.startsWith("data:") ? value : `data:${type};base64,${value}`
|
||||
const blob = await fetch(imageData).then(res => res.blob())
|
||||
|
||||
if (!blob.type.startsWith("image/")) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const extension = type.split("/")[1]?.split("+")[0] || "png"
|
||||
|
||||
return new File([blob], `clipboard-image.${extension}`, {type: blob.type || type})
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
export const NativeClipboardPasteExtension = Extension.create({
|
||||
name: "nativeClipboardPaste",
|
||||
|
||||
addProseMirrorPlugins() {
|
||||
const editor = this.editor
|
||||
|
||||
return [
|
||||
new Plugin({
|
||||
key: new PluginKey("nativeClipboardPaste"),
|
||||
props: {
|
||||
handlePaste: (_view, event) => {
|
||||
if (!nativeClipboardAvailable() || hasStandardPastePayload(event)) {
|
||||
return false
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
|
||||
void getNativeClipboardImage().then(file => {
|
||||
if (!file) {
|
||||
return
|
||||
}
|
||||
|
||||
editor.commands.addFile(file, editor.state.selection.from + 1)
|
||||
})
|
||||
|
||||
return true
|
||||
},
|
||||
},
|
||||
}),
|
||||
]
|
||||
},
|
||||
})
|
||||
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from "@welshman/app"
|
||||
import type {FileAttributes} from "@welshman/editor"
|
||||
import {Editor, MentionSuggestion, WelshmanExtension, editorProps} from "@welshman/editor"
|
||||
import {NativeClipboardPasteExtension} from "@app/editor/clipboard"
|
||||
import {escapeHtml} from "@lib/html"
|
||||
import {makeMentionNodeView} from "@app/editor/MentionNodeView"
|
||||
import ProfileSuggestion from "@app/editor/ProfileSuggestion.svelte"
|
||||
|
|
@ -137,6 +138,7 @@ export const makeEditor = async ({
|
|||
},
|
||||
},
|
||||
}),
|
||||
NativeClipboardPasteExtension,
|
||||
],
|
||||
onUpdate({editor}) {
|
||||
wordCount?.set(editor.storage.wordCount.words)
|
||||
|
|
|
|||
Loading…
Reference in a new issue