From 265bf11ad08616c7101e50e8b8b2767a50ae9b51 Mon Sep 17 00:00:00 2001 From: Tristan Yang Date: Fri, 2 Sep 2022 08:59:19 +0800 Subject: [PATCH] refactor: guest mode --- src/app/cache/useRehydrate.ts | 11 -- src/app/listener.middleware/index.ts | 3 - src/app/slices/auth.data.ts | 4 + src/common/component/RequireAuth.tsx | 20 ++- src/routes/chat/GuestBlankPlaceholder.tsx | 55 ++++++ .../GuestChannelChatInfo}/index.tsx | 6 +- .../GuestChannelChatInfo}/styled.tsx | 0 .../GuestSessionList}/Session.tsx | 2 +- .../GuestSessionList}/index.tsx | 2 - .../GuestSessionList}/styled.tsx | 0 src/routes/chat/Layout/styled.tsx | 3 - src/routes/chat/index.tsx | 21 ++- src/routes/chat/styled.tsx | 3 + src/routes/guest/BlankPlaceholder.tsx | 20 --- src/routes/guest/OffTip.tsx | 20 --- src/routes/guest/index.tsx | 65 ------- src/routes/guest/styled.tsx | 160 ------------------ src/routes/home/index.tsx | 73 ++++---- src/routes/home/styled.tsx | 3 + src/routes/index.tsx | 35 +--- 20 files changed, 140 insertions(+), 366 deletions(-) create mode 100644 src/routes/chat/GuestBlankPlaceholder.tsx rename src/routes/{guest/ChannelChat => chat/GuestChannelChatInfo}/index.tsx (93%) rename src/routes/{guest/ChannelChat => chat/GuestChannelChatInfo}/styled.tsx (100%) rename src/routes/{guest/SessionList => chat/GuestSessionList}/Session.tsx (96%) rename src/routes/{guest/SessionList => chat/GuestSessionList}/index.tsx (97%) rename src/routes/{guest/SessionList => chat/GuestSessionList}/styled.tsx (100%) delete mode 100644 src/routes/guest/BlankPlaceholder.tsx delete mode 100644 src/routes/guest/OffTip.tsx delete mode 100644 src/routes/guest/index.tsx delete mode 100644 src/routes/guest/styled.tsx diff --git a/src/app/cache/useRehydrate.ts b/src/app/cache/useRehydrate.ts index 2ccd60ef..a8f6a97a 100644 --- a/src/app/cache/useRehydrate.ts +++ b/src/app/cache/useRehydrate.ts @@ -10,22 +10,11 @@ import { fillUsers } from "../slices/users"; import { fillFootprint } from "../slices/footprint"; import { fillFileMessage } from "../slices/message.file"; import { fillUI } from "../slices/ui"; -import { useAppSelector } from "../store"; const useRehydrate = () => { const [iterated, setIterated] = useState(false); const dispatch = useDispatch(); - const { isGuest } = useAppSelector((store) => { - return { - isGuest: store.authData.user?.create_by == "guest" - }; - }); const rehydrate = async () => { - // 如果是游客,直接忽略 - if (isGuest) { - setIterated(true); - return; - } const rehydrateData = { channels: [], users: [], diff --git a/src/app/listener.middleware/index.ts b/src/app/listener.middleware/index.ts index 84bda282..76b5e1a9 100644 --- a/src/app/listener.middleware/index.ts +++ b/src/app/listener.middleware/index.ts @@ -46,9 +46,6 @@ listenerMiddleware.startListening({ // console.log("effect opt", action); if (!window.CACHE && prefix !== "__rtkq") return; const currentState = listenerApi.getState() as RootState; - // 如果是guest,则忽略 - const isGuest = currentState.authData.user?.create_by === "guest"; - if (isGuest) return; const state = prefix == "__rtkq" ? null : currentState[prefix]; switch (prefix) { case "__rtkq": diff --git a/src/app/slices/auth.data.ts b/src/app/slices/auth.data.ts index 8b323268..96427dcc 100644 --- a/src/app/slices/auth.data.ts +++ b/src/app/slices/auth.data.ts @@ -12,6 +12,7 @@ import { User } from "../../types/user"; interface State { initialized: boolean; + guest: boolean; user: User | undefined; token: string; expireTime: number; @@ -20,6 +21,7 @@ interface State { const loginUser = localStorage.getItem(KEY_LOGIN_USER) || ""; const initialState: State = { initialized: true, + guest: false, user: loginUser ? JSON.parse(loginUser) : undefined, token: localStorage.getItem(KEY_TOKEN) || "", expireTime: Number(localStorage.getItem(KEY_EXPIRE) || +new Date()), @@ -28,6 +30,7 @@ const initialState: State = { const emptyState: State = { initialized: true, + guest: false, user: undefined, token: "", expireTime: +new Date(), @@ -43,6 +46,7 @@ const authDataSlice = createSlice({ const { uid } = user; state.initialized = initialized; state.user = user; + // state.guest = user.create_by == "guest"; state.token = token; state.refreshToken = refresh_token; // 当前时间往后推expire时长 diff --git a/src/common/component/RequireAuth.tsx b/src/common/component/RequireAuth.tsx index e4afe57a..9285c5c6 100644 --- a/src/common/component/RequireAuth.tsx +++ b/src/common/component/RequireAuth.tsx @@ -1,6 +1,7 @@ -import React, { FC, ReactElement } from "react"; +import { FC, ReactElement, useEffect } from "react"; import { Navigate } from "react-router-dom"; -import { useGetInitializedQuery } from "../../app/services/auth"; +import { useGetInitializedQuery, useLazyGuestLoginQuery } from "../../app/services/auth"; +import { useGetLoginConfigQuery } from "../../app/services/server"; import { useAppSelector } from "../../app/store"; interface Props { @@ -9,11 +10,22 @@ interface Props { } const RequireAuth: FC = ({ children, redirectTo = "/login" }) => { - const { isLoading } = useGetInitializedQuery(); + const { data: loginConfig, isLoading: fetchingLoginConfig } = useGetLoginConfigQuery(); + const { isLoading: checkingInitial } = useGetInitializedQuery(); + const [guestLogin] = useLazyGuestLoginQuery(); const { token, initialized } = useAppSelector((store) => store.authData); - if (isLoading) return null; + useEffect(() => { + // 已初始化 , 没token,并且开启了guest,则guest自动登录 + if (initialized && !token && loginConfig?.guest) { + guestLogin(); + } + }, [token, initialized, loginConfig]); + // 初始化和login配置检查 + if (checkingInitial || fetchingLoginConfig) return null; // 未初始化 则先走setup 流程 if (!initialized) return ; + // 开启guest 并且没token 则等待guest登录结果 + if (loginConfig?.guest && !token) return null; return token ? children : ; }; diff --git a/src/routes/chat/GuestBlankPlaceholder.tsx b/src/routes/chat/GuestBlankPlaceholder.tsx new file mode 100644 index 00000000..5e6384f7 --- /dev/null +++ b/src/routes/chat/GuestBlankPlaceholder.tsx @@ -0,0 +1,55 @@ +// import React from "react"; +import { useDispatch } from "react-redux"; +import { useNavigate } from "react-router-dom"; +import styled from "styled-components"; +import { resetAuthData } from "../../app/slices/auth.data"; +import { useAppSelector } from "../../app/store"; +import Button from "../../common/component/styled/Button"; +import useLogout from "../../common/hook/useLogout"; +const Styled = styled.div` + display: flex; + align-items: center; + flex-direction: column; + .title { + font-style: normal; + font-weight: 700; + font-size: 30px; + line-height: 38px; + color: #344054; + } + .details { + display: flex; + flex-direction: column; + .desc { + margin: 12px 0; + font-weight: 400; + font-size: 14px; + line-height: 20px; + color: #98a2b3; + } + } +`; +// type Props = {}; + +const GuestBlankPlaceholder = () => { + const dispatch = useDispatch(); + const { clearLocalData } = useLogout(); + const navigateTo = useNavigate(); + const serverName = useAppSelector((store) => store.server.name); + const handleSignIn = () => { + dispatch(resetAuthData()); + clearLocalData(); + navigateTo("/login"); + }; + return ( + +

Welcome to {serverName} server

+
+ Please sign in to send a message + +
+
+ ); +}; + +export default GuestBlankPlaceholder; diff --git a/src/routes/guest/ChannelChat/index.tsx b/src/routes/chat/GuestChannelChatInfo/index.tsx similarity index 93% rename from src/routes/guest/ChannelChat/index.tsx rename to src/routes/chat/GuestChannelChatInfo/index.tsx index f6b14b20..511e3f44 100644 --- a/src/routes/guest/ChannelChat/index.tsx +++ b/src/routes/chat/GuestChannelChatInfo/index.tsx @@ -2,10 +2,10 @@ // import { NavLink } from "react-router-dom"; import useMessageFeed from "../../../common/hook/useMessageFeed"; import ChannelIcon from "../../../common/component/ChannelIcon"; -import Layout from "../../chat/Layout"; -import { renderMessageFragment } from "../../chat/utils"; +import Layout from "../Layout"; +import { renderMessageFragment } from "../utils"; import { StyledChannelChat, StyledHeader } from "./styled"; -import LoadMore from "../../chat/LoadMore"; +import LoadMore from "../LoadMore"; import { useAppSelector } from "../../../app/store"; type Props = { cid?: number; diff --git a/src/routes/guest/ChannelChat/styled.tsx b/src/routes/chat/GuestChannelChatInfo/styled.tsx similarity index 100% rename from src/routes/guest/ChannelChat/styled.tsx rename to src/routes/chat/GuestChannelChatInfo/styled.tsx diff --git a/src/routes/guest/SessionList/Session.tsx b/src/routes/chat/GuestSessionList/Session.tsx similarity index 96% rename from src/routes/guest/SessionList/Session.tsx rename to src/routes/chat/GuestSessionList/Session.tsx index 09c4375e..4499661d 100644 --- a/src/routes/guest/SessionList/Session.tsx +++ b/src/routes/chat/GuestSessionList/Session.tsx @@ -39,7 +39,7 @@ const Session: FC = ({ id, mid }) => { return (
  • - +
    diff --git a/src/routes/guest/SessionList/index.tsx b/src/routes/chat/GuestSessionList/index.tsx similarity index 97% rename from src/routes/guest/SessionList/index.tsx rename to src/routes/chat/GuestSessionList/index.tsx index 647b736b..f2d6c481 100644 --- a/src/routes/guest/SessionList/index.tsx +++ b/src/routes/chat/GuestSessionList/index.tsx @@ -5,10 +5,8 @@ import Session from "./Session"; import { useAppSelector } from "../../../app/store"; export interface ChatSession { key: string; - type: "user" | "channel"; id: number; mid?: number; - unread?: number; } type Props = {}; const SessionList: FC = () => { diff --git a/src/routes/guest/SessionList/styled.tsx b/src/routes/chat/GuestSessionList/styled.tsx similarity index 100% rename from src/routes/guest/SessionList/styled.tsx rename to src/routes/chat/GuestSessionList/styled.tsx diff --git a/src/routes/chat/Layout/styled.tsx b/src/routes/chat/Layout/styled.tsx index 1f740e9f..d833c6ae 100644 --- a/src/routes/chat/Layout/styled.tsx +++ b/src/routes/chat/Layout/styled.tsx @@ -141,8 +141,5 @@ const Styled = styled.article` } } } - &.readonly .main .chat { - height: calc(100vh - 62px - 18px); - } `; export default Styled; diff --git a/src/routes/chat/index.tsx b/src/routes/chat/index.tsx index 9292d0d8..86c79ce4 100644 --- a/src/routes/chat/index.tsx +++ b/src/routes/chat/index.tsx @@ -11,12 +11,16 @@ import UsersModal from "../../common/component/UsersModal"; import ChannelModal from "../../common/component/ChannelModal"; import SessionList from "./SessionList"; import { useAppSelector } from "../../app/store"; +import GuestBlankPlaceholder from "./GuestBlankPlaceholder"; +import GuestChannelChatInfo from "./GuestChannelChatInfo"; +import GuestSessionList from "./GuestSessionList"; export default function ChatPage() { const [channelModalVisible, setChannelModalVisible] = useState(false); const [usersModalVisible, setUsersModalVisible] = useState(false); const { channel_id = 0, user_id = 0 } = useParams(); - const { sessionUids } = useAppSelector((store) => { + const { sessionUids, isGuest } = useAppSelector((store) => { return { + isGuest: store.authData.guest, sessionUids: store.userMessage.ids }; }); @@ -43,14 +47,19 @@ export default function ChatPage() { )} {usersModalVisible && } - +
    - - + + {isGuest ? : }
    - {placeholderVisible && } - {channel_id !== 0 && } + {placeholderVisible && (isGuest ? : )} + {channel_id !== 0 && + (isGuest ? ( + + ) : ( + + ))} {user_id !== 0 && }
    diff --git a/src/routes/chat/styled.tsx b/src/routes/chat/styled.tsx index 3d46300a..4f5f346f 100644 --- a/src/routes/chat/styled.tsx +++ b/src/routes/chat/styled.tsx @@ -3,6 +3,9 @@ const StyledWrapper = styled.div` display: flex; height: 100%; padding: 8px 48px 10px 0; + &.guest { + padding-right: 0; + } > .left { background-color: #fff; position: relative; diff --git a/src/routes/guest/BlankPlaceholder.tsx b/src/routes/guest/BlankPlaceholder.tsx deleted file mode 100644 index ea2c6c86..00000000 --- a/src/routes/guest/BlankPlaceholder.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// import React from "react"; -import styled from "styled-components"; -const Styled = styled.div` - display: flex; - align-items: center; - font-size: 28px; - font-weight: bold; - color: #ccc; - padding: 50px; - height: calc(100vh - 24px); - text-transform: uppercase; - letter-spacing: 2px; -`; -// type Props = {}; - -const BlankPlaceholder = () => { - return Guest Mode; -}; - -export default BlankPlaceholder; diff --git a/src/routes/guest/OffTip.tsx b/src/routes/guest/OffTip.tsx deleted file mode 100644 index f1d4a73d..00000000 --- a/src/routes/guest/OffTip.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// import React from "react"; -import styled from "styled-components"; -const Styled = styled.div` - display: flex; - align-items: center; - font-size: 28px; - font-weight: bold; - color: orange; - padding: 50px; - height: calc(100vh - 24px); - text-transform: uppercase; - letter-spacing: 2px; -`; -// type Props = {}; - -const OffTip = () => { - return Guest Mode Off; -}; - -export default OffTip; diff --git a/src/routes/guest/index.tsx b/src/routes/guest/index.tsx deleted file mode 100644 index e1f2f4ea..00000000 --- a/src/routes/guest/index.tsx +++ /dev/null @@ -1,65 +0,0 @@ -// import React from 'react'; -import { useParams } from "react-router-dom"; -import StyledWrapper from "./styled"; -import Loading from "../../common/component/Loading"; -import Manifest from "../../common/component/Manifest"; -import Server from "../../common/component/Server"; -import BlankPlaceholder from "./BlankPlaceholder"; -import { useAppSelector } from "../../app/store"; -import usePreload from "../../common/hook/usePreload"; -import SessionList from "./SessionList"; -import ChannelChat from "./ChannelChat"; -// const routes = ["/setting", "/setting/channel/:cid"]; -export default function GuestHomePage() { - const { cid = 0 } = useParams(); - const placeholderVisible = cid == 0; - const { - ui: { ready } - } = useAppSelector((store) => { - return { - ui: store.ui - }; - }); - const { loading } = usePreload(); - if (loading || !ready) { - return ; - } - - return ( - <> - - -
    - - -
    -
    - {placeholderVisible && } - {cid !== 0 && } -
    -
    - - ); -} - -// import Server from "../../common/component/Server"; -// import ChannelChat from "./ChannelChat"; -// import SessionList from "./SessionList"; -// export default function ChatPage() { -// const { channel_id = 0 } = useParams(); -// const placeholderVisible = channel_id == 0 ; -// return ( -// <> -// -//
    -// -// -//
    -//
    -// {placeholderVisible && } -// {channel_id !== 0 && } -//
    -//
    -// -// ); -// } diff --git a/src/routes/guest/styled.tsx b/src/routes/guest/styled.tsx deleted file mode 100644 index 8ac5d64d..00000000 --- a/src/routes/guest/styled.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import styled from "styled-components"; -const StyledWrapper = styled.div` - display: flex; - height: 100%; - padding: 8px; - background: var(---navs-bg); - > .left { - background-color: #fff; - position: relative; - display: flex; - flex-direction: column; - min-width: 268px; - box-shadow: inset -1px 0px 0px rgba(0, 0, 0, 0.05); - height: 100%; - overflow: auto; - border-radius: 16px 0 0 16px; - .list { - margin: 12px 8px; - .title { - padding: 0 8px; - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 4px; - cursor: pointer; - > .txt { - user-select: none; - display: flex; - align-items: center; - gap: 5px; - font-weight: bold; - font-size: 12px; - line-height: 20px; - color: #78787c; - } - .icon { - transition: transform 0.5s ease; - transform-origin: center; - } - .add_icon { - width: 18px; - height: 18px; - } - } - > .nav { - display: flex; - flex-direction: column; - gap: 4px; - a { - text-decoration: none; - } - .session { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - padding: 4px 8px; - border-radius: 4px; - &:hover, - &.active { - background: rgba(116, 127, 141, 0.1); - } - - .avatar { - /* todo */ - } - .details { - display: flex; - flex-direction: column; - width: 100%; - .up { - display: flex; - justify-content: space-between; - align-items: center; - .name { - font-weight: 600; - font-size: 14px; - line-height: 20px; - color: #52525b; - max-width: 112px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - time { - white-space: nowrap; - font-weight: 500; - font-size: 12px; - line-height: 18px; - color: #78787c; - } - } - .down { - display: flex; - justify-content: space-between; - .msg { - min-height: 18px; - font-weight: normal; - font-size: 12px; - line-height: 18px; - color: #78787c; - white-space: nowrap; - overflow: hidden; - width: 140px; - text-overflow: ellipsis; - } - > .badge { - color: #fff; - height: 20px; - min-width: 20px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 10px; - background: #1fe1f9; - font-weight: 900; - font-size: 10px; - line-height: 10px; - &.dot { - min-width: unset; - width: 6px; - height: 6px; - padding: 0; - } - &.mute { - background: #bfbfbf; - } - } - } - } - } - /* drop files effect */ - .drop_over { - box-shadow: inset 0 0 0 2px #52edff; - } - } - &.collapse { - .title .icon { - transform: rotate(-90deg); - } - > .nav > .link:not(.active) { - display: none; - } - } - } - } - > .right { - border-radius: 0 16px 16px 0; - width: 100%; - &.placeholder { - background-color: #fff; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - } - } -`; - -export default StyledWrapper; diff --git a/src/routes/home/index.tsx b/src/routes/home/index.tsx index 0aa1fd64..f781347b 100644 --- a/src/routes/home/index.tsx +++ b/src/routes/home/index.tsx @@ -22,6 +22,7 @@ export default function HomePage() { const { pathname } = useLocation(); const { loginUid, + guest, ui: { ready, rememberedNavs: { chat: chatPath, user: userPath } @@ -29,7 +30,9 @@ export default function HomePage() { } = useAppSelector((store) => { return { ui: store.ui, - loginUid: store.authData.user?.uid + + loginUid: store.authData.user?.uid, + guest: store.authData.guest }; }); const { loading } = usePreload(); @@ -53,39 +56,41 @@ export default function HomePage() { <> - -
    - {loginUid && } - - {/*
    */} - -
    + + {!guest && ( +
    + {loginUid && } + + {/*
    */} + +
    + )}
    diff --git a/src/routes/home/styled.tsx b/src/routes/home/styled.tsx index 2f40d710..7baa107c 100644 --- a/src/routes/home/styled.tsx +++ b/src/routes/home/styled.tsx @@ -55,6 +55,9 @@ const StyledWrapper = styled.div` } } } + &.guest > .col.right { + margin: 0 8px; + } `; export default StyledWrapper; diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 4a833736..58748882 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -23,13 +23,9 @@ import RequireAuth from "../common/component/RequireAuth"; import RequireNoAuth from "../common/component/RequireNoAuth"; import Meta from "../common/component/Meta"; import HomePage from "./home"; -import GeustPage from "./guest"; -// import GuestChannelChatPage from "./guest/ChannelChat"; import ChatPage from "./chat"; import Loading from "../common/component/Loading"; import store, { useAppSelector } from "../app/store"; -import OffTip from "./guest/OffTip"; -import GuestOnly from "../common/component/GuestOnly"; let toastId: string; const PageRoutes = () => { const { @@ -93,34 +89,13 @@ const PageRoutes = () => { /> } /> } /> - {/* guest mode */} - - - - - } - /> - - - - } - /> - } /> - + }> - // } > @@ -203,15 +178,7 @@ const PageRoutes = () => { ); }; -// const local_key = "AUTH_DATA"; export default function ReduxRoutes() { - // const [authData, setAuthData] = useState( - // JSON.parse(localStorage.getItem(local_key)) - // ); - // const updateAuthData = (data) => { - // localStorage.setItem(local_key, JSON.stringify(data)); - // setAuthData(data); - // }; return (