Skip to content

Commit 946f418

Browse files
authored
impr: randomize themes based on system theme (@fehmer) (monkeytypegame#7075)
closes monkeytypegame#7069
1 parent c76f8dc commit 946f418

File tree

3 files changed

+28
-11
lines changed

3 files changed

+28
-11
lines changed

frontend/src/html/pages/settings.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1469,14 +1469,17 @@
14691469
random themes are not saved to your config. If set to 'favorite' only
14701470
favorite themes will be randomized. If set to 'light' or 'dark', only
14711471
presets with light or dark background colors will be randomized,
1472-
respectively. If set to 'custom', custom themes will be randomized.
1472+
respectively. If set to 'auto' dark or light themes are used, depending
1473+
on your system theme. If set to 'custom', custom themes will be
1474+
randomized.
14731475
</div>
14741476
<div class="buttons">
14751477
<button data-config-value="off">off</button>
14761478
<button data-config-value="on">on</button>
14771479
<button data-config-value="fav">favorite</button>
14781480
<button data-config-value="light">light</button>
14791481
<button data-config-value="dark">dark</button>
1482+
<button data-config-value="auto">auto</button>
14801483
<button data-config-value="custom">custom</button>
14811484
</div>
14821485
</div>

frontend/src/ts/controllers/theme-controller.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import * as Notifications from "../elements/notifications";
1111
import * as Loader from "../elements/loader";
1212
import { debounce } from "throttle-debounce";
1313
import { ThemeName } from "@monkeytype/schemas/configs";
14-
import { ThemesList } from "../constants/themes";
14+
import { themes, ThemesList } from "../constants/themes";
1515
import fileStorage from "../utils/file-storage";
1616

1717
export let randomTheme: ThemeName | string | null = null;
@@ -307,7 +307,7 @@ async function changeThemeList(): Promise<void> {
307307
themesList = themes
308308
.filter((t) => isColorDark(t.bgColor))
309309
.map((t) => t.name);
310-
} else if (Config.randomTheme === "on") {
310+
} else if (Config.randomTheme === "on" || Config.randomTheme === "auto") {
311311
themesList = themes.map((t) => {
312312
return t.name;
313313
});
@@ -323,14 +323,23 @@ export async function randomizeTheme(): Promise<void> {
323323
await changeThemeList();
324324
if (themesList.length === 0) return;
325325
}
326-
randomTheme = themesList[randomThemeIndex] as string;
327-
randomThemeIndex++;
328326

329-
if (randomThemeIndex >= themesList.length) {
330-
Arrays.shuffle(themesList);
331-
randomThemeIndex = 0;
327+
let filter = (_: string): boolean => true;
328+
if (Config.randomTheme === "auto") {
329+
filter = prefersColorSchemeDark() ? isColorDark : isColorLight;
332330
}
333331

332+
let nextTheme = null;
333+
do {
334+
randomTheme = themesList[randomThemeIndex] as string;
335+
nextTheme = themes[themesList[randomThemeIndex] as ThemeName];
336+
randomThemeIndex++;
337+
if (randomThemeIndex >= themesList.length) {
338+
Arrays.shuffle(themesList);
339+
randomThemeIndex = 0;
340+
}
341+
} while (!filter(nextTheme.bgColor));
342+
334343
let colorsOverride: string[] | undefined;
335344

336345
if (Config.randomTheme === "custom") {
@@ -484,7 +493,7 @@ ConfigEvent.subscribe(async (eventKey, eventValue, nosave) => {
484493
await clearRandom();
485494
await clearPreview(false);
486495
if (Config.autoSwitchTheme) {
487-
if (window.matchMedia?.("(prefers-color-scheme: dark)").matches) {
496+
if (prefersColorSchemeDark()) {
488497
await set(Config.themeDark, true);
489498
} else {
490499
await set(Config.themeLight, true);
@@ -523,7 +532,7 @@ ConfigEvent.subscribe(async (eventKey, eventValue, nosave) => {
523532
if (eventKey === "customBackgroundSize") applyCustomBackgroundSize();
524533
if (eventKey === "autoSwitchTheme") {
525534
if (eventValue as boolean) {
526-
if (window.matchMedia?.("(prefers-color-scheme: dark)").matches) {
535+
if (prefersColorSchemeDark()) {
527536
await set(Config.themeDark, true);
528537
} else {
529538
await set(Config.themeLight, true);
@@ -535,7 +544,7 @@ ConfigEvent.subscribe(async (eventKey, eventValue, nosave) => {
535544
if (
536545
eventKey === "themeLight" &&
537546
Config.autoSwitchTheme &&
538-
!window.matchMedia?.("(prefers-color-scheme: dark)").matches &&
547+
!prefersColorSchemeDark() &&
539548
!nosave
540549
) {
541550
await set(Config.themeLight, true);
@@ -569,3 +578,7 @@ window.addEventListener("customBackgroundFailed", () => {
569578
{ duration: 5 }
570579
);
571580
});
581+
582+
function prefersColorSchemeDark(): boolean {
583+
return window.matchMedia?.("(prefers-color-scheme: dark)").matches;
584+
}

packages/schemas/src/configs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export const RandomThemeSchema = z.enum([
6868
"light",
6969
"dark",
7070
"custom",
71+
"auto",
7172
]);
7273
export type RandomTheme = z.infer<typeof RandomThemeSchema>;
7374

0 commit comments

Comments
 (0)