) =>
setConfig((c) => (c ? { ...c, ...p } : c));
const save = async () => {
if (!config) return;
setSaving(true);
setMsg(undefined);
try {
setConfig(await putConfig(config));
setMsg("Saved — re-syncing with the new settings.");
} catch (e) {
setMsg(String(e));
} finally {
setSaving(false);
}
};
const sync = async () => {
setSyncing(true);
setMsg(undefined);
try {
await runSync();
setMsg("Sync requested.");
} catch (e) {
setMsg(String(e));
} finally {
setSyncing(false);
}
};
return (
{status ? (
{config && (
)}
) : (
Loading…
)}
{msg && (
{msg}
)}
);
}
function Connection({ status }: { status: Status }) {
const found = Boolean(status.location.file);
return (
}>
{found ? (
Exporter connected — updated{" "}
{relTime(status.location.mtime ?? undefined)}
.
{status.location.file}
) : (
No exporter output found. Install the{" "}
Punktfunk Sync extension in
Playnite (then restart Playnite).
{status.exportError && (
{status.exportError}
)}
Looked under:{" "}
{status.location.dir ?? "no Playnite data dir found"}
)}
);
}
function LibrarySummary({
status,
onSync,
syncing,
}: {
status: Status;
onSync: () => void;
syncing: boolean;
}) {
const report = status.lastReport;
const busy = syncing || status.syncing;
const sources = report
? Object.entries(report.perSource).sort((a, b) => b[1] - a[1])
: [];
return (
}
right={
}
>
{status.lastSync?.count ?? 0}
title(s) synced · last {relTime(status.lastSync?.at)}
{sources.length > 0 && (
{sources.map(([src, n]) => (
{src} {n}
))}
)}
{report && report.skipped.length > 0 && (
{report.skipped.length} skipped (e.g. {report.skipped[0]?.title}:{" "}
{report.skipped[0]?.reason})
)}
{report?.warnings.map((w) => (
{w}
))}
);
}
function Settings({
config,
patch,
onSave,
saving,
}: {
config: Config;
patch: (p: Partial) => void;
onSave: () => void;
saving: boolean;
}) {
const csv = (a: string[]) => a.join(", ");
const parseCsv = (s: string) =>
s
.split(",")
.map((x) => x.trim())
.filter(Boolean);
return (
}
right={
}
>
patch({ filter: { ...config.filter, installedOnly: v } })
}
/>
patch({ filter: { ...config.filter, includeHidden: v } })
}
/>
patch({ art: { ...config.art, mode: v ? "dataurl" : "off" } })
}
/>
patch({ art: { ...config.art, includeBackground: v } })
}
/>
);
}