1- import { Link , useRouter } from "expo-router" ;
1+ import { useRouter } from "expo-router" ;
22import { useCallback , useEffect , useState } from "react" ;
33import {
44 ActivityIndicator ,
55 FlatList ,
66 Pressable ,
7- RefreshControl ,
8- Text ,
97 TextInput ,
108 View ,
119} from "react-native" ;
12- import { SafeAreaView } from "react-native-safe-area-context " ;
10+ import { Text } from "../components/text " ;
1311import {
1412 createTask ,
1513 getGithubRepositories ,
1614 getIntegrations ,
17- getTasks ,
1815 runTaskInCloud ,
1916} from "../features/agent/lib/agentApi" ;
20- import type { Integration , Task } from "../features/agent/types/agent" ;
17+ import type { Integration } from "../features/agent/types/agent" ;
2118
22- export default function AgentScreen ( ) {
19+ export default function NewTaskScreen ( ) {
2320 const router = useRouter ( ) ;
24- const [ tasks , setTasks ] = useState < Task [ ] > ( [ ] ) ;
25- const [ loading , setLoading ] = useState ( true ) ;
26- const [ refreshing , setRefreshing ] = useState ( false ) ;
27-
28- const [ showNewTask , setShowNewTask ] = useState ( false ) ;
2921 const [ integrations , setIntegrations ] = useState < Integration [ ] > ( [ ] ) ;
3022 const [ repositories , setRepositories ] = useState < string [ ] > ( [ ] ) ;
3123 const [ selectedRepo , setSelectedRepo ] = useState < string | null > ( null ) ;
3224 const [ prompt , setPrompt ] = useState ( "" ) ;
3325 const [ creating , setCreating ] = useState ( false ) ;
34- const [ loadingRepos , setLoadingRepos ] = useState ( false ) ;
35-
36- const fetchTasks = useCallback ( async ( ) => {
37- try {
38- const data = await getTasks ( ) ;
39- setTasks (
40- data . sort (
41- ( a , b ) =>
42- new Date ( b . created_at ) . getTime ( ) - new Date ( a . created_at ) . getTime ( ) ,
43- ) ,
44- ) ;
45- } catch ( error ) {
46- console . error ( "Failed to fetch tasks:" , error ) ;
47- }
48- } , [ ] ) ;
26+ const [ loadingRepos , setLoadingRepos ] = useState ( true ) ;
4927
5028 const loadIntegrations = useCallback ( async ( ) => {
5129 try {
30+ setLoadingRepos ( true ) ;
5231 const data = await getIntegrations ( ) ;
5332 const githubIntegrations = data . filter ( ( i ) => i . kind === "github" ) ;
5433 setIntegrations ( githubIntegrations ) ;
5534
5635 if ( githubIntegrations . length > 0 ) {
57- setLoadingRepos ( true ) ;
5836 const allRepos : string [ ] = [ ] ;
5937 for ( const integration of githubIntegrations ) {
6038 const repos = await getGithubRepositories ( integration . id ) ;
6139 allRepos . push ( ...repos ) ;
6240 }
6341 setRepositories ( allRepos . sort ( ) ) ;
64- setLoadingRepos ( false ) ;
6542 }
6643 } catch ( error ) {
6744 console . error ( "Failed to fetch integrations:" , error ) ;
45+ } finally {
6846 setLoadingRepos ( false ) ;
6947 }
7048 } , [ ] ) ;
7149
7250 useEffect ( ( ) => {
73- setLoading ( true ) ;
74- fetchTasks ( ) . finally ( ( ) => setLoading ( false ) ) ;
75- } , [ fetchTasks ] ) ;
76-
77- const onRefresh = useCallback ( async ( ) => {
78- setRefreshing ( true ) ;
79- await fetchTasks ( ) ;
80- setRefreshing ( false ) ;
81- } , [ fetchTasks ] ) ;
82-
83- const handleNewTask = useCallback ( ( ) => {
84- setShowNewTask ( true ) ;
8551 loadIntegrations ( ) ;
8652 } , [ loadIntegrations ] ) ;
8753
@@ -101,10 +67,6 @@ export default function AgentScreen() {
10167
10268 await runTaskInCloud ( task . id ) ;
10369
104- setShowNewTask ( false ) ;
105- setPrompt ( "" ) ;
106- setSelectedRepo ( null ) ;
107-
10870 router . push ( `/agent/${ task . id } ` ) ;
10971 } catch ( error ) {
11072 console . error ( "Failed to create task:" , error ) ;
@@ -113,183 +75,80 @@ export default function AgentScreen() {
11375 }
11476 } , [ prompt , selectedRepo , integrations , router ] ) ;
11577
116- const renderTask = useCallback (
117- ( { item } : { item : Task } ) => (
118- < Link href = { `/agent/${ item . id } ` } asChild >
119- < Pressable className = "bg-neutral-800 rounded-xl p-4 mb-3" >
120- < Text className = "text-white font-medium mb-1" numberOfLines = { 2 } >
121- { item . title || item . description }
78+ return (
79+ < View className = "flex-1 bg-dark px-3 pt-4" >
80+ < Text className = "mb-2 text-gray-500 text-xs" > Repository</ Text >
81+ { loadingRepos ? (
82+ < View className = "mb-4 items-center rounded-lg border border-dark-border p-4" >
83+ < ActivityIndicator size = "small" color = "#f97316" />
84+ < Text className = "mt-2 text-dark-text-muted text-sm" >
85+ Loading repositories...
86+ </ Text >
87+ </ View >
88+ ) : repositories . length === 0 ? (
89+ < View className = "mb-4 rounded-lg border border-dark-border p-4" >
90+ < Text className = "text-center text-dark-text-muted text-sm" >
91+ No GitHub integrations found. Please add a GitHub integration in
92+ PostHog settings.
12293 </ Text >
123- { item . repository && (
124- < Text className = "text-neutral-400 text-sm" > { item . repository } </ Text >
125- ) }
126- < View className = "flex-row justify-between items-center mt-2" >
127- < Text className = "text-neutral-500 text-xs" >
128- { new Date ( item . created_at ) . toLocaleDateString ( ) }
129- </ Text >
130- { item . latest_run && (
131- < View
132- className = { `px-2 py-1 rounded ${
133- item . latest_run . status === "completed"
134- ? "bg-green-900"
135- : item . latest_run . status === "failed"
136- ? "bg-red-900"
137- : "bg-blue-900"
94+ </ View >
95+ ) : (
96+ < View className = "mb-4 max-h-48 rounded-lg border border-dark-border" >
97+ < FlatList
98+ data = { repositories }
99+ keyExtractor = { ( item ) => item }
100+ renderItem = { ( { item } ) => (
101+ < Pressable
102+ onPress = { ( ) => setSelectedRepo ( item ) }
103+ className = { `border-dark-border border-b px-3 py-3 ${
104+ selectedRepo === item ? "bg-amber-500/20" : ""
138105 } `}
139106 >
140- < Text className = "text-white text-xs" >
141- { item . latest_run . status }
107+ < Text
108+ className = { `text-sm ${
109+ selectedRepo === item ? "text-amber-400" : "text-gray-400"
110+ } `}
111+ >
112+ { item }
142113 </ Text >
143- </ View >
114+ </ Pressable >
144115 ) }
145- </ View >
146- </ Pressable >
147- </ Link >
148- ) ,
149- [ ] ,
150- ) ;
151-
152- if ( showNewTask ) {
153- return (
154- < SafeAreaView className = "flex-1 bg-neutral-900" >
155- < View className = "flex-1 px-4 pt-4" >
156- < View className = "flex-row items-center justify-between mb-6" >
157- < Text className = "text-white text-xl font-bold" >
158- New Conversation
159- </ Text >
160- < Pressable onPress = { ( ) => setShowNewTask ( false ) } >
161- < Text className = "text-blue-500" > Cancel</ Text >
162- </ Pressable >
163- </ View >
164-
165- < Text className = "text-neutral-400 text-sm mb-2" > Repository</ Text >
166- { loadingRepos ? (
167- < View className = "bg-neutral-800 rounded-xl p-4 mb-4 items-center" >
168- < ActivityIndicator size = "small" color = "#6b7280" />
169- < Text className = "text-neutral-500 text-sm mt-2" >
170- Loading repositories...
171- </ Text >
172- </ View >
173- ) : repositories . length === 0 ? (
174- < View className = "bg-neutral-800 rounded-xl p-4 mb-4" >
175- < Text className = "text-neutral-500 text-center" >
176- No GitHub integrations found. Please add a GitHub integration in
177- PostHog settings.
178- </ Text >
179- </ View >
180- ) : (
181- < View className = "bg-neutral-800 rounded-xl mb-4 max-h-48" >
182- < FlatList
183- data = { repositories }
184- keyExtractor = { ( item ) => item }
185- renderItem = { ( { item } ) => (
186- < Pressable
187- onPress = { ( ) => setSelectedRepo ( item ) }
188- className = { `px-4 py-3 border-b border-neutral-700 ${
189- selectedRepo === item ? "bg-blue-900" : ""
190- } `}
191- >
192- < Text
193- className = { `${
194- selectedRepo === item
195- ? "text-white"
196- : "text-neutral-300"
197- } `}
198- >
199- { item }
200- </ Text >
201- </ Pressable >
202- ) }
203- />
204- </ View >
205- ) }
206-
207- < Text className = "text-neutral-400 text-sm mb-2" >
208- What would you like the agent to do?
209- </ Text >
210- < TextInput
211- className = "bg-neutral-800 text-white px-4 py-3 rounded-xl mb-4 min-h-[100px]"
212- placeholder = "Describe your task..."
213- placeholderTextColor = "#6b7280"
214- value = { prompt }
215- onChangeText = { setPrompt }
216- multiline
217- textAlignVertical = "top"
218116 />
219-
220- < Pressable
221- onPress = { handleCreateTask }
222- disabled = { ! prompt . trim ( ) || ! selectedRepo || creating }
223- className = { `rounded-xl p-4 ${
224- prompt . trim ( ) && selectedRepo && ! creating
225- ? "bg-blue-600"
226- : "bg-neutral-700"
227- } `}
228- >
229- { creating ? (
230- < ActivityIndicator size = "small" color = "#fff" />
231- ) : (
232- < Text className = "text-white text-center font-medium" >
233- Start Conversation
234- </ Text >
235- ) }
236- </ Pressable >
237117 </ View >
238- </ SafeAreaView >
239- ) ;
240- }
241-
242- return (
243- < SafeAreaView className = "flex-1 bg-neutral-900" >
244- < View className = "flex-1 px-4 pt-4" >
245- < View className = "flex-row items-center justify-between mb-6" >
246- < View >
247- < Text className = "text-white text-xl font-bold" > Array Agent</ Text >
248- < Text className = "text-neutral-400 text-sm" >
249- Your agent conversations
250- </ Text >
251- </ View >
252- < Pressable
253- onPress = { handleNewTask }
254- className = "bg-blue-600 px-4 py-2 rounded-lg"
255- >
256- < Text className = "text-white font-medium" > New</ Text >
257- </ Pressable >
258- </ View >
259-
260- { loading ? (
261- < View className = "flex-1 items-center justify-center" >
262- < ActivityIndicator size = "large" color = "#6b7280" />
263- </ View >
264- ) : tasks . length === 0 ? (
265- < View className = "flex-1 items-center justify-center" >
266- < Text className = "text-neutral-500 text-center mb-4" >
267- No conversations yet
268- </ Text >
269- < Pressable
270- onPress = { handleNewTask }
271- className = "bg-blue-600 px-6 py-3 rounded-xl"
272- >
273- < Text className = "text-white font-medium" >
274- Start a Conversation
275- </ Text >
276- </ Pressable >
277- </ View >
118+ ) }
119+
120+ < Text className = "mb-2 text-gray-500 text-xs" > Task description</ Text >
121+ < TextInput
122+ className = "mb-4 min-h-[100px] rounded-lg border border-dark-border px-3 py-3 font-mono text-sm text-white"
123+ placeholder = "What would you like the agent to do?"
124+ placeholderTextColor = "#6b7280"
125+ value = { prompt }
126+ onChangeText = { setPrompt }
127+ multiline
128+ textAlignVertical = "top"
129+ />
130+
131+ < Pressable
132+ onPress = { handleCreateTask }
133+ disabled = { ! prompt . trim ( ) || ! selectedRepo || creating }
134+ className = { `rounded-lg py-3 ${
135+ prompt . trim ( ) && selectedRepo && ! creating
136+ ? "bg-orange-500"
137+ : "bg-dark-surface"
138+ } `}
139+ >
140+ { creating ? (
141+ < ActivityIndicator size = "small" color = "#fff" />
278142 ) : (
279- < FlatList
280- data = { tasks }
281- renderItem = { renderTask }
282- keyExtractor = { ( item ) => item . id }
283- refreshControl = {
284- < RefreshControl
285- refreshing = { refreshing }
286- onRefresh = { onRefresh }
287- tintColor = "#6b7280"
288- />
289- }
290- />
143+ < Text
144+ className = { `text-center font-medium ${
145+ prompt . trim ( ) && selectedRepo ? "text-white" : "text-gray-500"
146+ } `}
147+ >
148+ Create task
149+ </ Text >
291150 ) }
292- </ View >
293- </ SafeAreaView >
151+ </ Pressable >
152+ </ View >
294153 ) ;
295154}
0 commit comments