@@ -9,10 +9,12 @@ import Foundation
99import SwiftUI
1010import UIKit
1111import WebKit
12+ import Common
1213
1314@Observable final class WebViewModel {
1415 var url : URL
1516 var isLoading : Bool = true
17+ var progress : Double = 0.0
1618
1719 init ( url: URL ) {
1820 self . url = url
@@ -32,8 +34,20 @@ struct WebViewContainer: View {
3234 }
3335
3436 var body : some View {
35- LoadingView ( isShowing : self . $model . isLoading ) {
37+ ZStack {
3638 WebView ( viewModel: self . $model)
39+
40+ // Progress bar overlay positioned at the top
41+ VStack {
42+ if model. progress < 1.0 && model. isLoading {
43+ ProgressView ( value: model. progress)
44+ . progressViewStyle ( . linear)
45+ . frame ( height: 3 )
46+ . tint ( HNColors . orange)
47+ . animation ( . linear( duration: 0.1 ) , value: model. progress)
48+ }
49+ Spacer ( )
50+ }
3751 }
3852 . navigationBarTitleDisplayMode ( . inline)
3953 . navigationTitle ( title)
@@ -53,10 +67,8 @@ struct WebViewContainer: View {
5367 } label: {
5468 Image ( systemName: " ellipsis " )
5569 }
56-
57-
58- }
5970 }
71+ }
6072 }
6173}
6274
@@ -70,20 +82,44 @@ struct WebView: UIViewRepresentable {
7082
7183 class Coordinator : NSObject , WKNavigationDelegate {
7284 private var viewModel : WebViewModel
85+ private var progressObservation : NSKeyValueObservation ?
7386
7487 init ( _ viewModel: WebViewModel ) {
7588 self . viewModel = viewModel
7689 }
90+
91+ func startObserving( _ webView: WKWebView ) {
92+ progressObservation = webView. observe ( \. estimatedProgress, options: . new) { [ weak self] webView, _ in
93+ let progress = webView. estimatedProgress
94+ self ? . viewModel. progress = progress
95+ }
96+ }
97+
98+ func stopObserving( ) {
99+ progressObservation? . invalidate ( )
100+ progressObservation = nil
101+ }
77102
103+ func webView( _ webView: WKWebView , didStartProvisionalNavigation navigation: WKNavigation ! ) {
104+ self . viewModel. isLoading = true
105+ self . viewModel. progress = 0.0
106+ }
107+
78108 func webView( _ webView: WKWebView , didFinish navigation: WKNavigation ! ) {
79109 self . viewModel. isLoading = false
110+ self . viewModel. progress = 1.0
111+ }
112+
113+ deinit {
114+ stopObserving ( )
80115 }
81116 }
82117
83118 func makeUIView( context: Context ) -> WKWebView {
84119 self . webView. navigationDelegate = context. coordinator
85120 self . webView. backgroundColor = . systemBackground
86121 self . webView. isOpaque = false
122+ context. coordinator. startObserving ( self . webView)
87123
88124 return self . webView
89125 }
0 commit comments