Skip to content

Commit

Permalink
Add option to match system theme for light/dark mode (smogon#1921)
Browse files Browse the repository at this point in the history
  • Loading branch information
Karthik99999 authored Jan 31, 2022
1 parent 0191028 commit 9b58e8f
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 15 deletions.
25 changes: 19 additions & 6 deletions js/client-topbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -447,13 +447,13 @@
'change input[name=blockchallenges]': 'setBlockchallenges',
'change input[name=blockpms]': 'setBlockpms',
'change input[name=inchatpm]': 'setInchatpm',
'change input[name=dark]': 'setDark',
'change input[name=temporarynotifications]': 'setTemporaryNotifications',
'change input[name=refreshprompt]': 'setRefreshprompt',
'change select[name=bg]': 'setBg',
'change select[name=timestamps-lobby]': 'setTimestampsLobby',
'change select[name=timestamps-pms]': 'setTimestampsPMs',
'change select[name=onepanel]': 'setOnePanel',
'change select[name=theme]': 'setTheme',
'change input[name=logchat]': 'setLogChat',
'change input[name=selfhighlight]': 'setSelfHighlight',
'click img': 'avatars'
Expand All @@ -477,12 +477,18 @@

buf += '<hr />';
buf += '<p><strong>Graphics</strong></p>';
var theme = Dex.prefs('theme');
var colorSchemeQuerySupported = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').media !== 'not all';
buf += '<p><label class="optlabel">Theme: <select name="theme"><option value="light"' + (!theme || theme === 'light' ? ' selected="selected"' : '') + '>Light</option><option value="dark"' + (theme === 'dark' ? ' selected="selected"' : '') + '>Dark</option>';
if (colorSchemeQuerySupported) {
buf += '<option value="system"' + (theme === 'system' ? ' selected="selected"' : '') + '>Match system theme</option>';
}
buf += '</select></label></p>';
var onePanel = !!Dex.prefs('onepanel');
if ($(window).width() >= 660) {
buf += '<p><label class="optlabel">Layout: <select name="onepanel"><option value=""' + (!onePanel ? ' selected="selected"' : '') + '>&#x25EB; Left and right panels</option><option value="1"' + (onePanel ? ' selected="selected"' : '') + '>&#x25FB; Single panel</option></select></label></p>';
}
buf += '<p><label class="optlabel">Background: <button name="background">Change background</button></label></p>';
buf += '<p><label class="optlabel"><input type="checkbox" name="dark"' + (Dex.prefs('dark') ? ' checked' : '') + ' /> Dark mode</label></p>';
buf += '<p><label class="optlabel"><input type="checkbox" name="noanim"' + (Dex.prefs('noanim') ? ' checked' : '') + ' /> Disable animations</label></p>';
if (navigator.userAgent.includes(' Chrome/64.')) {
buf += '<p><label class="optlabel"><input type="checkbox" name="nogif"' + (Dex.prefs('nogif') ? ' checked' : '') + ' /> Disable GIFs for Chrome 64 bug</label></p>';
Expand Down Expand Up @@ -569,10 +575,17 @@
Storage.prefs('nogif', nogif);
Dex.loadSpriteData(nogif || Dex.prefs('bwgfx') ? 'bw' : 'xy');
},
setDark: function (e) {
var dark = !!e.currentTarget.checked;
Storage.prefs('dark', dark);
$('html').toggleClass('dark', dark);
setTheme: function (e) {
var theme = e.currentTarget.value;
Storage.prefs('theme', theme);
if (theme === 'system') {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
theme = 'dark';
} else {
theme = 'light';
}
}
$('html').toggleClass('dark', theme === 'dark');
},
setBwgfx: function (e) {
var bwgfx = !!e.currentTarget.checked;
Expand Down
10 changes: 9 additions & 1 deletion js/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,15 @@ function toId() {
var muted = Dex.prefs('mute');
BattleSound.setMute(muted);

$('html').toggleClass('dark', !!Dex.prefs('dark'));
var theme = Dex.prefs('theme');
var colorSchemeQuery = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)');
var dark = theme === 'dark' || (theme === 'system' && colorSchemeQuery && colorSchemeQuery.matches);
$('html').toggleClass('dark', dark);
if (colorSchemeQuery && colorSchemeQuery.media !== 'not all') {
colorSchemeQuery.addEventListener('change', function (cs) {
if (Dex.prefs('theme') === 'system') $('html').toggleClass('dark', cs.matches);
});
}

var effectVolume = Dex.prefs('effectvolume');
if (effectVolume !== undefined) BattleSound.setEffectVolume(effectVolume);
Expand Down
11 changes: 11 additions & 0 deletions js/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,17 @@ var updatePrefs = function () {
app.addPopupMessage('Your version of Chrome has a bug that makes animated GIFs freeze games sometimes, so certain animations have been disabled. Only some people have the problem, so you can experiment and enable them in the Options menu setting "Disable GIFs for Chrome 64 bug".');
});
}

