native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #169 from supabitapp/jolly-shark-210

O(1) look up of worktree using IdentifiedArrayOf

authored by

khoi and committed by
GitHub
f01afb56 018bc336

+91 -105
+2 -1
supacode/Domain/Repository.swift
··· 1 1 import Foundation 2 + import IdentifiedCollections 2 3 3 4 struct Repository: Identifiable, Hashable, Sendable { 4 5 let id: String 5 6 let rootURL: URL 6 7 let name: String 7 - let worktrees: [Worktree] 8 + let worktrees: IdentifiedArrayOf<Worktree> 8 9 9 10 var initials: String { 10 11 Self.initials(from: name)
+2 -2
supacode/Features/App/Reducer/AppFeature.swift
··· 32 32 } 33 33 } 34 34 35 - enum Action: Equatable { 35 + enum Action { 36 36 case task 37 37 case scenePhaseChanged(ScenePhase) 38 38 case repositories(RepositoriesFeature.Action) ··· 177 177 case .settings(.setSelection(let selection)): 178 178 switch selection { 179 179 case .repository(let repositoryID): 180 - guard let repository = state.repositories.repositories.first(where: { $0.id == repositoryID }) else { 180 + guard let repository = state.repositories.repositories[id: repositoryID] else { 181 181 state.settings.repositorySettings = nil 182 182 return .none 183 183 }
+39 -36
supacode/Features/Repositories/Reducer/RepositoriesFeature.swift
··· 1 1 import ComposableArchitecture 2 2 import Foundation 3 + import IdentifiedCollections 3 4 import SwiftUI 4 5 5 6 private enum CancelID { ··· 10 11 struct RepositoriesFeature { 11 12 @ObservableState 12 13 struct State: Equatable { 13 - var repositories: [Repository] = [] 14 + var repositories: IdentifiedArrayOf<Repository> = [] 14 15 var repositoryRoots: [URL] = [] 15 16 var loadFailuresByID: [Repository.ID: String] = [:] 16 17 var selectedWorktreeID: Worktree.ID? ··· 29 30 @Presents var alert: AlertState<Alert>? 30 31 } 31 32 32 - enum Action: Equatable { 33 + enum Action { 33 34 case task 34 35 case setOpenPanelPresented(Bool) 35 36 case loadPersistedRepositories ··· 98 99 case confirmRemoveRepository(Repository.ID) 99 100 } 100 101 102 + @CasePathable 101 103 enum Delegate: Equatable { 102 104 case selectedWorktreeChanged(Worktree?) 103 - case repositoriesChanged([Repository]) 105 + case repositoriesChanged(IdentifiedArrayOf<Repository>) 104 106 case openRepositorySettings(Repository.ID) 105 107 } 106 108 ··· 110 112 @Dependency(\.repositoryPersistence) private var repositoryPersistence 111 113 @Dependency(\.repositorySettingsClient) private var repositorySettingsClient 112 114 @Dependency(\.settingsClient) private var settingsClient 115 + @Dependency(\.uuid) private var uuid 113 116 114 117 var body: some Reducer<State, Action> { 115 118 Reduce { state, action in ··· 166 169 case .repositoriesLoaded(let repositories, let failures, let roots, let animated): 167 170 let previousSelection = state.selectedWorktreeID 168 171 let previousSelectedWorktree = state.worktree(for: previousSelection) 169 - let mergedRepositories = repositories 170 172 let didPrunePinned = applyRepositories( 171 - mergedRepositories, 173 + repositories, 172 174 state: &state, 173 175 animated: animated 174 176 ) ··· 180 182 let selectedWorktree = state.worktree(for: state.selectedWorktreeID) 181 183 let selectionChanged = previousSelectedWorktree != selectedWorktree 182 184 var allEffects: [Effect<Action>] = [ 183 - .send(.delegate(.repositoriesChanged(mergedRepositories))) 185 + .send(.delegate(.repositoriesChanged(state.repositories))) 184 186 ] 185 187 if selectionChanged { 186 188 allEffects.append(.send(.delegate(.selectedWorktreeChanged(selectedWorktree)))) ··· 230 232 case .openRepositoriesFinished(let repositories, let failures, let invalidRoots, let roots): 231 233 let previousSelection = state.selectedWorktreeID 232 234 let previousSelectedWorktree = state.worktree(for: previousSelection) 233 - let mergedRepositories = repositories 234 235 let didPrunePinned = applyRepositories( 235 - mergedRepositories, 236 + repositories, 236 237 state: &state, 237 238 animated: false 238 239 ) ··· 251 252 let selectedWorktree = state.worktree(for: state.selectedWorktreeID) 252 253 let selectionChanged = previousSelectedWorktree != selectedWorktree 253 254 var allEffects: [Effect<Action>] = [ 254 - .send(.delegate(.repositoriesChanged(mergedRepositories))) 255 + .send(.delegate(.repositoriesChanged(state.repositories))) 255 256 ] 256 257 if selectionChanged { 257 258 allEffects.append(.send(.delegate(.selectedWorktreeChanged(selectedWorktree)))) ··· 320 321 return .send(.createRandomWorktreeInRepository(repository.id)) 321 322 322 323 case .createRandomWorktreeInRepository(let repositoryID): 323 - guard let repository = state.repositories.first(where: { $0.id == repositoryID }) else { 324 + guard let repository = state.repositories[id: repositoryID] else { 324 325 state.alert = errorAlert( 325 326 title: "Unable to create worktree", 326 327 message: "Unable to resolve a repository for the new worktree." ··· 335 336 return .none 336 337 } 337 338 let previousSelection = state.selectedWorktreeID 338 - let pendingID = "pending:\(UUID().uuidString)" 339 + let pendingID = "pending:\(uuid().uuidString)" 339 340 let repositorySettings = repositorySettingsClient.load(repository.rootURL) 340 341 let selectedBaseRef = repositorySettings.worktreeBaseRef 341 342 state.pendingWorktrees.append( ··· 445 446 if state.removingRepositoryIDs.contains(repositoryID) { 446 447 return .none 447 448 } 448 - guard let repository = state.repositories.first(where: { $0.id == repositoryID }), 449 - let worktree = repository.worktrees.first(where: { $0.id == worktreeID }) 449 + guard let repository = state.repositories[id: repositoryID], 450 + let worktree = repository.worktrees[id: worktreeID] 450 451 else { 451 452 return .none 452 453 } ··· 473 474 let repositoryID, 474 475 let deleteBranchOnArchive 475 476 ): 476 - guard let repository = state.repositories.first(where: { $0.id == repositoryID }), 477 - let worktree = repository.worktrees.first(where: { $0.id == worktreeID }) 477 + guard let repository = state.repositories[id: repositoryID], 478 + let worktree = repository.worktrees[id: worktreeID] 478 479 else { 479 480 return .none 480 481 } ··· 503 504 return .send(.removeWorktreeConfirmed(worktreeID, repositoryID)) 504 505 505 506 case .removeWorktreeConfirmed(let worktreeID, let repositoryID): 506 - guard let repository = state.repositories.first(where: { $0.id == repositoryID }), 507 - let worktree = repository.worktrees.first(where: { $0.id == worktreeID }) 507 + guard let repository = state.repositories[id: repositoryID], 508 + let worktree = repository.worktrees[id: worktreeID] 508 509 else { 509 510 return .none 510 511 } ··· 621 622 .cancellable(id: CancelID.load, cancelInFlight: true) 622 623 623 624 case .alert(.presented(.confirmRemoveRepository(let repositoryID))): 624 - guard let repository = state.repositories.first(where: { $0.id == repositoryID }) else { 625 + guard let repository = state.repositories[id: repositoryID] else { 625 626 return .none 626 627 } 627 628 if state.removingRepositoryIDs.contains(repository.id) { ··· 845 846 id: rootID, 846 847 rootURL: normalizedRoot, 847 848 name: name, 848 - worktrees: worktrees 849 + worktrees: IdentifiedArray(uniqueElements: worktrees) 849 850 ) 850 851 loaded.append(repository) 851 852 } catch { ··· 892 893 let filteredWorktreeInfo = state.worktreeInfoByID.filter { 893 894 availableWorktreeIDs.contains($0.key) 894 895 } 896 + let identifiedRepositories = IdentifiedArray(uniqueElements: repositories) 895 897 if animated { 896 898 withAnimation { 897 - state.repositories = repositories 899 + state.repositories = identifiedRepositories 898 900 state.pendingWorktrees = filteredPendingWorktrees 899 901 state.deletingWorktreeIDs = filteredDeletingIDs 900 902 state.pendingSetupScriptWorktreeIDs = filteredSetupScriptIDs ··· 902 904 state.worktreeInfoByID = filteredWorktreeInfo 903 905 } 904 906 } else { 905 - state.repositories = repositories 907 + state.repositories = identifiedRepositories 906 908 state.pendingWorktrees = filteredPendingWorktrees 907 909 state.deletingWorktreeIDs = filteredDeletingIDs 908 910 state.pendingSetupScriptWorktreeIDs = filteredSetupScriptIDs ··· 944 946 repositoryID: Repository.ID, 945 947 state: State 946 948 ) -> AlertState<Alert>? { 947 - guard let repository = state.repositories.first(where: { $0.id == repositoryID }) else { 949 + guard let repository = state.repositories[id: repositoryID] else { 948 950 return nil 949 951 } 950 952 return AlertState { ··· 983 985 func worktree(for id: Worktree.ID?) -> Worktree? { 984 986 guard let id else { return nil } 985 987 for repository in repositories { 986 - if let worktree = repository.worktrees.first(where: { $0.id == id }) { 988 + if let worktree = repository.worktrees[id: id] { 987 989 return worktree 988 990 } 989 991 } ··· 1017 1019 ) 1018 1020 } 1019 1021 for repository in repositories { 1020 - if let worktree = repository.worktrees.first(where: { $0.id == id }) { 1022 + if let worktree = repository.worktrees[id: id] { 1021 1023 let isDeleting = 1022 1024 removingRepositoryIDs.contains(repository.id) 1023 1025 || deletingWorktreeIDs.contains(worktree.id) ··· 1039 1041 } 1040 1042 1041 1043 func repositoryName(for id: Repository.ID) -> String? { 1042 - repositories.first(where: { $0.id == id })?.name 1044 + repositories[id: id]?.name 1043 1045 } 1044 1046 1045 1047 func repositoryID(for worktreeID: Worktree.ID?) -> Repository.ID? { ··· 1188 1190 repositoryID: Repository.ID, 1189 1191 state: inout RepositoriesFeature.State 1190 1192 ) { 1191 - guard let index = state.repositories.firstIndex(where: { $0.id == repositoryID }) else { return } 1193 + guard let index = state.repositories.index(id: repositoryID) else { return } 1192 1194 let repository = state.repositories[index] 1193 - if repository.worktrees.contains(where: { $0.id == worktree.id }) { 1195 + if repository.worktrees[id: worktree.id] != nil { 1194 1196 return 1195 1197 } 1196 1198 var worktrees = repository.worktrees ··· 1209 1211 repositoryID: Repository.ID, 1210 1212 state: inout RepositoriesFeature.State 1211 1213 ) -> Bool { 1212 - guard let index = state.repositories.firstIndex(where: { $0.id == repositoryID }) else { return false } 1214 + guard let index = state.repositories.index(id: repositoryID) else { return false } 1213 1215 let repository = state.repositories[index] 1214 - let filteredWorktrees = repository.worktrees.filter { $0.id != worktreeID } 1215 - guard filteredWorktrees.count != repository.worktrees.count else { return false } 1216 + guard repository.worktrees[id: worktreeID] != nil else { return false } 1217 + var worktrees = repository.worktrees 1218 + worktrees.remove(id: worktreeID) 1216 1219 state.repositories[index] = Repository( 1217 1220 id: repository.id, 1218 1221 rootURL: repository.rootURL, 1219 1222 name: repository.name, 1220 - worktrees: filteredWorktrees 1223 + worktrees: worktrees 1221 1224 ) 1222 1225 return true 1223 1226 } ··· 1229 1232 ) { 1230 1233 for index in state.repositories.indices { 1231 1234 var repository = state.repositories[index] 1232 - guard let worktreeIndex = repository.worktrees.firstIndex(where: { $0.id == worktreeID }) else { 1235 + guard let worktreeIndex = repository.worktrees.index(id: worktreeID) else { 1233 1236 continue 1234 1237 } 1235 1238 let worktree = repository.worktrees[worktreeIndex] ··· 1237 1240 return 1238 1241 } 1239 1242 var worktrees = repository.worktrees 1240 - worktrees[worktreeIndex] = Worktree( 1243 + worktrees[id: worktreeID] = Worktree( 1241 1244 id: worktree.id, 1242 1245 name: name, 1243 1246 detail: worktree.detail, ··· 1315 1318 ) -> Repository? { 1316 1319 if let selectedWorktreeID = state.selectedWorktreeID { 1317 1320 if let pending = state.pendingWorktree(for: selectedWorktreeID) { 1318 - return state.repositories.first(where: { $0.id == pending.repositoryID }) 1321 + return state.repositories[id: pending.repositoryID] 1319 1322 } 1320 1323 for repository in state.repositories 1321 - where repository.worktrees.contains(where: { $0.id == selectedWorktreeID }) { 1324 + where repository.worktrees[id: selectedWorktreeID] != nil { 1322 1325 return repository 1323 1326 } 1324 1327 } ··· 1359 1362 in repositoryID: Repository.ID, 1360 1363 state: RepositoriesFeature.State 1361 1364 ) -> Worktree.ID? { 1362 - guard let repository = state.repositories.first(where: { $0.id == repositoryID }) else { 1365 + guard let repository = state.repositories[id: repositoryID] else { 1363 1366 return nil 1364 1367 } 1365 1368 return state.orderedWorktrees(in: repository).first?.id
+2 -1
supacode/Features/RepositorySettings/Reducer/RepositorySettingsFeature.swift
··· 13 13 var isBranchDataLoaded = false 14 14 } 15 15 16 - enum Action: Equatable { 16 + enum Action { 17 17 case task 18 18 case settingsLoaded(RepositorySettings, isBareRepository: Bool) 19 19 case branchDataLoaded([String], defaultBaseRef: String) ··· 25 25 case delegate(Delegate) 26 26 } 27 27 28 + @CasePathable 28 29 enum Delegate: Equatable { 29 30 case settingsChanged(URL) 30 31 }
+2 -1
supacode/Features/Settings/Reducer/SettingsFeature.swift
··· 41 41 } 42 42 } 43 43 44 - enum Action: Equatable { 44 + enum Action { 45 45 case task 46 46 case settingsLoaded(GlobalSettings) 47 47 case setAppearanceMode(AppearanceMode) ··· 57 57 case delegate(Delegate) 58 58 } 59 59 60 + @CasePathable 60 61 enum Delegate: Equatable { 61 62 case settingsChanged(GlobalSettings) 62 63 }
+1 -1
supacode/Features/Settings/Views/SettingsView.swift
··· 86 86 .navigationSubtitle("GitHub CLI integration") 87 87 } 88 88 case .repository(let repositoryID): 89 - if let repository = repositories.first(where: { $0.id == repositoryID }) { 89 + if let repository = repositories[id: repositoryID] { 90 90 SettingsDetailView { 91 91 IfLetStore( 92 92 settingsStore.scope(state: \.repositorySettings, action: \.repositorySettings)
+1 -1
supacode/Features/Updates/Reducer/UpdatesFeature.swift
··· 7 7 var didConfigureUpdates = false 8 8 } 9 9 10 - enum Action: Equatable { 10 + enum Action { 11 11 case applySettings( 12 12 automaticallyChecks: Bool, 13 13 automaticallyDownloads: Bool
+6 -3
supacodeTests/AppFeatureTerminalSetupScriptTests.swift
··· 1 1 import ComposableArchitecture 2 2 import DependenciesTestSupport 3 3 import Foundation 4 + import IdentifiedCollections 4 5 import Testing 5 6 6 7 @testable import supacode ··· 21 22 name: "repo", 22 23 worktrees: [worktree] 23 24 ) 24 - var repositoriesState = RepositoriesFeature.State(repositories: [repository]) 25 + var repositoriesState = RepositoriesFeature.State() 26 + repositoriesState.repositories = [repository] 25 27 repositoriesState.selectedWorktreeID = worktree.id 26 28 repositoriesState.pendingSetupScriptWorktreeIDs = [worktree.id] 27 29 let sent = LockIsolated<[TerminalClient.Command]>([]) ··· 39 41 } 40 42 41 43 await store.send(.newTerminal) 42 - await store.receive(.repositories(.consumeSetupScript(worktree.id))) { 44 + await store.receive(\.repositories.consumeSetupScript) { 43 45 $0.repositories.pendingSetupScriptWorktreeIDs.remove(worktree.id) 44 46 } 45 47 await store.finish() ··· 60 62 name: "repo", 61 63 worktrees: [worktree] 62 64 ) 63 - var repositoriesState = RepositoriesFeature.State(repositories: [repository]) 65 + var repositoriesState = RepositoriesFeature.State() 66 + repositoriesState.repositories = [repository] 64 67 repositoriesState.selectedWorktreeID = worktree.id 65 68 let sent = LockIsolated<[TerminalClient.Command]>([]) 66 69 let store = TestStore(
+5 -5
supacodeTests/RepositoriesFeaturePersistenceTests.swift
··· 23 23 } 24 24 25 25 await store.send(.task) 26 - await store.receive(.pinnedWorktreeIDsLoaded(pinned)) { 26 + await store.receive(\.pinnedWorktreeIDsLoaded) { 27 27 $0.pinnedWorktreeIDs = pinned 28 28 } 29 - await store.receive(.lastFocusedWorktreeIDLoaded(nil)) { 29 + await store.receive(\.lastFocusedWorktreeIDLoaded) { 30 30 $0.lastFocusedWorktreeID = nil 31 31 $0.shouldRestoreLastFocusedWorktree = true 32 32 } 33 - await store.receive(.loadPersistedRepositories) 34 - await store.receive(.repositoriesLoaded([], failures: [], roots: [], animated: false)) { 33 + await store.receive(\.loadPersistedRepositories) 34 + await store.receive(\.repositoriesLoaded) { 35 35 $0.repositories = [] 36 36 $0.pinnedWorktreeIDs = [] 37 37 $0.shouldRestoreLastFocusedWorktree = false 38 38 $0.isInitialLoadComplete = true 39 39 } 40 - await store.receive(.delegate(.repositoriesChanged([]))) 40 + await store.receive(\.delegate.repositoriesChanged) 41 41 await store.finish() 42 42 } 43 43 }
+27 -50
supacodeTests/RepositoriesFeatureTests.swift
··· 1 1 import ComposableArchitecture 2 + import CustomDump 2 3 import Foundation 4 + import IdentifiedCollections 3 5 import Testing 4 6 5 7 @testable import supacode ··· 16 18 await store.send(.selectWorktree(worktree.id)) { 17 19 $0.selectedWorktreeID = worktree.id 18 20 } 19 - await store.receive(.delegate(.selectedWorktreeChanged(worktree))) 21 + await store.receive(\.delegate.selectedWorktreeChanged) 20 22 } 21 23 22 24 @Test func createRandomWorktreeWithoutRepositoriesShowsAlert() async { ··· 60 62 } 61 63 62 64 await store.send(.requestRemoveWorktree(worktree.id, repository.id)) 63 - await store.receive( 64 - .presentWorktreeRemovalConfirmation( 65 - worktree.id, 66 - repository.id, 67 - deleteBranchOnArchive: true 68 - ) 69 - ) { 65 + await store.receive(\.presentWorktreeRemovalConfirmation) { 70 66 $0.alert = expectedAlert 71 67 } 72 68 } ··· 109 105 ) 110 106 let state = makeState(repositories: [repoA, repoB]) 111 107 112 - #expect( 113 - state.orderedWorktreeRows().map(\.id) == [ 108 + expectNoDifference( 109 + state.orderedWorktreeRows().map(\.id), 110 + [ 114 111 "/tmp/repo-a/wt1", 115 112 "/tmp/repo-a/wt2", 116 113 "/tmp/repo-b/wt3", ··· 137 134 $0.isInitialLoadComplete = true 138 135 } 139 136 140 - await store.receive(.delegate(.repositoriesChanged([]))) 137 + await store.receive(\.delegate.repositoriesChanged) 141 138 } 142 139 143 140 @Test func repositoriesLoadedUpdatesSelectedWorktreeDelegateOnChange() async { ··· 163 160 $0.repositories = [updatedRepository] 164 161 $0.isInitialLoadComplete = true 165 162 } 166 - await store.receive(.delegate(.repositoriesChanged([updatedRepository]))) 167 - await store.receive(.delegate(.selectedWorktreeChanged(updatedWorktree))) 163 + await store.receive(\.delegate.repositoriesChanged) 164 + await store.receive(\.delegate.selectedWorktreeChanged) 168 165 } 169 166 170 167 @Test func worktreeRemovedPrunesStateAndSendsDelegates() async { ··· 212 209 $0.worktreeInfoByID = [:] 213 210 $0.repositories = [updatedRepository] 214 211 } 215 - await store.receive(.delegate(.repositoriesChanged([updatedRepository]))) 216 - await store.receive(.reloadRepositories(animated: true)) 217 - await store.receive( 218 - .repositoriesLoaded( 219 - [updatedRepository], 220 - failures: [], 221 - roots: [repository.rootURL], 222 - animated: true 223 - ) 224 - ) { 212 + await store.receive(\.delegate.repositoriesChanged) 213 + await store.receive(\.reloadRepositories) 214 + await store.receive(\.repositoriesLoaded) { 225 215 $0.isInitialLoadComplete = true 226 216 } 227 - await store.receive(.delegate(.repositoriesChanged([updatedRepository]))) 217 + await store.receive(\.delegate.repositoriesChanged) 228 218 } 229 219 230 220 @Test func worktreeRemovedResetsSelectionWhenDriftedToDeletingWorktree() async { ··· 254 244 $0.repositories = [updatedRepository] 255 245 $0.selectedWorktreeID = mainWorktree.id 256 246 } 257 - await store.receive(.delegate(.repositoriesChanged([updatedRepository]))) 258 - await store.receive(.delegate(.selectedWorktreeChanged(mainWorktree))) 259 - await store.receive(.reloadRepositories(animated: true)) 260 - await store.receive( 261 - .repositoriesLoaded( 262 - [updatedRepository], 263 - failures: [], 264 - roots: [repository.rootURL], 265 - animated: true 266 - ) 267 - ) { 247 + await store.receive(\.delegate.repositoriesChanged) 248 + await store.receive(\.delegate.selectedWorktreeChanged) 249 + await store.receive(\.reloadRepositories) 250 + await store.receive(\.repositoriesLoaded) { 268 251 $0.isInitialLoadComplete = true 269 252 } 270 - await store.receive(.delegate(.repositoriesChanged([updatedRepository]))) 253 + await store.receive(\.delegate.repositoriesChanged) 271 254 } 272 255 273 256 @Test func createRandomWorktreeSucceededSendsRepositoriesChanged() async { ··· 307 290 $0.repositories = [updatedRepository] 308 291 } 309 292 310 - await store.receive(.reloadRepositories(animated: false)) 311 - await store.receive(.delegate(.repositoriesChanged([updatedRepository]))) 312 - await store.receive(.delegate(.selectedWorktreeChanged(newWorktree))) 313 - await store.receive( 314 - .repositoriesLoaded( 315 - [updatedRepository], 316 - failures: [], 317 - roots: [repository.rootURL], 318 - animated: false 319 - ) 320 - ) { 293 + await store.receive(\.reloadRepositories) 294 + await store.receive(\.delegate.repositoriesChanged) 295 + await store.receive(\.delegate.selectedWorktreeChanged) 296 + await store.receive(\.repositoriesLoaded) { 321 297 $0.isInitialLoadComplete = true 322 298 } 323 - await store.receive(.delegate(.repositoriesChanged([updatedRepository]))) 299 + await store.receive(\.delegate.repositoriesChanged) 324 300 } 325 301 326 302 private func makeWorktree(id: String, name: String, repoRoot: String = "/tmp/repo") -> Worktree { ··· 338 314 id: id, 339 315 rootURL: URL(fileURLWithPath: id), 340 316 name: "repo", 341 - worktrees: worktrees 317 + worktrees: IdentifiedArray(uniqueElements: worktrees) 342 318 ) 343 319 } 344 320 345 321 private func makeState(repositories: [Repository]) -> RepositoriesFeature.State { 346 - var state = RepositoriesFeature.State(repositories: repositories) 322 + var state = RepositoriesFeature.State() 323 + state.repositories = IdentifiedArray(uniqueElements: repositories) 347 324 state.repositoryRoots = repositories.map(\.rootURL) 348 325 return state 349 326 }
+4 -4
supacodeTests/SettingsFeatureTests.swift
··· 25 25 } 26 26 27 27 await store.send(.task) 28 - await store.receive(.settingsLoaded(loaded)) { 28 + await store.receive(\.settingsLoaded) { 29 29 $0.appearanceMode = .dark 30 30 $0.confirmBeforeQuit = true 31 31 $0.updatesAutomaticallyCheckForUpdates = false ··· 35 35 $0.githubIntegrationEnabled = true 36 36 $0.deleteBranchOnArchive = false 37 37 } 38 - await store.receive(.delegate(.settingsChanged(loaded))) 38 + await store.receive(\.delegate.settingsChanged) 39 39 } 40 40 41 41 @Test(.dependencies) func savesUpdatesChanges() async { ··· 74 74 githubIntegrationEnabled: initialSettings.githubIntegrationEnabled, 75 75 deleteBranchOnArchive: initialSettings.deleteBranchOnArchive 76 76 ) 77 - await store.receive(.delegate(.settingsChanged(expectedSettings))) 77 + await store.receive(\.delegate.settingsChanged) 78 78 79 79 await store.finish() 80 80 #expect(saved.value == expectedSettings) ··· 134 134 settings: .default 135 135 ) 136 136 } 137 - await store.receive(.delegate(.settingsChanged(loaded))) 137 + await store.receive(\.delegate.settingsChanged) 138 138 } 139 139 }