Implement background worker to make search response faster and avoid hanging the UI when there are a lot of files. Implement better toast messages for transitional events that automatically disappear.

This commit is contained in:
2026-01-31 21:02:16 +00:00
parent 1a164e0a08
commit 1970d40d8a
8 changed files with 305 additions and 41 deletions
+77 -1
View File
@@ -4,14 +4,30 @@ import { defineStore, type StateTree } from 'pinia'
import { collator } from '@/utils'
import { watchConnect, resumeWatching } from '@/repositories/WS'
import { sorted, type SortOrder } from '@/utils/docsort'
import SearchWorker from '@/workers/searchWorker?worker'
// Singleton search worker instance
let searchWorker: Worker | null = null
let searchId = 0
function getSearchWorker(): Worker {
if (!searchWorker) {
searchWorker = new SearchWorker()
}
return searchWorker
}
export const useMainStore = defineStore('main', {
state: () => ({
document: [] as Doc[],
selected: new Set<FUID>([]),
query: '' as string,
searchResults: [] as Doc[],
searchLoading: false,
fileExplorer: null as any,
error: '' as string,
error: '' as string, // Permanent status message (e.g., "Reconnecting...")
toast: '' as string, // Temporary toast (auto-dismisses)
toastTimeout: null as ReturnType<typeof setTimeout> | null,
connected: false,
authInProgress: false,
cursor: '' as string,
@@ -61,6 +77,66 @@ export const useMainStore = defineStore('main', {
loc.push(name)
}
this.document = docs
// Sync documents to search worker
this.syncSearchWorker()
},
/** Show a temporary toast message that auto-dismisses */
showToast(message: string, duration = 3000) {
if (this.toastTimeout) {
clearTimeout(this.toastTimeout)
this.toastTimeout = null
}
this.toast = message
this.toastTimeout = setTimeout(() => {
this.toast = ''
this.toastTimeout = null
}, duration)
},
/** Clear the current toast immediately */
clearToast() {
if (this.toastTimeout) {
clearTimeout(this.toastTimeout)
this.toastTimeout = null
}
this.toast = ''
},
syncSearchWorker() {
const worker = getSearchWorker()
// Send plain data to worker (no class instances)
const docData = this.document.map(doc => ({
loc: doc.loc,
name: doc.name,
key: doc.key,
size: doc.size,
mtime: doc.mtime,
dir: doc.dir,
}))
worker.postMessage({ type: 'update', documents: docData })
},
search(query: string, loc: string) {
const worker = getSearchWorker()
const id = ++searchId
if (!query) {
this.searchResults = []
this.searchLoading = false
return
}
this.searchLoading = true
worker.onmessage = (e) => {
if (e.data.id !== searchId) return // Stale result
// Convert plain data back to Doc instances
this.searchResults = e.data.docs.map((d: any) => new Doc(d))
if (e.data.done) {
this.searchLoading = false
}
}
worker.postMessage({ type: 'search', query, loc, id })
},
login(username: string, privileged: boolean) {
this.user.username = username