diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 08a31f483..9d77e1326 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -26,3 +26,13 @@ Don't run them anywhere else. Check logs there. ## Andriod Take screensots like this: `adb exec-out screencap -p > screenshot.png` + +## Asking Codex for a second opinion + +You can ask Codex for a second opinion on a problem you're working on. + +Set a high timeout, like 2 minutes. + +Try not to bias it, state the problem clearly and let it work it out. + +`codex exec "prompt"` diff --git a/packages/app/src/app/index.tsx b/packages/app/src/app/index.tsx index 3b4a009b2..c0c02f60f 100644 --- a/packages/app/src/app/index.tsx +++ b/packages/app/src/app/index.tsx @@ -30,11 +30,6 @@ import { useSafeAreaInsets } from "react-native-safe-area-context"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; import { theme as defaultTheme, theme } from "../styles/theme"; -// Simple unique ID generator -let messageIdCounter = 0; -function generateMessageId(): string { - return `msg_${Date.now()}_${messageIdCounter++}`; -} import { useWebSocket } from "@/hooks/use-websocket"; import { useAudioRecorder } from "@/hooks/use-audio-recorder"; import { useAudioPlayer } from "@/hooks/use-audio-player"; @@ -1247,9 +1242,8 @@ export default function VoiceAssistantScreen() { function handleSelectConversation(newConversationId: string | null) { // Clear all state setMessages([]); - setAgentMessages(new Map()); + setAgentStreamState(new Map()); setCurrentAssistantMessage(""); - setCurrentAgentMessages(new Map()); setUserInput(""); setArtifacts(new Map()); setCurrentArtifact(null); @@ -1402,7 +1396,7 @@ export default function VoiceAssistantScreen() { > {messages.length === 0 && !currentAssistantMessage && ( - OnTheGo + Hammock What would you like to work on? diff --git a/packages/app/src/components/create-agent-modal.tsx b/packages/app/src/components/create-agent-modal.tsx index d54e1e761..be2c31650 100644 --- a/packages/app/src/components/create-agent-modal.tsx +++ b/packages/app/src/components/create-agent-modal.tsx @@ -6,9 +6,10 @@ import { Pressable, TextInput, ScrollView, - KeyboardAvoidingView, - Platform, } from "react-native"; +import { useReanimatedKeyboardAnimation } from "react-native-keyboard-controller"; +import ReanimatedAnimated, { useAnimatedStyle } from "react-native-reanimated"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; import { X } from "lucide-react-native"; import { StyleSheet } from "react-native-unistyles"; import { theme as defaultTheme } from "@/styles/theme"; @@ -37,10 +38,24 @@ export function CreateAgentModal({ onClose, onCreateAgent, }: CreateAgentModalProps) { + const insets = useSafeAreaInsets(); + const { height: keyboardHeight } = useReanimatedKeyboardAnimation(); + const [workingDir, setWorkingDir] = useState(""); const [selectedMode, setSelectedMode] = useState("plan"); const [errorMessage, setErrorMessage] = useState(""); + // Keyboard animation + const bottomInset = insets.bottom; + const animatedKeyboardStyle = useAnimatedStyle(() => { + "worklet"; + const absoluteHeight = Math.abs(keyboardHeight.value); + const padding = Math.max(0, absoluteHeight - bottomInset); + return { + paddingBottom: padding, + }; + }); + function handleCreate() { if (!workingDir.trim()) { setErrorMessage("Working directory is required"); @@ -65,12 +80,11 @@ export function CreateAgentModal({ transparent={true} onRequestClose={handleClose} > - + - + {/* Header */} @@ -149,25 +163,29 @@ export function CreateAgentModal({ ))} - - {/* Action Buttons */} - - - Create Agent - - - - Cancel - - + + {/* Fixed Footer with Create Button */} + + + Create Agent + + - - + + ); } @@ -175,19 +193,28 @@ export function CreateAgentModal({ const styles = StyleSheet.create((theme) => ({ modalOverlay: { flex: 1, - backgroundColor: "rgba(0,0,0,0.5)", + justifyContent: "flex-end", }, modalBackdrop: { - flex: 1, + position: "absolute", + top: 0, + left: 0, + right: 0, + bottom: 0, + backgroundColor: "rgba(0,0,0,0.5)", + zIndex: 1, }, modalContent: { backgroundColor: theme.colors.card, borderTopLeftRadius: theme.spacing[6], borderTopRightRadius: theme.spacing[6], - height: "75%", + minHeight: "80%", + zIndex: 2, + elevation: 5, }, modalInner: { flex: 1, + minHeight: 0, }, header: { flexDirection: "row", @@ -207,7 +234,7 @@ const styles = StyleSheet.create((theme) => ({ }, scrollContent: { padding: theme.spacing[6], - paddingBottom: theme.spacing[4] * 5, + paddingBottom: theme.spacing[4], }, formSection: { marginBottom: theme.spacing[6], @@ -289,14 +316,18 @@ const styles = StyleSheet.create((theme) => ({ color: theme.colors.mutedForeground, fontSize: theme.fontSize.sm, }, - buttonContainer: { - gap: theme.spacing[3], - marginTop: theme.spacing[4], + footer: { + borderTopWidth: theme.borderWidth[1], + borderTopColor: theme.colors.border, + paddingHorizontal: theme.spacing[6], + paddingTop: theme.spacing[4], + backgroundColor: theme.colors.card, }, createButton: { backgroundColor: theme.colors.palette.blue[500], paddingVertical: theme.spacing[4], borderRadius: theme.borderRadius.lg, + marginBottom: theme.spacing[4], alignItems: "center", }, createButtonDisabled: { @@ -308,17 +339,4 @@ const styles = StyleSheet.create((theme) => ({ fontSize: theme.fontSize.base, fontWeight: theme.fontWeight.semibold, }, - cancelButton: { - backgroundColor: "transparent", - paddingVertical: theme.spacing[4], - borderRadius: theme.borderRadius.lg, - alignItems: "center", - borderWidth: theme.borderWidth[1], - borderColor: theme.colors.border, - }, - cancelButtonText: { - color: theme.colors.foreground, - fontSize: theme.fontSize.base, - fontWeight: theme.fontWeight.semibold, - }, }));