Skip to content

Commit 695af02

Browse files
committed
Nav: functions for nav/icon visibility #356
1 parent 1ed86b6 commit 695af02

File tree

8 files changed

+104
-66
lines changed

8 files changed

+104
-66
lines changed

src/apps/chat/components/message/ChatMessage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ import { parseBlocks } from './blocks';
4848
// How long is the user collapsed message
4949
const USER_COLLAPSED_LINES: number = 8;
5050

51-
// Enable the automatic menu on text selection
51+
// Enable the menu on text selection
5252
const ENABLE_SELECTION_RIGHT_CLICK_MENU: boolean = true;
5353

5454
// Enable the hover button to copy the whole message. The Copy button is also available in Blocks, or in the Avatar Menu.

src/common/app.nav.ts

+47-23
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ import EventNoteIcon from '@mui/icons-material/EventNote';
1313
import EventNoteOutlinedIcon from '@mui/icons-material/EventNoteOutlined';
1414
import FormatPaintIcon from '@mui/icons-material/FormatPaint';
1515
import FormatPaintOutlinedIcon from '@mui/icons-material/FormatPaintOutlined';
16+
import ImageIcon from '@mui/icons-material/Image';
17+
import ImageOutlinedIcon from '@mui/icons-material/ImageOutlined';
18+
import IosShareIcon from '@mui/icons-material/IosShare';
19+
import IosShareOutlinedIcon from '@mui/icons-material/IosShareOutlined';
1620
import TextsmsIcon from '@mui/icons-material/Textsms';
1721
import TextsmsOutlinedIcon from '@mui/icons-material/TextsmsOutlined';
1822
import WorkspacesIcon from '@mui/icons-material/Workspaces';
1923
import WorkspacesOutlinedIcon from '@mui/icons-material/WorkspacesOutlined';
20-
// Automatic apps
21-
import ImageOutlinedIcon from '@mui/icons-material/ImageOutlined';
22-
import IosShareIcon from '@mui/icons-material/IosShare';
2324
// Link icons
2425
import GitHubIcon from '@mui/icons-material/GitHub';
2526
import { DiscordIcon } from '~/common/components/icons/DiscordIcon';
@@ -29,11 +30,14 @@ import SettingsIcon from '@mui/icons-material/Settings';
2930

3031

3132
import { Brand } from '~/common/app.config';
33+
import { hasNoChatLinkItems } from '~/modules/trade/chatlink/store-chatlink';
3234

3335

3436
// enable to show all items, for layout development
3537
const SHOW_ALL_APPS = false;
3638

39+
const SPECIAL_DIVIDER = '__DIVIDER__';
40+
3741

3842
// Nav items
3943

