refactor(web): simplify organize defaults and restore historical options
This commit is contained in:
1 parent
acf68ee03b
commit
c85b139ec4
11 files changed
+661
-439
No files matched your search
@@ -1,81 +0,0 @@
|
||||
import { useEffect } from "react";
|
||||
import { filesErrorText } from "~/api/files.ts";
|
||||
import { useOrganizeSources } from "~/api/organize-sources.ts";
|
||||
import type { OrganizeSource } from "~/components/organize-wizard/organize-wizard.tsx";
|
||||
import { Button } from "~/components/ui/button.tsx";
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "~/components/ui/dialog.tsx";
|
||||
import { matchingOrganizeSources } from "./source-match.ts";
|
||||
|
||||
type FileSource = Extract<OrganizeSource, { kind: "files" }>;
|
||||
/** Wait for profiles even on the first click; ambiguous sources require an explicit choice. */
|
||||
export function FileSourceSelection({
|
||||
source,
|
||||
onSelect,
|
||||
onClose,
|
||||
}: {
|
||||
source: FileSource;
|
||||
onSelect: (source: FileSource) => void;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
const profiles = useOrganizeSources();
|
||||
const matches = matchingOrganizeSources(source.items, profiles.data?.items ?? []);
|
||||
useEffect(() => {
|
||||
if (!profiles.isSuccess || matches.length > 1) return;
|
||||
const profile = matches[0];
|
||||
onSelect(
|
||||
profile
|
||||
? { ...source, sourceConfigId: profile.id, defaultAction: profile.action, label: `整理来源 · ${profile.name}` }
|
||||
: source,
|
||||
);
|
||||
}, [profiles.isSuccess, matches, source, onSelect]);
|
||||
return (
|
||||
<Dialog open onOpenChange={(open) => !open && onClose()}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{profiles.isPending ? "读取整理来源…" : "选择整理来源"}</DialogTitle>
|
||||
<DialogDescription>整理时沿用所选整理来源的整理方式、目标目录和分类。</DialogDescription>
|
||||
</DialogHeader>
|
||||
{profiles.isPending ? (
|
||||
<p role="status" className="text-caption text-muted-foreground">
|
||||
匹配整理来源…
|
||||
</p>
|
||||
) : profiles.error ? (
|
||||
<>
|
||||
<p role="alert" className="text-caption text-destructive">
|
||||
{filesErrorText(profiles.error, "读取整理来源失败")}
|
||||
</p>
|
||||
<Button variant="outline" onClick={() => void profiles.refetch()}>
|
||||
重试
|
||||
</Button>
|
||||
</>
|
||||
) : matches.length > 1 ? (
|
||||
<div className="max-h-72 space-y-2 overflow-auto">
|
||||
{matches.map((profile) => (
|
||||
<Button
|
||||
key={profile.id}
|
||||
variant="outline"
|
||||
className="h-auto w-full justify-start whitespace-normal py-3 text-left"
|
||||
onClick={() =>
|
||||
onSelect({
|
||||
...source,
|
||||
sourceConfigId: profile.id,
|
||||
defaultAction: profile.action,
|
||||
label: `整理来源 · ${profile.name}`,
|
||||
})
|
||||
}
|
||||
>
|
||||
{profile.name} · {profile.action === "copy" ? "复制" : "移动"} · {profile.category ?? "自动分类"}
|
||||
{!profile.enabled ? " · 已停用" : ""}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
{!profiles.isPending && (profiles.error || matches.length > 1) ? (
|
||||
<Button variant="outline" onClick={() => onSelect(source)}>
|
||||
不用整理来源,手动设置
|
||||
</Button>
|
||||
) : null}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { OrganizeSourceView, OrganizeStockResult } from "@umt/contracts";
|
||||
import { useState } from "react";
|
||||
import { Link } from "react-router";
|
||||
import { toast } from "sonner";
|
||||
import { filesErrorText } from "~/api/files.ts";
|
||||
import { useOrganizeSources, useOrganizeStock } from "~/api/organize-sources.ts";
|
||||
@@ -42,12 +41,13 @@ export function SourceSelection({
|
||||
const sources = useOrganizeSources();
|
||||
const stock = useOrganizeStock();
|
||||
const [manual, setManual] = useState(false);
|
||||
if (manual)
|
||||
const direct = sources.isSuccess && !sources.data.items.length;
|
||||
if (manual || direct)
|
||||
return (
|
||||
<DirectoryDialog
|
||||
mode="source"
|
||||
allowRoot={false}
|
||||
onClose={() => setManual(false)}
|
||||
onClose={direct ? onClose : () => setManual(false)}
|
||||
onSelect={(ref) => onSelect({ kind: "files", items: [ref], label: "手动选择的目录" })}
|
||||
/>
|
||||
);
|
||||
@@ -56,7 +56,7 @@ export function SourceSelection({
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>选择整理来源</DialogTitle>
|
||||
<DialogDescription>扫描来源目录里已有的文件,预览后再整理。扫描不改变自动整理的基线。</DialogDescription>
|
||||
<DialogDescription>选择来源,扫描已有文件后开始整理。扫描不改变自动整理的基线。</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="max-h-72 space-y-2 overflow-auto">
|
||||
{sources.isPending ? <p className="text-caption text-muted-foreground">加载中…</p> : null}
|
||||
@@ -101,15 +101,6 @@ export function SourceSelection({
|
||||
<Button variant="outline" disabled={stock.isPending} onClick={() => setManual(true)}>
|
||||
手动选择目录
|
||||
</Button>
|
||||
{sources.isSuccess && !sources.data.items.length ? (
|
||||
<Link
|
||||
to="/console/settings#library/sources"
|
||||
onClick={onClose}
|
||||
className="text-caption text-muted-foreground underline"
|
||||
>
|
||||
新增整理来源
|
||||
</Link>
|
||||
) : null}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user