Refactoring Document storage (#5)

- Major refactoring that makes Doc a class with properties
- Data made only shallow reactive, for a good speedup of initial load
- Minor bugfixes and UX improvements along the way
- Fixed handling of hash and question marks in URLs (was confusing Vue Router)
- Search made stricter to find good results (not ignore all punctuation)

Reviewed-on: #5
This commit is contained in:
Leo Vasanko
2023-11-13 17:52:57 +00:00
parent dc4bb494f3
commit 41e8c78ecd
15 changed files with 141 additions and 248 deletions

View File

@@ -1,17 +1,42 @@
import { formatSize, formatUnixDate, haystackFormat } from "@/utils"
export type FUID = string
export type Document = {
export type DocProps = {
loc: string
name: string
key: FUID
size: number
sizedisp: string
mtime: number
modified: string
haystack: string
dir: boolean
}
export class Doc {
private _name: string = ""
public loc: string = ""
public key: FUID = ""
public size: number = 0
public mtime: number = 0
public haystack: string = ""
public dir: boolean = false
constructor(props: Partial<DocProps> = {}) { Object.assign(this, props) }
get name() { return this._name }
set name(name: string) {
if (name.includes('/') || name.startsWith('.')) throw Error(`Invalid name: ${name}`)
this._name = name
this.haystack = haystackFormat(name)
}
get sizedisp(): string { return formatSize(this.size) }
get modified(): string { return formatUnixDate(this.mtime) }
get url(): string {
const p = this.loc ? `${this.loc}/${this.name}` : this.name
return this.dir ? '/#/' + `${p}/`.replaceAll('#', '%23') : `/files/${p}`.replaceAll('?', '%3F').replaceAll('#', '%23')
}
get urlrouter(): string {
return this.url.replace(/^\/#/, '')
}
}
export type errorEvent = {
error: {
code: number
@@ -36,7 +61,7 @@ export type UpdateEntry = ['k', number] | ['d', number] | ['i', Array<FileEntry>
// Helper structure for selections
export interface SelectedItems {
keys: FUID[]
docs: Record<FUID, Document>
recursive: Array<[string, string, Document]>
docs: Record<FUID, Doc>
recursive: Array<[string, string, Doc]>
missing: Set<FUID>
}

View File

@@ -1,4 +1,4 @@
import { useDocumentStore } from "@/stores/documents"
import { useMainStore } from "@/stores/main"
import type { FileEntry, UpdateEntry, errorEvent } from "./Document"
export const controlUrl = '/api/control'
@@ -12,7 +12,7 @@ let wsWatch = null as WebSocket | null
export const loadSession = () => {
const s = localStorage['cista-files']
if (!s) return false
const store = useDocumentStore()
const store = useMainStore()
try {
tree = JSON.parse(s)
store.updateRoot(tree)
@@ -39,7 +39,7 @@ export const watchConnect = () => {
clearTimeout(watchTimeout)
watchTimeout = null
}
const store = useDocumentStore()
const store = useMainStore()
if (store.error !== 'Reconnecting...') store.error = 'Connecting...'
console.log(store.error)
@@ -81,7 +81,7 @@ export const watchDisconnect = () => {
let watchTimeout: any = null
const watchReconnect = (event: MessageEvent) => {
const store = useDocumentStore()
const store = useMainStore()
if (store.connected) {
console.warn("Disconnected from server", event)
store.connected = false
@@ -114,7 +114,7 @@ const handleWatchMessage = (event: MessageEvent) => {
}
function handleRootMessage({ root }: { root: FileEntry[] }) {
const store = useDocumentStore()
const store = useMainStore()
console.log('Watch root', root)
store.updateRoot(root)
tree = root
@@ -122,7 +122,7 @@ function handleRootMessage({ root }: { root: FileEntry[] }) {
}
function handleUpdateMessage(updateData: { update: UpdateEntry[] }) {
const store = useDocumentStore()
const store = useMainStore()
const update = updateData.update
console.log('Watch update', update)
if (!tree) return console.error('Watch update before root')
@@ -146,7 +146,7 @@ function handleUpdateMessage(updateData: { update: UpdateEntry[] }) {
}
function handleError(msg: errorEvent) {
const store = useDocumentStore()
const store = useMainStore()
if (msg.error.code === 401) {
store.user.isOpenLoginModal = true
store.user.isLoggedIn = false