Skip to content

Commit 9054231

Browse files
authored
Merge pull request CyberTimon#1424 from magnusrodseth/feat/copy-image-path
Add Cmd/Ctrl+L shortcut to copy image paths to the clipboard
2 parents 6211602 + 1a95b39 commit 9054231

14 files changed

Lines changed: 56 additions & 1 deletion

File tree

src/hooks/useKeyboardShortcuts.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { useEffect, useRef } from 'react';
1+
import { useCallback, useEffect, useRef } from 'react';
2+
import { toast } from 'react-toastify';
23
import { ImageFile, Panel, ExifOverlay } from '../components/ui/AppProperties';
34
import { KEYBIND_DEFINITIONS, normalizeCombo } from '../utils/keyboardUtils';
45
import { useEditorStore } from '../store/useEditorStore';
@@ -36,6 +37,19 @@ export const useKeyboardShortcuts = ({
3637
sortedListRef.current = sortedImageList;
3738
}, [sortedImageList]);
3839

40+
const handleCopyImagePaths = useCallback(async (paths: Array<string>) => {
41+
const physicalPaths = [...new Set(paths.map((path) => path.split('?vc=')[0]))];
42+
if (physicalPaths.length === 0) {
43+
return;
44+
}
45+
try {
46+
await navigator.clipboard.writeText(physicalPaths.join('\n'));
47+
} catch (err) {
48+
console.error('Failed to copy image path to clipboard', err);
49+
toast.error(`Failed to copy path: ${err}`);
50+
}
51+
}, []);
52+
3953
useEffect(() => {
4054
const getStoreState = () => ({
4155
editor: useEditorStore.getState(),
@@ -56,6 +70,21 @@ export const useKeyboardShortcuts = ({
5670
}
5771
}
5872

73+
const getImagePathsForCopy = (s: any): Array<string> => {
74+
if (s.editor.selectedImage) {
75+
return [s.editor.selectedImage.path];
76+
}
77+
const { libraryActivePath, multiSelectedPaths } = s.library;
78+
if (multiSelectedPaths.length > 0) {
79+
const listOrder = new Map(sortedListRef.current.map((image: ImageFile, index: number) => [image.path, index]));
80+
return [...multiSelectedPaths].sort(
81+
(a: string, b: string) =>
82+
(listOrder.get(a) ?? Number.MAX_SAFE_INTEGER) - (listOrder.get(b) ?? Number.MAX_SAFE_INTEGER),
83+
);
84+
}
85+
return libraryActivePath ? [libraryActivePath] : [];
86+
};
87+
5988
const actions: Record<string, any> = {
6089
open_image: {
6190
shouldFire: (s: any) => !s.editor.selectedImage && s.library.libraryActivePath !== null,
@@ -78,6 +107,13 @@ export const useKeyboardShortcuts = ({
78107
handlePasteAdjustments();
79108
},
80109
},
110+
copy_image_path: {
111+
shouldFire: (s: any) => getImagePathsForCopy(s).length > 0,
112+
execute: (e: any, s: any) => {
113+
e.preventDefault();
114+
handleCopyImagePaths(getImagePathsForCopy(s));
115+
},
116+
},
81117
copy_files: {
82118
shouldFire: (s: any) => s.library.multiSelectedPaths.length > 0,
83119
execute: (e: any, s: any) => {
@@ -590,6 +626,7 @@ export const useKeyboardShortcuts = ({
590626
handleZoomChange,
591627
handleRotate,
592628
handleCopyAdjustments,
629+
handleCopyImagePaths,
593630
handlePasteAdjustments,
594631
handleRate,
595632
handleSetColorLabel,

src/i18n/locales/de.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,6 +1496,7 @@
14961496
"color_label_yellow": "Farbmarkierung: Gelb",
14971497
"copy_adjustments": "Ausgewählte Anpassungen kopieren",
14981498
"copy_files": "Ausgewählte Datei(en) kopieren",
1499+
"copy_image_path": "Pfad des/der ausgewählten Bilder kopieren",
14991500
"cycle_zoom": "Zoom durchwechseln (Einpassen, 2x Einpassen, 100%)",
15001501
"delete_selected": "Ausgewählte Datei(en) löschen",
15011502
"focus_search": "Suchfeld fokussieren",

src/i18n/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,6 +1496,7 @@
14961496
"color_label_yellow": "Color label: Yellow",
14971497
"copy_adjustments": "Copy selected adjustments",
14981498
"copy_files": "Copy selected file(s)",
1499+
"copy_image_path": "Copy path of selected image(s)",
14991500
"cycle_zoom": "Cycle zoom (Fit, 2x Fit, 100%)",
15001501
"delete_selected": "Delete selected file(s)",
15011502
"focus_search": "Focus search field",

src/i18n/locales/es.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,6 +1529,7 @@
15291529
"color_label_yellow": "Etiqueta de color: Amarillo",
15301530
"copy_adjustments": "Copiar ajustes seleccionados",
15311531
"copy_files": "Copiar archivo(s) seleccionado(s)",
1532+
"copy_image_path": "Copiar la ruta de la(s) imagen(es) seleccionada(s)",
15321533
"cycle_zoom": "Alternar zoom (Ajustar, 2x Ajustar, 100%)",
15331534
"delete_selected": "Eliminar archivo(s) seleccionado(s)",
15341535
"focus_search": "Enfocar el campo de búsqueda",

src/i18n/locales/fr.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,6 +1529,7 @@
15291529
"color_label_yellow": "Étiquette de couleur : Jaune",
15301530
"copy_adjustments": "Copier les ajustements sélectionnés",
15311531
"copy_files": "Copier le(s) fichier(s) sélectionné(s)",
1532+
"copy_image_path": "Copier le chemin de la ou des images sélectionnées",
15321533
"cycle_zoom": "Faire défiler le zoom (Ajuster, 2x Ajuster, 100%)",
15331534
"delete_selected": "Supprimer le(s) fichier(s) sélectionné(s)",
15341535
"focus_search": "Activer le champ de recherche",

src/i18n/locales/it.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,6 +1529,7 @@
15291529
"color_label_yellow": "Etichetta colore: Giallo",
15301530
"copy_adjustments": "Copia regolazioni selezionate",
15311531
"copy_files": "Copia file selezionati",
1532+
"copy_image_path": "Copia il percorso delle immagini selezionate",
15321533
"cycle_zoom": "Ruota zoom (Adatta, Adatta 2x, 100%)",
15331534
"delete_selected": "Elimina file selezionati",
15341535
"focus_search": "Attiva il campo di ricerca",

src/i18n/locales/ja.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,7 @@
14941494
"color_label_yellow": "カラーラベル: イエロー",
14951495
"copy_adjustments": "選択した補正設定をコピー",
14961496
"copy_files": "選択したファイルをコピー",
1497+
"copy_image_path": "選択した画像のパスをコピー",
14971498
"cycle_zoom": "ズームの切り替え (全体表示、2倍拡大、100%)",
14981499
"delete_selected": "選択したファイルを削除",
14991500
"focus_search": "検索フィールドにフォーカス",

src/i18n/locales/ko.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,7 @@
14941494
"color_label_yellow": "색상 레이블: 노랑",
14951495
"copy_adjustments": "선택한 조정값 복사",
14961496
"copy_files": "선택한 파일 복사",
1497+
"copy_image_path": "선택한 이미지의 경로 복사",
14971498
"cycle_zoom": "확대/축소 순환 (맞춤, 2배 맞춤, 100%)",
14981499
"delete_selected": "선택한 파일 삭제",
14991500
"focus_search": "검색창에 포커스",

src/i18n/locales/pl.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,6 +1562,7 @@
15621562
"color_label_yellow": "Etykieta koloru: Żółty",
15631563
"copy_adjustments": "Kopiuj wybrane ustawienia",
15641564
"copy_files": "Skopiuj wybrane pliki",
1565+
"copy_image_path": "Kopiuj ścieżkę wybranych zdjęć",
15651566
"cycle_zoom": "Przełącz przybliżenie (Dopasuj, 2x Dopasuj, 100%)",
15661567
"delete_selected": "Usuń wybrane pliki",
15671568
"focus_search": "Przejdź do pola wyszukiwania",

src/i18n/locales/pt.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,6 +1529,7 @@
15291529
"color_label_yellow": "Rótulo de cor: Amarelo",
15301530
"copy_adjustments": "Copiar ajustes selecionados",
15311531
"copy_files": "Copiar arquivo(s) selecionado(s)",
1532+
"copy_image_path": "Copiar o caminho da(s) imagem(ns) selecionada(s)",
15321533
"cycle_zoom": "Alternar zoom (Caber, 2x Caber, 100%)",
15331534
"delete_selected": "Excluir arquivo(s) selecionado(s)",
15341535
"focus_search": "Focar o campo de pesquisa",

0 commit comments

Comments
 (0)