diff --git a/client-protocol/CallbackError.ts b/client-protocol/CallbackError.ts index c681760..14ac757 100644 --- a/client-protocol/CallbackError.ts +++ b/client-protocol/CallbackError.ts @@ -1,7 +1,11 @@ import ApiCallbackMessage from "./ApiCallbackMessage.ts" export default class CallbackError extends Error { + declare code: number + declare data?: object constructor(re: ApiCallbackMessage) { super(`[${re.code}] ${re.msg}${re.data ? ` (data: ${JSON.stringify(re.data)})` : ''}`) + this.code = re.code + this.data = re.data } } \ No newline at end of file diff --git a/client-protocol/main.ts b/client-protocol/main.ts index e1f6088..ce364d0 100644 --- a/client-protocol/main.ts +++ b/client-protocol/main.ts @@ -7,10 +7,13 @@ import GroupSettingsBean from "./bean/GroupSettingsBean.ts" import JoinRequestBean from "./bean/JoinRequestBean.ts" import MessageBean from "./bean/MessageBean.ts" import RecentChatBean from "./bean/RecentChatBean.ts" + import LingChairClient from "./LingChairClient.ts" +import CallbackError from "./CallbackError.ts" export { LingChairClient, + CallbackError, Chat, User, diff --git a/client/package.json b/client/package.json index 19bd22a..479b26d 100644 --- a/client/package.json +++ b/client/package.json @@ -15,6 +15,7 @@ "pinch-zoom-element": "1.1.1", "react": "18.3.1", "react-dom": "18.3.1", + "react-router": "7.10.1", "socket.io-client": "4.8.1", "split.js": "1.3.2", "ua-parser-js": "2.0.6" diff --git a/client/performAuth.ts b/client/performAuth.ts index a513687..258bbf8 100644 --- a/client/performAuth.ts +++ b/client/performAuth.ts @@ -2,7 +2,9 @@ import data from "./Data.ts"; import getClient from "./getClient.ts" /** - * 客户端上线 + * 尝试进行验证 + * + * 成功后自动保存到本地 * * 优先级: 账号密码 > 提供刷新令牌 > 储存的刷新令牌 * @@ -23,4 +25,5 @@ export default async function performAuth(args: { } data.refresh_token = getClient().getCachedRefreshToken() data.access_token = getClient().getCachedAccessToken() + data.apply() } diff --git a/client/ui/ImageViewer.tsx b/client/ui/ImageViewer.tsx new file mode 100644 index 0000000..ee06537 --- /dev/null +++ b/client/ui/ImageViewer.tsx @@ -0,0 +1,19 @@ +import { Dialog } from 'mdui' +import 'pinch-zoom-element' +import React from "react" + +export default function ImageViewer() { + const dialogRef = React.useRef() + + return + + + dialogRef.current!.open = false}> + + { + // @ts-ignore 注册了这个元素 + + } + +} diff --git a/client/ui/Main.tsx b/client/ui/Main.tsx index d441729..0743b15 100644 --- a/client/ui/Main.tsx +++ b/client/ui/Main.tsx @@ -1,104 +1,146 @@ import isMobileUI from "../utils/isMobileUI.ts" +import useEventListener from "../utils/useEventListener.ts" import AvatarMySelf from "./AvatarMySelf.tsx" import MainSharedContext from './MainSharedContext.ts' import React from "react" +import { BrowserRouter, Outlet, Route, Routes } from "react-router" +import LoginDialog from "./main-page/LoginDialog.tsx" +import useAsyncEffect from "../utils/useAsyncEffect.ts" +import performAuth from "../performAuth.ts" +import { CallbackError } from "lingchair-client-protocol" export default function Main() { + const [showLoginDialog, setShowLoginDialog] = React.useState(false) + + // 多页面切换 + const navigationRef = React.useRef() + const [currentShowPage, setCurrentShowPage] = React.useState('Recents') + type HTMLElementWithValue = HTMLElement & { value: string } + useEventListener(navigationRef, 'change', (event) => { + setCurrentShowPage((event.target as HTMLElementWithValue).value) + }) + const sharedContext = { - openChatFragment: React.useRef() + ui_functions: React.useRef({ + + }), + setShowLoginDialog, } + + useAsyncEffect(async () => { + try { + await performAuth({}) + } catch (e) { + if (e instanceof CallbackError) + if (e.code == 401 || e.code == 400) + setShowLoginDialog(true) + } + }) + return ( -
- { - /** - * Default: 侧边列表提供列表切换 - */ - !isMobileUI() ? - - - - - - - - - - - - - - 添加收藏对话 - 创建群组 - - - - /** - * Mobile: 底部导航栏提供列表切换 - */ - : + + - { - ({ - Recents: "最近对话", - Contacts: "收藏对话", - AllChats: "所有对话", - })['Recents'] - } -
- - - - 添加收藏对话 - 创建群组 - - - - - - -
- } - { - /** - * Mobile: 指定高度的容器 - * Default: 侧边列表 - */ - - } - { - /** - * Mobile: 底部导航栏提供列表切换 - * Default: 侧边列表提供列表切换 - */ - isMobileUI() && - 最近对话 - 收藏对话 - 全部对话 - - } -
+ + + + + + + + + 添加收藏对话 + 创建群组 + + + + /** + * Mobile: 底部导航栏提供列表切换 + */ + : + { + ({ + Recents: "最近对话", + Contacts: "收藏对话", + AllChats: "所有对话", + })['Recents'] + } +
+ + + + 添加收藏对话 + 创建群组 + + + + + + +
+ } + { + /** + * Mobile: 指定高度的容器 + * Default: 侧边列表 + */ + + } + { + /** + * Mobile: 底部导航栏提供列表切换 + * Default: 侧边列表提供列表切换 + */ + isMobileUI() && + 最近对话 + 收藏对话 + 全部对话 + + } + + )}> + + +
) } \ No newline at end of file diff --git a/client/ui/main-page/LoginDialog.tsx b/client/ui/main-page/LoginDialog.tsx new file mode 100644 index 0000000..4ab3240 --- /dev/null +++ b/client/ui/main-page/LoginDialog.tsx @@ -0,0 +1,44 @@ +import * as React from 'react' +import { Button, Dialog, TextField } from "mdui" + +import performAuth from '../../performAuth.ts' +import useEventListener from '../../utils/useEventListener.ts' +import showSnackbar from '../../utils/showSnackbar.ts' + +export default function LoginDialog({ ...props }: { open: boolean } & React.HTMLAttributes) { + const loginDialogRef = React.useRef(null) + const loginButtonRef = React.useRef