260 lines
7.2 KiB
Vue
260 lines
7.2 KiB
Vue
<template>
|
|
<v-app>
|
|
<v-main class="main">
|
|
<router-view />
|
|
|
|
<!-- Loading indicator -->
|
|
<v-container
|
|
fluid
|
|
fill-height
|
|
v-if="showLoadingScreen"
|
|
class="loading-container"
|
|
>
|
|
<v-row align="center" justify="center">
|
|
<v-col class="text-center">
|
|
<v-progress-circular
|
|
indeterminate
|
|
class="loading-convene"
|
|
></v-progress-circular>
|
|
<div>{{ $t("menu.loading", { appName: appName }) }}</div>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
|
|
<v-skeleton-loader
|
|
type="list-item-avatar-two-line, divider, list-item-three-line, card-heading"
|
|
v-if="showLoadingScreen"
|
|
></v-skeleton-loader>
|
|
</v-main>
|
|
</v-app>
|
|
</template>
|
|
|
|
<script>
|
|
import stickers from "./plugins/stickers";
|
|
import { registerServiceWorker, notificationCount, windowNotificationPermission } from "./plugins/notificationAndServiceWorker.js"
|
|
import logoMixin from "./components/logoMixin";
|
|
import { mapState } from 'vuex'
|
|
|
|
export default {
|
|
name: "App",
|
|
mixins: [logoMixin],
|
|
data() {
|
|
return {
|
|
loading: true,
|
|
browserLanguage: null,
|
|
availableJsonTranslation: null
|
|
}
|
|
},
|
|
beforeMount() {
|
|
this.setDefaultLanguage();
|
|
},
|
|
mounted() {
|
|
registerServiceWorker(this.$t('notification.periodicSync_new_msg_reminder'));
|
|
/**
|
|
if (
|
|
window.location.protocol == "http" &&
|
|
!window.location.hostname.endsWith(".onion")
|
|
) {
|
|
// Redirect to HTTPS
|
|
// window.location.href = window.location.href.replace("http:", "https:");
|
|
return;
|
|
}
|
|
**/
|
|
if (this.currentUser) {
|
|
this.$matrix
|
|
.login(this.currentUser)
|
|
.then(() => {
|
|
console.log("Matrix client ready");
|
|
})
|
|
.catch((error) => {
|
|
console.log("Error creating client", error);
|
|
if (error.data && ((error.data.errcode ==='M_FORBIDDEN' && this.currentUser.is_guest) || error.data.errcode ==='M_USER_DEACTIVATED')) {
|
|
// Guest account and password don't work. We are in a strange state, probably because
|
|
// of server cleanup of accounts or similar. Wipe account and restart...
|
|
this.$store.commit("setUser", null);
|
|
this.$store.commit("setCurrentRoomId", null);
|
|
this.$navigation.push({ path: "/login" }, -1);
|
|
}
|
|
})
|
|
.finally(() => {
|
|
this.loading = false;
|
|
});
|
|
} else {
|
|
this.loading = false;
|
|
}
|
|
this.$config.promise.then(this.onConfigLoaded);
|
|
},
|
|
methods: {
|
|
windowNotificationPermission,
|
|
onConfigLoaded(config) {
|
|
if (config.shortCodeStickers) {
|
|
stickers.loadStickersFromConfig(config);
|
|
}
|
|
},
|
|
setDefaultLanguage() {
|
|
let LocalesArr= Object.keys(this.$i18n.messages);
|
|
// No language set, default to browser language?
|
|
this.browserLanguage = (navigator.language ||navigator.userLanguage ||"").toLowerCase();
|
|
// Try with language name only.
|
|
let lang = this.browserLanguage.split("-")[0];
|
|
// Assigns available language for ex 'zh_Hans' when browser header language is 'zh' or 'zh-HK'
|
|
this.availableJsonTranslation= LocalesArr[LocalesArr.findIndex(locale => locale.includes(lang))];
|
|
|
|
if (!this.$store.state.language) {
|
|
// Set default language if not set already
|
|
if (this.$i18n.messages[this.browserLanguage]) {
|
|
this.$store.commit("setLanguage", this.browserLanguage);
|
|
} else if (this.browserLanguage.includes("-")) {
|
|
if (this.$i18n.messages[lang]) {
|
|
this.$store.commit("setLanguage", lang);
|
|
} else {
|
|
this.$store.commit("setLanguage", this.availableJsonTranslation);
|
|
}
|
|
} else {
|
|
this.$store.commit("setLanguage", this.availableJsonTranslation);
|
|
}
|
|
}
|
|
|
|
// Set language
|
|
this.$i18n.locale = this.$store.state.language || "en";
|
|
},
|
|
showNotification() {
|
|
if(document.visibilityState === "hidden") {
|
|
const title = this.$t('notification.title');
|
|
const self = this;
|
|
|
|
navigator.serviceWorker.ready.then(function(registration) {
|
|
registration.showNotification(title, {
|
|
icon: self.logotype,
|
|
data: { url: window.location.href }
|
|
});
|
|
});
|
|
}
|
|
},
|
|
},
|
|
computed: {
|
|
showLoadingScreen() {
|
|
return this.loading || !(this.$config.loaded);
|
|
},
|
|
notificationCount,
|
|
currentUser() {
|
|
return this.$store.state.auth.user;
|
|
},
|
|
appName() {
|
|
var translated = undefined;
|
|
if (this.$config.appNames) {
|
|
translated = this.$config.appNames[this.$i18n.locale];
|
|
}
|
|
return translated || this.$config.appName;
|
|
},
|
|
title() {
|
|
var title = this.appName;
|
|
if (this.notificationCount > 0) {
|
|
title += " [" + this.notificationCount + "]";
|
|
}
|
|
if (this.$route.meta.title) {
|
|
title += " - " + this.$route.meta.title;
|
|
}
|
|
if (this.$route.meta.includeRoom) {
|
|
if (this.$matrix.currentRoom) {
|
|
title +=
|
|
" - " +
|
|
(this.$matrix.currentRoom.name || this.$matrix.currentRoom.roomId);
|
|
} else if (this.$matrix.currentRoomId) {
|
|
title += " - " + this.$matrix.currentRoomId;
|
|
}
|
|
}
|
|
return title;
|
|
},
|
|
|
|
favicon() {
|
|
var favicon = this.$config.logo ? this.$config.logo : 'favicon.ico';
|
|
if (this.$route.meta.includeFavicon) {
|
|
if (this.$matrix.currentRoom) {
|
|
favicon = this.$matrix.currentRoom.avatar || favicon;
|
|
}
|
|
}
|
|
return favicon;
|
|
},
|
|
...mapState([
|
|
'globalNotification'
|
|
])
|
|
},
|
|
watch: {
|
|
notificationCount: {
|
|
handler(nCount) {
|
|
// windowNotificationPermission
|
|
// return value: 'granted', 'default', 'denied'
|
|
if (this.globalNotification && nCount > 0 && this.windowNotificationPermission() === "granted") {
|
|
this.showNotification()
|
|
}
|
|
}
|
|
},
|
|
"$i18n.locale": {
|
|
handler(val) {
|
|
// Locale changed, check file if RTL
|
|
var isRTL = this.$i18n.messages[val].language_is_rtl || false;
|
|
if (isRTL) {
|
|
this.$vuetify.rtl = true;
|
|
document.documentElement.setAttribute("dir", "rtl");
|
|
} else {
|
|
this.$vuetify.rtl = false;
|
|
document.documentElement.setAttribute("dir", "ltr");
|
|
}
|
|
},
|
|
immediate: true,
|
|
},
|
|
title: {
|
|
handler(title) {
|
|
document.title = title;
|
|
},
|
|
immediate: true,
|
|
},
|
|
|
|
favicon: {
|
|
handler(favicon) {
|
|
document.getElementById("favicon").setAttribute('href', favicon);
|
|
},
|
|
immediate: true,
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
@import '~vuetify/src/styles/settings/_variables.scss';
|
|
@import '@/assets/css/variables';
|
|
|
|
.copyright {
|
|
font-size: 10px;
|
|
}
|
|
|
|
#app {
|
|
background-color: var(--v-app-background);
|
|
}
|
|
|
|
.main {
|
|
@media #{map-get($display-breakpoints, 'lg-and-up')} {
|
|
margin: 0 auto;
|
|
width: $main-desktop-width;
|
|
}
|
|
}
|
|
.v-skeleton-loader--is-loading {
|
|
z-index: 100;
|
|
}
|
|
.loading {
|
|
&-container {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
z-index: 20;
|
|
background-color: rgba(255, 255, 255, 1);
|
|
}
|
|
|
|
&-convene {
|
|
color: $very-very-purple;
|
|
}
|
|
}
|
|
</style>
|