refactoring stuff to make sure the right responsibility is fullfilled in the right place

This commit is contained in:
Chris Kruining 2024-10-28 15:43:53 +01:00
parent fa9264326b
commit ddf4519f41
No known key found for this signature in database
GPG key ID: EB894A3560CCCAD2
3 changed files with 138 additions and 127 deletions

View file

@ -62,18 +62,14 @@ interface ContentTabType {
export default function Edit(props: ParentProps) {
const filesContext = useFiles();
const [root, { refetch: getRoot, mutate: updateRoot }] = createResource(() => filesContext?.get('__root__'));
const [tabs, { refetch: getTabs }] = createResource<ContentTabType[]>(async () => {
const handles = (await filesContext?.list()) ?? [];
return await Promise.all(handles.map(handle => {
const [api, setApi] = createSignal<GridApi>();
const [entries, setEntries] = createSignal<Entries>(new Map());
const files = handle.entries()
const root = filesContext.get('__root__');
const tabs = createMemo(() => filesContext.files().map(({ key, handle }) => {
const [api, setApi] = createSignal<GridApi>();
const [entries, setEntries] = createSignal<Entries>(new Map());
return ({ handle, api, setApi, entries, setEntries });
}));
}, { initialValue: [], ssrLoadFrom: 'initial' });
return ({ handle, api, setApi, entries, setEntries });
}));
const [active, setActive] = createSignal<string>();
const [contents, setContents] = createSignal<Map<string, Map<string, string>>>(new Map());
const [tree, setFiles] = createSignal<FolderEntry>(emptyFolder);
@ -152,119 +148,56 @@ export default function Edit(props: ParentProps) {
}).toArray();
});
// Since the files are stored in indexedDb we need to refetch on the client in order to populate on page load
onMount(() => {
getRoot();
getTabs();
});
createEffect(() => {
const directory = root();
if (root.state === 'ready' && directory?.kind === 'directory') {
if (directory === undefined) {
return;
}
(async () => {
const contents = await Array.fromAsync(walk(directory));
(async () => {
const contents = await Array.fromAsync(walk(directory));
console.log(contents);
setContents(new Map(contents.map(({ id, entries }) => [id, entries] as const)))
setContents(new Map(contents.map(({ id, entries }) => [id, entries] as const)))
const template = contents.map(({ lang, handle }) => [lang, { handle, value: '' }]);
const template = contents.map(({ lang, handle }) => [lang, { handle, value: '' }]);
const merged = contents.reduce((aggregate, { id, handle, path, lang, entries }) => {
for (const [key, value] of entries.entries()) {
const k = [...path, key].join('.');
const merged = contents.reduce((aggregate, { id, handle, path, lang, entries }) => {
for (const [key, value] of entries.entries()) {
const k = [...path, key].join('.');
if (!aggregate.has(k)) {
aggregate.set(k, Object.fromEntries(template));
}
aggregate.get(k)![lang] = { value, handle, id };
if (!aggregate.has(k)) {
aggregate.set(k, Object.fromEntries(template));
}
return aggregate;
}, new Map<string, Record<string, { id: string, value: string, handle: FileSystemFileHandle }>>());
aggregate.get(k)![lang] = { value, handle, id };
}
setFiles({ name: directory.name, id: '', kind: 'folder', handle: directory, entries: await Array.fromAsync(fileTreeWalk(directory)) });
setEntries(merged);
})();
}
return aggregate;
}, new Map<string, Record<string, { id: string, value: string, handle: FileSystemFileHandle }>>());
setFiles({ name: directory.name, id: '', kind: 'folder', handle: directory, entries: await Array.fromAsync(fileTreeWalk(directory)) });
setEntries(merged);
})();
});
const commands = {
open: createCommand('open', async () => {
const [fileHandle] = await window.showOpenFilePicker({
types: [
{
description: "JSON File(s)",
accept: {
"application/json": [".json", ".jsonp", ".jsonc"],
},
}
],
excludeAcceptAllOption: true,
multiple: true,
});
const file = await fileHandle.getFile();
const text = await file.text();
console.log(fileHandle, file, text);
}, { key: 'o', modifier: Modifier.Control }),
openFolder: createCommand('open folder', async () => {
open: createCommand('open folder', async () => {
const directory = await window.showDirectoryPicker({ mode: 'readwrite' });
filesContext.set('__root__', directory);
updateRoot(directory);
}, { key: 'o', modifier: Modifier.Control }),
close: createCommand('close folder', async () => {
filesContext.remove('__root__');
}),
save: createCommand('save', async () => {
const results = await Promise.allSettled(mutatedData().map(async ([handle, data]) => {
await Promise.allSettled(mutatedData().map(async ([handle, data]) => {
const stream = await handle.createWritable({ keepExistingData: false });
stream.write(JSON.stringify(data, null, 4));
stream.write('\n');
stream.close();
}));
console.log(results);
// const fileMutations = await Promise.all(mutations.map(async (mutation) => {
// const [k, lang] = splitAt(mutation.key, mutation.key.lastIndexOf('.'));
// const entry = _entries.get(k);
// const localEntry = entry?.[lang];
// if (!localEntry) {
// throw new Error('invalid edge case???');
// }
// const createNewFile = async () => {
// const [, alternativeLocalEntry] = Object.entries(entry).find(([l, e]) => l !== lang && e.id !== undefined) ?? [];
// const { directory, path } = alternativeLocalEntry ? findFile(tree(), alternativeLocalEntry.id) ?? {} : {};
// const handle = await window.showSaveFilePicker({
// suggestedName: `${lang}.json`,
// startIn: directory,
// excludeAcceptAllOption: true,
// types: [
// { accept: { 'application/json': ['.json'] }, description: 'JSON' },
// ]
// });
// // TODO :: patch the tree with this new entry
// // console.log(localEntry, tree());
// return { handle, path };
// };
// const { handle, path } = findFile(tree(), localEntry.id) ?? (mutation.kind !== MutarionKind.Delete ? await createNewFile() : {});
// const id = await handle?.getUniqueId();
// const key = path ? k.slice(path.join('.').length + 1) : k;
// const value = rows[k][lang];
// return { action: mutation.kind, key, id, value, handle };
// }));
// console.log(rows, entries(), Object.groupBy(fileMutations, m => m.id ?? 'undefined'))
}, { key: 's', modifier: Modifier.Control }),
saveAs: createCommand('save as', (handle?: FileSystemFileHandle) => {
console.log('save as ...', handle);
@ -301,7 +234,9 @@ export default function Edit(props: ParentProps) {
<Menu.Item label="file">
<Menu.Item command={commands.open} />
<Menu.Item command={commands.openFolder} />
<Menu.Item command={commands.close} />
<Menu.Separator />
<Menu.Item command={commands.save} />
</Menu.Item>
@ -326,12 +261,11 @@ export default function Edit(props: ParentProps) {
</Menu.Root>
<Sidebar as="aside" label={tree().name} class={css.sidebar}>
<Show when={!root.loading && root()} fallback={<button onpointerdown={() => commands.openFolder()}>open a folder</button>}>
<Show when={root()} fallback={<button onpointerdown={() => commands.open()}>open a folder</button>}>
<Tree entries={tree().entries}>{[
folder => {
return <span onDblClick={() => {
filesContext?.set(folder().name, folder().handle);
getTabs();
}}>{folder().name}</span>;
},
file => {
@ -340,7 +274,6 @@ export default function Edit(props: ParentProps) {
return <Context.Handle classList={{ [css.mutated]: mutated() }} onDblClick={() => {
const folder = file().directory;
filesContext?.set(folder.name, folder);
getTabs();
}}>{file().name}</Context.Handle>;
},
] as const}</Tree>
@ -349,7 +282,7 @@ export default function Edit(props: ParentProps) {
<Tabs active={setActive}>
<For each={tabs()}>{
({ handle, setApi, setEntries }) => <Tab id={handle.name} label={handle.name}><Content directory={handle} api={setApi} entries={setEntries} /></Tab>
({ handle, setApi, setEntries }) => <Tab id={handle.name} label={handle.name} ><Content directory={handle} api={setApi} entries={setEntries} /></Tab>
}</For>
</Tabs>
</Context.Root>