mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 06:52:21 -04:00
Handle internal pastes
This commit is contained in:
parent
4567c721ad
commit
3b42cd0e54
1 changed files with 31 additions and 24 deletions
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
import { ConfigKey_Bool } from "@generated/anki/config_pb";
|
import { ConfigKey_Bool } from "@generated/anki/config_pb";
|
||||||
import { addMediaFile, convertPastedImage, getConfigBool, retrieveUrl as retrieveUrlBackend } from "@generated/backend";
|
import { addMediaFile, convertPastedImage, getConfigBool, retrieveUrl as retrieveUrlBackend } from "@generated/backend";
|
||||||
import { bridgeCommand } from "@tslib/bridgecommand";
|
|
||||||
import { shiftPressed } from "@tslib/keys";
|
import { shiftPressed } from "@tslib/keys";
|
||||||
import { pasteHTML } from "../old-editor-adapter";
|
import { pasteHTML } from "../old-editor-adapter";
|
||||||
|
|
||||||
|
@ -34,11 +33,8 @@ const audioSuffixes = [
|
||||||
];
|
];
|
||||||
const mediaSuffixes = [...imageSuffixes, ...audioSuffixes];
|
const mediaSuffixes = [...imageSuffixes, ...audioSuffixes];
|
||||||
|
|
||||||
function imageDataToUint8Array(data: ImageData): Uint8Array {
|
|
||||||
return typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
||||||
}
|
|
||||||
|
|
||||||
let isShiftPressed = false;
|
let isShiftPressed = false;
|
||||||
|
let lastInternalFieldText = "";
|
||||||
|
|
||||||
async function wantsExtendedPaste(event: MouseEvent | KeyboardEvent | null = null): Promise<boolean> {
|
async function wantsExtendedPaste(event: MouseEvent | KeyboardEvent | null = null): Promise<boolean> {
|
||||||
let stripHtml = (await getConfigBool({
|
let stripHtml = (await getConfigBool({
|
||||||
|
@ -70,6 +66,10 @@ function getText(data: DataTransfer): string {
|
||||||
return data.getData("text/plain") ?? "";
|
return data.getData("text/plain") ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getHtml(data: DataTransfer): string {
|
||||||
|
return data.getData("text/html") ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
const QIMAGE_FORMATS = [
|
const QIMAGE_FORMATS = [
|
||||||
"image/jpeg",
|
"image/jpeg",
|
||||||
"image/png",
|
"image/png",
|
||||||
|
@ -139,6 +139,10 @@ async function urlToLink(url: string): Promise<string> {
|
||||||
return filenameToLink(filename);
|
return filenameToLink(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function imageDataToUint8Array(data: ImageData): Uint8Array {
|
||||||
|
return typeof data === "string" ? new TextEncoder().encode(data) : data;
|
||||||
|
}
|
||||||
|
|
||||||
async function checksum(data: string | Uint8Array): Promise<string> {
|
async function checksum(data: string | Uint8Array): Promise<string> {
|
||||||
const bytes = imageDataToUint8Array(data);
|
const bytes = imageDataToUint8Array(data);
|
||||||
const hashBuffer = await crypto.subtle.digest("SHA-1", bytes);
|
const hashBuffer = await crypto.subtle.digest("SHA-1", bytes);
|
||||||
|
@ -267,11 +271,11 @@ async function processText(data: DataTransfer, extended: Promise<boolean>): Prom
|
||||||
async function processDataTransferEvent(
|
async function processDataTransferEvent(
|
||||||
event: ClipboardEvent | DragEvent,
|
event: ClipboardEvent | DragEvent,
|
||||||
extended: Promise<boolean>,
|
extended: Promise<boolean>,
|
||||||
): Promise<string | null> {
|
): Promise<{ html: string | null; internal: boolean }> {
|
||||||
const data = event instanceof ClipboardEvent ? event.clipboardData! : event.dataTransfer!;
|
const data = event instanceof ClipboardEvent ? event.clipboardData! : event.dataTransfer!;
|
||||||
const html = data.getData("text/html");
|
const html = getHtml(data);
|
||||||
if (html) {
|
if (html) {
|
||||||
return html;
|
return { html, internal: false };
|
||||||
}
|
}
|
||||||
const urls = getUrls(data);
|
const urls = getUrls(data);
|
||||||
let handlers: ((data: DataTransfer, extended: Promise<boolean>) => Promise<string | null>)[];
|
let handlers: ((data: DataTransfer, extended: Promise<boolean>) => Promise<string | null>)[];
|
||||||
|
@ -284,11 +288,11 @@ async function processDataTransferEvent(
|
||||||
for (const handler of handlers) {
|
for (const handler of handlers) {
|
||||||
const html = await handler(data, extended);
|
const html = await handler(data, extended);
|
||||||
if (html) {
|
if (html) {
|
||||||
return html;
|
return { html, internal: true };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return { html: null, internal: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runPreFilter(html: string, internal = false): Promise<string> {
|
async function runPreFilter(html: string, internal = false): Promise<string> {
|
||||||
|
@ -321,24 +325,27 @@ async function runPreFilter(html: string, internal = false): Promise<string> {
|
||||||
return template.innerHTML;
|
return template.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handlePaste(event: ClipboardEvent) {
|
async function handlePasteOrDrop(event: ClipboardEvent | DragEvent) {
|
||||||
// bridgeCommand("paste");
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let html = await processDataTransferEvent(event, wantsExtendedPaste());
|
let html: string | null = lastInternalFieldText;
|
||||||
|
let internal = !!lastInternalFieldText;
|
||||||
|
const extended = wantsExtendedPaste(event instanceof ClipboardEvent ? null : event);
|
||||||
|
if (!html) {
|
||||||
|
// `extended` is passed as a promise because the event's data is apparently cleared if we wait here before calling getData()
|
||||||
|
({ html, internal } = await processDataTransferEvent(event, extended));
|
||||||
|
}
|
||||||
if (html) {
|
if (html) {
|
||||||
html = await runPreFilter(html);
|
html = await runPreFilter(html, internal);
|
||||||
pasteHTML(html, false, false);
|
pasteHTML(html, internal, await extended);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function handlePaste(event: ClipboardEvent) {
|
||||||
|
await handlePasteOrDrop(event);
|
||||||
|
}
|
||||||
|
|
||||||
export async function handleDrop(event: DragEvent) {
|
export async function handleDrop(event: DragEvent) {
|
||||||
event.preventDefault();
|
await handlePasteOrDrop(event);
|
||||||
// `extended` is passed as a promise because the event's data is apparently cleared if we wait here before calling getData()
|
|
||||||
let html = await processDataTransferEvent(event, wantsExtendedPaste(event));
|
|
||||||
if (html) {
|
|
||||||
html = await runPreFilter(html);
|
|
||||||
pasteHTML(html, false, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleDragover(event: DragEvent) {
|
export async function handleDragover(event: DragEvent) {
|
||||||
|
@ -349,6 +356,6 @@ export async function handleKeydown(event: KeyboardEvent) {
|
||||||
isShiftPressed = shiftPressed(event);
|
isShiftPressed = shiftPressed(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleCutOrCopy() {
|
export function handleCutOrCopy(event: ClipboardEvent) {
|
||||||
bridgeCommand("cutOrCopy");
|
lastInternalFieldText = getHtml(event.clipboardData!);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue