Skip to content

Commit d7714df

Browse files
committed
feat: edge config all
1 parent ea0db85 commit d7714df

File tree

11 files changed

+126
-33
lines changed

11 files changed

+126
-33
lines changed

src/app/(home)/page.tsx

+9-3
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@ import {
1919
softBouncePrest,
2020
softSpringPreset,
2121
} from '~/constants/spring'
22-
import { useConfig } from '~/hooks/data/use-config'
2322
import { isDev } from '~/lib/env'
2423
import { clsxm } from '~/lib/helper'
2524
import { noopObj } from '~/lib/noop'
2625
import { apiClient } from '~/lib/request'
2726
import { routeBuilder, Routes } from '~/lib/route-builder'
2827
import { springScrollToTop } from '~/lib/scroller'
29-
import { useAggregationSelector } from '~/providers/root/aggregation-data-provider'
28+
import {
29+
useAggregationSelector,
30+
useAppConfigSelector,
31+
} from '~/providers/root/aggregation-data-provider'
3032

3133
import { useHomeQueryData } from './query'
3234

@@ -110,7 +112,11 @@ const TwoColumnLayout = ({
110112
}
111113

112114
const Welcome = () => {
113-
const { title, description } = useConfig().hero
115+
const { title, description } = useAppConfigSelector((config) => {
116+
return {
117+
...config.hero,
118+
}
119+
})!
114120
const siteOwner = useAggregationSelector((agg) => agg.user)
115121
const { avatar, socialIds } = siteOwner || {}
116122

src/app/api/bilibili/check_live/route.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import axios from 'axios'
2+
import type { NextRequest } from 'next/server'
23
import type { BLUser } from './types/user'
34

4-
import { appConfig } from '~/app.config'
55
import { NextServerResponse } from '~/lib/edge-function.server'
66
import { getQueryClient } from '~/lib/query-client.server'
77

@@ -10,9 +10,11 @@ const headers = {
1010
'User-Agent': `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Shiro`,
1111
}
1212
export const runtime = 'edge'
13-
export const GET = async () => {
14-
const liveId = appConfig.module.bilibili.liveId
15-
13+
export const GET = async (req: NextRequest) => {
14+
const liveId = req.nextUrl.searchParams.get('liveId')
15+
if (!liveId) {
16+
return new NextServerResponse().status(400).end()
17+
}
1618
const queryClient = getQueryClient()
1719
const res = await queryClient.fetchQuery({
1820
queryKey: ['bilibili-live', liveId],

src/app/config.d.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
export interface AppConfig {
2+
site: Site
3+
hero: Hero
4+
module: Module
5+
}
6+
export interface Site {
7+
favicon: string
8+
}
9+
export interface Hero {
10+
title: Title
11+
description: string
12+
}
13+
export interface Title {
14+
template: TemplateItem[]
15+
}
16+
export interface TemplateItem {
17+
type: string
18+
text?: string
19+
class?: string
20+
}
21+
export interface Module {
22+
donate: Donate
23+
bilibili: Bilibili
24+
}
25+
export interface Donate {
26+
enable: boolean
27+
link: string
28+
qrcode: string[]
29+
}
30+
export interface Bilibili {
31+
liveId: number
32+
}

src/app/layout.tsx

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import '../styles/index.css'
22

33
import { Analytics } from '@vercel/analytics/react'
4+
import { cache } from 'react'
45
import { ToastContainer } from 'react-toastify'
56
import type { AggregateRoot } from '@mx-space/api-client'
7+
import type { AppConfig } from './config'
68

79
import { ClerkProvider } from '@clerk/nextjs'
10+
import { get } from '@vercel/edge-config'
811

912
import PKG from '~/../package.json'
10-
import { appConfig } from '~/app.config'
1113
import { Root } from '~/components/layout/root/Root'
1214
import { TocAutoScroll } from '~/components/widgets/toc/TocAutoScroll'
1315
import { attachUA } from '~/lib/attach-ua'
@@ -24,12 +26,18 @@ import { init } from './init'
2426
const { version } = PKG
2527
init()
2628

29+
const getAppConfig = cache(() => {
30+
return get('config') as Promise<AppConfig>
31+
})
32+
2733
let aggregationData: AggregateRoot | null = null
2834
export const generateMetadata = defineMetadata(async (_, getData) => {
2935
const fetchedData = aggregationData ?? (await getData())
3036
aggregationData = fetchedData
3137
const { seo, url, user } = fetchedData
3238

39+
const config = getAppConfig()
40+
3341
return {
3442
metadataBase: new URL(url.webUrl),
3543
title: {
@@ -40,7 +48,7 @@ export const generateMetadata = defineMetadata(async (_, getData) => {
4048
keywords: seo.keywords?.join(',') || '',
4149
icons: [
4250
{
43-
url: appConfig.site.favicon,
51+
url: config.site.favicon,
4452
type: 'image/svg+xml',
4553
sizes: 'any',
4654
},
@@ -102,6 +110,7 @@ export default async function RootLayout(props: Props) {
102110

103111
aggregationData = data
104112

113+
const appConfig = await getAppConfig()
105114
return (
106115
// <ClerkProvider localization={ClerkZhCN}>
107116
<ClerkProvider>
@@ -113,7 +122,7 @@ export default async function RootLayout(props: Props) {
113122
className={`${sansFont.variable} ${serifFont.variable} m-0 h-full p-0 font-sans`}
114123
>
115124
<Providers>
116-
<AggregationProvider aggregationData={data} />
125+
<AggregationProvider aggregationData={data} appConfig={appConfig} />
117126

118127
<Root>{children}</Root>
119128

src/components/layout/header/internal/AnimatedLogo.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import { useRouter } from 'next/navigation'
77

88
import { getAdminUrl, isLogged, useViewport } from '~/atoms'
99
import { useSingleAndDoubleClick } from '~/hooks/common/use-single-double-click'
10-
import { useConfig } from '~/hooks/data/use-config'
1110
import { Routes } from '~/lib/route-builder'
1211
import { toast } from '~/lib/toast'
12+
import { useAppConfigSelector } from '~/providers/root/aggregation-data-provider'
1313

1414
import { Activity } from './Activity'
1515
import { useHeaderMetaShouldShow } from './hooks'
@@ -22,9 +22,9 @@ const TapableLogo = () => {
2222
queryKey: ['live-check'],
2323
enabled: false,
2424
})
25-
const {
26-
module: { bilibili: { liveId } = {} },
27-
} = useConfig()
25+
26+
const { liveId } = useAppConfigSelector((config) => config.module.bilibili)!
27+
2828
const goLive = useCallback(() => {
2929
window.open(`https://live.bilibili.com/${liveId}`)
3030
}, [liveId])

src/components/layout/header/internal/SiteOwnerAvatar.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,26 @@ import { useCallback } from 'react'
55
import Image from 'next/image'
66

77
import { clsxm } from '~/lib/helper'
8-
import { useAggregationSelector } from '~/providers/root/aggregation-data-provider'
8+
import {
9+
useAggregationSelector,
10+
useAppConfigSelector,
11+
} from '~/providers/root/aggregation-data-provider'
912

1013
export const SiteOwnerAvatar: Component = ({ className }) => {
1114
const avatar = useAggregationSelector((data) => data.user.avatar)
15+
const liveId = useAppConfigSelector((config) => config.module.bilibili.liveId)
1216

1317
const { data: isLiving } = useQuery({
1418
queryKey: ['live-check'],
1519
queryFn: () =>
16-
fetch('/api/bilibili/check_live')
20+
fetch(`/api/bilibili/check_live?liveId=${liveId}`)
1721
.then((res) => res.json())
1822
.catch(() => null),
1923
select: useCallback((data: any) => {
2024
return !!data
2125
}, []),
2226
refetchInterval: 1000 * 60,
27+
enabled: !!liveId,
2328
meta: {
2429
persist: false,
2530
},

src/components/widgets/shared/AsideDonateButton.tsx

+3-8
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import type { HTMLMotionProps } from 'framer-motion'
66
import { MotionButtonBase } from '~/components/ui/button'
77
import { DialogOverlay } from '~/components/ui/dlalog/DialogOverlay'
88
import { useIsClient } from '~/hooks/common/use-is-client'
9-
import { useConfig } from '~/hooks/data/use-config'
109
import { clsxm } from '~/lib/helper'
10+
import { useAppConfigSelector } from '~/providers/root/aggregation-data-provider'
1111

1212
// TODO this component only use once in current page.
1313
const positionAtom = atom({
@@ -18,9 +18,7 @@ const overlayShowAtom = atom(false)
1818

1919
export const AsideDonateButton = () => {
2020
const isClient = useIsClient()
21-
const {
22-
module: { donate },
23-
} = useConfig()
21+
const donate = useAppConfigSelector((config) => config.module.donate)!
2422

2523
const overlayOpen = useAtomValue(overlayShowAtom)
2624

@@ -103,10 +101,7 @@ const DonateButtonInternal: Component<HTMLMotionProps<'button'>> = ({
103101

104102
...props
105103
}) => {
106-
const {
107-
module: { donate },
108-
} = useConfig()
109-
104+
const donate = useAppConfigSelector((config) => config.module.donate)
110105
if (!donate) return null
111106
return (
112107
<MotionButtonBase

src/hooks/data/use-config.ts

-4
This file was deleted.

src/lib/url-builder.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ import type {
66
} from '@mx-space/api-client'
77

88
import { isDev } from '~/lib/env'
9-
import { aggregationDataAtom } from '~/providers/root/aggregation-data-provider'
10-
11-
import { jotaiStore } from './store'
9+
import { getAggregationData } from '~/providers/root/aggregation-data-provider'
1210

1311
export function urlBuilder(path = '') {
1412
if (isDev) return new URL(path, 'http://localhost:2323')
15-
return new URL(path, jotaiStore.get(aggregationDataAtom)?.url.webUrl)
13+
return new URL(path, getAggregationData()?.url.webUrl)
1614
}
1715

1816
function isPostModel(model: any): model is PostModel {

src/providers/root/aggregation-data-provider.tsx

+30-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useCallback, useEffect, useRef } from 'react'
44
import { atom, useAtomValue } from 'jotai'
55
import { selectAtom } from 'jotai/utils'
66
import type { AggregateRoot } from '@mx-space/api-client'
7+
import type { AppConfig } from '~/app/config'
78
import type { FC, PropsWithChildren } from 'react'
89

910
import { fetchAppUrl } from '~/atoms'
@@ -12,16 +13,27 @@ import { useBeforeMounted } from '~/hooks/common/use-before-mounted'
1213
import { jotaiStore } from '~/lib/store'
1314

1415
export const aggregationDataAtom = atom<null | AggregateRoot>(null)
16+
const appConfigAtom = atom<AppConfig | null>(null)
1517

1618
export const AggregationProvider: FC<
1719
PropsWithChildren<{
1820
aggregationData: AggregateRoot
21+
appConfig: AppConfig
1922
}>
20-
> = ({ children, aggregationData }) => {
23+
> = ({ children, aggregationData, appConfig }) => {
2124
useBeforeMounted(() => {
2225
if (!aggregationData) return
2326
jotaiStore.set(aggregationDataAtom, aggregationData)
2427
})
28+
useBeforeMounted(() => {
29+
if (!appConfig) return
30+
jotaiStore.set(appConfigAtom, appConfig)
31+
})
32+
33+
useEffect(() => {
34+
if (!appConfig) return
35+
jotaiStore.set(appConfigAtom, appConfig)
36+
}, [appConfig])
2537

2638
useEffect(() => {
2739
if (!aggregationData) return
@@ -62,4 +74,21 @@ export const useAggregationSelector = <T,>(
6274
),
6375
)
6476

77+
export const useAppConfigSelector = <T,>(
78+
selector: (atomValue: AppConfig) => T,
79+
deps: any[] = [],
80+
): T | null =>
81+
useAtomValue(
82+
// @ts-ignore
83+
selectAtom(
84+
appConfigAtom,
85+
useCallback(
86+
(atomValue) => (!atomValue ? null : selector(atomValue)),
87+
deps,
88+
),
89+
),
90+
)
91+
6592
export const getAggregationData = () => jotaiStore.get(aggregationDataAtom)
93+
94+
export const getAppConfig = () => jotaiStore.get(appConfigAtom)

tailwind.config.ts

+21
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,27 @@ const UIKitColors = {
169169
const twConfig: Config = {
170170
content: ['./src/**/*.{js,jsx,ts,tsx}'],
171171
darkMode: ['class', '[data-theme="dark"]'],
172+
safelist: [
173+
'font-light',
174+
'text-3xl',
175+
'rounded',
176+
'p-1',
177+
'bg-gray-200',
178+
'dark:bg-gray-800/0',
179+
'hover:dark:bg-gray-800/100',
180+
'bg-opacity-0',
181+
'hover:bg-opacity-100',
182+
'transition-background',
183+
184+
'w-[1px]',
185+
'h-8',
186+
'-bottom-2',
187+
'bg-gray-800/80',
188+
'dark:bg-gray-200/80',
189+
'group-hover:opacity-100',
190+
'transition-opacity',
191+
'group-hover:animation-blink',
192+
],
172193
theme: {
173194
// colors: createVariableColors(twColors),
174195

0 commit comments

Comments
 (0)