Skip to content

Commit 7ccb7e2

Browse files
committed
feat: connect clerk to mx-backend
Signed-off-by: Innei <[email protected]>
1 parent 64ec7fc commit 7ccb7e2

File tree

8 files changed

+78
-28
lines changed

8 files changed

+78
-28
lines changed

src/app/ClientInit.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use client'
2+
3+
import { init } from './init'
4+
5+
init()
6+
export const ClientInit = () => null

src/app/layout.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { queries } from '~/queries/definition'
2222

2323
import { Providers } from '../providers/root'
2424
import { Analyze } from './analyze'
25+
import { ClientInit } from './ClientInit'
2526
import { init } from './init'
2627
import { InitInClient } from './InitInClient'
2728

@@ -141,6 +142,7 @@ export default async function RootLayout(props: Props) {
141142
return (
142143
// <ClerkProvider localization={ClerkZhCN}>
143144
<ClerkProvider>
145+
<ClientInit />
144146
<html lang="zh-CN" className="noise" suppressHydrationWarning>
145147
<head>
146148
<SayHi />

src/atoms/online.ts

-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
import { createAtomHooks } from 'jojoo/react'
2-
import { setGlobalStore } from 'jojoo'
32
import { atom } from 'jotai'
43

5-
import { jotaiStore } from '~/lib/store'
6-
7-
setGlobalStore(jotaiStore)
84
export const [, , useOnlineCount, , , setOnlineCount] = createAtomHooks(atom(0))

src/atoms/owner.ts

+14-5
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,24 @@ export const login = async (username?: string, password?: string) => {
5353
return
5454
}
5555

56-
await apiClient.user.proxy.login.put<{ token: string }>().then((res) => {
57-
jotaiStore.set(isLoggedAtom, true)
58-
toast(`欢迎回来,${jotaiStore.get(ownerAtom)?.name}`, 'success')
59-
setToken(res.token)
60-
})
56+
await refreshToken()
57+
toast(`欢迎回来,${jotaiStore.get(ownerAtom)?.name}`, 'success')
6158

6259
return true
6360
}
6461

6562
export const useIsLogged = () => useAtomValue(isLoggedAtom)
6663

6764
export const isLogged = () => jotaiStore.get(isLoggedAtom)
65+
66+
export const refreshToken = async () => {
67+
const token = getToken()
68+
if (!token) return
69+
await apiClient.user.proxy.login.put<{ token: string }>().then((res) => {
70+
jotaiStore.set(isLoggedAtom, true)
71+
72+
setToken(res.token)
73+
})
74+
75+
await fetchAppUrl()
76+
}

src/components/layout/header/Header.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ const MemoedHeader = memo(() => {
4545
<HeaderLogoArea>
4646
<AnimatedLogo />
4747

48-
{/* <SiteOwnerAvatar className="absolute bottom-[10px] right-[2px] hidden lg:inline-block" /> */}
4948
<OnlyMobile>
5049
<HeaderMeta />
5150
</OnlyMobile>

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

+48-8
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,37 @@
11
'use client'
22

3-
import React from 'react'
3+
import React, { useEffect } from 'react'
44
import { AnimatePresence } from 'framer-motion'
55
import dynamic from 'next/dynamic'
66
import { usePathname } from 'next/navigation'
77

8-
import { useIsLogged, useResolveAdminUrl } from '~/atoms'
8+
import { useSignIn } from '@clerk/nextjs'
9+
10+
import { refreshToken, useIsLogged, useResolveAdminUrl } from '~/atoms'
11+
import { UserArrowLeftIcon } from '~/components/icons/user-arrow-left'
912
import { MotionButtonBase } from '~/components/ui/button'
13+
import { FloatPopover } from '~/components/ui/float-popover'
1014
import { urlBuilder } from '~/lib/url-builder'
1115
import { useAggregationSelector } from '~/providers/root/aggregation-data-provider'
1216

13-
const UserAuthFromIcon = dynamic(() =>
14-
import('./UserAuthFromIcon').then((mod) => mod.UserAuthFromIcon),
15-
)
17+
import { HeaderActionButton } from './HeaderActionButton'
1618

1719
const SignedIn = dynamic(() =>
1820
import('@clerk/nextjs').then((mod) => mod.SignedIn),
1921
)
2022

23+
const UserAuthFromIcon = dynamic(() =>
24+
import('./UserAuthFromIcon').then((mod) => mod.UserAuthFromIcon),
25+
)
26+
const SignedOut = dynamic(() =>
27+
import('@clerk/nextjs').then((mod) => mod.SignedOut),
28+
)
2129
const UserButton = dynamic(() =>
2230
import('@clerk/nextjs').then((mod) => mod.UserButton),
2331
)
32+
const SignInButton = dynamic(() =>
33+
import('@clerk/nextjs').then((mod) => mod.SignInButton),
34+
)
2435

2536
const OwnerAvatar = () => {
2637
const ownerAvatar = useAggregationSelector((s) => s.user.avatar)!
@@ -30,18 +41,26 @@ const OwnerAvatar = () => {
3041
onClick={() => {
3142
window.open(resolveAdminUrl(), '_blank')
3243
}}
33-
className="pointer-events-auto flex h-10 w-10 items-center justify-center overflow-hidden rounded-full"
44+
className="pointer-events-auto relative flex h-10 w-10 items-center justify-center"
3445
>
3546
<span className="sr-only">Go to dashboard</span>
36-
<img src={ownerAvatar} alt="site owner" />
47+
<img className="rounded-full" src={ownerAvatar} alt="site owner" />
48+
<UserAuthFromIcon className="absolute -bottom-1 -right-1" />
3749
</MotionButtonBase>
3850
)
3951
}
52+
4053
export function UserAuth() {
4154
const pathname = usePathname()
42-
4355
const isLogged = useIsLogged()
4456

57+
const { isLoaded } = useSignIn()
58+
59+
useEffect(() => {
60+
// token 刷新,使用 mx token 替换
61+
if (isLoaded) refreshToken()
62+
}, [isLoaded])
63+
4564
if (isLogged) {
4665
return <OwnerAvatar />
4766
}
@@ -63,6 +82,27 @@ export function UserAuth() {
6382
</div>
6483
</div>
6584
</SignedIn>
85+
86+
<SignedOut key="sign-in">
87+
<FloatPopover
88+
TriggerComponent={TriggerComponent}
89+
wrapperClassName="h-full w-full flex items-center justify-center"
90+
type="tooltip"
91+
>
92+
登录
93+
</FloatPopover>
94+
</SignedOut>
6695
</AnimatePresence>
6796
)
6897
}
98+
99+
const TriggerComponent = () => {
100+
const pathname = usePathname()
101+
return (
102+
<SignInButton mode="modal" redirectUrl={urlBuilder(pathname).href}>
103+
<HeaderActionButton aria-label="Guest Login">
104+
<UserArrowLeftIcon className="h-4 w-4" />
105+
</HeaderActionButton>
106+
</SignInButton>
107+
)
108+
}

src/lib/cookie.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import dayjs from 'dayjs'
22
import Cookies from 'js-cookie'
33

4+
import { constants } from '@clerk/nextjs/server'
5+
46
export const TokenKey = 'mx-token'
57

6-
/**
7-
* 带了 bearer
8-
*/
98
export function getToken(): string | null {
10-
const token = Cookies.get(TokenKey)
9+
const clerkJwt = Cookies.get(constants.Cookies.Session)
10+
11+
const token = Cookies.get(TokenKey) || clerkJwt
12+
1113
return token || null
1214
}
1315

src/lib/store.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import { setGlobalStore as setStore } from 'jojoo'
2-
import { createStore } from 'jotai/vanilla'
1+
import { getDefaultStore } from 'jotai/vanilla'
32

4-
const jotaiStore = createStore()
5-
setStore(jotaiStore)
6-
7-
export { jotaiStore }
3+
export const jotaiStore = getDefaultStore()

0 commit comments

Comments
 (0)