Skip to content

Commit

Permalink
Nav: functions for nav/icon visibility #356
Browse files Browse the repository at this point in the history
  • Loading branch information
enricoros committed Jan 22, 2024
1 parent 1ed86b6 commit 695af02
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 66 deletions.
2 changes: 1 addition & 1 deletion src/apps/chat/components/message/ChatMessage.tsx
Expand Up @@ -48,7 +48,7 @@ import { parseBlocks } from './blocks';
// How long is the user collapsed message
const USER_COLLAPSED_LINES: number = 8;

// Enable the automatic menu on text selection
// Enable the menu on text selection
const ENABLE_SELECTION_RIGHT_CLICK_MENU: boolean = true;

// Enable the hover button to copy the whole message. The Copy button is also available in Blocks, or in the Avatar Menu.
Expand Down
70 changes: 47 additions & 23 deletions src/common/app.nav.ts
Expand Up @@ -13,13 +13,14 @@ import EventNoteIcon from '@mui/icons-material/EventNote';
import EventNoteOutlinedIcon from '@mui/icons-material/EventNoteOutlined';
import FormatPaintIcon from '@mui/icons-material/FormatPaint';
import FormatPaintOutlinedIcon from '@mui/icons-material/FormatPaintOutlined';
import ImageIcon from '@mui/icons-material/Image';
import ImageOutlinedIcon from '@mui/icons-material/ImageOutlined';
import IosShareIcon from '@mui/icons-material/IosShare';
import IosShareOutlinedIcon from '@mui/icons-material/IosShareOutlined';
import TextsmsIcon from '@mui/icons-material/Textsms';
import TextsmsOutlinedIcon from '@mui/icons-material/TextsmsOutlined';
import WorkspacesIcon from '@mui/icons-material/Workspaces';
import WorkspacesOutlinedIcon from '@mui/icons-material/WorkspacesOutlined';
// Automatic apps
import ImageOutlinedIcon from '@mui/icons-material/ImageOutlined';
import IosShareIcon from '@mui/icons-material/IosShare';
// Link icons
import GitHubIcon from '@mui/icons-material/GitHub';
import { DiscordIcon } from '~/common/components/icons/DiscordIcon';
Expand All @@ -29,11 +30,14 @@ import SettingsIcon from '@mui/icons-material/Settings';


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


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

const SPECIAL_DIVIDER = '__DIVIDER__';


// Nav items

