Skip to content

Commit

Permalink
chore: enchance copy link action (#8797)
Browse files Browse the repository at this point in the history
What's Changed

* enhance copy link action
* detect compatibility
* fall back to `document.execCommand`
  • Loading branch information
fundon authored and pull[bot] committed Dec 26, 2024
1 parent 2ea2877 commit c62cc00
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from '@affine/core/components/hooks/affine/use-share-url';
import { getAffineCloudBaseUrl } from '@affine/core/modules/cloud/services/fetch';
import { EditorService } from '@affine/core/modules/editor';
import { copyLinkToBlockStdScopeClipboard } from '@affine/core/utils/clipboard';
import { I18n } from '@affine/i18n';
import { track } from '@affine/track';
import type {
Expand Down Expand Up @@ -63,18 +64,15 @@ function createCopyLinkToBlockMenuItem(
const type = model.flavour;
const page = editor.editorContainer$.value;

page?.host?.std.clipboard
.writeToClipboard(items => {
items['text/plain'] = str;
// wrap a link
items['text/html'] = `<a href="${str}">${str}</a>`;
return items;
})
.then(() => {
track.doc.editor.toolbar.copyBlockToLink({ type });
copyLinkToBlockStdScopeClipboard(str, page?.host?.std.clipboard)
.then(success => {
if (!success) return;

notify.success({ title: I18n['Copied link to clipboard']() });
})
.catch(console.error);

track.doc.editor.toolbar.copyBlockToLink({ type });
},
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from '@affine/core/components/hooks/affine/use-share-url';
import { getAffineCloudBaseUrl } from '@affine/core/modules/cloud/services/fetch';
import { EditorService } from '@affine/core/modules/editor';
import { copyLinkToBlockStdScopeClipboard } from '@affine/core/utils/clipboard';
import { I18n } from '@affine/i18n';
import { track } from '@affine/track';
import type {
Expand Down Expand Up @@ -77,7 +78,7 @@ function createCopyLinkToBlockMenuItem(
) {
return {
...item,
action: (ctx: MenuContext) => {
action: async (ctx: MenuContext) => {
const baseUrl = getAffineCloudBaseUrl();
if (!baseUrl) {
ctx.close();
Expand Down Expand Up @@ -114,18 +115,16 @@ function createCopyLinkToBlockMenuItem(
return;
}

ctx.std.clipboard
.writeToClipboard(items => {
items['text/plain'] = str;
// wrap a link
items['text/html'] = `<a href="${str}">${str}</a>`;
return items;
})
.then(() => {
track.doc.editor.toolbar.copyBlockToLink({ type });
notify.success({ title: I18n['Copied link to clipboard']() });
})
.catch(console.error);
const success = await copyLinkToBlockStdScopeClipboard(
str,
ctx.std.clipboard
);

if (success) {
notify.success({ title: I18n['Copied link to clipboard']() });
}

track.doc.editor.toolbar.copyBlockToLink({ type });

ctx.close();
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { notify } from '@affine/component';
import { getAffineCloudBaseUrl } from '@affine/core/modules/cloud/services/fetch';
import { toURLSearchParams } from '@affine/core/modules/navigation';
import { copyTextToClipboard } from '@affine/core/utils/clipboard';
import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { type EditorHost } from '@blocksuite/affine/block-std';
Expand Down Expand Up @@ -145,23 +146,18 @@ export const useSharingUrl = ({ workspaceId, pageId }: UseSharingUrl) => {
elementIds,
});
if (sharingUrl) {
navigator.clipboard
.writeText(sharingUrl)
.then(() => {
notify.success({
title: t['Copied link to clipboard'](),
});
copyTextToClipboard(sharingUrl)
.then(success => {
if (success) {
notify.success({ title: t['Copied link to clipboard']() });
}
})
.catch(err => {
console.error(err);
});
track.$.sharePanel.$.copyShareLink({
type,
});
track.$.sharePanel.$.copyShareLink({ type });
} else {
notify.error({
title: 'Network not available',
});
notify.error({ title: 'Network not available' });
}
},
[pageId, t, workspaceId]
Expand Down
49 changes: 49 additions & 0 deletions packages/frontend/core/src/utils/clipboard/fake.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 54 additions & 0 deletions packages/frontend/core/src/utils/clipboard/index.ts
Original file line number Diff line number Diff line change
@@ -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;
};

0 comments on commit c62cc00

Please sign in to comment.