From 181db3fb93ecb1f8520e645136ee66307d00439b Mon Sep 17 00:00:00 2001 From: Arthur <110528300+c0rydoras@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:39:02 +0100 Subject: [PATCH] refactor(frontend): move appearance stuff into service (#539) --- frontend/app/protected/controller.js | 69 +--------------- frontend/app/services/appearance.js | 81 +++++++++++++++++++ .../tests/unit/services/appearance-test.js | 11 +++ 3 files changed, 96 insertions(+), 65 deletions(-) create mode 100644 frontend/app/services/appearance.js create mode 100644 frontend/tests/unit/services/appearance-test.js diff --git a/frontend/app/protected/controller.js b/frontend/app/protected/controller.js index b3d666011..3d2739291 100644 --- a/frontend/app/protected/controller.js +++ b/frontend/app/protected/controller.js @@ -4,68 +4,6 @@ import { service } from "@ember/service"; import { tracked } from "@glimmer/tracking"; import { keyResponder, onKey } from "ember-keyboard"; -const getHtml = () => document.querySelector("html"); - -const COLOR_SCHEME_KEY = "color-scheme"; -const THEME_KEY = "theme"; - -/** - * Sets dark or light mode - * @param {"light" | "dark"} colorScheme - * @param {ReturnType} html - **/ -const setColorScheme = (colorScheme, html = null) => { - const _html = html ?? getHtml(); - localStorage.setItem(COLOR_SCHEME_KEY, colorScheme); - - if (colorScheme === "light") { - _html.classList.remove("dark"); - return; - } - _html.classList.add("dark"); -}; - -const THEMES = /** @type {const} */ (["old", "regular"]); - -/** - * Sets regular or old color scheme - * @param {typeof THEMES[number]} theme - * @param {ReturnType} html - **/ -const setTheme = (theme, html = null) => { - const _html = html ?? getHtml(); - localStorage.setItem(THEME_KEY, theme); - - if (_html.classList.contains(theme)) { - return; - } - _html.classList.remove(...THEMES.filter((t) => t !== theme)); - _html.classList.add(theme); -}; - -const loadConfiguration = () => { - const colorScheme = - localStorage.getItem(COLOR_SCHEME_KEY) ?? - (window.matchMedia("(prefers-color-scheme:dark)").matches - ? "dark" - : "light"); - const theme = localStorage.getItem(THEME_KEY) ?? THEMES[0]; - const html = getHtml(); - setTheme(theme, html); - setColorScheme(colorScheme, html); -}; - -const toggleColorScheme = () => - setColorScheme( - localStorage.getItem(COLOR_SCHEME_KEY) === "dark" ? "light" : "dark", - ); - -const cycleTheme = () => { - const currentTheme = localStorage.getItem(THEME_KEY); - const newTheme = THEMES[THEMES.indexOf(currentTheme) + 1] ?? THEMES[0]; - setTheme(newTheme); -}; - @keyResponder export default class ProtectedController extends Controller { @service notify; @@ -74,6 +12,7 @@ export default class ProtectedController extends Controller { @service currentUser; @service("autostart-tour") autostartTour; @service tour; + @service appearance; @tracked visible; @tracked loading; @@ -141,18 +80,18 @@ export default class ProtectedController extends Controller { constructor(...args) { super(...args); - loadConfiguration(); + this.appearance.loadConfiguration(); } @onKey("ctrl+,") _toggleColorScheme(e) { e.preventDefault(); - toggleColorScheme(); + this.appearance.toggleColorScheme(); } @onKey("ctrl+.") _cycleTheme(e) { e.preventDefault(); - cycleTheme(); + this.appearance.cycleTheme(); } } diff --git a/frontend/app/services/appearance.js b/frontend/app/services/appearance.js new file mode 100644 index 000000000..4e7ee1a87 --- /dev/null +++ b/frontend/app/services/appearance.js @@ -0,0 +1,81 @@ +import { action } from "@ember/object"; +import Service from "@ember/service"; + +const getHtml = () => document.querySelector("html"); + +const COLOR_SCHEME_KEY = "color-scheme"; +const THEME_KEY = "theme"; + +const THEMES = /** @type {const} */ (["old", "regular"]); + +export default class AppearanceService extends Service { + constructor(...args) { + super(...args); + this.loadConfiguration(); + } + + loadConfiguration() { + const colorScheme = + this.colorScheme ?? + (window.matchMedia("(prefers-color-scheme:dark)").matches + ? "dark" + : "light"); + const theme = this.theme ?? THEMES[0]; + const html = getHtml(); + this.setTheme(theme, html); + this.setColorScheme(colorScheme, html); + } + + /** + * Sets dark or light mode + * @param {"light" | "dark"} colorScheme + * @param {ReturnType} html + **/ + @action + setColorScheme(colorScheme, html = null) { + const _html = html ?? getHtml(); + localStorage.setItem(COLOR_SCHEME_KEY, colorScheme); + + if (colorScheme === "light") { + _html.classList.remove("dark"); + return; + } + _html.classList.add("dark"); + } + + /** + * Sets regular or old color scheme + * @param {typeof THEMES[number]} theme + * @param {ReturnType} html + **/ + @action + setTheme(theme, html = null) { + const _html = html ?? getHtml(); + localStorage.setItem(THEME_KEY, theme); + + if (_html.classList.contains(theme)) { + return; + } + _html.classList.remove(...THEMES.filter((t) => t !== theme)); + _html.classList.add(theme); + } + + @action + toggleColorScheme() { + this.setColorScheme(this.colorScheme === "dark" ? "light" : "dark"); + } + + @action + cycleTheme() { + const newTheme = THEMES[THEMES.indexOf(this.theme) + 1] ?? THEMES[0]; + this.setTheme(newTheme); + } + + get theme() { + return localStorage.getItem(THEME_KEY); + } + + get colorScheme() { + return localStorage.getItem(COLOR_SCHEME_KEY); + } +} diff --git a/frontend/tests/unit/services/appearance-test.js b/frontend/tests/unit/services/appearance-test.js new file mode 100644 index 000000000..bcfb53ff2 --- /dev/null +++ b/frontend/tests/unit/services/appearance-test.js @@ -0,0 +1,11 @@ +import { module, test } from "qunit"; +import { setupTest } from "timed/tests/helpers"; + +module("Unit | Service | appearance", function (hooks) { + setupTest(hooks); + + test("it exists", function (assert) { + const service = this.owner.lookup("service:appearance"); + assert.ok(service); + }); +});