From c94a4e5c75272904b233aaa9ee866e5fd183759c Mon Sep 17 00:00:00 2001 From: arabcoders Date: Sat, 26 Jul 2025 20:39:06 +0300 Subject: [PATCH] migrated file browser to ts --- ui/app/pages/browser/[...slug].vue | 92 ++++++++++++++++-------------- ui/app/pages/logs.vue | 31 +++++----- ui/app/stores/SocketStore.ts | 2 +- ui/app/types/filebrowser.d.ts | 20 +++++++ 4 files changed, 85 insertions(+), 60 deletions(-) create mode 100644 ui/app/types/filebrowser.d.ts diff --git a/ui/app/pages/browser/[...slug].vue b/ui/app/pages/browser/[...slug].vue index 10ebd016..c70ac7a0 100644 --- a/ui/app/pages/browser/[...slug].vue +++ b/ui/app/pages/browser/[...slug].vue @@ -192,9 +192,10 @@ - diff --git a/ui/app/pages/logs.vue b/ui/app/pages/logs.vue index c983aac1..3950f042 100644 --- a/ui/app/pages/logs.vue +++ b/ui/app/pages/logs.vue @@ -172,7 +172,7 @@ watch(() => config.app.file_logging, async v => { const filteredItems = computed(() => { const raw = query.value.trim().toLowerCase() const contextMatch = raw.match(/context:(\d+)/) - const context = contextMatch ? parseInt(contextMatch[1], 10) : 0 + const context = contextMatch ? parseInt(String(contextMatch[1]), 10) : 0 const searchTerm = raw.replace(/context:\d+/, '').trim() if (!searchTerm) { @@ -191,7 +191,7 @@ const filteredItems = computed(() => { }) Array.from(matchedIndexes).sort((a: any, b: any) => a - b).forEach((index: any) => { - result.push(logs.value[index]) + result.push(logs.value[index] as log_line) }) return result @@ -276,21 +276,20 @@ const scrollToBottom = (fast = false) => { }) } +const log_handler = (data: log_line) => { + logs.value.push(data) + + nextTick(() => { + if (autoScroll.value && bottomMarker.value) { + bottomMarker.value.scrollIntoView({ behavior: 'smooth' }) + } + }) +} + onMounted(async () => { await fetchLogs() + socket.on('log_lines', log_handler) socket.emit('subscribe', 'log_lines') - - socket.on('log_lines', (data: any) => { - logs.value.push(data) - - nextTick(() => { - if (autoScroll.value && bottomMarker.value) { - bottomMarker.value.scrollIntoView({ behavior: 'smooth' }) - } - }) - - }) - if (bg_enable.value) { document.querySelector('body')?.setAttribute("style", `opacity: 1.0`) } @@ -298,7 +297,7 @@ onMounted(async () => { onBeforeUnmount(() => { socket.emit('unsubscribe', 'log_lines') - socket.off('log_lines') + socket.off('log_lines', log_handler) if (bg_enable.value) { document.querySelector('body')?.setAttribute("style", `opacity: ${bg_opacity.value}`) } @@ -306,7 +305,7 @@ onBeforeUnmount(() => { onBeforeUnmount(() => { socket.emit('unsubscribe', 'log_lines') - socket.off('log_lines') + socket.off('log_lines', log_handler) if (scrollTimeout) clearTimeout(scrollTimeout) }) diff --git a/ui/app/stores/SocketStore.ts b/ui/app/stores/SocketStore.ts index 779a52f1..da7a668f 100644 --- a/ui/app/stores/SocketStore.ts +++ b/ui/app/stores/SocketStore.ts @@ -20,7 +20,7 @@ export const useSocketStore = defineStore('socket', () => { event.forEach(e => socket.value?.on(e, (...args) => true === withEvent ? callback(e, ...args) : callback(...args))) } - const off = (event: string | string[], callback: (...args: any[]) => void): any => { + const off = (event: string | string[], callback?: (...args: any[]) => void): any => { if (!Array.isArray(event)) { event = [event] } diff --git a/ui/app/types/filebrowser.d.ts b/ui/app/types/filebrowser.d.ts new file mode 100644 index 00000000..3bd6db03 --- /dev/null +++ b/ui/app/types/filebrowser.d.ts @@ -0,0 +1,20 @@ +type FileItem = { + type: 'file' | 'dir' | 'link' + content_type: 'image' | 'video' | 'text' | 'subtitle' | 'metadata' | 'dir' | string + name: string + path: string + size: number + mime: string + mtime: string + ctime: string + is_dir: boolean + is_file: boolean + is_symlink: boolean +} + +type FileBrowserResponse = { + path: string + contents: FileItem[] +} + +export type { FileItem, FileBrowserResponse }