Skip to content

Commit

Permalink
PoC RMF support #2
Browse files Browse the repository at this point in the history
This reverts commit 83ba686.
  • Loading branch information
ayoy committed Nov 15, 2024
1 parent 16cbe5c commit 0f5cd16
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 10 deletions.
2 changes: 1 addition & 1 deletion DuckDuckGo/Application/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
freemiumDBPPromotionViewCoordinator = FreemiumDBPPromotionViewCoordinator(freemiumDBPUserStateManager: freemiumDBPUserStateManager,
freemiumDBPFeature: freemiumDBPFeature)

newTabPageActionsManager = NewTabPageActionsManager(appearancePreferences: .shared)
newTabPageActionsManager = NewTabPageActionsManager(appearancePreferences: .shared, activeRemoteMessageModel: activeRemoteMessageModel)
}

func applicationWillFinishLaunching(_ notification: Notification) {
Expand Down
25 changes: 24 additions & 1 deletion DuckDuckGo/HomePage/NewTabPageActionsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import Foundation
import Combine
import PixelKit
import RemoteMessaging
import Common
import os.log

Expand All @@ -37,16 +38,20 @@ protocol NewTabPageActionsManaging: AnyObject {
func reportException(with params: [String: String])
func showContextMenu(with params: [String: Any])
func updateWidgetConfigs(with params: [[String: String]])
func getRemoteMessage() -> NewTabPageUserScript.RMFMessage?
}

final class NewTabPageActionsManager: NewTabPageActionsManaging {

private let appearancePreferences: AppearancePreferences
private let activeRemoteMessageModel: ActiveRemoteMessageModel

private var cancellables = Set<AnyCancellable>()
private var userScripts = NSHashTable<NewTabPageUserScript>.weakObjects()

init(appearancePreferences: AppearancePreferences) {
init(appearancePreferences: AppearancePreferences, activeRemoteMessageModel: ActiveRemoteMessageModel) {
self.appearancePreferences = appearancePreferences
self.activeRemoteMessageModel = activeRemoteMessageModel

appearancePreferences.$isFavoriteVisible.dropFirst().removeDuplicates().asVoid()
.receive(on: DispatchQueue.main)
Expand All @@ -61,6 +66,12 @@ final class NewTabPageActionsManager: NewTabPageActionsManaging {
self?.notifyWidgetConfigsDidChange()
}
.store(in: &cancellables)

activeRemoteMessageModel.$remoteMessage.dropFirst()
.sink { [weak self] remoteMessage in
self?.notifyRemoteMessageDidChange(remoteMessage)
}
.store(in: &cancellables)
}

func registerUserScript(_ userScript: NewTabPageUserScript) {
Expand All @@ -76,6 +87,14 @@ final class NewTabPageActionsManager: NewTabPageActionsManaging {
}
}

private func notifyRemoteMessageDidChange(_ remoteMessage: RemoteMessageModel?) {
let data = NewTabPageUserScript.RMFData(content: .small(.init(descriptionText: "Hello, this is a description", id: "hejka", titleText: "Hello I'm a title")))

userScripts.allObjects.forEach { userScript in
userScript.notifyRemoteMessageDidChange(data)
}
}

var configuration: NewTabPageUserScript.NewTabPageConfiguration {
#if DEBUG || REVIEW
let env = "development"
Expand Down Expand Up @@ -177,6 +196,10 @@ final class NewTabPageActionsManager: NewTabPageActionsManaging {
}
}

func getRemoteMessage() -> NewTabPageUserScript.RMFMessage? {
.small(.init(descriptionText: "Hello, this is a description", id: "hejka", titleText: "Hello I'm a title"))
}

func reportException(with params: [String: String]) {
let message = params["message"] ?? ""
let id = params["id"] ?? ""
Expand Down
97 changes: 90 additions & 7 deletions DuckDuckGo/HomePage/NewTabPageUserScript.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ final class NewTabPageUserScript: NSObject, Subfeature {
case initialSetup
case reportInitException
case reportPageException
case rmfGetData = "rmf_getData"
case statsGetConfig = "stats_getConfig"
case statsGetData = "stats_getData"
case widgetsSetConfig = "widgets_setConfig"
Expand All @@ -58,6 +59,7 @@ final class NewTabPageUserScript: NSObject, Subfeature {
.initialSetup: { [weak self] in try await self?.initialSetup(params: $0, original: $1) },
.reportInitException: { [weak self] in try await self?.reportException(params: $0, original: $1) },
.reportPageException: { [weak self] in try await self?.reportException(params: $0, original: $1) },
.rmfGetData: { [weak self] in try await self?.rmfGetData(params: $0, original: $1) },
.statsGetConfig: { [weak self] in try await self?.statsGetConfig(params: $0, original: $1) },
.statsGetData: { [weak self] in try await self?.statsGetData(params: $0, original: $1) },
.widgetsSetConfig: { [weak self] in try await self?.widgetsSetConfig(params: $0, original: $1) }
Expand All @@ -75,16 +77,17 @@ final class NewTabPageUserScript: NSObject, Subfeature {
}
broker?.push(method: "widgets_onConfigUpdated", params: widgetConfigs, for: self, into: webView)
}
}

extension NewTabPageUserScript {
@MainActor
private func showContextMenu(params: Any, original: WKScriptMessage) async throws -> Encodable? {
guard let params = params as? [String: Any] else { return nil }
actionsManager.showContextMenu(with: params)
return nil
func notifyRemoteMessageDidChange(_ remoteMessageData: NewTabPageUserScript.RMFData?) {
guard let webView else {
return
}

broker?.push(method: "rmf_onDataUpdate", params: remoteMessageData, for: self, into: webView)
}
}

extension NewTabPageUserScript {
@MainActor
private func favoritesGetConfig(params: Any, original: WKScriptMessage) async throws -> Encodable? {
actionsManager.getFavoritesConfig()
Expand Down Expand Up @@ -117,6 +120,19 @@ extension NewTabPageUserScript {
return nil
}

@MainActor
private func showContextMenu(params: Any, original: WKScriptMessage) async throws -> Encodable? {
guard let params = params as? [String: Any] else { return nil }
actionsManager.showContextMenu(with: params)
return nil
}

@MainActor
private func rmfGetData(params: Any, original: WKScriptMessage) async throws -> Encodable? {
let data = NewTabPageUserScript.RMFData(content: actionsManager.getRemoteMessage())
return data
}

private func reportException(params: Any, original: WKScriptMessage) async throws -> Encodable? {
guard let params = params as? [String: String] else { return nil }
actionsManager.reportException(with: params)
Expand Down Expand Up @@ -209,4 +225,71 @@ extension NewTabPageUserScript {
let count: Int
let displayName: String
}

struct RMFData: Encodable {
var content: RMFMessage?
}

enum RMFMessage: Encodable {
case small(SmallMessage), medium(MediumMessage), bigSingleAction(BigSingleActionMessage), bigTwoAction(BigTwoActionMessage)

func encode(to encoder: any Encoder) throws {
try message.encode(to: encoder)
}

var message: Encodable {
switch self {
case .small(let message):
return message
case .medium(let message):
return message
case .bigSingleAction(let message):
return message
case .bigTwoAction(let message):
return message
}
}
}

struct SmallMessage: Encodable {
let messageType = "small"

var descriptionText: String
var id: String
var titleText: String
}

struct MediumMessage: Encodable {
let messageType = "medium"

var descriptionText: String
var icon: RMFIcon
var id: String
var titleText: String
}

struct BigSingleActionMessage: Encodable {
let messageType = "big_single_action"

var descriptionText: String
var icon: RMFIcon
var id: String
var primaryActionText: String
var titleText: String
}

struct BigTwoActionMessage: Encodable {
let messageType = "big_two_action"

var descriptionText: String
var icon: RMFIcon
var id: String
var primaryActionText: String
var secondaryActionText: String
var titleText: String
}

enum RMFIcon: String, Encodable {
case announce, ddgAnnounce, criticalUpdate, appUpdate, privacyPro
}
}
2 changes: 1 addition & 1 deletion DuckDuckGo/RemoteMessaging/RemoteMessagingClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ final class RemoteMessagingClient: RemoteMessagingProcessing {
static let minimumConfigurationRefreshInterval: TimeInterval = 60 * 30
static let endpoint: URL = {
#if DEBUG
URL(string: "https://raw.githubusercontent.com/duckduckgo/remote-messaging-config/main/samples/ios/sample1.json")!
URL(string: "https://www.jsonblob.com/api/1261360708536098816")!
#else
URL(string: "https://staticcdn.duckduckgo.com/remotemessaging/config/v1/macos-config.json")!
#endif
Expand Down

0 comments on commit 0f5cd16

Please sign in to comment.