Skip to content

Commit

Permalink
fix: the color schema of the post detail page will flash
Browse files Browse the repository at this point in the history
  • Loading branch information
WhiteMinds committed Sep 14, 2023
1 parent f9291d2 commit 25b20f5
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 3 deletions.
73 changes: 73 additions & 0 deletions packages/app/src/pages/_document.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import Document, { Head, Html, Main, NextScript } from 'next/document'
import Script from 'next/script'
import { KEY_DARK_MODE } from '../services/AppSettings'

export default class CustomDocument<P> extends Document<P> {
render() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
<Script
id={prepareColorSchemaClasses.name}
dangerouslySetInnerHTML={{
__html: `(${prepareColorSchemaClasses.toString()})(...${JSON.stringify([
KEY_DARK_MODE,
'themeLight',
'themeDark',
])})`,
}}
strategy="beforeInteractive"
/>
</body>
</Html>
)
}
}

// Note that this function should not use any external code dependencies in its implementation.
// Refs: https://github.com/donavon/use-dark-mode/issues/55
function prepareColorSchemaClasses(key: string, lightModeClassName: string, darkModeClassName: string) {
//
// Preparing code dependencies
//

class PersistenceService {
get<T = unknown>(key: string, defaultValue: T): T
get<T = unknown>(key: string, defaultValue?: T): T | undefined {
// in SSR mode
if (typeof localStorage === 'undefined') return defaultValue
const jsonStr = localStorage.getItem(key)
if (!jsonStr) return defaultValue
return JSON.parse(jsonStr) as T
}

set<T = unknown>(key: string, value: T): T {
// in SSR mode
if (typeof localStorage === 'undefined') return value
localStorage.setItem(key, JSON.stringify(value))
return value
}
}

const persistenceService = new PersistenceService()

function getBrowserDarkMode() {
return typeof globalThis.window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches
}

//
// Logic code
//

// Currently only the posts page supports color schema.
if (!location.pathname.startsWith('/posts/')) {
document.documentElement.classList.add(darkModeClassName)
return
}

const darkMode = persistenceService.get(key, getBrowserDarkMode())
document.documentElement.classList.add(darkMode ? darkModeClassName : lightModeClassName)
}
1 change: 1 addition & 0 deletions packages/app/src/pages/posts/[...slug].page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export const getStaticProps: GetStaticProps<PageProps, { slug?: string[] }> = as
const menu = getPostTopMenu(post)
if (!menu) return { notFound: true }
const menusWithPosts = await getMenusWithPosts()
// TODO: clean menusWithPosts post content
const menuWithPosts = menusWithPosts.find(({ name }) => name === menu.name)
if (!menuWithPosts) return { notFound: true }

Expand Down
6 changes: 4 additions & 2 deletions packages/app/src/services/AppSettings/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { BehaviorSubject, tap } from 'rxjs'
import { PersistenceService, persistenceService } from '../PersistenceService'

export const KEY_DARK_MODE = 'darkMode'

export class AppSettings {
constructor(private persistenceService: PersistenceService) {
this.darkMode$
.pipe(
tap(value => {
this.persistenceService.set<boolean>('darkMode', value)
this.persistenceService.set<boolean>(KEY_DARK_MODE, value)
return value
}),
)
.subscribe()
}

darkMode$ = new BehaviorSubject(this.persistenceService.get<boolean>('darkMode', getBrowserDarkMode()))
darkMode$ = new BehaviorSubject(this.persistenceService.get<boolean>(KEY_DARK_MODE, getBrowserDarkMode()))
setDarkMode(value: boolean) {
this.darkMode$.next(value)
}
Expand Down
12 changes: 11 additions & 1 deletion packages/app/src/styles/globals.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ body {
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans',
'Droid Sans', 'Helvetica Neue', sans-serif;
background-color: var(--colorPrimaryBg);
}

body {
--contentAreaWidth: 1320px;
--contentWrapperPadding: 32px;
@include themeDark;

@media (max-width: $mobileBreakPoint) {
--contentWrapperPadding: 24px;
Expand All @@ -32,3 +32,13 @@ a {
* {
box-sizing: border-box;
}

// This is provided to `prepareColorSchemaClasses` in `_document.page.tsx`.
.themeLight {
@include themeLight;
}

// This is provided to `prepareColorSchemaClasses` in `_document.page.tsx`.
.themeDark {
@include themeDark;
}

0 comments on commit 25b20f5

Please sign in to comment.