From c206fc6f3462be2e0ebc0bd16d96b3c0099fdda1 Mon Sep 17 00:00:00 2001 From: Dominik Pschenitschni Date: Tue, 4 Oct 2022 12:10:12 +0000 Subject: [PATCH] feat: move composables in separate files (#2485) Co-authored-by: Dominik Pschenitschni Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/2485 Reviewed-by: konrad Co-authored-by: Dominik Pschenitschni Co-committed-by: Dominik Pschenitschni --- src/components/home/contentAuth.vue | 96 ++----------------------- src/composables/useRenewTokenOnFocus.ts | 40 +++++++++++ src/composables/useRouteWithModal.ts | 54 ++++++++++++++ src/stores/base.ts | 9 +-- 4 files changed, 106 insertions(+), 93 deletions(-) create mode 100644 src/composables/useRenewTokenOnFocus.ts create mode 100644 src/composables/useRouteWithModal.ts diff --git a/src/components/home/contentAuth.vue b/src/components/home/contentAuth.vue index 3396be576..616c17dfe 100644 --- a/src/components/home/contentAuth.vue +++ b/src/components/home/contentAuth.vue @@ -60,65 +60,18 @@ diff --git a/src/composables/useRenewTokenOnFocus.ts b/src/composables/useRenewTokenOnFocus.ts new file mode 100644 index 000000000..06305984e --- /dev/null +++ b/src/composables/useRenewTokenOnFocus.ts @@ -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') + } + }) +} \ No newline at end of file diff --git a/src/composables/useRouteWithModal.ts b/src/composables/useRouteWithModal.ts new file mode 100644 index 000000000..c7ff45985 --- /dev/null +++ b/src/composables/useRouteWithModal.ts @@ -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() + 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} +} \ No newline at end of file diff --git a/src/stores/base.ts b/src/stores/base.ts index 2e5702b6c..83be64133 100644 --- a/src/stores/base.ts +++ b/src/stores/base.ts @@ -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('')