From 93670c15d9b6542b24078c9cef7b09e09fc8cb47 Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Sat, 07 Mar 2026 13:49:16 +0100
Subject: [PATCH] feat: project picker in session drawer

---
 components/SessionDrawer.tsx |  151 ++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 132 insertions(+), 19 deletions(-)

diff --git a/components/SessionDrawer.tsx b/components/SessionDrawer.tsx
index 8019e74..75db7b8 100644
--- a/components/SessionDrawer.tsx
+++ b/components/SessionDrawer.tsx
@@ -25,7 +25,7 @@
   ScaleDecorator,
 } from "react-native-draggable-flatlist";
 import * as Haptics from "expo-haptics";
-import { WsSession } from "../types";
+import { WsSession, PaiProject } from "../types";
 import { useChat } from "../contexts/ChatContext";
 import { useTheme, type ThemeColors } from "../contexts/ThemeContext";
 
@@ -262,10 +262,14 @@
     renameSession,
     removeSession,
     createSession,
+    fetchProjects,
+    projects,
     unreadCounts,
   } = useChat();
   const { colors } = useTheme();
   const [editingId, setEditingId] = useState<string | null>(null);
+  const [showProjectPicker, setShowProjectPicker] = useState(false);
+  const [customPath, setCustomPath] = useState("");
   const slideAnim = useRef(new Animated.Value(-DRAWER_WIDTH)).current;
   const fadeAnim = useRef(new Animated.Value(0)).current;
   const [rendered, setRendered] = useState(false);
@@ -326,6 +330,8 @@
 
   const handleClose = useCallback(() => {
     setEditingId(null);
+    setShowProjectPicker(false);
+    setCustomPath("");
     Keyboard.dismiss();
     onClose();
   }, [onClose]);
@@ -362,8 +368,18 @@
   );
 
   const handleNewSession = useCallback(() => {
+    Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+    setShowProjectPicker((prev) => {
+      if (!prev) fetchProjects();
+      return !prev;
+    });
+  }, [fetchProjects]);
+
+  const launchSession = useCallback((opts?: { project?: string; path?: string }) => {
     Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
-    createSession();
+    createSession(opts);
+    setShowProjectPicker(false);
+    setCustomPath("");
     handleClose();
     setTimeout(() => requestSessions(), 2500);
   }, [createSession, requestSessions, handleClose]);
@@ -519,23 +535,120 @@
               />
             )}
 
-            {/* New session button */}
-            <View style={{ alignItems: "center", paddingVertical: 12 }}>
-              <Pressable
-                onPress={handleNewSession}
-                style={{
-                  flexDirection: "row",
-                  alignItems: "center",
-                  gap: 6,
-                  paddingHorizontal: 20,
-                  paddingVertical: 10,
-                  borderRadius: 24,
-                  backgroundColor: colors.accent,
-                }}
-              >
-                <Text style={{ color: "#FFF", fontSize: 18, fontWeight: "700" }}>+</Text>
-                <Text style={{ color: "#FFF", fontSize: 15, fontWeight: "600" }}>New Session</Text>
-              </Pressable>
+            {/* New session button + project picker */}
+            <View style={{ paddingVertical: 8 }}>
+              <View style={{ alignItems: "center", paddingBottom: showProjectPicker ? 8 : 0 }}>
+                <Pressable
+                  onPress={handleNewSession}
+                  style={{
+                    flexDirection: "row",
+                    alignItems: "center",
+                    gap: 6,
+                    paddingHorizontal: 20,
+                    paddingVertical: 10,
+                    borderRadius: 24,
+                    backgroundColor: colors.accent,
+                  }}
+                >
+                  <Text style={{ color: "#FFF", fontSize: 18, fontWeight: "700" }}>+</Text>
+                  <Text style={{ color: "#FFF", fontSize: 15, fontWeight: "600" }}>New Session</Text>
+                </Pressable>
+              </View>
+
+              {showProjectPicker && (
+                <View style={{
+                  marginHorizontal: 12,
+                  borderRadius: 12,
+                  backgroundColor: colors.bgTertiary,
+                  overflow: "hidden",
+                }}>
+                  {/* Home directory โ€” always first */}
+                  <Pressable
+                    onPress={() => launchSession({ path: "~" })}
+                    style={({ pressed }) => ({
+                      flexDirection: "row",
+                      alignItems: "center",
+                      paddingHorizontal: 16,
+                      paddingVertical: 12,
+                      backgroundColor: pressed ? colors.border : "transparent",
+                    })}
+                  >
+                    <Text style={{ fontSize: 18, marginRight: 10 }}>๐Ÿ </Text>
+                    <View style={{ flex: 1 }}>
+                      <Text style={{ color: colors.text, fontSize: 15, fontWeight: "600" }}>Home</Text>
+                      <Text style={{ color: colors.textMuted, fontSize: 12 }}>~/</Text>
+                    </View>
+                  </Pressable>
+
+                  {/* PAI projects */}
+                  {projects.map((p) => (
+                    <Pressable
+                      key={p.slug}
+                      onPress={() => launchSession({ project: p.name })}
+                      style={({ pressed }) => ({
+                        flexDirection: "row",
+                        alignItems: "center",
+                        paddingHorizontal: 16,
+                        paddingVertical: 12,
+                        borderTopWidth: 1,
+                        borderTopColor: colors.border,
+                        backgroundColor: pressed ? colors.border : "transparent",
+                      })}
+                    >
+                      <Text style={{ fontSize: 18, marginRight: 10 }}>๐Ÿ“‚</Text>
+                      <View style={{ flex: 1 }}>
+                        <Text style={{ color: colors.text, fontSize: 15, fontWeight: "500" }}>{p.name}</Text>
+                        <Text style={{ color: colors.textMuted, fontSize: 12 }} numberOfLines={1}>
+                          {p.path.replace(/^\/Users\/[^/]+/, "~")}
+                        </Text>
+                      </View>
+                    </Pressable>
+                  ))}
+
+                  {/* Custom path input */}
+                  <View style={{
+                    flexDirection: "row",
+                    alignItems: "center",
+                    borderTopWidth: 1,
+                    borderTopColor: colors.border,
+                    paddingHorizontal: 16,
+                    paddingVertical: 8,
+                  }}>
+                    <TextInput
+                      value={customPath}
+                      onChangeText={setCustomPath}
+                      placeholder="Custom pathโ€ฆ"
+                      placeholderTextColor={colors.textMuted}
+                      autoCapitalize="none"
+                      autoCorrect={false}
+                      returnKeyType="go"
+                      onSubmitEditing={() => {
+                        if (customPath.trim()) launchSession({ path: customPath.trim() });
+                      }}
+                      style={{
+                        flex: 1,
+                        color: colors.text,
+                        fontSize: 14,
+                        paddingVertical: 6,
+                      }}
+                    />
+                    {customPath.trim().length > 0 && (
+                      <Pressable
+                        onPress={() => launchSession({ path: customPath.trim() })}
+                        style={{
+                          paddingHorizontal: 12,
+                          paddingVertical: 6,
+                          borderRadius: 8,
+                          backgroundColor: colors.accent,
+                          marginLeft: 8,
+                        }}
+                      >
+                        <Text style={{ color: "#FFF", fontSize: 13, fontWeight: "600" }}>Go</Text>
+                      </Pressable>
+                    )}
+                  </View>
+                </View>
+              )}
             </View>
 
             {/* Footer */}

--
Gitblit v1.3.1