Created
October 21, 2024 12:31
-
-
Save mary-ext/1089a1da08df72dbd08381c956bb8a93 to your computer and use it in GitHub Desktop.
vue modal router thing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script setup lang="ts"> | |
import { computed } from 'vue'; | |
import { type RouteLocationNormalizedLoaded as LoadedRouteLocation, RouterView, useRoute } from 'vue-router'; | |
import { assert } from '~/utils/misc.ts'; | |
const route = useRoute(); | |
const handleModalRoute = (route: LoadedRouteLocation): LoadedRouteLocation => { | |
// on modal routes, we only want the actual modal itself to be rendered | |
return { ...route, matched: route.matched.slice(-1) }; | |
}; | |
const resolvedRoute = computed((): [bg: LoadedRouteLocation, fg: LoadedRouteLocation | null] => { | |
const meta = route.meta; | |
if (meta && meta.defaultBackgroundRoute) { | |
const resolved = meta._bgRoute; | |
assert(resolved != null); | |
return [resolved, handleModalRoute(route)]; | |
} | |
return [route, null]; | |
}); | |
</script> | |
<template> | |
<RouterView :route="resolvedRoute[0]" :key="resolvedRoute[0].fullPath" /> | |
<template v-if="resolvedRoute[1]"> | |
<RouterView :route="resolvedRoute[1]" :key="resolvedRoute[1].fullPath" /> | |
</template> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createRouter, createWebHistory, loadRouteLocation } from 'vue-router'; | |
import { isDid } from '~/api/utils.ts'; | |
import { multiagent } from '~/globals/agent.ts'; | |
export const router = createRouter({ | |
history: createWebHistory(), | |
routes: [ | |
{ | |
path: '/', | |
component: () => import('~/views/FrontPage.vue'), | |
}, | |
{ | |
path: '/u/:uid', | |
component: () => import('~/views/main/MainLayout.vue'), | |
beforeEnter(to) { | |
const uid = to.params.uid as string; | |
const $accounts = multiagent.accounts; | |
if (!$accounts || !isDid(uid) || !$accounts[uid]) { | |
const path = to.path.slice(4 + uid.length); | |
return { | |
path: '/', | |
query: { | |
to: `@uid/${path}`, | |
}, | |
}; | |
} | |
}, | |
children: [ | |
{ | |
path: '', | |
component: () => import('~/views/main/home/HomePage.vue'), | |
}, | |
{ | |
path: 'notifications', | |
component: () => import('~/views/main/notifications/NotificationsPage.vue'), | |
}, | |
{ | |
path: 'profile/:actor', | |
component: () => import('~/views/main/profile/ProfileLayout.vue'), | |
children: [ | |
{ | |
path: '', | |
component: () => import('~/views/main/profile/ProfileTimelinePage.vue'), | |
}, | |
], | |
}, | |
{ | |
path: 'profile/:actor/post/:tid', | |
component: () => import('~/views/main/modals/PostsModal.vue'), | |
meta: { | |
defaultBackgroundRoute(to) { | |
const uid = to.params.uid as DID; | |
const actor = to.params.actor as string; | |
return `/u/${uid}/profile/${actor}`; | |
}, | |
}, | |
}, | |
], | |
}, | |
{ | |
path: '/:rest(.*)*', | |
component: () => import('~/views/NotFoundPage.vue'), | |
}, | |
], | |
}); | |
// Modal route handling | |
let first = true; | |
router.beforeResolve(async (to, from) => { | |
const meta = to.meta; | |
if (meta.defaultBackgroundRoute) { | |
if (first) { | |
const bg = meta.defaultBackgroundRoute(to); | |
const resolved = router.resolve(bg); | |
await loadRouteLocation(resolved); | |
meta._bgRoute = resolved; | |
} else if (from.meta._bgRoute) { | |
meta._bgRoute = from.meta._bgRoute; | |
} else { | |
meta._bgRoute = from; | |
} | |
} | |
first = false; | |
}); | |
declare module 'vue-router' { | |
interface RouteMeta { | |
/** | |
* Indicates that this route is a modal route, it will try to use the route | |
* it was transitioning from as the background view, but if it can't, it | |
* will call this function to get the "default" background view for use | |
*/ | |
defaultBackgroundRoute?: (to: RouteLocationNormalized) => RouteLocationRaw; | |
/** | |
* @internal | |
* This is an internal property for our navigation guards to attach the | |
* appropriate background view to use for a modal route. | |
*/ | |
_bgRoute?: RouteLocation; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment