1- import { FolderPicker } from "@features/folder-picker/components/FolderPicker" ;
2- import { useWorkspaceStore } from "@features/workspace/stores/workspaceStore" ;
31import { useSetHeaderContent } from "@hooks/useSetHeaderContent" ;
42import { Warning } from "@phosphor-icons/react" ;
53import {
64 Box ,
75 Button ,
86 Callout ,
97 Card ,
8+ Code ,
109 Flex ,
1110 Heading ,
1211 Text ,
1312} from "@radix-ui/themes" ;
1413import { logger } from "@renderer/lib/logger" ;
1514import { useNavigationStore } from "@renderer/stores/navigationStore" ;
1615import { useRegisteredFoldersStore } from "@renderer/stores/registeredFoldersStore" ;
17- import { trpcVanilla } from "@renderer/trpc" ;
18- import { useMutation , useQueryClient } from "@tanstack/react-query" ;
19- import { useEffect , useState } from "react" ;
16+ import { useState } from "react" ;
2017
2118const log = logger . scope ( "folder-settings" ) ;
2219
2320export function FolderSettingsView ( ) {
2421 useSetHeaderContent ( null ) ;
2522
2623 const { view, navigateToTaskInput } = useNavigationStore ( ) ;
27- const { folders, removeFolder, loadFolders } = useRegisteredFoldersStore ( ) ;
28- const queryClient = useQueryClient ( ) ;
24+ const { folders, removeFolder } = useRegisteredFoldersStore ( ) ;
2925
3026 const folderId = view . type === "folder-settings" ? view . folderId : undefined ;
3127 const folder = folders . find ( ( f ) => f . id === folderId ) ;
3228
33- const [ newPath , setNewPath ] = useState ( folder ?. path ?? "" ) ;
3429 const [ error , setError ] = useState < string | null > ( null ) ;
3530
36- // Reset form when folder changes
37- useEffect ( ( ) => {
38- if ( folder ) {
39- setNewPath ( folder . path ) ;
40- }
41- } , [ folder ] ) ;
42-
43- const updatePathMutation = useMutation ( {
44- mutationFn : async ( path : string ) => {
45- if ( ! folderId ) throw new Error ( "No folder selected" ) ;
46- return await trpcVanilla . folders . updateFolderPath . mutate ( {
47- folderId,
48- newPath : path ,
49- } ) ;
50- } ,
51- onSuccess : async ( _ , newPath ) => {
52- await loadFolders ( ) ;
53- queryClient . invalidateQueries ( { queryKey : [ "folders" ] } ) ;
54- setError ( null ) ;
55-
56- if ( folderId ) {
57- const { workspaces, updateWorkspace } = useWorkspaceStore . getState ( ) ;
58- for ( const [ taskId , workspace ] of Object . entries ( workspaces ) ) {
59- if ( workspace . folderId === folderId ) {
60- updateWorkspace ( taskId , { ...workspace , folderPath : newPath } ) ;
61- }
62- }
63- await useWorkspaceStore . getState ( ) . loadWorkspaces ( ) ;
64- }
65- } ,
66- onError : ( err ) => {
67- log . error ( "Failed to update folder path:" , err ) ;
68- setError ( err instanceof Error ? err . message : "Failed to update path" ) ;
69- } ,
70- } ) ;
71-
72- const handlePathChange = async ( path : string ) => {
73- setNewPath ( path ) ;
74- if ( folder && ! folder . exists && path !== folder . path ) {
75- await updatePathMutation . mutateAsync ( path ) ;
76- }
77- } ;
78-
79- const handleUpdatePath = async ( ) => {
80- if ( ! newPath || newPath === folder ?. path ) return ;
81- await updatePathMutation . mutateAsync ( newPath ) ;
82- } ;
83-
8431 const handleRemoveFolder = async ( ) => {
8532 if ( ! folderId ) return ;
8633 try {
@@ -107,75 +54,112 @@ export function FolderSettingsView() {
10754 ) ;
10855 }
10956
110- return (
111- < Box height = "100%" overflowY = "auto" >
112- < Box p = "6" style = { { maxWidth : "600px" , margin : "0 auto" } } >
113- < Flex direction = "column" gap = "6" >
114- < Flex direction = "column" gap = "2" >
115- < Heading size = "4" > Repository Settings</ Heading >
116- < Text size = "1" color = "gray" >
117- Manage settings for { folder . name }
118- </ Text >
119- </ Flex >
57+ // When folder doesn't exist, show message to restore or remove
58+ if ( ! folder . exists ) {
59+ return (
60+ < Box height = "100%" overflowY = "auto" >
61+ < Box p = "6" style = { { maxWidth : "600px" , margin : "0 auto" } } >
62+ < Flex direction = "column" gap = "6" >
63+ < Flex direction = "column" gap = "2" >
64+ < Heading size = "4" > Repository Not Found</ Heading >
65+ < Text size = "1" color = "gray" >
66+ { folder . name }
67+ </ Text >
68+ </ Flex >
12069
121- { ! folder . exists && (
12270 < Callout . Root color = "amber" >
12371 < Callout . Icon >
12472 < Warning />
12573 </ Callout . Icon >
12674 < Callout . Text >
12775 < Flex direction = "column" gap = "1" >
12876 < Text weight = "medium" >
129- Repository path needs to be updated
77+ The repository folder could not be found
13078 </ Text >
13179 < Text size = "1" >
132- The folder at "{ folder . path } " was not found. If you moved
133- this repository, select the new location below to continue
134- working on tasks in this repository.
80+ The folder at < Code > { folder . path } </ Code > no longer exists or
81+ has been moved.
13582 </ Text >
13683 </ Flex >
13784 </ Callout . Text >
13885 </ Callout . Root >
139- ) }
14086
141- { error && (
142- < Callout . Root color = "red" >
143- < Callout . Text > { error } </ Callout . Text >
144- </ Callout . Root >
145- ) }
87+ { error && (
88+ < Callout . Root color = "red" >
89+ < Callout . Text > { error } </ Callout . Text >
90+ </ Callout . Root >
91+ ) }
14692
147- < Flex direction = "column" gap = "3" >
148- < Heading size = "3" > Location</ Heading >
14993 < Card >
15094 < Flex direction = "column" gap = "4" >
15195 < Flex direction = "column" gap = "2" >
15296 < Text size = "1" weight = "medium" >
153- Root path
97+ Option 1: Restore the folder
15498 </ Text >
155- < FolderPicker
156- value = { newPath }
157- onChange = { handlePathChange }
158- placeholder = { folder . path }
159- size = "1"
160- skipRegister
161- />
16299 < Text size = "1" color = "gray" >
163- The main repository directory
100+ Move or restore the repository folder back to its original
101+ location:
102+ </ Text >
103+ < Code size = "1" > { folder . path } </ Code >
104+ </ Flex >
105+ </ Flex >
106+ </ Card >
107+
108+ < Card >
109+ < Flex direction = "column" gap = "4" >
110+ < Flex direction = "column" gap = "2" >
111+ < Text size = "1" weight = "medium" >
112+ Option 2: Remove the repository
113+ </ Text >
114+ < Text size = "1" color = "gray" >
115+ This will remove the repository from Array, including all
116+ associated tasks and their workspaces. This action cannot be
117+ undone.
164118 </ Text >
165119 </ Flex >
166- { newPath && newPath !== folder . path && folder . exists && (
167- < Button
168- variant = "classic"
169- size = "1"
170- onClick = { handleUpdatePath }
171- disabled = { updatePathMutation . isPending }
172- style = { { alignSelf : "flex-start" } }
173- >
174- { updatePathMutation . isPending
175- ? "Updating..."
176- : "Update path" }
177- </ Button >
178- ) }
120+ < Button
121+ variant = "soft"
122+ color = "red"
123+ size = "1"
124+ onClick = { handleRemoveFolder }
125+ style = { { alignSelf : "flex-start" } }
126+ >
127+ Remove repository
128+ </ Button >
129+ </ Flex >
130+ </ Card >
131+ </ Flex >
132+ </ Box >
133+ </ Box >
134+ ) ;
135+ }
136+
137+ // Normal settings view when folder exists
138+ return (
139+ < Box height = "100%" overflowY = "auto" >
140+ < Box p = "6" style = { { maxWidth : "600px" , margin : "0 auto" } } >
141+ < Flex direction = "column" gap = "6" >
142+ < Flex direction = "column" gap = "2" >
143+ < Heading size = "4" > Repository Settings</ Heading >
144+ < Text size = "1" color = "gray" >
145+ Manage settings for { folder . name }
146+ </ Text >
147+ </ Flex >
148+
149+ { error && (
150+ < Callout . Root color = "red" >
151+ < Callout . Text > { error } </ Callout . Text >
152+ </ Callout . Root >
153+ ) }
154+
155+ < Flex direction = "column" gap = "3" >
156+ < Heading size = "3" > Location</ Heading >
157+ < Card >
158+ < Flex direction = "column" gap = "2" >
159+ < Text size = "1" weight = "medium" >
160+ Root path
161+ </ Text >
162+ < Code size = "1" > { folder . path } </ Code >
179163 </ Flex >
180164 </ Card >
181165 </ Flex >
0 commit comments