Skip to content

Commit 116228a

Browse files
committed
fix: the color schema of the post detail page will flash
1 parent e653357 commit 116228a

File tree

4 files changed

+89
-3
lines changed

4 files changed

+89
-3
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import Document, { Head, Html, Main, NextScript } from 'next/document'
2+
import Script from 'next/script'
3+
import { KEY_DARK_MODE } from '../services/AppSettings'
4+
5+
export default class CustomDocument<P> extends Document<P> {
6+
render() {
7+
return (
8+
<Html lang="en">
9+
<Head />
10+
<body>
11+
<Main />
12+
<NextScript />
13+
<Script
14+
id={prepareColorSchemaClasses.name}
15+
dangerouslySetInnerHTML={{
16+
__html: `(${prepareColorSchemaClasses.toString()})(...${JSON.stringify([
17+
KEY_DARK_MODE,
18+
'themeLight',
19+
'themeDark',
20+
])})`,
21+
}}
22+
strategy="beforeInteractive"
23+
/>
24+
</body>
25+
</Html>
26+
)
27+
}
28+
}
29+
30+
// Note that this function should not use any external code dependencies in its implementation.
31+
// Refs: https://github.com/donavon/use-dark-mode/issues/55
32+
function prepareColorSchemaClasses(key: string, lightModeClassName: string, darkModeClassName: string) {
33+
//
34+
// Preparing code dependencies
35+
//
36+
37+
class PersistenceService {
38+
get<T = unknown>(key: string, defaultValue: T): T
39+
get<T = unknown>(key: string, defaultValue?: T): T | undefined {
40+
// in SSR mode
41+
if (typeof localStorage === 'undefined') return defaultValue
42+
const jsonStr = localStorage.getItem(key)
43+
if (!jsonStr) return defaultValue
44+
return JSON.parse(jsonStr) as T
45+
}
46+
47+
set<T = unknown>(key: string, value: T): T {
48+
// in SSR mode
49+
if (typeof localStorage === 'undefined') return value
50+
localStorage.setItem(key, JSON.stringify(value))
51+
return value
52+
}
53+
}
54+
55+
const persistenceService = new PersistenceService()
56+
57+
function getBrowserDarkMode() {
58+
return typeof globalThis.window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches
59+
}
60+
61+
//
62+
// Logic code
63+
//
64+
65+
// Currently only the posts page supports color schema.
66+
if (!location.pathname.startsWith('/posts/')) {
67+
document.documentElement.classList.add(darkModeClassName)
68+
return
69+
}
70+
71+
const darkMode = persistenceService.get(key, getBrowserDarkMode())
72+
document.documentElement.classList.add(darkMode ? darkModeClassName : lightModeClassName)
73+
}

packages/app/src/pages/posts/[...slug].page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ export const getStaticProps: GetStaticProps<PageProps, { slug?: string[] }> = as
144144
const menu = getPostTopMenu(post)
145145
if (!menu) return { notFound: true }
146146
const menusWithPosts = await getMenusWithPosts()
147+
// TODO: clean menusWithPosts post content
147148
const menuWithPosts = menusWithPosts.find(({ name }) => name === menu.name)
148149
if (!menuWithPosts) return { notFound: true }
149150

packages/app/src/services/AppSettings/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
import { BehaviorSubject, tap } from 'rxjs'
22
import { PersistenceService, persistenceService } from '../PersistenceService'
33

4+
export const KEY_DARK_MODE = 'darkMode'
5+
46
export class AppSettings {
57
constructor(private persistenceService: PersistenceService) {
68
this.darkMode$
79
.pipe(
810
tap(value => {
9-
this.persistenceService.set<boolean>('darkMode', value)
11+
this.persistenceService.set<boolean>(KEY_DARK_MODE, value)
1012
return value
1113
}),
1214
)
1315
.subscribe()
1416
}
1517

16-
darkMode$ = new BehaviorSubject(this.persistenceService.get<boolean>('darkMode', getBrowserDarkMode()))
18+
darkMode$ = new BehaviorSubject(this.persistenceService.get<boolean>(KEY_DARK_MODE, getBrowserDarkMode()))
1719
setDarkMode(value: boolean) {
1820
this.darkMode$.next(value)
1921
}

packages/app/src/styles/globals.scss

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ body {
88
padding: 0;
99
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans',
1010
'Droid Sans', 'Helvetica Neue', sans-serif;
11+
background-color: var(--colorPrimaryBg);
1112
}
1213

1314
body {
1415
--contentAreaWidth: 1320px;
1516
--contentWrapperPadding: 32px;
16-
@include themeDark;
1717

1818
@media (max-width: $mobileBreakPoint) {
1919
--contentWrapperPadding: 24px;
@@ -32,3 +32,13 @@ a {
3232
* {
3333
box-sizing: border-box;
3434
}
35+
36+
// This is provided to `prepareColorSchemaClasses` in `_document.page.tsx`.
37+
.themeLight {
38+
@include themeLight;
39+
}
40+
41+
// This is provided to `prepareColorSchemaClasses` in `_document.page.tsx`.
42+
.themeDark {
43+
@include themeDark;
44+
}

0 commit comments

Comments
 (0)