fix: cancelVerification spinner, silent scan-persist, KeeperSheet reveal errors, indentation#109
Merged
Merged
Conversation
…rsist, reveal errors - cancelVerification(forGroupID:) now immediately removes the group from verifyingGroupIDs, verifyTasksByID, and verifyCancellationsByID so the spinner clears the moment the user cancels, rather than waiting for the task's deferred MainActor.run block to run. - Scan-time hash-cache persist failures now surface through errorMessage. The post-scan Task.detached now calls persistThrowing() and routes any write failure to the main actor, matching the behaviour already present in OnDemandVerificationStore.persistAsync. - KeeperComparisonSheet: add onRevealError callback so reveal/revealAll failures are passed back to the caller (DuplicateCandidatesView routes them to ScanStore.errorMessage). Previously both results were discarded with _ = and the user got no feedback when a file had been moved/deleted. - Fix three indentation regressions (column-0 statements) in ScanStore, DuplicateHashCache, and FileSystemScanner left by earlier diff hunks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… store over callback - cancelVerification(forGroupID:): use removeValue(forKey:) which returns the removed value, collapsing 3 dict hash/probe operations per dict to 1 and eliminating the separate wasActive nil-check pass. - ScanStore.scan(_:) catch block: hoist error.localizedDescription to `desc` so the os_signpost call and the errorMessage string share one evaluation. Same fix in OnDemandVerificationStore.persistAsync where `errorMessage` was already hoisted but then error.localizedDescription was called again on the reportError line anyway. - KeeperComparisonSheet: replace onRevealError: (String) -> Void with @ObservedObject var store: ScanStore, matching every other view in the codebase. The sheet now writes store.errorMessage directly instead of routing a string through a callback that every future caller must wire. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cancelVerification(forGroupID:)leaves spinner active — the method cancelled the Swift Task andScanCancellationbut never removed the group fromverifyingGroupIDs. The spinner stayed visible until the task's deferredMainActor.runblock eventually ran. Fix: remove the group from all three tracking dicts immediately at the call site.Scan-time hash-cache persist failures are silent — the post-scan
Task.detachedcalledpersist()(which swallows errors viatry?). Disk-full or permission-denied failures reached onlyos_log;errorMessagewas never set. Fix: switch topersistThrowing()and route failures toerrorMessage, matching the pattern already used inOnDemandVerificationStore.persistAsync.KeeperComparisonSheetdrops reveal/revealAll errors — both calls used_ =and the sheet had no way to route errors back toScanStore. Fix: addonRevealError: (String) -> Voidparameter;DuplicateCandidatesViewpasses{ store.errorMessage = $0 }.Indentation regressions — three column-0 statements (
errorMessage = …inScanStore,let data: DatainDuplicateHashCache,Array(items.sorted …inFileSystemScanner) left by earlier diff hunks. No runtime impact; fixed for consistency.Test plan
swift build— clean, no warningsswift test— 172 tests, all greenerrorMessagefires after scan completes🤖 Generated with Claude Code