Add a setting to hide the quarantine from Plex

Settings -> Media servers -> "Hide quarantine from Plex" writes a
.plexignore into every pair's quarantine folder (.playlink-trash by
default), with patterns for every folder depth quarantined files live
at. Quarantine folders opened later get the file automatically.

The file carries a marker line: turning the option off removes only
playlink's own file, and an existing .plexignore written by someone else
is never overwritten or deleted (reported instead). Writes go through a
temporary file and a rename.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cdnutterandClaude Opus 5.5 committed 2026-09-28 21:57:56 -07:00
1 parent 42161e4287
commit 1da0132d5e
7 files changed
+238 -2

No files matched your search

+1
View File
@@ -33,6 +33,7 @@ export type Info = {
allowed_roots: string[];
default_extensions: string[];
dry_run: boolean;
plex_ignore: boolean;
};
export type Job = {
+26
View File
@@ -15,6 +15,17 @@ export function SettingsPage() {
mutationFn: (v: boolean) => api.put("/settings", { dry_run: v }),
onSuccess: () => qc.invalidateQueries({ queryKey: ["info"] }),
});
const plex = useMutation({
mutationFn: (v: boolean) =>
api.put<{ plex_ignore: boolean; results?: { pair: string; path: string; error?: string }[] }>("/settings", { plex_ignore: v }),
onSuccess: (res) => {
qc.invalidateQueries({ queryKey: ["info"] });
const failed = (res.results ?? []).filter((r) => r.error);
if (failed.length > 0) failed.forEach((r) => toast("err", `${r.pair}: ${r.error}`));
else toast("ok", res.plex_ignore ? "Added .plexignore to every quarantine folder." : "Removed playlink's .plexignore files.");
},
onError: (e) => toast("err", e.message),
});
const pw = useMutation({
mutationFn: () => api.post("/auth/password", { current: cur, new: next }),
onSuccess: () => {
@@ -52,6 +63,21 @@ export function SettingsPage() {
</div>
</Card>
<Card className="space-y-3 p-5">
<h2 className="font-semibold">Media servers</h2>
<Toggle
checked={info.data?.plex_ignore ?? false}
onChange={(v) => plex.mutate(v)}
label={<span className="font-medium">Hide quarantine from Plex</span>}
/>
<p className="text-sm text-muted">
Adds a <code className="mono">.plexignore</code> file to each library pair's quarantine folder (by default{" "}
<code className="mono">.playlink-trash</code> in the slave library), so Plex doesn't pick up quarantined songs as duplicates. New
quarantine folders get it automatically. Turning this off removes the file again, but only if playlink created it: a{" "}
<code className="mono">.plexignore</code> of your own is never changed.
</p>
</Card>
<Card className="space-y-2 p-5">
<h2 className="font-semibold">Environment</h2>
<div className="text-sm">