Skip to content

Commit 0087124

Browse files
committed
dark theme support #12
1 parent cfa46c3 commit 0087124

File tree

6 files changed

+192
-9
lines changed

6 files changed

+192
-9
lines changed

src/pages/Background/index.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,25 @@ const persistdisplayTabInFullStatus = (status) => {
9292
});
9393
};
9494

95+
/**
96+
* Dark Mode
97+
*/
98+
let darkMode = 'auto';
99+
100+
chrome.storage.sync.get(['darkMode'], (result) => {
101+
if (result.darkMode !== undefined) {
102+
darkMode = result.darkMode;
103+
} else {
104+
persistDarkMode('auto'); // default to auto
105+
}
106+
});
107+
108+
const persistDarkMode = (status) => {
109+
chrome.storage.sync.set({
110+
darkMode: status,
111+
});
112+
};
113+
95114
const toggleSidebar = (toStatus = null) => {
96115
if (toStatus === null || toStatus === undefined) {
97116
sidebarOpen = !sidebarOpen;
@@ -203,6 +222,23 @@ const updateDisplayTabInFullStatus = (toStatus) => {
203222
);
204223
};
205224

225+
const updateDarkModeStatus = (toStatus) => {
226+
chrome.tabs.query(
227+
{
228+
currentWindow: true,
229+
},
230+
function(tabs) {
231+
tabs.forEach((tab) => {
232+
chrome.tabs.sendMessage(tab.id, {
233+
from: 'background',
234+
msg: 'UPDATE_DARK_MODE_STATUS',
235+
toStatus,
236+
});
237+
});
238+
}
239+
);
240+
};
241+
206242
// chrome.browserAction.setPopup({
207243
// popup: chrome.extension.getURL('sidebar.html'),
208244
// });
@@ -281,5 +317,13 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
281317
displayTabInFull = toStatus;
282318
persistdisplayTabInFullStatus(displayTabInFull);
283319
updateDisplayTabInFullStatus(displayTabInFull);
320+
} else if (
321+
request.from === 'settings' &&
322+
request.msg === 'USER_CHANGE_DARK_MODE'
323+
) {
324+
const { toStatus } = request;
325+
darkMode = toStatus;
326+
persistDarkMode(darkMode);
327+
updateDarkModeStatus(darkMode);
284328
}
285329
});

src/pages/Sidebar/containers/Title/SettingsBox/SettingsBox.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
}
6363

