aboutsummaryrefslogtreecommitdiff
path: root/src/components/SettingsModal.vue
diff options
context:
space:
mode:
authorTerry Truong <terry06890@gmail.com>2022-09-14 19:17:41 +1000
committerTerry Truong <terry06890@gmail.com>2022-09-14 20:29:01 +1000
commit8b5538e0a55a83b1ff190cd5ad689827777e73a7 (patch)
tree33ccb2eadbe9a53dc2a870d57ba5efe758592390 /src/components/SettingsModal.vue
parent556d6c953e74996e0ae6a8328e352ab43735f993 (diff)
Use Pinia to store user settings, palette colors, etc
Move uiOpts and lytOpts to store.ts Add 'const's to *.ts
Diffstat (limited to 'src/components/SettingsModal.vue')
-rw-r--r--src/components/SettingsModal.vue192
1 files changed, 83 insertions, 109 deletions
diff --git a/src/components/SettingsModal.vue b/src/components/SettingsModal.vue
index df8444f..a55dc41 100644
--- a/src/components/SettingsModal.vue
+++ b/src/components/SettingsModal.vue
@@ -9,19 +9,19 @@
<h2 class="font-bold md:text-xl text-center pt-1 md:pt-2 md:pb-1">Timing</h2>
<div class="grid grid-cols-[130px_minmax(0,1fr)_65px] gap-1 px-2 md:px-3">
<!-- Row 1 -->
- <label for="animTimeInput" @click="onReset('UI', 'transitionDuration')" :class="rLabelClasses">
+ <label for="animTimeInput" @click="onResetOne('transitionDuration')" :class="rLabelClasses">
Animation Time
</label>
- <input type="range" min="0" max="1000" v-model.number="uiOpts.transitionDuration"
- @change="onSettingChg('UI', 'transitionDuration')" class="my-auto" name="animTimeInput"/>
- <div class="my-auto text-right">{{uiOpts.transitionDuration}} ms</div>
+ <input type="range" min="0" max="1000" v-model.number="store.transitionDuration"
+ @change="onSettingChg('transitionDuration')" class="my-auto" name="animTimeInput"/>
+ <div class="my-auto text-right">{{store.transitionDuration}} ms</div>
<!-- Row 2 -->
- <label for="autoDelayInput" @click="onReset('UI', 'autoActionDelay')" :class="rLabelClasses">
+ <label for="autoDelayInput" @click="onResetOne('autoActionDelay')" :class="rLabelClasses">
Auto-mode Delay
</label>
- <input type="range" min="100" max="1000" v-model.number="uiOpts.autoActionDelay"
- @change="onSettingChg('UI', 'autoActionDelay')" class="my-auto" name="autoDelayInput"/>
- <div class="my-auto text-right">{{uiOpts.autoActionDelay}} ms</div>
+ <input type="range" min="300" max="2000" v-model.number="store.autoActionDelay"
+ @change="onSettingChg('autoActionDelay')" class="my-auto" name="autoDelayInput"/>
+ <div class="my-auto text-right">{{store.autoActionDelay}} ms</div>
</div>
</div>
<div class="pb-2" :class="borderBClasses">
@@ -31,49 +31,49 @@
<div>Sweep leaves left</div>
<ul>
<li> <label> <input type="radio" v-model="sweepLeaves" :value="true"
- @change="onSettingChg('LYT', 'layoutType')"/> Yes </label> </li>
+ @change="onSettingChg('lytOpts.layoutType')"/> Yes </label> </li>
<li> <label> <input type="radio" v-model="sweepLeaves" :value="false"
- @change="onSettingChg('LYT', 'layoutType')"/> No </label> </li>
+ @change="onSettingChg('lytOpts.layoutType')"/> No </label> </li>
</ul>
</div>
<div>
<div>Sweep into parent</div>
<ul>
- <li> <label> <input type="radio" :disabled="!sweepLeaves" v-model="lytOpts.sweepToParent"
- value="none" @change="onSettingChg('LYT', 'sweepToParent')"/> Never </label> </li>
- <li> <label> <input type="radio" :disabled="!sweepLeaves" v-model="lytOpts.sweepToParent"
- value="prefer" @change="onSettingChg('LYT', 'sweepToParent')"/> Always </label> </li>
- <li> <label> <input type="radio" :disabled="!sweepLeaves" v-model="lytOpts.sweepToParent"
- value="fallback" @change="onSettingChg('LYT', 'sweepToParent')"/> If needed </label> </li>
+ <li> <label> <input type="radio" :disabled="!sweepLeaves" v-model="store.lytOpts.sweepToParent"
+ value="none" @change="onSettingChg('lytOpts.sweepToParent')"/> Never </label> </li>
+ <li> <label> <input type="radio" :disabled="!sweepLeaves" v-model="store.lytOpts.sweepToParent"
+ value="prefer" @change="onSettingChg('lytOpts.sweepToParent')"/> Always </label> </li>
+ <li> <label> <input type="radio" :disabled="!sweepLeaves" v-model="store.lytOpts.sweepToParent"
+ value="fallback" @change="onSettingChg('lytOpts.sweepToParent')"/> If needed </label> </li>
</ul>
</div>
</div>
<div class="grid grid-cols-[100px_minmax(0,1fr)_65px] gap-1 w-fit mx-auto px-2 md:px-3">
<!-- Row 1 -->
- <label for="minTileSizeInput" @click="onReset('LYT', 'minTileSz')" :class="rLabelClasses">
+ <label for="minTileSizeInput" @click="onResetOne('lytOpts.minTileSz')" :class="rLabelClasses">
Min Tile Size
</label>
<input type="range"
- min="15" :max="uiOpts.breakpoint == 'sm' ? 150 : 200" v-model.number="lytOpts.minTileSz"
- @input="onSettingChgThrottled('LYT', 'minTileSz')" @change="onSettingChg('LYT', 'minTileSz')"
+ min="15" :max="store.breakpoint == 'sm' ? 150 : 200" v-model.number="store.lytOpts.minTileSz"
+ @input="onSettingChgThrottled('lytOpts.minTileSz')" @change="onSettingChg('lytOpts.minTileSz')"
name="minTileSizeInput" ref="minTileSzRef"/>
- <div class="my-auto text-right">{{lytOpts.minTileSz}} px</div>
+ <div class="my-auto text-right">{{store.lytOpts.minTileSz}} px</div>
<!-- Row 2 -->
- <label for="maxTileSizeInput" @click="onReset('LYT', 'maxTileSz')" :class="rLabelClasses">
+ <label for="maxTileSizeInput" @click="onResetOne('lytOpts.maxTileSz')" :class="rLabelClasses">
Max Tile Size
</label>
- <input type="range" min="15" max="400" v-model.number="lytOpts.maxTileSz"
- @input="onSettingChgThrottled('LYT', 'maxTileSz')" @change="onSettingChg('LYT', 'maxTileSz')"
+ <input type="range" min="15" max="400" v-model.number="store.lytOpts.maxTileSz"
+ @input="onSettingChgThrottled('lytOpts.maxTileSz')" @change="onSettingChg('lytOpts.maxTileSz')"
name="maxTileSizeInput" ref="maxTileSzRef"/>
- <div class="my-auto text-right">{{lytOpts.maxTileSz}} px</div>
+ <div class="my-auto text-right">{{store.lytOpts.maxTileSz}} px</div>
<!-- Row 3 -->
- <label for="tileSpacingInput" @click="onReset('LYT', 'tileSpacing')" :class="rLabelClasses">
+ <label for="tileSpacingInput" @click="onResetOne('lytOpts.tileSpacing')" :class="rLabelClasses">
Tile Spacing
</label>
- <input type="range" min="0" max="20" v-model.number="lytOpts.tileSpacing"
- @input="onSettingChgThrottled('LYT', 'tileSpacing')" @change="onSettingChg('LYT', 'tileSpacing')"
+ <input type="range" min="0" max="20" v-model.number="store.lytOpts.tileSpacing"
+ @input="onSettingChgThrottled('lytOpts.tileSpacing')" @change="onSettingChg('lytOpts.tileSpacing')"
name="tileSpacingInput"/>
- <div class="my-auto text-right">{{lytOpts.tileSpacing}} px</div>
+ <div class="my-auto text-right">{{store.lytOpts.tileSpacing}} px</div>
</div>
</div>
<div class="pb-2 px-2 md:px-3" :class="borderBClasses">
@@ -81,29 +81,29 @@
<div>
Tree to use
<ul class="flex justify-evenly">
- <li> <label> <input type="radio" v-model="uiOpts.tree" value="trimmed"
- @change="onSettingChg('UI', 'tree')"/> Complex </label> </li>
- <li> <label> <input type="radio" v-model="uiOpts.tree" value="images"
- @change="onSettingChg('UI', 'tree')"/> Visual </label> </li>
- <li> <label> <input type="radio" v-model="uiOpts.tree" value="picked"
- @change="onSettingChg('UI', 'tree')"/> Minimal </label> </li>
+ <li> <label> <input type="radio" v-model="store.tree" value="trimmed"
+ @change="onSettingChg('tree')"/> Complex </label> </li>
+ <li> <label> <input type="radio" v-model="store.tree" value="images"
+ @change="onSettingChg('tree')"/> Visual </label> </li>
+ <li> <label> <input type="radio" v-model="store.tree" value="picked"
+ @change="onSettingChg('tree')"/> Minimal </label> </li>
</ul>
</div>
<div>
- <label> <input type="checkbox" v-model="uiOpts.searchJumpMode"
- @change="onSettingChg('UI', 'searchJumpMode')"/> Skip search animation </label>
+ <label> <input type="checkbox" v-model="store.searchJumpMode"
+ @change="onSettingChg('searchJumpMode')"/> Skip search animation </label>
</div>
<div>
- <label> <input type="checkbox" v-model="uiOpts.autoHide"
- @change="onSettingChg('UI', 'autoHide')"/> Auto-hide ancestors </label>
+ <label> <input type="checkbox" v-model="store.autoHide"
+ @change="onSettingChg('autoHide')"/> Auto-hide ancestors </label>
</div>
- <div v-if="uiOpts.touchDevice == false">
- <label> <input type="checkbox" v-model="uiOpts.disableShortcuts"
- @change="onSettingChg('UI', 'disableShortcuts')"/> Disable keyboard shortcuts </label>
+ <div v-if="store.touchDevice == false">
+ <label> <input type="checkbox" v-model="store.disableShortcuts"
+ @change="onSettingChg('disableShortcuts')"/> Disable keyboard shortcuts </label>
</div>
</div>
- <s-button class="mx-auto my-2" :style="{color: uiOpts.textColor, backgroundColor: uiOpts.bgColor}"
- @click="onResetAll">
+ <s-button class="mx-auto my-2" :style="{color: store.color.text, backgroundColor: store.color.bg}"
+ @click="onReset">
Reset
</s-button>
<transition name="fade">
@@ -114,11 +114,10 @@
</template>
<script setup lang="ts">
-import {ref, computed, watch, PropType} from 'vue';
+import {ref, computed, watch} from 'vue';
import SButton from './SButton.vue';
import CloseIcon from './icon/CloseIcon.vue';
-import {UiOptions, OptionType, getDefaultLytOpts, getDefaultUiOpts} from '../lib';
-import {LayoutOptions} from '../layout';
+import {useStore, StoreState} from '../store';
// Refs
const rootRef = ref(null as HTMLDivElement | null);
@@ -127,37 +126,36 @@ const minTileSzRef = ref(null as HTMLInputElement | null);
const maxTileSzRef = ref(null as HTMLInputElement | null);
const saveIndRef = ref(null as HTMLDivElement | null);
-// Props + events
-const props = defineProps({
- lytOpts: {type: Object as PropType<LayoutOptions>, required: true},
- uiOpts: {type: Object as PropType<UiOptions>, required: true},
-});
-const emit = defineEmits(['close', 'setting-chg', 'reset', ]);
+// Global store
+const store = useStore();
-// For settings
-const sweepLeaves = ref(props.lytOpts.layoutType == 'sweep');
- // For making only two of 'layoutType's values available for user selection)
-watch(sweepLeaves, (newVal) => {props.lytOpts.layoutType = newVal ? 'sweep' : 'rect'})
+// Events
+const emit = defineEmits(['close', 'setting-chg', 'reset']);
+
+// For making only two of 'layoutType's values available for user selection)
+const sweepLeaves = ref(store.lytOpts.layoutType == 'sweep');
+watch(sweepLeaves, (newVal) => {store.lytOpts.layoutType = newVal ? 'sweep' : 'rect'})
// Settings change handling
const saved = ref(false); // Set to true after a setting is saved
-const settingChgTimeout = ref(0); // Used to throttle some setting-change handling
-function onSettingChg(optionType: OptionType, option: string){
+let settingChgTimeout = 0; // Used to throttle some setting-change handling
+function onSettingChg(option: string){
// Maintain min/max-tile-size consistency
- if (optionType == 'LYT' && (option == 'minTileSz' || option == 'maxTileSz')){
+ if (option == 'lytOpts.minTileSz' || option == 'lytOpts.maxTileSz'){
let minInput = minTileSzRef.value!;
let maxInput = maxTileSzRef.value!;
- if (option == 'minTileSz' && Number(minInput.value) > Number(maxInput.value)){
- props.lytOpts.maxTileSz = props.lytOpts.minTileSz;
- emit('setting-chg', 'LYT', 'maxTileSz');
- } else if (option == 'maxTileSz' && Number(maxInput.value) < Number(minInput.value)){
- props.lytOpts.minTileSz = props.lytOpts.maxTileSz;
- emit('setting-chg', 'LYT', 'minTileSz');
+ if (Number(minInput.value) > Number(maxInput.value)){
+ if (option == 'lytOpts.minTileSz'){
+ store.lytOpts.maxTileSz = store.lytOpts.minTileSz;
+ emit('setting-chg', 'lytOpts.maxTileSz');
+ } else {
+ store.lytOpts.minTileSz = store.lytOpts.maxTileSz;
+ emit('setting-chg', 'lytOpts.minTileSz');
+ }
}
}
- // Notify parent component
- emit('setting-chg', optionType, option,
- {relayout: optionType == 'LYT', reinit: optionType == 'UI' && option == 'tree'});
+ // Notify parent (might need to relayout)
+ emit('setting-chg', option);
// Possibly make saved-indicator appear/animate
if (!saved.value){
saved.value = true;
@@ -168,48 +166,24 @@ function onSettingChg(optionType: OptionType, option: string){
el.classList.add('animate-flash-green');
}
}
-function onSettingChgThrottled(optionType: OptionType, option: string){
- if (settingChgTimeout.value == 0){
- settingChgTimeout.value = setTimeout(() => {
- settingChgTimeout.value = 0;
- onSettingChg(optionType, option);
- }, props.uiOpts.animationDelay);
+function onSettingChgThrottled(option: string){
+ if (settingChgTimeout == 0){
+ settingChgTimeout = setTimeout(() => {
+ settingChgTimeout = 0;
+ onSettingChg(option);
+ }, store.animationDelay);
}
}
-function onReset(optionType: OptionType, option: string){
- // Restore the setting's default
- let defaultLytOpts = getDefaultLytOpts();
- let defaultUiOpts = getDefaultUiOpts(defaultLytOpts);
- if (optionType == 'LYT'){
- let lytOpt = option as keyof LayoutOptions;
- if (props.lytOpts[lytOpt] == defaultLytOpts[lytOpt]){
- return;
- }
- (props.lytOpts[lytOpt] as any) = defaultLytOpts[lytOpt];
- if (option == 'layoutType'){
- sweepLeaves.value = props.lytOpts.layoutType == 'sweep';
- }
- } else {
- let uiOpt = option as keyof UiOptions;
- if (props.uiOpts[uiOpt] == defaultUiOpts[uiOpt]){
- return;
- }
- (props.uiOpts[uiOpt] as any) = defaultUiOpts[uiOpt];
+function onResetOne(option: string){
+ store.resetOne(option);
+ if (option == 'lytOpts.layoutType'){
+ sweepLeaves.value = (store.lytOpts.layoutType == 'sweep');
}
- // Notify parent component
- onSettingChg(optionType, option);
+ onSettingChg(option);
}
-function onResetAll(){
- // Restore default options
- let defaultLytOpts = getDefaultLytOpts();
- let defaultUiOpts = getDefaultUiOpts(defaultLytOpts);
- let needReinit = props.uiOpts.tree != defaultUiOpts.tree;
- Object.assign(props.lytOpts, defaultLytOpts);
- Object.assign(props.uiOpts, defaultUiOpts);
- // Notify parent component
- emit('reset', needReinit);
- // Clear saved-indicator
- saved.value = false;
+function onReset(){
+ emit('reset'); // Notify parent (might need to relayout)
+ saved.value = false; // Clear saved-indicator
}
// Close handling
@@ -221,9 +195,9 @@ function onClose(evt: Event){
// Styles and classes
const styles = computed(() => ({
- backgroundColor: props.uiOpts.bgColorAlt,
- borderRadius: props.uiOpts.borderRadius + 'px',
- boxShadow: props.uiOpts.shadowNormal,
+ backgroundColor: store.color.bgAlt,
+ borderRadius: store.borderRadius + 'px',
+ boxShadow: store.shadowNormal,
}));
const borderBClasses = 'border-b border-stone-400';
const rLabelClasses = "w-fit hover:cursor-pointer hover:text-lime-600"; // For reset-upon-click labels