Skip to content

Commit

Permalink
refactor(frontend): move appearance stuff into service (#539)
Browse files Browse the repository at this point in the history
  • Loading branch information
c0rydoras authored Dec 16, 2024
1 parent bc189df commit 181db3f
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 65 deletions.
69 changes: 4 additions & 65 deletions frontend/app/protected/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -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<getHtml>} 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<getHtml>} 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;
Expand All @@ -74,6 +12,7 @@ export default class ProtectedController extends Controller {
@service currentUser;
@service("autostart-tour") autostartTour;
@service tour;
@service appearance;

@tracked visible;
@tracked loading;
Expand Down Expand Up @@ -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();
}
}
81 changes: 81 additions & 0 deletions frontend/app/services/appearance.js
Original file line number Diff line number Diff line change
@@ -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<getHtml>} 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<getHtml>} 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);
}
}
11 changes: 11 additions & 0 deletions frontend/tests/unit/services/appearance-test.js
Original file line number Diff line number Diff line change
@@ -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);
});
});

0 comments on commit 181db3f

Please sign in to comment.