Compare commits

...

3 Commits

Author SHA1 Message Date
CrescentLeaf
e22d99d04f featwip 资料卡 2025-12-13 12:33:00 +08:00
CrescentLeaf
a6ddb9025a 改用数据模式 Router 2025-12-13 12:32:48 +08:00
CrescentLeaf
bf1551c6c3 封装路由对话框函数
* 并且修复了用户手动返回导致动画丢失的问题
2025-12-13 12:32:24 +08:00
3 changed files with 207 additions and 147 deletions

View File

@@ -3,7 +3,7 @@ import useEventListener from "../utils/useEventListener.ts"
import AvatarMySelf from "./AvatarMySelf.tsx" import AvatarMySelf from "./AvatarMySelf.tsx"
import MainSharedContext from './MainSharedContext.ts' import MainSharedContext from './MainSharedContext.ts'
import * as React from 'react' import * as React from 'react'
import { BrowserRouter, Link, Outlet, Route, Routes, useNavigate } from "react-router" import { BrowserRouter, createBrowserRouter, Link, Outlet, Route, RouterProvider, Routes } from "react-router"
import LoginDialog from "./main-page/LoginDialog.tsx" import LoginDialog from "./main-page/LoginDialog.tsx"
import useAsyncEffect from "../utils/useAsyncEffect.ts" import useAsyncEffect from "../utils/useAsyncEffect.ts"
import performAuth from "../performAuth.ts" import performAuth from "../performAuth.ts"
@@ -18,24 +18,7 @@ import AllChatsList from "./main-page/AllChatsList.tsx"
import FavouriteChatsList from "./main-page/FavouriteChatsList.tsx" import FavouriteChatsList from "./main-page/FavouriteChatsList.tsx"
import AddFavourtieChatDialog from "./main-page/AddFavourtieChatDialog.tsx" import AddFavourtieChatDialog from "./main-page/AddFavourtieChatDialog.tsx"
import RecentChatsList from "./main-page/RecentChatsList.tsx" import RecentChatsList from "./main-page/RecentChatsList.tsx"
import ChatInfoDialog from "./routers/ChatInfoDialog.tsx" import UserOrChatInfoDialog from "./routers/UserOrChatInfoDialog.tsx"
function Test() {
const nav = useNavigate()
const dialogRef = React.useRef<Dialog>()
useAsyncEffect(async () => {
await sleep(10)
dialogRef.current!.open = true
dialogRef.current!.addEventListener('overlay-click', () => {
dialogRef.current!.open = false
})
dialogRef.current!.addEventListener('closed', async () => {
await sleep(100)
nav(-1)
})
}, [])
return <mdui-dialog ref={dialogRef}></mdui-dialog>
}
export default function Main() { export default function Main() {
const [myProfileCache, setMyProfileCache] = React.useState<UserMySelf>() const [myProfileCache, setMyProfileCache] = React.useState<UserMySelf>()
@@ -111,11 +94,8 @@ export default function Main() {
waitingForAuth.open = false waitingForAuth.open = false
}) })
return ( const Root = (
<BrowserRouter>
<MainSharedContext.Provider value={sharedContext}> <MainSharedContext.Provider value={sharedContext}>
<Routes>
<Route path="/" element={(
<div style={{ <div style={{
display: "flex", display: "flex",
position: 'relative', position: 'relative',
@@ -230,14 +210,16 @@ export default function Main() {
</mdui-navigation-bar> </mdui-navigation-bar>
} }
</div> </div>
)}>
<Route path="info">
<Route path="chat" element={<Test />} />
<Route path="user" element={<ChatInfoDialog />} />
</Route>
</Route>
</Routes>
</MainSharedContext.Provider> </MainSharedContext.Provider>
</BrowserRouter>
) )
const router = createBrowserRouter([{
path: "/",
element: Root,
children: [
{ path: 'info/:type', Component: UserOrChatInfoDialog, },
],
}])
return <RouterProvider router={router} />
} }

View File

@@ -0,0 +1,46 @@
import { dialog } from "mdui"
import useRouterDialogRef from "./useRouterDialogRef"
import { BlockerFunction, useBlocker, useLocation, useNavigate, useParams, useSearchParams } from "react-router"
import useAsyncEffect from "../../utils/useAsyncEffect"
import { CallbackError, Chat } from "lingchair-client-protocol"
import showSnackbar from "../../utils/showSnackbar"
import getClient from "../../getClient"
import Avatar from "../Avatar"
import { useContextSelector } from "use-context-selector"
import MainSharedContext, { Shared } from "../MainSharedContext"
import * as React from 'react'
export default function UserOrChatInfoDialog() {
const shared = useContextSelector(MainSharedContext, (context: Shared) => ({
myProfileCache: context.myProfileCache,
favouriteChats: context.favouriteChats,
}))
const dialogRef = useRouterDialogRef()
const location = useLocation()
const searchParams = useSearchParams()
const params = useParams()
return (
<mdui-dialog close-on-overlay-click close-on-esc ref={dialogRef}>
<span style={{
wordBreak: "break-word",
}} dangerouslySetInnerHTML={{
__html: "↓ searchParams<br><br>"
+ Object.keys(location)
// @ts-ignore 懒
.map((k) => `${k} = ${location[k]}`)
.join('<br><br>')
+ "<br><br>↓ searchParams<br><br>" + Object.keys(searchParams)
// @ts-ignore 懒
.map((k) => `${k} = ${searchParams[k]}`)
.join('<br><br>')
+ "<br><br>↓ params<br><br>" + Object.keys(params)
// @ts-ignore 懒
.map((k) => `${k} = ${params[k]}`)
.join('<br><br>')
}}></span>
</mdui-dialog>
)
}

View File

@@ -0,0 +1,32 @@
import { Dialog } from "mdui"
import useAsyncEffect from "../../utils/useAsyncEffect"
import sleep from "../../utils/sleep"
import { useBlocker, useNavigate } from "react-router"
import * as React from 'react'
export default function useRouterDialogRef() {
const dialogRef = React.useRef<Dialog>()
const shouldBlock = React.useRef(true)
const nav = useNavigate()
const blocker = useBlocker(({ currentLocation, nextLocation }) => shouldBlock.current && currentLocation.pathname !== nextLocation.pathname)
// 避免用户手动返回导致动画丢失
React.useEffect(() => {
if (blocker.state === "blocked") {
// 这个让姐姐来就好啦
dialogRef.current!.open = false
}
}, [blocker])
useAsyncEffect(async () => {
await sleep(10)
dialogRef.current!.open = true
dialogRef.current!.addEventListener('closed', async () => {
await sleep(10)
// 无论如何, 让姐姐先解除返回限制, 这样才能出去嘛
shouldBlock.current = false
nav(-1)
})
}, [])
return dialogRef
}