toolbar family keyed (57 -> 33)
Toolbar, ActionButtons, SelectionActions and DefaultActions. Almost every string here reused an existing files.menu.* key from the last two commits rather than adding a duplicate — cut/copy/paste/download/delete/newFolder/uploadFiles/ uploadFolder/hideHiddenFiles were all already there. Three new: gitClone, searchFiles, clearSelection, refresh, selected. The clone-URL placeholder here is the same hint as NewEntryDialog's, reused rather than restated with different example names (user/repo vs owner/repo) — one key per meaning, not per occurrence. The "N selected" count splits the number and the word across two spans (the word hidden on mobile); only the word needed a key, so files.menu.selected is standalone prose rather than an interpolated frame.
This commit is contained in:
+3
-1
@@ -1,5 +1,6 @@
|
|||||||
import { RefreshCw } from 'lucide-react';
|
import { RefreshCw } from 'lucide-react';
|
||||||
import type { UseFileBrowserAppType } from '../../useFileBrowserApp';
|
import type { UseFileBrowserAppType } from '../../useFileBrowserApp';
|
||||||
|
import { useTranslation } from '../../../../../locales';
|
||||||
import { SelectionActions } from './SelectionActions';
|
import { SelectionActions } from './SelectionActions';
|
||||||
import { DefaultActions } from './DefaultActions';
|
import { DefaultActions } from './DefaultActions';
|
||||||
|
|
||||||
@@ -8,13 +9,14 @@ type ActionButtonsProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const ActionButtons = ({ fileBrowserManager }: ActionButtonsProps) => {
|
export const ActionButtons = ({ fileBrowserManager }: ActionButtonsProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { refresh, selected } = fileBrowserManager;
|
const { refresh, selected } = fileBrowserManager;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<button
|
<button
|
||||||
onClick={refresh}
|
onClick={refresh}
|
||||||
title="Refresh"
|
title={t('files.menu.refresh')}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<RefreshCw className="h-4 w-4" />
|
<RefreshCw className="h-4 w-4" />
|
||||||
|
|||||||
+6
-4
@@ -1,12 +1,14 @@
|
|||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import { FolderPlus, Upload, FolderUp, ClipboardPaste } from 'lucide-react';
|
import { FolderPlus, Upload, FolderUp, ClipboardPaste } from 'lucide-react';
|
||||||
import type { UseFileBrowserAppType } from '../../useFileBrowserApp';
|
import type { UseFileBrowserAppType } from '../../useFileBrowserApp';
|
||||||
|
import { useTranslation } from '../../../../../locales';
|
||||||
|
|
||||||
type DefaultActionsProps = {
|
type DefaultActionsProps = {
|
||||||
fileBrowserManager: UseFileBrowserAppType;
|
fileBrowserManager: UseFileBrowserAppType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DefaultActions = ({ fileBrowserManager }: DefaultActionsProps) => {
|
export const DefaultActions = ({ fileBrowserManager }: DefaultActionsProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { setNewEntry, handleUpload, clipboard, handlePaste } = fileBrowserManager;
|
const { setNewEntry, handleUpload, clipboard, handlePaste } = fileBrowserManager;
|
||||||
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
||||||
const folderInputRef = useRef<HTMLInputElement | null>(null);
|
const folderInputRef = useRef<HTMLInputElement | null>(null);
|
||||||
@@ -22,7 +24,7 @@ export const DefaultActions = ({ fileBrowserManager }: DefaultActionsProps) => {
|
|||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
onClick={() => setNewEntry('folder')}
|
onClick={() => setNewEntry('folder')}
|
||||||
title="New folder"
|
title={t('files.menu.newFolder')}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<FolderPlus className="h-4 w-4" />
|
<FolderPlus className="h-4 w-4" />
|
||||||
@@ -30,7 +32,7 @@ export const DefaultActions = ({ fileBrowserManager }: DefaultActionsProps) => {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => fileInputRef.current?.click()}
|
onClick={() => fileInputRef.current?.click()}
|
||||||
title="Upload files"
|
title={t('files.menu.uploadFiles')}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<Upload className="h-4 w-4" />
|
<Upload className="h-4 w-4" />
|
||||||
@@ -39,7 +41,7 @@ export const DefaultActions = ({ fileBrowserManager }: DefaultActionsProps) => {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => folderInputRef.current?.click()}
|
onClick={() => folderInputRef.current?.click()}
|
||||||
title="Upload folder"
|
title={t('files.menu.uploadFolder')}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<FolderUp className="h-4 w-4" />
|
<FolderUp className="h-4 w-4" />
|
||||||
@@ -57,7 +59,7 @@ export const DefaultActions = ({ fileBrowserManager }: DefaultActionsProps) => {
|
|||||||
{clipboard !== null && (
|
{clipboard !== null && (
|
||||||
<button
|
<button
|
||||||
onClick={handlePaste}
|
onClick={handlePaste}
|
||||||
title="Paste"
|
title={t('files.menu.paste')}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<ClipboardPaste className="h-4 w-4" />
|
<ClipboardPaste className="h-4 w-4" />
|
||||||
|
|||||||
+9
-7
@@ -1,11 +1,13 @@
|
|||||||
import { Scissors, Copy, ClipboardPaste, Download, Trash2, X } from 'lucide-react';
|
import { Scissors, Copy, ClipboardPaste, Download, Trash2, X } from 'lucide-react';
|
||||||
import type { UseFileBrowserAppType } from '../../useFileBrowserApp';
|
import type { UseFileBrowserAppType } from '../../useFileBrowserApp';
|
||||||
|
import { useTranslation } from '../../../../../locales';
|
||||||
|
|
||||||
type SelectionActionsProps = {
|
type SelectionActionsProps = {
|
||||||
fileBrowserManager: UseFileBrowserAppType;
|
fileBrowserManager: UseFileBrowserAppType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SelectionActions = ({ fileBrowserManager }: SelectionActionsProps) => {
|
export const SelectionActions = ({ fileBrowserManager }: SelectionActionsProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const {
|
const {
|
||||||
selected,
|
selected,
|
||||||
clipboard,
|
clipboard,
|
||||||
@@ -21,18 +23,18 @@ export const SelectionActions = ({ fileBrowserManager }: SelectionActionsProps)
|
|||||||
<>
|
<>
|
||||||
<span className="text-sm font-medium text-duck-dark/70 mr-1">
|
<span className="text-sm font-medium text-duck-dark/70 mr-1">
|
||||||
{selected.size}
|
{selected.size}
|
||||||
<span className="hidden md:inline"> selected</span>
|
<span className="hidden md:inline"> {t('files.menu.selected')}</span>
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
onClick={handleCut}
|
onClick={handleCut}
|
||||||
title="Cut"
|
title={t('files.menu.cut')}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<Scissors className="h-4 w-4" />
|
<Scissors className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleCopy}
|
onClick={handleCopy}
|
||||||
title="Copy"
|
title={t('files.menu.copy')}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<Copy className="h-4 w-4" />
|
<Copy className="h-4 w-4" />
|
||||||
@@ -40,7 +42,7 @@ export const SelectionActions = ({ fileBrowserManager }: SelectionActionsProps)
|
|||||||
{clipboard !== null && (
|
{clipboard !== null && (
|
||||||
<button
|
<button
|
||||||
onClick={handlePaste}
|
onClick={handlePaste}
|
||||||
title="Paste"
|
title={t('files.menu.paste')}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<ClipboardPaste className="h-4 w-4" />
|
<ClipboardPaste className="h-4 w-4" />
|
||||||
@@ -48,21 +50,21 @@ export const SelectionActions = ({ fileBrowserManager }: SelectionActionsProps)
|
|||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={handleDownloadSelected}
|
onClick={handleDownloadSelected}
|
||||||
title="Download"
|
title={t('files.menu.download')}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<Download className="h-4 w-4" />
|
<Download className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleDeleteSelected}
|
onClick={handleDeleteSelected}
|
||||||
title="Delete"
|
title={t('files.menu.delete')}
|
||||||
className="p-1.5 rounded-md text-destructive hover:bg-destructive cursor-pointer transition-colors"
|
className="p-1.5 rounded-md text-destructive hover:bg-destructive cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<Trash2 className="h-4 w-4" />
|
<Trash2 className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setSelected(new Set())}
|
onClick={() => setSelected(new Set())}
|
||||||
title="Clear selection"
|
title={t('files.menu.clearSelection')}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<X className="h-4 w-4" />
|
<X className="h-4 w-4" />
|
||||||
|
|||||||
+10
-8
@@ -1,5 +1,6 @@
|
|||||||
import { Loader2, LayoutGrid, List, Search, X, Check, GitBranch, Eye, EyeOff, Download, Mic } from 'lucide-react';
|
import { Loader2, LayoutGrid, List, Search, X, Check, GitBranch, Eye, EyeOff, Download, Mic } from 'lucide-react';
|
||||||
import type { UseFileBrowserAppType } from '../../useFileBrowserApp';
|
import type { UseFileBrowserAppType } from '../../useFileBrowserApp';
|
||||||
|
import { useTranslation } from '../../../../../locales';
|
||||||
import { ActionButtons } from './ActionButtons';
|
import { ActionButtons } from './ActionButtons';
|
||||||
|
|
||||||
type ToolbarProps = {
|
type ToolbarProps = {
|
||||||
@@ -7,6 +8,7 @@ type ToolbarProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const Toolbar = ({ fileBrowserManager }: ToolbarProps) => {
|
export const Toolbar = ({ fileBrowserManager }: ToolbarProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const {
|
const {
|
||||||
showCloneInput,
|
showCloneInput,
|
||||||
setShowCloneInput,
|
setShowCloneInput,
|
||||||
@@ -41,7 +43,7 @@ export const Toolbar = ({ fileBrowserManager }: ToolbarProps) => {
|
|||||||
autoFocus
|
autoFocus
|
||||||
value={cloneUrl}
|
value={cloneUrl}
|
||||||
onChange={(ev) => setCloneUrl(ev.target.value)}
|
onChange={(ev) => setCloneUrl(ev.target.value)}
|
||||||
placeholder="https://github.com/user/repo.git"
|
placeholder={t('newEntry.clone.placeholder')}
|
||||||
className="h-8 w-40 md:w-64 text-sm rounded-md border border-duck-dark/20 bg-background/60 text-duck-dark placeholder:text-duck-dark/40 outline-none focus:border-duck-teal/50 px-2"
|
className="h-8 w-40 md:w-64 text-sm rounded-md border border-duck-dark/20 bg-background/60 text-duck-dark placeholder:text-duck-dark/40 outline-none focus:border-duck-teal/50 px-2"
|
||||||
disabled={cloning}
|
disabled={cloning}
|
||||||
onKeyDown={(ev) => {
|
onKeyDown={(ev) => {
|
||||||
@@ -55,7 +57,7 @@ export const Toolbar = ({ fileBrowserManager }: ToolbarProps) => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
disabled={cloning}
|
disabled={cloning}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors disabled:opacity-40"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors disabled:opacity-40"
|
||||||
title="Clone"
|
title={t('files.menu.cloneRepository')}
|
||||||
>
|
>
|
||||||
{cloning ? <Loader2 className="h-4 w-4 animate-spin" /> : <Check className="h-4 w-4" />}
|
{cloning ? <Loader2 className="h-4 w-4 animate-spin" /> : <Check className="h-4 w-4" />}
|
||||||
</button>
|
</button>
|
||||||
@@ -67,7 +69,7 @@ export const Toolbar = ({ fileBrowserManager }: ToolbarProps) => {
|
|||||||
setCloneUrl('');
|
setCloneUrl('');
|
||||||
}}
|
}}
|
||||||
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors disabled:opacity-40"
|
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors disabled:opacity-40"
|
||||||
title="Cancel"
|
title={t('newEntry.cancel')}
|
||||||
>
|
>
|
||||||
<X className="h-4 w-4" />
|
<X className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
@@ -76,21 +78,21 @@ export const Toolbar = ({ fileBrowserManager }: ToolbarProps) => {
|
|||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowVideoDownload(true)}
|
onClick={() => setShowVideoDownload(true)}
|
||||||
title="Download video"
|
title={t('files.menu.downloadVideo')}
|
||||||
className="hidden md:block p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="hidden md:block p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<Download className="h-4 w-4" />
|
<Download className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowDictate(true)}
|
onClick={() => setShowDictate(true)}
|
||||||
title="Dictate"
|
title={t('files.menu.dictate')}
|
||||||
className="hidden md:block p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="hidden md:block p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<Mic className="h-4 w-4" />
|
<Mic className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowCloneInput(true)}
|
onClick={() => setShowCloneInput(true)}
|
||||||
title="Git clone"
|
title={t('files.menu.gitClone')}
|
||||||
className="hidden md:block p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
className="hidden md:block p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<GitBranch className="h-4 w-4" />
|
<GitBranch className="h-4 w-4" />
|
||||||
@@ -109,7 +111,7 @@ export const Toolbar = ({ fileBrowserManager }: ToolbarProps) => {
|
|||||||
searchInputRef.current?.blur();
|
searchInputRef.current?.blur();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
placeholder="Search files..."
|
placeholder={t('files.menu.searchFiles')}
|
||||||
className="h-8 w-28 focus:w-40 md:w-40 md:focus:w-56 transition-all pl-8 pr-7 text-base md:text-sm rounded-md border border-duck-dark/20 bg-background/60 text-duck-dark placeholder:text-duck-dark/40 outline-none focus:border-duck-teal/50"
|
className="h-8 w-28 focus:w-40 md:w-40 md:focus:w-56 transition-all pl-8 pr-7 text-base md:text-sm rounded-md border border-duck-dark/20 bg-background/60 text-duck-dark placeholder:text-duck-dark/40 outline-none focus:border-duck-teal/50"
|
||||||
/>
|
/>
|
||||||
{searchQuery && (
|
{searchQuery && (
|
||||||
@@ -124,7 +126,7 @@ export const Toolbar = ({ fileBrowserManager }: ToolbarProps) => {
|
|||||||
<button
|
<button
|
||||||
onClick={() => setShowHidden((v) => !v)}
|
onClick={() => setShowHidden((v) => !v)}
|
||||||
className={`hidden md:block p-1.5 rounded-md cursor-pointer transition-colors ${showHidden ? 'bg-duck-teal text-duck-yellow' : 'text-duck-teal hover:bg-duck-dark/5'}`}
|
className={`hidden md:block p-1.5 rounded-md cursor-pointer transition-colors ${showHidden ? 'bg-duck-teal text-duck-yellow' : 'text-duck-teal hover:bg-duck-dark/5'}`}
|
||||||
title={showHidden ? 'Hide hidden files' : 'Show hidden files'}
|
title={showHidden ? t('files.menu.hideHiddenFiles') : t('files.menu.showHiddenFiles')}
|
||||||
>
|
>
|
||||||
{showHidden ? <Eye className="h-4 w-4" /> : <EyeOff className="h-4 w-4" />}
|
{showHidden ? <Eye className="h-4 w-4" /> : <EyeOff className="h-4 w-4" />}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -521,7 +521,12 @@
|
|||||||
"unpin": "Unpin",
|
"unpin": "Unpin",
|
||||||
"pin": "Pin",
|
"pin": "Pin",
|
||||||
"chat": "Chat...",
|
"chat": "Chat...",
|
||||||
"delete": "Delete"
|
"delete": "Delete",
|
||||||
|
"gitClone": "Git clone",
|
||||||
|
"searchFiles": "Search files...",
|
||||||
|
"clearSelection": "Clear selection",
|
||||||
|
"selected": "selected",
|
||||||
|
"refresh": "Refresh"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"taskRunner": {
|
"taskRunner": {
|
||||||
|
|||||||
@@ -521,7 +521,12 @@
|
|||||||
"unpin": "Remover fixação",
|
"unpin": "Remover fixação",
|
||||||
"pin": "Fixar",
|
"pin": "Fixar",
|
||||||
"chat": "Chat...",
|
"chat": "Chat...",
|
||||||
"delete": "Eliminar"
|
"delete": "Eliminar",
|
||||||
|
"gitClone": "Clonar via Git",
|
||||||
|
"searchFiles": "Pesquisar ficheiros...",
|
||||||
|
"clearSelection": "Limpar seleção",
|
||||||
|
"selected": "selecionados",
|
||||||
|
"refresh": "Atualizar"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"taskRunner": {
|
"taskRunner": {
|
||||||
|
|||||||
Reference in New Issue
Block a user