Skip to content

Commit

Permalink
♻️ feat: refactor to url state (lobehub#157)
Browse files Browse the repository at this point in the history
* ✨ feat: support hash state

* ♻️ refactor: refactor page to query mode

* 🚚 refactor: move SessionList

* ♻️ refactor: refactor the chat session url

* ♻️ refactor: refactor the router state

* 🐛 fix: fix topic problem
  • Loading branch information
arvinxx authored Sep 8, 2023
1 parent b0146f3 commit 2efac2b
Show file tree
Hide file tree
Showing 37 changed files with 332 additions and 214 deletions.
3 changes: 3 additions & 0 deletions src/const/url.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pkg from '../../package.json';
import { INBOX_SESSION_ID } from './session';

export const GITHUB = pkg.homepage;
export const CHANGELOG = `${pkg.homepage}/blob/master/CHANGELOG.md`;
Expand All @@ -8,3 +9,5 @@ export const DISCORD = 'https://discord.gg/AYFPHvv2jT';

export const PLUGINS_INDEX_URL =
process.env.PLUGINS_INDEX_URL ?? 'https://chat-plugins.lobehub.com';

export const SESSION_CHAT_URL = (id: string = INBOX_SESSION_ID) => `/chat#session=${id}`;
4 changes: 3 additions & 1 deletion src/features/MobileTabBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { memo, useMemo } from 'react';
import { useTranslation } from 'react-i18next';

import { useGlobalStore } from '@/store/global';
import { useSessionStore } from '@/store/session';

const useStyles = createStyles(({ css, token }) => ({
active: css`
Expand All @@ -20,6 +21,7 @@ export default memo<{ className?: string }>(({ className }) => {
const [tab, setTab] = useGlobalStore((s) => [s.sidebarKey, s.switchSideBar]);
const { t } = useTranslation('common');
const { styles } = useStyles();
const switchSession = useSessionStore((s) => s.switchSession);
const items: MobileTabBarProps['items'] = useMemo(
() => [
{
Expand All @@ -28,7 +30,7 @@ export default memo<{ className?: string }>(({ className }) => {
),
key: 'chat',
onClick: () => {
Router.push('/chat');
switchSession();
},
title: t('tab.chat'),
},
Expand Down
7 changes: 4 additions & 3 deletions src/features/SideBar/TopActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { memo } from 'react';
import { useTranslation } from 'react-i18next';

import { GlobalStore } from '@/store/global';
import { useSessionStore } from '@/store/session';

export interface TopActionProps {
setTab: GlobalStore['switchSideBar'];
Expand All @@ -13,7 +14,7 @@ export interface TopActionProps {

const TopActions = memo<TopActionProps>(({ tab, setTab }) => {
const { t } = useTranslation('common');

const switchBackToChat = useSessionStore((s) => s.switchBackToChat);
return (
<>
<ActionIcon
Expand All @@ -22,7 +23,7 @@ const TopActions = memo<TopActionProps>(({ tab, setTab }) => {
onClick={() => {
// 如果已经在 chat 路径下了,那么就不用再跳转了
if (Router.asPath.startsWith('/chat')) return;
Router.push('/chat');
switchBackToChat();
setTab('chat');
}}
size="large"
Expand All @@ -31,7 +32,7 @@ const TopActions = memo<TopActionProps>(({ tab, setTab }) => {
<ActionIcon
active={tab === 'market'}
icon={Sticker}
onClick={() => setTab('market')}
// onClick={() => setTab('market')}
size="large"
title={t('tab.market')}
/>
Expand Down
34 changes: 0 additions & 34 deletions src/pages/chat/[id]/layout.tsx

This file was deleted.

31 changes: 0 additions & 31 deletions src/pages/chat/[id]/mobile.tsx

This file was deleted.

14 changes: 6 additions & 8 deletions src/pages/chat/features/Header/Mobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,19 @@ import Router from 'next/router';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';

import { INBOX_SESSION_ID } from '@/const/session';
import { useGlobalStore } from '@/store/global';
import { useSessionStore } from '@/store/session';
import { agentSelectors } from '@/store/session/selectors';
import { agentSelectors, sessionSelectors } from '@/store/session/selectors';

const MobileHeader = memo<{ settings?: boolean }>(({ settings = true }) => {
const MobileHeader = memo(() => {
const { t } = useTranslation('common');

const [id, title, model] = useSessionStore((s) => [
s.activeId,
const [isInbox, title, model] = useSessionStore((s) => [
sessionSelectors.isInboxSession(s),
agentSelectors.currentAgentTitle(s),
agentSelectors.currentAgentModel(s),
]);

const isInbox = id === INBOX_SESSION_ID;
const [toggleConfig] = useGlobalStore((s) => [s.toggleMobileTopic]);

const displayTitle = isInbox ? t('inbox.title') : title;
Expand All @@ -30,11 +28,11 @@ const MobileHeader = memo<{ settings?: boolean }>(({ settings = true }) => {
right={
<>
<ActionIcon icon={LayoutList} onClick={() => toggleConfig()} />
{settings && (
{!isInbox && (
<ActionIcon
icon={Settings}
onClick={() => {
Router.push(`/chat/${id}/setting`);
Router.push({ hash: location.hash, pathname: `/chat/setting` });
}}
/>
)}
Expand Down
31 changes: 15 additions & 16 deletions src/pages/chat/features/Header/PC.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,30 @@ import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';

import { INBOX_SESSION_ID } from '@/const/session';
import { useGlobalStore } from '@/store/global';
import { useSessionChatInit, useSessionStore } from '@/store/session';
import { agentSelectors } from '@/store/session/selectors';
import { agentSelectors, sessionSelectors } from '@/store/session/selectors';

import PluginTag from './PluginTag';
import ShareButton from './ShareButton';

const Header = memo<{ settings?: boolean }>(({ settings = true }) => {
const Header = memo(() => {
const init = useSessionChatInit();

const { t } = useTranslation('common');

const [id, title, description, avatar, backgroundColor, model, plugins] = useSessionStore((s) => [
s.activeId,

agentSelectors.currentAgentTitle(s),
agentSelectors.currentAgentDescription(s),
agentSelectors.currentAgentAvatar(s),
agentSelectors.currentAgentBackgroundColor(s),
agentSelectors.currentAgentModel(s),
agentSelectors.currentAgentPlugins(s),
]);
const [isInbox, title, description, avatar, backgroundColor, model, plugins] = useSessionStore(
(s) => [
sessionSelectors.isInboxSession(s),
agentSelectors.currentAgentTitle(s),
agentSelectors.currentAgentDescription(s),
agentSelectors.currentAgentAvatar(s),
agentSelectors.currentAgentBackgroundColor(s),
agentSelectors.currentAgentModel(s),
agentSelectors.currentAgentPlugins(s),
],
);

const isInbox = id === INBOX_SESSION_ID;
const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
s.preference.showChatSideBar,
s.toggleChatSideBar,
Expand Down Expand Up @@ -77,11 +76,11 @@ const Header = memo<{ settings?: boolean }>(({ settings = true }) => {
size={{ fontSize: 24 }}
title={t('roleAndArchive')}
/>
{settings && (
{!isInbox && (
<ActionIcon
icon={Settings}
onClick={() => {
Router.push(`/chat/${id}/setting`);
Router.push({ hash: location.hash, pathname: `/chat/setting` });
}}
size={{ fontSize: 24 }}
title={t('header.session', { ns: 'setting' })}
Expand Down
6 changes: 3 additions & 3 deletions src/pages/chat/features/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { memo } from 'react';
import Mobile from './Mobile';
import PC from './PC';

const Header = memo<{ settings?: boolean }>((props) => {
const Header = memo(() => {
const { mobile } = useResponsive();

if (mobile) return <Mobile {...props} />;
if (mobile) return <Mobile />;

return <PC {...props} />;
return <PC />;
});

export default Header;
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next';

import { DEFAULT_INBOX_AVATAR } from '@/const/meta';
import { INBOX_SESSION_ID } from '@/const/session';
import { SESSION_CHAT_URL } from '@/const/url';
import { useSessionStore } from '@/store/session';

const { Item } = List;
Expand All @@ -14,7 +15,7 @@ const Inbox = memo(() => {
const ref = useRef(null);
const isHovering = useHover(ref);
const { t } = useTranslation('common');
const [activeId] = useSessionStore((s) => [s.activeId]);
const [activeId, switchSession] = useSessionStore((s) => [s.activeId, s.switchSession]);

const avatarRender = useMemo(
() => (
Expand All @@ -29,7 +30,13 @@ const Inbox = memo(() => {
);

return (
<Link href={'/chat'}>
<Link
href={SESSION_CHAT_URL()}
onClick={(e) => {
e.preventDefault();
switchSession(INBOX_SESSION_ID);
}}
>
<Item
active={activeId === INBOX_SESSION_ID}
avatar={avatarRender}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import isEqual from 'fast-deep-equal';
import Link from 'next/link';
import { memo } from 'react';

import { SESSION_CHAT_URL } from '@/const/url';
import { useSessionHydrated, useSessionStore } from '@/store/session';
import { sessionSelectors } from '@/store/session/selectors';

Expand All @@ -11,14 +12,22 @@ import SkeletonList from './SkeletonList';

const SessionList = memo(() => {
const list = useSessionStore(sessionSelectors.sessionList, isEqual);
const activeSession = useSessionStore((s) => s.activeSession);

const isInit = useSessionHydrated();

return !isInit ? (
<SkeletonList />
) : list.length > 0 ? (
list.map(({ id }) => (
<Link href={`/chat/${id}`} key={id}>
<Link
href={SESSION_CHAT_URL(id)}
key={id}
onClick={(e) => {
e.preventDefault();
activeSession(id);
}}
>
<SessionItem id={id} />
</Link>
))
Expand Down
File renamed without changes.
8 changes: 6 additions & 2 deletions src/pages/chat/features/Sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { Flexbox } from 'react-layout-kit';
import SafeSpacing from '@/components/SafeSpacing';
import { CHAT_SIDEBAR_WIDTH } from '@/const/layoutTokens';
import { useGlobalStore } from '@/store/global';
import { useSessionStore } from '@/store/session';
import { sessionSelectors } from '@/store/session/slices/session/selectors';

import Mobile from './Mobile';
import SystemRole from './SystemRole';
Expand Down Expand Up @@ -37,13 +39,15 @@ interface SideBarProps {
mobile?: boolean;
systemRole?: boolean;
}
const SideBar = memo<SideBarProps>(({ systemRole = true, mobile }) => {
const SideBar = memo<SideBarProps>(({ mobile }) => {
const { styles } = useStyles(mobile);
const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
s.preference.showChatSideBar,
s.toggleChatSideBar,
]);

const isInbox = useSessionStore(sessionSelectors.isInboxSession);

const { t } = useTranslation('common');

const topic = (
Expand Down Expand Up @@ -79,7 +83,7 @@ const SideBar = memo<SideBarProps>(({ systemRole = true, mobile }) => {
style={{ flex: 'none', height: '100%', minWidth: CHAT_SIDEBAR_WIDTH }}
>
<SafeSpacing />
{systemRole && <SystemRole mobile={mobile} />}
{!isInbox && <SystemRole mobile={mobile} />}

{topic}
</DraggablePanelContainer>
Expand Down
20 changes: 9 additions & 11 deletions src/pages/chat/index.page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { useResponsive } from 'antd-style';
import Head from 'next/head';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';

import { INBOX_SESSION_ID } from '@/const/session';
import { useOnFinishHydrationSession, useSessionStore } from '@/store/session';
import { useSessionStore } from '@/store/session';
import { agentSelectors } from '@/store/session/selectors';
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';

import Conversation from './features/Conversation';
Expand All @@ -15,13 +14,12 @@ import Layout from './layout';
import Mobile from './mobile';

const Chat = memo(() => {
const { t } = useTranslation('common');
const { mobile } = useResponsive();
const pageTitle = genSiteHeadTitle(t('inbox.title'));

useOnFinishHydrationSession(() => {
useSessionStore.getState().activeSession(INBOX_SESSION_ID);
});
const [avatar, title] = useSessionStore((s) => [
agentSelectors.currentAgentAvatar(s),
agentSelectors.currentAgentTitle(s),
]);
const pageTitle = genSiteHeadTitle([avatar, title].filter(Boolean).join(' '));

return (
<>
Expand All @@ -32,10 +30,10 @@ const Chat = memo(() => {
<Mobile />
) : (
<Layout>
<Header settings={false} />
<Header />
<Flexbox flex={1} height={'calc(100vh - 64px)'} horizontal>
<Conversation />
<SideBar systemRole={false} />
<SideBar />
</Flexbox>
</Layout>
)}
Expand Down
Loading

0 comments on commit 2efac2b

Please sign in to comment.