Skip to content

Commit 1336b7c

Browse files
committed
services/color-scheme: Add watcherTask and resolvedScheme property
1 parent 5aed44f commit 1336b7c

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

app/services/color-scheme.js

+39
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { action } from '@ember/object';
22
import Service from '@ember/service';
33
import { tracked } from '@glimmer/tracking';
44

5+
import { restartableTask, waitForEvent } from 'ember-concurrency';
6+
57
import * as localStorage from '../utils/local-storage';
68

79
const DEFAULT_SCHEME = 'light';
@@ -10,6 +12,16 @@ const LS_KEY = 'color-scheme';
1012

1113
export default class DesignService extends Service {
1214
@tracked _scheme = localStorage.getItem(LS_KEY);
15+
@tracked resolvedScheme;
16+
17+
constructor() {
18+
super(...arguments);
19+
this.restartWatcherTask();
20+
}
21+
22+
get isDark() {
23+
return this.resolvedScheme === 'dark';
24+
}
1325

1426
get scheme() {
1527
return VALID_SCHEMES.has(this._scheme) ? this._scheme : DEFAULT_SCHEME;
@@ -18,5 +30,32 @@ export default class DesignService extends Service {
1830
@action set(scheme) {
1931
this._scheme = scheme;
2032
localStorage.setItem(LS_KEY, scheme);
33+
this.restartWatcherTask();
2134
}
35+
36+
restartWatcherTask() {
37+
this.watcherTask.perform().catch(() => {
38+
// Ignore Promise rejections. This shouldn't be able to fail, and task cancellations are expected.
39+
});
40+
}
41+
42+
/**
43+
* This task watches for changes in the system color scheme and updates the `resolvedScheme` property accordingly.
44+
*/
45+
watcherTask = restartableTask(async () => {
46+
let mediaQueryList = window.matchMedia('(prefers-color-scheme: dark)');
47+
// eslint-disable-next-line no-constant-condition
48+
while (true) {
49+
let scheme = this.scheme;
50+
if (scheme === 'system') {
51+
scheme = mediaQueryList.matches ? 'dark' : 'light';
52+
}
53+
54+
if (this.resolvedScheme !== scheme) {
55+
this.resolvedScheme = scheme;
56+
}
57+
58+
await waitForEvent(mediaQueryList, 'change');
59+
}
60+
});
2261
}

0 commit comments

Comments
 (0)