refactor: move editor clipboard helpers into module
This commit is contained in:
@@ -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
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
})
|
||||||
+1
-81
@@ -1,10 +1,6 @@
|
|||||||
import {mount} from "svelte"
|
import {mount} from "svelte"
|
||||||
import type {Writable} from "svelte/store"
|
import type {Writable} from "svelte/store"
|
||||||
import {get, derived} from "svelte/store"
|
import {get, derived} from "svelte/store"
|
||||||
import {Clipboard} from "@capacitor/clipboard"
|
|
||||||
import {Capacitor} from "@capacitor/core"
|
|
||||||
import {Extension} from "@tiptap/core"
|
|
||||||
import {Plugin, PluginKey} from "@tiptap/pm/state"
|
|
||||||
import {Router} from "@welshman/router"
|
import {Router} from "@welshman/router"
|
||||||
import {dec, inc} from "@welshman/lib"
|
import {dec, inc} from "@welshman/lib"
|
||||||
import {throttled} from "@welshman/store"
|
import {throttled} from "@welshman/store"
|
||||||
@@ -19,6 +15,7 @@ import {
|
|||||||
} from "@welshman/app"
|
} from "@welshman/app"
|
||||||
import type {FileAttributes} from "@welshman/editor"
|
import type {FileAttributes} from "@welshman/editor"
|
||||||
import {Editor, MentionSuggestion, WelshmanExtension, editorProps} from "@welshman/editor"
|
import {Editor, MentionSuggestion, WelshmanExtension, editorProps} from "@welshman/editor"
|
||||||
|
import {NativeClipboardPasteExtension} from "@app/editor/clipboard"
|
||||||
import {escapeHtml} from "@lib/html"
|
import {escapeHtml} from "@lib/html"
|
||||||
import {makeMentionNodeView} from "@app/editor/MentionNodeView"
|
import {makeMentionNodeView} from "@app/editor/MentionNodeView"
|
||||||
import ProfileSuggestion from "@app/editor/ProfileSuggestion.svelte"
|
import ProfileSuggestion from "@app/editor/ProfileSuggestion.svelte"
|
||||||
@@ -26,83 +23,6 @@ import {uploadFile} from "@app/core/commands"
|
|||||||
import {deriveSpaceMembers} from "@app/core/state"
|
import {deriveSpaceMembers} from "@app/core/state"
|
||||||
import {pushToast} from "@app/util/toast"
|
import {pushToast} from "@app/util/toast"
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const makeEditor = async ({
|
export const makeEditor = async ({
|
||||||
encryptFiles = false,
|
encryptFiles = false,
|
||||||
aggressive = false,
|
aggressive = false,
|
||||||
|
|||||||
Reference in New Issue
Block a user