From ae467ef245d1798650bbb51523179da5037afa13 Mon Sep 17 00:00:00 2001 From: SeydX Date: Thu, 6 May 2021 03:52:56 +0200 Subject: [PATCH] fix missing plugin config & added fullscreen button to actionsheet --- CHANGELOG.md | 4 +- services/config/config.service.js | 3 +- ui/src/components/actionsheet.vue | 14 ++- ui/src/i18n/locale/de.json | 2 + ui/src/i18n/locale/en.json | 2 + ui/src/i18n/locale/nl.json | 2 + ui/src/views/camview/Camview.vue | 183 +++++++++++++++++++++--------- 7 files changed, 150 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80c2f851..a4aa02b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,16 @@ # Changelog -# NEXT +# v4.2.1 - 2021-05-06 ## Other changes - Interface: + - Added `fullscreen` button to bottom actionsheet (camview) - Changed recording subtitle from `Type - Date` to `Type - Room` (recordings) - Added additional media queries to recording cards - Minor UI improvements ## Bugfixexs +- Fixed an issue where missing plugin config crashed homebridge - Minor UI bugfixes # v4.2.0 - 2021-05-05 diff --git a/services/config/config.service.js b/services/config/config.service.js index 070ac893..e15d3d20 100644 --- a/services/config/config.service.js +++ b/services/config/config.service.js @@ -70,7 +70,7 @@ class ConfigService { this.plugin = this.config.platforms.find((x) => x.platform === 'CameraUI'); - return this.plugin; + return this.plugin || {}; } getUiConfig() { @@ -99,7 +99,6 @@ class ConfigService { this.getPluginConfig(); } - this.ui.auth = this.plugin.auth || 'form'; this.ui.language = this.plugin.language || 'en'; this.ui.theme = this.plugin.theme || 'light-pink'; } diff --git a/ui/src/components/actionsheet.vue b/ui/src/components/actionsheet.vue index 0b537ae6..f765bace 100644 --- a/ui/src/components/actionsheet.vue +++ b/ui/src/components/actionsheet.vue @@ -6,9 +6,11 @@ transition(name="fade" @enter="enter") b-modal(v-model="show" modal-class="overflow-hidden" dialog-class="modal-bottom" hide-footer hide-header) .row.pb-4(v-if="showLeftNavi || showRightNavi") .col.d-flex.flex-wrap.justify-content-start.align-content-center - b-button.back-button(pill, @click="$emit('leftNaviClick')") {{ leftNaviName }} + b-button.left-button(pill, @click="$emit('leftNaviClick')") {{ leftNaviName }} + .col.d-flex.flex-wrap.justify-content-center.align-content-center + b-button.middle-button(pill, @click="$emit('middleNaviClick')") {{ middleNaviName }} .col.d-flex.flex-wrap.justify-content-end.align-content-center - b-button.btn-primary.logout-button(pill, @click="$emit('rightNaviClick')") {{ rightNaviName }} + b-button.btn-primary.right-button(pill, @click="$emit('rightNaviClick')") {{ rightNaviName }} hr.mt-0.pt-0(v-if="showLeftNavi || showRightNavi") div(v-for="(item, i) in items" :key="item.name") .row @@ -45,6 +47,10 @@ export default { type: String, default: 'Back', }, + middleNaviName: { + type: String, + default: 'Fullscreen', + }, rightNaviName: { type: String, default: 'Signout', @@ -53,6 +59,10 @@ export default { type: Boolean, default: false, }, + showMiddleNavi: { + type: Boolean, + default: false, + }, showRightNavi: { type: Boolean, default: false, diff --git a/ui/src/i18n/locale/de.json b/ui/src/i18n/locale/de.json index 17a12dc2..3fd1bcef 100644 --- a/ui/src/i18n/locale/de.json +++ b/ui/src/i18n/locale/de.json @@ -37,6 +37,7 @@ "chat_id": "Chat ID", "confidence": "Zuversichtlichkeit", "config": "Konfiguration", + "close": "Schließen", "darkmode": "Darkmode", "dashboard": "Dashboard", "database_resetted": "Datenbank wurde zurückgesetzt", @@ -50,6 +51,7 @@ "favourites": "Favoriten", "forgotpw_title": "Passwort vergessen?", "forgotpw_content": "Wenn Sie ihr Passwort vergessen haben, können sie durch das Löschen der Datenbank oder Einspielen eines Backups diesen wieder herstellen.", + "fullscreen": "Vollbild", "general": "Allgemein", "general_information": "Allgemeine Informationen", "go_back": "Zurück", diff --git a/ui/src/i18n/locale/en.json b/ui/src/i18n/locale/en.json index eefd968a..06133fb5 100644 --- a/ui/src/i18n/locale/en.json +++ b/ui/src/i18n/locale/en.json @@ -36,6 +36,7 @@ "cannot_login": "Username and/or password are incorrect", "confidence": "Confidence", "config": "Config", + "close": "Close", "darkmode": "Darkmode", "dashboard": "Dashboard", "database_resetted": "Database resetted", @@ -49,6 +50,7 @@ "favourites": "Favourites", "forgotpw_title": "Forgot password?", "forgotpw_content": "If you have forgotten your password, you can restore it by deleting the database or importing a backup.", + "fullscreen": "Fullscreen", "general": "General", "general_information": "General Information", "go_back": "Back", diff --git a/ui/src/i18n/locale/nl.json b/ui/src/i18n/locale/nl.json index 119e0a87..9df3ca5e 100644 --- a/ui/src/i18n/locale/nl.json +++ b/ui/src/i18n/locale/nl.json @@ -36,6 +36,7 @@ "cannot_login": "Gebruikersnaam en/of wachtwoord zijn onjuist", "confidence": "Confidence", "config": "Config", + "close": "Close", "darkmode": "Darkmode", "dashboard": "Dashboard", "database_resetted": "Database werd gereset", @@ -49,6 +50,7 @@ "favourites": "Favoriten", "forgotpw_title": "Wachtwoord vergeten?", "forgotpw_content": "Als u uw wachtwoord bent vergeten, kunt u het herstellen door de database te wissen of een back-up te importeren.", + "fullscreen": "Fullscreen", "general": "Algemeen", "general_information": "Algemene informatie", "go_back": "Terug", diff --git a/ui/src/views/camview/Camview.vue b/ui/src/views/camview/Camview.vue index e33b77e3..d566ff9e 100644 --- a/ui/src/views/camview/Camview.vue +++ b/ui/src/views/camview/Camview.vue @@ -27,6 +27,9 @@ div :showLeftNavi="true" :leftNaviName="$t('back')" @leftNaviClick="goBack" + :showMiddleNavi="true" + :middleNaviName="$t('fullscreen')" + @middleNaviClick="showFullscreen" :showRightNavi="true" :rightNaviName="$t('signout')" @rightNaviClick="logOut" @@ -62,6 +65,7 @@ export default { return { allCameras: [], cameras: [], + fullscreen: false, grid: null, loading: true, prevRoute: null, @@ -119,6 +123,8 @@ export default { await timeout(100); this.updateLayout(); + document.addEventListener('keydown', this.logKey); + document.addEventListener('fullscreenchange', this.fullscreenHandler); window.addEventListener('resize', this.resizeHandler); } else { this.$toast.error(this.$t('no_access')); @@ -133,9 +139,39 @@ export default { body.classList.remove('body-bg-dark'); html.classList.remove('body-bg-dark'); + document.removeEventListener('keydown', this.logKey); + document.removeEventListener('fullscreenchange', this.fullscreenHandler); window.removeEventListener('resize', this.resizeHandler); }, methods: { + closeFullscreen() { + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.mozCancelFullScreen) { + /* Firefox */ + document.mozCancelFullScreen(); + } else if (document.webkitExitFullscreen) { + /* Chrome, Safari and Opera */ + document.webkitExitFullscreen(); + } else if (document.msExitFullscreen) { + /* IE/Edge */ + document.msExitFullscreen(); + } + + const fullscreenButton = document.querySelector('.middle-button'); + fullscreenButton.innerHTML = this.$t('fullscreen'); + + this.fullscreen = false; + }, + fullscreenHandler() { + if (document.fullscreenElement) { + console.log(`Element: ${document.fullscreenElement.id} entered fullscreen mode.`); + this.fullscreen = true; + } else { + console.log('Leaving full-screen mode.'); + this.fullscreen = false; + } + }, async handleFavouriteCamera(cam) { try { const camera = this.allCameras.find((camera) => camera && camera.name === cam.name); @@ -172,6 +208,61 @@ export default { this.$toast.error(err.message); } }, + getLayout() { + let nodes = []; + + let index_ = 0; + let x = 0; + let y = 0; + let w = this.items().length < 7 ? 6 : 4; + let h = + 12 / + Math.round( + (this.items().length % 2 === 0 ? this.items().length : this.items().length + 1) / + (this.items().length < 7 ? 2 : 3) + ); + + for (const [index, element] of this.items().entries()) { + const beforeElement = this.items()[index ? index - 1 : index]; + let lastX = Number.parseInt(beforeElement.getAttribute('gs-x')); + + x = this.items().length < 7 ? (index && !lastX ? 6 : 0) : index && !lastX ? 4 : lastX == 4 ? 8 : 0; + + if (this.items().length < 7 && index % 2 == 0) { + y = index_ * h; + index_++; + } + + if (this.items().length >= 7 && index % 3 == 0) { + y = index_ * h; + index_++; + } + + if (this.items().length === 1) { + x = 0; + y = 0; + w = 12; + h = 12; + } + + if (this.items().length === 2) { + x = 0; + y = index * 6; + w = 12; + h = 6; + } + + nodes.push({ + el: element, + x: x, + y: y, + w: w, + h: h, + }); + } + + return nodes; + }, goBack() { if (this.prevRoute && !this.prevRoute.name && !this.prevRoute.meta.name) { return this.$router.push('/dashboard'); @@ -188,10 +279,40 @@ export default { items() { return document.querySelectorAll('.grid-stack-item'); }, + logKey(event) { + if (event.key === 'F11' || event.keyCode === 122) { + event.preventDefault(); + !this.fullscreen ? this.openFullscreen() : this.closeFullscreen(); + } else if ((event.key === 'Escape' || event.keyCode === 27) && this.fullscreen) { + event.preventDefault(); + this.closeFullscreen(); + } + }, async logOut() { await this.$store.dispatch('auth/logout'); this.$router.push('/'); }, + openFullscreen() { + const elem = document.querySelector('html'); + + if (elem.requestFullscreen) { + elem.requestFullscreen(); + } else if (elem.mozRequestFullScreen) { + /* Firefox */ + elem.mozRequestFullScreen(); + } else if (elem.webkitRequestFullscreen) { + /* Chrome, Safari and Opera */ + elem.webkitRequestFullscreen(); + } else if (elem.msRequestFullscreen) { + /* IE/Edge */ + elem.msRequestFullscreen(); + } + + const fullscreenButton = document.querySelector('.middle-button'); + fullscreenButton.innerHTML = this.$t('close'); + + this.fullscreen = true; + }, refreshStreamSocket(event) { if (this.$refs[event.camera] && this.$refs[event.camera][0]) { this.$refs[event.camera][0].pauseStream(true); @@ -210,6 +331,13 @@ export default { //console.log(`Storing layout: ${JSON.stringify(this.serializedData)}`); this.$store.dispatch('camview/updateElements', this.serializedData); }, + showFullscreen() { + if (this.fullscreen) { + this.closeFullscreen(); + } else { + this.openFullscreen(); + } + }, updateLayout(manual) { this.grid = GridStack.init({ alwaysShowResizeHandle: this.isMobile(), @@ -255,61 +383,6 @@ export default { }); } }, - getLayout() { - let nodes = []; - - let index_ = 0; - let x = 0; - let y = 0; - let w = this.items().length < 7 ? 6 : 4; - let h = - 12 / - Math.round( - (this.items().length % 2 === 0 ? this.items().length : this.items().length + 1) / - (this.items().length < 7 ? 2 : 3) - ); - - for (const [index, element] of this.items().entries()) { - const beforeElement = this.items()[index ? index - 1 : index]; - let lastX = Number.parseInt(beforeElement.getAttribute('gs-x')); - - x = this.items().length < 7 ? (index && !lastX ? 6 : 0) : index && !lastX ? 4 : lastX == 4 ? 8 : 0; - - if (this.items().length < 7 && index % 2 == 0) { - y = index_ * h; - index_++; - } - - if (this.items().length >= 7 && index % 3 == 0) { - y = index_ * h; - index_++; - } - - if (this.items().length === 1) { - x = 0; - y = 0; - w = 12; - h = 12; - } - - if (this.items().length === 2) { - x = 0; - y = index * 6; - w = 12; - h = 6; - } - - nodes.push({ - el: element, - x: x, - y: y, - w: w, - h: h, - }); - } - - return nodes; - }, windowHeight() { let windowHeight = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/.test(navigator.userAgent) ||