mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix: resolve QA report issues across routing, editor, i18n, and pipeline
- Add /tools/:toolId legacy redirect and catch-all 404 page (P1-12, P1-13) - Add Shift+O dodge/burn/sponge cycle and Ctrl+Y redo shortcut (P1-3, P1-4) - Fix Fit on Screen menu action to properly compute fit zoom (P1-8) - Add filename input to editor export dialog (P1-2) - Fix password validation mismatch: frontend now requires 8 chars (P1-11) - Add license info to Settings About section (P1-9) - Replace hardcoded strings in dropzone, files, pipeline with i18n keys (P1-17 to P1-25) - Add 20+ missing i18n keys to all 21 locale files - Translate Japanese editor.shapes and settings.aiFeatures sections (P1-19, P1-20) - Fix RTL: use logical CSS properties in sidebar, files, app-layout (P2-24 to P2-26) - Add single-file download button to pipeline results (P1-28) - Fix compress step settings restoration on pipeline load (P1-27) - Increase mobile nav touch targets to 44px minimum (P2-29)
This commit is contained in:
@@ -2,6 +2,7 @@ import { TOOLS } from "@snapotter/shared";
|
||||
import { FileImage, ImageIcon, Workflow } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTranslation } from "@/contexts/i18n-context";
|
||||
import {
|
||||
apiGetFileDetails,
|
||||
formatHeaders,
|
||||
@@ -74,6 +75,7 @@ interface FileDetailsProps {
|
||||
}
|
||||
|
||||
export function FileDetails({ mobile = false }: FileDetailsProps) {
|
||||
const { t } = useTranslation();
|
||||
const { selectedFileId } = useFilesPageStore();
|
||||
const setFiles = useFileStore((s) => s.setFiles);
|
||||
const navigate = useNavigate();
|
||||
@@ -139,11 +141,11 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
|
||||
"flex flex-col items-center justify-center text-muted-foreground",
|
||||
mobile
|
||||
? "flex flex-col gap-4"
|
||||
: "w-60 border-l border-border p-4 shrink-0 hidden lg:flex flex-col",
|
||||
: "w-60 border-s border-border p-4 shrink-0 hidden lg:flex flex-col",
|
||||
)}
|
||||
>
|
||||
<FileImage className="h-12 w-12 mb-3 opacity-30" />
|
||||
<p className="text-sm">Select a file to view details</p>
|
||||
<p className="text-sm">{t.files.selectFilePrompt}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -155,7 +157,7 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
|
||||
"flex items-center justify-center",
|
||||
mobile
|
||||
? "flex flex-col gap-4"
|
||||
: "w-60 border-l border-border p-4 shrink-0 hidden lg:flex flex-col",
|
||||
: "w-60 border-s border-border p-4 shrink-0 hidden lg:flex flex-col",
|
||||
)}
|
||||
>
|
||||
<div className="h-6 w-6 border-2 border-primary border-t-transparent rounded-full animate-spin" />
|
||||
@@ -171,7 +173,7 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
|
||||
"overflow-y-auto",
|
||||
mobile
|
||||
? "flex flex-col gap-4"
|
||||
: "w-60 border-l border-border p-4 shrink-0 hidden lg:flex flex-col",
|
||||
: "w-60 border-s border-border p-4 shrink-0 hidden lg:flex flex-col",
|
||||
)}
|
||||
>
|
||||
{/* Thumbnail */}
|
||||
@@ -187,24 +189,28 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
|
||||
<div className="flex-1">
|
||||
<div className="rounded-lg border border-border overflow-hidden">
|
||||
<div className="bg-blue-500/10 border-b border-border px-3 py-2">
|
||||
<h4 className="text-sm font-semibold text-blue-600 dark:text-blue-400">File Details</h4>
|
||||
<h4 className="text-sm font-semibold text-blue-600 dark:text-blue-400">
|
||||
{t.files.fileDetailsHeading}
|
||||
</h4>
|
||||
</div>
|
||||
<div className="divide-y divide-border">
|
||||
<DetailRow label="Name" value={details.originalName} />
|
||||
<DetailRow label={t.files.name} value={details.originalName} />
|
||||
<DetailRow
|
||||
label="Format"
|
||||
label={t.files.format}
|
||||
value={details.mimeType.replace("image/", "").toUpperCase()}
|
||||
/>
|
||||
<DetailRow label="Size" value={formatSize(details.size)} />
|
||||
<DetailRow label={t.files.size} value={formatSize(details.size)} />
|
||||
<DetailRow
|
||||
label="Dimensions"
|
||||
label={t.files.dimensions}
|
||||
value={details.width && details.height ? `${details.width} × ${details.height}` : "—"}
|
||||
/>
|
||||
<DetailRow label="Version" value={`V${details.version}`} />
|
||||
<DetailRow label={t.files.version} value={`V${details.version}`} />
|
||||
<DetailRow
|
||||
label="Tools Used"
|
||||
label={t.files.toolsUsed}
|
||||
value={
|
||||
details.toolChain.length > 0 ? details.toolChain.map(toolName).join(", ") : "None"
|
||||
details.toolChain.length > 0
|
||||
? details.toolChain.map(toolName).join(", ")
|
||||
: t.files.none
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user