From e486f8c074644186ee93649b731bb9bf977c66db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bertrand?= Date: Mon, 14 Aug 2023 06:40:29 +0200 Subject: [PATCH] add sub clocks (#222) --- CHANGELOG.md | 6 ++++ src/css/moment.css | 15 +++++++++ src/moment.html | 17 ++++++++++ src/moment.ts | 83 ++++++++++++++++++++++++++++++++++++++++------ src/options.html | 60 ++++++++++++++++++++++++++++++--- src/options.ts | 61 +++++++++++++++++++++++++++++++++- src/settings.ts | 10 +++++- tsconfig.json | 4 +-- 8 files changed, 237 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6acf71b..4d8d79c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- Additional clocks (Thanks [Jouke van der Maas](https://github.com/joukevandermaas)) [#213](https://github.com/laedit/new-tab-moment/issues/213) + ## [0.12.1] - 2023-06-25 ### Changed diff --git a/src/css/moment.css b/src/css/moment.css index 42c39d9..85845ab 100644 --- a/src/css/moment.css +++ b/src/css/moment.css @@ -93,6 +93,21 @@ a { display: none; } +#subClocks { + font-weight: var(--font-weight-weather, 100); + font-size: .10em; + display: none; + margin: 20px 0; +} + +#subClocks > div { + display: none; +} + +#subClocks > div > div:nth-child(1) { + font-size: 1.5em; +} + @media only screen and (max-width: 700px) { body { font-size: 6em; diff --git a/src/moment.html b/src/moment.html index 417d2fc..71ba1a1 100644 --- a/src/moment.html +++ b/src/moment.html @@ -18,6 +18,23 @@ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
...
diff --git a/src/moment.ts b/src/moment.ts index 84281d2..315ef4c 100644 --- a/src/moment.ts +++ b/src/moment.ts @@ -2,14 +2,17 @@ let elementsMap: Record; let interval: number; function refresh(settings: Settings, language: string): void { - var dateTimeParts = new Intl.DateTimeFormat(language, { + let dateTimeFormatOptions: Intl.DateTimeFormatOptions = { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric", hour12: settings.clock === "12" - }).formatToParts(new Date()); + }; + const currentDate = new Date(); + const dateTimeParts = new Intl.DateTimeFormat(language, dateTimeFormatOptions).formatToParts(currentDate); + const useLeadingZero = settings.leadingZero && settings.clock === "12"; let hour = dateTimeParts.find(part => part.type == 'hour')?.value!; - if (settings.leadingZero && settings.clock === "12" && hour.length === 1) { + if (useLeadingZero && hour.length === 1) { hour = "0" + hour; } const timeText = settings.timePattern.replace("H", hour) @@ -21,6 +24,21 @@ function refresh(settings: Settings, language: string): void { .replace("Y", dateTimeParts.find(part => part.type == 'year')?.value!) .replace("M", dateTimeParts.find(part => part.type == 'month')?.value!); setValue(elementsMap.date, dateText); + + // set sub clocks + if (settings.subClocks) { + for (let index = 0; index < settings.subClocks.length; index++) { + const subClock = settings.subClocks[index]; + + dateTimeFormatOptions.timeZone = subClock.timeZone; + const subClockParts = new Intl.DateTimeFormat(language, dateTimeFormatOptions).formatToParts(currentDate); + let hour = subClockParts.find(part => part.type == 'hour')?.value!; + if (useLeadingZero && hour.length === 1) { + hour = "0" + hour; + } + setValue(elementsMap[`subClock${index + 1}Time`], `${hour}:${subClockParts.find(part => part.type == 'minute')?.value!}`); + } + } } async function displayWeather({ measurementUnits, location, displayIcon, activateDebugMode, displayHumidity, displayPressure, displayWind, useFeelsLikeTemperature }: Settings, language: string): Promise { @@ -201,18 +219,60 @@ async function load(): Promise { windGustText: document.getElementById("wind-gust-text")!, gust: document.getElementById("gust")!, error: document.getElementById("error")!, + subClocks: document.getElementById("subClocks")!, + subClock1: document.getElementById("subClock1")!, + subClock1Time: document.getElementById("subClock1Time")!, + subClock1TimeZone: document.getElementById("subClock1TimeZone")!, + subClock1Name: document.getElementById("subClock1Name")!, + subClock2: document.getElementById("subClock2")!, + subClock2Time: document.getElementById("subClock2Time")!, + subClock2TimeZone: document.getElementById("subClock2TimeZone")!, + subClock2Name: document.getElementById("subClock2Name")!, + subClock3: document.getElementById("subClock3")!, + subClock3Time: document.getElementById("subClock3Time")!, + subClock3TimeZone: document.getElementById("subClock3TimeZone")!, + subClock3Name: document.getElementById("subClock3Name")!, }; } // apply style settings setStyle(userSettings); + displaySubClocks(userSettings); + + // display cog icon + displayOptionIcon(userSettings); + startTime(userSettings, language); // get weather displayWeather(userSettings, language); +} - // display cog icon +function displaySubClocks(userSettings: Settings) { + if (userSettings.subClocks && userSettings.subClocks.length > 0) { + elementsMap.subClocks.style.display = "grid"; + elementsMap.subClocks.style.gridTemplateColumns = `repeat(${userSettings.subClocks.length}, 1fr)`; + + for (let index = 0; index < userSettings.subClocks.length; index++) { + const subClock = userSettings.subClocks[index]; + + elementsMap[`subClock${index + 1}`].style.display = "block"; + setValue(elementsMap[`subClock${index + 1}TimeZone`], subClock.displayTimeZone ? subClock.timeZone : ''); + setValue(elementsMap[`subClock${index + 1}Name`], subClock.name); + } + + if (userSettings.subClocks.length < 3) { + for (let index = userSettings.subClocks.length + 1; index < 4; index++) { + elementsMap[`subClock${index}`].style.display = "none"; + setValue(elementsMap[`subClock${index}TimeZone`], ''); + setValue(elementsMap[`subClock${index}Name`], ''); + } + } + } +} + +function displayOptionIcon(userSettings: Settings) { if (userSettings.displayOptionsButton) { let optionsLink = document.createElement("a"); optionsLink.setAttribute('id', 'options'); @@ -235,19 +295,20 @@ function isBackgroundDark(settings: Settings): boolean { case 'light': return false; case 'system': return window?.matchMedia?.('(prefers-color-scheme:dark)')?.matches; } - var rgbRegex = /^rgb\(([0-9]{1,3}),[ +]?([0-9]{1,3}),[ +]?([0-9]{1,3})\)$/; - var rgbMatch = document.documentElement.style.backgroundColor.match(rgbRegex)!; - var r = parseFloat(rgbMatch[1]); - var g = parseFloat(rgbMatch[2]); - var b = parseFloat(rgbMatch[3]); + const rgbRegex = /^rgb\(([0-9]{1,3}),[ +]?([0-9]{1,3}),[ +]?([0-9]{1,3})\)$/; + const rgbMatch = document.documentElement.style.backgroundColor.match(rgbRegex)!; + const r = parseFloat(rgbMatch[1]); + const g = parseFloat(rgbMatch[2]); + const b = parseFloat(rgbMatch[3]); - var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709 + const luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709 return luma < 128; } -async function getSettings() { +async function getSettings(): Promise { return browser.storage.sync.get(defaultSettings); } browser.storage.onChanged.addListener(async () => load()); + document.addEventListener("DOMContentLoaded", async () => load()); diff --git a/src/options.html b/src/options.html index 2576f11..1e0c32b 100644 --- a/src/options.html +++ b/src/options.html @@ -76,12 +76,63 @@

Appearance

+
+
+

Additional clocks:

+

First

+ + + +

Second

+ + + +

Third

+ + + +
+
+
@@ -98,6 +149,7 @@

Additional weather infos:

Display wind: +
@@ -168,11 +220,11 @@

Debug mode

-

-
+

+
-
-
+ +

Credits

diff --git a/src/options.ts b/src/options.ts index 217e19b..65c3f13 100644 --- a/src/options.ts +++ b/src/options.ts @@ -56,7 +56,8 @@ function saveOptions(e: Event): void { displayPressure: getInputValue("displayPressure") as boolean, displayHumidity: getInputValue("displayHumidity") as boolean, displayWind: getInputValue("displayWind") as boolean, - useFeelsLikeTemperature: getInputValue("useFeelsLikeTemperature") as boolean + useFeelsLikeTemperature: getInputValue("useFeelsLikeTemperature") as boolean, + subClocks: getSubClocks() }; browser.storage.sync.set(settings).catch(displayError); @@ -64,6 +65,31 @@ function saveOptions(e: Event): void { e.preventDefault(); } +function getSubClocks(): SubClock[] { + let subClocks: SubClock[] = []; + + for (let index = 1; index < 4; index++) { + let subClock = getSubClock(index); + if (subClock !== undefined) { + subClocks.push(subClock); + } + } + + return subClocks; +} + +function getSubClock(index: number): SubClock | undefined { + let subClockTimeZone = getInputValue(`subClock${index}TimeZone`) as string; + if (subClockTimeZone) { + return { + timeZone: subClockTimeZone, + displayTimeZone: getInputValue(`subClock${index}DisplayTimeZone`) as boolean, + name: getInputValue(`subClock${index}Name`) as string + }; + } + return undefined; +} + function restoreOptions(): void { browser.storage.sync.get(defaultSettings) .then(settings => { @@ -87,10 +113,43 @@ function restoreOptions(): void { setInputValue("displayWind", settings.displayWind); setInputValue("useFeelsLikeTemperature", settings.useFeelsLikeTemperature); colorSchemeOnChange(document.getElementById("colorScheme") as HTMLSelectElement); + restoreSubClocks(settings.subClocks); }) .catch(displayError); } +function restoreSubClocks(subClocks: SubClock[] | undefined) { + + for (let index = 1; index < 4; index++) { + const timeZonesSelect = document.getElementById(`subClock${index}TimeZone`) as HTMLSelectElement; + if (typeof Intl.supportedValuesOf === "undefined") { + // method is supported + let option = document.createElement("option"); + option.innerText = "Please update your browser to use this"; + timeZonesSelect.append(option) + } + else { + Intl.supportedValuesOf('timeZone').map((timeZone: string) => { + let option = document.createElement("option"); + option.value = timeZone; + option.innerText = timeZone; + timeZonesSelect.append(option) + }); + } + setInputValue(`subClock${index}DisplayTimeZone`, true); + } + + if (subClocks) { + subClocks.forEach((subClock, index) => { + console.debug(subClock); + console.debug(document.getElementById(`subClock${index + 1}TimeZone`)); + setInputValue(`subClock${index + 1}TimeZone`, subClock.timeZone); + setInputValue(`subClock${index + 1}DisplayTimeZone`, subClock.displayTimeZone); + setInputValue(`subClock${index + 1}Name`, subClock.name); + }); + } +} + function colorSchemeOnChange(elm: HTMLSelectElement) { const value = elm.value as ColorScheme; const enable = (value === "custom"); diff --git a/src/settings.ts b/src/settings.ts index e379679..cdeb34b 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -17,7 +17,8 @@ const defaultSettings: Settings = { displayPressure: false, displayHumidity: false, displayWind: false, - useFeelsLikeTemperature: false + useFeelsLikeTemperature: false, + subClocks: undefined }; type TempUnit = "celsius" | "fahrenheit"; @@ -47,4 +48,11 @@ type Settings = { displayHumidity: boolean; displayWind: boolean; useFeelsLikeTemperature: boolean; + subClocks?: SubClock[]; }; + +type SubClock = { + timeZone: string; + displayTimeZone: boolean; + name: string; +} diff --git a/tsconfig.json b/tsconfig.json index d9b233f..03f4496 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { /* Basic Options */ - "target": "ES2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ + "target": "ES2022", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ "module": "none", /* Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation: */ // "allowJs": true, /* Allow javascript files to be compiled. */ @@ -51,4 +51,4 @@ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ } -} \ No newline at end of file +}