Back to Blocks

Claude Terminal

Loading...

Task Details
PXL-742Done
High

πŸ”„ Keep meal UI state in sync during background updates (checkboxes, chevrons, expand/collapse)

b2-herasyncui/ux

What we're fixing:

When you interact with meals throughout the day (checking off items, expanding/collapsing sections), the app syncs your data in the background with the cloud. During this sync process, multiple UI state issues can occur: nutrient totals at the top don't always update, chevron arrows can point the wrong direction, and meal sections can unexpectedly expand or collapse. This task ensures that all meal UI elementsβ€”checkboxes, chevrons, expanded/collapsed states, and nutrient totalsβ€”stay properly synchronized even when background syncing is happening.


Overview

We have three related issues that occur when interacting with meals while a sync is happening. These manifest as UI state getting out of sync with the underlying data model.


Issue 1: Nutrient amounts in expandable header not updating after sync βœ… PARTIALLY FIXED

Problem: When toggling logged states during a sync, the nutrient totals in the expandable day header at the top don't recalculate to match what's currently checked off when sync completes.

Fix Applied:

  • ●Added updateCircleState() call in DayViewController.updateVisibleCellsAnimated() at line 1405 to ensure logged state checkmarks update after sync
  • ●The expandable header already has proper logic to show consumed values via day.consumedValue(for:) when in log mode

Files Modified:

  • ●/Users/pxlshpr/Developer/NutriKit/DayViewController.swift:1404-1407 - Added updateCircleState() call

Issue 2 & 3: Chevron rotation and meal expanded/collapsed state desync βœ… FIXED (PENDING TESTING)

Problems Identified:

  1. ●Cell Reuse Desync: When table view cells were reused, logicallyCollapsed and intendedCollapsedState were reset to false in prepareForReuse(), but the chevron's visual rotation was NOT reset. When configure() was called on reused cells, it skipped chevron updates, leaving stale rotations.
  2. ●Sync Update Interference: During CloudKit sync, updateVisibleCellsAnimated() called headerCell.updateValues(), which intentionally didn't update the chevron to avoid interfering with animations. This meant sync-triggered state changes wouldn't update the chevron visual.
  3. ●Missing State Reconciliation: There was no mechanism to detect when the model's collapse state differed from the cell's internal state and correct it.

Implementation (2026-01-12):

File: MealHeaderTableViewCell.swift

  1. ●prepareForReuse() enhancement (lines 257-259):
    • ●Resets chevron to default rotation when cell is reused
    • ●Prevents carrying over stale rotation from previous meal
  2. ●New syncChevronWithModel() method (lines 1709-1742):
    • ●Determines model's collapse state from diary.collapsedMealIDs and day.collapsedMealIDs
    • ●Only updates if model state differs from internal state (prevents unnecessary updates)
    • ●Updates both logicallyCollapsed and intendedCollapsedState to match model
    • ●Supports animated or instant rotation updates
    • ●Updates menu button visibility to match collapse state
  3. ●configure() enhancement (lines 415-417):
    • ●Calls syncChevronWithModel() when cell is reconfigured after reuse
    • ●Ensures chevron matches new meal's collapse state immediately
  4. ●updateValues() enhancement (lines 694-699):
    • ●Syncs chevron during updateValues() calls (triggered by sync)
    • ●Safeguard: only syncs when NOT in the middle of a user-initiated toggle
    • ●Preserves user animation integrity while fixing sync-induced desync

How It Fixes The Issues:

  • β—βœ… Cell Reuse: Chevron transform properly resets and resyncs with new meal's state
  • β—βœ… Rapid Tapping: Protected because didTapHeader() sets intendedCollapsedState first, preventing syncChevronWithModel() from interfering during user animations
  • β—βœ… Sync Updates: Model state changes from CloudKit sync now properly update chevron rotation
  • β—βœ… State Consistency: Both visual (chevron rotation) and logical (internal state) stay synchronized with model
  • β—βœ… Menu Button: Menu button visibility also stays synchronized with collapse state

Build Status: βœ… Build succeeded with no compilation errors


Testing Required

1. Cell Reuse Testing

  • ● Scroll up and down through meal list to trigger cell reuse
  • ● Verify chevrons show correct rotation for each meal (expanded vs collapsed)
  • ● Verify no visual glitches or wrong orientations after scrolling

2. Rapid Tapping Testing

  • ● Rapidly tap meal headers (3-5 quick taps)
  • ● Verify chevron rotates correctly with each tap
  • ● Verify meal sections expand/collapse correctly with taps
  • ● Verify no desync between chevron rotation and actual section state

3. CloudKit Sync Testing

  • ● Expand/collapse several meals locally
  • ● Trigger background CloudKit sync while meals are in various states
  • ● Verify chevrons maintain correct rotation during sync
  • ● Verify meal sections maintain correct expanded/collapsed state during sync
  • ● Verify nutrient totals update correctly after sync completes

4. Cross-Device Sync Testing

  • ● Change collapse state of meals on Device A
  • ● Sync to cloud
  • ● Open same day on Device B
  • ● Verify chevrons show correct rotation matching Device A's state
  • ● Change state on Device B, sync, verify Device A updates correctly

5. Regression Testing

  • ● Test expand/collapse functionality works normally
  • ● Test haptic feedback still works
  • ● Test menu button appears/disappears correctly with collapse state
  • ● Test animations are smooth and not janky
  • ● Test "Past Midnight" label behavior not affected
  • ● Test circle checkmark visibility in log mode not affected

Technical Context

Component: Meal logging diary view with expandable/collapsible meal sections Framework: UIKit (UITableView with custom cells) State Management: Day model with meal items, CloudKit sync in background Animation: Chevron rotation animations tied to expand/collapse state

Why This Matters: This affects the core logging functionality where users check off meals throughout the day. UI state desyncs during CloudKit sync operations create confusion and poor UX, especially for users actively logging while syncing.


Acceptance Criteria
  • ● Nutrient totals in expandable header update correctly after sync completes (Issue 1)
  • ● Chevron rotation matches actual expand/collapse state of meal headers (Issue 2)
  • ● Rapid tapping on meal headers doesn't cause chevron state desync (Issue 2)
  • ● Meal expanded/collapsed state remains correct during and after background sync operations (Issue 3)
  • ● Chevron icon rotation stays in sync with meal state even when state changes during sync (Issue 3)
  • ● All testing scenarios pass without regressions
  • ● No regressions in meal header expand/collapse behavior

Build instruction: Use -destination 'platform=iOS Simulator,name=iPhone 17 Pro' when building this project

Created Dec 15, 2025, 5:40 PM | Updated Jan 30, 2026, 12:29 PM