2023-08-14 11:32:30 +02:00

134 lines
3.6 KiB
TypeScript

import type { ApiMessage } from '../../../../api/types';
import { ApiMediaFormat } from '../../../../api/types';
import * as mediaLoader from '../../../../util/mediaLoader';
import {
getMessageContact,
getMessageMediaHash,
getMessagePhoto,
getMessageText,
getMessageTextWithSpoilers,
getMessageWebPagePhoto,
getMessageWebPageVideo,
hasMessageLocalBlobUrl,
} from '../../../../global/helpers';
import {
CLIPBOARD_ITEM_SUPPORTED,
copyHtmlToClipboard,
copyImageToClipboard,
copyTextToClipboard,
} from '../../../../util/clipboard';
import getMessageIdsForSelectedText from '../../../../util/getMessageIdsForSelectedText';
import { renderMessageText } from '../../../common/helpers/renderMessageText';
type ICopyOptions = {
label: string;
icon: string;
handler: () => void;
}[];
export function getMessageCopyOptions(
message: ApiMessage,
href?: string,
canCopy?: boolean,
afterEffect?: () => void,
onCopyLink?: () => void,
onCopyMessages?: (messageIds: number[]) => void,
onCopyNumber?: () => void,
): ICopyOptions {
const options: ICopyOptions = [];
const text = getMessageText(message);
const photo = getMessagePhoto(message)
|| (!getMessageWebPageVideo(message) ? getMessageWebPagePhoto(message) : undefined);
const contact = getMessageContact(message);
const mediaHash = getMessageMediaHash(message, 'inline');
const canImageBeCopied = canCopy && photo && (mediaHash || hasMessageLocalBlobUrl(message))
&& CLIPBOARD_ITEM_SUPPORTED;
const selection = window.getSelection();
if (canImageBeCopied) {
options.push({
label: 'lng_context_copy_image',
icon: 'copy-media',
handler: () => {
Promise.resolve(mediaHash ? mediaLoader.fetch(mediaHash, ApiMediaFormat.BlobUrl) : photo!.blobUrl)
.then(copyImageToClipboard);
afterEffect?.();
},
});
}
if (canCopy && href) {
options.push({
label: 'lng_context_copy_link',
icon: 'copy',
handler: () => {
copyTextToClipboard(href);
afterEffect?.();
},
});
} else if (canCopy && text) {
// Detect if the user has selection in the current message
const hasSelection = Boolean((
selection?.anchorNode?.parentNode
&& (selection.anchorNode.parentNode as HTMLElement).closest('.Message .content-inner')
&& selection.toString().replace(/(?:\r\n|\r|\n)/g, '') !== ''
));
options.push({
label: getCopyLabel(hasSelection),
icon: 'copy',
handler: () => {
const messageIds = getMessageIdsForSelectedText();
if (messageIds?.length && onCopyMessages) {
onCopyMessages(messageIds);
} else if (hasSelection) {
document.execCommand('copy');
} else {
const clipboardText = renderMessageText(
message, undefined, undefined, undefined, undefined, undefined, true,
);
if (clipboardText) copyHtmlToClipboard(clipboardText.join(''), getMessageTextWithSpoilers(message)!);
}
afterEffect?.();
},
});
}
if (onCopyLink) {
options.push({
label: 'lng_context_copy_message_link',
icon: 'link',
handler: () => {
onCopyLink();
afterEffect?.();
},
});
}
if (contact && onCopyNumber) {
options.push({
label: 'lng_profile_copy_phone',
icon: 'copy',
handler: () => {
onCopyNumber();
afterEffect?.();
},
});
}
return options;
}
function getCopyLabel(hasSelection: boolean): string {
if (hasSelection) {
return 'lng_context_copy_selected';
}
return 'lng_context_copy_text';
}