authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-03-03 09:55:52-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-03-03 10:01:18-08:00
log93af851dc53e950673dacc1fb79c2bd95a8b6a9d
treed1b80f4a1d1af8d0460749381d3fe6f000c27279
parentfabb3e07348eb864d6a2c33234db1afb59c7e310

type


3 files changed, 27 insertions(+), 11 deletions(-)

apps/web/src/components/BranchToolbar.logic.ts+5-3
...@@ -1,10 +1,12 @@...@@ -1,10 +1,12 @@
1import type { GitBranch } from "@t3tools/contracts";1import type { GitBranch } from "@t3tools/contracts";
22
3export type EnvMode = "local" | "worktree";
4
3export function resolveDraftEnvModeAfterBranchChange(input: {5export function resolveDraftEnvModeAfterBranchChange(input: {
4 nextWorktreePath: string | null;6 nextWorktreePath: string | null;
5 currentWorktreePath: string | null;7 currentWorktreePath: string | null;
6 effectiveEnvMode: "local" | "worktree";8 effectiveEnvMode: EnvMode;
7}): "local" | "worktree" {9}): EnvMode {
8 const { nextWorktreePath, currentWorktreePath, effectiveEnvMode } = input;10 const { nextWorktreePath, currentWorktreePath, effectiveEnvMode } = input;
9 if (nextWorktreePath) {11 if (nextWorktreePath) {
10 return "worktree";12 return "worktree";
...@@ -16,7 +18,7 @@ export function resolveDraftEnvModeAfterBranchChange(input: {...@@ -16,7 +18,7 @@ export function resolveDraftEnvModeAfterBranchChange(input: {
16}18}
1719
18export function resolveBranchToolbarValue(input: {20export function resolveBranchToolbarValue(input: {
19 envMode: "local" | "worktree";21 envMode: EnvMode;
20 activeWorktreePath: string | null;22 activeWorktreePath: string | null;
21 activeThreadBranch: string | null;23 activeThreadBranch: string | null;
22 currentGitBranch: string | null;24 currentGitBranch: string | null;
apps/web/src/components/BranchToolbar.tsx+4-4
...@@ -5,14 +5,14 @@ import { newCommandId } from "../lib/utils";...@@ -5,14 +5,14 @@ import { newCommandId } from "../lib/utils";
5import { readNativeApi } from "../nativeApi";5import { readNativeApi } from "../nativeApi";
6import { useComposerDraftStore } from "../composerDraftStore";6import { useComposerDraftStore } from "../composerDraftStore";
7import { useStore } from "../store";7import { useStore } from "../store";
8import { resolveDraftEnvModeAfterBranchChange } from "./BranchToolbar.logic";8import { EnvMode, resolveDraftEnvModeAfterBranchChange } from "./BranchToolbar.logic";
9import { BranchToolbarBranchSelector } from "./BranchToolbarBranchSelector";9import { BranchToolbarBranchSelector } from "./BranchToolbarBranchSelector";
10import { Button } from "./ui/button";10import { Button } from "./ui/button";
1111
12interface BranchToolbarProps {12interface BranchToolbarProps {
13 threadId: ThreadId;13 threadId: ThreadId;
14 envMode: "local" | "worktree";14 envMode: EnvMode;
15 onEnvModeChange: (mode: "local" | "worktree") => void;15 onEnvModeChange: (mode: EnvMode) => void;
16 envLocked: boolean;16 envLocked: boolean;
17 onComposerFocusRequest?: () => void;17 onComposerFocusRequest?: () => void;
18}18}
...@@ -38,7 +38,7 @@ export default function BranchToolbar({...@@ -38,7 +38,7 @@ export default function BranchToolbar({
38 const activeWorktreePath = serverThread?.worktreePath ?? draftThread?.worktreePath ?? null;38 const activeWorktreePath = serverThread?.worktreePath ?? draftThread?.worktreePath ?? null;
39 const branchCwd = activeWorktreePath ?? activeProject?.cwd ?? null;39 const branchCwd = activeWorktreePath ?? activeProject?.cwd ?? null;
40 const hasServerThread = serverThread !== undefined;40 const hasServerThread = serverThread !== undefined;
41 const effectiveEnvMode: "local" | "worktree" =41 const effectiveEnvMode: EnvMode =
42 activeWorktreePath || (!hasServerThread && draftThread?.envMode === "worktree")42 activeWorktreePath || (!hasServerThread && draftThread?.envMode === "worktree")
43 ? "worktree"43 ? "worktree"
44 : envMode;44 : envMode;
apps/web/src/components/BranchToolbarBranchSelector.tsx+18-4
...@@ -2,13 +2,22 @@ import type { GitBranch } from "@t3tools/contracts";...@@ -2,13 +2,22 @@ import type { GitBranch } from "@t3tools/contracts";
2import { useQuery, useQueryClient } from "@tanstack/react-query";2import { useQuery, useQueryClient } from "@tanstack/react-query";
3import { useVirtualizer } from "@tanstack/react-virtual";3import { useVirtualizer } from "@tanstack/react-virtual";
4import { ChevronDownIcon } from "lucide-react";4import { ChevronDownIcon } from "lucide-react";
5import { useCallback, useEffect, useMemo, useOptimistic, useRef, useState, useTransition } from "react";5import {
6 useCallback,
7 useEffect,
8 useMemo,
9 useOptimistic,
10 useRef,
11 useState,
12 useTransition,
13} from "react";
614
7import { gitBranchesQueryOptions, gitQueryKeys, invalidateGitQueries } from "../lib/gitReactQuery";15import { gitBranchesQueryOptions, gitQueryKeys, invalidateGitQueries } from "../lib/gitReactQuery";
8import { readNativeApi } from "../nativeApi";16import { readNativeApi } from "../nativeApi";
9import {17import {
10 dedupeRemoteBranchesWithLocalMatches,18 dedupeRemoteBranchesWithLocalMatches,
11 deriveLocalBranchNameFromRemoteRef,19 deriveLocalBranchNameFromRemoteRef,
20 EnvMode,
12 resolveBranchToolbarValue,21 resolveBranchToolbarValue,
13} from "./BranchToolbar.logic";22} from "./BranchToolbar.logic";
14import { Button } from "./ui/button";23import { Button } from "./ui/button";
...@@ -28,7 +37,7 @@ interface BranchToolbarBranchSelectorProps {...@@ -28,7 +37,7 @@ interface BranchToolbarBranchSelectorProps {
28 activeThreadBranch: string | null;37 activeThreadBranch: string | null;
29 activeWorktreePath: string | null;38 activeWorktreePath: string | null;
30 branchCwd: string | null;39 branchCwd: string | null;
31 effectiveEnvMode: "local" | "worktree";40 effectiveEnvMode: EnvMode;
32 envLocked: boolean;41 envLocked: boolean;
33 onSetThreadBranch: (branch: string | null, worktreePath: string | null) => void;42 onSetThreadBranch: (branch: string | null, worktreePath: string | null) => void;
34 onComposerFocusRequest?: () => void;43 onComposerFocusRequest?: () => void;
...@@ -40,7 +49,7 @@ function toBranchActionErrorMessage(error: unknown): string {...@@ -40,7 +49,7 @@ function toBranchActionErrorMessage(error: unknown): string {
4049
41function getBranchTriggerLabel(input: {50function getBranchTriggerLabel(input: {
42 activeWorktreePath: string | null;51 activeWorktreePath: string | null;
43 effectiveEnvMode: "local" | "worktree";52 effectiveEnvMode: EnvMode;
44 resolvedActiveBranch: string | null;53 resolvedActiveBranch: string | null;
45}): string {54}): string {
46 const { activeWorktreePath, effectiveEnvMode, resolvedActiveBranch } = input;55 const { activeWorktreePath, effectiveEnvMode, resolvedActiveBranch } = input;
...@@ -215,7 +224,12 @@ export function BranchToolbarBranchSelector({...@@ -215,7 +224,12 @@ export function BranchToolbarBranchSelector({
215 };224 };
216225
217 useEffect(() => {226 useEffect(() => {
218 if (effectiveEnvMode !== "worktree" || activeWorktreePath || activeThreadBranch || !currentGitBranch) {227 if (
228 effectiveEnvMode !== "worktree" ||
229 activeWorktreePath ||
230 activeThreadBranch ||
231 !currentGitBranch
232 ) {
219 return;233 return;
220 }234 }
221 onSetThreadBranch(currentGitBranch, null);235 onSetThreadBranch(currentGitBranch, null);