@digia-engage/core 2.2.1 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DigiaEngageReactNative.podspec +1 -1
- package/LICENSE +77 -0
- package/README.md +1 -1
- package/lib/commonjs/Digia.js +1 -1
- package/lib/commonjs/DigiaAnchorView.js +42 -25
- package/lib/commonjs/DigiaAnchorView.js.map +1 -1
- package/lib/commonjs/DigiaHealthReporter.js +1 -1
- package/lib/commonjs/DigiaProvider.js +38 -6
- package/lib/commonjs/DigiaProvider.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/Digia.js +1 -1
- package/lib/module/DigiaAnchorView.js +42 -25
- package/lib/module/DigiaAnchorView.js.map +1 -1
- package/lib/module/DigiaHealthReporter.js +1 -1
- package/lib/module/DigiaProvider.js +38 -6
- package/lib/module/DigiaProvider.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/DigiaAnchorView.d.ts +17 -1
- package/lib/typescript/DigiaAnchorView.d.ts.map +1 -1
- package/lib/typescript/DigiaProvider.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/templateTypes.d.ts +2 -0
- package/lib/typescript/templateTypes.d.ts.map +1 -1
- package/package.json +2 -8
- package/src/Digia.ts +1 -1
- package/src/DigiaAnchorView.tsx +74 -41
- package/src/DigiaHealthReporter.ts +1 -1
- package/src/DigiaProvider.tsx +36 -6
- package/src/index.ts +1 -0
- package/src/templateTypes.ts +2 -0
- package/android/.project +0 -28
- package/android/bin/.gradle/8.13/fileHashes/fileHashes.lock +0 -0
- package/android/bin/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/bin/.gradle/buildOutputCleanup/cache.properties +0 -2
- package/android/bin/.project +0 -34
- package/android/bin/build/generated/source/buildConfig/debug/com/digia/engage/rn/BuildConfig.class +0 -0
- package/android/bin/build/generated/source/codegen/java/com/digia/engage/rn/NativeDigiaEngageSpec.class +0 -0
- package/android/bin/build.gradle +0 -97
- package/android/bin/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/bin/gradle/wrapper/gradle-wrapper.properties +0 -5
- package/android/bin/gradle.properties +0 -2
- package/android/bin/gradlew +0 -185
- package/android/bin/gradlew.bat +0 -89
- package/android/bin/local.properties +0 -1
- package/android/bin/settings.gradle +0 -25
- package/android/bin/src/main/AndroidManifest.xml +0 -2
- package/android/bin/src/main/java/com/digia/engage/rn/DigiaAnchorViewManager.kt +0 -90
- package/android/bin/src/main/java/com/digia/engage/rn/DigiaModule.kt +0 -309
- package/android/bin/src/main/java/com/digia/engage/rn/DigiaPackage.kt +0 -70
- package/android/bin/src/main/java/com/digia/engage/rn/DigiaSlotViewManager.kt +0 -183
- package/android/bin/src/main/java/com/digia/engage/rn/DigiaViewManager.kt +0 -64
- package/android/local.properties +0 -1
package/android/bin/gradlew.bat
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
@rem
|
|
2
|
-
@rem Copyright 2015 the original author or authors.
|
|
3
|
-
@rem
|
|
4
|
-
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
@rem you may not use this file except in compliance with the License.
|
|
6
|
-
@rem You may obtain a copy of the License at
|
|
7
|
-
@rem
|
|
8
|
-
@rem https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
@rem
|
|
10
|
-
@rem Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
@rem See the License for the specific language governing permissions and
|
|
14
|
-
@rem limitations under the License.
|
|
15
|
-
@rem
|
|
16
|
-
|
|
17
|
-
@if "%DEBUG%" == "" @echo off
|
|
18
|
-
@rem ##########################################################################
|
|
19
|
-
@rem
|
|
20
|
-
@rem Gradle startup script for Windows
|
|
21
|
-
@rem
|
|
22
|
-
@rem ##########################################################################
|
|
23
|
-
|
|
24
|
-
@rem Set local scope for the variables with windows NT shell
|
|
25
|
-
if "%OS%"=="Windows_NT" setlocal
|
|
26
|
-
|
|
27
|
-
set DIRNAME=%~dp0
|
|
28
|
-
if "%DIRNAME%" == "" set DIRNAME=.
|
|
29
|
-
set APP_BASE_NAME=%~n0
|
|
30
|
-
set APP_HOME=%DIRNAME%
|
|
31
|
-
|
|
32
|
-
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
|
33
|
-
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
|
34
|
-
|
|
35
|
-
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
36
|
-
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
|
37
|
-
|
|
38
|
-
@rem Find java.exe
|
|
39
|
-
if defined JAVA_HOME goto findJavaFromJavaHome
|
|
40
|
-
|
|
41
|
-
set JAVA_EXE=java.exe
|
|
42
|
-
%JAVA_EXE% -version >NUL 2>&1
|
|
43
|
-
if "%ERRORLEVEL%" == "0" goto execute
|
|
44
|
-
|
|
45
|
-
echo.
|
|
46
|
-
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
47
|
-
echo.
|
|
48
|
-
echo Please set the JAVA_HOME variable in your environment to match the
|
|
49
|
-
echo location of your Java installation.
|
|
50
|
-
|
|
51
|
-
goto fail
|
|
52
|
-
|
|
53
|
-
:findJavaFromJavaHome
|
|
54
|
-
set JAVA_HOME=%JAVA_HOME:"=%
|
|
55
|
-
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|
56
|
-
|
|
57
|
-
if exist "%JAVA_EXE%" goto execute
|
|
58
|
-
|
|
59
|
-
echo.
|
|
60
|
-
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
|
61
|
-
echo.
|
|
62
|
-
echo Please set the JAVA_HOME variable in your environment to match the
|
|
63
|
-
echo location of your Java installation.
|
|
64
|
-
|
|
65
|
-
goto fail
|
|
66
|
-
|
|
67
|
-
:execute
|
|
68
|
-
@rem Setup the command line
|
|
69
|
-
|
|
70
|
-
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
@rem Execute Gradle
|
|
74
|
-
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
|
75
|
-
|
|
76
|
-
:end
|
|
77
|
-
@rem End local scope for the variables with windows NT shell
|
|
78
|
-
if "%ERRORLEVEL%"=="0" goto mainEnd
|
|
79
|
-
|
|
80
|
-
:fail
|
|
81
|
-
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
|
82
|
-
rem the _cmd.exe /c_ return code!
|
|
83
|
-
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
|
84
|
-
exit /b 1
|
|
85
|
-
|
|
86
|
-
:mainEnd
|
|
87
|
-
if "%OS%"=="Windows_NT" endlocal
|
|
88
|
-
|
|
89
|
-
:omega
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
sdk.dir=/Users/ram/Library/Android/sdk
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
pluginManagement {
|
|
2
|
-
plugins {
|
|
3
|
-
id 'com.android.library' version '8.11.2'
|
|
4
|
-
id 'com.android.application' version '8.11.2'
|
|
5
|
-
id 'org.jetbrains.kotlin.android' version '2.1.0'
|
|
6
|
-
id 'org.jetbrains.kotlin.plugin.compose' version '2.1.0'
|
|
7
|
-
id 'org.jetbrains.kotlin.plugin.serialization' version '2.1.0'
|
|
8
|
-
}
|
|
9
|
-
repositories {
|
|
10
|
-
google()
|
|
11
|
-
mavenCentral()
|
|
12
|
-
gradlePluginPortal()
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
dependencyResolutionManagement {
|
|
17
|
-
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
|
18
|
-
repositories {
|
|
19
|
-
mavenLocal()
|
|
20
|
-
google()
|
|
21
|
-
mavenCentral()
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
rootProject.name = "digia-engage-rn"
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
package com.digia.engage.rn
|
|
2
|
-
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import android.view.View
|
|
5
|
-
import android.view.ViewTreeObserver
|
|
6
|
-
import android.widget.FrameLayout
|
|
7
|
-
import com.digia.engage.Digia
|
|
8
|
-
import com.facebook.react.uimanager.ThemedReactContext
|
|
9
|
-
import com.facebook.react.uimanager.ViewGroupManager
|
|
10
|
-
import com.facebook.react.uimanager.annotations.ReactProp
|
|
11
|
-
|
|
12
|
-
internal class DigiaAnchorContainerView(context: Context) : FrameLayout(context) {
|
|
13
|
-
|
|
14
|
-
var anchorKey: String = ""
|
|
15
|
-
|
|
16
|
-
private val globalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener { reportPosition() }
|
|
17
|
-
|
|
18
|
-
override fun onAttachedToWindow() {
|
|
19
|
-
super.onAttachedToWindow()
|
|
20
|
-
viewTreeObserver.addOnGlobalLayoutListener(globalLayoutListener)
|
|
21
|
-
reportPosition()
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
override fun onDetachedFromWindow() {
|
|
25
|
-
viewTreeObserver.removeOnGlobalLayoutListener(globalLayoutListener)
|
|
26
|
-
if (anchorKey.isNotBlank()) Digia.unregisterAnchor(anchorKey)
|
|
27
|
-
super.onDetachedFromWindow()
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
private fun reportPosition() {
|
|
31
|
-
val key = anchorKey.takeIf { it.isNotBlank() } ?: return
|
|
32
|
-
// React Native (Fabric) may not call layout() on this FrameLayout wrapper,
|
|
33
|
-
// so this.width/height can be 0. Derive dimensions from the first child instead.
|
|
34
|
-
val targetView: android.view.View = if (childCount > 0) getChildAt(0) else this
|
|
35
|
-
val w = targetView.width
|
|
36
|
-
val h = targetView.height
|
|
37
|
-
if (w == 0 || h == 0) return // not measured yet — wait for next layout pass
|
|
38
|
-
val loc = IntArray(2)
|
|
39
|
-
targetView.getLocationOnScreen(loc)
|
|
40
|
-
android.util.Log.d(
|
|
41
|
-
"Digia",
|
|
42
|
-
"[DigiaAnchorView] registerAnchor key='$key' x=${loc[0]} y=${loc[1]} w=$w h=$h"
|
|
43
|
-
)
|
|
44
|
-
Digia.registerAnchor(key, loc[0], loc[1], w, h)
|
|
45
|
-
Digia.registerAnchorView(key, targetView)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// ViewGroupManager (not SimpleViewManager) because Fabric calls getViewGroupManager()
|
|
50
|
-
// on any view that hosts RN children — DigiaAnchorView wraps the anchor target element.
|
|
51
|
-
internal class DigiaAnchorViewManager : ViewGroupManager<DigiaAnchorContainerView>() {
|
|
52
|
-
|
|
53
|
-
override fun getName(): String = VIEW_NAME
|
|
54
|
-
|
|
55
|
-
override fun createViewInstance(context: ThemedReactContext) = DigiaAnchorContainerView(context)
|
|
56
|
-
|
|
57
|
-
// Use updateProperties instead of @ReactProp to be compatible with both
|
|
58
|
-
// Old Architecture (Paper) and New Architecture (Fabric) without codegen.
|
|
59
|
-
override fun updateProperties(
|
|
60
|
-
viewToUpdate: DigiaAnchorContainerView,
|
|
61
|
-
props: com.facebook.react.uimanager.ReactStylesDiffMap,
|
|
62
|
-
) {
|
|
63
|
-
super.updateProperties(viewToUpdate, props)
|
|
64
|
-
if (props.hasKey("anchorKey")) {
|
|
65
|
-
viewToUpdate.anchorKey = props.getString("anchorKey") ?: ""
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
@com.facebook.react.uimanager.annotations.ReactProp(name = "anchorKey")
|
|
70
|
-
fun setAnchorKey(view: DigiaAnchorContainerView, key: String?) {
|
|
71
|
-
view.anchorKey = key.orEmpty()
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
override fun addView(parent: DigiaAnchorContainerView, child: View, index: Int) {
|
|
75
|
-
parent.addView(child, index)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
override fun getChildCount(parent: DigiaAnchorContainerView): Int = parent.childCount
|
|
79
|
-
|
|
80
|
-
override fun getChildAt(parent: DigiaAnchorContainerView, index: Int): View =
|
|
81
|
-
parent.getChildAt(index)
|
|
82
|
-
|
|
83
|
-
override fun removeViewAt(parent: DigiaAnchorContainerView, index: Int) {
|
|
84
|
-
parent.removeViewAt(index)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
companion object {
|
|
88
|
-
const val VIEW_NAME = "DigiaAnchorView"
|
|
89
|
-
}
|
|
90
|
-
}
|
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DigiaModule
|
|
3
|
-
*
|
|
4
|
-
* React Native NativeModule that bridges the Digia Engage Android SDK.
|
|
5
|
-
*
|
|
6
|
-
* Exposed methods (callable from JS via NativeModules.DigiaEngageModule):
|
|
7
|
-
*
|
|
8
|
-
* initialize(apiKey, environment, logLevel, baseUrl): Promise<void> register(): void
|
|
9
|
-
* setCurrentScreen(name): void triggerCampaign(id, content, cepContext): void
|
|
10
|
-
* triggerCampaignById(campaignId): void invalidateCampaign(campaignId): void
|
|
11
|
-
*
|
|
12
|
-
* Architecture ──────────── The RN bridge mirrors the native Digia.initialize / Digia.register /
|
|
13
|
-
* Digia.setCurrentScreen flow exactly. An internal [RNEventBridgePlugin] is the single native
|
|
14
|
-
* DigiaCEPPlugin registered via Digia.register().
|
|
15
|
-
*
|
|
16
|
-
* When the SDK calls plugin.setup(delegate), the bridge stores that delegate reference. JS plugins
|
|
17
|
-
* that need to push campaigns into the Compose overlay call triggerCampaign / invalidateCampaign
|
|
18
|
-
* which forward to delegate.onCampaignTriggered / delegate.onCampaignInvalidated.
|
|
19
|
-
*
|
|
20
|
-
* Overlay lifecycle events (impressed / clicked / dismissed) are forwarded from the native
|
|
21
|
-
* plugin.notifyEvent() to JS via DeviceEventEmitter so that pure-JS CEP plugins (e.g.
|
|
22
|
-
* DigiaMoEngagePlugin) can report analytics.
|
|
23
|
-
*/
|
|
24
|
-
package com.digia.engage.rn
|
|
25
|
-
|
|
26
|
-
import androidx.lifecycle.LifecycleOwner
|
|
27
|
-
import androidx.lifecycle.ViewModelStoreOwner
|
|
28
|
-
import androidx.lifecycle.setViewTreeLifecycleOwner
|
|
29
|
-
import androidx.lifecycle.setViewTreeViewModelStoreOwner
|
|
30
|
-
import androidx.savedstate.SavedStateRegistryOwner
|
|
31
|
-
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
|
|
32
|
-
import com.digia.engage.DiagnosticReport
|
|
33
|
-
import com.digia.engage.Digia
|
|
34
|
-
import com.digia.engage.DigiaCEPDelegate
|
|
35
|
-
import com.digia.engage.DigiaCEPPlugin
|
|
36
|
-
import com.digia.engage.DigiaConfig
|
|
37
|
-
import com.digia.engage.DigiaEnvironment
|
|
38
|
-
import com.digia.engage.DigiaExperienceEvent
|
|
39
|
-
import com.digia.engage.DigiaHostView
|
|
40
|
-
import com.digia.engage.DigiaLogLevel
|
|
41
|
-
import com.digia.engage.InAppPayload
|
|
42
|
-
import com.facebook.react.bridge.Arguments
|
|
43
|
-
import com.facebook.react.bridge.Promise
|
|
44
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
|
45
|
-
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
46
|
-
import com.facebook.react.bridge.ReactMethod
|
|
47
|
-
import com.facebook.react.bridge.ReadableMap
|
|
48
|
-
import com.facebook.react.bridge.UiThreadUtil
|
|
49
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
50
|
-
|
|
51
|
-
internal class DigiaModule(
|
|
52
|
-
private val reactContext: ReactApplicationContext,
|
|
53
|
-
) : ReactContextBaseJavaModule(reactContext) {
|
|
54
|
-
|
|
55
|
-
private val rnPlugin = RNEventBridgePlugin(reactContext)
|
|
56
|
-
|
|
57
|
-
override fun getName(): String = MODULE_NAME
|
|
58
|
-
|
|
59
|
-
// ─── initialize ───────────────────────────────────────────────────────────
|
|
60
|
-
|
|
61
|
-
@ReactMethod
|
|
62
|
-
fun initialize(
|
|
63
|
-
apiKey: String,
|
|
64
|
-
environment: String,
|
|
65
|
-
logLevel: String,
|
|
66
|
-
baseUrl: String?,
|
|
67
|
-
fontFamily: String?,
|
|
68
|
-
promise: Promise
|
|
69
|
-
) {
|
|
70
|
-
try {
|
|
71
|
-
val cleanBaseUrl =
|
|
72
|
-
baseUrl.trim().trimEnd('/').removeSuffix("/api/v1").takeIf { it.isNotBlank() }
|
|
73
|
-
val config =
|
|
74
|
-
DigiaConfig(
|
|
75
|
-
apiKey = apiKey,
|
|
76
|
-
baseUrl = cleanBaseUrl,
|
|
77
|
-
environment =
|
|
78
|
-
when (environment.lowercase()) {
|
|
79
|
-
"sandbox" -> DigiaEnvironment.SANDBOX
|
|
80
|
-
else -> DigiaEnvironment.PRODUCTION
|
|
81
|
-
},
|
|
82
|
-
logLevel =
|
|
83
|
-
when (logLevel.lowercase()) {
|
|
84
|
-
"verbose" -> DigiaLogLevel.VERBOSE
|
|
85
|
-
"none" -> DigiaLogLevel.NONE
|
|
86
|
-
else -> DigiaLogLevel.ERROR
|
|
87
|
-
},
|
|
88
|
-
baseUrl = baseUrl?.takeIf { it.isNotBlank() },
|
|
89
|
-
fontFamily = fontFamily?.takeIf { it.isNotBlank() },
|
|
90
|
-
)
|
|
91
|
-
Digia.initialize(reactContext.applicationContext, config)
|
|
92
|
-
|
|
93
|
-
UiThreadUtil.runOnUiThread {
|
|
94
|
-
// Mount the Compose overlay ABOVE the ReactRootView via addContentView().
|
|
95
|
-
// This keeps it outside Fabric's shadow tree entirely so Fabric hit-testing
|
|
96
|
-
// never sees it. Touch pass-through is handled by DigiaHostView.dispatchTouchEvent
|
|
97
|
-
// returning false at the native Android level — which works correctly at this
|
|
98
|
-
// level of the hierarchy, unlike inside Fabric where pointerEvents="none" on
|
|
99
|
-
// non-ReactViewGroup views is not respected during shadow-tree hit-testing.
|
|
100
|
-
mountDigiaHost()
|
|
101
|
-
promise.resolve(null)
|
|
102
|
-
}
|
|
103
|
-
} catch (e: Exception) {
|
|
104
|
-
promise.reject("DIGIA_INIT_ERROR", e.message ?: "Initialisation failed", e)
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// ─── register ─────────────────────────────────────────────────────────────
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Registers [RNEventBridgePlugin] with the native Digia SDK.
|
|
112
|
-
*
|
|
113
|
-
* This is bridge infrastructure — not a user-facing CEP plugin. Called once by the JS
|
|
114
|
-
* `Digia.register()` wrapper on the first plugin registration so that
|
|
115
|
-
* [RNEventBridgePlugin.delegate] is populated before any triggerCampaign / invalidateCampaign
|
|
116
|
-
* calls arrive from JS.
|
|
117
|
-
*/
|
|
118
|
-
@ReactMethod
|
|
119
|
-
fun registerBridge() {
|
|
120
|
-
Digia.register(rnPlugin)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ─── setCurrentScreen ─────────────────────────────────────────────────────
|
|
124
|
-
|
|
125
|
-
@ReactMethod
|
|
126
|
-
fun setCurrentScreen(name: String) {
|
|
127
|
-
Digia.setCurrentScreen(name)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// ─── triggerCampaign ──────────────────────────────────────────────────────
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Forwards a campaign payload to the native DigiaCEPDelegate.
|
|
134
|
-
*
|
|
135
|
-
* This is called by the JS DigiaDelegate.onCampaignTriggered() implementation when a JS CEP
|
|
136
|
-
* plugin (e.g. DigiaMoEngagePlugin) delivers a campaign. The delegate routes it into the
|
|
137
|
-
* Compose overlay for rendering.
|
|
138
|
-
*/
|
|
139
|
-
@ReactMethod
|
|
140
|
-
fun triggerCampaign(id: String, content: ReadableMap, cepContext: ReadableMap) {
|
|
141
|
-
val delegate = rnPlugin.delegate ?: return
|
|
142
|
-
delegate.onCampaignTriggered(
|
|
143
|
-
InAppPayload(
|
|
144
|
-
id = id,
|
|
145
|
-
content = content.toHashMap().toMap(),
|
|
146
|
-
cepContext = cepContext.toHashMap().toMap(),
|
|
147
|
-
)
|
|
148
|
-
)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/** Triggers a fetched Digia campaign directly by campaign id/key. */
|
|
152
|
-
@ReactMethod
|
|
153
|
-
fun triggerCampaignById(campaignId: String) {
|
|
154
|
-
Digia.triggerCampaign(campaignId)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// ─── invalidateCampaign ───────────────────────────────────────────────────
|
|
158
|
-
|
|
159
|
-
/** Forwards a campaign invalidation to the native DigiaCEPDelegate. */
|
|
160
|
-
@ReactMethod
|
|
161
|
-
fun invalidateCampaign(campaignId: String) {
|
|
162
|
-
rnPlugin.delegate?.onCampaignInvalidated(campaignId)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// ─── Anchor registration ──────────────────────────────────────────────────
|
|
166
|
-
|
|
167
|
-
@ReactMethod
|
|
168
|
-
fun registerAnchor(key: String, x: Int, y: Int, width: Int, height: Int) {
|
|
169
|
-
Digia.registerAnchor(key, x, y, width, height)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
@ReactMethod
|
|
173
|
-
fun unregisterAnchor(key: String) {
|
|
174
|
-
Digia.unregisterAnchor(key)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
@ReactMethod
|
|
178
|
-
fun getRegisteredComponents(promise: Promise) {
|
|
179
|
-
promise.resolve(Arguments.createArray())
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// ─── Internal: mount the Compose overlay host ─────────────────────────────
|
|
183
|
-
|
|
184
|
-
private fun mountDigiaHost() {
|
|
185
|
-
val activity =
|
|
186
|
-
reactContext.currentActivity
|
|
187
|
-
?: run {
|
|
188
|
-
android.util.Log.w(
|
|
189
|
-
"DigiaHost",
|
|
190
|
-
"[mountDigiaHost] no current activity — skipping"
|
|
191
|
-
)
|
|
192
|
-
return
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
val contentRoot = activity.window.decorView.findViewWithTag<DigiaHostView>(DIGIA_HOST_TAG)
|
|
196
|
-
if (contentRoot != null) {
|
|
197
|
-
android.util.Log.d(
|
|
198
|
-
"DigiaHost",
|
|
199
|
-
"[mountDigiaHost] already mounted (tag found) — skipping"
|
|
200
|
-
)
|
|
201
|
-
return
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
android.util.Log.d("DigiaHost", "[mountDigiaHost] mounting native overlay on DecorView")
|
|
205
|
-
|
|
206
|
-
// Mount on the DecorView (not content area) so the overlay covers the full screen
|
|
207
|
-
// including status bar and navigation bar. This also ensures the Compose Popup's
|
|
208
|
-
// canvas y=0 aligns with the absolute screen y=0, matching getLocationOnScreen()
|
|
209
|
-
// coordinates used by DigiaAnchorView.
|
|
210
|
-
val decorView =
|
|
211
|
-
activity.window.decorView as? android.view.ViewGroup
|
|
212
|
-
?: run {
|
|
213
|
-
android.util.Log.w(
|
|
214
|
-
"DigiaHost",
|
|
215
|
-
"[mountDigiaHost] decorView not a ViewGroup — skipping"
|
|
216
|
-
)
|
|
217
|
-
return
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
val composeView =
|
|
221
|
-
DigiaHostView(activity).apply {
|
|
222
|
-
tag = DIGIA_HOST_TAG
|
|
223
|
-
if (activity is LifecycleOwner) setViewTreeLifecycleOwner(activity)
|
|
224
|
-
if (activity is ViewModelStoreOwner) setViewTreeViewModelStoreOwner(activity)
|
|
225
|
-
if (activity is SavedStateRegistryOwner)
|
|
226
|
-
setViewTreeSavedStateRegistryOwner(activity)
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
decorView.addView(
|
|
230
|
-
composeView,
|
|
231
|
-
android.view.ViewGroup.LayoutParams(
|
|
232
|
-
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
|
|
233
|
-
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
|
|
234
|
-
),
|
|
235
|
-
)
|
|
236
|
-
android.util.Log.d(
|
|
237
|
-
"DigiaHost",
|
|
238
|
-
"[mountDigiaHost] done — DecorView child count: ${decorView.childCount}"
|
|
239
|
-
)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
companion object {
|
|
243
|
-
const val MODULE_NAME = "DigiaEngageModule"
|
|
244
|
-
private const val DIGIA_HOST_TAG = "digia_host_compose_view"
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* RNEventBridgePlugin
|
|
250
|
-
*
|
|
251
|
-
* The single native DigiaCEPPlugin used in React Native.
|
|
252
|
-
*
|
|
253
|
-
* When Digia.register(rnPlugin) is called, the SDK calls setup(delegate) which gives us the
|
|
254
|
-
* DigiaCEPDelegate reference. This delegate is used by triggerCampaign / invalidateCampaign bridge
|
|
255
|
-
* methods to push campaigns into the native rendering engine.
|
|
256
|
-
*
|
|
257
|
-
* Overlay lifecycle events (impressed / clicked / dismissed) received via notifyEvent() are emitted
|
|
258
|
-
* to JS as DeviceEventEmitter events so that JS CEP plugins can report analytics back to their
|
|
259
|
-
* platform.
|
|
260
|
-
*/
|
|
261
|
-
internal class RNEventBridgePlugin(
|
|
262
|
-
private val reactContext: ReactApplicationContext,
|
|
263
|
-
) : DigiaCEPPlugin {
|
|
264
|
-
|
|
265
|
-
override val identifier: String = "rn-event-bridge"
|
|
266
|
-
|
|
267
|
-
/** Delegate received from the SDK via setup(). Used by DigiaModule bridge methods. */
|
|
268
|
-
var delegate: DigiaCEPDelegate? = null
|
|
269
|
-
private set
|
|
270
|
-
|
|
271
|
-
private fun emit(event: String, params: com.facebook.react.bridge.WritableMap) {
|
|
272
|
-
if (reactContext.hasActiveReactInstance()) {
|
|
273
|
-
reactContext
|
|
274
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
275
|
-
.emit(event, params)
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
override fun setup(delegate: DigiaCEPDelegate) {
|
|
280
|
-
this.delegate = delegate
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
override fun forwardScreen(name: String) {
|
|
284
|
-
/* forwarded by Digia.setCurrentScreen() on the native side */
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
override fun notifyEvent(event: DigiaExperienceEvent, payload: InAppPayload) {
|
|
288
|
-
val params =
|
|
289
|
-
Arguments.createMap().apply {
|
|
290
|
-
putString("campaignId", payload.id)
|
|
291
|
-
when (event) {
|
|
292
|
-
is DigiaExperienceEvent.Impressed -> putString("type", "impressed")
|
|
293
|
-
is DigiaExperienceEvent.Clicked -> {
|
|
294
|
-
putString("type", "clicked")
|
|
295
|
-
event.elementId?.let { putString("elementId", it) }
|
|
296
|
-
}
|
|
297
|
-
is DigiaExperienceEvent.Dismissed -> putString("type", "dismissed")
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
emit("digiaEngageEvent", params)
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
override fun teardown() {
|
|
304
|
-
delegate = null
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
override fun healthCheck(): DiagnosticReport =
|
|
308
|
-
DiagnosticReport(isHealthy = true, metadata = mapOf("identifier" to identifier))
|
|
309
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DigiaPackage
|
|
3
|
-
*
|
|
4
|
-
* Registers the Digia Engage native module and view managers with React Native.
|
|
5
|
-
*
|
|
6
|
-
* Extends TurboReactPackage so the package works transparently on both Old Architecture (bridge)
|
|
7
|
-
* and New Architecture (TurboModules / JSI).
|
|
8
|
-
*
|
|
9
|
-
* Why is this needed? ──────────────────── React Native's auto-linker reads react-native.config.js,
|
|
10
|
-
* which declares `packageInstance: 'new DigiaPackage()'`. At host-app compile time, RN injects this
|
|
11
|
-
* into the generated `PackageList`, making our native module and view managers available to JS
|
|
12
|
-
* without any manual MainApplication edits.
|
|
13
|
-
*
|
|
14
|
-
* JS: NativeModules.DigiaEngageModule ──► DigiaModule.kt JS:
|
|
15
|
-
* requireNativeComponent('DigiaHostView') ──► DigiaViewManager.kt JS:
|
|
16
|
-
* requireNativeComponent('DigiaSlotView') ──► DigiaSlotViewManager.kt
|
|
17
|
-
*/
|
|
18
|
-
package com.digia.engage.rn
|
|
19
|
-
|
|
20
|
-
import com.facebook.react.BaseReactPackage
|
|
21
|
-
import com.facebook.react.bridge.NativeModule
|
|
22
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
|
23
|
-
import com.facebook.react.module.model.ReactModuleInfo
|
|
24
|
-
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
25
|
-
import com.facebook.react.uimanager.ViewManager
|
|
26
|
-
|
|
27
|
-
class DigiaPackage : BaseReactPackage() {
|
|
28
|
-
|
|
29
|
-
// ─── Native Modules ───────────────────────────────────────────────────────
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Called by New Architecture (TurboModules) to instantiate the module by name. Old Architecture
|
|
33
|
-
* continues to use createNativeModules() which TurboReactPackage implements internally by
|
|
34
|
-
* delegating to this method via getReactModuleInfoProvider.
|
|
35
|
-
*/
|
|
36
|
-
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? =
|
|
37
|
-
when (name) {
|
|
38
|
-
DigiaModule.MODULE_NAME -> DigiaModule(reactContext)
|
|
39
|
-
else -> null
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Metadata table: tells the RN runtime which modules this package provides and whether they
|
|
44
|
-
* should be treated as TurboModules (New Architecture).
|
|
45
|
-
*/
|
|
46
|
-
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider = ReactModuleInfoProvider {
|
|
47
|
-
mapOf(
|
|
48
|
-
DigiaModule.MODULE_NAME to
|
|
49
|
-
ReactModuleInfo(
|
|
50
|
-
/* name */ DigiaModule.MODULE_NAME,
|
|
51
|
-
/* className */ DigiaModule.MODULE_NAME,
|
|
52
|
-
/* canOverrideExistingModule */ false,
|
|
53
|
-
/* needsEagerInit */ false,
|
|
54
|
-
/* isCxxModule */ false,
|
|
55
|
-
/* isTurboModule */ false,
|
|
56
|
-
),
|
|
57
|
-
)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ─── View Managers ────────────────────────────────────────────────────────
|
|
61
|
-
|
|
62
|
-
override fun createViewManagers(
|
|
63
|
-
reactContext: ReactApplicationContext,
|
|
64
|
-
): List<ViewManager<*, *>> =
|
|
65
|
-
listOf(
|
|
66
|
-
DigiaViewManager(),
|
|
67
|
-
DigiaSlotViewManager(),
|
|
68
|
-
DigiaAnchorViewManager(),
|
|
69
|
-
)
|
|
70
|
-
}
|