fix(BAL-211): fix game session duration not logged when app closed mid-game#212
Merged
sebastianricaldoni merged 4 commits intoJun 10, 2026
Merged
Conversation
- Add finalizeOpenActions() to close pending "Opened X" actions when app backgrounds, fixing zero-duration bug when app is killed mid-game - Move reset() logic to UIApplication.willEnterForegroundNotification observer on ActivityLogEntry (synchronous, fires before SwiftUI views) to avoid race condition with async saveLog on background - Add didBecomeActiveNotification handler in ActivityLogBaseView with isVisible guard to re-log current view on resume when onAppear does not fire reliably - Add Home view logging via ActivityLogBaseView wrapper - Add Encodable.toJSON() debug utility in BalanceExtensions - Fix WKCompanionAppBundleIdentifier for local device signing
…model Replace fragile "Opened X" / "Closed X" string-matching with a clean push(viewName:) + finalizePending() stack model: - push() finalizes previous pending entry then opens a new one - finalizePending() closes current entry with correct duration - onDisappear only finalizes if pendingEntry matches view (guards against forward-nav double-finalize since onAppear fires first) - ActivityLogEntry observes willEnterForegroundNotification directly (synchronous, before SwiftUI views) to guarantee reset fires before any onAppear on resume - ActivityLogBaseView uses didBecomeActiveNotification + isVisible guard to re-push current view when onAppear does not fire on resume - Home ActivityLogBaseView moved inside NavigationStack root so onAppear/onDisappear fire correctly on forward/back navigation - Rename actions → entries (CodingKeys maps to "actions" for backwards compatibility with existing user data) - addActionButton renamed to addButtonEvent for clarity - Coins eligibility extracted to Set<String> replacing long if-chain - ProfileView share buttons do fresh file load on tap (single source of truth); ShareLink replaced with Button + UIActivityViewController - SpotifyViewController updated to new push/finalizePending API
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #212 +/- ##
========================================
+ Coverage 5.06% 5.23% +0.18%
========================================
Files 130 130
Lines 2158 2142 -16
========================================
+ Hits 109 112 +3
+ Misses 2049 2030 -19
Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
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
onDisappearnever fires when user closes app mid-game — iOS keeps views mounted on background. Session duration stayed 0 seconds."Opened X"/"Closed X") to a cleanpush(viewName:)+finalizePending()stack model. App background triggersfinalizePending()via a synchronousUIApplication.willEnterForegroundNotificationobserver — guaranteed to fire before any SwiftUI view events.Changes
ActivityStorageManager— Newpush(viewName:)/finalizePending()API replacesaddAction/endLog/finalizeOpenActions.ActivityLogEntrynow owns its own reset logic viaNotificationCenterobserver.actionsrenamed toentriesinternally (JSON key preserved as"actions"for backwards compatibility with existing user data).ActivityLogBaseView— Uses new push/finalize API.onDisappearguards against double-finalize on forward navigation (childonAppearfires before parentonDisappearin NavigationStack). AddsdidBecomeActiveNotificationhandler as fallback for whenonAppeardoesn't fire on resume.Home—ActivityLogBaseView("Home")moved insideNavigationStackroot so SwiftUI correctly firesonAppear/onDisappearon forward/back navigation.ProfileView— Share buttons do fresh file load on tap (single source of truth).ShareLinkreplaced withButton+UIActivityViewControllerto avoid eager CSV computation on every render.SpotifyViewController— Updated to new API.BalanceExtensions— AddedEncodable.toJSON()debug utility (DEBUG only).Test plan
Closes #211
🤖 Generated with Claude Code