fix(core): refresh file listing when the device queue drains

File operations are pushed onto the device's command queue and run
asynchronously, but FileBrowser only re-listed the directory when dev,
path, or updateIndex changed -- and updateIndex was only ever bumped by
a breadcrumb click. The listing stayed stale after an upload, delete,
rename, or directory creation.

Watch the device's running flag and queue length, and re-list on the
busy -> idle transition so a multi-file delete refreshes once at the end
rather than per queued command. The refresh is silent: it skips the
loading flag so the current icons stay on screen instead of flashing the
spinner, and keeps the old listing if the re-fetch fails.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-07-22 17:05:04 -04:00
parent f2c2844079
commit 6219e03c35

View file

@ -52,8 +52,10 @@ const selected = ref<FileInfo[]>([]);
const files = ref<FileInfo[] | null>(null);
const loading = ref(false);
async function loadFiles() {
loading.value = true;
// `silent` keeps the current listing on screen while re-fetching, so the
// refresh after a queued operation doesn't flash the loading spinner.
async function loadFiles(silent = false) {
if (!silent) loading.value = true;
try {
const contents = await devices.listDir(props.dev, path.value);
files.value = contents.map((file) => ({
@ -62,13 +64,27 @@ async function loadFiles() {
}));
} catch (e) {
console.error(e);
files.value = null;
if (!silent) files.value = null;
} finally {
loading.value = false;
}
}
watch([() => props.dev, path, updateIndex], loadFiles, {immediate: true});
watch([() => props.dev, path, updateIndex], () => loadFiles(), {immediate: true});
// File operations (upload, delete, rename, create directory) are pushed onto
// the device's command queue and run asynchronously, so the listing on screen
// is stale by the time they finish. Re-list once the queue drains.
const busy = computed(() => {
const device = devices.devices[props.dev];
if (!device) return false;
return !!device.running || !!device.queue?.length;
});
watch(busy, (isBusy, wasBusy) => {
// FileView resets its own selection when the new listing arrives.
if (wasBusy && !isBusy) loadFiles(true);
});
watch(path, () => {
selected.value = [];