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
23 changes: 13 additions & 10 deletions apps/mobile/src/components/CompactBrandTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ import { NATIVE_LIQUID_GLASS_SUPPORTED } from "../native/native-glass";
const IOS_NATIVE_LEADING_TITLE_OFFSET = -6;
const IPAD_NATIVE_LEADING_TITLE_OFFSET = 7;

/**
* Horizontal correction applied to content rendered in the brand title slot,
* shared with the connection-status swap so both align identically.
*/
export function brandTitleOffset(nativeLeadingItem: boolean): number {
if (Platform.OS !== "ios") return 0;
if (nativeLeadingItem) {
return Platform.isPad ? IPAD_NATIVE_LEADING_TITLE_OFFSET : IOS_NATIVE_LEADING_TITLE_OFFSET;
}
return Platform.isPad ? IPAD_HOME_TITLE_OFFSET : 0;
}

/**
* Compact brand lockup sized for native navigation bars.
*/
Expand All @@ -28,16 +40,7 @@ export function CompactBrandTitle(
const mutedColor = useThemeColor("--color-foreground-muted");
const subtleColor = useThemeColor("--color-subtle");
const stageLabel = resolveMobileStageLabel(Constants.expoConfig?.extra?.appVariant);
const titleOffset =
Platform.OS !== "ios"
? 0
: props.nativeLeadingItem
? Platform.isPad
? IPAD_NATIVE_LEADING_TITLE_OFFSET
: IOS_NATIVE_LEADING_TITLE_OFFSET
: Platform.isPad
? IPAD_HOME_TITLE_OFFSET
: 0;
const titleOffset = brandTitleOffset(props.nativeLeadingItem === true);

return (
<View
Expand Down
35 changes: 23 additions & 12 deletions apps/mobile/src/features/home/HomeHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
NATIVE_MAIL_SEARCH_TOOLBAR_SUPPORTED,
} from "../layout/native-mail-search-toolbar";
import type { HomeProjectSortOrder } from "./homeThreadList";
import { WorkspaceConnectionTitle } from "./WorkspaceConnectionTitle";
import {
buildHomeListFilterMenu,
type HomeListFilterMenuEnvironment,
Expand All @@ -47,6 +48,7 @@ export function HomeHeader(props: {
readonly onProjectChange: (projectKey: string | null) => void;
readonly onProjectSortOrderChange: (sortOrder: HomeProjectSortOrder) => void;
readonly onThreadSortOrderChange: (sortOrder: SidebarThreadSortOrder) => void;
readonly onOpenEnvironments: () => void;
readonly onOpenSettings: () => void;
readonly onStartNewTask: () => void;
}) {
Expand Down Expand Up @@ -207,18 +209,27 @@ function AndroidHomeHeader(props: HomeHeaderProps) {
>
<View className="w-full max-w-[720px] self-center gap-3">
<View className="flex-row items-center gap-2.5">
<View className="flex-1 flex-row items-center gap-2">
{/* Mirrors the desktop SidebarBrand: T3 mark + muted "Code". */}
<T3Wordmark color={iconColor} height={15} />
<RNText className="-ml-0.5 text-[21px] font-t3-medium tracking-[-0.5px] text-foreground-muted">
Code
</RNText>
<View className="rounded-full bg-subtle px-2 py-0.75">
<RNText className="text-[11px] font-t3-bold tracking-[1.1px] text-foreground-muted uppercase">
{stageLabel}
</RNText>
</View>
</View>
{/* Brand slot doubles as the connection status surface: while an
environment reconnects, the lockup fades to a status label in
place (no layout shift in the list below). */}
<WorkspaceConnectionTitle
grow
onPress={props.onOpenEnvironments}
brand={
<View className="flex-row items-center gap-2">
{/* Mirrors the desktop SidebarBrand: T3 mark + muted "Code". */}
<T3Wordmark color={iconColor} height={15} />
<RNText className="-ml-0.5 text-[21px] font-t3-medium tracking-[-0.5px] text-foreground-muted">
Code
</RNText>
<View className="rounded-full bg-subtle px-2 py-0.75">
<RNText className="text-[11px] font-t3-bold tracking-[1.1px] text-foreground-muted uppercase">
{stageLabel}
</RNText>
</View>
</View>
}
/>

<ControlPillMenu
actions={menuActions}
Expand Down
20 changes: 14 additions & 6 deletions apps/mobile/src/features/home/HomeRouteScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import * as Order from "effect/Order";
import { useNavigation } from "@react-navigation/native";
import { useEffect, useMemo, useState } from "react";

import { getCompactBrandHeaderOptions } from "../../components/CompactBrandTitle";
import { NativeHeaderToolbar, NativeStackScreenOptions } from "../../native/StackHeader";
import { useProjects, useThreadShells } from "../../state/entities";
import { usePendingNewTasks } from "../../state/use-pending-new-tasks";
Expand All @@ -20,6 +19,7 @@ import { useHomeListOptions } from "./home-list-options";
import { buildHomeProjectScopes } from "./homeThreadList";
import { usePendingTaskListActions } from "./usePendingTaskListActions";
import { useThreadListActions } from "./useThreadListActions";
import { getConnectionAwareBrandHeaderOptions } from "./WorkspaceConnectionTitle";

/* ─── Route screen ───────────────────────────────────────────────────── */

Expand Down Expand Up @@ -126,8 +126,16 @@ export function HomeRouteScreen() {
onStartNewTask={() => navigation.navigate("NewTaskSheet", { screen: "NewTask" })}
>
<>
{/* Restore the compact title after the split branch blanks the detail header. */}
<NativeStackScreenOptions options={getCompactBrandHeaderOptions()} />
{/* Restore the compact title after the split branch blanks the detail
header. The brand slot doubles as the connection status surface:
while an environment reconnects, the lockup fades to a status label
in place (no layout shift in the list below). */}
<NativeStackScreenOptions
options={getConnectionAwareBrandHeaderOptions({
onOpenEnvironments: () =>
navigation.navigate("SettingsSheet", { screen: "SettingsEnvironments" }),
})}
/>
<HomeHeader
environments={environments}
projects={projectFilterOptions}
Expand All @@ -138,6 +146,9 @@ export function HomeRouteScreen() {
threadSortOrder={listOptions.threadSortOrder}
onEnvironmentChange={setSelectedEnvironmentId}
onProjectChange={setSelectedProjectKey}
onOpenEnvironments={() =>
navigation.navigate("SettingsSheet", { screen: "SettingsEnvironments" })
}
onOpenSettings={() => navigation.navigate("SettingsSheet", { screen: "Settings" })}
onProjectSortOrderChange={setProjectSortOrder}
onSearchQueryChange={setSearchQuery}
Expand All @@ -161,9 +172,6 @@ export function HomeRouteScreen() {
onUnpinThread={unpinThread}
onEnvironmentChange={setSelectedEnvironmentId}
onProjectChange={setSelectedProjectKey}
onOpenEnvironments={() =>
navigation.navigate("SettingsSheet", { screen: "SettingsEnvironments" })
}
onOpenSettings={() => navigation.navigate("SettingsSheet", { screen: "Settings" })}
onProjectSortOrderChange={setProjectSortOrder}
onSearchQueryChange={setSearchQuery}
Expand Down
46 changes: 5 additions & 41 deletions apps/mobile/src/features/home/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ import {
type HomeProjectSortOrder,
} from "./homeThreadList";
import { SwipeableScrollGateProvider, useSwipeableScrollGate } from "./thread-swipe-actions";
import { WorkspaceConnectionStatus } from "./WorkspaceConnectionStatus";
import { shouldShowWorkspaceConnectionStatus } from "./workspace-connection-status";

/* ─── Types ──────────────────────────────────────────────────────────── */

Expand All @@ -97,7 +95,6 @@ interface HomeScreenProps {
readonly onProjectSortOrderChange: (sortOrder: HomeProjectSortOrder) => void;
readonly onThreadSortOrderChange: (sortOrder: SidebarThreadSortOrder) => void;
readonly onAddConnection: () => void;
readonly onOpenEnvironments: () => void;
readonly onOpenSettings: () => void;
readonly onStartNewTask: () => void;
readonly onSelectThread: (thread: EnvironmentThreadShell) => void;
Expand Down Expand Up @@ -969,20 +966,13 @@ export function HomeScreen(props: HomeScreenProps) {
? null
: (props.savedConnectionsById[props.selectedEnvironmentId]?.environmentLabel ??
"this environment");
const shouldShowConnectionStatus = shouldShowWorkspaceConnectionStatus(props.catalogState);
// Connection state surfaces in the header title slot
// (WorkspaceConnectionTitle) — nothing renders inside the list, so
// reconnects never shift the rows.
const emptyState = deriveEmptyState({
catalogState: props.catalogState,
projectCount: props.projects.length,
});
const connectionStatus =
shouldShowConnectionStatus && Platform.OS !== "ios" ? (
<View
className="absolute left-0 right-0 items-center"
style={{ bottom: Math.max(insets.bottom, 18) + 76 }}
>
<WorkspaceConnectionStatus state={props.catalogState} onPress={props.onOpenEnvironments} />
</View>
) : null;

if (!hasAnyThreads) {
return (
Expand All @@ -1001,41 +991,17 @@ export function HomeScreen(props: HomeScreenProps) {
onAction={!props.catalogState.hasReadyEnvironment ? props.onAddConnection : undefined}
variant="plain"
/>
{emptyState.loading && !shouldShowConnectionStatus ? (
{emptyState.loading ? (
<View className="mt-4 items-center">
<ActivityIndicator color={accentColor} />
</View>
) : null}
{shouldShowConnectionStatus && Platform.OS === "ios" ? (
<View className="mt-4">
<WorkspaceConnectionStatus
state={props.catalogState}
onPress={props.onOpenEnvironments}
variant="sidebar"
/>
</View>
) : null}
</View>
{connectionStatus}
</View>
);
}

const listHeader = (
<>
{Platform.OS === "ios" ? null : <HomeTopContentSpacer />}

{shouldShowConnectionStatus && Platform.OS === "ios" ? (
<View className="pb-4">
<WorkspaceConnectionStatus
state={props.catalogState}
onPress={props.onOpenEnvironments}
variant="sidebar"
/>
</View>
) : null}
</>
);
const listHeader = Platform.OS === "ios" ? null : <HomeTopContentSpacer />;

// Project scoping lives in the header filter menu (no inline chip row on
// mobile — the menu is the one filter surface).
Expand Down Expand Up @@ -1116,7 +1082,6 @@ export function HomeScreen(props: HomeScreenProps) {
}}
/>
</SwipeableScrollGateProvider>
{connectionStatus}
</View>
);
}
Expand Down Expand Up @@ -1171,7 +1136,6 @@ export function HomeScreen(props: HomeScreenProps) {
}
/>
</SwipeableScrollGateProvider>
{connectionStatus}
</View>
);
}
56 changes: 0 additions & 56 deletions apps/mobile/src/features/home/WorkspaceConnectionStatus.tsx

This file was deleted.

Loading
Loading