2023-11-13 17:55:04 +00:00
|
|
|
import type { FileEntry, FUID, SelectedItems } from '@/repositories/Document'
|
|
|
|
import { Doc } from '@/repositories/Document'
|
|
|
|
import { defineStore } from 'pinia'
|
|
|
|
import { collator } from '@/utils'
|
|
|
|
import { logoutUser } from '@/repositories/User'
|
|
|
|
import { watchConnect } from '@/repositories/WS'
|
|
|
|
import { shallowRef } from 'vue'
|
2023-11-13 22:11:32 +00:00
|
|
|
import { sorted, type SortOrder } from '@/utils/docsort'
|
2023-11-13 17:55:04 +00:00
|
|
|
|
|
|
|
type User = {
|
|
|
|
username: string
|
|
|
|
privileged: boolean
|
|
|
|
isOpenLoginModal: boolean
|
|
|
|
isLoggedIn: boolean
|
|
|
|
}
|
|
|
|
|
|
|
|
export const useMainStore = defineStore({
|
|
|
|
id: 'main',
|
|
|
|
state: () => ({
|
|
|
|
document: shallowRef<Doc[]>([]),
|
|
|
|
selected: new Set<FUID>(),
|
2023-11-13 22:11:32 +00:00
|
|
|
query: '' as string,
|
2023-11-13 17:55:04 +00:00
|
|
|
fileExplorer: null as any,
|
|
|
|
error: '' as string,
|
|
|
|
connected: false,
|
2023-11-18 03:44:18 +00:00
|
|
|
cursor: '' as string,
|
2023-11-13 17:55:04 +00:00
|
|
|
server: {} as Record<string, any>,
|
2023-11-13 22:11:32 +00:00
|
|
|
prefs: {
|
2023-11-18 19:38:25 +00:00
|
|
|
gallery: false,
|
2023-11-13 22:11:32 +00:00
|
|
|
sortListing: '' as SortOrder,
|
|
|
|
sortFiltered: '' as SortOrder,
|
|
|
|
},
|
2023-11-13 17:55:04 +00:00
|
|
|
user: {
|
|
|
|
username: '',
|
|
|
|
privileged: false,
|
|
|
|
isLoggedIn: false,
|
|
|
|
isOpenLoginModal: false
|
|
|
|
} as User
|
|
|
|
}),
|
2023-11-13 22:11:32 +00:00
|
|
|
persist: {
|
|
|
|
paths: ['prefs'],
|
|
|
|
},
|
2023-11-13 17:55:04 +00:00
|
|
|
actions: {
|
|
|
|
updateRoot(root: FileEntry[]) {
|
|
|
|
const docs = []
|
|
|
|
let loc = [] as string[]
|
|
|
|
for (const [level, name, key, mtime, size, isfile] of root) {
|
|
|
|
loc = loc.slice(0, level - 1)
|
|
|
|
docs.push(new Doc({
|
|
|
|
name,
|
|
|
|
loc: level ? loc.join('/') : '/',
|
|
|
|
key,
|
|
|
|
size,
|
|
|
|
mtime,
|
|
|
|
dir: !isfile,
|
|
|
|
}))
|
|
|
|
loc.push(name)
|
|
|
|
}
|
|
|
|
this.document = docs
|
|
|
|
},
|
|
|
|
login(username: string, privileged: boolean) {
|
|
|
|
this.user.username = username
|
|
|
|
this.user.privileged = privileged
|
|
|
|
this.user.isLoggedIn = true
|
|
|
|
this.user.isOpenLoginModal = false
|
|
|
|
if (!this.connected) watchConnect()
|
|
|
|
},
|
|
|
|
loginDialog() {
|
|
|
|
this.user.isOpenLoginModal = true
|
|
|
|
},
|
|
|
|
async logout() {
|
|
|
|
console.log("Logout")
|
|
|
|
await logoutUser()
|
|
|
|
this.$reset()
|
|
|
|
localStorage.clear()
|
|
|
|
history.go() // Reload page
|
|
|
|
},
|
2023-11-13 22:11:32 +00:00
|
|
|
toggleSort(name: SortOrder) {
|
|
|
|
if (this.query) this.prefs.sortFiltered = this.prefs.sortFiltered === name ? '' : name
|
|
|
|
else this.prefs.sortListing = this.prefs.sortListing === name ? '' : name
|
2023-11-13 17:55:04 +00:00
|
|
|
},
|
2023-11-18 14:31:26 +00:00
|
|
|
sort(name: SortOrder | '') {
|
|
|
|
if (this.query) this.prefs.sortFiltered = name
|
|
|
|
else this.prefs.sortListing = name
|
|
|
|
},
|
2023-11-18 18:15:13 +00:00
|
|
|
focusBreadcrumb() {
|
|
|
|
(document.querySelector('.breadcrumb') as HTMLAnchorElement).focus()
|
|
|
|
}
|
2023-11-13 22:11:32 +00:00
|
|
|
},
|
|
|
|
getters: {
|
|
|
|
sortOrder(): SortOrder { return this.query ? this.prefs.sortFiltered : this.prefs.sortListing },
|
|
|
|
isUserLogged(): boolean { return this.user.isLoggedIn },
|
|
|
|
recentDocuments(): Doc[] { return sorted(this.document, 'modified') },
|
2023-11-13 17:55:04 +00:00
|
|
|
selectedFiles(): SelectedItems {
|
|
|
|
const selected = this.selected
|
|
|
|
const found = new Set<FUID>()
|
|
|
|
const ret: SelectedItems = {
|
|
|
|
missing: new Set(),
|
|
|
|
docs: {},
|
|
|
|
keys: [],
|
|
|
|
recursive: [],
|
|
|
|
}
|
|
|
|
for (const doc of this.document) {
|
|
|
|
if (selected.has(doc.key)) {
|
|
|
|
found.add(doc.key)
|
|
|
|
ret.keys.push(doc.key)
|
|
|
|
ret.docs[doc.key] = doc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// What did we not select?
|
|
|
|
for (const key of selected) if (!found.has(key)) ret.missing.add(key)
|
|
|
|
// Build a flat list including contents recursively
|
|
|
|
const relnames = new Set<string>()
|
|
|
|
function add(rel: string, full: string, doc: Doc) {
|
|
|
|
if (!doc.dir && relnames.has(rel)) throw Error(`Multiple selections conflict for: ${rel}`)
|
|
|
|
relnames.add(rel)
|
|
|
|
ret.recursive.push([rel, full, doc])
|
|
|
|
}
|
|
|
|
for (const key of ret.keys) {
|
|
|
|
const base = ret.docs[key]
|
|
|
|
const basepath = base.loc ? `${base.loc}/${base.name}` : base.name
|
|
|
|
const nremove = base.loc.length
|
|
|
|
add(base.name, basepath, base)
|
|
|
|
for (const doc of this.document) {
|
|
|
|
if (doc.loc === basepath || doc.loc.startsWith(basepath) && doc.loc[basepath.length] === '/') {
|
|
|
|
const full = doc.loc ? `${doc.loc}/${doc.name}` : doc.name
|
|
|
|
const rel = full.slice(nremove)
|
|
|
|
add(rel, full, doc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Sort by rel (name stored as on download)
|
|
|
|
ret.recursive.sort((a, b) => collator.compare(a[0], b[0]))
|
|
|
|
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|