Skip to content

Commit

Permalink
feat: state-driven in-app messaging (#815)
Browse files Browse the repository at this point in the history
Co-authored-by: Shahroz Khan <[email protected]>
  • Loading branch information
mrehan27 and Shahroz16 authored Sep 17, 2024
1 parent c7fb7e6 commit 5cd651b
Show file tree
Hide file tree
Showing 48 changed files with 2,854 additions and 1,330 deletions.
14 changes: 13 additions & 1 deletion Sources/MessagingInApp/Extensions/GistExtensions.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import Foundation

extension Message {
extension Message: CustomStringConvertible {
// Used for getting details about the Message object for sending to logs.
//
// We are logging the Gist campaign id as delivery id because we call it delivery id on our system.
var describeForLogs: String {
"id: \(messageId), queueId: \(queueId ?? "none"), deliveryId: \(gistProperties.campaignId ?? "none")"
}

// Provides string representation of Message object with all its properties for debugging purposes.
public var description: String {
"Message(messageId=\(messageId), instanceId=\(instanceId), priority=\(String(describing: priority)), queueId=\(String(describing: queueId)), properties=\(gistProperties))"
}
}

extension GistProperties: CustomStringConvertible {
// Provides string representation of GistProperties object with all its properties for debugging purposes.
public var description: String {
"GistProperties(routeRule=\(String(describing: routeRule)), elementId=\(String(describing: elementId)), deliveryId=\(String(describing: campaignId)), position=\(position), persistent=\(String(describing: persistent)))"
}
}
24 changes: 24 additions & 0 deletions Sources/MessagingInApp/Extensions/LoggerExtensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import CioInternalCommon
import Foundation

extension Logger {
/// Logs a message with the `[InApp]` tag, appending it to the log message.
/// This method is specific to the In-App module, where all log messages will be prefixed with `[InApp]`.
///
/// - Parameters:
/// - message: The log message to be displayed.
/// - level: The log level (e.g., `.info`, `.debug`, `.error`).
func logWithModuleTag(_ message: String, level: CioLogLevel) {
let formattedMessage = "[InApp] \(message)"
switch level {
case .info:
info(formattedMessage)
case .debug:
debug(formattedMessage)
case .error:
error(formattedMessage)
case .none:
break
}
}
}
14 changes: 0 additions & 14 deletions Sources/MessagingInApp/Gist/EngineWeb/EngineRoute.swift

This file was deleted.

17 changes: 13 additions & 4 deletions Sources/MessagingInApp/Gist/EngineWeb/EngineWeb.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ protocol EngineWebInstance: AutoMockable {
}

public class EngineWeb: NSObject, EngineWebInstance {
private let logger: Logger = DIGraphShared.shared.logger
private let inAppMessageManager: InAppMessageManager = DIGraphShared.shared.inAppMessageManager
private let currentMessage: Message
private var _currentRoute = ""
private var _timeoutTimer: Timer?
private var _elapsedTimer = ElapsedTimer()
Expand All @@ -40,7 +43,9 @@ public class EngineWeb: NSObject, EngineWebInstance {
}
}

init(configuration: EngineWebConfiguration) {
init(configuration: EngineWebConfiguration, state: InAppMessageState, message: Message) {
self.currentMessage = message

super.init()

_elapsedTimer.start(title: "Engine render for message: \(configuration.messageId)")
Expand All @@ -65,8 +70,8 @@ public class EngineWeb: NSObject, EngineWebInstance {
let jsonString = String(data: jsonData, encoding: .utf8),
let options = jsonString.data(using: .utf8)?.base64EncodedString()
.addingPercentEncoding(withAllowedCharacters: .alphanumerics) {
let url = "\(Settings.Network.renderer)/index.html?options=\(options)"
Logger.instance.info(message: "Loading URL: \(url)")
let url = "\(state.environment.networkSettings.renderer)/index.html?options=\(options)"
logger.logWithModuleTag("Loading URL: \(url)", level: .info)
if let link = URL(string: url) {
self._timeoutTimer = Timer.scheduledTimer(
timeInterval: 5.0,
Expand All @@ -82,14 +87,17 @@ public class EngineWeb: NSObject, EngineWebInstance {
}

public func cleanEngineWeb() {
_timeoutTimer?.invalidate()
_timeoutTimer = nil
webView.removeFromSuperview()
webView.configuration.userContentController.removeAllUserScripts()
webView.configuration.userContentController.removeScriptMessageHandler(forName: "gist")
}

@objc
func forcedTimeout() {
Logger.instance.info(message: "Timeout triggered, triggering message error.")
logger.logWithModuleTag("Timeout triggered, triggering message error.", level: .info)
inAppMessageManager.dispatch(action: .engineAction(action: .messageLoadingFailed(message: currentMessage)))
delegate?.error()
}
}
Expand All @@ -111,6 +119,7 @@ extension EngineWeb: WKScriptMessageHandler {
switch engineEventMethod {
case .bootstrapped:
_timeoutTimer?.invalidate()
_timeoutTimer = nil
delegate?.bootstrapped()
case .routeLoaded:
_elapsedTimer.end()
Expand Down
6 changes: 3 additions & 3 deletions Sources/MessagingInApp/Gist/EngineWeb/EngineWebProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import Foundation

// Allows us to mock EngineWeb instances for testing.
protocol EngineWebProvider {
func getEngineWebInstance(configuration: EngineWebConfiguration) -> EngineWebInstance
func getEngineWebInstance(configuration: EngineWebConfiguration, state: InAppMessageState, message: Message) -> EngineWebInstance
}

// sourcery: InjectRegisterShared = "EngineWebProvider"
class EngineWebProviderImpl: EngineWebProvider {
func getEngineWebInstance(configuration: EngineWebConfiguration) -> EngineWebInstance {
EngineWeb(configuration: configuration)
func getEngineWebInstance(configuration: EngineWebConfiguration, state: InAppMessageState, message: Message) -> EngineWebInstance {
EngineWeb(configuration: configuration, state: state, message: message)
}
}
Loading

0 comments on commit 5cd651b

Please sign in to comment.