Skip to content

Commit f381a26

Browse files
authored
Merge pull request #3 from HubSpot/hs-update-improve-links
Update handling of links when clicked to avoid blank screen
2 parents b51b669 + ea3efdc commit f381a26

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

Sources/HubspotMobileSDK/Views/ChatView/HubspotChatView.swift

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,20 @@ import WebKit
2828
/// HubspotChatView(manager: HubspotManager.shared, chatFlow: "support")
2929
/// ```
3030
///
31+
/// ### Handling Links (Optional)
32+
///
33+
/// The chat may have links within that are targeted at opening in a new window. The ``HubspotChatView`` triggers these using the SwiftUI open url environment action. By default, this will cause the system to open the url in the external browser.
34+
///
35+
/// These can be handled in an alternative way if desired by providing an alternative url handler using SwiftUIs exsting open url environment feature
36+
///
37+
/// ```swift
38+
/// HubspotChatView()
39+
/// .environment(\.openURL, OpenURLAction(handler: { URL in
40+
/// /// Handle opening of link in chat in some in app browser, or some other method
41+
/// return OpenURLAction.Result.systemAction
42+
/// }))
43+
/// ```
44+
///
3145
/// ### Opening Chat From Push Notification
3246
///
3347
/// If opening chat view in response to a push notification , ideally extract important information from the notification using the ``PushNotificationChatData`` struct , and pass to the initialiser like so:
@@ -124,6 +138,9 @@ struct HubspotChatWebView: UIViewRepresentable {
124138
private let chatFlow: String?
125139
private let pushData: PushNotificationChatData?
126140

141+
@Environment(\.openURL)
142+
var openURLAction
143+
127144
// Note - not a state , or observed object - we don't need to monitor it here
128145
let viewModel: ChatViewModel
129146

@@ -147,12 +164,15 @@ struct HubspotChatWebView: UIViewRepresentable {
147164
}
148165

149166
func makeCoordinator() -> WebviewCoordinator {
150-
return WebviewCoordinator(manager: manager, viewModel: viewModel)
167+
return WebviewCoordinator(manager: manager, viewModel: viewModel, urlHandler: openURLAction)
151168
}
152169

153170
func makeUIView(context: Context) -> WKWebView {
154171
let configuration = WKWebViewConfiguration()
155172

173+
let coordinator = context.coordinator
174+
coordinator.urlHandler = context.environment[keyPath: \.openURL]
175+
156176
configuration.applicationNameForUserAgent = "HubspotMobileSDK"
157177
configuration.websiteDataStore = .default()
158178

@@ -221,9 +241,12 @@ struct HubspotChatWebView: UIViewRepresentable {
221241
let viewModel: ChatViewModel
222242
let manager: HubspotManager
223243

224-
init(manager: HubspotManager, viewModel: ChatViewModel) {
244+
var urlHandler: OpenURLAction
245+
246+
init(manager: HubspotManager, viewModel: ChatViewModel, urlHandler: OpenURLAction) {
225247
self.manager = manager
226248
self.viewModel = viewModel
249+
self.urlHandler = urlHandler
227250
}
228251

229252
let handlerName = "nativeApp"
@@ -347,6 +370,30 @@ struct HubspotChatWebView: UIViewRepresentable {
347370
}
348371
}
349372
}
373+
374+
func webView(_: WKWebView, decidePolicyFor navigationAction: WKNavigationAction) async -> WKNavigationActionPolicy {
375+
// Most navigations are allowed, as that matches default behaviour. But for links specifically, we do additional checks
376+
switch navigationAction.navigationType {
377+
case .linkActivated:
378+
if navigationAction.targetFrame?.isMainFrame ?? false {
379+
// For links specifically targeting the main frame, lets assume that's intentional to replace chat?
380+
// If links are incorrectly being sent targeting the main frame handle it like the else branch for all link activated
381+
return .allow
382+
} else if let url = navigationAction.request.url {
383+
// A link not targeting the main frame would be a pop up, other tab type attempt at opening. Use the system open URL and cancel any nav within the webview
384+
urlHandler(url)
385+
return .cancel
386+
} else {
387+
// Not sure what the link type would be without a url - whatever it is , just default to allowing it
388+
return .allow
389+
}
390+
391+
case .formSubmitted, .backForward, .reload, .formResubmitted, .other:
392+
return .allow
393+
@unknown default:
394+
return .allow
395+
}
396+
}
350397
}
351398
}
352399

0 commit comments

Comments
 (0)