diff --git a/static/js/app.mjs b/static/js/app.mjs
index 16dab2b..45cd85b 100644
--- a/static/js/app.mjs
+++ b/static/js/app.mjs
@@ -6,13 +6,13 @@ import { Node } from 'node'
export class App {
constructor() {// {{{
this.currentNode = null
- this.treeNative = new N2Tree()
+ this.tree = new N2Tree()
this.crumbs = new N2Crumbs()
this.crumbsElement = document.getElementById('crumbs')
this.nodeUI = document.getElementById('note')
_mbus.subscribe('TREE_TRUNK_FETCHED', async () => {
- document.getElementById('tree').append(this.treeNative.render())
+ document.getElementById('tree').append(this.tree.render())
document.getElementById('tree-nodes')?.focus()
const startNode = await this.getStartNode()
@@ -188,7 +188,7 @@ export class App {
node.reset() // any modifications are discarded.
this.currentNode = node
- this.treeNative.setSelected(node, dontExpand)
+ this.tree.setSelected(node, dontExpand)
const ancestors = await nodeStore.getNodeAncestry(node)
_mbus.dispatch('CRUMBS_SET', ancestors, () => this.crumbsElement.replaceChildren(this.crumbs.render()))
@@ -196,7 +196,7 @@ export class App {
_mbus.dispatch('NODE_UNMODIFIED')
// Scrolls node into view.
- this.treeNative.makeVisible(node)
+ this.tree.makeVisible(node)
}//}}}
}
diff --git a/static/js/node.mjs b/static/js/node.mjs
index 949724c..d611c64 100644
--- a/static/js/node.mjs
+++ b/static/js/node.mjs
@@ -54,7 +54,7 @@ export class Node {
if (a.data.Name > b.data.Name) return 0
return 0
}//}}}
- static create(name, parentUUID) {
+ static create(name, parentUUID) {// {{{
return new Node({
UUID: uuidv7(),
Created: (new Date()).toISOString(),
@@ -64,7 +64,7 @@ export class Node {
Markdown: false,
History: false,
})
- }
+ }// }}}
constructor(nodeData, level) {//{{{
@@ -123,9 +123,6 @@ export class Node {
return this._children_fetched
}//}}}
async fetchChildren() {//{{{
- if (this._children_fetched)
- return this.Children
-
this.Children = await nodeStore.getTreeNodes(this.UUID, this.Level + 1)
this._children_fetched = true
diff --git a/static/js/node_store.mjs b/static/js/node_store.mjs
index 98642d1..e849e29 100644
--- a/static/js/node_store.mjs
+++ b/static/js/node_store.mjs
@@ -159,6 +159,7 @@ export class NodeStore {
})
}//}}}
+ /*
upsertNodeRecords(records) {//{{{
return new Promise((resolve, reject) => {
const t = this.db.transaction('nodes', 'readwrite')
@@ -187,16 +188,10 @@ export class NodeStore {
record.modified = 0
addReq = nodeStore.put(record)
}
- addReq.onsuccess = () => {
- console.debug(`${op} ${record.UUID} (${record.Name})`)
- }
- addReq.onerror = (event) => {
- console.log(`error ${op} ${record.UUID}`, event.target.error)
- reject(event.target.error)
- }
}
})
}//}}}
+ */
getTreeNodes(parent, newLevel) {//{{{
return new Promise((resolve, reject) => {
// Parent of toplevel nodes is ROOT_NODE in indexedDB.
@@ -219,7 +214,7 @@ export class NodeStore {
req.onerror = (event) => reject(event.target.error)
})
}//}}}
- async search(searchfor, parent) {//{{{
+ search(searchfor, parent) {//{{{
return new Promise((resolve, reject) => {
const trx = this.db.transaction('nodes', 'readonly')
const nodeStore = trx.objectStore('nodes')
@@ -249,43 +244,55 @@ export class NodeStore {
})
}//}}}
- add(records) {//{{{
+ add(records, objstore) {//{{{
return new Promise((resolve, reject) => {
try {
- const t = this.db.transaction('nodes', 'readwrite')
- const nodeStore = t.objectStore('nodes')
- t.onerror = (event) => {
- console.error('transaction error', event.target.error)
- reject(event.target.error)
+ // A nodestore can be provided in order to
+ // avoid creating new transactions.
+ let nodeStore = objstore
+ let t
+
+ if (nodeStore === undefined) {
+ t = this.db.transaction('nodes', 'readwrite')
+ nodeStore = t.objectStore('nodes')
+
+ t.oncomplete = (_event) => {
+ resolve()
+ }
+
+ t.onerror = (event) => {
+ console.error('transaction error', event.target.error)
+ reject(event.target.error)
+ }
}
// records is an object, not an array.
- const promises = []
for (const recordIdx in records) {
const record = records[recordIdx]
- const addReq = nodeStore.put(record.data)
-
- const promise = new Promise((resolve, reject) => {
- addReq.onsuccess = () => resolve()
- addReq.onerror = (event) => {
- console.error('Error!', event.target.error, record.ID)
- reject(event.target.error)
- }
- })
- promises.push(promise)
+ nodeStore.put(record.data)
}
- Promise.all(promises).then(() => resolve())
+ resolve()
} catch (e) {
- console.log(e)
+ console.error(e)
+ reject(e)
}
})
}//}}}
- get(uuid) {//{{{
+ get(uuid, suppliedNodestore) {//{{{
return new Promise((resolve, reject) => {
- const trx = this.db.transaction('nodes', 'readonly')
- const nodeStore = trx.objectStore('nodes')
+ // A nodestore can be provided in order to
+ // avoid creating new transactions.
+ let trx
+ let nodeStore = suppliedNodestore
+
+ if (nodeStore === undefined) {
+ trx = this.db.transaction('nodes', 'readonly')
+ nodeStore = trx.objectStore('nodes')
+ }
+
const getRequest = nodeStore.get(uuid)
+
getRequest.onsuccess = (event) => {
// Node not found in IndexedDB.
if (event.target.result === undefined) {
@@ -328,6 +335,9 @@ export class NodeStore {
})
}//}}}
+ newTransaction(objectStore, mode) {// {{{
+ return this.db.transaction(objectStore, mode)
+ }// }}}
nodeCount() {//{{{
return new Promise((resolve, reject) => {
diff --git a/static/js/sync.mjs b/static/js/sync.mjs
index fd606f3..9b58cf7 100644
--- a/static/js/sync.mjs
+++ b/static/js/sync.mjs
@@ -65,9 +65,16 @@ export class Sync {
* sync be preserved in the backend. */
let backendNode = null
+
+ // Create a single transaction to be used in the chain of
+ // this sync. Otherwise it would take more time to create
+ // transactions for each node.
+ const trx = nodeStore.newTransaction('nodes', 'readwrite')
+ const objstore = trx.objectStore('nodes')
+
for (const i in res.Nodes) {
backendNode = new Node(res.Nodes[i], -1)
- await window._sync.handleNode(backendNode)
+ await this.handleNode(backendNode, objstore)
handled++
if (handled % 100 === 0)
@@ -88,16 +95,16 @@ export class Sync {
}
return (syncEnd - syncStart)
}//}}}
- async handleNode(backendNode) {//{{{
+ async handleNode(backendNode, objstore) {//{{{
try {
/* Retrieving the local copy of this node from IndexedDB.
* The backend node can be discarded if it is older than
* the local copy since it is considered history preserved
* in the backend. */
- return nodeStore.get(backendNode.UUID)
- .then(async localNode => {
+ return nodeStore.get(backendNode.UUID, objstore)
+ .then(localNode => {
if (localNode.updated() >= backendNode.updated()) {
- console.log(`History from backend: ${backendNode.UUID}`)
+ console.debug(`History from backend: ${backendNode.UUID}`)
return
}
@@ -107,12 +114,12 @@ export class Sync {
*
* If the local node has seen change, the change is already
* placed into the send_queue anyway. */
- return nodeStore.add([backendNode])
+ return nodeStore.add([backendNode], objstore)
})
- .catch(async () => {
+ .catch(() => {
// Not found in IndexedDB - OK to just insert since it only exists in backend.
- return nodeStore.add([backendNode])
+ return nodeStore.add([backendNode], objstore)
})
} catch (e) {
console.error(e)
@@ -198,10 +205,7 @@ export class N2SyncProgress extends CustomHTMLElement {
break
// Reload the tree nodes to reflect the new/updated nodes.
- if (window._notes2?.current?.reloadTree.value !== null) {
- nodeStore.purgeCache()
- window._notes2.current.reloadTree.value = window._notes2.current.reloadTree.value + 1
- }
+ window._app.tree.reset()
break
}
this.render()
diff --git a/static/js/tree.mjs b/static/js/tree.mjs
index d7a11ee..1da5dee 100644
--- a/static/js/tree.mjs
+++ b/static/js/tree.mjs
@@ -10,6 +10,7 @@ export class N2Tree extends CustomHTMLElement {
+