fix(nav): collapse push-tap, tab and back-arrow navigations into the back stack via replace
This commit is contained in:
parent
c46684800c
commit
dce6be949a
10 changed files with 97 additions and 33 deletions
|
|
@ -10,8 +10,11 @@ export function BackRouteHandler({ children }: BackRouteHandlerProps) {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
const goBack = useCallback(() => {
|
const goBack = useCallback(() => {
|
||||||
|
// Back arrow walks up the route tree to the section root — semantically
|
||||||
|
// a "go up", not a "push parent". Replacing keeps the back-stack from
|
||||||
|
// growing when the user repeatedly taps back on nested screens.
|
||||||
const parent = getRouteSectionParent(location.pathname);
|
const parent = getRouteSectionParent(location.pathname);
|
||||||
if (parent) navigate(parent);
|
if (parent) navigate(parent, { replace: true });
|
||||||
}, [navigate, location.pathname]);
|
}, [navigate, location.pathname]);
|
||||||
|
|
||||||
return children(goBack);
|
return children(goBack);
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,11 @@ export function IncomingCallStrip({ call, room }: IncomingCallStripProps) {
|
||||||
const callKey = getIncomingCallKey(call.callId, call.roomId);
|
const callKey = getIncomingCallKey(call.callId, call.roomId);
|
||||||
|
|
||||||
const handleAnswer = () => {
|
const handleAnswer = () => {
|
||||||
navigate(getDirectRoomPath(getCanonicalAliasOrRoomId(mx, call.roomId)));
|
// Mirror the native CallStyle Answer path (usePushNotifications
|
||||||
|
// pushNotificationActionPerformed handler): in-app strip Answer is the
|
||||||
|
// same semantic action — switch to the call room — so it should not
|
||||||
|
// grow the back stack either.
|
||||||
|
navigate(getDirectRoomPath(getCanonicalAliasOrRoomId(mx, call.roomId)), { replace: true });
|
||||||
switchOrStartDmCall(call.roomId)
|
switchOrStartDmCall(call.roomId)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const evId = call.notifEvent.getId();
|
const evId = call.notifEvent.getId();
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ const EXIT_CONFIRM_WINDOW_MS = 2000;
|
||||||
/**
|
/**
|
||||||
* Maps the Android hardware back button to web-equivalent behavior, using
|
* Maps the Android hardware back button to web-equivalent behavior, using
|
||||||
* an app-level back stack instead of the WebView's native history. The
|
* an app-level back stack instead of the WebView's native history. The
|
||||||
* WebView's canGoBack includes redirects / replaces / tab-switch entries
|
* WebView's canGoBack counts redirects and `replace` calls as separate
|
||||||
* that inflate its depth, which is why we maintain our own stack keyed
|
* entries, so we cannot trust its depth — keep our own stack keyed off
|
||||||
* off react-router's useNavigationType.
|
* react-router's useNavigationType.
|
||||||
*
|
*
|
||||||
* 1. Overlay/modal open → dispatch Escape (closes folds Overlay via
|
* 1. Overlay/modal open → dispatch Escape (closes folds Overlay via
|
||||||
* focus-trap-react's escapeDeactivates).
|
* focus-trap-react's escapeDeactivates).
|
||||||
|
|
@ -29,6 +29,11 @@ const EXIT_CONFIRM_WINDOW_MS = 2000;
|
||||||
* second press within EXIT_CONFIRM_WINDOW_MS to exit; first press
|
* second press within EXIT_CONFIRM_WINDOW_MS to exit; first press
|
||||||
* shows a native Android toast. Any navigation between presses
|
* shows a native Android toast. Any navigation between presses
|
||||||
* resets the window so the prompt can't leak across screens.
|
* resets the window so the prompt can't leak across screens.
|
||||||
|
*
|
||||||
|
* Stack-bloat sources are addressed at the navigation site (push-tap and
|
||||||
|
* sidebar tabs use `replace`, useRoomNavigate auto-replaces same-pathname
|
||||||
|
* navs) — keeping this tracker free of dedup logic that would otherwise
|
||||||
|
* have to reconcile against phantom router-history entries.
|
||||||
*/
|
*/
|
||||||
export const useAndroidBackButton = (): void => {
|
export const useAndroidBackButton = (): void => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
|
||||||
|
|
@ -298,11 +298,15 @@ export function usePushNotificationsLifecycle(): void {
|
||||||
const detail = (ev as CustomEvent).detail as
|
const detail = (ev as CustomEvent).detail as
|
||||||
| { roomId?: string; isInvite?: boolean }
|
| { roomId?: string; isInvite?: boolean }
|
||||||
| undefined;
|
| undefined;
|
||||||
|
// Push-tap navigations are "switch to this", not "stack on top of where
|
||||||
|
// I was". Without replace, N notifications from the same chat plus tab
|
||||||
|
// hops accumulate as N+ entries in our app back-stack (see
|
||||||
|
// useAndroidBackButton) — user presses back many times to exit one chat.
|
||||||
if (detail?.isInvite) {
|
if (detail?.isInvite) {
|
||||||
navigate(getInboxInvitesPath());
|
navigate(getInboxInvitesPath(), { replace: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (detail?.roomId) navigateRoom(detail.roomId);
|
if (detail?.roomId) navigateRoom(detail.roomId, undefined, { replace: true });
|
||||||
};
|
};
|
||||||
const onSubChange = () => {
|
const onSubChange = () => {
|
||||||
if (isPushEnabled()) register().catch(noop);
|
if (isPushEnabled()) register().catch(noop);
|
||||||
|
|
@ -350,7 +354,7 @@ export function usePushNotificationsLifecycle(): void {
|
||||||
// route; `getHomeRoomPath` resolves to a Home-tab placeholder for IDs
|
// route; `getHomeRoomPath` resolves to a Home-tab placeholder for IDs
|
||||||
// it doesn't have in its left-rail, hence the DM path here.
|
// it doesn't have in its left-rail, hence the DM path here.
|
||||||
if (data.call_action === 'answer' && data.room_id) {
|
if (data.call_action === 'answer' && data.room_id) {
|
||||||
navigate(getDirectRoomPath(data.room_id));
|
navigate(getDirectRoomPath(data.room_id), { replace: true });
|
||||||
setPendingCallAction({
|
setPendingCallAction({
|
||||||
kind: 'answer',
|
kind: 'answer',
|
||||||
roomId: data.room_id,
|
roomId: data.room_id,
|
||||||
|
|
@ -381,11 +385,11 @@ export function usePushNotificationsLifecycle(): void {
|
||||||
// carry notif_event_id and this branch will route them to the DM
|
// carry notif_event_id and this branch will route them to the DM
|
||||||
// tab incorrectly — revisit together with the group-call pipeline.
|
// tab incorrectly — revisit together with the group-call pipeline.
|
||||||
if (data.room_id && data.notif_event_id) {
|
if (data.room_id && data.notif_event_id) {
|
||||||
navigate(getDirectRoomPath(data.room_id));
|
navigate(getDirectRoomPath(data.room_id), { replace: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.room_id) navigateRoom(data.room_id);
|
if (data.room_id) navigateRoom(data.room_id, undefined, { replace: true });
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useCallback } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
import { NavigateOptions, useNavigate } from 'react-router-dom';
|
import { NavigateOptions, useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { useAtomValue } from 'jotai';
|
import { useAtomValue } from 'jotai';
|
||||||
import { getCanonicalAliasOrRoomId } from '../utils/matrix';
|
import { getCanonicalAliasOrRoomId } from '../utils/matrix';
|
||||||
import {
|
import {
|
||||||
|
|
@ -18,18 +18,51 @@ import { useSetting } from '../state/hooks/settings';
|
||||||
|
|
||||||
export const useRoomNavigate = () => {
|
export const useRoomNavigate = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
const roomToParents = useAtomValue(roomToParentsAtom);
|
const roomToParents = useAtomValue(roomToParentsAtom);
|
||||||
const mDirects = useAtomValue(mDirectAtom);
|
const mDirects = useAtomValue(mDirectAtom);
|
||||||
const spaceSelectedId = useSelectedSpace();
|
const spaceSelectedId = useSelectedSpace();
|
||||||
const [developerTools] = useSetting(settingsAtom, 'developerTools');
|
const [developerTools] = useSetting(settingsAtom, 'developerTools');
|
||||||
|
|
||||||
|
// navigate(samePath) creates a fresh history entry in react-router-v6 even
|
||||||
|
// though the screen does not change — repeated taps on the same chat from
|
||||||
|
// search/inbox/notifications would inflate the back-stack tracked by
|
||||||
|
// useAndroidBackButton. Force replace when the target matches the current
|
||||||
|
// pathname so callers do not need to pass it everywhere.
|
||||||
|
//
|
||||||
|
// Pathname tracking has two sources:
|
||||||
|
// 1. useLocation → pathnameRef on every render, for consistency with the
|
||||||
|
// router after it commits a navigation we did not initiate.
|
||||||
|
// 2. Optimistic write inside safeNavigate, so two calls in the same tick
|
||||||
|
// (before React commits the first) collapse correctly: the second sees
|
||||||
|
// the target the first just navigated to and forces replace.
|
||||||
|
// Without (2), two simultaneous navigateRoom(samePath) calls — e.g. two
|
||||||
|
// notifications dispatched back-to-back, or a double-clicked list item —
|
||||||
|
// both compare against the pre-navigation pathname and both PUSH. Without
|
||||||
|
// (1), an external navigate() between our calls would leave pathnameRef
|
||||||
|
// ahead of the actual route.
|
||||||
|
//
|
||||||
|
// The callback identity stays stable (deps = [navigate] only) so consumers
|
||||||
|
// that wrap navigateRoom in their own useCallback do not capture a stale
|
||||||
|
// closure on every route change.
|
||||||
|
const pathnameRef = useRef(location.pathname);
|
||||||
|
pathnameRef.current = location.pathname;
|
||||||
|
const safeNavigate = useCallback(
|
||||||
|
(target: string, opts?: NavigateOptions) => {
|
||||||
|
const finalOpts = pathnameRef.current === target ? { ...opts, replace: true } : opts;
|
||||||
|
navigate(target, finalOpts);
|
||||||
|
pathnameRef.current = target;
|
||||||
|
},
|
||||||
|
[navigate]
|
||||||
|
);
|
||||||
|
|
||||||
const navigateSpace = useCallback(
|
const navigateSpace = useCallback(
|
||||||
(roomId: string) => {
|
(roomId: string) => {
|
||||||
const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, roomId);
|
const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, roomId);
|
||||||
navigate(getSpacePath(roomIdOrAlias));
|
safeNavigate(getSpacePath(roomIdOrAlias));
|
||||||
},
|
},
|
||||||
[mx, navigate]
|
[mx, safeNavigate]
|
||||||
);
|
);
|
||||||
|
|
||||||
const navigateRoom = useCallback(
|
const navigateRoom = useCallback(
|
||||||
|
|
@ -48,7 +81,7 @@ export const useRoomNavigate = () => {
|
||||||
|
|
||||||
const pSpaceIdOrAlias = getCanonicalAliasOrRoomId(mx, parentSpace);
|
const pSpaceIdOrAlias = getCanonicalAliasOrRoomId(mx, parentSpace);
|
||||||
|
|
||||||
navigate(
|
safeNavigate(
|
||||||
getSpaceRoomPath(pSpaceIdOrAlias, openSpaceTimeline ? roomId : roomIdOrAlias, eventId),
|
getSpaceRoomPath(pSpaceIdOrAlias, openSpaceTimeline ? roomId : roomIdOrAlias, eventId),
|
||||||
opts
|
opts
|
||||||
);
|
);
|
||||||
|
|
@ -56,13 +89,13 @@ export const useRoomNavigate = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDirects.has(roomId)) {
|
if (mDirects.has(roomId)) {
|
||||||
navigate(getDirectRoomPath(roomIdOrAlias, eventId), opts);
|
safeNavigate(getDirectRoomPath(roomIdOrAlias, eventId), opts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
navigate(getHomeRoomPath(roomIdOrAlias, eventId), opts);
|
safeNavigate(getHomeRoomPath(roomIdOrAlias, eventId), opts);
|
||||||
},
|
},
|
||||||
[mx, navigate, spaceSelectedId, roomToParents, mDirects, developerTools]
|
[mx, safeNavigate, spaceSelectedId, roomToParents, mDirects, developerTools]
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { mDirectAtom } from '../../../state/mDirectList';
|
||||||
import { allRoomsAtom } from '../../../state/room-list/roomList';
|
import { allRoomsAtom } from '../../../state/room-list/roomList';
|
||||||
import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
|
import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
|
||||||
import { getDirectPath, joinPathComponent } from '../../pathUtils';
|
import { getDirectPath, joinPathComponent } from '../../pathUtils';
|
||||||
|
import { isNativePlatform } from '../../../utils/capacitor';
|
||||||
import { useRoomsUnread } from '../../../state/hooks/unread';
|
import { useRoomsUnread } from '../../../state/hooks/unread';
|
||||||
import {
|
import {
|
||||||
SidebarAvatar,
|
SidebarAvatar,
|
||||||
|
|
@ -77,13 +78,14 @@ export function DirectTab() {
|
||||||
const directSelected = useDirectSelected();
|
const directSelected = useDirectSelected();
|
||||||
|
|
||||||
const handleDirectClick = () => {
|
const handleDirectClick = () => {
|
||||||
|
const navOpts = { replace: isNativePlatform() };
|
||||||
const activePath = navToActivePath.get('direct');
|
const activePath = navToActivePath.get('direct');
|
||||||
if (activePath && screenSize !== ScreenSize.Mobile) {
|
if (activePath && screenSize !== ScreenSize.Mobile) {
|
||||||
navigate(joinPathComponent(activePath));
|
navigate(joinPathComponent(activePath), navOpts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
navigate(getDirectPath());
|
navigate(getDirectPath(), navOpts);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleContextMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
const handleContextMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||||
import { getMxIdServer } from '../../../utils/matrix';
|
import { getMxIdServer } from '../../../utils/matrix';
|
||||||
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
|
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
|
||||||
import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
|
import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
|
||||||
|
import { isNativePlatform } from '../../../utils/capacitor';
|
||||||
|
|
||||||
export function ExploreTab() {
|
export function ExploreTab() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
@ -28,28 +29,29 @@ export function ExploreTab() {
|
||||||
const exploreSelected = useExploreSelected();
|
const exploreSelected = useExploreSelected();
|
||||||
|
|
||||||
const handleExploreClick = () => {
|
const handleExploreClick = () => {
|
||||||
|
const navOpts = { replace: isNativePlatform() };
|
||||||
if (screenSize === ScreenSize.Mobile) {
|
if (screenSize === ScreenSize.Mobile) {
|
||||||
navigate(getExplorePath());
|
navigate(getExplorePath(), navOpts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const activePath = navToActivePath.get('explore');
|
const activePath = navToActivePath.get('explore');
|
||||||
if (activePath) {
|
if (activePath) {
|
||||||
navigate(joinPathComponent(activePath));
|
navigate(joinPathComponent(activePath), navOpts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientConfig.featuredCommunities?.openAsDefault) {
|
if (clientConfig.featuredCommunities?.openAsDefault) {
|
||||||
navigate(getExploreFeaturedPath());
|
navigate(getExploreFeaturedPath(), navOpts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const userId = mx.getUserId();
|
const userId = mx.getUserId();
|
||||||
const userServer = userId ? getMxIdServer(userId) : undefined;
|
const userServer = userId ? getMxIdServer(userId) : undefined;
|
||||||
if (userServer) {
|
if (userServer) {
|
||||||
navigate(getExploreServerPath(userServer));
|
navigate(getExploreServerPath(userServer), navOpts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
navigate(getExplorePath());
|
navigate(getExplorePath(), navOpts);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import { roomToParentsAtom } from '../../../state/room/roomToParents';
|
||||||
import { allRoomsAtom } from '../../../state/room-list/roomList';
|
import { allRoomsAtom } from '../../../state/room-list/roomList';
|
||||||
import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
|
import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
|
||||||
import { getHomePath, joinPathComponent } from '../../pathUtils';
|
import { getHomePath, joinPathComponent } from '../../pathUtils';
|
||||||
|
import { isNativePlatform } from '../../../utils/capacitor';
|
||||||
import { useRoomsUnread } from '../../../state/hooks/unread';
|
import { useRoomsUnread } from '../../../state/hooks/unread';
|
||||||
import {
|
import {
|
||||||
SidebarAvatar,
|
SidebarAvatar,
|
||||||
|
|
@ -78,13 +79,19 @@ export function HomeTab() {
|
||||||
const [menuAnchor, setMenuAnchor] = useState<RectCords>();
|
const [menuAnchor, setMenuAnchor] = useState<RectCords>();
|
||||||
|
|
||||||
const handleHomeClick = () => {
|
const handleHomeClick = () => {
|
||||||
|
// On native, tab tap is "switch tab", not "stack on top" — replace keeps
|
||||||
|
// the app back-stack (see useAndroidBackButton) reflecting actual content
|
||||||
|
// navigation, not tab toggles. Same in Direct/Inbox/Explore/Space tabs.
|
||||||
|
// On web we keep PUSH so browser-back behaves the way desktop users
|
||||||
|
// expect: back undoes the tab switch.
|
||||||
|
const navOpts = { replace: isNativePlatform() };
|
||||||
const activePath = navToActivePath.get('home');
|
const activePath = navToActivePath.get('home');
|
||||||
if (activePath && screenSize !== ScreenSize.Mobile) {
|
if (activePath && screenSize !== ScreenSize.Mobile) {
|
||||||
navigate(joinPathComponent(activePath));
|
navigate(joinPathComponent(activePath), navOpts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
navigate(getHomePath());
|
navigate(getHomePath(), navOpts);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleContextMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
const handleContextMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import { useInboxSelected } from '../../../hooks/router/useInbox';
|
||||||
import { UnreadBadge } from '../../../components/unread-badge';
|
import { UnreadBadge } from '../../../components/unread-badge';
|
||||||
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
|
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
|
||||||
import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
|
import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
|
||||||
|
import { isNativePlatform } from '../../../utils/capacitor';
|
||||||
|
|
||||||
export function InboxTab() {
|
export function InboxTab() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
@ -31,18 +32,19 @@ export function InboxTab() {
|
||||||
const inviteCount = allInvites.length;
|
const inviteCount = allInvites.length;
|
||||||
|
|
||||||
const handleInboxClick = () => {
|
const handleInboxClick = () => {
|
||||||
|
const navOpts = { replace: isNativePlatform() };
|
||||||
if (screenSize === ScreenSize.Mobile) {
|
if (screenSize === ScreenSize.Mobile) {
|
||||||
navigate(getInboxPath());
|
navigate(getInboxPath(), navOpts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const activePath = navToActivePath.get('inbox');
|
const activePath = navToActivePath.get('inbox');
|
||||||
if (activePath) {
|
if (activePath) {
|
||||||
navigate(joinPathComponent(activePath));
|
navigate(joinPathComponent(activePath), navOpts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = inviteCount > 0 ? getInboxInvitesPath() : getInboxNotificationsPath();
|
const path = inviteCount > 0 ? getInboxInvitesPath() : getInboxNotificationsPath();
|
||||||
navigate(path);
|
navigate(path, navOpts);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ import { RoomUnreadProvider, RoomsUnreadProvider } from '../../../components/Roo
|
||||||
import { useSelectedSpace } from '../../../hooks/router/useSelectedSpace';
|
import { useSelectedSpace } from '../../../hooks/router/useSelectedSpace';
|
||||||
import { UnreadBadge } from '../../../components/unread-badge';
|
import { UnreadBadge } from '../../../components/unread-badge';
|
||||||
import { getCanonicalAliasOrRoomId, isRoomAlias } from '../../../utils/matrix';
|
import { getCanonicalAliasOrRoomId, isRoomAlias } from '../../../utils/matrix';
|
||||||
|
import { isNativePlatform } from '../../../utils/capacitor';
|
||||||
import { RoomAvatar } from '../../../components/room-avatar';
|
import { RoomAvatar } from '../../../components/room-avatar';
|
||||||
import { nameInitials, randomStr } from '../../../utils/common';
|
import { nameInitials, randomStr } from '../../../utils/common';
|
||||||
import {
|
import {
|
||||||
|
|
@ -760,18 +761,19 @@ export function SpaceTabs({ scrollRef }: SpaceTabsProps) {
|
||||||
if (!targetSpaceId) return;
|
if (!targetSpaceId) return;
|
||||||
|
|
||||||
const spacePath = getSpacePath(getCanonicalAliasOrRoomId(mx, targetSpaceId));
|
const spacePath = getSpacePath(getCanonicalAliasOrRoomId(mx, targetSpaceId));
|
||||||
|
const navOpts = { replace: isNativePlatform() };
|
||||||
if (screenSize === ScreenSize.Mobile) {
|
if (screenSize === ScreenSize.Mobile) {
|
||||||
navigate(spacePath);
|
navigate(spacePath, navOpts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const activePath = navToActivePath.get(targetSpaceId);
|
const activePath = navToActivePath.get(targetSpaceId);
|
||||||
if (activePath && activePath.pathname.startsWith(spacePath)) {
|
if (activePath && activePath.pathname.startsWith(spacePath)) {
|
||||||
navigate(joinPathComponent(activePath));
|
navigate(joinPathComponent(activePath), navOpts);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
navigate(getSpaceLobbyPath(getCanonicalAliasOrRoomId(mx, targetSpaceId)));
|
navigate(getSpaceLobbyPath(getCanonicalAliasOrRoomId(mx, targetSpaceId)), navOpts);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFolderToggle: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
const handleFolderToggle: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue