Prebuild lookup structures to reduce UI lag on very large file lists.
This commit is contained in:
@@ -98,7 +98,7 @@ const uploadCloudFiles = (files: CloudFile[]) => {
|
|||||||
files.sort((a, b) => collator.compare(a.cloudName, b.cloudName))
|
files.sort((a, b) => collator.compare(a.cloudName, b.cloudName))
|
||||||
// Optimistic update: ghost folders and files
|
// Optimistic update: ghost folders and files
|
||||||
const now = Math.floor(Date.now() / 1000)
|
const now = Math.floor(Date.now() / 1000)
|
||||||
const byPath = new Map(store.document.map(d => [d.loc ? `${d.loc}/${d.name}` : d.name, d]))
|
const byPath = store.docsByPath
|
||||||
const added = new Set<string>()
|
const added = new Set<string>()
|
||||||
for (const f of files) {
|
for (const f of files) {
|
||||||
const lastSlash = f.cloudName.lastIndexOf('/')
|
const lastSlash = f.cloudName.lastIndexOf('/')
|
||||||
|
|||||||
@@ -269,6 +269,24 @@ export const useMainStore = defineStore('main', {
|
|||||||
sortOrder(): SortOrder { return this.query ? this.prefs.sortFiltered : this.prefs.sortListing },
|
sortOrder(): SortOrder { return this.query ? this.prefs.sortFiltered : this.prefs.sortListing },
|
||||||
isUserLogged(): boolean { return this.user.isLoggedIn },
|
isUserLogged(): boolean { return this.user.isLoggedIn },
|
||||||
recentDocuments(): Doc[] { return sorted(this.document, 'modified') },
|
recentDocuments(): Doc[] { return sorted(this.document, 'modified') },
|
||||||
|
/** Set of all full paths - for O(1) existence checks */
|
||||||
|
pathSet(): Set<string> {
|
||||||
|
return new Set(this.document.map(d => d.loc ? `${d.loc}/${d.name}` : d.name))
|
||||||
|
},
|
||||||
|
/** Map from location to documents in that folder - for O(1) folder listing */
|
||||||
|
docsByLoc(): Map<string, Doc[]> {
|
||||||
|
const map = new Map<string, Doc[]>()
|
||||||
|
for (const doc of this.document) {
|
||||||
|
const arr = map.get(doc.loc)
|
||||||
|
if (arr) arr.push(doc)
|
||||||
|
else map.set(doc.loc, [doc])
|
||||||
|
}
|
||||||
|
return map
|
||||||
|
},
|
||||||
|
/** Map from full path to Doc - for O(1) path lookup */
|
||||||
|
docsByPath(): Map<string, Doc> {
|
||||||
|
return new Map(this.document.map(d => [d.loc ? `${d.loc}/${d.name}` : d.name, d]))
|
||||||
|
},
|
||||||
selectedFiles(): SelectedItems {
|
selectedFiles(): SelectedItems {
|
||||||
const selected = this.selected
|
const selected = this.selected
|
||||||
const found = new Set<FUID>()
|
const found = new Set<FUID>()
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import { useMainStore } from '@/stores/main'
|
|||||||
|
|
||||||
export const exists = (path: string[]) => {
|
export const exists = (path: string[]) => {
|
||||||
const store = useMainStore()
|
const store = useMainStore()
|
||||||
const p = path.join('/')
|
return store.pathSet.has(path.join('/'))
|
||||||
return store.document.some(doc => (doc.loc ? `${doc.loc}/${doc.name}` : doc.name) === p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Strip file extension intelligently (handles .tar.gz, name.with.dots.pdf, etc.) */
|
/** Strip file extension intelligently (handles .tar.gz, name.with.dots.pdf, etc.) */
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ const documents = computed(() => {
|
|||||||
|
|
||||||
// List the current location (no search)
|
// List the current location (no search)
|
||||||
if (!query) return sorted(
|
if (!query) return sorted(
|
||||||
store.document.filter(doc => doc.loc === loc),
|
store.docsByLoc.get(loc) ?? [],
|
||||||
store.prefs.sortListing,
|
store.prefs.sortListing,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user