From fe4834e6b4d588730465b92cdb2de7396a428d3b Mon Sep 17 00:00:00 2001 From: xie392 Date: Mon, 3 Jun 2024 23:04:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=AD=98=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron/main/update.ts | 1 + package.json | 3 +- specification.md | 14 + src/app.tsx | 9 +- src/components/badge.tsx | 21 - src/components/chat-list.tsx | 17 +- src/components/layout/layout-drawer.tsx | 28 +- .../messages/message-content/index.tsx | 8 +- .../virtualizer-list/virtual-list.tsx | 1 + src/components/virtualizer-list/virtual.ts | 2 + src/hooks/useCache.ts | 13 + src/hooks/useDefer.ts | 2 +- src/hooks/useDialogHistory.ts | 2 +- src/hooks/useDraggable.ts | 2 +- src/hooks/useLogin.ts | 2 +- src/hooks/useLongPress.ts | 7 +- src/i18n/locales/en.json | 96 +- src/i18n/locales/tc.json | 96 +- src/i18n/locales/zh.json | 96 +- src/pages/account/index.tsx | 2 +- src/pages/account/login.tsx | 47 +- src/pages/account/qr-code.tsx | 10 +- src/pages/account/register.tsx | 27 +- src/pages/dashboard.tsx | 2 +- src/pages/dashboard/index.tsx | 2 +- src/pages/index.tsx | 2 +- src/storage/impl.ts | 10 - src/storage/index.ts | 14 +- src/storage/services/chat-list.ts | 0 src/storage/services/friends.ts | 0 src/storage/services/group-messages.ts | 38 - src/storage/services/group.ts | 0 src/storage/services/private-messages.ts | 0 src/storage/services/request_list.ts | 0 src/stores/cache.ts | 24 + src/types/storage.d.ts | 2 +- src/types/store.d.ts | 25 + src/utils/request.ts | 16 +- src/utils/theme.ts | 5 - stats.html | 4842 +++++++++++++++++ tsconfig.json | 4 - vite.config.ts | 33 +- 42 files changed, 5274 insertions(+), 251 deletions(-) create mode 100644 electron/main/update.ts delete mode 100644 src/components/badge.tsx create mode 100644 src/hooks/useCache.ts delete mode 100644 src/storage/impl.ts delete mode 100644 src/storage/services/chat-list.ts delete mode 100644 src/storage/services/friends.ts delete mode 100644 src/storage/services/group-messages.ts delete mode 100644 src/storage/services/group.ts delete mode 100644 src/storage/services/private-messages.ts delete mode 100644 src/storage/services/request_list.ts create mode 100644 src/stores/cache.ts delete mode 100644 src/utils/theme.ts create mode 100644 stats.html diff --git a/electron/main/update.ts b/electron/main/update.ts new file mode 100644 index 00000000..07467c44 --- /dev/null +++ b/electron/main/update.ts @@ -0,0 +1 @@ +// TODO: Implement update logic diff --git a/package.json b/package.json index 57ee44ab..6ed5a2a4 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,6 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-infinite-scroll-component": "^6.1.0", - "react-router": "^6.23.1", "react-router-dom": "^6.23.1", "zustand": "^4.5.2" }, @@ -92,4 +91,4 @@ "vue-auto-translate": "^1.1.13" }, "main": "dist-electron/main.js" -} \ No newline at end of file +} diff --git a/specification.md b/specification.md index 863abd2b..f1bab50f 100644 --- a/specification.md +++ b/specification.md @@ -34,3 +34,17 @@ - build: 构建 - ci: 持续集成 - chore: 其他修改 + +# 五、其他规范 + +1.所有需要多语言化的文字都应该使用 `$t('xxx')` 包裹,这样可以自动根据当前语言切换显示。 + +```ts +import { $t } from '@/i18n' + +const Component = () => { + return
{$t('这是中文')}
+} + +return Component +``` diff --git a/src/app.tsx b/src/app.tsx index c06cb19a..1613f719 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -2,7 +2,7 @@ import { ConfigProvider } from 'antd' import { Suspense, useEffect, useState } from 'react' import useCommonStore from '@/stores/common' import Loading from '@/components/loading' -import { useRoutes } from 'react-router' +import { useRoutes } from 'react-router-dom' import routes from '~react-pages' import { App as AppComponent } from 'antd' import useAuth from '@/hooks/useLogin' @@ -13,6 +13,9 @@ import { Locale } from 'antd/es/locale' import Call from '@/components/call' const App = () => { + // 鉴权 + useAuth() + const commonStore = useCommonStore() const [locale, setLocal] = useState(enUS) @@ -27,9 +30,6 @@ const App = () => { } }, []) - // 鉴权 - useAuth() - return ( { colorPrimary: commonStore.themeColor, borderRadius: 4, fontSize: 16 - // colorBgElevated: 'transparent' } }} locale={locale} diff --git a/src/components/badge.tsx b/src/components/badge.tsx deleted file mode 100644 index 09f5ff6e..00000000 --- a/src/components/badge.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Flex } from 'antd' -import clsx from 'clsx' -import { useMemo } from 'react' - -interface BadgeProps { - count: number - className?: string -} - -const Badge: React.FC = ({ count = 0, className }) => { - const text = useMemo(() => (count >= 99 ? '99+' : count), [count]) - if (!count) return null - // {text} - return ( - - {text} - - ) -} - -export default Badge diff --git a/src/components/chat-list.tsx b/src/components/chat-list.tsx index 3d33b0c3..7a656059 100644 --- a/src/components/chat-list.tsx +++ b/src/components/chat-list.tsx @@ -2,7 +2,7 @@ import { Avatar, Flex, Badge, List, Typography } from 'antd' import React, { useCallback } from 'react' import { formatTime } from '@/utils/format-time' import { headerHeight } from '@/components/layout/layout-header' -import { useNavigate, useParams } from 'react-router' +import { useNavigate, useParams } from 'react-router-dom' import clsx from 'clsx' import VirtualizerList from '@/components/virtualizer-list' import useMobile from '@/hooks/useMobile' @@ -43,11 +43,7 @@ const ChatList: React.FC = (props) => { return ( - + ) } @@ -71,16 +67,11 @@ const ChatListItemTitle: React.FC<{ chat: ChatData }> = ({ chat }) => { ) } -const ChatListItemAvatar: React.FC<{ chat: ChatData }> = ({ chat }) => ( - -) +const ChatListItemAvatar: React.FC<{ chat: ChatData }> = ({ chat }) => const ChatListItemDescription: React.FC<{ chat: ChatData }> = ({ chat }) => { return ( - + {chat.last_message.sender_info.name}: {chat.last_message.content} ) diff --git a/src/components/layout/layout-drawer.tsx b/src/components/layout/layout-drawer.tsx index 9767e046..ca4b39a8 100644 --- a/src/components/layout/layout-drawer.tsx +++ b/src/components/layout/layout-drawer.tsx @@ -15,7 +15,7 @@ import GroupCreate from '@/components/group/group-create' import SettingList from '@/components/setting-list' import useMobile from '@/hooks/useMobile' import useUserStore from '@/stores/user' -import { useNavigate } from 'react-router' +import { useNavigate } from 'react-router-dom' import { createFingerprint } from '@/utils/fingerprint' import { getUserInfoApi } from '@/api/user' @@ -130,11 +130,7 @@ const LayoutDrawer: React.FC> = (props) => { {...props} > - + {userInfo.nickname} @@ -155,22 +151,15 @@ const LayoutDrawer: React.FC> = (props) => { gap="middle" onClick={() => handlerMenusClick(item, index)} > - - - {item.title} - + + {item.title} ))} - commonStore.update({ theme: isLight ? THEME.DARK : THEME.LIGHT }) - } + onClick={() => commonStore.update({ theme: isLight ? THEME.DARK : THEME.LIGHT })} > > = (props) => { - setModalOpen(false)} - footer={null} - > + setModalOpen(false)} footer={null}> {Component} diff --git a/src/components/messages/message-content/index.tsx b/src/components/messages/message-content/index.tsx index 83036870..de8fb0d1 100644 --- a/src/components/messages/message-content/index.tsx +++ b/src/components/messages/message-content/index.tsx @@ -6,6 +6,7 @@ import MessageItem from './message-item' import InfiniteScroll from '@/components/infinite-scroll' // import VirtualList from '@/components/virtualizer-list/virtual-list' +// TODO: 优化虚拟列表 const MessageContent = () => { const parentRef = useRef(null) const [, height] = useElementSize(parentRef) @@ -81,12 +82,7 @@ const MessageContent = () => { isScrollToEnd /> */} - + {data.reverse().map((_, index) => renderItem(index))} {/* */} diff --git a/src/components/virtualizer-list/virtual-list.tsx b/src/components/virtualizer-list/virtual-list.tsx index c81e7aef..a2d39012 100644 --- a/src/components/virtualizer-list/virtual-list.tsx +++ b/src/components/virtualizer-list/virtual-list.tsx @@ -15,6 +15,7 @@ interface VirtualListProps { children: (index: number) => React.ReactNode } +// TODO: modify all the code to use Virtual const VirtualList: React.FC = ({ data, itemHeight, height, children }) => { const containerRef = useRef(null) const [visibleData, setVisibleData] = useState([]) diff --git a/src/components/virtualizer-list/virtual.ts b/src/components/virtualizer-list/virtual.ts index 310c657b..7ad2b02a 100644 --- a/src/components/virtualizer-list/virtual.ts +++ b/src/components/virtualizer-list/virtual.ts @@ -6,6 +6,8 @@ export interface VirtualProps { renderItem: (item: T, index: number) => JSX.Element onResize?: (height: number) => void } + +// TODO: implement Virtual class class Virtual { data: T[] visibleData: T[] diff --git a/src/hooks/useCache.ts b/src/hooks/useCache.ts new file mode 100644 index 00000000..2232b599 --- /dev/null +++ b/src/hooks/useCache.ts @@ -0,0 +1,13 @@ +import storage from '@/storage' + +function useCache() { + const cacheContactList = storage.contact_list.toArray() + const cacheGroupList = storage.groups_list.toArray() + + return { + cacheContactList, + cacheGroupList + } +} + +export default useCache diff --git a/src/hooks/useDefer.ts b/src/hooks/useDefer.ts index a187d425..74dea293 100644 --- a/src/hooks/useDefer.ts +++ b/src/hooks/useDefer.ts @@ -9,7 +9,7 @@ import { useEffect, useState } from 'react' * Array.from({ length: 100 }).map((_,index)=> defer(index) ?
自定义内容
: null) * } */ -const useDefer = (max = 20) => { +function useDefer(max = 20) { const [isRendering, setIsRendering] = useState(true) const [isRenderFinish, setIsRenderFinish] = useState(false) diff --git a/src/hooks/useDialogHistory.ts b/src/hooks/useDialogHistory.ts index fdc42306..413a5021 100644 --- a/src/hooks/useDialogHistory.ts +++ b/src/hooks/useDialogHistory.ts @@ -1,6 +1,6 @@ import useCommonStore from '@/stores/common' import { useEffect } from 'react' -import { useParams, useLocation } from 'react-router' +import { useParams, useLocation } from 'react-router-dom' function useDialogHistory() { const params = useParams() diff --git a/src/hooks/useDraggable.ts b/src/hooks/useDraggable.ts index 19f03ee9..a76bb278 100644 --- a/src/hooks/useDraggable.ts +++ b/src/hooks/useDraggable.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' -const useDraggable = (el: HTMLElement | null) => { +function useDraggable(el: HTMLElement | null) { const [isDraggable, setIsDraggable] = useState(false) const handleMouseDown = (e: MouseEvent) => { diff --git a/src/hooks/useLogin.ts b/src/hooks/useLogin.ts index b8409210..0634bab7 100644 --- a/src/hooks/useLogin.ts +++ b/src/hooks/useLogin.ts @@ -1,6 +1,6 @@ import useUserStore from '@/stores/user' import { useEffect } from 'react' -import { useNavigate, useLocation } from 'react-router' +import { useNavigate, useLocation } from 'react-router-dom' function useAuth() { const userStore = useUserStore() diff --git a/src/hooks/useLongPress.ts b/src/hooks/useLongPress.ts index 0f88b59b..66c2e55f 100644 --- a/src/hooks/useLongPress.ts +++ b/src/hooks/useLongPress.ts @@ -6,10 +6,7 @@ interface LongPressOptions { data: any } -export default function useLongPress( - el: React.MutableRefObject, - options?: LongPressOptions -) { +function useLongPress(el: React.MutableRefObject, options?: LongPressOptions) { const timerRef = useRef(null) const scrollingRef = useRef(false) @@ -54,3 +51,5 @@ export default function useLongPress( } }, []) } + +export default useLongPress diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 28e9eb5f..8ef7563b 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -2,5 +2,97 @@ "你好11": "hello11", "你妈": "your mother", "你好assay": "helloassay", - "事实上,你访问的页面不存在": "In fact, the page you visited does not exist" -} + "事实上,你访问的页面不存在": "In fact, the page you visited does not exist", + "静音": "mute", + "挂断": "hang up", + "扬声器": "speaker", + "拒绝": "reject", + "接通": "Connect", + "加载更多数据": "load more data", + "名称": "name", + "类型": "type", + "公开群": "Public group", + "私密群": "private group", + "选择联系人": "Select contact", + "确定": "Sure", + "重置": "reset", + "联系人": "Contact person", + "确定要退出登陆吗?": "Are you sure you want to log out?", + "新建群组": "Create new group", + "设置": "set up", + "退出登录": "sign out", + "夜间模式": "Night mode", + "日间模式": "day mode", + "退出登陆": "sign out", + "搜索": "search", + "输入消息...": "Enter message...", + "哦不!": "Oh no!", + "没有找到相关表情": "No related expressions found", + "添加自定义表情": "Add custom emoticons", + "活动": "Activity", + "自定义": "customize", + "旗帜": "banner", + "食物与饮品": "food and drink", + "最近使用": "Recently Used", + "动物与自然": "animals and nature", + "物品": "thing", + "表情与角色": "Expressions and characters", + "旅行与景点": "Travel & Attractions", + "搜索结果": "search results", + "符号": "symbol", + "默认": "default", + "白色": "White", + "偏白": "White", + "中等": "medium", + "偏黑": "Darker", + "黑色": "black", + "选择默认肤色": "Select default skin tone", + "选择一个表情…": "Choose an emoticon…", + "全体成员": "all members", + "消息免打扰": "Do not disturb messages", + "邮箱": "Mail", + "请输入邮箱": "please input your email", + "邮箱格式不正确": "E-mail format is incorrect", + "密码": "password", + "密码长度不能小于6": "Password length cannot be less than 6", + "记住我": "remember me", + "忘记密码": "forget the password", + "登陆": "Login", + "扫码登陆": "Scan the QR code to log in", + "注册": "register", + "点击刷新": "Click to refresh", + "邮箱登陆": "log in with email", + "请使用客户端APP扫码登录": "Please use the client APP to scan the QR code to log in", + "用户名": "username", + "确认密码": "Confirm Password", + "两次密码不一致": "Two passwords are inconsistent", + "黑名单": "blacklist", + "创建群聊": "Create group chat", + "群聊信息": "Group chat information", + "群公告": "Group announcement", + "群二维码": "Group QR code", + "消息也": "News also", + "我的": "mine", + "请求列表": "Request list", + "添加好友": "add friend", + "用户信息": "User Info", + "用户二维码": "User QR code", + "设置用户ID": "Set user ID", + "生产环境": "Production Environment", + "测试环境": "test environment", + "错误": "mistake", + "星期日": "Sunday", + "星期一": "Monday", + "星期二": "Tuesday", + "星期三": "Wednesday", + "星期四": "Thursday", + "星期五": "Friday", + "星期六": "Saturday", + "昨天": "yesterday", + "解密失败": "Decryption failed", + "请输入姓名、电子邮件和密码": "Please enter name, email and password", + "请求": "ask", + "登录过期": "Login expired", + "响应": "response", + "取消重复请求": "Cancel duplicate request" +} \ No newline at end of file diff --git a/src/i18n/locales/tc.json b/src/i18n/locales/tc.json index bff665f8..1153e67a 100644 --- a/src/i18n/locales/tc.json +++ b/src/i18n/locales/tc.json @@ -2,5 +2,97 @@ "你好11": "你好11", "你妈": "你媽", "你好assay": "你好assay", - "事实上,你访问的页面不存在": "事實上,你造訪的頁面不存在" -} + "事实上,你访问的页面不存在": "事實上,你造訪的頁面不存在", + "静音": "靜音", + "挂断": "掛斷", + "扬声器": "揚聲器", + "拒绝": "拒絕", + "接通": "接通", + "加载更多数据": "載入更多數據", + "名称": "名稱", + "类型": "類型", + "公开群": "公開群", + "私密群": "私密群", + "选择联系人": "選擇聯絡人", + "确定": "確定", + "重置": "重置", + "联系人": "聯絡人", + "确定要退出登陆吗?": "確定要退出登陸嗎?", + "新建群组": "新群組", + "设置": "設定", + "退出登录": "登出登入", + "夜间模式": "夜間模式", + "日间模式": "日間模式", + "退出登陆": "退出登陸", + "搜索": "搜尋", + "输入消息...": "輸入訊息...", + "哦不!": "哦不!", + "没有找到相关表情": "沒有找到相關表情", + "添加自定义表情": "新增自訂表情", + "活动": "活動", + "自定义": "自訂", + "旗帜": "旗幟", + "食物与饮品": "食物與飲品", + "最近使用": "最近使用", + "动物与自然": "動物與自然", + "物品": "物品", + "表情与角色": "表情與角色", + "旅行与景点": "旅行與景點", + "搜索结果": "搜尋結果", + "符号": "符號", + "默认": "預設", + "白色": "白色", + "偏白": "偏白", + "中等": "中等", + "偏黑": "偏黑", + "黑色": "黑色", + "选择默认肤色": "選擇預設膚色", + "选择一个表情…": "選擇一個表情…", + "全体成员": "全體成員", + "消息免打扰": "訊息免打擾", + "邮箱": "信箱", + "请输入邮箱": "請輸入信​​箱", + "邮箱格式不正确": "郵箱格式不正確", + "密码": "密碼", + "密码长度不能小于6": "密碼長度不能小於6", + "记住我": "記住我", + "忘记密码": "忘記密碼", + "登陆": "登陸", + "扫码登陆": "掃碼登陸", + "注册": "註冊", + "点击刷新": "點擊刷新", + "邮箱登陆": "信箱登陸", + "请使用客户端APP扫码登录": "請使用客戶端APP掃碼登入", + "用户名": "使用者名稱", + "确认密码": "確認密碼", + "两次密码不一致": "兩次密碼不一致", + "黑名单": "黑名單", + "创建群聊": "建立群聊", + "群聊信息": "群聊資訊", + "群公告": "群公告", + "群二维码": "群二維碼", + "消息也": "訊息也", + "我的": "我的", + "请求列表": "請求列表", + "添加好友": "新增好友", + "用户信息": "使用者資訊", + "用户二维码": "使用者二維碼", + "设置用户ID": "設定用戶ID", + "生产环境": "生產環境", + "测试环境": "測試環境", + "错误": "錯誤", + "星期日": "星期日", + "星期一": "星期一", + "星期二": "星期二", + "星期三": "星期三", + "星期四": "星期四", + "星期五": "星期五", + "星期六": "星期六", + "昨天": "昨天", + "解密失败": "解密失敗", + "请输入姓名、电子邮件和密码": "請輸入姓名、電子郵件和密碼", + "请求": "請求", + "登录过期": "登入過期", + "响应": "回應", + "取消重复请求": "取消重複請求" +} \ No newline at end of file diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index 007f9c73..94de015a 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -2,5 +2,97 @@ "你好11": "你好11", "你妈": "你妈", "你好assay": "你好assay", - "事实上,你访问的页面不存在": "事实上,你访问的页面不存在" -} + "事实上,你访问的页面不存在": "事实上,你访问的页面不存在", + "静音": "静音", + "挂断": "挂断", + "扬声器": "扬声器", + "拒绝": "拒绝", + "接通": "接通", + "加载更多数据": "加载更多数据", + "名称": "名称", + "类型": "类型", + "公开群": "公开群", + "私密群": "私密群", + "选择联系人": "选择联系人", + "确定": "确定", + "重置": "重置", + "联系人": "联系人", + "确定要退出登陆吗?": "确定要退出登陆吗?", + "新建群组": "新建群组", + "设置": "设置", + "退出登录": "退出登录", + "夜间模式": "夜间模式", + "日间模式": "日间模式", + "退出登陆": "退出登陆", + "搜索": "搜索", + "输入消息...": "输入消息...", + "哦不!": "哦不!", + "没有找到相关表情": "没有找到相关表情", + "添加自定义表情": "添加自定义表情", + "活动": "活动", + "自定义": "自定义", + "旗帜": "旗帜", + "食物与饮品": "食物与饮品", + "最近使用": "最近使用", + "动物与自然": "动物与自然", + "物品": "物品", + "表情与角色": "表情与角色", + "旅行与景点": "旅行与景点", + "搜索结果": "搜索结果", + "符号": "符号", + "默认": "默认", + "白色": "白色", + "偏白": "偏白", + "中等": "中等", + "偏黑": "偏黑", + "黑色": "黑色", + "选择默认肤色": "选择默认肤色", + "选择一个表情…": "选择一个表情…", + "全体成员": "全体成员", + "消息免打扰": "消息免打扰", + "邮箱": "邮箱", + "请输入邮箱": "请输入邮箱", + "邮箱格式不正确": "邮箱格式不正确", + "密码": "密码", + "密码长度不能小于6": "密码长度不能小于6", + "记住我": "记住我", + "忘记密码": "忘记密码", + "登陆": "登陆", + "扫码登陆": "扫码登陆", + "注册": "注册", + "点击刷新": "点击刷新", + "邮箱登陆": "邮箱登陆", + "请使用客户端APP扫码登录": "请使用客户端APP扫码登录", + "用户名": "用户名", + "确认密码": "确认密码", + "两次密码不一致": "两次密码不一致", + "黑名单": "黑名单", + "创建群聊": "创建群聊", + "群聊信息": "群聊信息", + "群公告": "群公告", + "群二维码": "群二维码", + "消息也": "消息也", + "我的": "我的", + "请求列表": "请求列表", + "添加好友": "添加好友", + "用户信息": "用户信息", + "用户二维码": "用户二维码", + "设置用户ID": "设置用户ID", + "生产环境": "生产环境", + "测试环境": "测试环境", + "错误": "错误", + "星期日": "星期日", + "星期一": "星期一", + "星期二": "星期二", + "星期三": "星期三", + "星期四": "星期四", + "星期五": "星期五", + "星期六": "星期六", + "昨天": "昨天", + "解密失败": "解密失败", + "请输入姓名、电子邮件和密码": "请输入姓名、电子邮件和密码", + "请求": "请求", + "登录过期": "登录过期", + "响应": "响应", + "取消重复请求": "取消重复请求" +} \ No newline at end of file diff --git a/src/pages/account/index.tsx b/src/pages/account/index.tsx index cf5c2786..49fba57a 100644 --- a/src/pages/account/index.tsx +++ b/src/pages/account/index.tsx @@ -1,4 +1,4 @@ -import { Navigate } from 'react-router' +import { Navigate } from 'react-router-dom' const Account = () => { return diff --git a/src/pages/account/login.tsx b/src/pages/account/login.tsx index e7809870..6dca19ba 100644 --- a/src/pages/account/login.tsx +++ b/src/pages/account/login.tsx @@ -1,9 +1,9 @@ -import React, { useEffect, useState } from 'react' +import { useEffect, useState } from 'react' import { LockOutlined, MailOutlined } from '@ant-design/icons' import { Button, Form, Input, Avatar, Flex, Checkbox, message } from 'antd' import { $t } from '@/i18n' import clsx from 'clsx' -import { NavigateOptions, useLocation, useNavigate } from 'react-router' +import { NavigateOptions, useLocation, useNavigate } from 'react-router-dom' import useUserStore from '@/stores/user' import { createFingerprint } from '@/utils/fingerprint' @@ -67,18 +67,10 @@ const Login: React.FC = () => { return ( <> {contextHolder} - +
{ if (!value) { return Promise.reject($t('请输入邮箱')) } - if ( - !/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test( - value - ) - ) { + if (!/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value)) { return Promise.reject($t('邮箱格式不正确')) } return Promise.resolve() @@ -124,12 +112,7 @@ const Login: React.FC = () => { }) ]} > - } - type="password" - placeholder={$t('密码')} - /> + } type="password" placeholder={$t('密码')} /> @@ -143,28 +126,16 @@ const Login: React.FC = () => { - - toQRCode({ replace: true })} - > + toQRCode({ replace: true })}> {$t('扫码登陆')} - toRegister({ replace: true })} - > + toRegister({ replace: true })}> {$t('注册')} diff --git a/src/pages/account/qr-code.tsx b/src/pages/account/qr-code.tsx index f62aa447..a5a2e419 100644 --- a/src/pages/account/qr-code.tsx +++ b/src/pages/account/qr-code.tsx @@ -2,7 +2,7 @@ import { $t } from '@/i18n' import { Button, Flex, Form, QRCode } from 'antd' import clsx from 'clsx' -import { NavigateOptions, useNavigate } from 'react-router' +import { NavigateOptions, useNavigate } from 'react-router-dom' // import QRCodeImg from '@/assets/qrcode.png' import { useEffect, useState } from 'react' @@ -37,13 +37,7 @@ const QRCodePage: React.FC = () => { return ( <> - +
{/* {isExpire && ( diff --git a/src/pages/account/register.tsx b/src/pages/account/register.tsx index e3c0dce5..462df8a1 100644 --- a/src/pages/account/register.tsx +++ b/src/pages/account/register.tsx @@ -3,7 +3,7 @@ import { LockOutlined, MailOutlined, UserOutlined } from '@ant-design/icons' import { Button, Form, Input, Avatar, Flex, message } from 'antd' import { $t } from '@/i18n' import clsx from 'clsx' -import { NavigateOptions, useNavigate } from 'react-router' +import { NavigateOptions, useNavigate } from 'react-router-dom' import { registerApi } from '@/api/user' import useUserStore from '@/stores/user' @@ -59,9 +59,7 @@ const Register: React.FC = () => { {contextHolder} { if (!value) { return Promise.reject($t('请输入邮箱')) } - if ( - !/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test( - value - ) - ) { + if (!/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value)) { return Promise.reject($t('邮箱格式不正确')) } return Promise.resolve() @@ -109,12 +103,7 @@ const Register: React.FC = () => { }) ]} > - } - type="password" - placeholder={$t('密码')} - /> + } type="password" placeholder={$t('密码')} /> { } type="password" placeholder={$t('确认密码')} /> - diff --git a/src/pages/dashboard.tsx b/src/pages/dashboard.tsx index 94f9ad01..76f3b941 100644 --- a/src/pages/dashboard.tsx +++ b/src/pages/dashboard.tsx @@ -1,6 +1,6 @@ import { Flex } from 'antd' import LayoutSidebar from '@/components/layout/layout-sidebar' -import { Outlet } from 'react-router' +import { Outlet } from 'react-router-dom' import useDialogHistory from '@/hooks/useDialogHistory' const Dashboard = () => { diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index 8ef66741..91cb6cad 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -1,7 +1,7 @@ import useCommonStore from '@/stores/common' import { Avatar, Flex } from 'antd' import { memo } from 'react' -import { Navigate } from 'react-router' +import { Navigate } from 'react-router-dom' const Dashboard = memo(() => { const commonStore = useCommonStore() diff --git a/src/pages/index.tsx b/src/pages/index.tsx index a7b30e3d..fb0a41f0 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,4 +1,4 @@ -import { Navigate } from 'react-router' +import { Navigate } from 'react-router-dom' const Home = () => diff --git a/src/storage/impl.ts b/src/storage/impl.ts deleted file mode 100644 index 50948bcd..00000000 --- a/src/storage/impl.ts +++ /dev/null @@ -1,10 +0,0 @@ -import Storage from '.' - -class StorageImpl extends Storage { - // private tableName: string - // constructor(tableName: string) { - // this.tableName = tableName - // } -} - -export default StorageImpl diff --git a/src/storage/index.ts b/src/storage/index.ts index 9ecd899e..abdab7e1 100644 --- a/src/storage/index.ts +++ b/src/storage/index.ts @@ -1,5 +1,5 @@ import useUserStore from '@/stores/user' -import type { FriendData, GroupData, RequestData } from '@/types/storage' +import type { ContactData, GroupData, RequestData } from '@/types/storage' import Dexie, { Table } from 'dexie' class Storage extends Dexie { @@ -7,8 +7,8 @@ class Storage extends Dexie { group_messages!: Table chat_list!: Table request_list!: Table - friends!: Table - groups!: Table + contact_list!: Table + groups_list!: Table constructor(name: string, version: number = 1) { super(name) @@ -17,8 +17,8 @@ class Storage extends Dexie { group_messages: '++id, msg_id, dialog_id, content, type, sender_id, receiver_id, group_id', chat_list: '++id, dialog_id, dialog_name, dialog_avatar, top_at, last_message', request_list: '++id, request_id, dialog_id', // TODO: add more fields - friends: '++id, user_id', // TODO: add more fields - groups: '++id, group_id' // TODO: add more fields + contact_list: '++id, user_id', // TODO: add more fields + groups_list: '++id, group_id' // TODO: add more fields }) } } @@ -29,4 +29,6 @@ export function createStorage(name: string = 'coss-storage', version: number = 1 return new Storage(`${name}-${userId}`, version) } -export default Storage +const storage = createStorage() + +export default storage diff --git a/src/storage/services/chat-list.ts b/src/storage/services/chat-list.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/storage/services/friends.ts b/src/storage/services/friends.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/storage/services/group-messages.ts b/src/storage/services/group-messages.ts deleted file mode 100644 index 492f1dbc..00000000 --- a/src/storage/services/group-messages.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { inject } from 'inversify' -import Storage, { TYPES } from '..' - -class GroupMessagesService { - private tableName = 'group_messages' - - constructor(@inject(TYPES.Storage) private readonly storage: Storage) {} - - getTableName() { - return this.tableName - } - - async find(groupId: string) { - return this.storage.table(this.tableName).get(groupId) - } - - async create(groupId: string, message: string) { - return this.storage.table(this.tableName).bulkAdd([{ groupId, message }]) - } - - async update(groupId: string, message: string) { - return this.storage.table(this.tableName).update(groupId, { message }) - } - - async delete(groupId: string) { - return this.storage.table(this.tableName).delete(groupId) - } - - async clear() { - return this.storage.table(this.tableName).clear() - } - - async getAll() { - return this.storage.table(this.tableName).toArray() - } -} - -export default GroupMessagesService diff --git a/src/storage/services/group.ts b/src/storage/services/group.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/storage/services/private-messages.ts b/src/storage/services/private-messages.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/storage/services/request_list.ts b/src/storage/services/request_list.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/stores/cache.ts b/src/stores/cache.ts new file mode 100644 index 00000000..c267dff2 --- /dev/null +++ b/src/stores/cache.ts @@ -0,0 +1,24 @@ +import { create } from 'zustand' +import type { CacheOptions, CacheStore, CacheStoreMethods } from '@/types/store' + +const states: CacheOptions = { + cacheChatList: [], + cacheContactList: [], + cacheGroupList: [], + cacheMessageUnread: 0, + cacheRequestList: [] +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const actions = (set: any, _get: any): CacheStoreMethods => ({ + update: async (options) => set(options) +}) + +const cacheStore = (set: any, get: any): CacheStore => ({ + ...states, + ...actions(set, get) +}) + +const useCacheStore = create(cacheStore) + +export default useCacheStore diff --git a/src/types/storage.d.ts b/src/types/storage.d.ts index 11a49a5a..771733dd 100644 --- a/src/types/storage.d.ts +++ b/src/types/storage.d.ts @@ -1,5 +1,5 @@ export interface RequestData {} -export interface FriendData {} +export interface ContactData {} export interface GroupData {} diff --git a/src/types/store.d.ts b/src/types/store.d.ts index 6053451d..ddf00451 100644 --- a/src/types/store.d.ts +++ b/src/types/store.d.ts @@ -1,4 +1,5 @@ import { LoginParams, LogoutParams } from './api' +import { GroupData, RequestData, ContactData } from './storage' export interface CommonOptions { /** @@ -81,9 +82,33 @@ export interface CallStoreMethods { hangup: () => Promise> } +/** @description 缓存聊天记录 */ +// cacheChatRecord: ChatRecordData[] +/** @description 缓存消息列表, 包括未读消息 */ +// cacheMessageList: Message[] +export interface CacheOptions { + /** @description 缓存会话列表 */ + cacheChatList: ChatData[] + /** @description 缓存联系人列表 */ + cacheContactList: ContactData[] + /** @description 缓存群组列表 */ + cacheGroupList: GroupData[] + /** @description 缓存消息未读数 */ + cacheMessageUnread: number + /** @description 缓存申请列表 */ + cacheRequestList: RequestData[] +} + +export interface CacheStoreMethods { + /** @description 更新某个值 */ + update: (options: Partial) => Promise +} + // 通用仓库 export type CommonStore = CommonOptions & CommonStoreMethods // 用户仓库 export type UserStore = UserOptions & UserStoreMethods // 通话仓库 export type CallStore = CallOptions & CallStoreMethods +// 本地存储仓库 +export type CacheStore = CacheOptions & CacheStoreMethods diff --git a/src/utils/request.ts b/src/utils/request.ts index 6c29ee6a..89a84f98 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -1,6 +1,5 @@ import axios from 'axios' import type { InternalAxiosRequestConfig, AxiosResponse, AxiosError } from 'axios' -// import { getCookie, removeAllCookie } from './cookie' import useUserStore from '@/stores/user' import { RESPONSE_CODE } from '@/utils/enum' import PGPUtils from '@/utils/pgp' @@ -66,8 +65,6 @@ const getClientKeys = async () => { try { const clientKey = JSON.parse(window.localStorage.getItem('PGPKEYSCLIENT')!) if (!clientKey) { - // f7.dialog.close() - // f7.dialog.alert('数据丢失,请找回账号...') return null } return clientKey @@ -137,11 +134,7 @@ service.interceptors.response.use( // 获取客户端密钥 const clientKey = await getClientKeys() if (!clientKey) return responseData - const aesKey = await PGPUtils.rsaDecrypt( - clientKey.privateKey, - pgpEnv.passphrase, - responseData.secret - ) + const aesKey = await PGPUtils.rsaDecrypt(clientKey.privateKey, pgpEnv.passphrase, responseData.secret) const decryptedData = await PGPUtils.aes256Decrypt(responseData.message, aesKey) response.data = decryptedData } catch (error) { @@ -155,13 +148,6 @@ service.interceptors.response.use( (error: AxiosError) => { if (error.response) { if (error.response.status === 401) { - // f7.dialog.close() - // f7.dialog.alert('登录已过期,请重新登录', '登录过期', () => { - // // 清除 token 及 用户信息 - // removeAllCookie() - // location.reload() - // return false - // }) useUserStore().update({ userId: '', userInfo: '', diff --git a/src/utils/theme.ts b/src/utils/theme.ts deleted file mode 100644 index 481ade5a..00000000 --- a/src/utils/theme.ts +++ /dev/null @@ -1,5 +0,0 @@ -const layoutToken = { - siderBg: 'hls(var(--background))' -} - -export { layoutToken } diff --git a/stats.html b/stats.html new file mode 100644 index 00000000..b15805c2 --- /dev/null +++ b/stats.html @@ -0,0 +1,4842 @@ + + + + + + + + Rollup Visualizer + + + +
+ + + + + diff --git a/tsconfig.json b/tsconfig.json index d2d88194..a9e36c88 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,10 +20,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, - "types": ["reflect-metadata"], - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "baseUrl": ".", "paths": { "@/*": ["./src/*"], diff --git a/vite.config.ts b/vite.config.ts index 2edb2930..2e42b449 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -14,7 +14,7 @@ export default defineConfig({ plugins: [ react(), pages() - // visualizer({ open: false }) + // visualizer({ open: true }) ], resolve: { alias: { @@ -31,25 +31,24 @@ export default defineConfig({ 'process.env': {} }, build: { - minify: 'terser', - cssCodeSplit: true, - terserOptions: { - compress: { - drop_console: false, - drop_debugger: true - } - }, + // minify: 'terser', + // cssCodeSplit: true, + // terserOptions: { + // compress: { + // drop_console: false, + // drop_debugger: true + // } + // }, chunkSizeWarningLimit: 1000, rollupOptions: { output: { - // manualChunks(id) { - // if (id.includes('node_modules')) { - // return id.toString().split('node_modules/')[1].split('/')[0].toString() - // } - // } - chunkFileNames: 'js/[name]-[hash].js', - entryFileNames: 'js/[name]-[hash].js', - assetFileNames: '[ext]/[name]-[hash].[ext]' + manualChunks: { + openpgp: ['openpgp'], + i18next: ['i18next'] + } + // chunkFileNames: 'js/[name]-[hash].js', + // entryFileNames: 'js/[name]-[hash].js', + // assetFileNames: '[ext]/[name]-[hash].[ext]' } } }