authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-03-09 09:10:37-07:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-03-09 09:31:39-07:00
log5c286cab8b87fa5055533c54721cca52ec32050d
tree94003d24e9959d67c005e7d91c8af369512e2217
parent75ca0d4fa41a4b5a85a6aa852dad813fbcbb94db

Open project folder picker immediately in Electron

- remove mobile-width gating from sidebar project picker behavior - simplify picker logic/tests to depend only on Electron runtime

3 files changed, 5 insertions(+), 16 deletions(-)

apps/web/src/components/Sidebar.logic.test.ts+4-11
...@@ -2,30 +2,23 @@ import { describe, expect, it } from "vitest";...@@ -2,30 +2,23 @@ import { describe, expect, it } from "vitest";
2import { shouldOpenProjectFolderPickerImmediately } from "./Sidebar.logic";2import { shouldOpenProjectFolderPickerImmediately } from "./Sidebar.logic";
33
4describe("shouldOpenProjectFolderPickerImmediately", () => {4describe("shouldOpenProjectFolderPickerImmediately", () => {
5 it("opens the folder picker immediately in Electron on desktop", () => {5 it("opens the folder picker immediately in Electron", () => {
6 expect(6 expect(
7 shouldOpenProjectFolderPickerImmediately({7 shouldOpenProjectFolderPickerImmediately({
8 isElectron: true,8 isElectron: true,
9 isMobile: false,
10 }),9 }),
11 ).toBe(true);10 ).toBe(true);
12 });11 });
1312
14 it("keeps manual project entry on mobile Electron layouts", () => {13 it("still opens the folder picker immediately for mobile-width Electron layouts", () => {
15 expect(14 expect(
16 shouldOpenProjectFolderPickerImmediately({15 shouldOpenProjectFolderPickerImmediately({
17 isElectron: true,16 isElectron: true,
18 isMobile: true,
19 }),17 }),
20 ).toBe(false);18 ).toBe(true);
21 });19 });
2220
23 it("keeps manual project entry outside Electron", () => {21 it("keeps manual project entry outside Electron", () => {
24 expect(22 expect(shouldOpenProjectFolderPickerImmediately({ isElectron: false })).toBe(false);
25 shouldOpenProjectFolderPickerImmediately({
26 isElectron: false,
27 isMobile: false,
28 }),
29 ).toBe(false);
30 });23 });
31});24});
apps/web/src/components/Sidebar.logic.ts+1-2
...@@ -1,6 +1,5 @@...@@ -1,6 +1,5 @@
1export function shouldOpenProjectFolderPickerImmediately(input: {1export function shouldOpenProjectFolderPickerImmediately(input: {
2 isElectron: boolean;2 isElectron: boolean;
3 isMobile: boolean;
4}): boolean {3}): boolean {
5 return input.isElectron && !input.isMobile;4 return input.isElectron;
6}5}
apps/web/src/components/Sidebar.tsx-3
...@@ -32,7 +32,6 @@ import { type Thread } from "../types";...@@ -32,7 +32,6 @@ import { type Thread } from "../types";
32import { derivePendingApprovals } from "../session-logic";32import { derivePendingApprovals } from "../session-logic";
33import { gitRemoveWorktreeMutationOptions, gitStatusQueryOptions } from "../lib/gitReactQuery";33import { gitRemoveWorktreeMutationOptions, gitStatusQueryOptions } from "../lib/gitReactQuery";
34import { serverConfigQueryOptions } from "../lib/serverReactQuery";34import { serverConfigQueryOptions } from "../lib/serverReactQuery";
35import { useMediaQuery } from "../hooks/useMediaQuery";
36import { readNativeApi } from "../nativeApi";35import { readNativeApi } from "../nativeApi";
37import { type DraftThreadEnvMode, useComposerDraftStore } from "../composerDraftStore";36import { type DraftThreadEnvMode, useComposerDraftStore } from "../composerDraftStore";
38import { selectThreadTerminalState, useTerminalStateStore } from "../terminalStateStore";37import { selectThreadTerminalState, useTerminalStateStore } from "../terminalStateStore";
...@@ -268,7 +267,6 @@ function ProjectFavicon({ cwd }: { cwd: string }) {...@@ -268,7 +267,6 @@ function ProjectFavicon({ cwd }: { cwd: string }) {
268}267}
269268
270export default function Sidebar() {269export default function Sidebar() {
271 const isMobile = useMediaQuery("(max-width: 767px)");
272 const projects = useStore((store) => store.projects);270 const projects = useStore((store) => store.projects);
273 const threads = useStore((store) => store.threads);271 const threads = useStore((store) => store.threads);
274 const markThreadUnread = useStore((store) => store.markThreadUnread);272 const markThreadUnread = useStore((store) => store.markThreadUnread);
...@@ -317,7 +315,6 @@ export default function Sidebar() {...@@ -317,7 +315,6 @@ export default function Sidebar() {
317 const [desktopUpdateState, setDesktopUpdateState] = useState<DesktopUpdateState | null>(null);315 const [desktopUpdateState, setDesktopUpdateState] = useState<DesktopUpdateState | null>(null);
318 const shouldBrowseForProjectImmediately = shouldOpenProjectFolderPickerImmediately({316 const shouldBrowseForProjectImmediately = shouldOpenProjectFolderPickerImmediately({
319 isElectron,317 isElectron,
320 isMobile,
321 });318 });
322 const shouldShowProjectPathEntry = addingProject && !shouldBrowseForProjectImmediately;319 const shouldShowProjectPathEntry = addingProject && !shouldBrowseForProjectImmediately;
323 const pendingApprovalByThreadId = useMemo(() => {320 const pendingApprovalByThreadId = useMemo(() => {