feat: persistent menuActive state with Local Storage (#3011)
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/3011 Reviewed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
This commit is contained in:
commit
e3dd4ef78a
@ -86,9 +86,6 @@ function showKeyboardShortcuts() {
|
|||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
// hide menu on mobile
|
|
||||||
watch(() => route.fullPath, () => window.innerWidth < 769 && baseStore.setMenuActive(false))
|
|
||||||
|
|
||||||
// FIXME: this is really error prone
|
// FIXME: this is really error prone
|
||||||
// Reset the current list highlight in menu if the current route is not list related.
|
// Reset the current list highlight in menu if the current route is not list related.
|
||||||
watch(() => route.name as string, (routeName) => {
|
watch(() => route.name as string, (routeName) => {
|
||||||
|
@ -146,7 +146,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, computed, onMounted, onBeforeMount} from 'vue'
|
import {ref, computed, onBeforeMount} from 'vue'
|
||||||
import draggable from 'zhyswan-vuedraggable'
|
import draggable from 'zhyswan-vuedraggable'
|
||||||
import type {SortableEvent} from 'sortablejs'
|
import type {SortableEvent} from 'sortablejs'
|
||||||
|
|
||||||
@ -159,7 +159,6 @@ import Logo from '@/components/home/Logo.vue'
|
|||||||
import {calculateItemPosition} from '@/helpers/calculateItemPosition'
|
import {calculateItemPosition} from '@/helpers/calculateItemPosition'
|
||||||
import {getNamespaceTitle} from '@/helpers/getNamespaceTitle'
|
import {getNamespaceTitle} from '@/helpers/getNamespaceTitle'
|
||||||
import {getListTitle} from '@/helpers/getListTitle'
|
import {getListTitle} from '@/helpers/getListTitle'
|
||||||
import {useEventListener} from '@vueuse/core'
|
|
||||||
import type {IList} from '@/modelTypes/IList'
|
import type {IList} from '@/modelTypes/IList'
|
||||||
import type {INamespace} from '@/modelTypes/INamespace'
|
import type {INamespace} from '@/modelTypes/INamespace'
|
||||||
import ColorBubble from '@/components/misc/colorBubble.vue'
|
import ColorBubble from '@/components/misc/colorBubble.vue'
|
||||||
@ -200,17 +199,8 @@ const namespaceListsCount = computed(() => {
|
|||||||
return namespaces.value.map((_, index) => activeLists.value[index]?.length ?? 0)
|
return namespaces.value.map((_, index) => activeLists.value[index]?.length ?? 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
useEventListener('resize', resize)
|
|
||||||
onMounted(() => resize())
|
|
||||||
|
|
||||||
const listStore = useListStore()
|
const listStore = useListStore()
|
||||||
|
|
||||||
function resize() {
|
|
||||||
// Hide the menu by default on mobile
|
|
||||||
baseStore.setMenuActive(window.innerWidth >= 770)
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleLists(namespaceId: INamespace['id']) {
|
function toggleLists(namespaceId: INamespace['id']) {
|
||||||
listsVisible.value[namespaceId] = !listsVisible.value[namespaceId]
|
listsVisible.value[namespaceId] = !listsVisible.value[namespaceId]
|
||||||
}
|
}
|
||||||
|
47
src/composables/useMenuActive.ts
Normal file
47
src/composables/useMenuActive.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import {ref, watch, readonly} from 'vue'
|
||||||
|
import {useLocalStorage, useMediaQuery} from '@vueuse/core'
|
||||||
|
|
||||||
|
const BULMA_MOBILE_BREAKPOINT = 768
|
||||||
|
|
||||||
|
export function useMenuActive() {
|
||||||
|
const isMobile = useMediaQuery(`(max-width: ${BULMA_MOBILE_BREAKPOINT}px)`)
|
||||||
|
|
||||||
|
const desktopPreference = useLocalStorage(
|
||||||
|
'menuActiveDesktopPreference',
|
||||||
|
true,
|
||||||
|
// If we have two tabs open we want to be able to have the menu open in one window
|
||||||
|
// and closed in the other. The last changed value will be the new preference
|
||||||
|
{listenToStorageChanges: false},
|
||||||
|
)
|
||||||
|
|
||||||
|
const menuActive = ref(false)
|
||||||
|
|
||||||
|
// set to prefered value
|
||||||
|
watch(isMobile, (current) => {
|
||||||
|
menuActive.value = current
|
||||||
|
// On mobile we don't show the menu in an expanded state
|
||||||
|
// because that would hide the main content
|
||||||
|
? false
|
||||||
|
: desktopPreference.value
|
||||||
|
}, {immediate: true})
|
||||||
|
|
||||||
|
watch(menuActive, (current) => {
|
||||||
|
if (!isMobile.value) {
|
||||||
|
desktopPreference.value = current
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function setMenuActive(newMenuActive: boolean) {
|
||||||
|
menuActive.value = newMenuActive
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleMenu() {
|
||||||
|
menuActive.value = menuActive.value = !menuActive.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
menuActive: readonly(menuActive),
|
||||||
|
setMenuActive,
|
||||||
|
toggleMenu,
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {readonly, ref} from 'vue'
|
import { readonly, ref} from 'vue'
|
||||||
import {defineStore, acceptHMRUpdate} from 'pinia'
|
import {defineStore, acceptHMRUpdate} from 'pinia'
|
||||||
|
|
||||||
import {getBlobFromBlurHash} from '@/helpers/getBlobFromBlurHash'
|
import {getBlobFromBlurHash} from '@/helpers/getBlobFromBlurHash'
|
||||||
@ -7,6 +7,8 @@ import ListModel from '@/models/list'
|
|||||||
import ListService from '../services/list'
|
import ListService from '../services/list'
|
||||||
import {checkAndSetApiUrl} from '@/helpers/checkAndSetApiUrl'
|
import {checkAndSetApiUrl} from '@/helpers/checkAndSetApiUrl'
|
||||||
|
|
||||||
|
import {useMenuActive} from '@/composables/useMenuActive'
|
||||||
|
|
||||||
import {useAuthStore} from '@/stores/auth'
|
import {useAuthStore} from '@/stores/auth'
|
||||||
import type {IList} from '@/modelTypes/IList'
|
import type {IList} from '@/modelTypes/IList'
|
||||||
|
|
||||||
@ -23,7 +25,6 @@ export const useBaseStore = defineStore('base', () => {
|
|||||||
const blurHash = ref('')
|
const blurHash = ref('')
|
||||||
|
|
||||||
const hasTasks = ref(false)
|
const hasTasks = ref(false)
|
||||||
const menuActive = ref(true)
|
|
||||||
const keyboardShortcutsActive = ref(false)
|
const keyboardShortcutsActive = ref(false)
|
||||||
const quickActionsActive = ref(false)
|
const quickActionsActive = ref(false)
|
||||||
const logoVisible = ref(true)
|
const logoVisible = ref(true)
|
||||||
@ -53,14 +54,6 @@ export const useBaseStore = defineStore('base', () => {
|
|||||||
hasTasks.value = newHasTasks
|
hasTasks.value = newHasTasks
|
||||||
}
|
}
|
||||||
|
|
||||||
function setMenuActive(newMenuActive: boolean) {
|
|
||||||
menuActive.value = newMenuActive
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleMenu() {
|
|
||||||
menuActive.value = !menuActive.value
|
|
||||||
}
|
|
||||||
|
|
||||||
function setKeyboardShortcutsActive(value: boolean) {
|
function setKeyboardShortcutsActive(value: boolean) {
|
||||||
keyboardShortcutsActive.value = value
|
keyboardShortcutsActive.value = value
|
||||||
}
|
}
|
||||||
@ -139,25 +132,24 @@ export const useBaseStore = defineStore('base', () => {
|
|||||||
background: readonly(background),
|
background: readonly(background),
|
||||||
blurHash: readonly(blurHash),
|
blurHash: readonly(blurHash),
|
||||||
hasTasks: readonly(hasTasks),
|
hasTasks: readonly(hasTasks),
|
||||||
menuActive: readonly(menuActive),
|
|
||||||
keyboardShortcutsActive: readonly(keyboardShortcutsActive),
|
keyboardShortcutsActive: readonly(keyboardShortcutsActive),
|
||||||
quickActionsActive: readonly(quickActionsActive),
|
quickActionsActive: readonly(quickActionsActive),
|
||||||
logoVisible: readonly(logoVisible),
|
logoVisible: readonly(logoVisible),
|
||||||
|
|
||||||
setLoading,
|
setLoading,
|
||||||
|
setReady,
|
||||||
setCurrentList,
|
setCurrentList,
|
||||||
setHasTasks,
|
setHasTasks,
|
||||||
setMenuActive,
|
|
||||||
toggleMenu,
|
|
||||||
setKeyboardShortcutsActive,
|
setKeyboardShortcutsActive,
|
||||||
setQuickActionsActive,
|
setQuickActionsActive,
|
||||||
setBackground,
|
setBackground,
|
||||||
setBlurHash,
|
setBlurHash,
|
||||||
setLogoVisible,
|
setLogoVisible,
|
||||||
setReady,
|
|
||||||
|
|
||||||
handleSetCurrentList,
|
handleSetCurrentList,
|
||||||
loadApp,
|
loadApp,
|
||||||
|
|
||||||
|
...useMenuActive(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user