Skip to content
This repository was archived by the owner on Feb 7, 2025. It is now read-only.

Commit 07e5e51

Browse files
authored
DEV: A general code clean-up (#49)
Summary: * removed `computed` usage from a glimmer component * converted the component to gjs * converted the connector to gjs and made it into a regular glimmer component (w/ service injections and a getter instead of `setupComponent`) * used `session` service injection instead of Session singleton wherever possible * moved prop initialization out of a constructor * removed a use of string-based action * simplified showInSidebar logic * converted the initializer to the new class-based paradigm (w/ service injections) * added an escape hatch (isDestroying/isDestroyed check) to a `later` call * add a matching `removeEventListener` to `window.matchMedia(…).addEventListener` * used qunit-dom in tests
1 parent f4af152 commit 07e5e51

File tree

7 files changed

+132
-99
lines changed

7 files changed

+132
-99
lines changed

javascripts/discourse/components/color-scheme-toggler.js renamed to javascripts/discourse/components/color-scheme-toggler.gjs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
11
import Component from "@glimmer/component";
22
import { tracked } from "@glimmer/tracking";
3-
import { action, computed } from "@ember/object";
3+
import { action } from "@ember/object";
44
import { service } from "@ember/service";
5-
import Session from "discourse/models/session";
5+
import DButton from "discourse/components/d-button";
6+
import i18n from "discourse-common/helpers/i18n";
67
import {
78
COLOR_SCHEME_OVERRIDE_KEY,
89
colorSchemeOverride,
910
} from "../lib/color-scheme-override";
1011

1112
export default class ColorSchemeToggler extends Component {
1213
@service keyValueStore;
13-
@tracked storedOverride;
14+
@service session;
1415

15-
constructor() {
16-
super(...arguments);
17-
this.storedOverride = this.keyValueStore.getItem(COLOR_SCHEME_OVERRIDE_KEY);
18-
}
16+
@tracked
17+
storedOverride = this.keyValueStore.getItem(COLOR_SCHEME_OVERRIDE_KEY);
1918

20-
@computed("storedOverride")
2119
get toggleButtonIcon() {
2220
switch (this.OSMode) {
2321
case "dark":
@@ -56,8 +54,17 @@ export default class ColorSchemeToggler extends Component {
5654
this.keyValueStore.getItem(COLOR_SCHEME_OVERRIDE_KEY) || null;
5755

5856
// currently only used to flip category logos back/forth
59-
Session.currentProp("colorSchemeOverride", this.storedOverride);
57+
this.session.set("colorSchemeOverride", this.storedOverride);
6058

6159
colorSchemeOverride(this.storedOverride);
6260
}
61+
62+
<template>
63+
<DButton
64+
@action={{this.toggleScheme}}
65+
@icon={{this.toggleButtonIcon}}
66+
@translatedTitle={{i18n (themePrefix "toggle_button_title")}}
67+
class="color-scheme-toggler btn-flat"
68+
/>
69+
</template>
6370
}

javascripts/discourse/components/color-scheme-toggler.hbs

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import Component from "@glimmer/component";
2+
import { service } from "@ember/service";
3+
import ColorSchemeToggler from "../../components/color-scheme-toggler";
4+
5+
export default class TogglerButton extends Component {
6+
@service session;
7+
@service siteSettings;
8+
9+
get showInSidebar() {
10+
return (
11+
(this.session.darkModeAvailable ||
12+
this.siteSettings.default_dark_mode_color_scheme_id >= 0) &&
13+
!settings.add_color_scheme_toggle_to_header
14+
);
15+
}
16+
17+
<template>
18+
{{#if this.showInSidebar}}
19+
<ColorSchemeToggler />
20+
{{/if}}
21+
</template>
22+
}

javascripts/discourse/connectors/sidebar-footer-actions/toggler-button.hbs

Lines changed: 0 additions & 3 deletions
This file was deleted.

javascripts/discourse/connectors/sidebar-footer-actions/toggler-button.js

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,69 @@
1+
import { setOwner } from "@ember/owner";
12
import { later, schedule } from "@ember/runloop";
3+
import { service } from "@ember/service";
24
import { loadColorSchemeStylesheet } from "discourse/lib/color-scheme-picker";
35
import { withPluginApi } from "discourse/lib/plugin-api";
46
import { currentThemeId } from "discourse/lib/theme-selector";
5-
import Session from "discourse/models/session";
7+
import { bind } from "discourse-common/utils/decorators";
68
import ColorSchemeToggler from "../components/color-scheme-toggler";
79
import {
810
COLOR_SCHEME_OVERRIDE_KEY,
911
colorSchemeOverride,
1012
} from "../lib/color-scheme-override";
1113

12-
export default {
13-
name: "color-scheme-toggler",
14+
class TogglerInit {
15+
@service keyValueStore;
16+
@service session;
17+
@service siteSettings;
1418

15-
initialize(container) {
16-
const keyValueStore = container.lookup("service:key-value-store");
17-
const storedOverride = keyValueStore.getItem(COLOR_SCHEME_OVERRIDE_KEY);
19+
constructor(owner) {
20+
setOwner(this, owner);
1821

19-
if (!Session.currentProp("darkModeAvailable")) {
20-
const siteSettings = container.lookup("service:site-settings");
22+
const storedOverride = this.keyValueStore.getItem(
23+
COLOR_SCHEME_OVERRIDE_KEY
24+
);
2125

22-
if (siteSettings.default_dark_mode_color_scheme_id > 0) {
23-
loadColorSchemeStylesheet(
24-
siteSettings.default_dark_mode_color_scheme_id,
25-
currentThemeId(),
26-
true
27-
).then(() => {
28-
if (storedOverride) {
29-
colorSchemeOverride(storedOverride);
30-
} else {
31-
// ensures that this extra stylesheet isn't auto-used when OS is in dark mode
32-
document.querySelector("link#cs-preview-dark").media =
33-
"(prefers-color-scheme: none)";
34-
}
35-
});
36-
} else {
26+
if (!this.session.darkModeAvailable) {
27+
if (this.siteSettings.default_dark_mode_color_scheme_id <= 0) {
3728
// eslint-disable-next-line no-console
3829
console.warn(
3930
"No dark color scheme available, the discourse-color-scheme-toggle component has no effect."
4031
);
4132
return;
4233
}
34+
35+
loadColorSchemeStylesheet(
36+
this.siteSettings.default_dark_mode_color_scheme_id,
37+
currentThemeId(),
38+
true
39+
).then(() => {
40+
if (storedOverride) {
41+
colorSchemeOverride(storedOverride);
42+
} else {
43+
// ensures that this extra stylesheet isn't auto-used when OS is in dark mode
44+
document.querySelector("link#cs-preview-dark").media =
45+
"(prefers-color-scheme: none)";
46+
}
47+
});
4348
}
4449

4550
if (storedOverride) {
46-
Session.currentProp("colorSchemeOverride", storedOverride);
51+
this.session.set("colorSchemeOverride", storedOverride);
4752
}
4853

49-
if (Session.currentProp("darkModeAvailable") && storedOverride) {
54+
if (this.session.darkModeAvailable && storedOverride) {
5055
schedule("afterRender", () => {
5156
const logoDarkSrc = document.querySelector(".title picture source");
5257
// in some cases the logo widget is not yet rendered
5358
// so we schedule the calculation after a short delay
5459
if (!logoDarkSrc) {
55-
later(() => colorSchemeOverride(storedOverride), 500);
60+
later(() => {
61+
if (owner.isDestroying || owner.isDestroyed) {
62+
return;
63+
}
64+
65+
colorSchemeOverride(storedOverride);
66+
}, 500);
5667
} else {
5768
colorSchemeOverride(storedOverride);
5869
}
@@ -61,12 +72,7 @@ export default {
6172

6273
window
6374
.matchMedia("(prefers-color-scheme: dark)")
64-
.addEventListener("change", () => {
65-
// reset when switching OS dark mode
66-
keyValueStore.removeItem(COLOR_SCHEME_OVERRIDE_KEY);
67-
Session.currentProp("colorSchemeOverride", null);
68-
colorSchemeOverride();
69-
});
75+
.addEventListener("change", this.onColorChange);
7076

7177
if (settings.add_color_scheme_toggle_to_header) {
7278
withPluginApi("1.28.0", (api) => {
@@ -83,5 +89,32 @@ export default {
8389
);
8490
});
8591
}
92+
}
93+
94+
@bind
95+
onColorChange() {
96+
// reset when switching OS dark mode
97+
this.keyValueStore.removeItem(COLOR_SCHEME_OVERRIDE_KEY);
98+
this.session.set("colorSchemeOverride", null);
99+
colorSchemeOverride();
100+
}
101+
102+
teardown() {
103+
window
104+
.matchMedia("(prefers-color-scheme: dark)")
105+
.removeEventListener("change", this.onColorChange);
106+
}
107+
}
108+
109+
export default {
110+
name: "color-scheme-toggler",
111+
112+
initialize(owner) {
113+
this.instance = new TogglerInit(owner);
114+
},
115+
116+
teardown() {
117+
this.instance.teardown();
118+
this.instance = null;
86119
},
87120
};

test/acceptance/toggle-test.js

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,38 @@
11
import { visit } from "@ember/test-helpers";
22
import { test } from "qunit";
33
import Session from "discourse/models/session";
4-
import { acceptance, visible } from "discourse/tests/helpers/qunit-helpers";
4+
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
55

66
acceptance("Color Scheme Toggle - header icon", function (needs) {
7-
needs.hooks.beforeEach(() => {
7+
needs.hooks.beforeEach(function () {
88
settings.add_color_scheme_toggle_to_header = true;
9-
Session.currentProp("darkModeAvailable", true);
9+
Session.current().set("darkModeAvailable", true);
1010
});
1111

12-
needs.hooks.afterEach(() => {
13-
Session.currentProp("darkModeAvailable", null);
12+
needs.hooks.afterEach(function () {
13+
Session.current().set("darkModeAvailable", null);
1414
});
1515

1616
test("shows in header", async function (assert) {
1717
await visit("/");
1818

19-
assert.ok(
20-
visible(".header-color-scheme-toggle"),
21-
"button present in header"
22-
);
19+
assert
20+
.dom(".header-color-scheme-toggle")
21+
.exists("button present in header");
2322
});
2423
});
2524

2625
acceptance("Color Scheme Toggle - no op", function (needs) {
27-
needs.hooks.beforeEach(() => {
26+
needs.hooks.beforeEach(function () {
2827
settings.add_color_scheme_toggle_to_header = true;
2928
});
3029

3130
test("does not show when no dark color scheme available", async function (assert) {
3231
await visit("/");
3332

34-
assert.ok(
35-
!visible(".header-color-scheme-toggle"),
36-
"button is not present in header"
37-
);
33+
assert
34+
.dom(".header-color-scheme-toggle")
35+
.doesNotExist("button is not present in header");
3836
});
3937
});
4038

@@ -44,25 +42,25 @@ acceptance("Color Scheme Toggle - sidebar icon", function (needs) {
4442
enable_experimental_sidebar_hamburger: true,
4543
});
4644

47-
needs.hooks.beforeEach(() => {
45+
needs.hooks.beforeEach(function () {
4846
settings.add_color_scheme_toggle_to_header = false;
49-
Session.currentProp("darkModeAvailable", true);
47+
Session.current().set("darkModeAvailable", true);
5048
});
5149

52-
needs.hooks.afterEach(() => {
53-
Session.currentProp("darkModeAvailable", null);
50+
needs.hooks.afterEach(function () {
51+
Session.current().set("darkModeAvailable", null);
5452
});
5553

5654
test("shows in sidebar", async function (assert) {
5755
await visit("/");
5856

59-
assert.ok(
60-
!visible(".header-color-scheme-toggle"),
61-
"button not present in header"
62-
);
57+
assert
58+
.dom(".header-color-scheme-toggle")
59+
.doesNotExist("button not present in header");
6360

64-
const toggleButton = ".sidebar-footer-wrapper .color-scheme-toggler";
65-
assert.ok(visible(toggleButton), "button in footer");
61+
assert
62+
.dom(".sidebar-footer-wrapper .color-scheme-toggler")
63+
.exists("button in footer");
6664
});
6765
});
6866

@@ -83,19 +81,19 @@ acceptance("Color Scheme Toggle - sidebar icon", function (needs) {
8381
default_dark_mode_color_scheme_id: 2,
8482
});
8583

86-
needs.hooks.beforeEach(() => {
84+
needs.hooks.beforeEach(function () {
8785
settings.add_color_scheme_toggle_to_header = false;
8886
});
8987

9088
test("shows in sidebar if site has auto dark mode", async function (assert) {
9189
await visit("/");
9290

93-
assert.ok(
94-
!visible(".header-color-scheme-toggle"),
95-
"button not present in header"
96-
);
91+
assert
92+
.dom(".header-color-scheme-toggle")
93+
.doesNotExist("button not present in header");
9794

98-
const toggleButton = ".sidebar-footer-wrapper .color-scheme-toggler";
99-
assert.ok(visible(toggleButton), "button in footer");
95+
assert
96+
.dom(".sidebar-footer-wrapper .color-scheme-toggler")
97+
.exists("button in footer");
10098
});
10199
});

0 commit comments

Comments
 (0)