Skip to content

Conversation

@graycreate
Copy link
Member

Summary

Optimize the FeedDetailPage list loading to reduce visual jumping when content populates.

Changes

  • Add staged appearance for list sections:
    1. Content section appears first
    2. Postscripts appear after content is ready
    3. Reply section appears with 150ms delay after content
  • Add repliesReady state to control reply section visibility
  • Add smooth easeInOut animations for both states
  • Handle edge case when content is empty (show replies immediately)

How it works

The cascading load effect prevents all sections from appearing at once, which was causing jarring list jumps. Each section appears in sequence with a slight delay, creating a smoother user experience.

Test plan

  • Open a topic detail page with content and replies
  • Observe smooth, staged appearance of sections
  • Open a topic with no content body - verify replies appear immediately
  • Pull to refresh - verify smooth reload behavior

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings December 29, 2025 01:03
Use opacity animation instead of hiding/showing sections:
- Sections remain in layout (no height jumps)
- Fade in via opacity 0->1 when ready
- Postscripts fade in when content is ready
- Replies fade in 150ms after content
- Faster easeIn animation (0.15s)

This avoids layout recalculation and position jumping.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@graycreate graycreate force-pushed the feature/feed-detail-list-optimization branch from 4883212 to b2f6419 Compare December 29, 2025 01:04
@github-actions github-actions bot added size/M and removed size/S labels Dec 29, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes the FeedDetailPage to reduce visual jumping by implementing a staged loading approach for list sections. Content appears first, followed by postscripts, and then replies after a short delay.

Key Changes:

  • Added repliesReady state variable to control reply section visibility timing
  • Implemented cascading load effect with 150ms delay between content and replies
  • Added easeInOut animations for smooth transitions between states

Comment on lines 46 to +47
@State private var contentReady = false
@State private var repliesReady = false
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The state variables contentReady and repliesReady are not reset when new data is loaded. When a user pulls to refresh or when data is reloaded, these states remain true, preventing the staged appearance animation from running again. Consider adding an onChange handler that resets these states when state.model changes or when a refresh begins.

Copilot uses AI. Check for mistakes.
Comment on lines +212 to 216
DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
withAnimation(.easeInOut(duration: 0.2)) {
repliesReady = true
}
}
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DispatchQueue.main.asyncAfter closure captures self implicitly, which could lead to a retain cycle if the view is dismissed before the delay completes. Additionally, if the view is dismissed or refreshed before the 0.15 second delay completes, the delayed closure will still execute and set repliesReady = true on a potentially stale view. Consider using a weak self capture or canceling the delayed work when appropriate.

Copilot uses AI. Check for mistakes.
Comment on lines +280 to +281
.animation(.easeIn(duration: 0.15), value: contentReady)
.animation(.easeIn(duration: 0.15), value: repliesReady)
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The animation modifier is applied to the entire List based on contentReady and repliesReady state changes. This causes all changes to the List to be animated with easeInOut, not just the appearance of content and replies. This could lead to unintended animations for other state changes, such as when loading more replies or when the reply section header appears. Consider applying the animation only to the specific views that should be animated, or use a more targeted approach.

Suggested change
.animation(.easeIn(duration: 0.15), value: contentReady)
.animation(.easeIn(duration: 0.15), value: repliesReady)

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

Code Coverage Report ❌

Current coverage: 33.94%

@graycreate graycreate closed this Dec 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants