mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: Import from Files works, remove pipeline button from files page
- Import from Files now navigates back to the tool page with the selected file loaded (uses selectForTool router state) - Tool page skips file store reset when arriving from the library - Removed "Open in Pipeline" button from file details and file list - Button text changes to "Select File" when in file-selection mode
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { TOOLS } from "@snapotter/shared";
|
import { TOOLS } from "@snapotter/shared";
|
||||||
import { FileImage, ImageIcon, Workflow } from "lucide-react";
|
import { FileImage, ImageIcon } from "lucide-react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import { useTranslation } from "@/contexts/i18n-context";
|
import { useTranslation } from "@/contexts/i18n-context";
|
||||||
import {
|
import {
|
||||||
apiGetFileDetails,
|
apiGetFileDetails,
|
||||||
@@ -79,6 +79,8 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
|
|||||||
const { selectedFileId } = useFilesPageStore();
|
const { selectedFileId } = useFilesPageStore();
|
||||||
const setFiles = useFileStore((s) => s.setFiles);
|
const setFiles = useFileStore((s) => s.setFiles);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
const selectForTool = (location.state as { selectForTool?: string } | null)?.selectForTool;
|
||||||
|
|
||||||
const [details, setDetails] = useState<UserFileDetail | null>(null);
|
const [details, setDetails] = useState<UserFileDetail | null>(null);
|
||||||
const [loadingDetails, setLoadingDetails] = useState(false);
|
const [loadingDetails, setLoadingDetails] = useState(false);
|
||||||
@@ -121,7 +123,13 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
|
|||||||
if (valid.length === 0) return;
|
if (valid.length === 0) return;
|
||||||
|
|
||||||
setFiles(valid.map((d) => d.file));
|
setFiles(valid.map((d) => d.file));
|
||||||
navigate("/", { state: { fromLibrary: true } });
|
|
||||||
|
if (selectForTool) {
|
||||||
|
const tool = TOOLS.find((t) => t.id === selectForTool);
|
||||||
|
navigate(tool?.route ?? "/", { state: { fromLibrary: true } });
|
||||||
|
} else {
|
||||||
|
navigate("/", { state: { fromLibrary: true } });
|
||||||
|
}
|
||||||
|
|
||||||
// Set serverFileId on each entry so tool processing creates new versions
|
// Set serverFileId on each entry so tool processing creates new versions
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -224,19 +232,7 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
|
|||||||
onClick={handleOpenFile}
|
onClick={handleOpenFile}
|
||||||
className="w-full px-4 py-2 bg-primary text-primary-foreground text-sm font-medium rounded-lg hover:bg-primary/90 transition-colors"
|
className="w-full px-4 py-2 bg-primary text-primary-foreground text-sm font-medium rounded-lg hover:bg-primary/90 transition-colors"
|
||||||
>
|
>
|
||||||
Open File
|
{selectForTool ? t.files.selectFile : t.files.openFile}
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => {
|
|
||||||
const { checkedIds } = useFilesPageStore.getState();
|
|
||||||
const ids = checkedIds.size > 1 ? Array.from(checkedIds) : [details.id];
|
|
||||||
navigate("/automate", { state: { libraryFileIds: ids } });
|
|
||||||
}}
|
|
||||||
className="w-full px-4 py-2 border border-primary text-primary text-sm font-medium rounded-lg hover:bg-primary/5 transition-colors flex items-center justify-center gap-2"
|
|
||||||
>
|
|
||||||
<Workflow className="h-4 w-4" />
|
|
||||||
Open in Pipeline
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Download, Search, Trash2, Workflow } from "lucide-react";
|
import { Download, Search, Trash2 } from "lucide-react";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useTranslation } from "@/contexts/i18n-context";
|
import { useTranslation } from "@/contexts/i18n-context";
|
||||||
@@ -49,10 +49,6 @@ export function FileList() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSendToPipeline() {
|
|
||||||
navigate("/automate", { state: { libraryFileIds: Array.from(checkedIds) } });
|
|
||||||
}
|
|
||||||
|
|
||||||
const allChecked = files.length > 0 && checkedIds.size === files.length;
|
const allChecked = files.length > 0 && checkedIds.size === files.length;
|
||||||
const someChecked = checkedIds.size > 0;
|
const someChecked = checkedIds.size > 0;
|
||||||
|
|
||||||
@@ -95,14 +91,6 @@ export function FileList() {
|
|||||||
<Trash2 className="h-3.5 w-3.5" />
|
<Trash2 className="h-3.5 w-3.5" />
|
||||||
{t.files.delete}
|
{t.files.delete}
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={handleSendToPipeline}
|
|
||||||
className="flex items-center gap-1 px-2 py-1 text-xs text-primary hover:bg-primary/10 rounded-lg transition-colors"
|
|
||||||
>
|
|
||||||
<Workflow className="h-3.5 w-3.5" />
|
|
||||||
{t.files.pipeline}
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleBulkDownload}
|
onClick={handleBulkDownload}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import type { Crop } from "react-image-crop";
|
import type { Crop } from "react-image-crop";
|
||||||
import { Link, useParams } from "react-router-dom";
|
import { Link, useLocation, useParams } from "react-router-dom";
|
||||||
import { BeforeAfterSlider } from "@/components/common/before-after-slider";
|
import { BeforeAfterSlider } from "@/components/common/before-after-slider";
|
||||||
import { BottomSheet } from "@/components/common/bottom-sheet";
|
import { BottomSheet } from "@/components/common/bottom-sheet";
|
||||||
import { Dropzone } from "@/components/common/dropzone";
|
import { Dropzone } from "@/components/common/dropzone";
|
||||||
@@ -198,6 +198,7 @@ function FileSelectionInfo({
|
|||||||
export function ToolPage() {
|
export function ToolPage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { toolId } = useParams<{ toolId: string }>();
|
const { toolId } = useParams<{ toolId: string }>();
|
||||||
|
const location = useLocation();
|
||||||
const tool = useMemo(() => TOOLS.find((t) => t.id === toolId), [toolId]);
|
const tool = useMemo(() => TOOLS.find((t) => t.id === toolId), [toolId]);
|
||||||
const registryEntry = useMemo(
|
const registryEntry = useMemo(
|
||||||
() => (toolId ? getToolRegistryEntry(toolId) : undefined),
|
() => (toolId ? getToolRegistryEntry(toolId) : undefined),
|
||||||
@@ -333,7 +334,10 @@ export function ToolPage() {
|
|||||||
|
|
||||||
// biome-ignore lint/correctness/useExhaustiveDependencies: toolId triggers intentional reset on tool navigation
|
// biome-ignore lint/correctness/useExhaustiveDependencies: toolId triggers intentional reset on tool navigation
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
useFileStore.getState().reset();
|
const fromLibrary = (location.state as { fromLibrary?: boolean } | null)?.fromLibrary;
|
||||||
|
if (!fromLibrary) {
|
||||||
|
useFileStore.getState().reset();
|
||||||
|
}
|
||||||
|
|
||||||
useBase64Store.getState().reset();
|
useBase64Store.getState().reset();
|
||||||
useCollageStore.getState().reset();
|
useCollageStore.getState().reset();
|
||||||
|
|||||||
@@ -3214,6 +3214,7 @@ export const ar: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3243,6 +3243,7 @@ export const de: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3180,6 +3180,7 @@ export const en = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3220,6 +3220,7 @@ export const es: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3241,6 +3241,7 @@ export const fr: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3211,6 +3211,7 @@ export const hi: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3228,6 +3228,7 @@ export const id: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3235,6 +3235,7 @@ export const it: TranslationKeys = {
|
|||||||
noFilesFound: "Nessun file trovato",
|
noFilesFound: "Nessun file trovato",
|
||||||
selectFilePrompt: "Seleziona un file per visualizzare i dettagli",
|
selectFilePrompt: "Seleziona un file per visualizzare i dettagli",
|
||||||
openFile: "Apri file",
|
openFile: "Apri file",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Apri nella pipeline",
|
openInPipeline: "Apri nella pipeline",
|
||||||
name: "Nome",
|
name: "Nome",
|
||||||
format: "Formato",
|
format: "Formato",
|
||||||
|
|||||||
@@ -3184,6 +3184,7 @@ export const ja: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3169,6 +3169,7 @@ export const ko: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3231,6 +3231,7 @@ export const nl: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3238,6 +3238,7 @@ export const pl: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3231,6 +3231,7 @@ export const ptBR: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3230,6 +3230,7 @@ export const ru: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3225,6 +3225,7 @@ export const sv: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3202,6 +3202,7 @@ export const th: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3235,6 +3235,7 @@ export const tr: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3231,6 +3231,7 @@ export const uk: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3225,6 +3225,7 @@ export const vi: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3153,6 +3153,7 @@ export const zhCN: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
@@ -3151,6 +3151,7 @@ export const zhTW: TranslationKeys = {
|
|||||||
noFilesFound: "No files found",
|
noFilesFound: "No files found",
|
||||||
selectFilePrompt: "Select a file to view details",
|
selectFilePrompt: "Select a file to view details",
|
||||||
openFile: "Open File",
|
openFile: "Open File",
|
||||||
|
selectFile: "Select File",
|
||||||
openInPipeline: "Open in Pipeline",
|
openInPipeline: "Open in Pipeline",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "Format",
|
format: "Format",
|
||||||
|
|||||||
Reference in New Issue
Block a user