@@ -41,6 +41,7 @@ struct ContentView: View {
4141 @AppStorage ( " selectedWorkspaceId " ) private var selectedWorkspaceId : String ?
4242 @AppStorage ( " selectedRepositoryId " ) private var selectedRepositoryId : String ?
4343 @AppStorage ( " selectedWorktreeId " ) private var selectedWorktreeId : String ?
44+ @AppStorage ( " selectedWorktreeByRepository " ) private var selectedWorktreeByRepositoryData : String = " {} "
4445
4546 init ( context: NSManagedObjectContext , repositoryManager: RepositoryManager , gitChangesContext: Binding < GitChangesContext ? > ) {
4647 self . repositoryManager = repositoryManager
@@ -98,6 +99,7 @@ struct ContentView: View {
9899 selectedWorktree = nextWorktree
99100 }
100101 )
102+ . id ( worktree. id)
101103 } else {
102104 placeholderView (
103105 titleKey: " contentView.selectWorktree " ,
@@ -142,13 +144,24 @@ struct ContentView: View {
142144 selectedRepository = repositories. first ( where: { $0. id == uuid } )
143145 }
144146
145- // Restore selected worktree from persistent storage
146- if selectedWorktree == nil ,
147- let worktreeId = selectedWorktreeId,
148- let uuid = UUID ( uuidString: worktreeId) ,
149- let repository = selectedRepository {
147+ // Restore selected worktree from repository-specific storage first.
148+ if selectedWorktree == nil , let repository = selectedRepository {
150149 let worktrees = ( repository. worktrees as? Set < Worktree > ) ?? [ ]
151- selectedWorktree = worktrees. first ( where: { $0. id == uuid } )
150+ if let restoredWorktreeId = getStoredWorktreeId ( for: repository) {
151+ selectedWorktree = worktrees. first ( where: { $0. id == restoredWorktreeId && !$0. isDeleted } )
152+ }
153+
154+ // Fallback to global selection if repository-specific value is missing.
155+ if selectedWorktree == nil ,
156+ let worktreeId = selectedWorktreeId,
157+ let uuid = UUID ( uuidString: worktreeId) {
158+ selectedWorktree = worktrees. first ( where: { $0. id == uuid && !$0. isDeleted } )
159+ }
160+
161+ if selectedWorktree == nil {
162+ let candidates = worktrees. filter { !$0. isDeleted }
163+ selectedWorktree = candidates. first ( where: { $0. isPrimary } ) ?? candidates. first
164+ }
152165 }
153166
154167 if !hasShownOnboarding {
@@ -191,16 +204,25 @@ struct ContentView: View {
191204 }
192205 }
193206
194- // Auto-select primary worktree when repository changes
207+ // Restore previously selected worktree for this repository.
195208 let worktrees = ( repo. worktrees as? Set < Worktree > ) ?? [ ]
196- selectedWorktree = worktrees. first ( where: { $0. isPrimary } )
209+ if let restoredWorktreeId = getStoredWorktreeId ( for: repo) ,
210+ let restoredWorktree = worktrees. first ( where: { $0. id == restoredWorktreeId && !$0. isDeleted } ) {
211+ selectedWorktree = restoredWorktree
212+ } else {
213+ let candidates = worktrees. filter { !$0. isDeleted }
214+ selectedWorktree = candidates. first ( where: { $0. isPrimary } ) ?? candidates. first
215+ }
197216 }
198217 }
199218 . onChange ( of: selectedWorktree) { _, newValue in
200219 selectedWorktreeId = newValue? . id? . uuidString
201220
202221 if let newWorktree = newValue, !newWorktree. isDeleted {
203222 previousWorktree = newWorktree
223+ if let repository = selectedRepository {
224+ storeWorktreeSelection ( newWorktree. id, for: repository)
225+ }
204226 // Update worktree access asynchronously to avoid blocking UI
205227 Task { @MainActor in
206228 try ? repositoryManager. updateWorktreeAccess ( newWorktree)
@@ -283,6 +305,40 @@ struct ContentView: View {
283305 controller. showWindow ( nil )
284306 }
285307
308+ private func decodeSelectedWorktreeByRepository( ) -> [ String : String ] {
309+ guard let data = selectedWorktreeByRepositoryData. data ( using: . utf8) ,
310+ let decoded = try ? JSONDecoder ( ) . decode ( [ String : String ] . self, from: data) else {
311+ return [ : ]
312+ }
313+ return decoded
314+ }
315+
316+ private func encodeSelectedWorktreeByRepository( _ map: [ String : String ] ) {
317+ guard let encoded = try ? JSONEncoder ( ) . encode ( map) ,
318+ let json = String ( data: encoded, encoding: . utf8) else {
319+ return
320+ }
321+ selectedWorktreeByRepositoryData = json
322+ }
323+
324+ private func getStoredWorktreeId( for repository: Repository ) -> UUID ? {
325+ guard let repositoryId = repository. id? . uuidString else { return nil }
326+ let map = decodeSelectedWorktreeByRepository ( )
327+ guard let worktreeIdString = map [ repositoryId] else { return nil }
328+ return UUID ( uuidString: worktreeIdString)
329+ }
330+
331+ private func storeWorktreeSelection( _ worktreeId: UUID ? , for repository: Repository ) {
332+ guard let repositoryId = repository. id? . uuidString else { return }
333+ var map = decodeSelectedWorktreeByRepository ( )
334+ if let worktreeId {
335+ map [ repositoryId] = worktreeId. uuidString
336+ } else {
337+ map. removeValue ( forKey: repositoryId)
338+ }
339+ encodeSelectedWorktreeByRepository ( map)
340+ }
341+
286342 private func quickSwitchToPreviousWorktree( ) {
287343 let request : NSFetchRequest < Worktree > = Worktree . fetchRequest ( )
288344 request. sortDescriptors = [ NSSortDescriptor ( keyPath: \Worktree . lastAccessed, ascending: false ) ]
0 commit comments