mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
V2 File Editor Shortcuts (#4619)
# Description of Changes Add shortcut icons for Pin and Download, and rename Delete to Close for consistency with the rest of the tool.
This commit is contained in:
parent
2a29bda34f
commit
d714a1617f
@ -66,6 +66,8 @@
|
|||||||
"save": "Save",
|
"save": "Save",
|
||||||
"saveToBrowser": "Save to Browser",
|
"saveToBrowser": "Save to Browser",
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
|
"pin": "Pin",
|
||||||
|
"unpin": "Unpin",
|
||||||
"undoOperationTooltip": "Click to undo the last operation and restore the original files",
|
"undoOperationTooltip": "Click to undo the last operation and restore the original files",
|
||||||
"undo": "Undo",
|
"undo": "Undo",
|
||||||
"moreOptions": "More Options",
|
"moreOptions": "More Options",
|
||||||
|
|||||||
@ -34,9 +34,9 @@
|
|||||||
.header {
|
.header {
|
||||||
height: 2.25rem;
|
height: 2.25rem;
|
||||||
border-radius: 0.0625rem 0.0625rem 0 0;
|
border-radius: 0.0625rem 0.0625rem 0 0;
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: 44px 1fr 44px;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
background: var(--bg-toolbar);
|
background: var(--bg-toolbar);
|
||||||
@ -86,14 +86,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.headerIndex {
|
.headerIndex {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kebab {
|
.headerActions {
|
||||||
justify-self: end;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerIconButton {
|
||||||
color: #FFFFFF !important;
|
color: #FFFFFF !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,6 +225,11 @@
|
|||||||
color: rgba(0, 0, 0, 0.35);
|
color: rgba(0, 0, 0, 0.35);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pinned {
|
||||||
|
color: #FFC107 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Unsupported file indicator */
|
/* Unsupported file indicator */
|
||||||
.unsupportedPill {
|
.unsupportedPill {
|
||||||
margin-left: 1.75rem;
|
margin-left: 1.75rem;
|
||||||
|
|||||||
@ -288,7 +288,7 @@ const FileEditor = ({
|
|||||||
|
|
||||||
|
|
||||||
// File operations using context
|
// File operations using context
|
||||||
const handleDeleteFile = useCallback((fileId: FileId) => {
|
const handleCloseFile = useCallback((fileId: FileId) => {
|
||||||
const record = activeStirlingFileStubs.find(r => r.id === fileId);
|
const record = activeStirlingFileStubs.find(r => r.id === fileId);
|
||||||
const file = record ? selectors.getFile(record.id) : null;
|
const file = record ? selectors.getFile(record.id) : null;
|
||||||
if (record && file) {
|
if (record && file) {
|
||||||
@ -467,7 +467,7 @@ const FileEditor = ({
|
|||||||
selectedFiles={localSelectedIds}
|
selectedFiles={localSelectedIds}
|
||||||
selectionMode={selectionMode}
|
selectionMode={selectionMode}
|
||||||
onToggleFile={toggleFile}
|
onToggleFile={toggleFile}
|
||||||
onDeleteFile={handleDeleteFile}
|
onCloseFile={handleCloseFile}
|
||||||
onViewFile={handleViewFile}
|
onViewFile={handleViewFile}
|
||||||
_onSetStatus={showStatus}
|
_onSetStatus={showStatus}
|
||||||
onReorderFiles={handleReorderFiles}
|
onReorderFiles={handleReorderFiles}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import React, { useState, useCallback, useRef, useMemo, useEffect } from 'react';
|
import React, { useState, useCallback, useRef, useMemo, useEffect } from 'react';
|
||||||
import { Text, ActionIcon, CheckboxIndicator } from '@mantine/core';
|
import { Text, ActionIcon, CheckboxIndicator, Tooltip } from '@mantine/core';
|
||||||
import { alert } from '../toast';
|
import { alert } from '../toast';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
||||||
import DownloadOutlinedIcon from '@mui/icons-material/DownloadOutlined';
|
import DownloadOutlinedIcon from '@mui/icons-material/DownloadOutlined';
|
||||||
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
import UnarchiveIcon from '@mui/icons-material/Unarchive';
|
import UnarchiveIcon from '@mui/icons-material/Unarchive';
|
||||||
import PushPinIcon from '@mui/icons-material/PushPin';
|
import PushPinIcon from '@mui/icons-material/PushPin';
|
||||||
import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined';
|
import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined';
|
||||||
@ -29,7 +29,7 @@ interface FileEditorThumbnailProps {
|
|||||||
selectedFiles: FileId[];
|
selectedFiles: FileId[];
|
||||||
selectionMode: boolean;
|
selectionMode: boolean;
|
||||||
onToggleFile: (fileId: FileId) => void;
|
onToggleFile: (fileId: FileId) => void;
|
||||||
onDeleteFile: (fileId: FileId) => void;
|
onCloseFile: (fileId: FileId) => void;
|
||||||
onViewFile: (fileId: FileId) => void;
|
onViewFile: (fileId: FileId) => void;
|
||||||
_onSetStatus: (status: string) => void;
|
_onSetStatus: (status: string) => void;
|
||||||
onReorderFiles?: (sourceFileId: FileId, targetFileId: FileId, selectedFileIds: FileId[]) => void;
|
onReorderFiles?: (sourceFileId: FileId, targetFileId: FileId, selectedFileIds: FileId[]) => void;
|
||||||
@ -44,7 +44,7 @@ const FileEditorThumbnail = ({
|
|||||||
index,
|
index,
|
||||||
selectedFiles,
|
selectedFiles,
|
||||||
onToggleFile,
|
onToggleFile,
|
||||||
onDeleteFile,
|
onCloseFile,
|
||||||
_onSetStatus,
|
_onSetStatus,
|
||||||
onReorderFiles,
|
onReorderFiles,
|
||||||
onDownloadFile,
|
onDownloadFile,
|
||||||
@ -258,11 +258,52 @@ const FileEditorThumbnail = ({
|
|||||||
{index + 1}
|
{index + 1}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Action buttons group */}
|
||||||
|
<div className={styles.headerActions}>
|
||||||
|
{/* Pin/Unpin icon */}
|
||||||
|
<Tooltip label={isPinned ? t('unpin', 'Unpin') : t('pin', 'Pin')}>
|
||||||
|
<ActionIcon
|
||||||
|
aria-label={isPinned ? t('unpin', 'Unpin') : t('pin', 'Pin')}
|
||||||
|
variant="subtle"
|
||||||
|
className={isPinned ? styles.pinned : styles.headerIconButton}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (actualFile) {
|
||||||
|
if (isPinned) {
|
||||||
|
unpinFile(actualFile);
|
||||||
|
alert({ alertType: 'neutral', title: `Unpinned ${file.name}`, expandable: false, durationMs: 3000 });
|
||||||
|
} else {
|
||||||
|
pinFile(actualFile);
|
||||||
|
alert({ alertType: 'success', title: `Pinned ${file.name}`, expandable: false, durationMs: 3000 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isPinned ? <PushPinIcon fontSize="small" /> : <PushPinOutlinedIcon fontSize="small" />}
|
||||||
|
</ActionIcon>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
{/* Download icon */}
|
||||||
|
<Tooltip label={t('download', 'Download')}>
|
||||||
|
<ActionIcon
|
||||||
|
aria-label={t('download', 'Download')}
|
||||||
|
variant="subtle"
|
||||||
|
className={styles.headerIconButton}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onDownloadFile(file.id);
|
||||||
|
alert({ alertType: 'success', title: `Downloading ${file.name}`, expandable: false, durationMs: 2500 });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DownloadOutlinedIcon fontSize="small" />
|
||||||
|
</ActionIcon>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
{/* Kebab menu */}
|
{/* Kebab menu */}
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
aria-label={t('moreOptions', 'More options')}
|
aria-label={t('moreOptions', 'More options')}
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
className={styles.kebab}
|
className={styles.headerIconButton}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setShowActions((v) => !v);
|
setShowActions((v) => !v);
|
||||||
@ -271,6 +312,7 @@ const FileEditorThumbnail = ({
|
|||||||
<MoreVertIcon fontSize="small" />
|
<MoreVertIcon fontSize="small" />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Actions overlay */}
|
{/* Actions overlay */}
|
||||||
{showActions && (
|
{showActions && (
|
||||||
@ -294,7 +336,7 @@ const FileEditorThumbnail = ({
|
|||||||
setShowActions(false);
|
setShowActions(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isPinned ? <PushPinIcon fontSize="small" /> : <PushPinOutlinedIcon fontSize="small" />}
|
{isPinned ? <PushPinIcon className={styles.pinned} fontSize="small" /> : <PushPinOutlinedIcon fontSize="small" />}
|
||||||
<span>{isPinned ? t('unpin', 'Unpin') : t('pin', 'Pin')}</span>
|
<span>{isPinned ? t('unpin', 'Unpin') : t('pin', 'Pin')}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@ -321,13 +363,13 @@ const FileEditorThumbnail = ({
|
|||||||
<button
|
<button
|
||||||
className={`${styles.actionRow} ${styles.actionDanger}`}
|
className={`${styles.actionRow} ${styles.actionDanger}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onDeleteFile(file.id);
|
onCloseFile(file.id);
|
||||||
alert({ alertType: 'neutral', title: `Deleted ${file.name}`, expandable: false, durationMs: 3500 });
|
alert({ alertType: 'neutral', title: `Closed ${file.name}`, expandable: false, durationMs: 3500 });
|
||||||
setShowActions(false);
|
setShowActions(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DeleteOutlineIcon fontSize="small" />
|
<CloseIcon fontSize="small" />
|
||||||
<span>{t('delete', 'Delete')}</span>
|
<span>{t('close', 'Close')}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -394,13 +436,6 @@ const FileEditorThumbnail = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Pin indicator (bottom-left) */}
|
|
||||||
{isPinned && (
|
|
||||||
<span className={styles.pinIndicator} aria-hidden>
|
|
||||||
<PushPinIcon fontSize="small" />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Drag handle (span wrapper so we can attach a ref reliably) */}
|
{/* Drag handle (span wrapper so we can attach a ref reliably) */}
|
||||||
<span ref={handleRef} className={styles.dragHandle} aria-hidden>
|
<span ref={handleRef} className={styles.dragHandle} aria-hidden>
|
||||||
<DragIndicatorIcon fontSize="small" />
|
<DragIndicatorIcon fontSize="small" />
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user