diff options
| author | Terry Truong <terry06890@gmail.com> | 2022-09-13 20:39:03 +1000 |
|---|---|---|
| committer | Terry Truong <terry06890@gmail.com> | 2022-09-13 21:34:27 +1000 |
| commit | 556d6c953e74996e0ae6a8328e352ab43735f993 (patch) | |
| tree | 465edb30070578759476bcbd56cf84ab55a00d47 /src | |
| parent | 23b5cc80ba02936659564dd03b173d3214ce5978 (diff) | |
Trigger expand/collapse-fail animation via callback
Previously, this was done by changing a LayoutNode field from
App.vue, and having TolTile watch that field
Diffstat (limited to 'src')
| -rw-r--r-- | src/App.vue | 65 | ||||
| -rw-r--r-- | src/components/TolTile.vue | 37 | ||||
| -rw-r--r-- | src/layout.ts | 2 |
3 files changed, 59 insertions, 45 deletions
diff --git a/src/App.vue b/src/App.vue index 6ed2423..01f41a2 100644 --- a/src/App.vue +++ b/src/App.vue @@ -236,7 +236,7 @@ async function reInit(){ // Collapse tree to root await onDetachedAncestorClick(layoutTree.value, true); } - await onNonleafClick(layoutTree.value, true); + await onNonleafClick(layoutTree.value, null, true); await initTreeFromServer(false); } onMounted(() => initTreeFromServer()); @@ -339,7 +339,8 @@ onMounted(() => window.addEventListener('resize', onResize)); onUnmounted(() => window.removeEventListener('resize', onResize)); // For tile expand/collapse events -async function onLeafClick(layoutNode: LayoutNode, subAction = false): Promise<boolean> { +async function onLeafClick( + layoutNode: LayoutNode, onFail: null | (() => void) = null, subAction = false): Promise<boolean> { if (!subAction && !onActionStart('expand')){ return false; } @@ -377,8 +378,8 @@ async function onLeafClick(layoutNode: LayoutNode, subAction = false): Promise<b } } // - if (!subAction && !success){ - layoutNode.failFlag = !layoutNode.failFlag; // Triggers failure animation + if (!subAction && !success && onFail != null){ + onFail(); // Triggers failure animation } nextTick(endLoadInd); return success; @@ -387,8 +388,8 @@ async function onLeafClick(layoutNode: LayoutNode, subAction = false): Promise<b let success: boolean; if (overflownRoot.value){ // If clicking child of overflowing active-root if (!uiOpts.value.autoHide){ - if (!subAction){ - layoutNode.failFlag = !layoutNode.failFlag; // Triggers failure animation + if (!subAction && onFail != null){ + onFail(); // Triggers failure animation } success = false; } else { @@ -415,7 +416,8 @@ async function onLeafClick(layoutNode: LayoutNode, subAction = false): Promise<b } return success; } -async function onNonleafClick(layoutNode: LayoutNode, subAction = false): Promise<boolean> { +async function onNonleafClick( + layoutNode: LayoutNode, onFail: null | (() => void) = null, subAction = false): Promise<boolean> { if (!subAction && !onActionStart('collapse')){ return false; } @@ -432,12 +434,14 @@ async function onNonleafClick(layoutNode: LayoutNode, subAction = false): Promis } if (!subAction){ if (!success){ - layoutNode.failFlag = !layoutNode.failFlag; // Triggers failure animation + if (onFail != null){ + onFail(); // Triggers failure animation + } } else { // Possibly clear out excess nodes when a threshold is reached let numNodes = tolMap.value.size; let extraNodes = numNodes - layoutMap.value.size; - if (extraNodes > EXCESS_TOLNODE_THRESHOLD.value){ + if (extraNodes > EXCESS_TOLNODE_THRESHOLD){ for (let n of tolMap.value.keys()){ if (!layoutMap.value.has(n)){ tolMap.value.delete(n) @@ -454,7 +458,8 @@ async function onNonleafClick(layoutNode: LayoutNode, subAction = false): Promis return success; } // For expand-to-view and ancestry-bar events -async function onLeafClickHeld(layoutNode: LayoutNode, subAction = false): Promise<boolean> { +async function onLeafClickHeld( + layoutNode: LayoutNode, onFail: null | (() => void) = null, subAction = false): Promise<boolean> { // Special case for active root if (layoutNode == activeRoot.value){ console.log('Ignored expand-to-view on active-root node'); @@ -488,8 +493,8 @@ async function onLeafClickHeld(layoutNode: LayoutNode, subAction = false): Promi } } // - if (!success && !subAction){ - layoutNode.failFlag = !layoutNode.failFlag; // Triggers failure animation + if (!success && !subAction && onFail != null){ + onFail(); // Triggers failure animation } nextTick(endLoadInd); return success; @@ -514,7 +519,8 @@ async function onLeafClickHeld(layoutNode: LayoutNode, subAction = false): Promi } return success; } -async function onNonleafClickHeld(layoutNode: LayoutNode, subAction = false): Promise<boolean> { +async function onNonleafClickHeld( + layoutNode: LayoutNode, onFail: null | (() => void) = null, subAction = false): Promise<boolean> { // Special case for active root if (layoutNode == activeRoot.value){ console.log('Ignored expand-to-view on active-root node'); @@ -555,10 +561,10 @@ async function onDetachedAncestorClick(layoutNode: LayoutNode, subAction = false if (layoutNode.children.length > 0){ success = relayoutWithCollapse(false); // Second pass for regularity } else { - success = await onLeafClick(layoutNode, true); + success = await onLeafClick(layoutNode, null, true); } } else { - success = await onNonleafClick(layoutNode, true); // For reducing tile-flashing on-screen + success = await onNonleafClick(layoutNode, null, true); // For reducing tile-flashing on-screen } LayoutNode.showDownward(layoutNode); // @@ -569,7 +575,7 @@ async function onDetachedAncestorClick(layoutNode: LayoutNode, subAction = false return success; } -// For tile-info modal/events +// For tile-info modal const infoModalNodeName = ref(null as string | null); // Name of node to display info for, or null const infoModalData = ref(null as InfoResponse | null); async function onInfoClick(nodeName: string){ @@ -593,7 +599,7 @@ function onInfoClose(){ onActionEnd('tileInfo'); } -// For search modal/events +// For search modal const searchOpen = ref(false); function onSearchIconClick(){ if (!onActionStart('search')){ @@ -666,20 +672,20 @@ async function expandToNode(name: string){ LayoutNode.hideUpward(targetNode!.parent!, layoutMap.value); activeRoot.value = targetNode!.parent!; updateAreaDims(); - await onNonleafClick(activeRoot.value, true); - await onLeafClick(activeRoot.value, true); + await onNonleafClick(activeRoot.value, null, true); + await onLeafClick(activeRoot.value, null, true); } else { - await onLeafClick(activeRoot.value, true); + await onLeafClick(activeRoot.value, null, true); } setTimeout(() => expandToNode(name), uiOpts.value.transitionDuration); return; } if (overflownRoot.value){ - await onLeafClickHeld(layoutNode, true); + await onLeafClickHeld(layoutNode, null, true); setTimeout(() => expandToNode(name), uiOpts.value.transitionDuration); return; } - let success = await onLeafClick(layoutNode, true); + let success = await onLeafClick(layoutNode, null, true); if (success){ setTimeout(() => expandToNode(name), uiOpts.value.transitionDuration); return; @@ -696,7 +702,7 @@ async function expandToNode(name: string){ ancestorChain.push(layoutNode); } layoutNode = ancestorChain[Math.floor((ancestorChain.length - 1) / 2)] - await onNonleafClickHeld(layoutNode, true); + await onNonleafClickHeld(layoutNode, null, true); setTimeout(() => expandToNode(name), uiOpts.value.transitionDuration); } function onSearchClose(){ @@ -820,13 +826,13 @@ async function autoAction(){ setLastFocused(node.parent!); break; case 'expand': - success = await onLeafClick(node, true); + success = await onLeafClick(node, null, true); break; case 'collapse': - success = await onNonleafClick(node, true); + success = await onNonleafClick(node, null, true); break; case 'expandToView': - success = await onNonleafClickHeld(node, true); + success = await onNonleafClickHeld(node, null, true); break; case 'unhideAncestor': success = await onDetachedAncestorClick(node.parent!, true); @@ -846,7 +852,7 @@ function onAutoClose(){ onActionEnd('autoMode'); } -// For settings modal/events +// For settings modal const settingsOpen = ref(false); function onSettingsIconClick(){ if (!onActionStart('settings')){ @@ -884,7 +890,7 @@ function onResetSettings(reinit: boolean){ } } -// For help modal/events +// For help modal const helpOpen = ref(false); function onHelpIconClick(){ if (!onActionStart('help')){ @@ -898,13 +904,12 @@ function onHelpClose(){ onActionEnd('help'); } -// For tutorial pane/events +// For tutorial pane const tutPaneOpen = ref(!uiOpts.value.tutorialSkip); const tutWelcome = ref(!uiOpts.value.tutorialSkip); const tutTriggerAction = ref(null as Action | null); // Used to advance tutorial upon user-actions const tutTriggerFlag = ref(false); const actionsDone = ref(new Set() as Set<Action>); // Used to avoid disabling actions the user has already seen -// For tutorial-pane events function onStartTutorial(){ if (!tutPaneOpen.value){ tutPaneOpen.value = true; diff --git a/src/components/TolTile.vue b/src/components/TolTile.vue index d3b3539..810c5b7 100644 --- a/src/components/TolTile.vue +++ b/src/components/TolTile.vue @@ -165,14 +165,22 @@ function onClick(): void { return; } wasClicked.value = true; - emit(isLeaf.value ? 'leaf-click' : 'nonleaf-click', props.layoutNode); + if (isLeaf.value){ + emit('leaf-click', props.layoutNode, onExpandFail); + } else { + emit('nonleaf-click', props.layoutNode, onCollapseFail); + } } function onClickHold(): void { if (isLeaf.value && !isExpandableLeaf.value){ console.log('Ignored click-hold on non-expandable node'); return; } - emit(isLeaf.value ? 'leaf-click-held' : 'nonleaf-click-held', props.layoutNode); + if (isLeaf.value){ + emit('leaf-click-held', props.layoutNode, onExpandFail); + } else { + emit('nonleaf-click-held', props.layoutNode, onCollapseFail); + } } function onDblClick(): void { onClickHold(); @@ -181,19 +189,19 @@ function onInfoIconClick(): void { emit('info-click', props.layoutNode.name); } // Child click-action propagation -function onInnerLeafClick(node: LayoutNode): void { +function onInnerLeafClick(node: LayoutNode, onFail: () => void): void { wasClicked.value = true; - emit('leaf-click', node); + emit('leaf-click', node, onFail); } -function onInnerNonleafClick(node: LayoutNode): void { +function onInnerNonleafClick(node: LayoutNode, onFail: () => void): void { wasClicked.value = true; - emit('nonleaf-click', node); + emit('nonleaf-click', node, onFail); } -function onInnerLeafClickHeld(node: LayoutNode): void { - emit('leaf-click-held', node); +function onInnerLeafClickHeld(node: LayoutNode, onFail: () => void): void { + emit('leaf-click-held', node, onFail); } -function onInnerNonleafClickHeld(node: LayoutNode): void { - emit('nonleaf-click-held', node); +function onInnerNonleafClickHeld(node: LayoutNode, onFail: () => void): void { + emit('nonleaf-click-held', node, onFail); } function onInnerInfoIconClick(nodeName: string): void { emit('info-click', nodeName); @@ -265,9 +273,12 @@ function triggerAnimation(animation: string){ el.offsetWidth; // Triggers reflow el.classList.add(animation); } -watch(() => props.layoutNode.failFlag, () => - triggerAnimation(isLeaf.value ? 'animate-expand-shrink' : 'animate-shrink-expand') -); +function onExpandFail(){ + triggerAnimation('animate-expand-shrink'); +} +function onCollapseFail(){ + triggerAnimation('animate-shrink-expand'); +} // For 'flashing' the tile when focused const inFlash = ref(false); // Used to 'flash' the tile when focused diff --git a/src/layout.ts b/src/layout.ts index ec5b70c..140af77 100644 --- a/src/layout.ts +++ b/src/layout.ts @@ -27,7 +27,6 @@ export class LayoutNode { hidden: boolean; // Used to hide nodes upon an expand-to-view hiddenWithVisibleTip: boolean; hasFocus: boolean; // Used by search and auto-mode to mark/flash a tile - failFlag: boolean; // Used to trigger failure animations // Constructor ('parent' are 'depth' are generally initialised later, 'tips' is computed) constructor(name: string, children: LayoutNode[]){ this.name = name; @@ -45,7 +44,6 @@ export class LayoutNode { this.hidden = false; this.hiddenWithVisibleTip = false; this.hasFocus = false; - this.failFlag = false; } // Returns a new tree with the same structure and names // 'chg' is usable to apply a change to the resultant tree |
