fix update detection for filebrowser

AuthorKonata <konata@posteo.jp>
Date
Commit5d1a3a9df1109c5d2a801a117b032fc8d0e7665b
Parent3382d74
2 files changed, 20 insertions(+), 16 deletions(-)
▾Mwebclient/src/components/FileBrowser.tsx
@@ -6,7 +6,6 @@ import {
createSignal,
For,
type InitializedResource,
mapArray,
on,
onMount,
type ResourceActions,
@@ -14,7 +13,7 @@ import {
Show,
Suspense,
} from "solid-js";
import type { MediaFile, FileListing } from "music-server-shared/types";
import type { MediaFile, FileListing, Directory } from "music-server-shared/types";
import type { AppOptions, PlaylistItem } from "../types";
import { generateUUID, joinPath, LocalStorageValues } from "../utils";
import { ClosedFolderSVG, DownSVG, MusicSVG, RefreshSVG, UpSVG } from "./SVG";
@@ -178,9 +177,15 @@ export default function FileBrowser(props: FileBrowserProps) {
});
});
//needed to only apply diff, and allow files.refetech to not cause full rerenders
//this proxy store allows us to diff changes correctly when the filelisting changes, only rerendering the changed items
//absolute paths are required here to make sure it's really the same file in the same directory
const [fileStore, setFileStore] = createStore<FlatFileListing>([]);
createEffect(() => setFileStore(reconcile(props.files.latest)));
createEffect(() => {
const absolutePathArray = props.files.latest.map(([name, item]) => {
return [joinPath(props.currentDir(), name), item] as [string, Directory | MediaFile];
});
setFileStore(reconcile(absolutePathArray, { key: "0" }));
});
return (
<>
@@ -260,13 +265,10 @@ export default function FileBrowser(props: FileBrowserProps) {
</Show>
<div class="file-list" ref={filelistElement}>
{/* for some reason neither <For> nor <Index> seems to cache the input files correctly
either causing full rerenders or only updating the length, and newly added items, not changes ones */}
{mapArray(
() => fileStore,
([fileName, item]) => {
<For each={fileStore}>
{([fullPath, item]) => {
const isDirectory = !("metadata" in item);
const fullPath = joinPath(props.currentDir(), fileName);
const fileName = fullPath.split("/").toReversed()[0];
return (
<>
<div
@@ -302,8 +304,8 @@ export default function FileBrowser(props: FileBrowserProps) {
</div>
</>
);
},
)()}
}}
</For>
</div>
</div>
<Show when={!props.options.hideCover && (cover.loading || cover())}>
▾Mwebclient/src/offline.ts
@@ -205,11 +205,12 @@ function fullyKnown(dir: DirectoryWithStatus) {
//non-recursive listing should not include nested children
function pruneChildren(listing: FileListing) {
const cloned = structuredClone(listing);
for (const [, item] of cloned.entries()) {
if ("files" in item) item.files.clear();
const pruned = new Map();
for (const [name, item] of listing.entries()) {
if ("metadata" in item) pruned.set(name, item);
else pruned.set(name, { files: new Map() });
}
return cloned;
return pruned;
}
//used for combining the online and offline results, to be able to show files that only exist locally
@@ -237,6 +238,7 @@ function combineFileListings(listing1: FileListing, listing2: FileListing): File
export async function listFiles(dir: string, offline: boolean, recursive: boolean): Promise<FileListing> {
if (offline) {
const files = listOfflineFiles(dir);
console.log(recursive ? files : pruneChildren(files))
return recursive ? files : pruneChildren(files);
}
const cached = getDirInTree(dir, false, false);