Skip to content

Commit 5697cf9

Browse files
committed
frontend/dark-mode: update darkreader, improve config, remove unused config param grayscale, refactor code
1 parent e468623 commit 5697cf9

File tree

8 files changed

+126
-105
lines changed

8 files changed

+126
-105
lines changed

src/packages/frontend/account/dark-mode.ts

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,21 @@
33
* License: MS-RSL – see LICENSE.md for details
44
*/
55

6-
import { throttle, isEqual } from "lodash";
6+
import { throttle, isEqual, debounce } from "lodash";
7+
8+
import { DARK_MODE_DEFAULTS } from "@cocalc/util/db-schema/accounts";
79
import { AccountStore } from "./store";
810

9-
export const dark_mode_mins = {
10-
brightness: 20,
11-
contrast: 20,
11+
export const DARK_MODE_KEYS = ["brightness", "contrast", "sepia"] as const;
12+
13+
type Config = Record<(typeof DARK_MODE_KEYS)[number], number>;
14+
15+
export const DARK_MODE_MINS: Config = {
16+
brightness: 30,
17+
contrast: 30,
1218
sepia: 0,
13-
grayscale: 0,
1419
} as const;
1520

16-
interface Config {
17-
brightness: number;
18-
contrast: number;
19-
sepia: number;
20-
grayscale: number;
21-
}
22-
2321
// Returns number between 0 and 100.
2422
function to_number(x: any, default_value: number): number {
2523
if (x == null) return default_value;
@@ -44,25 +42,17 @@ export function get_dark_mode_config(other_settings?: {
4442
dark_mode_brightness?: number;
4543
dark_mode_contrast?: number;
4644
dark_mode_sepia?: number;
47-
dark_mode_grayscale?: number;
4845
}): Config {
49-
const brightness = Math.max(
50-
dark_mode_mins.brightness,
51-
to_number(other_settings?.dark_mode_brightness, 100),
52-
);
53-
const contrast = Math.max(
54-
dark_mode_mins.contrast,
55-
to_number(other_settings?.dark_mode_contrast, 90),
56-
);
57-
const sepia = to_number(
58-
other_settings?.dark_mode_sepia,
59-
dark_mode_mins.sepia,
60-
);
61-
const grayscale = to_number(
62-
other_settings?.dark_mode_grayscale,
63-
dark_mode_mins.grayscale,
64-
);
65-
return { brightness, contrast, sepia, grayscale };
46+
const config = {} as Config;
47+
48+
for (const key of DARK_MODE_KEYS) {
49+
config[key] = Math.max(
50+
DARK_MODE_MINS[key],
51+
to_number(other_settings?.[`dark_mode_${key}`], DARK_MODE_DEFAULTS[key]),
52+
);
53+
}
54+
55+
return config;
6656
}
6757

6858
let currentDarkMode: boolean = false;
@@ -71,7 +61,7 @@ let last_config: Config | undefined = undefined;
7161
export function init_dark_mode(account_store: AccountStore): void {
7262
account_store.on(
7363
"change",
74-
throttle(async () => {
64+
debounce(async () => {
7565
const dark_mode = !!account_store.getIn(["other_settings", "dark_mode"]);
7666
currentDarkMode = dark_mode;
7767
const config = get_dark_mode_config(
@@ -87,11 +77,12 @@ export function init_dark_mode(account_store: AccountStore): void {
8777
last_dark_mode = dark_mode;
8878
last_config = config;
8979
if (dark_mode) {
80+
disable();
9081
enable(config);
9182
} else {
9283
disable();
9384
}
94-
}, 3000),
85+
}, 1000, {trailing: true, leading: false}),
9586
);
9687
}
9788

src/packages/frontend/account/other-settings.tsx

Lines changed: 68 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
* License: MS-RSL – see LICENSE.md for details
44
*/
55

6-
import { Card, InputNumber } from "antd";
6+
import { Button, Card, Slider } from "antd";
7+
import { debounce } from "lodash";
78
import { Map } from "immutable";
8-
import { FormattedMessage, useIntl } from "react-intl";
9+
import { useMemo } from "react";
10+
import { defineMessages, FormattedMessage, useIntl } from "react-intl";
911

1012
import { Checkbox, Panel } from "@cocalc/frontend/antd-bootstrap";
1113
import { Rendered, redux, useTypedRedux } from "@cocalc/frontend/app-framework";
@@ -41,13 +43,33 @@ import track from "@cocalc/frontend/user-tracking";
4143
import { webapp_client } from "@cocalc/frontend/webapp-client";
4244
import { DEFAULT_NEW_FILENAMES, NEW_FILENAMES } from "@cocalc/util/db-schema";
4345
import { OTHER_SETTINGS_REPLY_ENGLISH_KEY } from "@cocalc/util/i18n/const";
44-
import { dark_mode_mins, get_dark_mode_config } from "./dark-mode";
46+
import {
47+
DARK_MODE_KEYS,
48+
DARK_MODE_MINS,
49+
get_dark_mode_config,
50+
} from "./dark-mode";
51+
import { DARK_MODE_DEFAULTS } from "@cocalc/util/db-schema/accounts";
4552
import { I18NSelector, I18N_MESSAGE, I18N_TITLE } from "./i18n-selector";
4653
import Messages from "./messages";
4754
import Tours from "./tours";
4855
import { useLanguageModelSetting } from "./useLanguageModelSetting";
4956
import { UserDefinedLLMComponent } from "./user-defined-llm";
5057

58+
const DARK_MODE_LABELS = defineMessages({
59+
brightness: {
60+
id: "account.other-settings.theme.dark_mode.brightness",
61+
defaultMessage: "Brightness",
62+
},
63+
contrast: {
64+
id: "account.other-settings.theme.dark_mode.contrast",
65+
defaultMessage: "Contrast",
66+
},
67+
sepia: {
68+
id: "account.other-settings.theme.dark_mode.sepia",
69+
defaultMessage: "Sepia",
70+
},
71+
});
72+
5173
// See https://github.com/sagemathinc/cocalc/issues/5620
5274
// There are weird bugs with relying only on mathjax, whereas our
5375
// implementation of katex with a fallback to mathjax works very well.
@@ -79,6 +101,17 @@ export function OtherSettings(props: Readonly<Props>): React.JSX.Element {
79101
redux.getActions("account").set_other_settings(name, value);
80102
}
81103

104+
// Debounced version for dark mode sliders to reduce CPU usage
105+
const on_change_dark_mode = useMemo(
106+
() =>
107+
debounce(
108+
(name: string, value: any) => on_change(name, value),
109+
50,
110+
{ trailing: true, leading: false }
111+
),
112+
[]
113+
);
114+
82115
function toggle_global_banner(val: boolean): void {
83116
if (val) {
84117
// this must be "null", not "undefined" – otherwise the data isn't stored in the DB.
@@ -363,7 +396,6 @@ export function OtherSettings(props: Readonly<Props>): React.JSX.Element {
363396
function render_dark_mode(): Rendered {
364397
const checked = !!props.other_settings.get("dark_mode");
365398
const config = get_dark_mode_config(props.other_settings.toJS());
366-
const label_style = { width: "100px", display: "inline-block" } as const;
367399
return (
368400
<div>
369401
<Checkbox
@@ -400,57 +432,38 @@ export function OtherSettings(props: Readonly<Props>): React.JSX.Element {
400432
defaultMessage: "Dark Mode Configuration",
401433
})}
402434
>
403-
<span style={label_style}>
404-
<FormattedMessage
405-
id="account.other-settings.theme.dark_mode.brightness"
406-
defaultMessage="Brightness"
407-
/>
408-
</span>
409-
<InputNumber
410-
min={dark_mode_mins.brightness}
411-
max={100}
412-
value={config.brightness}
413-
onChange={(x) => on_change("dark_mode_brightness", x)}
414-
/>
415-
<br />
416-
<span style={label_style}>
417-
<FormattedMessage
418-
id="account.other-settings.theme.dark_mode.contrast"
419-
defaultMessage="Contrast"
420-
/>
421-
</span>
422-
<InputNumber
423-
min={dark_mode_mins.contrast}
424-
max={100}
425-
value={config.contrast}
426-
onChange={(x) => on_change("dark_mode_contrast", x)}
427-
/>
428-
<br />
429-
<span style={label_style}>
430-
<FormattedMessage
431-
id="account.other-settings.theme.dark_mode.sepia"
432-
defaultMessage="Sepia"
433-
/>
434-
</span>
435-
<InputNumber
436-
min={dark_mode_mins.sepia}
437-
max={100}
438-
value={config.sepia}
439-
onChange={(x) => on_change("dark_mode_sepia", x)}
440-
/>
441-
<br />
442-
<span style={label_style}>
443-
<FormattedMessage
444-
id="account.other-settings.theme.dark_mode.grayscale"
445-
defaultMessage="Grayscale"
446-
/>
447-
</span>
448-
<InputNumber
449-
min={dark_mode_mins.grayscale}
450-
max={100}
451-
value={config.grayscale}
452-
onChange={(x) => on_change("dark_mode_grayscale", x)}
453-
/>
435+
<div style={{ display: "flex", flexDirection: "column", gap: 5 }}>
436+
{DARK_MODE_KEYS.map((key) => (
437+
<div
438+
key={key}
439+
style={{ display: "flex", gap: 10, alignItems: "center" }}
440+
>
441+
<div style={{ width: 100 }}>
442+
{intl.formatMessage(DARK_MODE_LABELS[key])}
443+
</div>
444+
<Slider
445+
min={DARK_MODE_MINS[key]}
446+
max={100}
447+
value={config[key]}
448+
onChange={(x) => on_change_dark_mode(`dark_mode_${key}`, x)}
449+
marks={{
450+
[DARK_MODE_DEFAULTS[key]]: String(
451+
DARK_MODE_DEFAULTS[key],
452+
),
453+
}}
454+
style={{ flex: 1, width: 0 }}
455+
/>
456+
<Button
457+
size="small"
458+
onClick={() =>
459+
on_change_dark_mode(`dark_mode_${key}`, DARK_MODE_DEFAULTS[key])
460+
}
461+
>
462+
{intl.formatMessage(labels.reset)}
463+
</Button>
464+
</div>
465+
))}
466+
</div>
454467
</Card>
455468
) : undefined}
456469
</div>

src/packages/frontend/account/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ export interface AccountState {
5151
dark_mode_brightness: number;
5252
dark_mode_contrast: number;
5353
dark_mode_sepia: number;
54-
dark_mode_grayscale: number;
5554
news_read_until: number; // JavaScript timestamp in milliseconds
5655
[OTHER_SETTINGS_USERDEFINED_LLM]: string; // string is JSON: CustomLLM[]
5756
[OTHER_SETTINGS_LOCALE_KEY]?: string;

src/packages/frontend/cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
"antd",
8383
"buttonbar",
8484
"collab",
85+
"darkreader",
8586
"descr",
8687
"flyoutdragbar",
8788
"flyouts",

src/packages/frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
"csv-parse": "^5.3.6",
8686
"csv-stringify": "^6.3.0",
8787
"d3": "^3.5.6",
88-
"darkreader": "4.9.95",
88+
"darkreader": "4.9.109",
8989
"dayjs": "^1.11.11",
9090
"debug": "^4.4.0",
9191
"direction": "^1.0.4",

src/packages/next/components/account/config/system/appearance.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ interface Data {
3131
dark_mode_brightness: number;
3232
dark_mode_contrast: number;
3333
dark_mode_sepia: number;
34-
dark_mode_grayscale: number;
3534
};
3635
}
3736

@@ -84,12 +83,6 @@ register({
8483
min={0}
8584
max={100}
8685
/>
87-
<EditNumber
88-
path="other_settings.dark_mode_grayscale"
89-
title="Grayscale"
90-
min={0}
91-
max={100}
92-
/>
9386
</div>
9487
</div>
9588
);

src/packages/pnpm-lock.yaml

Lines changed: 24 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/packages/util/db-schema/accounts.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ export const AUTOBALANCE_DEFAULTS = {
7070
enabled: true,
7171
} as AutoBalance;
7272

73+
export const DARK_MODE_DEFAULTS = {
74+
brightness: 100,
75+
contrast: 90,
76+
sepia: 0,
77+
} as const;
78+
7379
// throw error if not valid
7480
export function ensureAutoBalanceValid(obj) {
7581
if (obj == null) {
@@ -501,10 +507,9 @@ Table({
501507
no_free_warnings: false,
502508
allow_mentions: true,
503509
dark_mode: false,
504-
dark_mode_brightness: 100,
505-
dark_mode_contrast: 90,
506-
dark_mode_sepia: 0,
507-
dark_mode_grayscale: 0,
510+
dark_mode_brightness: DARK_MODE_DEFAULTS.brightness,
511+
dark_mode_contrast: DARK_MODE_DEFAULTS.contrast,
512+
dark_mode_sepia: DARK_MODE_DEFAULTS.sepia,
508513
news_read_until: 0,
509514
hide_project_popovers: false,
510515
hide_file_popovers: false,

0 commit comments

Comments
 (0)