More caching, first tree navigation with up/down.
This commit is contained in:
parent
0bd5d08edf
commit
82f09dcb1d
8 changed files with 317 additions and 151 deletions
|
|
@ -47,7 +47,10 @@ export class Notes2 extends Component {
|
|||
this.setState({ startNode: node })
|
||||
})
|
||||
}//}}}
|
||||
async goToNode(nodeUUID, dontPush) {//{{{
|
||||
async goToNode(nodeUUID, dontPush, dontExpand) {//{{{
|
||||
if (nodeUUID === null || nodeUUID === undefined)
|
||||
return
|
||||
|
||||
// Don't switch notes until saved.
|
||||
if (this.nodeUI.current.nodeModified.value) {
|
||||
if (!confirm("Changes not saved. Do you want to discard changes?"))
|
||||
|
|
@ -63,7 +66,7 @@ export class Notes2 extends Component {
|
|||
const ancestors = await nodeStore.getNodeAncestry(node)
|
||||
this.nodeUI.current.setNode(node)
|
||||
this.nodeUI.current.setCrumbs(ancestors)
|
||||
this.tree.setSelected(node)
|
||||
this.tree.setSelected(node, dontExpand)
|
||||
}//}}}
|
||||
logout() {//{{{
|
||||
localStorage.removeItem('session.UUID')
|
||||
|
|
@ -79,6 +82,7 @@ class Tree extends Component {
|
|||
this.treeTrunk = []
|
||||
this.selectedNode = null
|
||||
this.expandedNodes = {} // keyed on UUID
|
||||
this.treeDiv = createRef()
|
||||
|
||||
this.props.app.tree = this
|
||||
|
||||
|
|
@ -90,12 +94,17 @@ class Tree extends Component {
|
|||
return html`<${TreeNode} key=${`treenode_${node.UUID}`} tree=${this} node=${node} ref=${this.treeNodeComponents[node.UUID]} selected=${node.UUID === app.state.startNode?.UUID} />`
|
||||
})
|
||||
return html`
|
||||
<div id="tree">
|
||||
<div id="tree" ref=${this.treeDiv} tabindex="0">
|
||||
<div id="logo" onclick=${() => _notes2.current.goToNode(ROOT_NODE)}><img src="/images/${_VERSION}/logo.svg" /></div>
|
||||
<div class="icons">
|
||||
<img src="/images/${_VERSION}/icon_refresh.svg" />
|
||||
</div>
|
||||
${renderedTreeTrunk}
|
||||
</div>`
|
||||
}//}}}
|
||||
componentDidMount() {//{{{
|
||||
this.treeDiv.current.addEventListener('keydown', event => this.keyHandler(event))
|
||||
|
||||
// This will show and select the treenode that is selected in the node UI.
|
||||
const node = _notes2.current?.nodeUI.current?.node.value
|
||||
if (node === null)
|
||||
|
|
@ -105,14 +114,14 @@ class Tree extends Component {
|
|||
}//}}}
|
||||
|
||||
populateFirstLevel(callback = null) {//{{{
|
||||
nodeStore.getTreeNodes('', 0)
|
||||
.then(async res => {
|
||||
res.sort(Node.sort)
|
||||
nodeStore.get(ROOT_NODE)
|
||||
.then(node => node.fetchChildren())
|
||||
.then(children => {
|
||||
this.treeNodeComponents = {}
|
||||
this.treeTrunk = []
|
||||
for (const node of res) {
|
||||
for (const node of children) {
|
||||
// The root node isn't supposed to be shown in the tree.
|
||||
if (node.UUID === '00000000-0000-0000-0000-000000000000')
|
||||
if (node.UUID === ROOT_NODE)
|
||||
continue
|
||||
if (node.ParentUUID === '')
|
||||
this.treeTrunk.push(node)
|
||||
|
|
@ -124,7 +133,7 @@ class Tree extends Component {
|
|||
})
|
||||
.catch(e => { console.log(e); console.log(e.type, e.error); alert(e.error) })
|
||||
}//}}}
|
||||
setSelected(node) {//{{{
|
||||
setSelected(node, dontExpand) {//{{{
|
||||
// The previously selected node, if any, needs to be rerendered
|
||||
// to not retain its 'selected' class.
|
||||
const prevUUID = this.selectedNode?.UUID
|
||||
|
|
@ -135,8 +144,8 @@ class Tree extends Component {
|
|||
// And now the newly selected node is rerendered.
|
||||
this.treeNodeComponents[node.UUID]?.current.forceUpdate()
|
||||
|
||||
// Expanding selected nodes... I don't know...
|
||||
this.setNodeExpanded(node.UUID, true)
|
||||
if (!dontExpand)
|
||||
this.setNodeExpanded(node.UUID, true)
|
||||
}//}}}
|
||||
isSelected(node) {//{{{
|
||||
return this.selectedNode?.UUID === node.UUID
|
||||
|
|
@ -154,7 +163,7 @@ class Tree extends Component {
|
|||
return
|
||||
|
||||
// Start the chain of by expanding the top node.
|
||||
this.setNodeExpanded(ancestry[ancestry.length-1].UUID, true)
|
||||
this.setNodeExpanded(ancestry[ancestry.length - 1].UUID, true)
|
||||
}//}}}
|
||||
getNodeExpanded(UUID) {//{{{
|
||||
if (this.expandedNodes[UUID] === undefined)
|
||||
|
|
@ -166,6 +175,95 @@ class Tree extends Component {
|
|||
this.getNodeExpanded(UUID)
|
||||
this.expandedNodes[UUID].value = value
|
||||
}//}}}
|
||||
getParentNodeWithNextSibling(node) {//{{{
|
||||
let currNode = node
|
||||
while (currNode !== null && currNode.UUID !== ROOT_NODE && currNode.getSiblingAfter() === null) {
|
||||
currNode = currNode.getParent()
|
||||
}
|
||||
return currNode?.getSiblingAfter()
|
||||
}//}}}
|
||||
|
||||
async keyHandler(event) {//{{{
|
||||
let handled = true
|
||||
let nodeExpanded = false
|
||||
let siblingBefore = null
|
||||
let siblingExpanded = false
|
||||
let parent = null
|
||||
const n = this.selectedNode
|
||||
|
||||
switch (event.key) {
|
||||
case 'j':
|
||||
case 'ArrowDown':
|
||||
nodeExpanded = this.getNodeExpanded(n.UUID)
|
||||
|
||||
// Last node, not expanded, so it matters not whether it has children or not.
|
||||
// Traverse upward to nearest parent with next sibling.
|
||||
if (!nodeExpanded && n.isLastSibling()) {
|
||||
const wantedNode = this.getParentNodeWithNextSibling(n)
|
||||
if (wantedNode?.UUID === ROOT_NODE)
|
||||
break
|
||||
await _notes2.current.goToNode(wantedNode?.UUID, true, true)
|
||||
break
|
||||
}
|
||||
|
||||
if (nodeExpanded && n.isLastSibling() && !n.hasChildren()) {
|
||||
const wantedNode = this.getParentNodeWithNextSibling(n)
|
||||
await _notes2.current.goToNode(wantedNode?.UUID, true, true)
|
||||
break
|
||||
}
|
||||
// Node not expanded. Go to this node's next sibling.
|
||||
// GoToNode will abort if given null.
|
||||
if (!nodeExpanded || !n.hasChildren()) {
|
||||
await _notes2.current.goToNode(n.getSiblingAfter()?.UUID, true, true)
|
||||
break
|
||||
}
|
||||
|
||||
// Node is expanded.
|
||||
// Children will be visually beneath this node, if any.
|
||||
if (nodeExpanded && n.hasChildren()) {
|
||||
await _notes2.current.goToNode(n.Children[0].UUID, true, true)
|
||||
break
|
||||
}
|
||||
break
|
||||
|
||||
case 'k':
|
||||
case 'ArrowUp':
|
||||
siblingBefore = n.getSiblingBefore()
|
||||
if (siblingBefore !== null)
|
||||
siblingExpanded = this.getNodeExpanded(siblingBefore.UUID)
|
||||
|
||||
if (n.isFirstSibling()) {
|
||||
parent = n.getParent()
|
||||
if (parent?.UUID === ROOT_NODE)
|
||||
break
|
||||
await _notes2.current.goToNode(parent?.UUID, true, true)
|
||||
break
|
||||
}
|
||||
|
||||
if (siblingBefore !== null && siblingExpanded && siblingBefore.hasChildren()) {
|
||||
await _notes2.current.goToNode(siblingBefore.Children[siblingBefore.Children.length - 1]?.UUID, true, true)
|
||||
break
|
||||
}
|
||||
|
||||
if (siblingBefore) {
|
||||
await _notes2.current.goToNode(siblingBefore.UUID, true, true)
|
||||
break
|
||||
}
|
||||
break
|
||||
|
||||
case 'h':
|
||||
case 'ArrowLeft':
|
||||
break
|
||||
|
||||
default:
|
||||
handled = false
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
}//}}}
|
||||
}
|
||||
|
||||
class TreeNode extends Component {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue