Fetch remote files when not in indexeddb
This commit is contained in:
parent
f3ca7b9a44
commit
6df2be7944
6 changed files with 153 additions and 36 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -597,7 +597,6 @@ class FileNodesLinkStore extends SimpleNodeStore {
|
|||
// Maintains an index to quickly find orphaned files.
|
||||
nodelink.NodeCount = nodelink.Nodes.length
|
||||
|
||||
console.log('removing', nodelink)
|
||||
await this.add({data: nodelink})
|
||||
}
|
||||
}// }}}
|
||||
|
|
@ -620,7 +619,6 @@ class FileNodesLinkStore extends SimpleNodeStore {
|
|||
// Maintains an index to quickly find orphaned files.
|
||||
nodelink.NodeCount = nodelink.Nodes.length
|
||||
|
||||
console.log('pushing', nodelink)
|
||||
await this.add({data: nodelink})
|
||||
}
|
||||
}// }}}
|
||||
|
|
|
|||
|
|
@ -549,7 +549,6 @@ export class Node {
|
|||
if (this.UUID == ROOT_NODE)
|
||||
return
|
||||
|
||||
|
||||
// File links from the original, unmodified content are found to compare to links from the new content.
|
||||
// All files (images) needs to be indexed to nodes in order to track orphaned files.
|
||||
const before = new Set([...this.data.Content.matchAll(dblink)].map(m => m[1]))
|
||||
|
|
|
|||
|
|
@ -11,16 +11,20 @@ const CACHED_ASSETS = [
|
|||
|
||||
'/images/{{ .VERSION }}/collapsed.svg',
|
||||
'/images/{{ .VERSION }}/expanded.svg',
|
||||
'/images/{{ .VERSION }}/icon_back.svg',
|
||||
'/images/{{ .VERSION }}/icon_history.svg',
|
||||
'/images/{{ .VERSION }}/icon_home.svg',
|
||||
'/images/{{ .VERSION }}/icon_markdown_hollow.svg',
|
||||
'/images/{{ .VERSION }}/icon_markdown.svg',
|
||||
'/images/{{ .VERSION }}/icon_menu.svg',
|
||||
'/images/{{ .VERSION }}/icon_new_document.svg',
|
||||
'/images/{{ .VERSION }}/icon_refresh.svg',
|
||||
'/images/{{ .VERSION }}/icon_save_disabled.svg',
|
||||
'/images/{{ .VERSION }}/icon_save.svg',
|
||||
'/images/{{ .VERSION }}/icon_search.svg',
|
||||
'/images/{{ .VERSION }}/icon_settings.svg',
|
||||
'/images/{{ .VERSION }}/icon_table.svg',
|
||||
'/images/{{ .VERSION }}/icon_transfer.svg',
|
||||
'/images/{{ .VERSION }}/leaf.svg',
|
||||
'/images/{{ .VERSION }}/logo_small.svg',
|
||||
'/images/{{ .VERSION }}/logo.svg',
|
||||
|
|
@ -42,6 +46,7 @@ const CACHED_ASSETS = [
|
|||
'/js/{{ .VERSION }}/notes2.mjs',
|
||||
'/js/{{ .VERSION }}/page_history.mjs',
|
||||
'/js/{{ .VERSION }}/page_node.mjs',
|
||||
'/js/{{ .VERSION }}/page_preferences.mjs',
|
||||
'/js/{{ .VERSION }}/page_storage.mjs',
|
||||
'/js/{{ .VERSION }}/sidebar.mjs',
|
||||
'/js/{{ .VERSION }}/sync.mjs',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue