Old project/workflow names and browser settings migrate on load; /funpack redirects to /fun. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016acRss69eH1235eRdFTZHY
50 lines
3.2 KiB
JavaScript
50 lines
3.2 KiB
JavaScript
// Files: what FunUI keeps on disk for prompts (the shortcut library, cut words) and the taste keys, to see and delete. As v4's tab.
|
|
import { composer as c } from "../../composer/composer.js";
|
|
|
|
const size = (n) => (n < 1024 ? `${n} B` : n < 1048576 ? `${(n / 1024).toFixed(1)} KB` : `${(n / 1048576).toFixed(1)} MB`);
|
|
|
|
export function files(app) {
|
|
const page = c.region.stack({ gap: "sm" });
|
|
const sure = (title, message) => c.modal.dialogue({ title, message: `${message} This cannot be undone.`, tone: "danger", confirmLabel: "Delete" }).result;
|
|
async function draw() {
|
|
let lib, keys = null;
|
|
try { lib = await app.api.libraryFiles(); } catch (err) { return page.set([c.banner.warn({ text: `Could not list the files: ${err.message}` })]); }
|
|
try { keys = (await app.api.tasteKeys()).keys || []; } catch { /* no taste module: no keys to show */ }
|
|
const row = (label, hint, onDelete) => c.settingsRow.default({ label, hint, control: c.button.sm({ label: "✕ Delete", tone: "danger", onClick: onDelete }) });
|
|
// A key's kinds: one module's learning each. Deleting one kind leaves the key's other kinds as they are.
|
|
const kindRows = async (k) => {
|
|
let kinds = [];
|
|
try { kinds = (await app.api.tasteKindsOf(k)).kinds || []; } catch (err) { return [c.hint.default({ text: `Could not list ${k}: ${err.message}` })]; }
|
|
if (!kinds.length) return [c.hint.default({ text: "Nothing learned under this key yet." })];
|
|
return kinds.map((kd) => c.settingsRow.default({ label: kd.title, hint: `${kd.hint} · ${size(kd.bytes)}`,
|
|
control: c.button.sm({ label: "✕ Delete", tone: "danger", onClick: async () => {
|
|
if (!(await sure("Delete what was learned", `Delete “${kd.title}” under “${k}”? The key's other learning stays.`))) return;
|
|
try { await app.api.clearTasteKind(k, kd.kind); } catch (err) { c.toast.warn({ text: err.message }); }
|
|
draw();
|
|
} }) }));
|
|
};
|
|
const keyBlocks = keys ? await Promise.all(keys.map(async (k) => [
|
|
c.settingsRow.default({ label: k, hint: "what your ratings taught under this name", control: c.button.sm({ label: "✕ Delete key", tone: "danger", onClick: async () => {
|
|
if (!(await sure("Delete taste key", `Delete “${k}” and everything it learned?`))) return;
|
|
try { await app.api.deleteTasteKey(k); } catch (err) { c.toast.warn({ text: err.message }); }
|
|
draw();
|
|
} }) }),
|
|
...(await kindRows(k)),
|
|
])) : null;
|
|
page.set([
|
|
c.toolbar.default({ items: [c.button.sm({ label: "↻ Refresh", tone: "ghost", onClick: draw })] }),
|
|
c.label.section({ text: "Prompt library" }),
|
|
c.hint.default({ text: lib.dir }),
|
|
...(lib.files.length ? lib.files.map((f) => row(f.name, size(f.size), async () => {
|
|
if (!(await sure("Delete file", `Delete “${f.name}”?`))) return;
|
|
try { await app.api.deleteLibraryFile(f.name); } catch (err) { c.toast.warn({ text: err.message }); }
|
|
draw();
|
|
})) : [c.hint.default({ text: "No files." })]),
|
|
...(keyBlocks ? [c.label.section({ text: "Taste keys" }),
|
|
...(keys.length ? keyBlocks.flat() : [c.hint.default({ text: "No keys." })])] : []),
|
|
]);
|
|
}
|
|
draw();
|
|
return page;
|
|
}
|