Author SHA1 Message Date
koka a660597791 fix(client): use single-pane mobile navigation 2026-08-10 09:12:28 +02:00
3 changed files with 81 additions and 9 deletions
+22 -2
View File
@@ -1,7 +1,7 @@
import { ReactNode } from 'react';
import { useMatch } from 'react-router-dom';
import { ScreenSize, useScreenSizeContext } from '../hooks/useScreenSize';
import { DIRECT_PATH, EXPLORE_PATH, HOME_PATH, INBOX_PATH, SPACE_PATH } from './paths';
import { BOTSU_PATH, DIRECT_PATH, EXPLORE_PATH, HOME_PATH, INBOX_PATH, SPACE_PATH } from './paths';
type MobileFriendlyClientNavProps = {
children: ReactNode;
@@ -9,6 +9,7 @@ type MobileFriendlyClientNavProps = {
export function MobileFriendlyClientNav({ children }: MobileFriendlyClientNavProps) {
const screenSize = useScreenSizeContext();
const homeMatch = useMatch({ path: HOME_PATH, caseSensitive: true, end: true });
const botsuMatch = useMatch({ path: BOTSU_PATH, caseSensitive: true, end: true });
const directMatch = useMatch({ path: DIRECT_PATH, caseSensitive: true, end: true });
const spaceMatch = useMatch({ path: SPACE_PATH, caseSensitive: true, end: true });
const exploreMatch = useMatch({ path: EXPLORE_PATH, caseSensitive: true, end: true });
@@ -16,7 +17,7 @@ export function MobileFriendlyClientNav({ children }: MobileFriendlyClientNavPro
if (
screenSize === ScreenSize.Mobile &&
!(homeMatch || directMatch || spaceMatch || exploreMatch || inboxMatch)
!(homeMatch || botsuMatch || directMatch || spaceMatch || exploreMatch || inboxMatch)
) {
return null;
}
@@ -42,3 +43,22 @@ export function MobileFriendlyPageNav({ path, children }: MobileFriendlyPageNavP
return children;
}
type MobileFriendlyPageContentProps = {
path: string;
children: ReactNode;
};
export function MobileFriendlyPageContent({ path, children }: MobileFriendlyPageContentProps) {
const screenSize = useScreenSizeContext();
const exactPath = useMatch({
path,
caseSensitive: true,
end: true,
});
if (screenSize === ScreenSize.Mobile && exactPath) {
return null;
}
return children;
}
+23 -7
View File
@@ -64,7 +64,11 @@ import { WelcomePage } from './client/WelcomePage';
import { SidebarNav } from './client/SidebarNav';
import { PageRoot } from '../components/page';
import { ScreenSize } from '../hooks/useScreenSize';
import { MobileFriendlyPageNav, MobileFriendlyClientNav } from './MobileFriendly';
import {
MobileFriendlyPageNav,
MobileFriendlyClientNav,
MobileFriendlyPageContent,
} from './MobileFriendly';
import { ClientInitStorageAtom } from './client/ClientInitStorageAtom';
import { ClientNonUIFeatures } from './client/ClientNonUIFeatures';
import { AuthRouteThemeManager, UnAuthRouteThemeManager } from './ThemeManager';
@@ -186,7 +190,9 @@ export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize)
</MobileFriendlyPageNav>
}
>
<BotsuFrame />
<MobileFriendlyPageContent path={BOTSU_PATH}>
<BotsuFrame />
</MobileFriendlyPageContent>
</PageRoot>
}
>
@@ -213,7 +219,9 @@ export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize)
</MobileFriendlyPageNav>
}
>
<Outlet />
<MobileFriendlyPageContent path={HOME_PATH}>
<Outlet />
</MobileFriendlyPageContent>
</PageRoot>
}
>
@@ -240,7 +248,9 @@ export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize)
</MobileFriendlyPageNav>
}
>
<Outlet />
<MobileFriendlyPageContent path={DIRECT_PATH}>
<Outlet />
</MobileFriendlyPageContent>
</PageRoot>
}
>
@@ -266,7 +276,9 @@ export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize)
</MobileFriendlyPageNav>
}
>
<Outlet />
<MobileFriendlyPageContent path={SPACE_PATH}>
<Outlet />
</MobileFriendlyPageContent>
</PageRoot>
</RouteSpaceProvider>
}
@@ -305,7 +317,9 @@ export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize)
</MobileFriendlyPageNav>
}
>
<Outlet />
<MobileFriendlyPageContent path={EXPLORE_PATH}>
<Outlet />
</MobileFriendlyPageContent>
</PageRoot>
}
>
@@ -330,7 +344,9 @@ export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize)
</MobileFriendlyPageNav>
}
>
<Outlet />
<MobileFriendlyPageContent path={INBOX_PATH}>
<Outlet />
</MobileFriendlyPageContent>
</PageRoot>
}
>
@@ -13,6 +13,7 @@ const shellTabUrl = new URL('./BotsuTab.tsx', import.meta.url);
const shellLogoUrl = new URL('./BotsuLogo.tsx', import.meta.url);
const presenceUrl = new URL('../presence/BotsuPresence.tsx', import.meta.url);
const routerUrl = new URL('../../app/pages/Router.tsx', import.meta.url);
const mobileFriendlyUrl = new URL('../../app/pages/MobileFriendly.tsx', import.meta.url);
const clientNonUiUrl = new URL('../../app/pages/client/ClientNonUIFeatures.tsx', import.meta.url);
const settingsUrl = new URL('../../app/state/settings.ts', import.meta.url);
const generalSettingsUrl = new URL('../../app/features/settings/general/General.tsx', import.meta.url);
@@ -383,7 +384,42 @@ test('BOTSU route restores the default left page panel', async () => {
assert.match(services, /label: 'Convertisseur'/);
});
test('mobile section roots render only the global sidebar and page panel', async () => {
const [router, mobileFriendly] = await Promise.all([
readFile(routerUrl, 'utf8'),
readFile(mobileFriendlyUrl, 'utf8'),
]);
assert.match(
router,
/import \{[\s\S]*MobileFriendlyPageNav,[\s\S]*MobileFriendlyClientNav,[\s\S]*MobileFriendlyPageContent,[\s\S]*\} from '\.\/MobileFriendly';/
);
assert.match(mobileFriendly, /export function MobileFriendlyPageContent/);
assert.match(mobileFriendly, /BOTSU_PATH/);
assert.match(
mobileFriendly,
/const botsuMatch = useMatch\(\{ path: BOTSU_PATH, caseSensitive: true, end: true \}\);/
);
assert.match(mobileFriendly, /homeMatch \|\| botsuMatch \|\| directMatch/);
assert.match(
mobileFriendly,
/if \(screenSize === ScreenSize\.Mobile && exactPath\) \{\s*return null;\s*\}/s
);
assert.match(
router,
/<MobileFriendlyPageContent path=\{BOTSU_PATH\}>\s*<BotsuFrame \/>\s*<\/MobileFriendlyPageContent>/s
);
for (const path of ['HOME_PATH', 'DIRECT_PATH', 'SPACE_PATH', 'EXPLORE_PATH', 'INBOX_PATH']) {
assert.match(
router,
new RegExp(
`<MobileFriendlyPageContent path=\\{${path}\\}>\\s*<Outlet \\/>\\s*<\\/MobileFriendlyPageContent>`,
's'
)
);
}
});
test('BOTSU exposes a Matrix Drawing Room type with a Paint canvas surface', async () => {
const [types, selector, createRoom, modal, roomUtils, room, header, drawingView] = await Promise.all([