]>
Commit | Line | Data |
---|---|---|
1 | const app = new Vue({ | |
2 | el: '#app', | |
3 | data: { | |
4 | config: null, | |
5 | offline: false, | |
6 | filter: '', | |
7 | vlayout: true, | |
8 | isDark: null | |
9 | }, | |
10 | created: async function () { | |
11 | let that = this; | |
12 | ||
13 | this.isDark = 'overrideDark' in localStorage ? | |
14 | JSON.parse(localStorage.overrideDark) : matchMedia("(prefers-color-scheme: dark)").matches; | |
15 | ||
16 | if ('vlayout' in localStorage) { | |
17 | this.vlayout = JSON.parse(localStorage.vlayout) | |
18 | } | |
19 | ||
20 | this.checkOffline(); | |
21 | try { | |
22 | this.config = await this.getConfig(); | |
23 | document.title = this.config.title + ' | Homer'; | |
24 | } catch (error) { | |
25 | this.offline = true; | |
26 | } | |
27 | ||
28 | // Look for a new message if an endpoint is provided. | |
29 | if (this.config.message && this.config.message.url) { | |
30 | this.getMessage(this.config.message.url).then(function(message){ | |
31 | // keep the original config value if no value is provided by the endpoint | |
32 | for (const prop of ['title','style','content']) { | |
33 | if (prop in message && message[prop] !== null) { | |
34 | that.config.message[prop] = message[prop]; | |
35 | } | |
36 | } | |
37 | }); | |
38 | } | |
39 | ||
40 | document.addEventListener('visibilitychange', function () { | |
41 | if (document.visibilityState == "visible") { | |
42 | that.checkOffline(); | |
43 | } | |
44 | }, false); | |
45 | }, | |
46 | methods: { | |
47 | checkOffline: function () { | |
48 | let that = this; | |
49 | return fetch(window.location.href + "?alive", { | |
50 | method: 'HEAD', | |
51 | cache: 'no-store' | |
52 | }).then(function () { | |
53 | that.offline = false; | |
54 | }).catch(function () { | |
55 | that.offline = true; | |
56 | }); | |
57 | }, | |
58 | getConfig: function (event) { | |
59 | return fetch('config.yml').then(function (response) { | |
60 | if (response.status != 200) { | |
61 | return | |
62 | } | |
63 | return response.text().then(function (body) { | |
64 | return jsyaml.load(body); | |
65 | }); | |
66 | }); | |
67 | }, | |
68 | getMessage: function (url) { | |
69 | return fetch(url).then(function (response) { | |
70 | if (response.status != 200) { | |
71 | return; | |
72 | } | |
73 | return response.json(); | |
74 | }); | |
75 | }, | |
76 | toggleTheme: function() { | |
77 | this.isDark = !this.isDark; | |
78 | localStorage.overrideDark = this.isDark; | |
79 | }, | |
80 | toggleLayout: function() { | |
81 | this.vlayout = !this.vlayout; | |
82 | localStorage.vlayout = this.vlayout; | |
83 | }, | |
84 | } | |
85 | }); | |
86 | ||
87 | Vue.component('service', { | |
88 | props: ['item'], | |
89 | template: `<div> | |
90 | <div class="card"> | |
91 | <a :href="item.url" :target="item.target"> | |
92 | <div class="card-content"> | |
93 | <div class="media"> | |
94 | <div v-if="item.logo" class="media-left"> | |
95 | <figure class="image is-48x48"> | |
96 | <img :src="item.logo" /> | |
97 | </figure> | |
98 | </div> | |
99 | <div v-if="item.icon" class="media-left"> | |
100 | <figure class="image is-48x48"> | |
101 | <i style="font-size: 35px" :class="item.icon"></i> | |
102 | </figure> | |
103 | </div> | |
104 | <div class="media-content"> | |
105 | <p class="title is-4">{{ item.name }}</p> | |
106 | <p class="subtitle is-6">{{ item.subtitle }}</p> | |
107 | </div> | |
108 | </div> | |
109 | <div class="tag" :class="item.tagstyle" v-if="item.tag"> | |
110 | <strong class="tag-text">#{{ item.tag }}</strong> | |
111 | </div> | |
112 | </div> | |
113 | </a> | |
114 | </div></div>` | |
115 | }); | |
116 | ||
117 | if ('serviceWorker' in navigator) { | |
118 | window.addEventListener('load', function () { | |
119 | navigator.serviceWorker.register('worker.js'); | |
120 | }); | |
121 | } |