Fetch remote files when not in indexeddb

This commit is contained in:
Magnus Åhall 2026-06-26 14:07:26 +02:00
parent f3ca7b9a44
commit 6df2be7944
6 changed files with 153 additions and 36 deletions

View file

@ -1,4 +1,5 @@
import { CustomHTMLElement } from "./lib/custom_html_element.mjs";
import { API } from 'api'
export class N2File extends CustomHTMLElement {
static {// {{{
@ -34,6 +35,9 @@ export class N2File extends CustomHTMLElement {
constructor() {// {{{
super(true)
this.file = null
this.uuid = null
this.addEventListener('click', event => {
event.preventDefault()
event.stopPropagation()
@ -45,16 +49,34 @@ export class N2File extends CustomHTMLElement {
}
// Open in browser.
window.open(
URL.createObjectURL(this.file),
event.ctrlKey ? '_blank' : '_self',
)
this.openInBrowser(event)
})
this.render()
}// }}}
openInBrowser(event) {
// this.file is only defined when file is stored in IndexedDB.
if (this.file)
window.open(
URL.createObjectURL(this.file),
event.ctrlKey ? '_blank' : '_self',
)
else {
const jwt = localStorage.getItem('token')
window.open(
`/file/${this.uuid}?jwt=${jwt}`,
event.ctrlKey ? '_blank' : '_self',
)
}
}
async downloadToDisk() {// {{{
try {
// this.file is only defined when file is stored in IndexedDB.
// TODO: implement download of remote content.
if (this.file === null)
throw new Error('This file is only available online. Download not implemented yet.')
const handle = await window.showSaveFilePicker({
suggestedName: this.file.name,
})
@ -78,26 +100,61 @@ export class N2File extends CustomHTMLElement {
// while Marked lib has to be returned a string when exiting this function.
// populateImg makes sure this returned img element exists and then populates it
// with the image from IndexedDB.
const file = await globalThis.nodeStore.files.get(src.slice(5))
if (!file)
return
this.file = file.file
const fileUUID = src.slice(5)
this.uuid = fileUUID
const file = await globalThis.nodeStore.files.get(fileUUID)
if (file.file.type.startsWith('image/'))
this.elImage.src = URL.createObjectURL(file.file)
else {
// Check for and use an existing MIME type icon.
// Place them in static/images/file_icons/ and replace the slash with an underscore.
const url = `/images/${_VERSION}/file_icons/${file.file.type.replaceAll('/', '_')}.svg`
const res = await fetch(url)
if (res.ok)
this.elImage.src = url
this.elFilename.innerText = file.file.name
this.elFilename.style.display = 'block'
if (file) {
this.renderLocalFile(file)
} else {
/* <file> can be undefined when a node is retrieved but files aren't synced.
* Try to show from server.
*
* Metadata is needed to know whether to display an image or the file representation. */
try {
const res = await API.query('GET', `/file/${fileUUID}/metadata`)
this.renderRemoteFile(res.Metadata)
} catch (err) {
console.error(err)
}
}
} else
// Probably an external URL.
this.elImage.src = src
}// }}}
async renderLocalFile(file) {// {{{
this.file = file.file
if (file.file.type.startsWith('image/'))
this.elImage.src = URL.createObjectURL(file.file)
else {
// Check for and use an existing MIME type icon.
// Place them in static/images/file_icons/ and replace the slash with an underscore.
const url = `/images/${_VERSION}/file_icons/${file.file.type.replaceAll('/', '_')}.svg`
const res = await fetch(url)
if (res.ok)
this.elImage.src = url
this.elFilename.innerText = file.file.name
this.elFilename.style.display = 'block'
}
}// }}}
async renderRemoteFile(md) {// {{{
if (md.Type.startsWith('image/')) {
const jwt = localStorage.getItem('token')
this.elImage.src = `/file/${md.UUID}?jwt=${jwt}`
} else {
// Check for and use an existing MIME type icon.
// Place them in static/images/file_icons/ and replace the slash with an underscore.
const url = `/images/${_VERSION}/file_icons/${md.Type.replaceAll('/', '_')}.svg`
const res = await fetch(url)
if (res.ok)
this.elImage.src = url
this.elFilename.innerText = md.Name
this.elFilename.style.display = 'block'
}
}// }}}
}
customElements.define('n2-file', N2File)