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:
@@ -21,10 +21,12 @@ export function CompressControls({ settings: initialSettings, onChange }: Compre
|
||||
const [targetSizeValue, setTargetSizeValue] = useState("");
|
||||
const [sizeUnit, setSizeUnit] = useState<SizeUnit>("KB");
|
||||
|
||||
const initializedRef = useRef(false);
|
||||
const prevSettingsKeyRef = useRef<string | null>(null);
|
||||
useEffect(() => {
|
||||
if (!initialSettings || initializedRef.current) return;
|
||||
initializedRef.current = true;
|
||||
if (!initialSettings) return;
|
||||
const key = JSON.stringify(initialSettings);
|
||||
if (prevSettingsKeyRef.current === key) return;
|
||||
prevSettingsKeyRef.current = key;
|
||||
if (initialSettings.mode != null) setMode(initialSettings.mode as CompressMode);
|
||||
if (initialSettings.quality != null) setQuality(Number(initialSettings.quality));
|
||||
if (initialSettings.targetSizeKb != null)
|
||||
|
||||
@@ -129,7 +129,7 @@ function SortableStep({
|
||||
e.stopPropagation();
|
||||
onRemove();
|
||||
}}
|
||||
title="Remove"
|
||||
title={t.automate.removeStep}
|
||||
className="p-1 rounded hover:bg-destructive/10 text-muted-foreground hover:text-destructive"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
@@ -159,6 +159,7 @@ export function PipelineBuilder({
|
||||
onUpdateSettings,
|
||||
onToggleStep,
|
||||
}: PipelineBuilderProps) {
|
||||
const { t } = useTranslation();
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
|
||||
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
|
||||
@@ -177,10 +178,8 @@ export function PipelineBuilder({
|
||||
<div className="p-4 rounded-full bg-muted/50 mb-4">
|
||||
<FileImage className="h-8 w-8 text-muted-foreground" />
|
||||
</div>
|
||||
<h3 className="text-sm font-medium text-foreground mb-1">No steps yet</h3>
|
||||
<p className="text-sm text-muted-foreground max-w-[240px]">
|
||||
Click tools from the palette to build your pipeline
|
||||
</p>
|
||||
<h3 className="text-sm font-medium text-foreground mb-1">{t.automate.noStepsHeading}</h3>
|
||||
<p className="text-sm text-muted-foreground max-w-[240px]">{t.automate.addToolsPrompt}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -66,12 +66,16 @@ export function ToolPalette({ onAddStep, className }: ToolPaletteProps) {
|
||||
return (
|
||||
<div className={cn("flex flex-col h-full", className)}>
|
||||
<div className="px-3 pt-3 pb-2 shrink-0">
|
||||
<SearchBar value={search} onChange={setSearch} placeholder="Search tools..." />
|
||||
<SearchBar
|
||||
value={search}
|
||||
onChange={setSearch}
|
||||
placeholder={t.automate.searchToolsPlaceholder}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-y-auto px-3 pb-3">
|
||||
{availableTools.length === 0 ? (
|
||||
<p className="text-sm text-muted-foreground text-center py-8">No tools found</p>
|
||||
<p className="text-sm text-muted-foreground text-center py-8">{t.common.noToolsFound}</p>
|
||||
) : isSearching ? (
|
||||
<div className="space-y-1">
|
||||
{availableTools.map((tool) => (
|
||||
|
||||
Reference in New Issue
Block a user