Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/web/src/components/AppSidebarLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import LegacyThreadSidebar from "./LegacySidebar";
import ThreadSidebar from "./Sidebar";
import { SettingsSidebarNav } from "./settings/SettingsSidebarNav";
import { SidebarChromeHeader } from "./sidebar/SidebarChrome";
import { MainAppLocationTracker } from "./sidebar/mainAppLocation";
import { useSidebarStageBackdropVariant } from "./SidebarStageBackdrop";
import { useProjects } from "../state/entities";
import {
Expand Down Expand Up @@ -321,6 +322,7 @@ export function AppSidebarLayout({ children }: { children: ReactNode }) {
{children}
<SidebarControl />
<NavigationHistoryShortcuts />
<MainAppLocationTracker />
</SidebarProvider>
</PanelAnimationSuppressionProvider>
);
Expand Down
28 changes: 8 additions & 20 deletions apps/web/src/components/sidebar/SidebarChrome.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ArrowLeftIcon, ChartNoAxesColumnIcon, SettingsIcon } from "lucide-react";
import type { ReactNode } from "react";
import { memo, useCallback } from "react";
import { Link, useCanGoBack, useLocation, useNavigate } from "@tanstack/react-router";
import { Link, useLocation, useNavigate } from "@tanstack/react-router";

import { useEnvironmentIdentificationMode } from "../../hooks/useSettings";
import { cn } from "../../lib/utils";
Expand All @@ -24,6 +24,7 @@ import {
} from "../ui/sidebar";
import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
import { readPullRequestListPreferences } from "../pullRequest/pullRequestListPreferences";
import { isSidebarUtilityPage, useNavigateToMainApp } from "./mainAppLocation";
import { SidebarThreadUndoNotice } from "./SidebarThreadUndoNotice";
import { SidebarProviderUpdatePill } from "./SidebarProviderUpdatePill";
import { SidebarUpdateArchitectureWarning, SidebarUpdatePill } from "./SidebarUpdatePill";
Expand Down Expand Up @@ -127,19 +128,10 @@ function SidebarUtilityItem({

export const SidebarUtilityMenu = memo(function SidebarUtilityMenu() {
const navigate = useNavigate();
const canGoBack = useCanGoBack();
const navigateToMainApp = useNavigateToMainApp();
const { isMobile, setOpenMobile } = useSidebar();
const currentFooterPage = useLocation({
select: (location) =>
/^\/settings(?:\/|$)/.test(location.pathname)
? "settings"
: /^\/projects\/[^/]+\/?$/.test(location.pathname)
? "project-settings"
: location.pathname === "/usage"
? "usage"
: location.pathname === "/pull-requests"
? "pull-requests"
: null,
const isOnUtilityPage = useLocation({
select: (location) => isSidebarUtilityPage(location.pathname),
});
const { environments } = useEnvironments();
// The page reads every connected server, so one of them offering pull requests is enough for
Expand Down Expand Up @@ -173,16 +165,12 @@ export const SidebarUtilityMenu = memo(function SidebarUtilityMenu() {

const handleBackClick = useCallback(() => {
closeMobileSidebar();
if (canGoBack) {
window.history.back();
return;
}
void navigate({ to: "/" });
}, [canGoBack, closeMobileSidebar, navigate]);
void navigateToMainApp();
}, [closeMobileSidebar, navigateToMainApp]);

return (
<SidebarMenu className="flex-row items-center">
{currentFooterPage ? (
{isOnUtilityPage ? (
<SidebarMenuItem className="min-w-0 flex-1">
<SidebarMenuButton onClick={handleBackClick}>
<ArrowLeftIcon />
Expand Down
36 changes: 36 additions & 0 deletions apps/web/src/components/sidebar/mainAppLocation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useLocation, useNavigate } from "@tanstack/react-router";
import { useCallback, useEffect } from "react";

// Settings, Usage, and Pull Requests replace the sidebar utility row with a
// Back button. Everything else is the main app. Legacy `/projects/<key>` links
// redirect into settings, so they count too and are never remembered.
export function isSidebarUtilityPage(pathname: string) {
return (
pathname === "/settings" ||
pathname.startsWith("/settings/") ||
pathname.startsWith("/projects/") ||
pathname === "/usage" ||
pathname === "/pull-requests"
Comment thread
macroscopeapp[bot] marked this conversation as resolved.
);
}

let mainAppHref: string | null = null;

// Mount once in the app shell. Records the latest main app URL so Back can
// return there no matter how many utility pages were visited since.
export function MainAppLocationTracker() {
const href = useLocation({
select: (location) => (isSidebarUtilityPage(location.pathname) ? null : location.href),
});
useEffect(() => {
if (href !== null) mainAppHref = href;
}, [href]);
return null;
}

// Leaves a utility page for the last main app URL, or the thread list when
// the app was opened directly on a utility page.
export function useNavigateToMainApp() {
const navigate = useNavigate();
return useCallback(() => navigate({ href: mainAppHref ?? "/" }), [navigate]);
}
26 changes: 6 additions & 20 deletions apps/web/src/routes/settings.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import {
Outlet,
createFileRoute,
redirect,
useCanGoBack,
useLocation,
useNavigate,
} from "@tanstack/react-router";
import { useCallback, useEffect, useState, type ReactNode } from "react";
import { Outlet, createFileRoute, redirect, useLocation } from "@tanstack/react-router";
import { useEffect, useState, type ReactNode } from "react";
import { RotateCcwIcon } from "lucide-react";
import { Button } from "../components/ui/button";
import { useSettingsRestore } from "../components/settings/SettingsPanels";

import { SettingsBreadcrumb } from "../components/settings/SettingsBreadcrumb";
import { SidebarInset } from "../components/ui/sidebar";
import { useNavigateToMainApp } from "../components/sidebar/mainAppLocation";
import { WorkspacePageHeader } from "../components/WorkspacePageHeader";
import { isElectron } from "../env";
import {
Expand Down Expand Up @@ -117,17 +111,9 @@ function SettingsScopeBoundary({ pathname, children }: { pathname: string; child

function SettingsContentLayout() {
const location = useLocation();
const navigate = useNavigate();
const canGoBack = useCanGoBack();
const navigateToMainApp = useNavigateToMainApp();
const { search } = useSettingsScope();
const [restoreSignal, setRestoreSignal] = useState(0);
const navigateBackWithinApp = useCallback(() => {
if (canGoBack) {
window.history.back();
return;
}
void navigate({ to: "/" });
}, [canGoBack, navigate]);

useEffect(() => {
const onKeyDown = (event: KeyboardEvent) => {
Expand All @@ -140,15 +126,15 @@ function SettingsContentLayout() {
activeElement.blur();
}

navigateBackWithinApp();
void navigateToMainApp();
}
};

window.addEventListener("keydown", onKeyDown);
return () => {
window.removeEventListener("keydown", onKeyDown);
};
}, [navigateBackWithinApp]);
}, [navigateToMainApp]);

return (
<SidebarInset className="h-dvh min-h-0 overflow-hidden overscroll-y-none isolate">
Expand Down
Loading