Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Copy to clipboard #613

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions resources/icons/copy.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/frontend/containers/ContentView/menu-items.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,14 @@ export const SlideFileViewerMenuItems = observer(({ file }: { file: ClientFile }
uiStore.openPreviewWindow();
};

const handleCopyToClipboard = () => {
uiStore.selectFile(file, true);
uiStore.copyToClipboard();
};

return (
<>
<MenuItem onClick={handleCopyToClipboard} text="Copy" icon={IconSet.COPY} />
<MenuItem
onClick={handlePreviewWindow}
text="Open In Preview Window"
Expand Down
34 changes: 34 additions & 0 deletions src/frontend/stores/UiStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { action, computed, makeObservable, observable } from 'mobx';

import { maxNumberOfExternalFilesBeforeWarning } from 'common/config';
import { clamp, notEmpty } from 'common/core';
import { encodeFilePath } from 'common/fs';
import { ID } from '../../api/id';
import { SearchCriteria } from '../../api/search-criteria';
import { RendererMessenger } from '../../ipc/renderer';
Expand Down Expand Up @@ -318,6 +319,39 @@ class UiStore {
}
}

@action.bound async copyToClipboard(): Promise<void> {
if (this.fileSelection.size === 0) {
return;
}

const file = Array.from(this.fileSelection)[0];
if (file.isBroken) {
return;
}

try {
const src = await this.rootStore.imageLoader.getImageSrc(file);
if (src !== undefined) {
const image = new Image();
image.src = encodeFilePath(src);
const canvas = new OffscreenCanvas(image.width, image.height);
canvas.width = image.width;
canvas.height = image.height;
const ctx2D = canvas.getContext('2d');
if (!ctx2D) {
throw new Error('Context2D not available!');
}
ctx2D.drawImage(image, 0, 0);
const blob = await canvas.convertToBlob({ type: 'image/png' });
navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })]);
} else {
throw new Error('Failed to get image data.');
}
} catch (e) {
console.error('Could not copy image to clipboard', e);
}
}

@action.bound openExternal(warnIfTooManyFiles: boolean = true): void {
// Don't open when no files have been selected
if (this.fileSelection.size === 0) {
Expand Down
2 changes: 2 additions & 0 deletions widgets/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import CHROME_DEVTOOLS from 'resources/icons/chrome-devtools.svg';
import CLEAR_DATABASE from 'resources/icons/clear-database.svg';
import CLOSE from 'resources/icons/close.svg';
import COLOR from 'resources/icons/color.svg';
import COPY from 'resources/icons/copy.svg';
import CHROME_CLOSE from 'resources/icons/chrome-close.svg';
import CHROME_MAXIMIZE from 'resources/icons/chrome-maximize.svg';
import CHROME_MINIMIZE from 'resources/icons/chrome-minimize.svg';
Expand Down Expand Up @@ -130,6 +131,7 @@ const IconSet = {
CLEAR_DATABASE: toSvg(CLEAR_DATABASE),
CLOSE: toSvg(CLOSE),
COLOR: toSvg(COLOR),
COPY: toSvg(COPY),
CHROME_CLOSE: toSvg(CHROME_CLOSE),
CHROME_MAXIMIZE: toSvg(CHROME_MAXIMIZE),
CHROME_MINIMIZE: toSvg(CHROME_MINIMIZE),
Expand Down
Loading