Manual server file uploads implemented

This commit is contained in:
Magnus Åhall 2026-06-26 08:31:54 +02:00
parent c8308664d3
commit 70b5285e16
10 changed files with 329 additions and 26 deletions

View file

@ -15,12 +15,13 @@ export class NodeStore {
this.sendQueue = null
this.nodesHistory = null
this.files = null
this.filesMetadata = null
this.initializeSpecialNodes()
}//}}}
initializeDB() {//{{{
return new Promise((resolve, reject) => {
const req = indexedDB.open('notes', 8)
const req = indexedDB.open('notes', 10)
// Schema upgrades for IndexedDB.
// These can start from different points depending on updates to Notes2 since a device was online.
@ -71,6 +72,14 @@ export class NodeStore {
case 8:
files = db.createObjectStore('files', { keyPath: 'UUID' })
break
case 9:
db.createObjectStore('files_metadata', { keyPath: 'UUID' })
break
case 10:
trx.objectStore('files_metadata').createIndex('byUploaded', 'uploaded', { unique: false })
break
}
}
}
@ -80,6 +89,7 @@ export class NodeStore {
this.sendQueue = new SimpleNodeStore(this.db, 'send_queue')
this.nodesHistory = new NodeHistoryStore(this.db, 'nodes_history')
this.files = new SimpleNodeStore(this.db, 'files')
this.filesMetadata = new SimpleNodeStore(this.db, 'files_metadata')
resolve()
}
@ -332,6 +342,56 @@ export class NodeStore {
}
})
}//}}}
async storeFile(file) {// {{{
const metadata = new FileMetadata(file, {})
await this.files.add({ data: { UUID: metadata.UUID, file } })
await this.filesMetadata.add({ data: metadata })
return metadata
}// }}}
nextFileToSync() {// {{{
return new Promise((resolve, reject) => {
const req = this.db
.transaction('files_metadata', 'readonly')
.objectStore('files_metadata')
.index('byUploaded')
.get('only_on_device')
req.onerror = (e) => reject(e)
req.onsuccess = (e) => {
const data = e.target.result
// No more files to sync.
if (data === undefined) {
resolve({ file: null, metadata: null })
return
}
// Retrieve file as well.
const filereq = this.db.
transaction('files', 'readonly')
.objectStore('files')
.get(data.UUID)
filereq.onsuccess = (e) => {
const f = e.target.result
// File should always be in IndexedDB when metadata is.
if (f === undefined) {
reject(new Error(`File with UUID '${data.UUID}' is missing.`))
return
}
resolve({
file: f.file,
metadata: new FileMetadata(f.file, data),
})
}
}
})
}// }}}
}
class SimpleNodeStore {
@ -351,7 +411,6 @@ class SimpleNodeStore {
// Node to be moved is first stored in the new queue.
const req = store.put(node.data)
req.onsuccess = () => {
console.log('here')
resolve()
}
req.onerror = (event) => {
@ -539,4 +598,29 @@ export function uuidv7() {// {{{
return `${str.slice(0, 8)}-${str.slice(8, 12)}-${str.slice(12, 16)}-${str.slice(16, 20)}-${str.slice(20)}`
}// }}}
class FileMetadata {
constructor(file, data) {// {{{
this.UUID = data.UUID || uuidv7()
this.uploaded = data.uploaded || 'only_on_device'
this.name = file.name
this.size = file.size
this.type = file.type || 'application/octet-stream'
this.modified = file.lastModified
}// }}}
setUploaded() {// {{{
this.uploaded = 'on_server'
}// }}}
get data() {// {{{
return {
UUID: this.UUID,
uploaded: this.uploaded,
name: this.name,
size: this.size,
type: this.type,
modified: this.modified,
}
}// }}}
}
// vim: foldmethod=marker