CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/account/dark-mode.ts
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { throttle, isEqual } from "lodash";
7
import { AccountStore } from "./store";
8
9
export const dark_mode_mins = {
10
brightness: 20,
11
contrast: 20,
12
sepia: 0,
13
grayscale: 0,
14
} as const;
15
16
interface Config {
17
brightness: number;
18
contrast: number;
19
sepia: number;
20
grayscale: number;
21
}
22
23
// Returns number between 0 and 100.
24
function to_number(x: any, default_value: number): number {
25
if (x == null) return default_value;
26
try {
27
x = parseInt(x);
28
if (isNaN(x)) {
29
return default_value;
30
}
31
if (x < 0) {
32
x = 0;
33
}
34
if (x > 100) {
35
x = 100;
36
}
37
return x;
38
} catch (_) {
39
return default_value;
40
}
41
}
42
43
export function get_dark_mode_config(other_settings?: {
44
dark_mode_brightness?: number;
45
dark_mode_contrast?: number;
46
dark_mode_sepia?: number;
47
dark_mode_grayscale?: number;
48
}): 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 };
66
}
67
68
let currentDarkMode: boolean = false;
69
let last_dark_mode: boolean = false;
70
let last_config: Config | undefined = undefined;
71
export function init_dark_mode(account_store: AccountStore): void {
72
account_store.on(
73
"change",
74
throttle(async () => {
75
const dark_mode = !!account_store.getIn(["other_settings", "dark_mode"]);
76
currentDarkMode = dark_mode;
77
const config = get_dark_mode_config(
78
account_store.get("other_settings")?.toJS(),
79
);
80
if (
81
dark_mode == last_dark_mode &&
82
(!dark_mode || isEqual(last_config, config))
83
) {
84
return;
85
}
86
const { enable, disable } = await import("darkreader");
87
last_dark_mode = dark_mode;
88
last_config = config;
89
if (dark_mode) {
90
enable(config);
91
} else {
92
disable();
93
}
94
}, 3000),
95
);
96
}
97
98
export function inDarkMode() {
99
return currentDarkMode;
100
}
101
102