feat: move composables in separate files (#2485)
Co-authored-by: Dominik Pschenitschni <mail@celement.de> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/2485 Reviewed-by: konrad <k@knt.li> Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de> Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
This commit is contained in:
parent
6f2dedcb48
commit
c206fc6f34
4 changed files with 106 additions and 93 deletions
|
@ -60,65 +60,18 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {watch, computed, shallowRef, watchEffect, type VNode, h} from 'vue'
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import {useEventListener} from '@vueuse/core'
|
||||
import {watch, computed} from 'vue'
|
||||
import {useRoute} from 'vue-router'
|
||||
|
||||
import {useLabelStore} from '@/stores/labels'
|
||||
import Navigation from '@/components/home/navigation.vue'
|
||||
import QuickActions from '@/components/quick-actions/quick-actions.vue'
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
|
||||
function useRouteWithModal() {
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const backdropView = computed(() => route.fullPath && window.history.state.backdropView)
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import {useLabelStore} from '@/stores/labels'
|
||||
|
||||
const routeWithModal = computed(() => {
|
||||
return backdropView.value
|
||||
? router.resolve(backdropView.value)
|
||||
: route
|
||||
})
|
||||
|
||||
const currentModal = shallowRef<VNode>()
|
||||
watchEffect(() => {
|
||||
if (!backdropView.value) {
|
||||
currentModal.value = undefined
|
||||
return
|
||||
}
|
||||
|
||||
// logic from vue-router
|
||||
// https://github.com/vuejs/vue-router-next/blob/798cab0d1e21f9b4d45a2bd12b840d2c7415f38a/src/RouterView.ts#L125
|
||||
const routePropsOption = route.matched[0]?.props.default
|
||||
const routeProps = routePropsOption
|
||||
? routePropsOption === true
|
||||
? route.params
|
||||
: typeof routePropsOption === 'function'
|
||||
? routePropsOption(route)
|
||||
: routePropsOption
|
||||
: null
|
||||
|
||||
currentModal.value = h(
|
||||
route.matched[0]?.components.default,
|
||||
routeProps,
|
||||
)
|
||||
})
|
||||
|
||||
function closeModal() {
|
||||
const historyState = computed(() => route.fullPath && window.history.state)
|
||||
|
||||
if (historyState.value) {
|
||||
router.back()
|
||||
} else {
|
||||
const backdropRoute = historyState.value?.backdropView && router.resolve(historyState.value.backdropView)
|
||||
router.push(backdropRoute)
|
||||
}
|
||||
}
|
||||
|
||||
return {routeWithModal, currentModal, closeModal}
|
||||
}
|
||||
import {useRouteWithModal} from '@/composables/useRouteWithModal'
|
||||
import {useRenewTokenOnFocus} from '@/composables/useRenewTokenOnFocus'
|
||||
|
||||
const {routeWithModal, currentModal, closeModal} = useRouteWithModal()
|
||||
|
||||
|
@ -162,43 +115,8 @@ watch(() => route.name as string, (routeName) => {
|
|||
|
||||
// TODO: Reset the title if the page component does not set one itself
|
||||
|
||||
function useRenewTokenOnFocus() {
|
||||
const router = useRouter()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
|
||||
const userInfo = computed(() => authStore.info)
|
||||
const authenticated = computed(() => authStore.authenticated)
|
||||
|
||||
// Try renewing the token every time vikunja is loaded initially
|
||||
// (When opening the browser the focus event is not fired)
|
||||
authStore.renewToken()
|
||||
|
||||
// Check if the token is still valid if the window gets focus again to maybe renew it
|
||||
useEventListener('focus', () => {
|
||||
if (!authenticated.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const expiresIn = (userInfo.value !== null ? userInfo.value.exp : 0) - +new Date() / 1000
|
||||
|
||||
// If the token expiry is negative, it is already expired and we have no choice but to redirect
|
||||
// the user to the login page
|
||||
if (expiresIn < 0) {
|
||||
authStore.checkAuth()
|
||||
router.push({name: 'user.login'})
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the token is valid for less than 60 hours and renew if thats the case
|
||||
if (expiresIn < 60 * 3600) {
|
||||
authStore.renewToken()
|
||||
console.debug('renewed token')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useRenewTokenOnFocus()
|
||||
|
||||
const labelStore = useLabelStore()
|
||||
labelStore.loadAllLabels()
|
||||
</script>
|
||||
|
|
40
src/composables/useRenewTokenOnFocus.ts
Normal file
40
src/composables/useRenewTokenOnFocus.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
import {computed} from 'vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
import {useEventListener} from '@vueuse/core'
|
||||
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
|
||||
export function useRenewTokenOnFocus() {
|
||||
const router = useRouter()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const userInfo = computed(() => authStore.info)
|
||||
const authenticated = computed(() => authStore.authenticated)
|
||||
|
||||
// Try renewing the token every time vikunja is loaded initially
|
||||
// (When opening the browser the focus event is not fired)
|
||||
authStore.renewToken()
|
||||
|
||||
// Check if the token is still valid if the window gets focus again to maybe renew it
|
||||
useEventListener('focus', () => {
|
||||
if (!authenticated.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const expiresIn = (userInfo.value !== null ? userInfo.value.exp : 0) - +new Date() / 1000
|
||||
|
||||
// If the token expiry is negative, it is already expired and we have no choice but to redirect
|
||||
// the user to the login page
|
||||
if (expiresIn < 0) {
|
||||
authStore.checkAuth()
|
||||
router.push({name: 'user.login'})
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the token is valid for less than 60 hours and renew if thats the case
|
||||
if (expiresIn < 60 * 3600) {
|
||||
authStore.renewToken()
|
||||
console.debug('renewed token')
|
||||
}
|
||||
})
|
||||
}
|
54
src/composables/useRouteWithModal.ts
Normal file
54
src/composables/useRouteWithModal.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
import { computed, shallowRef, watchEffect, h, type VNode } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
export function useRouteWithModal() {
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const backdropView = computed(() => route.fullPath && window.history.state.backdropView)
|
||||
|
||||
const routeWithModal = computed(() => {
|
||||
return backdropView.value
|
||||
? router.resolve(backdropView.value)
|
||||
: route
|
||||
})
|
||||
|
||||
const currentModal = shallowRef<VNode>()
|
||||
watchEffect(() => {
|
||||
if (!backdropView.value) {
|
||||
currentModal.value = undefined
|
||||
return
|
||||
}
|
||||
|
||||
// logic from vue-router
|
||||
// https://github.com/vuejs/vue-router-next/blob/798cab0d1e21f9b4d45a2bd12b840d2c7415f38a/src/RouterView.ts#L125
|
||||
const routePropsOption = route.matched[0]?.props.default
|
||||
const routeProps = routePropsOption
|
||||
? routePropsOption === true
|
||||
? route.params
|
||||
: typeof routePropsOption === 'function'
|
||||
? routePropsOption(route)
|
||||
: routePropsOption
|
||||
: null
|
||||
|
||||
const component = route.matched[0]?.components?.default
|
||||
|
||||
if (!component) {
|
||||
currentModal.value = undefined
|
||||
return
|
||||
}
|
||||
currentModal.value = h(component, routeProps)
|
||||
})
|
||||
|
||||
function closeModal() {
|
||||
const historyState = computed(() => route.fullPath && window.history.state)
|
||||
|
||||
if (historyState.value) {
|
||||
router.back()
|
||||
} else {
|
||||
const backdropRoute = historyState.value?.backdropView && router.resolve(historyState.value.backdropView)
|
||||
router.push(backdropRoute)
|
||||
}
|
||||
}
|
||||
|
||||
return {routeWithModal, currentModal, closeModal}
|
||||
}
|
|
@ -12,7 +12,7 @@ import type {IList} from '@/modelTypes/IList'
|
|||
export interface RootStoreState {
|
||||
loading: boolean,
|
||||
|
||||
currentList: IList,
|
||||
currentList: IList | null,
|
||||
background: string,
|
||||
blurHash: string,
|
||||
|
||||
|
@ -47,12 +47,13 @@ export const useBaseStore = defineStore('base', {
|
|||
this.loading = loading
|
||||
},
|
||||
|
||||
setCurrentList(currentList: IList) {
|
||||
setCurrentList(currentList: IList | null) {
|
||||
// Server updates don't return the right. Therefore, the right is reset after updating the list which is
|
||||
// confusing because all the buttons will disappear in that case. To prevent this, we're keeping the right
|
||||
// when updating the list in global state.
|
||||
if (
|
||||
typeof this.currentList.maxRight !== 'undefined' &&
|
||||
typeof this.currentList?.maxRight !== 'undefined' &&
|
||||
currentList !== null &&
|
||||
(
|
||||
typeof currentList.maxRight === 'undefined' ||
|
||||
currentList.maxRight === null
|
||||
|
@ -95,7 +96,7 @@ export const useBaseStore = defineStore('base', {
|
|||
this.logoVisible = visible
|
||||
},
|
||||
|
||||
async handleSetCurrentList({list, forceUpdate = false} : {list: IList, forceUpdate: boolean}) {
|
||||
async handleSetCurrentList({list, forceUpdate = false} : {list: IList | null, forceUpdate: boolean}) {
|
||||
if (list === null) {
|
||||
this.setCurrentList({})
|
||||
this.setBackground('')
|
||||
|
|
Loading…
Reference in a new issue