mackenzii/src/main.vue

161 lines
3.9 KiB
Vue

<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { getCurrentRoute } from 'src/utilities/vuetils'
import { injectStylesheet } from 'src/utilities/dom'
import { storage } from './utilities/fetch'
import { useRouteStore } from 'src/routes'
import type { WarningModal } from 'content/routes.js'
import HeaderLink from 'src/components/shared/header-link.vue'
import ThemePicker from 'src/components/shared/theme-picker.vue'
import WarningPrompt from 'src/components/shared/warning-prompt.vue'
const router = useRouter()
const routeStore = useRouteStore()
const globalConfig = routeStore._globals
let currentRoute = getCurrentRoute()
let routeConfig = routeStore._routes[currentRoute.path]
let rememberWarning = false
const ready = ref(false)
const firstInit = ref(false)
const acknowledged = ref(false)
const storageId = ref('')
const routeId = ref('')
const warning = ref({} as WarningModal)
const determineWarning = () => {
if (!routeConfig.warning || routeStore.doesRouteRememberWarning(currentRoute.path)) {
acknowledged.value = true
return
}
rememberWarning = storage.read(`${storageId.value}::rememberWarning`) || false
if (rememberWarning) {
acknowledged.value = true
routeStore.rememberRouteWarning(currentRoute.path)
return
}
warning.value = routeConfig.warning === true
? globalConfig.warning
: routeConfig.warning
}
const determineStylesheets = (stylesheetUrls?: string[]) => {
const staleStylesheets = document.head.querySelectorAll('link.page-stylesheet[rel="stylesheet"]')
staleStylesheets.forEach(stylesheet => {
document.head.removeChild(stylesheet)
})
stylesheetUrls?.forEach(stylesheet => {
injectStylesheet(stylesheet, 'page-stylesheet')
})
}
const determineGlobalStylesheets = () => {
globalConfig.stylesheetUrls.forEach(stylesheet => {
injectStylesheet(stylesheet, 'global-stylesheet')
})
}
const determineScript = async () => {
if (!!routeConfig.scriptUrl) {
const { callbacks } = await import(/* @vite-ignore */ routeConfig.scriptUrl)
if (!!callbacks.onPageLoaded) {
callbacks.onPageLoaded();
}
}
return null
}
const refresh = async () => {
ready.value = false
acknowledged.value = false
currentRoute = getCurrentRoute()
routeConfig = routeStore._routes[currentRoute.path]
storageId.value = `${globalConfig.id}::${currentRoute.path}`
routeId.value = routeStore._routes[currentRoute.path].id
determineWarning()
determineStylesheets(routeConfig.stylesheetUrls)
scrollTo({
top: 0,
})
setTimeout(() => ready.value = true)
}
const onAcknowledgedWarning = () => {
acknowledged.value = true
routeStore.rememberRouteWarning(currentRoute.path)
}
const onRouteLoaded = async () => {
await determineScript()
}
const handlePageClosed = async (scriptUrl?: string) => {
if (!!scriptUrl) {
const { callbacks } = await import(/* @vite-ignore */ scriptUrl)
if (!!callbacks.onPageClosed) {
callbacks.onPageClosed()
}
}
}
onMounted(async () => {
await refresh()
firstInit.value = true
determineGlobalStylesheets()
router.afterEach(async (to, from) => {
const oldUrl = routeConfig.scriptUrl
await refresh()
await handlePageClosed(oldUrl)
})
})
</script>
<template lang="pug">
#main-container
header(
v-if='firstInit && !!globalConfig.header'
)
ul
HeaderLink(
v-for='entry in globalConfig.header'
:entry='entry'
)
ThemePicker
main(
v-if='ready'
)
#main-entry(
v-if='acknowledged'
)
router-view(
v-slot='{ Component }'
@loaded='onRouteLoaded'
)
Transition
component(
:id='routeId'
:is='Component'
)
#main-entry(
v-else
)
Transition
WarningPrompt(
:storageId='storageId'
:warning='warning'
@acknowledged='onAcknowledgedWarning()'
)
</template>
<style scoped lang="sass">
</style>