@@ -47,12 +51,14 @@ interface ItemBase {
4751
export interface NavItemApp extends ItemBase {
4852
type: 'app',
4953
route: string,
54+
landingRoute?: string, // specify a different route than the nextjs page router route, to land to
5055
barTitle?: string, // set to override the name as the bar title (unless custom bar content is used)
56+
hideIcon?: boolean
57+
| (() => boolean), // set to true to hide the icon, unless this is the active app
5158
hideBar?: boolean, // set to true to hide the page bar
5259
hideDrawer?: boolean, // set to true to hide the drawer
53-
hideNav?: boolean, // set to hide the Nav bar (note: must have a way to navigate back)
54-
hideOnMobile?: boolean, // set to true to hide on mobile
55-
automatic?: boolean, // only accessible by the machine
60+
hideNav?: boolean
61+
| (() => boolean), // set to hide the Nav bar (note: must have a way to navigate back)
5662
fullWidth?: boolean, // set to true to override the user preference
5763
_delete?: boolean, // delete from the UI
5864
}
@@ -131,6 +137,13 @@ export const navItems: {
131137
route: '/workspace',
132138
_delete: true,
133139
},
140+
// <-- divider here -->
141+
{
142+
name: SPECIAL_DIVIDER,
143+
type: 'app',
144+
route: SPECIAL_DIVIDER,
145+
icon: () => null,
146+
},
134147
{
135148
name: 'Personas',
136149
icon: Diversity2OutlinedIcon,
@@ -139,33 +152,32 @@ export const navItems: {
139152
route: '/personas',
140153
hideBar: true,
141154
},
142-
{
143-
name: 'News',
144-
icon: EventNoteOutlinedIcon,
145-
iconActive: EventNoteIcon,
146-
type: 'app',
147-
route: '/news',
148-
hideBar: true,
149-
hideDrawer: true,
150-
},
151-
152-
// non-user-selectable ('automatic') Apps
153155
{
154156
name: 'Media Library',
155157
icon: ImageOutlinedIcon,
158+
iconActive: ImageIcon,
156159
type: 'app',
157160
route: '/media',
158-
automatic: true,
159-
hideNav: true,
160161
_delete: true,
161162
},
162163
{
163164
name: 'Shared Chat',
164-
icon: IosShareIcon,
165+
icon: IosShareOutlinedIcon,
166+
iconActive: IosShareIcon,
165167
type: 'app',
166168
route: '/link/chat/[chatLinkId]',
167-
automatic: true,
168-
hideNav: true,
169+
landingRoute: '/link/chat/list',
170+
hideIcon: hasNoChatLinkItems,
171+
hideNav: hasNoChatLinkItems,
172+
},
173+
{
174+
name: 'News',
175+
icon: EventNoteOutlinedIcon,
176+
iconActive: EventNoteIcon,
177+
type: 'app',
178+
route: '/news',
179+
hideBar: true,
180+
hideDrawer: true,
169181
},
170182
],
171183

@@ -210,4 +222,16 @@ export const navItems: {
210222
};
211223

212224
// apply UI filtering right away - do it here, once, and for all
213-
navItems.apps = navItems.apps.filter(app => !app._delete || SHOW_ALL_APPS);
225+
navItems.apps = navItems.apps.filter(app => !app._delete || SHOW_ALL_APPS);
226+
227+
export function checkDivider(app?: NavItemApp) {
228+
return app?.name === SPECIAL_DIVIDER;
229+
}
230+
231+
export function checkVisibileIcon(app: NavItemApp, currentApp?: NavItemApp) {
232+
return app === currentApp ? true : typeof app.hideIcon === 'function' ? !app.hideIcon() : !app.hideIcon;
233+
}
234+
235+
export function checkVisibleNav(app?: NavItemApp) {
236+
return !app ? false : typeof app.hideNav === 'function' ? !app.hideNav() : !app.hideNav;
237+
}

src/common/layout/optima/DesktopDrawer.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as React from 'react';
22

33
import { Box, Sheet, styled } from '@mui/joy';
44

5-
import type { NavItemApp } from '~/common/app.nav';
5+
import { checkVisibleNav, NavItemApp } from '~/common/app.nav';
66
import { themeZIndexDesktopDrawer } from '~/common/app.theme';
77

88
import { useOptimaDrawers } from './useOptimaDrawers';
@@ -81,7 +81,7 @@ export function DesktopDrawer(props: { currentApp?: NavItemApp }) {
8181
}, [closeDrawer, currentAppUsesDrawer]);
8282

