Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
2e66b1f
fix(web): live background-work banner no longer hides behind the upda…
t3dotgg Aug 7, 2026
b792ed9
fix(web): stabilize chat timeline positioning (#5449)
jmeistrich Aug 7, 2026
7963cc7
feat(server): record runtime mode per turn and on mode changes (#5593)
t3dotgg Aug 7, 2026
b2ee17d
feat(web): thread actions from the chat header title (#5592)
t3dotgg Aug 7, 2026
a17459e
fix(mobile): avoid iOS terminal reset on clear (#5440)
justynleung Aug 7, 2026
33a03c8
fix(mobile): pad scroll views above Android nav bar (#5415)
StoneCotton Aug 7, 2026
bd422fd
fix(mobile): keep Android chat text from showing through the composer…
PollyGlot Aug 7, 2026
af281c9
fix(mobile): repair Clerk auth navigation headers (#5140)
gabrielelpidio Aug 7, 2026
bfc69e4
Bump mobile app version to 1.0.2 (#5588)
juliusmarminge Aug 7, 2026
61b51ae
feat(web): click the pin icon to unpin a thread (#5578)
UtkarshUsername Aug 7, 2026
239ef1c
fix(web): show the correctly matching shortcut in new thread button's…
UtkarshUsername Aug 7, 2026
be1a836
chore(release): prepare v0.0.32
t3-code[bot] Aug 7, 2026
6d70e6d
fix(mobile): reconnects no longer shift the thread list (#5372)
t3dotgg Aug 7, 2026
5661c61
feat(web): drag pinned threads into your own order (#5581)
t3dotgg Aug 7, 2026
7920591
fix(connection): refresh network status after app activation
DominicVonk Aug 7, 2026
ebc5d85
fix(connection): preserve offline relay state during refresh
DominicVonk Aug 7, 2026
a9ddf54
fix(connection): preserve activation signal ordering
DominicVonk Aug 7, 2026
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: 1 addition & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@t3tools/desktop",
"version": "0.0.31",
"version": "0.0.32",
"private": true,
"type": "module",
"main": "dist-electron/main.cjs",
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ const config: ExpoConfig = {
slug: "t3-code",
platforms: ["ios", "android"],
scheme: variant.scheme,
version: "1.0.1",
version: "1.0.2",
runtimeVersion: {
// Fingerprint (not appVersion) so an OTA only reaches binaries whose native
// project — native deps, config plugins, AND patches/ — matches the update.
Expand Down
6 changes: 6 additions & 0 deletions apps/mobile/modules/t3-terminal/ios/T3TerminalView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,12 @@ public final class T3TerminalView: ExpoView, UITextFieldDelegate {
return
}

if buffer.isEmpty {
feedData(Data("\u{1B}[3J\u{1B}[H\u{1B}[2J".utf8))
lastAppliedBuffer = ""
return
}

if buffer.hasPrefix(lastAppliedBuffer) {
let suffix = String(buffer.dropFirst(lastAppliedBuffer.count))
feedData(Data(suffix.utf8))
Expand Down
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
23 changes: 2 additions & 21 deletions apps/mobile/src/connection/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,31 +56,12 @@ const connectivityLayer = Connectivity.layer({
changes: Stream.callback((queue) =>
Effect.acquireRelease(
Effect.sync(() => {
let active = true;
const networkSubscription = Network.addNetworkStateListener((state) => {
Queue.offerUnsafe(queue, networkStatus(state));
});
const appStateSubscription = AppState.addEventListener("change", (state) => {
if (state !== "active") {
return;
}
void Network.getNetworkStateAsync()
.then((current) => {
if (active) {
Queue.offerUnsafe(queue, networkStatus(current));
}
})
.catch(() => undefined);
});
return {
close: () => {
active = false;
networkSubscription.remove();
appStateSubscription.remove();
},
};
return networkSubscription;
}),
({ close }) => Effect.sync(close),
(subscription) => Effect.sync(() => subscription.remove()),
).pipe(Effect.asVoid),
),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ export function ConnectionsRouteScreen() {
contentInsetAdjustmentBehavior="automatic"
showsVerticalScrollIndicator={false}
className="flex-1"
contentInset={{ bottom: Math.max(insets.bottom, 18) + 18 }}
contentContainerStyle={{
paddingBottom: Math.max(insets.bottom, 18) + 18,
paddingHorizontal: 20,
paddingTop: 16,
}}
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
22 changes: 16 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 All @@ -44,6 +44,7 @@ export function HomeRouteScreen() {
unsnoozeThread,
pinThread,
unpinThread,
movePinnedThread,
unsettleThread,
} = useThreadListActions();
const pendingTasks = usePendingNewTasks();
Expand Down Expand Up @@ -126,8 +127,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 +147,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 @@ -159,11 +171,9 @@ export function HomeRouteScreen() {
onUnsettleThread={unsettleThread}
onPinThread={pinThread}
onUnpinThread={unpinThread}
onMovePinnedThread={movePinnedThread}
onEnvironmentChange={setSelectedEnvironmentId}
onProjectChange={setSelectedProjectKey}
onOpenEnvironments={() =>
navigation.navigate("SettingsSheet", { screen: "SettingsEnvironments" })
}
onOpenSettings={() => navigation.navigate("SettingsSheet", { screen: "Settings" })}
onProjectSortOrderChange={setProjectSortOrder}
onSearchQueryChange={setSearchQuery}
Expand Down
Loading
Loading