Experiment to rebuild Diffuse using web applets.
1import * as IDB from "idb-keyval";
2import * as URI from "uri-js";
3import QS from "query-string";
4
5import type { Track } from "@applets/core/types.d.ts";
6import type { Handles } from "./types";
7import { isAudioFile } from "@scripts/input/common";
8import { IDB_HANDLES, SCHEME } from "./constants";
9
10////////////////////////////////////////////
11// 🛠️
12////////////////////////////////////////////
13export async function fetchHandles(): Promise<Handles> {
14 return (await IDB.get(IDB_HANDLES)) ?? {};
15}
16
17export async function fetchHandlesList() {
18 return Object.entries(await fetchHandles()).map(([id, handle]) => {
19 return { id, handle };
20 });
21}
22export function groupTracksByHandle(tracks: Track[]) {
23 const acc: Record<string, { tracks: Track[] }> = {};
24
25 tracks.forEach((track: Track) => {
26 const id = trackHandleId(track);
27 if (!id) return acc;
28
29 if (acc[id]) {
30 acc[id].tracks.push(track);
31 } else {
32 acc[id] = { tracks: [track] };
33 }
34 });
35
36 return acc;
37}
38
39export function isSupported() {
40 return !!(globalThis as any).showDirectoryPicker;
41}
42
43export function trackCid(track: Track): string | undefined {
44 const a = URI.parse(track.uri);
45 const cid = a.query ? QS.parse(a.query).cid || undefined : undefined;
46 return Array.isArray(cid) && cid[0] ? cid[0] : typeof cid === "string" ? cid : undefined;
47}
48
49export function trackHandleId(track: Track): string | undefined {
50 const a = URI.parse(track.uri);
51 return a.host;
52}
53
54export async function recursiveList(
55 dir: FileSystemDirectoryHandle,
56 rootHandleId: string,
57 path: string[],
58): Promise<Track[]> {
59 const tracks: Track[] = [];
60
61 for await (const item of dir.values()) {
62 if (item.kind === "file" && isAudioFile(item.name)) {
63 const uri = URI.serialize({
64 scheme: SCHEME,
65 host: rootHandleId,
66 path: `${path.length ? "/" + path.join("/") : ""}/${item.name}`,
67 });
68
69 const track: Track = {
70 id: crypto.randomUUID(),
71 uri,
72 };
73
74 tracks.push(track);
75 } else if (item.kind === "directory") {
76 const nestedItems = await recursiveList(item as FileSystemDirectoryHandle, rootHandleId, [
77 ...path,
78 item.name,
79 ]);
80
81 tracks.push(...nestedItems);
82 }
83 }
84
85 return tracks;
86}