|
@@ -0,0 +1,192 @@
|
|
|
|
+<!DOCTYPE html>
|
|
|
|
+<html lang="{{.Config.Language}}">
|
|
|
|
+
|
|
|
|
+<head>
|
|
|
|
+ <meta charset="UTF-8">
|
|
|
|
+ <title>{{.Config.Title}}</title>
|
|
|
|
+ <meta name="description" content="{{.Config.Description}}" />
|
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1">
|
|
|
|
+ <link rel="icon" type="image/png" href="/common/assets/favicon.ico" />
|
|
|
|
+ <link href="/theme/css/tailwind.min.css" rel="stylesheet">
|
|
|
|
+ <link rel="stylesheet" href="/common/css/all.min.css">
|
|
|
|
+ <link rel="stylesheet" href="/common/css/core.css">
|
|
|
|
+ <link rel="stylesheet" href="/theme/css/simplefox.css">
|
|
|
|
+ <link rel="stylesheet" href="/common/css/custom.css">
|
|
|
|
+
|
|
|
|
+ <script>
|
|
|
|
+ customElements.define("svg-file", class extends HTMLElement {
|
|
|
|
+ async connectedCallback(
|
|
|
|
+ src = this.getAttribute("src"),
|
|
|
|
+ shadowRoot = this.shadowRoot || this.attachShadow({ mode: "open" })
|
|
|
|
+ ) {
|
|
|
|
+ shadowRoot.innerHTML = await (await fetch(src)).text()
|
|
|
|
+ shadowRoot.append(...this.querySelectorAll("[shadowRoot]"))
|
|
|
|
+ this.hasAttribute("replaceWith") && this.replaceWith(...shadowRoot.childNodes)
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ </script>
|
|
|
|
+</head>
|
|
|
|
+
|
|
|
|
+<body>
|
|
|
|
+ <div class="grid place-items-center h-screen">
|
|
|
|
+ <div class="flex">
|
|
|
|
+ <div class="shrink place-items-center inset-0">
|
|
|
|
+ <div class="grid gap-4 grid-cols-2 grid-rows-2">
|
|
|
|
+ <div class="content-center">
|
|
|
|
+ <p id="clock" class="text-6xl font-bold text-center"></p>
|
|
|
|
+ <p id="greeting" class="text-2xl font-bold text-center"></p>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="content-center">
|
|
|
|
+ <p id="date" class="text-6xl font-bold text-center"></p>
|
|
|
|
+ <div id="weather-info" class="flex place-items-center gap-3 justify-center">
|
|
|
|
+ <div></div>
|
|
|
|
+ <canvas id="weather-icon" width="40" height="40"></canvas>
|
|
|
|
+ <p id="temp" class="text-2xl font-bold text-center"></p>
|
|
|
|
+ <p id="weather-desc" class="text-center"></p>
|
|
|
|
+ <div></div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="grid grid-cols-4 gap-4">
|
|
|
|
+ {{range (index (index .Contents 0).Columns 0).Bookmarks}}
|
|
|
|
+ <div class="hover:bg-gray-800 box rounded-lg p-10 drop-shadow-xl cursor-pointer" onclick="window.location.href='{{.Url}}'">
|
|
|
|
+ <div class="icon-container">
|
|
|
|
+ {{if .IsImage}}
|
|
|
|
+ <img src="{{.Icon}}" class="icon">
|
|
|
|
+ {{else if .IsSVG}}
|
|
|
|
+ <svg-file src="{{.Icon}}" class="svg-icon"></svg-file>
|
|
|
|
+ {{else}}
|
|
|
|
+ <i class="{{.Icon}} fa-2xl icon"></i>
|
|
|
|
+ {{end}}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ {{end}}
|
|
|
|
+ </div>
|
|
|
|
+ <div class="grid gap-4 grid-cols-2">
|
|
|
|
+ {{range (index .Contents 1).Columns}}
|
|
|
|
+ <div class="box rounded-lg drop-shadow-xl gap-2 p-5 grid grid-flow-row auto-rows-max justify-center">
|
|
|
|
+ <div class="icon-container-small mb-4">
|
|
|
|
+ <center>
|
|
|
|
+ {{if .IsImage}}
|
|
|
|
+ <img src="{{.Icon}}" class="icon">
|
|
|
|
+ {{else if .IsSVG}}
|
|
|
|
+ <svg-file src="{{.Icon}}" class="svg-icon"></svg-file>
|
|
|
|
+ {{else}}
|
|
|
|
+ <i class="{{.Icon}} fa-xl icon"></i>
|
|
|
|
+ {{end}}
|
|
|
|
+ </center>
|
|
|
|
+ </div>
|
|
|
|
+ {{range .Bookmarks}}
|
|
|
|
+ <a href="{{.Url}}" class="text-center">{{.Name}}</a>
|
|
|
|
+ {{end}}
|
|
|
|
+ </div>
|
|
|
|
+ {{end}}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <script src="/theme/js/skycons.min.js"></script>
|
|
|
|
+ <script src="/common/js/core.js"></script>
|
|
|
|
+ <script>
|
|
|
|
+ window.config = {
|
|
|
|
+ localization: {{.Config.Localization}},
|
|
|
|
+ language: {{.Config.Language}},
|
|
|
|
+ useMetric: {{.Config.UseMetric}}
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ (function setTimer() {
|
|
|
|
+ const clock = document.querySelector("#clock");
|
|
|
|
+ const datetb = document.querySelector("#date");
|
|
|
|
+ const clockOptions = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' };
|
|
|
|
+ (function clockTick() {
|
|
|
|
+ const now = new Date();
|
|
|
|
+ clock.innerText = `${now.getHours()}:${now.getMinutes().toLocaleString(window.config.localization, { minimumIntegerDigits: 2, useGrouping: false })}`;
|
|
|
|
+ datetb.innerText = now.toLocaleTimeString(window.config.localization, { month: 'short', day: 'numeric' }).split(',')[0];
|
|
|
|
+ setTimeout(clockTick, 2000);
|
|
|
|
+ })();
|
|
|
|
+ //Set greeting
|
|
|
|
+ const greeting = document.querySelector("#greeting");
|
|
|
|
+ const hour = new Date().getHours();
|
|
|
|
+ if (hour >= 5 && hour < 12) {
|
|
|
|
+ greeting.innerText = {{.Language.Greeting.Morning}};
|
|
|
|
+ }
|
|
|
|
+ else if (hour >= 12 && hour < 17) {
|
|
|
|
+ greeting.innerText = {{.Language.Greeting.Afternoon}};
|
|
|
|
+ }
|
|
|
|
+ else if (hour >= 17 && hour < 20) {
|
|
|
|
+ greeting.innerText = {{.Language.Greeting.Evening}};
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ greeting.innerText = {{.Language.Greeting.Night}};
|
|
|
|
+ }
|
|
|
|
+ }) ();
|
|
|
|
+
|
|
|
|
+ async function loadWeather() {
|
|
|
|
+ // Get info from api
|
|
|
|
+ const weather = await (await fetch("./weather")).json();
|
|
|
|
+ if (!weather) return;
|
|
|
|
+ // Parse weather id
|
|
|
|
+ let icon = null;
|
|
|
|
+ let weatherDesc = "";
|
|
|
|
+ let hour = new Date().getHours();
|
|
|
|
+ let isDay = hour >= 6 && hour < 18;
|
|
|
|
+ const weatherCode = weather.weather[0].id;
|
|
|
|
+ if ([200, 201, 202, 210, 211, 212, 221, 230, 231, 232].includes(weatherCode)) {
|
|
|
|
+ icon = Skycons.RAIN; //Thunderstorm
|
|
|
|
+ weatherDesc = {{.Language.Weather.Thunderstorm}};
|
|
|
|
+ } else if ([300, 301, 302, 310, 311, 312, 313, 314, 321].includes(weatherCode)) {
|
|
|
|
+ icon = Skycons.RAIN; //Drizzle
|
|
|
|
+ weatherDesc = {{.Language.Weather.Drizzle}};
|
|
|
|
+ } else if ([500, 501, 502, 503, 504, 511, 520, 521, 522, 531].includes(weatherCode)) {
|
|
|
|
+ icon = Skycons.RAIN;
|
|
|
|
+ weatherDesc = {{.Language.Weather.Rain}};
|
|
|
|
+ } else if ([600, 601, 602, 611, 612, 613, 615, 616, 620, 621, 622].includes(weatherCode)) {
|
|
|
|
+ icon = Skycons.SNOW;
|
|
|
|
+ weatherDesc = {{.Language.Weather.Snow}};
|
|
|
|
+ } else if (weatherCode === 800) {
|
|
|
|
+ icon = isDay ? Skycons.CLEAR_DAY : Skycons.CLEAR_NIGHT;
|
|
|
|
+ weatherDesc = isDay ? {{.Language.Weather.ClearDay}} : {{.Language.Weather.ClearNight}};
|
|
|
|
+ } else if ([801, 802, 803, 804].includes(weatherCode)) {
|
|
|
|
+ if (weatherCode >= 803) {
|
|
|
|
+ icon = Skycons.CLOUDY;
|
|
|
|
+ weatherDesc = {{.Language.Weather.Cloudy}};
|
|
|
|
+ } else {
|
|
|
|
+ icon = isDay ? Skycons.PARTLY_CLOUDY_DAY : Skycons.PARTLY_CLOUDY_NIGHT;
|
|
|
|
+ weatherDesc = isDay ? {{.Language.Weather.PartlyCloudyDay}} : {{.Language.Weather.PartlyCloudyNight}};
|
|
|
|
+ }
|
|
|
|
+ } else if ([762, 761, 751, 731, 721].includes(weatherCode)) {
|
|
|
|
+ icon = Skycons.SLEET;
|
|
|
|
+ weatherDesc = {{.Language.Weather.Sleet}};
|
|
|
|
+ } else if ([771, 781].includes(weatherCode)) {
|
|
|
|
+ icon = Skycons.WIND;
|
|
|
|
+ weatherDesc = {{.Language.Weather.Windy}};
|
|
|
|
+ } else if ([701, 711, 741].includes(weatherCode)) {
|
|
|
|
+ icon = Skycons.FOG;
|
|
|
|
+ weatherDesc = {{.Language.Weather.Foggy}};
|
|
|
|
+ } else {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // Set weather icon to canvas
|
|
|
|
+ var skycons = new Skycons({ "color": window.cssRoot["--accentColor"] });
|
|
|
|
+ skycons.add("weather-icon", icon);
|
|
|
|
+ skycons.play();
|
|
|
|
+ // Set weather info
|
|
|
|
+ if (window.config.useMetric) {
|
|
|
|
+ document.querySelector("#temp").innerText = Math.floor(weather.main.temp - 273.15) + "°C";
|
|
|
|
+ } else {
|
|
|
|
+ document.querySelector("#temp").innerText = Math.floor((weather.main.temp - 32) * 5 / 9) + "°F";
|
|
|
|
+ }
|
|
|
|
+ document.querySelector("#weather-info").style.visibility = "visible";
|
|
|
|
+ document.querySelector("#weather-desc").innerText = weatherDesc;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ (function weatherTick() {
|
|
|
|
+ loadWeather();
|
|
|
|
+ setTimeout(weatherTick, 3600000);
|
|
|
|
+ })();
|
|
|
|
+ </script>
|
|
|
|
+ <script src="/common/js/custom.js"></script>
|
|
|
|
+</body>
|
|
|
|
+
|
|
|
|
+</html>
|