Skip to content

Commit 04136fe

Browse files
committed
Add automatic theme
1 parent 9e0d3e8 commit 04136fe

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

src/components/common/tabbed-options.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ interface TabClickEvent extends React.MouseEvent {
1515
}
1616

1717
export const TabsContainer = styled((p: {
18-
onClick: (tabValue: any) => void,
19-
isSelected: (value: any) => boolean,
20-
children: Array<React.ReactElement<any, typeof Tab>>
18+
onClick: (tabValue: any) => void;
19+
isSelected: (value: any) => boolean;
20+
children: Array<React.ReactElement<any, typeof Tab>>;
21+
disabled?: boolean;
2122
}) => <nav
2223
{...omit(p, 'isSelected')}
2324
onClick={(event: TabClickEvent) => {
@@ -40,6 +41,11 @@ export const TabsContainer = styled((p: {
4041
flex-direction: column;
4142
justify-content: center;
4243
align-items: flex-start;
44+
45+
${p => p.disabled && css`
46+
opacity: 0.5;
47+
pointer-events: none;
48+
`}
4349
`;
4450

4551
export const Tab = styled((p: {

src/components/settings/settings-page.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ const AccountContactFooter = styled.div`
8686
}
8787
`;
8888

89+
const ThemeAutoButton = styled(SettingsButton)`
90+
margin: 10px 0;
91+
`;
92+
8993
const ThemeColors = styled.div`
9094
display: grid;
9195
grid-template-columns: 1fr 1fr;
@@ -286,8 +290,12 @@ class SettingsPage extends React.Component<SettingsPageProps> {
286290
Themes
287291
</CollapsibleCardHeading>
288292
</header>
293+
<ThemeAutoButton onClick={uiStore.toggleAutoTheme}>
294+
{uiStore.autoTheme ? 'Use specific theme' : 'Use automatic theme'}
295+
</ThemeAutoButton>
289296
<TabbedOptionsContainer>
290297
<TabsContainer
298+
disabled={uiStore.autoTheme}
291299
onClick={(value: ThemeName | Theme) => uiStore.setTheme(value)}
292300
isSelected={(value: ThemeName | Theme) => {
293301
if (typeof value === 'string') {
@@ -311,7 +319,7 @@ class SettingsPage extends React.Component<SettingsPageProps> {
311319
</Tab>
312320
<Tab
313321
icon={['fas', 'adjust']}
314-
value={'high-contrast'}
322+
value='high-contrast'
315323
>
316324
High Contrast
317325
</Tab>

src/model/ui/ui-store.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,25 @@ export class UiStore {
111111
// logout & subscription expiration (even if that happened while the app was
112112
// closed), but don't get reset when the app starts with stale account data.
113113
observe(this.accountStore, 'accountDataLastUpdated', () => {
114-
if (!this.accountStore.isPaidUser) this.setTheme('light');
114+
if (!this.accountStore.isPaidUser) {
115+
this.autoTheme = false;
116+
this.setTheme('light');
117+
}
115118
});
116119

117120
await hydrate({
118121
key: 'ui-store',
119122
store: this
120123
});
121124

125+
const darkThemeMq = window.matchMedia("(prefers-color-scheme: dark)");
126+
this._prefersDarkTheme = darkThemeMq.matches;
127+
this._updateAutoTheme();
128+
darkThemeMq.addEventListener('change', e => {
129+
this._prefersDarkTheme = e.matches;
130+
this._updateAutoTheme();
131+
});
132+
122133
console.log('UI store initialized');
123134
});
124135

@@ -152,6 +163,26 @@ export class UiStore {
152163
}
153164
}
154165

166+
/**
167+
* Stores if user prefers a dark color theme (for example when set in system settings).
168+
* Used if automatic theme is enabled.
169+
*/
170+
private _prefersDarkTheme: boolean = false;
171+
172+
@persist @observable
173+
autoTheme: boolean = false;
174+
175+
@action.bound
176+
toggleAutoTheme() {
177+
this.autoTheme = !this.autoTheme
178+
this._updateAutoTheme();
179+
}
180+
181+
private _updateAutoTheme() {
182+
if (!this.autoTheme) return;
183+
this.setTheme(this._prefersDarkTheme ? 'dark' : 'light');
184+
}
185+
155186
// Set briefly at the moment any card expansion is toggled, to trigger animation for the expansion as it's
156187
// applied, not always (to avoid animating expanded cards when they're rendered e.g. when selecting a request).
157188
@observable

0 commit comments

Comments
 (0)