@@ -33,6 +33,9 @@ final class WebViewController: UIViewController, WKNavigationDelegate, WKUIDeleg
3333 private var emptyStateView : UIView ?
3434 private let emptyStateTransitionDuration : TimeInterval = 0.3
3535
36+ private var statusBarView : UIView ?
37+ private var webViewTopConstraint : NSLayoutConstraint ?
38+
3639 private var initialURL : URL ?
3740 private var statusBarButtonsStack : UIStackView ?
3841 private var lastNavigationWasServerError = false
@@ -454,9 +457,22 @@ final class WebViewController: UIViewController, WKNavigationDelegate, WKUIDeleg
454457 webView. translatesAutoresizingMaskIntoConstraints = false
455458 webView. leftAnchor. constraint ( equalTo: view. leftAnchor) . isActive = true
456459 webView. rightAnchor. constraint ( equalTo: view. rightAnchor) . isActive = true
457- webView. topAnchor. constraint ( equalTo: statusBarView. bottomAnchor) . isActive = true
458460 webView. bottomAnchor. constraint ( equalTo: view. bottomAnchor) . isActive = true
459461 webView. autoresizingMask = [ . flexibleWidth, . flexibleHeight]
462+
463+ // Create the top constraint based on edge-to-edge setting
464+ // On iOS (not Catalyst), edge-to-edge mode pins the webview to the top of the view
465+ // On Catalyst, we always show the status bar buttons, so we pin to statusBarView
466+ // Also use edge-to-edge behavior when fullScreen is enabled (status bar hidden)
467+ let edgeToEdge = ( Current . settingsStore. edgeToEdge || Current . settingsStore. fullScreen) && !Current. isCatalyst
468+ if edgeToEdge {
469+ webViewTopConstraint = webView. topAnchor. constraint ( equalTo: view. topAnchor)
470+ statusBarView. isHidden = true
471+ } else {
472+ webViewTopConstraint = webView. topAnchor. constraint ( equalTo: statusBarView. bottomAnchor)
473+ statusBarView. isHidden = false
474+ }
475+ webViewTopConstraint? . isActive = true
460476 }
461477
462478 private func setupURLObserver( ) {
@@ -516,6 +532,7 @@ final class WebViewController: UIViewController, WKNavigationDelegate, WKUIDeleg
516532 private func setupStatusBarView( ) -> UIView {
517533 let statusBarView = UIView ( )
518534 statusBarView. tag = 111
535+ self . statusBarView = statusBarView
519536
520537 view. addSubview ( statusBarView)
521538 statusBarView. translatesAutoresizingMaskIntoConstraints = false
@@ -530,7 +547,6 @@ final class WebViewController: UIViewController, WKNavigationDelegate, WKUIDeleg
530547 if Current . isCatalyst {
531548 setupStatusBarButtons ( in: statusBarView)
532549 }
533-
534550 return statusBarView
535551 }
536552
@@ -680,15 +696,17 @@ final class WebViewController: UIViewController, WKNavigationDelegate, WKUIDeleg
680696
681697 let cachedColors = ThemeColors . cachedThemeColors ( for: traitCollection)
682698
699+ view. backgroundColor = cachedColors [ . primaryBackgroundColor]
683700 webView? . backgroundColor = cachedColors [ . primaryBackgroundColor]
684701 webView? . scrollView. backgroundColor = cachedColors [ . primaryBackgroundColor]
685702
686- if let statusBarView = view. viewWithTag ( 111 ) {
687- if server. info. version < . canUseAppThemeForStatusBar {
688- statusBarView. backgroundColor = cachedColors [ . appHeaderBackgroundColor]
689- } else {
690- statusBarView. backgroundColor = cachedColors [ . appThemeColor]
691- }
703+ // Use the stored reference instead of searching by tag
704+ if let statusBarView {
705+ let backgroundColor = server. info. version < . canUseAppThemeForStatusBar
706+ ? cachedColors [ . appHeaderBackgroundColor]
707+ : cachedColors [ . appThemeColor]
708+ statusBarView. backgroundColor = backgroundColor
709+ statusBarView. isOpaque = true
692710 }
693711
694712 refreshControl. tintColor = cachedColors [ . primaryColor]
@@ -744,6 +762,40 @@ final class WebViewController: UIViewController, WKNavigationDelegate, WKUIDeleg
744762 if reason == . settingChange {
745763 setNeedsStatusBarAppearanceUpdate ( )
746764 setNeedsUpdateOfHomeIndicatorAutoHidden ( )
765+ updateEdgeToEdgeLayout ( )
766+ }
767+ }
768+
769+ private func updateEdgeToEdgeLayout( ) {
770+ guard let statusBarView else { return }
771+
772+ // Edge-to-edge mode only applies to iOS (not Catalyst)
773+ // Also use edge-to-edge behavior when fullScreen is enabled (status bar hidden)
774+ let edgeToEdge = ( Current . settingsStore. edgeToEdge || Current . settingsStore. fullScreen) && !Current. isCatalyst
775+
776+ // Deactivate the current constraint
777+ webViewTopConstraint? . isActive = false
778+
779+ // Create the new constraint based on edge-to-edge setting
780+ if edgeToEdge {
781+ webViewTopConstraint = webView. topAnchor. constraint ( equalTo: view. topAnchor)
782+ statusBarView. isHidden = true
783+ } else {
784+ webViewTopConstraint = webView. topAnchor. constraint ( equalTo: statusBarView. bottomAnchor)
785+ statusBarView. isHidden = false
786+ }
787+ webViewTopConstraint? . isActive = true
788+
789+ // Force layout update
790+ view. setNeedsLayout ( )
791+ view. layoutIfNeeded ( )
792+
793+ // Refresh styling to ensure statusBarView has proper background color
794+ styleUI ( )
795+
796+ // Animate the layout change
797+ UIView . animate ( withDuration: 0.25 ) {
798+ self . view. layoutIfNeeded ( )
747799 }
748800 }
749801
0 commit comments