Files
spot/src/Spot.vue
2026-05-10 20:03:56 +02:00

102 lines
2.6 KiB
Vue

<script>
import Project from '@components/project';
import Admin from '@components/admin';
import Upload from '@components/upload';
const aoRoutes = {
'project': Project,
'admin': Admin,
'upload': Upload
};
export default {
data() {
return {
hash: {page: '', items: []},
consts: this.appConfig.consts,
mobile: false
};
},
provide() {
return {
hash: this.hash,
consts: this.consts,
isMobile: () => this.isMobile()
};
},
computed: {
route() {
return aoRoutes[this.hash.page];
},
hashSnapshot() {
return JSON.stringify(this.hash);
}
},
inject: ['appConfig'],
created() {
this.mobileMediaQuery = window.matchMedia('only screen and (max-width: 800px)');
this.mobileMediaQuery.addEventListener('change', this.updateMobile);
this.updateMobile();
//Set initial page
let asInitHash = this.getBrowserHash();
if(!asInitHash.page) asInitHash.page = this.consts.default_page;
this.setVarHash(asInitHash);
},
mounted() {
//Catch browser hash change
window.addEventListener('hashchange', this.onBrowserHashChange);
},
watch: {
hashSnapshot(jNewHash, jOldHash) {
const asNewHash = JSON.parse(jNewHash);
//Sync variable -> #hash
if(asNewHash != this.getBrowserHash()) {
this.setBrowserHash(asNewHash.page, asNewHash.items);
}
this.setPageTitle(asNewHash.page);
}
},
methods: {
isMobile() {
return this.mobile;
},
updateMobile() {
this.mobile = this.mobileMediaQuery.matches;
},
setPageTitle(sTitle) {
document.title = this.consts.title + ' - ' + sTitle.trim();
},
setVarHash(asHash) {
this.hash.page = asHash.page || '';
this.hash.items = Array.isArray(asHash.items) ? [...asHash.items.filter(n => n)] : [];
},
onBrowserHashChange() { //Sync #hash -> variable
let asHash = this.getBrowserHash();
if(asHash != this.hash) this.setVarHash(asHash);
},
getBrowserHash() {
let sHash = window.location.hash.slice(1);
let asHash = sHash.split(this.consts.hash_sep).filter(n => n);
let sPage = asHash.shift() || '';
return {page: sPage, items: asHash};
},
setBrowserHash(sPage = '', asItems = []) {
if(typeof asItems == 'string' && asItems != '') asItems = [asItems];
const sItems = (asItems.length > 0)?(this.consts.hash_sep + asItems.join(this.consts.hash_sep)):'';
window.location.hash = '#' + sPage + sItems;
}
},
beforeUnmount() {
window.removeEventListener('hashchange', this.onBrowserHashChange);
this.mobileMediaQuery.removeEventListener('change', this.updateMobile);
}
}
</script>
<template>
<div id="main">
<component :is="route" />
</div>
</template>