Skip to content

AB#280444 - Add GamifyWidget SDK module#140

Open
dmytro-b-optimove wants to merge 8 commits into
masterfrom
feature/280444-gamify-widget-ios
Open

AB#280444 - Add GamifyWidget SDK module#140
dmytro-b-optimove wants to merge 8 commits into
masterfrom
feature/280444-gamify-widget-ios

Conversation

@dmytro-b-optimove
Copy link
Copy Markdown

@dmytro-b-optimove dmytro-b-optimove commented Apr 13, 2026

Summary

  • Adds GamifyWidgetSDK — public entry point with initialize(widgetUrl:) and open(from:userId:token:) that presents a modal sheet
  • Adds GamifyWidgetViewController — internal UIKit view controller hosting a WKWebView with JS bridge (READY → INIT → CLOSE handshake), loading spinner, and error state
  • Adds GamifyWidgetSDKTests — unit tests for URL initialisation

iOS equivalent of Android SDK PR #91 (AB#280444). No changes to Package.swift — new files sit inside the existing OptimoveSDK target source path.

JS Bridge

Widget fires READY → native responds with INIT (userId/token) via window.postMessage. Widget calls window.webkit.messageHandlers.nativeBridge.postMessage to close. Token is redacted in logs.

Test plan

  • cmd+U on OptimoveSDK scheme — GamifyWidgetSDKTests pass
  • cmd+B on iOS scheme — clean build, no errors or warnings
  • Run QA app, navigate to Gamify Widget, fill tenant + userId, tap Open Widget — sheet opens and close button dismisses

@dmytro-b-optimove dmytro-b-optimove marked this pull request as draft April 13, 2026 23:41
@dmytro-b-optimove dmytro-b-optimove marked this pull request as ready for review April 27, 2026 11:28
@dmytro-b-optimove dmytro-b-optimove force-pushed the feature/280444-gamify-widget-ios branch from 0ac9128 to fa68645 Compare April 27, 2026 11:57
SofiaVainstein
SofiaVainstein previously approved these changes Apr 30, 2026
Comment thread OptimoveSDK/Sources/Classes/GamifyWidget/GamifyWidgetViewController.swift Outdated
Comment thread OptimoveSDK/Sources/Classes/GamifyWidget/GamifyWidgetViewController.swift Outdated
Comment thread OptimoveSDK/Sources/Classes/GamifyWidget/GamifyWidgetSDK.swift Outdated
Comment thread OptimoveSDK/Sources/Classes/GamifyWidget/GamifyWidgetSDK.swift
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread OptimoveSDK/Sources/Classes/GamifyWidget/GamifyWidgetSDK.swift
Match the ensureMain + assertOnMainThread pattern from InAppPresenter.swift
so public entry points dispatch to main themselves instead of relying on a
debug-only assert that strips in release builds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Gamify Widget” feature area to the OptimoveSDK, providing a public SDK entry point to configure a widget URL and present a modal sheet hosting a WKWebView with a simple JS bridge handshake.

Changes:

  • Introduces GamifyWidgetSDK as the public API for configuring and opening the widget.
  • Adds GamifyWidgetViewController to host the WKWebView, show loading/error UI, and handle READY/INIT/CLOSE messages.
  • Adds GamifyWidgetSDKTests covering URL initialization behavior (including a background-thread call case).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
OptimoveSDK/Sources/Classes/GamifyWidget/GamifyWidgetSDK.swift Public entry point to initialize widget URL and present the widget as a modal sheet.
OptimoveSDK/Sources/Classes/GamifyWidget/GamifyWidgetViewController.swift Internal UIKit controller with WKWebView + JS bridge, loading spinner, and error state.
OptimoveSDK/Tests/Sources/GamifyWidget/GamifyWidgetSDKTests.swift Unit tests validating widget URL initialization behavior.
Comments suppressed due to low confidence (1)

OptimoveSDK/Tests/Sources/GamifyWidget/GamifyWidgetSDKTests.swift:21

  • Same issue as above: this test asserts immediately after calling initialize, but initialize may be async if invoked off the main thread. Make the test deterministic by running the call on the main thread or waiting until the main-queue work has executed.
    func testInitializeOverwritesPreviousUrl() {
        GamifyWidgetSDK.initialize(widgetUrl: "https://first.example.com")
        GamifyWidgetSDK.initialize(widgetUrl: "https://second.example.com")
        XCTAssertEqual(GamifyWidgetSDK.widgetUrl, "https://second.example.com")
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// Copyright © 2026 Optimove. All rights reserved.

import UIKit
import WebKit
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, interesting how it was linked then

Comment on lines +6 to +9
private enum BridgeMessage {
static let receiveMessage = "receiveMessage"
static let closeWidget = "closeWidget"
}
Comment on lines +45 to +50
assertOnMainThread()
let vc = GamifyWidgetViewController(
widgetUrl: widgetUrl,
userId: userId,
token: token
)
Copy link
Copy Markdown
Author

@dmytro-b-optimove dmytro-b-optimove May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty/invalid widgetUrl doesn't produce a blank sheet — GamifyWidgetViewController.loadWidget() guards via URL(string:) and falls through to showError(), which reveals the error label set up in setupErrorLabel() (L80-L102):

"Unable to load widget.\nCheck your connection and try again."

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this error message help a user?
Copilot says not to open the error screen if we know that the user will see it immediately.

Comment thread OptimoveSDK/Tests/Sources/GamifyWidget/GamifyWidgetSDKTests.swift
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants