fix: rework compact nav and centralized back routing
Use master-detail layout on skinny windows so server and channel lists share one screen, with back returning to the space list instead of redirect loops. Add useBackRoute for title-bar and page-header back buttons with view transitions.
This commit is contained in:
@@ -1,90 +1,11 @@
|
||||
import { ReactNode, useCallback } from 'react';
|
||||
import { matchPath, useLocation, useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
decodeRouteParam,
|
||||
getDirectPath,
|
||||
getExplorePath,
|
||||
getHomePath,
|
||||
getInboxPath,
|
||||
getSpacePath,
|
||||
} from '../pages/pathUtils';
|
||||
import { DIRECT_PATH, EXPLORE_PATH, HOME_PATH, INBOX_PATH, SPACE_PATH } from '../pages/paths';
|
||||
import { ReactNode } from 'react';
|
||||
import { useBackRoute } from '../hooks/useBackRoute';
|
||||
|
||||
type BackRouteHandlerProps = {
|
||||
children: (onBack: () => void) => ReactNode;
|
||||
};
|
||||
export function BackRouteHandler({ children }: BackRouteHandlerProps) {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
const goBack = useCallback(() => {
|
||||
if (
|
||||
matchPath(
|
||||
{
|
||||
path: HOME_PATH,
|
||||
caseSensitive: true,
|
||||
end: false,
|
||||
},
|
||||
location.pathname
|
||||
)
|
||||
) {
|
||||
navigate(getHomePath());
|
||||
return;
|
||||
}
|
||||
if (
|
||||
matchPath(
|
||||
{
|
||||
path: DIRECT_PATH,
|
||||
caseSensitive: true,
|
||||
end: false,
|
||||
},
|
||||
location.pathname
|
||||
)
|
||||
) {
|
||||
navigate(getDirectPath());
|
||||
return;
|
||||
}
|
||||
const spaceMatch = matchPath(
|
||||
{
|
||||
path: SPACE_PATH,
|
||||
caseSensitive: true,
|
||||
end: false,
|
||||
},
|
||||
location.pathname
|
||||
);
|
||||
if (spaceMatch?.params.spaceIdOrAlias) {
|
||||
const spaceIdOrAlias = decodeRouteParam(spaceMatch.params.spaceIdOrAlias);
|
||||
if (spaceIdOrAlias) {
|
||||
navigate(getSpacePath(spaceIdOrAlias));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (
|
||||
matchPath(
|
||||
{
|
||||
path: EXPLORE_PATH,
|
||||
caseSensitive: true,
|
||||
end: false,
|
||||
},
|
||||
location.pathname
|
||||
)
|
||||
) {
|
||||
navigate(getExplorePath());
|
||||
return;
|
||||
}
|
||||
if (
|
||||
matchPath(
|
||||
{
|
||||
path: INBOX_PATH,
|
||||
caseSensitive: true,
|
||||
end: false,
|
||||
},
|
||||
location.pathname
|
||||
)
|
||||
) {
|
||||
navigate(getInboxPath());
|
||||
}
|
||||
}, [navigate, location]);
|
||||
const { goBack } = useBackRoute();
|
||||
|
||||
return children(goBack);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ContainerColor } from '../../styles/ContainerColor.css';
|
||||
import * as css from './style.css';
|
||||
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
|
||||
import { SidebarDockedCallPanel } from '../../features/call/SidebarDockedCallPanel';
|
||||
import { useShowCompactMasterView } from '../../hooks/useCompactNav';
|
||||
|
||||
type PageRootProps = {
|
||||
nav: ReactNode;
|
||||
@@ -13,6 +14,7 @@ type PageRootProps = {
|
||||
|
||||
export function PageRoot({ nav, children }: PageRootProps) {
|
||||
const screenSize = useScreenSizeContext();
|
||||
const showCompactMaster = useShowCompactMasterView();
|
||||
|
||||
return (
|
||||
<Box grow="Yes" className={ContainerColor({ variant: 'Background' })}>
|
||||
@@ -20,7 +22,7 @@ export function PageRoot({ nav, children }: PageRootProps) {
|
||||
{screenSize !== ScreenSize.Mobile && (
|
||||
<Line variant="Background" size="300" direction="Vertical" />
|
||||
)}
|
||||
{children}
|
||||
{!showCompactMaster && children}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -76,6 +76,11 @@ export const TitleBarDragRegion = style({
|
||||
color: color.Surface.OnContainer,
|
||||
});
|
||||
|
||||
export const TitleBarBackButton = style({
|
||||
WebkitAppRegion: 'no-drag',
|
||||
flexShrink: 0,
|
||||
});
|
||||
|
||||
export const SyncStatusBadge = style({
|
||||
position: 'absolute',
|
||||
left: '50%',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { ReactNode, useMemo, useEffect, useState, useCallback, useRef } from 'react';
|
||||
import { Box, Text } from 'folds';
|
||||
import { Box, Text, IconButton } from 'folds';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { MatrixClient, RoomEvent, ClientEvent, MatrixEvent, Room, IPushRules, SyncState } from 'matrix-js-sdk';
|
||||
import { useAtomValue } from 'jotai';
|
||||
@@ -18,6 +18,8 @@ import { AccountDataEvent } from '../../../types/matrix/accountData';
|
||||
import { getNotificationMode, NotificationMode } from '../../hooks/useNotificationMode';
|
||||
import { isRoomId } from '../../utils/matrix';
|
||||
import { useSyncState } from '../../hooks/useSyncState';
|
||||
import { useBackRoute } from '../../hooks/useBackRoute';
|
||||
import { Icon, Icons } from '../icons';
|
||||
|
||||
type NewMessageNotification = {
|
||||
id: string;
|
||||
@@ -42,6 +44,7 @@ export function TitleBar({ mx, children }: TitleBarProps) {
|
||||
const navigate = useNavigate();
|
||||
const roomToParents = useAtomValue(roomToParentsAtom);
|
||||
const mDirects = useAtomValue(mDirectAtom);
|
||||
const { showInTitleBar, goBack } = useBackRoute(mx);
|
||||
|
||||
// Sync status state
|
||||
const [syncStateData, setSyncStateData] = useState<{
|
||||
@@ -652,6 +655,20 @@ export function TitleBar({ mx, children }: TitleBarProps) {
|
||||
grow="Yes"
|
||||
onMouseDown={handleDragStart}
|
||||
>
|
||||
{showInTitleBar && (
|
||||
<IconButton
|
||||
className={css.TitleBarBackButton}
|
||||
size="300"
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
radii="300"
|
||||
onClick={goBack}
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
aria-label="Back"
|
||||
>
|
||||
<Icon src={Icons.ArrowLeft} size="200" />
|
||||
</IconButton>
|
||||
)}
|
||||
<Text size="T200" truncate style={{ color: 'inherit' }}>
|
||||
<span style={{ fontWeight: 700 }}>Paarrot</span>{titleParts.suffix}
|
||||
</Text>
|
||||
|
||||
Reference in New Issue
Block a user