X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=app.js;h=9e6bdd9a12d813efec730f25613701cb41a45389;hb=554fc76d750ef6a3516a2f1141ba575fb2563a19;hp=40830da1a457f3053b4ff230b54e0814c0add6a2;hpb=5738264ea00221c0ca128d5e7f74d31a8ec0490c;p=github%2Fbastienwirtz%2Fhomer.git diff --git a/app.js b/app.js index 40830da..9e6bdd9 100644 --- a/app.js +++ b/app.js @@ -5,9 +5,10 @@ const app = new Vue({ offline: false, filter: '', vlayout: true, - isDark: null + isDark: null, + showMenu: false }, - created: function () { + created: async function () { let that = this; this.isDark = 'overrideDark' in localStorage ? @@ -18,11 +19,24 @@ const app = new Vue({ } this.checkOffline(); - that.getConfig().then(function (config) { - that.config = config; - }).catch(function () { - that.offline = true; - }); + try { + this.config = await this.getConfig(); + document.title = this.config.title + ' | ' + this.config.subtitle; + } catch (error) { + this.offline = true; + } + + // Look for a new message if an endpoint is provided. + if (this.config.message && this.config.message.url) { + this.getMessage(this.config.message.url).then(function(message){ + // keep the original config value if no value is provided by the endpoint + for (const prop of ['title','style','content']) { + if (prop in message && message[prop] !== null) { + that.config.message[prop] = message[prop]; + } + } + }); + } document.addEventListener('visibilitychange', function () { if (document.visibilityState == "visible") { @@ -52,6 +66,14 @@ const app = new Vue({ }); }); }, + getMessage: function (url) { + return fetch(url).then(function (response) { + if (response.status != 200) { + return; + } + return response.json(); + }); + }, toggleTheme: function() { this.isDark = !this.isDark; localStorage.overrideDark = this.isDark; @@ -60,6 +82,58 @@ const app = new Vue({ this.vlayout = !this.vlayout; localStorage.vlayout = this.vlayout; }, + toggleMenu: function() { + this.showMenu = !this.showMenu; + }, + matchesFilter: function(item) { + return (item.name.toLowerCase().includes(this.filter.toLowerCase()) + || (item.tag && item.tag.toLowerCase().includes(this.filter.toLowerCase()))) + }, + firstMatchingService: function() { + for (group of this.config.services) { + for (item of group.items) { + if (this.matchesFilter(item)) { + return item; + } + } + } + return null; + }, + navigateToFirstService: function(target) { + service = this.firstMatchingService(); + if (service) { + window.open(service.url, target || service.target || '_self'); + } + } + }, + mounted() { + function isSmallScreen() { + return window.matchMedia('screen and (max-width: 1023px)').matches; + } + this._keyListener = function(e) { + if (e.key === '/') { + if (isSmallScreen()) { + this.showMenu = true; + } + Vue.nextTick(() => { + this.$refs.search.focus(); + }); + + e.preventDefault(); + } + if (e.key === 'Escape') { + this.filter = ''; + this.$refs.search.blur(); + if (isSmallScreen()) { + this.showMenu = false; + } + } + } + + document.addEventListener('keydown', this._keyListener.bind(this)); + }, + beforeDestroy() { + document.removeEventListener('keydown', this._keyListener); } }); @@ -67,7 +141,7 @@ Vue.component('service', { props: ['item'], template: `
- +