mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 12:55:00 +00:00
chore: enchance copy link action (#8797)
What's Changed * enhance copy link action * detect compatibility * fall back to `document.execCommand`
This commit is contained in:
49
packages/frontend/core/src/utils/clipboard/fake.ts
Normal file
49
packages/frontend/core/src/utils/clipboard/fake.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
const createFakeElement = (text: string) => {
|
||||
const isRTL = document.documentElement.getAttribute('dir') === 'rtl';
|
||||
const fakeElement = document.createElement('textarea');
|
||||
// Prevent zooming on iOS
|
||||
fakeElement.style.fontSize = '12pt';
|
||||
// Reset box model
|
||||
fakeElement.style.border = '0';
|
||||
fakeElement.style.padding = '0';
|
||||
fakeElement.style.margin = '0';
|
||||
// Move element out of screen horizontally
|
||||
fakeElement.style.position = 'absolute';
|
||||
fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px';
|
||||
// Move element to the same position vertically
|
||||
const yPosition = window.pageYOffset || document.documentElement.scrollTop;
|
||||
fakeElement.style.top = `${yPosition}px`;
|
||||
|
||||
fakeElement.setAttribute('readonly', '');
|
||||
fakeElement.value = text;
|
||||
|
||||
return fakeElement;
|
||||
};
|
||||
|
||||
function command(type: string) {
|
||||
try {
|
||||
return document.execCommand(type);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const fakeCopyAction = (text: string, container = document.body) => {
|
||||
let success = false;
|
||||
|
||||
const fakeElement = createFakeElement(text);
|
||||
container.append(fakeElement);
|
||||
|
||||
try {
|
||||
fakeElement.select();
|
||||
fakeElement.setSelectionRange(0, fakeElement.value.length);
|
||||
success = command('copy');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
fakeElement.remove();
|
||||
|
||||
return success;
|
||||
};
|
||||
54
packages/frontend/core/src/utils/clipboard/index.ts
Normal file
54
packages/frontend/core/src/utils/clipboard/index.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { type Clipboard as BlockStdScopeClipboard } from '@blocksuite/affine/block-std';
|
||||
|
||||
import { fakeCopyAction } from './fake';
|
||||
|
||||
const clipboardWriteIsSupported =
|
||||
'clipboard' in navigator && 'write' in navigator.clipboard;
|
||||
|
||||
const clipboardWriteTextIsSupported =
|
||||
'clipboard' in navigator && 'writeText' in navigator.clipboard;
|
||||
|
||||
export const copyTextToClipboard = async (text: string) => {
|
||||
// 1. try using Async API first, works on HTTPS domain
|
||||
if (clipboardWriteTextIsSupported) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. try using `document.execCommand`
|
||||
// https://github.com/zenorocha/clipboard.js/blob/master/src/actions/copy.js
|
||||
return fakeCopyAction(text);
|
||||
};
|
||||
|
||||
export const copyLinkToBlockStdScopeClipboard = async (
|
||||
text: string,
|
||||
clipboard?: BlockStdScopeClipboard
|
||||
) => {
|
||||
let success = false;
|
||||
|
||||
if (!clipboard) return success;
|
||||
|
||||
if (clipboardWriteIsSupported) {
|
||||
try {
|
||||
await clipboard.writeToClipboard(items => {
|
||||
items['text/plain'] = text;
|
||||
// wrap a link
|
||||
items['text/html'] = `<a href="${text}">${text}</a>`;
|
||||
return items;
|
||||
});
|
||||
success = true;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
success = await copyTextToClipboard(text);
|
||||
}
|
||||
|
||||
return success;
|
||||
};
|
||||
Reference in New Issue
Block a user