var colorSchemeQuerySupported = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').media !== 'not all';
if (Storage.prefs('theme') === 'system' && !colorSchemeQuerySupported) {
Storage.prefs('theme', null);
}
if (Storage.prefs('dark') !== undefined) {
if (Storage.prefs('dark')) {
Storage.prefs('theme', 'dark');
}
Storage.prefs('dark', null);
}
};
Storage.whenPrefsLoaded(updatePrefs);

Expand Down
15 changes: 13 additions & 2 deletions src/client-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ const PSPrefsDefaults: {[key: string]: any} = {};
*/
class PSPrefs extends PSStreamModel<string | null> {
/**
* Dark mode!
* The theme to use. "system" matches the theme of the system accessing the client.
*/
dark = false;
theme: 'light' | 'dark' | 'system' = 'light';
/**
* Disables animated GIFs, but keeps other animations enabled.
* Workaround for a Chrome 64 bug with GIFs.
Expand Down Expand Up @@ -128,6 +128,17 @@ class PSPrefs extends PSStreamModel<string | null> {
newPrefs['nogif'] = true;
alert('Your version of Chrome has a bug that makes animated GIFs freeze games sometimes, so certain animations have been disabled. Only some people have the problem, so you can experiment and enable them in the Options menu setting "Disable GIFs for Chrome 64 bug".');
}

const colorSchemeQuerySupported = window.matchMedia?.('(prefers-color-scheme: dark)').media !== 'not all';
if (newPrefs['theme'] === 'system' && !colorSchemeQuerySupported) {
newPrefs['theme'] = 'light';
}
if (newPrefs['dark'] !== undefined) {
if (newPrefs['dark']) {
newPrefs['theme'] = 'dark';
}
delete newPrefs['dark'];
}
}
}

Expand Down
12 changes: 8 additions & 4 deletions src/panel-topbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -450,17 +450,21 @@ PS.roomTypes['volume'] = {
};

class OptionsPanel extends PSRoomPanel {
setCheckbox = (e: Event) => {
const checkbox = e.currentTarget as HTMLInputElement;
PS.prefs.set(checkbox.name as 'dark', !!checkbox.checked);
setTheme = (e: Event) => {
const theme = (e.currentTarget as HTMLSelectElement).value as 'light' | 'dark' | 'system';
PS.prefs.set('theme', theme);
this.forceUpdate();
};
render() {
const room = this.props.room;
return <PSPanelWrapper room={room}>
<h3>Graphics</h3>
<p>
<label class="checkbox"><input type="checkbox" name="dark" checked={PS.prefs.dark} onChange={this.setCheckbox} /> Dark mode</label>
<label class="optlabel">Theme: <select onChange={this.setTheme}>
<option value="light" selected={PS.prefs.theme === 'light'}>Light</option>
<option value="dark" selected={PS.prefs.theme === 'dark'}>Dark</option>
<option value="system" selected={PS.prefs.theme === 'system'}>Match system theme</option>
</select></label>
</p>
</PSPanelWrapper>;
}
Expand Down
13 changes: 11 additions & 2 deletions src/panels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,18 @@ class PSMain extends preact.Component {
}
});

const colorSchemeQuery = window.matchMedia?.('(prefers-color-scheme: dark)');
if (colorSchemeQuery?.media !== 'not all') {
colorSchemeQuery.addEventListener('change', function (cs) {
if (PS.prefs.theme === 'system') document.body.className = cs.matches ? 'dark' : '';
});
}

PS.prefs.subscribeAndRun(key => {
if (!key || key === 'dark') {
document.body.className = PS.prefs.dark ? 'dark' : '';
if (!key || key === 'theme') {
const dark = PS.prefs.theme === 'dark' ||
(PS.prefs.theme === 'system' && colorSchemeQuery && colorSchemeQuery.matches);
document.body.className = dark ? 'dark' : '';
}
});
}
Expand Down

0 comments on commit 9b58e8f

Please sign in to comment.