Expand All @@ -47,12 +51,14 @@ interface ItemBase {
export interface NavItemApp extends ItemBase {
type: 'app',
route: string,
landingRoute?: string, // specify a different route than the nextjs page router route, to land to
barTitle?: string, // set to override the name as the bar title (unless custom bar content is used)
hideIcon?: boolean
| (() => boolean), // set to true to hide the icon, unless this is the active app
hideBar?: boolean, // set to true to hide the page bar
hideDrawer?: boolean, // set to true to hide the drawer
hideNav?: boolean, // set to hide the Nav bar (note: must have a way to navigate back)
hideOnMobile?: boolean, // set to true to hide on mobile
automatic?: boolean, // only accessible by the machine
hideNav?: boolean
| (() => boolean), // set to hide the Nav bar (note: must have a way to navigate back)
fullWidth?: boolean, // set to true to override the user preference
_delete?: boolean, // delete from the UI
}
Expand Down Expand Up @@ -131,6 +137,13 @@ export const navItems: {
route: '/workspace',
_delete: true,
},
// <-- divider here -->
{
name: SPECIAL_DIVIDER,
type: 'app',
route: SPECIAL_DIVIDER,
icon: () => null,
},
{
name: 'Personas',
icon: Diversity2OutlinedIcon,
Expand All @@ -139,33 +152,32 @@ export const navItems: {
route: '/personas',
hideBar: true,
},
{
name: 'News',
icon: EventNoteOutlinedIcon,
iconActive: EventNoteIcon,
type: 'app',
route: '/news',
hideBar: true,
hideDrawer: true,
},

// non-user-selectable ('automatic') Apps
{
name: 'Media Library',
icon: ImageOutlinedIcon,
iconActive: ImageIcon,
type: 'app',
route: '/media',
automatic: true,
hideNav: true,
_delete: true,
},
{
name: 'Shared Chat',
icon: IosShareIcon,
icon: IosShareOutlinedIcon,
iconActive: IosShareIcon,
type: 'app',
route: '/link/chat/[chatLinkId]',
automatic: true,
hideNav: true,
landingRoute: '/link/chat/list',
hideIcon: hasNoChatLinkItems,
hideNav: hasNoChatLinkItems,
},
{
name: 'News',
icon: EventNoteOutlinedIcon,
iconActive: EventNoteIcon,
type: 'app',
route: '/news',
hideBar: true,
hideDrawer: true,
},
],

Expand Down Expand Up @@ -210,4 +222,16 @@ export const navItems: {
};

// apply UI filtering right away - do it here, once, and for all
navItems.apps = navItems.apps.filter(app => !app._delete || SHOW_ALL_APPS);
navItems.apps = navItems.apps.filter(app => !app._delete || SHOW_ALL_APPS);

export function checkDivider(app?: NavItemApp) {
return app?.name === SPECIAL_DIVIDER;
}

export function checkVisibileIcon(app: NavItemApp, currentApp?: NavItemApp) {
return app === currentApp ? true : typeof app.hideIcon === 'function' ? !app.hideIcon() : !app.hideIcon;
}

export function checkVisibleNav(app?: NavItemApp) {
return !app ? false : typeof app.hideNav === 'function' ? !app.hideNav() : !app.hideNav;
}
4 changes: 2 additions & 2 deletions src/common/layout/optima/DesktopDrawer.tsx
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';

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

import type { NavItemApp } from '~/common/app.nav';
import { checkVisibleNav, NavItemApp } from '~/common/app.nav';
import { themeZIndexDesktopDrawer } from '~/common/app.theme';

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

// [special case] remove in the future
const shallOpenNavForSharedLink = !props.currentApp?.hideDrawer && !!props.currentApp?.hideNav;
const shallOpenNavForSharedLink = !props.currentApp?.hideDrawer && checkVisibleNav(props.currentApp);
React.useEffect(() => {
if (shallOpenNavForSharedLink)
openDrawer();
Expand Down
46 changes: 24 additions & 22 deletions src/common/layout/optima/DesktopNav.tsx
Expand Up @@ -7,7 +7,7 @@ import MenuIcon from '@mui/icons-material/Menu';
import { useModelsStore } from '~/modules/llms/store-llms';

import { AgiSquircleIcon } from '~/common/components/icons/AgiSquircleIcon';
import { NavItemApp, navItems } from '~/common/app.nav';
import { checkDivider, checkVisibileIcon, NavItemApp, navItems } from '~/common/app.nav';
import { themeZIndexDesktopNav } from '~/common/app.theme';

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

// App items
const navAppItems = React.useMemo(() => {
return navItems.apps.filter(app => !app.hideNav).map(item => {
const isActive = item === props.currentApp;
const isDrawerable = isActive && !item.hideDrawer;
const isPaneOpen = isDrawerable && isDrawerOpen;
const isNotForUser = !!item.automatic && !isActive;
return (
<Tooltip disableInteractive enterDelay={600} key={'n-m-' + item.route.slice(1)} title={item.name}>
<DesktopNavIcon
disabled={isNotForUser}
variant={isActive ? 'solid' : undefined}
onClick={isDrawerable ? toggleDrawer : () => Router.push(item.route)}
className={`${navItemClasses.typeApp} ${isActive ? navItemClasses.active : ''} ${isPaneOpen ? navItemClasses.paneOpen : ''}`}
>
{/*{(isActive && item.iconActive) ? <item.iconActive /> : <item.icon />}*/}
<item.icon />
</DesktopNavIcon>
</Tooltip>
);
})
// (disabled) add this code after the map to add a divider
.toSpliced(-2, 0, <Divider sx={{ my: 1, width: '50%', mx: 'auto' }} />);
return navItems.apps
.filter(_app => checkVisibileIcon(_app, props.currentApp))
.map((app, appIdx) => {
const isActive = app === props.currentApp;
const isDrawerable = isActive && !app.hideDrawer;
const isPaneOpen = isDrawerable && isDrawerOpen;

if (checkDivider(app))
return <Divider key={'div-' + appIdx} sx={{ my: 1, width: '50%', mx: 'auto' }} />;

return (
<Tooltip key={'n-m-' + app.route.slice(1)} disableInteractive enterDelay={600} title={app.name}>
<DesktopNavIcon
variant={isActive ? 'solid' : undefined}
onClick={isDrawerable ? toggleDrawer : () => Router.push(app.landingRoute || app.route)}
className={`${navItemClasses.typeApp} ${isActive ? navItemClasses.active : ''} ${isPaneOpen ? navItemClasses.paneOpen : ''}`}
>
{/*{(isActive && app.iconActive) ? <app.iconActive /> : <app.icon />}*/}
<app.icon />
</DesktopNavIcon>
</Tooltip>
);
});
}, [props.currentApp, isDrawerOpen, toggleDrawer]);


Expand Down
37 changes: 24 additions & 13 deletions src/common/layout/optima/MobileNavListItem.tsx
@@ -1,8 +1,8 @@
import * as React from 'react';
import Router from 'next/router';
import { Button, ButtonGroup, ListItem } from '@mui/joy';
import { Button, ButtonGroup, ListItem, Tooltip } from '@mui/joy';

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

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

Expand All @@ -27,17 +27,28 @@ export function MobileNavListItem(props: { currentApp?: NavItemApp }) {
gap: 1,
}}
>
{navItems.apps.filter(app => !app.hideOnMobile && !app.hideNav).map(app =>
<Button
key={'app-' + app.name}
disabled={!!app.automatic}
size='sm'
variant={app == props.currentApp ? 'soft' : 'solid'}
onClick={() => Router.push(app.route)}
>
{app == props.currentApp ? app.name : <app.icon />}
</Button>,
)}
{navItems.apps
.filter(app => checkVisibileIcon(app))
.map((app, appIdx) => {
const isActive = app === props.currentApp;

if (checkDivider(app))
return null;
// return <Divider orientation='vertical' key={'div-' + appIdx} />;

return (
<Tooltip key={'n-m-' + app.route.slice(1)} disableInteractive enterDelay={600} title={app.name}>
<Button
key={'app-' + app.name}
size='sm'
variant={isActive ? 'soft' : 'solid'}
onClick={() => Router.push(app.landingRoute || app.route)}
>
{isActive ? app.name : <app.icon />}
</Button>
</Tooltip>
);
})}
</ButtonGroup>

{/* Group 2: Social Links */}
Expand Down
4 changes: 2 additions & 2 deletions src/common/layout/optima/OptimaLayout.tsx
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';
import { useRouter } from 'next/router';
import { PanelGroup } from 'react-resizable-panels';

import { navItems } from '~/common/app.nav';
import { checkVisibleNav, navItems } from '~/common/app.nav';
import { useIsMobile } from '~/common/components/useMatchMedia';

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

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

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

<DesktopDrawer currentApp={currentApp} />

Expand Down
6 changes: 3 additions & 3 deletions src/common/layout/optima/PageBar.tsx
Expand Up @@ -9,7 +9,7 @@ import MenuIcon from '@mui/icons-material/Menu';
import MoreVertIcon from '@mui/icons-material/MoreVert';
import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined';

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

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

{(!appDrawerContent || props.currentApp?.hideNav) ? (
{(!appDrawerContent || !checkVisibleNav(props.currentApp)) ? (
<IconButton component={Link} href={ROUTE_INDEX} noLinkStyle>
<ArrowBackIcon />
</IconButton>
Expand Down
1 change: 1 addition & 0 deletions src/modules/trade/chatlink/store-chatlink.ts
Expand Up @@ -64,3 +64,4 @@ export const useLinkStorageOwnerId = () =>
export const rememberChatLinkItem = useTradeStore.getState().rememberChatLinkItem;
export const forgetChatLinkItem = useTradeStore.getState().forgetChatLinkItem;
export const updateChatLinkDeletionKey = useTradeStore.getState().updateChatLinkDeletionKey;
export const hasNoChatLinkItems = () => !useTradeStore.getState().chatLinkItems.length;

0 comments on commit 695af02

Please sign in to comment.