-
Notifications
You must be signed in to change notification settings - Fork 45
Add immersive mode for posts view #1216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Implements a new immersive reading experience that automatically hides the navigation bar and toolbar when scrolling down, and shows them when scrolling up. Features: • Toggle available in main settings and posts settings • Velocity-based transitions (0.5 threshold) • Automatic bar reveal when near top/bottom of content • Gradient overlay for improved status bar readability • Seamless light/dark theme integration • Smooth 0.25s animations with proper layout updates Files modified: • AwfulSettings: Added immersionModeEnabled setting • AwfulSettingsUI: Added settings toggles and localization • PostsPageView: Core scroll handling and UI hiding logic • PostsPageViewController: Navigation bar integration • PostsPageSettingsViewController: In-page settings toggle
nolanw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice! got a few nits but overall looking fine
| .store(in: &cancellables) | ||
|
|
||
| $immersionModeEnabled | ||
| .receive(on: RunLoop.main) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will delay updates while scrolling until after scrolling completes, is that intentional? It kinda makes sense to me so I'm ok with it, but a comment would be good. (Usually receiving on the main run loop is not what people want.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I double checked with Claude and it seemed pretty sure that this was preferable. So it added a comment as suggested
| } | ||
| } | ||
| return nil | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get it, why don't we have an outlet or property with the stack view handy?
| // Create immersion mode switch | ||
| immersionModeSwitch = UISwitch() | ||
| immersionModeSwitch.isOn = immersionModeEnabled // Set initial state | ||
| immersionModeSwitch.onTintColor = theme["settingsSwitchColor"] // Apply theme color |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should (re)set this in themeDidChange.
| scrollViewDelegateMux = ScrollViewDelegateMultiplexer(scrollView: renderView.scrollView) | ||
| scrollViewDelegateMux?.addDelegate(self) | ||
|
|
||
| // Configure initial gradient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep that's what the next line says!
| height: gradientHeight) | ||
|
|
||
| // Update gradient layer frame to match view bounds | ||
| if let gradientLayer = safeAreaGradientView.layer.sublayers?.first as? CAGradientLayer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is better done as a UIView subclass that overrides layerClass and does something like
var gradientLayer: CAGradientLayer { layer as! CAGradientLayer }then we don't have to root around for the gradient layer and set its frame. Also then it works with UIKit animation.
| gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0) | ||
|
|
||
| safeAreaGradientView.layer.addSublayer(gradientLayer) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this could go into that UIView subclass, which could also implement themeDidChange.
| self.toolbar.alpha = 1.0 | ||
| self.toolbar.transform = .identity | ||
|
|
||
| // Hide safe area gradient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recognize these useless comments as very llm coding, which is ok, but I'd love a pass to get rid of them after.
| init() { | ||
| super.init(frame: .zero) | ||
| showsMenuAsPrimaryAction = true | ||
| // Enable modern iOS 26 menu styling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
| // Update interface style before showing the menu to ensure it uses the correct theme | ||
| updateInterfaceStyle() | ||
|
|
||
| // Use the original approach that was working, but ensure we get iOS 26 styling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
| } | ||
|
|
||
| func updateInterfaceStyle() { | ||
| // Follow the theme's mode setting for menu appearance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Menu appearance" is an excellent candidate for a dedicated theme key.
…tead of "mode". Changed the way Immersion Mode is activated from velocity-based gesture to 1:1 scroll distance. Improved safe area gradient using UIView subclass.
|
So the approach itself has changed from velocity-based to be more of a 1:1 hide/reveal based on user scroll distance. |
Implements a new immersive reading experience that automatically hides the navigation bar and toolbar when scrolling down, and shows them when scrolling up.
Features:
• Toggle available in main settings and posts settings
• Velocity-based transitions (0.5 threshold)
• Automatic bar reveal when near top/bottom of content
• Gradient overlay for improved status bar readability
• Seamless light/dark theme integration
• Smooth 0.25s animations with proper layout updates
Files modified:
• AwfulSettings: Added immersionModeEnabled setting
• AwfulSettingsUI: Added settings toggles and localization
• PostsPageView: Core scroll handling and UI hiding logic
• PostsPageViewController: Navigation bar integration
• PostsPageSettingsViewController: In-page settings toggle