6464
.PopoverContent .SettingEntryContent label {
65+
flex: 0;
6566
margin-right: 8px;
6667
display: flex;
6768
align-items: center;

src/pages/Sidebar/containers/Title/SettingsBox/SettingsBox.jsx

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useContext } from 'react';
22
import DarkModeContext from '../../../context/dark-mode-context';
3-
import { MdSettings } from 'react-icons/md';
3+
import { MdSettings, MdBrightnessAuto } from 'react-icons/md';
44
import { TiDownload } from 'react-icons/ti';
55
import {
66
FaAlignJustify,
@@ -9,7 +9,7 @@ import {
99
FaCheck,
1010
FaTimes,
1111
} from 'react-icons/fa';
12-
import { IoIosBarcode } from 'react-icons/io';
12+
import { IoIosBarcode, IoIosMoon, IoIosSunny } from 'react-icons/io';
1313
import { WiMoonAltNew, WiMoonAltWaxingCrescent3 } from 'react-icons/wi';
1414

1515
import './SettingsBox.css';
@@ -21,6 +21,8 @@ const SettingsBox = ({
2121
setSettingSidebarShouldShrinkBody,
2222
settingDisplayTabTitleInFull,
2323
setSettingDisplayTabTitleInFull,
24+
settingDarkMode,
25+
setSettingDarkMode,
2426
}) => {
2527
const darkModeContext = useContext(DarkModeContext);
2628

@@ -38,6 +40,7 @@ const SettingsBox = ({
3840
<MdSettings style={{ marginRight: 6 }} /> Settings
3941
</div>
4042
<div className={['PopoverContent', isDark ? 'Dark' : null].join(' ')}>
43+
{/* SIDEBAR POSITION */}
4144
<div className="SettingEntryContainer">
4245
<div className="SettingEntryTitle">
4346
<FaAlignJustify className="SettingEntryTitleIcon" />
@@ -80,7 +83,7 @@ const SettingsBox = ({
8083
</div>
8184

8285
{divider}
83-
86+
{/* SQUEEZE WEB PAGE WHEN SIDEBAR OPENS */}
8487
<div className="SettingEntryContainer">
8588
<div className="SettingEntryTitle">
8689
<TiDownload
@@ -128,7 +131,7 @@ const SettingsBox = ({
128131
</div>
129132

130133
{divider}
131-
134+
{/* DISPLAY TAB TITLE IN FULL */}
132135
<div className="SettingEntryContainer">
133136
<div className="SettingEntryTitle">
134137
<IoIosBarcode className="SettingEntryTitleIcon" />
@@ -169,6 +172,64 @@ const SettingsBox = ({
169172
</div>
170173
</form>
171174
</div>
175+
176+
{divider}
177+
{/* DARK THEME */}
178+
<div className="SettingEntryContainer">
179+
<div className="SettingEntryTitle">
180+
<IoIosMoon className="SettingEntryTitleIcon" />
181+
Dark theme:
182+
</div>
183+
<form className="SettingEntryContent">
184+
<div style={{ display: 'flex', alignItems: 'center' }}>
185+
<label
186+
className={[
187+
settingDarkMode === 'auto' ? 'Active' : null,
188+
isDark ? 'Dark' : null,
189+
].join(' ')}
190+
>
191+
<input
192+
type="radio"
193+
checked={settingDarkMode === 'auto'}
194+
onChange={() => setSettingDarkMode('auto')}
195+
name="radio"
196+
/>
197+
<MdBrightnessAuto className="SettingEntryOptionIcon" />
198+
Auto
199+
</label>
200+
<label
201+
className={[
202+
settingDarkMode === 'light' ? 'Active' : null,
203+
isDark ? 'Dark' : null,
204+
].join(' ')}
205+
>
206+
<input
207+
type="radio"
208+
checked={settingDarkMode === 'light'}
209+
onChange={() => setSettingDarkMode('light')}
210+
name="radio"
211+
/>
212+
<IoIosSunny className="SettingEntryOptionIcon" />
213+
Light
214+
</label>
215+
<label
216+
className={[
217+
settingDarkMode === 'dark' ? 'Active' : null,
218+
isDark ? 'Dark' : null,
219+
].join(' ')}
220+
>
221+
<input
222+
type="radio"
223+
checked={settingDarkMode === 'dark'}
224+
onChange={() => setSettingDarkMode('dark')}
225+
name="radio"
226+
/>
227+
<IoIosMoon className="SettingEntryOptionIcon" />
228+
Dark
229+
</label>
230+
</div>
231+
</form>
232+
</div>
172233
</div>
173234
</div>
174235
);

src/pages/Sidebar/containers/Title/Title.jsx

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class Title extends Component {
2222
settingSidebarLocation: 'left',
2323
settingSidebarShouldShrinkBody: true,
2424
settingDisplayTabTitleInFull: true,
25+
settingDarkMode: 'auto',
2526
};
2627

2728
componentDidMount() {
@@ -52,6 +53,20 @@ class Title extends Component {
5253
}
5354
});
5455

56+
chrome.storage.sync.get(['darkMode'], (result) => {
57+
if (result.darkMode !== undefined) {
58+
this.setState({
59+
settingDarkMode: result.darkMode,
60+
});
61+
62+
if (result.darkMode !== 'auto') {
63+
this.context.setDarkStatus(result.darkMode === 'dark');
64+
} else {
65+
this.context.setDarkStatus(this.context.mediaQueryDark);
66+
}
67+
}
68+
});
69+
5570
// sync settings across tabs
5671
chrome.runtime.onMessage.addListener((request, sender, response) => {
5772
// no need to sync sidebarOnLeft here,
@@ -73,6 +88,12 @@ class Title extends Component {
7388
) {
7489
const { toStatus } = request;
7590
this.setState({ settingSidebarShouldShrinkBody: toStatus === true });
91+
} else if (
92+
request.from === 'background' &&
93+
request.msg === 'UPDATE_DARK_MODE_STATUS'
94+
) {
95+
const { toStatus } = request;
96+
this.setState({ settingDarkMode: toStatus });
7697
}
7798
});
7899
}
@@ -124,13 +145,35 @@ class Title extends Component {
124145
});
125146
};
126147

148+
static contextType = DarkModeContext;
149+
150+
setSettingDarkMode = (toStatus) => {
151+
if (toStatus === this.state.settingDarkMode) {
152+
return;
153+
}
154+
155+
if (toStatus !== 'auto') {
156+
this.context.setDarkStatus(toStatus === 'dark');
157+
} else {
158+
this.context.setDarkStatus(this.context.mediaQueryDark);
159+
}
160+
161+
this.setState({ settingDarkMode: toStatus });
162+
chrome.runtime.sendMessage({
163+
from: 'settings',
164+
msg: 'USER_CHANGE_DARK_MODE',
165+
toStatus,
166+
});
167+
};
168+
127169
render() {
128170
const {
129171
sidebarOnLeft,
130172
isSettingsPopoverOpen,
131173
settingSidebarLocation,
132174
settingSidebarShouldShrinkBody,
133175
settingDisplayTabTitleInFull,
176+
settingDarkMode,
134177
} = this.state;
135178

136179
return (
@@ -160,7 +203,7 @@ class Title extends Component {
160203
containerStyle={{
161204
zIndex: 999999999,
162205
minWidth: '180px',
163-
maxWidth: '220px',
206+
maxWidth: '290px',
164207
padding: '0px 2px 2px 2px',
165208
}}
166209
content={({ position, targetRect, popoverRect }) => (
@@ -187,6 +230,8 @@ class Title extends Component {
187230
setSettingDisplayTabTitleInFull={
188231
this.setSettingDisplayTabTitleInFull
189232
}
233+
settingDarkMode={settingDarkMode}
234+
setSettingDarkMode={this.setSettingDarkMode}
190235
/>
191236
</ArrowContainer>
192237
)}

src/pages/Sidebar/context/dark-mode-context.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22

33
const darkModeContext = React.createContext({
4-
shouldFollowSystemDarkMode: false,
4+
mediaQueryDark: false,
55
isDark: false,
66
setDarkStatus: () => {},
77
});

src/pages/Sidebar/index.jsx

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import { render } from 'react-dom';
33
import { DndProvider } from 'react-dnd';
44
import HTML5Backend from 'react-dnd-html5-backend';
@@ -11,6 +11,8 @@ import DarkModeContext from './context/dark-mode-context';
1111

1212
const App = () => {
1313
const [isDark, setIsDark] = useState(false);
14+
const [mediaQueryDark, setMediaQueryDark] = useState(false);
15+
const [darkModeSetting, setDarkModeSetting] = useState(null);
1416

1517
const setDarkStatus = (dark) => {
1618
setIsDark(dark);
@@ -21,13 +23,43 @@ const App = () => {
2123
}
2224
};
2325

26+
useEffect(() => {
27+
chrome.storage.sync.get(['darkMode'], (result) => {
28+
if (result.darkMode !== undefined) {
29+
setDarkModeSetting(result.darkMode);
30+
} else {
31+
setDarkModeSetting('auto');
32+
}
33+
});
34+
35+
// sync settings across tabs
36+
chrome.runtime.onMessage.addListener((request, sender, response) => {
37+
if (
38+
request.from === 'background' &&
39+
request.msg === 'UPDATE_DARK_MODE_STATUS'
40+
) {
41+
const { toStatus } = request;
42+
setDarkModeSetting(toStatus);
43+
}
44+
});
45+
}, []);
46+
47+
if (darkModeSetting === null) {
48+
return null;
49+
}
50+
2451
return (
2552
<React.Fragment>
26-
<DarkModeContext.Provider value={{ isDark, setDarkStatus }}>
53+
<DarkModeContext.Provider
54+
value={{ mediaQueryDark, isDark, setDarkStatus }}
55+
>
2756
<Media
2857
query="(prefers-color-scheme: dark)"
2958
onChange={(dark) => {
30-
setDarkStatus(dark);
59+
setMediaQueryDark(dark);
60+
if (darkModeSetting === 'auto') {
61+
setDarkStatus(dark);
62+
}
3163
}}
3264
/>
3365
<DndProvider backend={HTML5Backend}>

0 commit comments

Comments
 (0)