8383
// [special case] remove in the future
84-
const shallOpenNavForSharedLink = !props.currentApp?.hideDrawer && !!props.currentApp?.hideNav;
84+
const shallOpenNavForSharedLink = !props.currentApp?.hideDrawer && checkVisibleNav(props.currentApp);
8585
React.useEffect(() => {
8686
if (shallOpenNavForSharedLink)
8787
openDrawer();

src/common/layout/optima/DesktopNav.tsx

+24-22
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import MenuIcon from '@mui/icons-material/Menu';
77
import { useModelsStore } from '~/modules/llms/store-llms';
88

99
import { AgiSquircleIcon } from '~/common/components/icons/AgiSquircleIcon';
10-
import { NavItemApp, navItems } from '~/common/app.nav';
10+
import { checkDivider, checkVisibileIcon, NavItemApp, navItems } from '~/common/app.nav';
1111
import { themeZIndexDesktopNav } from '~/common/app.theme';
1212

1313
import { BringTheLove } from './components/BringTheLove';
@@ -47,27 +47,29 @@ export function DesktopNav(props: { currentApp?: NavItemApp }) {
4747

4848
// App items
4949
const navAppItems = React.useMemo(() => {
50-
return navItems.apps.filter(app => !app.hideNav).map(item => {
51-
const isActive = item === props.currentApp;
52-
const isDrawerable = isActive && !item.hideDrawer;
53-
const isPaneOpen = isDrawerable && isDrawerOpen;
54-
const isNotForUser = !!item.automatic && !isActive;
55-
return (
56-
<Tooltip disableInteractive enterDelay={600} key={'n-m-' + item.route.slice(1)} title={item.name}>
57-
<DesktopNavIcon
58-
disabled={isNotForUser}
59-
variant={isActive ? 'solid' : undefined}
60-
onClick={isDrawerable ? toggleDrawer : () => Router.push(item.route)}
61-
className={`${navItemClasses.typeApp} ${isActive ? navItemClasses.active : ''} ${isPaneOpen ? navItemClasses.paneOpen : ''}`}
62-
>
63-
{/*{(isActive && item.iconActive) ? <item.iconActive /> : <item.icon />}*/}
64-
<item.icon />
65-
</DesktopNavIcon>
66-
</Tooltip>
67-
);
68-
})
69-
// (disabled) add this code after the map to add a divider
70-
.toSpliced(-2, 0, <Divider sx={{ my: 1, width: '50%', mx: 'auto' }} />);
50+
return navItems.apps
51+
.filter(_app => checkVisibileIcon(_app, props.currentApp))
52+
.map((app, appIdx) => {
53+
const isActive = app === props.currentApp;
54+
const isDrawerable = isActive && !app.hideDrawer;
55+
const isPaneOpen = isDrawerable && isDrawerOpen;
56+
57+
if (checkDivider(app))
58+
return <Divider key={'div-' + appIdx} sx={{ my: 1, width: '50%', mx: 'auto' }} />;
59+
60+
return (
61+
<Tooltip key={'n-m-' + app.route.slice(1)} disableInteractive enterDelay={600} title={app.name}>
62+
<DesktopNavIcon
63+
variant={isActive ? 'solid' : undefined}
64+
onClick={isDrawerable ? toggleDrawer : () => Router.push(app.landingRoute || app.route)}
65+
className={`${navItemClasses.typeApp} ${isActive ? navItemClasses.active : ''} ${isPaneOpen ? navItemClasses.paneOpen : ''}`}
66+
>
67+
{/*{(isActive && app.iconActive) ? <app.iconActive /> : <app.icon />}*/}
68+
<app.icon />
69+
</DesktopNavIcon>
70+
</Tooltip>
71+
);
72+
});
7173
}, [props.currentApp, isDrawerOpen, toggleDrawer]);
7274

7375

src/common/layout/optima/MobileNavListItem.tsx

+24-13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import * as React from 'react';
22
import Router from 'next/router';
3-
import { Button, ButtonGroup, ListItem } from '@mui/joy';
3+
import { Button, ButtonGroup, ListItem, Tooltip } from '@mui/joy';
44

5-
import { NavItemApp, navItems } from '~/common/app.nav';
5+
import { checkDivider, checkVisibileIcon, NavItemApp, navItems } from '~/common/app.nav';
66

77
import { BringTheLove } from './components/BringTheLove';
88

@@ -27,17 +27,28 @@ export function MobileNavListItem(props: { currentApp?: NavItemApp }) {
2727
gap: 1,
2828
}}
2929
>
30-
{navItems.apps.filter(app => !app.hideOnMobile && !app.hideNav).map(app =>
31-
<Button
32-
key={'app-' + app.name}
33-
disabled={!!app.automatic}
34-
size='sm'
35-
variant={app == props.currentApp ? 'soft' : 'solid'}
36-
onClick={() => Router.push(app.route)}
37-
>
38-
{app == props.currentApp ? app.name : <app.icon />}
39-
</Button>,
40-
)}
30+
{navItems.apps
31+
.filter(app => checkVisibileIcon(app))
32+
.map((app, appIdx) => {
33+
const isActive = app === props.currentApp;
34+
35+
if (checkDivider(app))
36+
return null;
37+
// return <Divider orientation='vertical' key={'div-' + appIdx} />;
38+
39+
return (
40+
<Tooltip key={'n-m-' + app.route.slice(1)} disableInteractive enterDelay={600} title={app.name}>
41+
<Button
42+
key={'app-' + app.name}
43+
size='sm'
44+
variant={isActive ? 'soft' : 'solid'}
45+
onClick={() => Router.push(app.landingRoute || app.route)}
46+
>
47+
{isActive ? app.name : <app.icon />}
48+
</Button>
49+
</Tooltip>
50+
);
51+
})}
4152
</ButtonGroup>
4253

4354
{/* Group 2: Social Links */}

src/common/layout/optima/OptimaLayout.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as React from 'react';
22
import { useRouter } from 'next/router';
33
import { PanelGroup } from 'react-resizable-panels';
44

5-
import { navItems } from '~/common/app.nav';
5+
import { checkVisibleNav, navItems } from '~/common/app.nav';
66
import { useIsMobile } from '~/common/components/useMatchMedia';
77

88
import { DesktopDrawer } from './DesktopDrawer';
@@ -50,7 +50,7 @@ export function OptimaLayout(props: { suspendAutoModelsSetup?: boolean, children
5050

5151
<PanelGroup direction='horizontal' id='desktop-layout'>
5252

53-
{!currentApp?.hideNav && <DesktopNav currentApp={currentApp} />}
53+
{checkVisibleNav(currentApp) && <DesktopNav currentApp={currentApp} />}
5454

5555
<DesktopDrawer currentApp={currentApp} />
5656

src/common/layout/optima/PageBar.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import MenuIcon from '@mui/icons-material/Menu';
99
import MoreVertIcon from '@mui/icons-material/MoreVert';
1010
import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined';
1111

12-
import type { NavItemApp } from '~/common/app.nav';
12+
import { checkVisibleNav, NavItemApp } from '~/common/app.nav';
1313
import { AgiSquircleIcon } from '~/common/components/icons/AgiSquircleIcon';
1414
import { Brand } from '~/common/app.config';
1515
import { CloseableMenu } from '~/common/components/CloseableMenu';
@@ -125,10 +125,10 @@ export function PageBar(props: { currentApp?: NavItemApp, isMobile?: boolean, sx
125125
<InvertedBar direction='horizontal' sx={props.sx}>
126126

127127
{/* [Mobile] Drawer button */}
128-
{(!!props.isMobile || props.currentApp?.hideNav) && (
128+
{(!!props.isMobile || !checkVisibleNav(props.currentApp)) && (
129129
<InvertedBarCornerItem>
130130

131-
{(!appDrawerContent || props.currentApp?.hideNav) ? (
131+
{(!appDrawerContent || !checkVisibleNav(props.currentApp)) ? (
132132
<IconButton component={Link} href={ROUTE_INDEX} noLinkStyle>
133133
<ArrowBackIcon />
134134
</IconButton>

src/modules/trade/chatlink/store-chatlink.ts

+1
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,4 @@ export const useLinkStorageOwnerId = () =>
6464
export const rememberChatLinkItem = useTradeStore.getState().rememberChatLinkItem;
6565
export const forgetChatLinkItem = useTradeStore.getState().forgetChatLinkItem;
6666
export const updateChatLinkDeletionKey = useTradeStore.getState().updateChatLinkDeletionKey;
67+
export const hasNoChatLinkItems = () => !useTradeStore.getState().chatLinkItems.length;

0 commit comments

Comments
 (0)