diff options
| -rw-r--r-- | src/App.vue | 77 | ||||
| -rw-r--r-- | src/components/Tile.vue | 10 | ||||
| -rw-r--r-- | src/components/TutorialPane.vue | 33 |
3 files changed, 66 insertions, 54 deletions
diff --git a/src/App.vue b/src/App.vue index 4c37dbd..5144f50 100644 --- a/src/App.vue +++ b/src/App.vue @@ -101,6 +101,7 @@ function getDefaultUiOpts(){ // Other useReducedTree: false, jumpToSearchedNode: false, + disabledActions: new Set() as Set<Action>, }; } @@ -121,7 +122,6 @@ export default defineComponent({ settingsOpen: false, tutorialOpen: true, welcomeOpen: true, - disabledActions: new Set(), ancestryBarInTransition: false, tutTriggerAction: null as Action | null, tutTriggerFlag: false, @@ -196,9 +196,10 @@ export default defineComponent({ methods: { // For tile expand/collapse events onLeafClick(layoutNode: LayoutNode){ - if (!this.handleActionForTutorial('expand')){ + if (this.uiOpts.disabledActions.has('expand')){ return Promise.resolve(false); } + this.handleActionForTutorial('expand'); this.setLastFocused(null); // If clicking child of overflowing active-root if (this.overflownRoot){ @@ -246,9 +247,10 @@ export default defineComponent({ } }, onNonleafClick(layoutNode: LayoutNode, skipClean = false){ - if (!this.handleActionForTutorial('collapse')){ + if (this.uiOpts.disabledActions.has('collapse')){ return false; } + this.handleActionForTutorial('collapse'); this.setLastFocused(null); let success = tryLayout(this.activeRoot, [0,0], this.tileAreaDims, this.lytOpts, { allowCollapse: false, @@ -280,9 +282,10 @@ export default defineComponent({ }, // For expand-to-view and ancestry-bar events onLeafClickHeld(layoutNode: LayoutNode){ - if (!this.handleActionForTutorial('expandToView')){ + if (this.uiOpts.disabledActions.has('expandToView')){ return; } + this.handleActionForTutorial('expandToView'); this.setLastFocused(null); if (layoutNode == this.activeRoot){ this.onLeafClick(layoutNode); @@ -340,9 +343,10 @@ export default defineComponent({ } }, onNonleafClickHeld(layoutNode: LayoutNode){ - if (!this.handleActionForTutorial('expandToView')){ + if (this.uiOpts.disabledActions.has('expandToView')){ return; } + this.handleActionForTutorial('expandToView'); this.setLastFocused(null); if (layoutNode == this.activeRoot){ console.log('Ignored expand-to-view on active-root node'); @@ -362,9 +366,10 @@ export default defineComponent({ this.updateAreaDims().then(() => this.relayoutWithCollapse()); }, onDetachedAncestorClick(layoutNode: LayoutNode, alsoCollapse = false){ - if (!this.handleActionForTutorial('unhideAncestor')){ + if (this.uiOpts.disabledActions.has('unhideAncestor')){ return Promise.resolve(false); } + this.handleActionForTutorial('unhideAncestor'); this.setLastFocused(null); this.activeRoot = layoutNode; this.overflownRoot = false; @@ -387,9 +392,7 @@ export default defineComponent({ }, // For tile-info events onInfoClick(nodeName: string){ - if (!this.handleActionForTutorial('tileInfo')){ - return; - } + this.handleActionForTutorial('tileInfo'); if (!this.searchOpen){ this.resetMode(); } @@ -397,9 +400,7 @@ export default defineComponent({ }, // For search events onSearchIconClick(){ - if (!this.handleActionForTutorial('search')){ - return; - } + this.handleActionForTutorial('search'); this.resetMode(); this.searchOpen = true; }, @@ -499,9 +500,7 @@ export default defineComponent({ }, // For auto-mode events onPlayIconClick(){ - if (!this.handleActionForTutorial('autoMode')){ - return; - } + this.handleActionForTutorial('autoMode'); this.resetMode(); this.modeRunning = true; this.autoAction(); @@ -613,9 +612,7 @@ export default defineComponent({ }, // For settings events onSettingsIconClick(){ - if (!this.handleActionForTutorial('settings')){ - return; - } + this.handleActionForTutorial('settings'); this.resetMode(); this.settingsOpen = true; }, @@ -629,13 +626,18 @@ export default defineComponent({ this.initTreeFromServer(); }, onSettingsChg(changedLytOpts: Iterable<string>, changedUiOpts: Iterable<string>){ + let changed = false; for (let opt of changedLytOpts){ localStorage.setItem('lyt ' + opt, String(this.lytOpts[opt as keyof LayoutOptions])); + changed = true; } for (let opt of changedUiOpts){ localStorage.setItem('ui ' + opt, String(this.uiOpts[opt])); + changed = true; + } + if (changed){ + console.log('Settings saved'); } - console.log('Settings saved'); }, onResetSettings(){ localStorage.clear(); @@ -651,9 +653,7 @@ export default defineComponent({ }, // For help events onHelpIconClick(){ - if (!this.handleActionForTutorial('help')){ - return; - } + this.handleActionForTutorial('help'); this.resetMode(); this.helpOpen = true; }, @@ -674,7 +674,7 @@ export default defineComponent({ onTutorialClose(){ this.tutorialOpen = false; this.welcomeOpen = false; - this.disabledActions.clear(); + this.uiOpts.disabledActions.clear(); // Repeatedly relayout tiles during tutorial-pane transition this.tutPaneInTransition = true; let timerId = setInterval(() => { @@ -684,14 +684,13 @@ export default defineComponent({ } }, 100); }, - onTutStageChg(disabledActions: Set<Action>, triggerAction: Action | null){ + onTutStageChg(triggerAction: Action | null){ this.welcomeOpen = false; - this.disabledActions = disabledActions; this.tutTriggerAction = triggerAction; }, - handleActionForTutorial(action: Action): boolean { + handleActionForTutorial(action: Action){ if (!this.tutorialOpen){ - return true; + return; } // Close welcome message on first action if (this.welcomeOpen){ @@ -701,8 +700,6 @@ export default defineComponent({ if (this.tutTriggerAction == action){ this.tutTriggerFlag = !this.tutTriggerFlag; } - // Indicate whether the action is allowed - return !this.disabledActions.has(action); }, // For other events onResize(){ @@ -816,7 +813,7 @@ export default defineComponent({ return opts; }, getUiOpts(){ - let opts: {[x: string]: boolean|number|string|string[]|(string|number)[][]} = getDefaultUiOpts(); + let opts: {[x: string]: boolean|number|string|string[]|(string|number)[][]|Set<Action>} = getDefaultUiOpts(); for (let prop of Object.getOwnPropertyNames(opts)){ let item = localStorage.getItem('ui ' + prop); if (item != null){ @@ -904,20 +901,24 @@ export default defineComponent({ <div class="flex bg-black shadow"> <h1 class="text-lime-500 px-4 my-auto text-2xl">Tree of Life</h1> <!-- Icons --> - <div class="ml-auto mr-2 my-2 w-9 aspect-square p-2 rounded-full bg-lime-600 text-lime-100 - hover:brightness-125 active:brightness-125 hover:cursor-pointer" @click="onSearchIconClick"> + <div v-if="!uiOpts.disabledActions.has('search')" + class="ml-auto mr-2 my-2 w-9 aspect-square p-2 rounded-full bg-lime-600 text-lime-100 + hover:brightness-125 active:brightness-125 hover:cursor-pointer" @click="onSearchIconClick"> <search-icon/> </div> - <div class="mr-2 my-2 w-9 aspect-square p-2 rounded-full bg-lime-600 text-lime-100 - hover:brightness-125 active:brightness-125 hover:cursor-pointer" @click="onPlayIconClick"> + <div v-if="!uiOpts.disabledActions.has('autoMode')" + class="mr-2 my-2 w-9 aspect-square p-2 rounded-full bg-lime-600 text-lime-100 + hover:brightness-125 active:brightness-125 hover:cursor-pointer" @click="onPlayIconClick"> <play-icon/> </div> - <div class="mr-2 my-2 w-9 aspect-square p-2 rounded-full bg-lime-600 text-lime-100 - hover:brightness-125 active:brightness-125 hover:cursor-pointer" @click="onSettingsIconClick"> + <div v-if="!uiOpts.disabledActions.has('settings')" + class="mr-2 my-2 w-9 aspect-square p-2 rounded-full bg-lime-600 text-lime-100 + hover:brightness-125 active:brightness-125 hover:cursor-pointer" @click="onSettingsIconClick"> <settings-icon/> </div> - <div class="mr-2 my-2 w-9 aspect-square p-2 rounded-full bg-lime-600 text-lime-100 - hover:brightness-125 active:brightness-125 hover:cursor-pointer" @click="onHelpIconClick"> + <div v-if="!uiOpts.disabledActions.has('help')" + class="mr-2 my-2 w-9 aspect-square p-2 rounded-full bg-lime-600 text-lime-100 + hover:brightness-125 active:brightness-125 hover:cursor-pointer" @click="onHelpIconClick"> <help-icon/> </div> </div> diff --git a/src/components/Tile.vue b/src/components/Tile.vue index c0a9ca0..33eb62f 100644 --- a/src/components/Tile.vue +++ b/src/components/Tile.vue @@ -483,7 +483,7 @@ export default defineComponent({ @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" @mousedown="onMouseDown" @mouseup="onMouseUp"> <template v-if="!hasCompoundImage"> <h1 :style="leafHeaderStyles">{{displayName}}</h1> - <info-icon :style="infoIconStyles" + <info-icon v-if="!uiOpts.disabledActions.has('tileInfo')" :style="infoIconStyles" class="text-white/10 hover:text-white hover:cursor-pointer" @click.stop="onInfoIconClick" @mousedown.stop @mouseup.stop/> </template> @@ -491,7 +491,7 @@ export default defineComponent({ <div :style="leafFirstImgStyles" class="col-start-1 row-start-1"></div> <div :style="leafSecondImgStyles" class="col-start-1 row-start-1"></div> <h1 :style="leafHeaderStyles" class="col-start-1 row-start-1 z-10">{{displayName}}</h1> - <info-icon :style="infoIconStyles" + <info-icon v-if="!uiOpts.disabledActions.has('tileInfo')" :style="infoIconStyles" class="col-start-1 row-start-1 z-10 text-white/10 hover:text-white hover:cursor-pointer" @click.stop="onInfoIconClick" @mousedown.stop @mouseup.stop/> </template> @@ -500,7 +500,8 @@ export default defineComponent({ <div v-if="showNonleafHeader" :style="nonleafHeaderStyles" class="flex hover:cursor-pointer" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" @mousedown="onMouseDown" @mouseup="onMouseUp"> <h1 :style="nonleafHeaderTextStyles" class="grow">{{displayName}}</h1> - <info-icon :style="infoIconStyles" class="text-white/10 hover:text-white hover:cursor-pointer" + <info-icon v-if="!uiOpts.disabledActions.has('tileInfo')" + :style="infoIconStyles" class="text-white/10 hover:text-white hover:cursor-pointer" @click.stop="onInfoIconClick" @mousedown.stop @mouseup.stop/> </div> <div :style="sepSweptAreaStyles" ref="sepSweptArea" :class="sepSweptAreaHideEdgeClass"> @@ -508,7 +509,8 @@ export default defineComponent({ :style="nonleafHeaderStyles" class="flex hover:cursor-pointer" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" @mousedown="onMouseDown" @mouseup="onMouseUp"> <h1 :style="nonleafHeaderTextStyles" class="grow">{{displayName}}</h1> - <info-icon :style="infoIconStyles" class="text-white/10 hover:text-white hover:cursor-pointer" + <info-icon v-if="!uiOpts.disabledActions.has('tileInfo')" + :style="infoIconStyles" class="text-white/10 hover:text-white hover:cursor-pointer" @click.stop="onInfoIconClick" @mousedown.stop @mouseup.stop/> </div> <transition name="fadein"> diff --git a/src/components/TutorialPane.vue b/src/components/TutorialPane.vue index d34456d..5e6c1c0 100644 --- a/src/components/TutorialPane.vue +++ b/src/components/TutorialPane.vue @@ -47,37 +47,46 @@ export default defineComponent({ methods: { onStartTutorial(){ this.stage = 1; - this.sendEnabledFeatures(); + this.setEnabledFeatures(); }, onPrevClick(){ this.stage = Math.max(1, this.stage - 1); - this.sendEnabledFeatures(); + this.setEnabledFeatures(); }, onNextClick(){ this.stage = Math.min(this.maxStage, this.stage + 1); - this.sendEnabledFeatures(); + this.setEnabledFeatures(); }, onClose(){ this.$emit('close'); }, - sendEnabledFeatures(){ + setEnabledFeatures(){ const stageActions = [ null, 'expand', 'expand', 'collapse', 'expandToView', 'unhideAncestor', - 'tileInfo', 'search', 'autoMode', 'settings', 'help' + 'tileInfo', 'search', 'autoMode', 'settings', 'help', ] as (Action | null)[]; - let disabledActions = new Set() as Set<Action>; - for (let i = this.stage + 1; i < this.maxStage; i++){ - disabledActions.add(stageActions[i] as Action); + let disabledActions = this.uiOpts.disabledActions; + let currentAction = stageActions[this.stage]; + for (let i = 1; i <= this.maxStage; i++){ + let action = stageActions[i]; + if (i <= this.stage){ + if (disabledActions.has(action)){ + disabledActions.delete(action); + } + } else { + if (!disabledActions.has(action) && action != currentAction){ + disabledActions.add(action); + } + } } - disabledActions.delete(stageActions[this.stage] as Action); - let triggerAction = stageActions[this.stage] as Action; - this.$emit('stage-chg', disabledActions, triggerAction); + let triggerAction = currentAction; + this.$emit('stage-chg', triggerAction); }, }, created(){ if (this.skipWelcome){ - this.sendEnabledFeatures(); + this.setEnabledFeatures(); } }, components: {CloseIcon, RButton, }, |
