From 89794f32ed7d8de3f699bfa5f985c179c5b3762c Mon Sep 17 00:00:00 2001 From: Shahroz Khan Date: Fri, 26 May 2023 18:57:47 +0500 Subject: [PATCH] feat: dismiss in-app message (#186) --- .../java/io/customer/commontest/BaseTest.kt | 6 ++-- messaginginapp/api/messaginginapp.api | 10 ++++++ .../messaginginapp/ModuleMessagingInApp.kt | 14 ++++++--- .../messaginginapp/di/DIGraphMessaginIApp.kt | 7 +++++ .../provider/GistApiProvider.kt | 12 ++++++- .../provider/GistInAppMessagesProvider.kt | 8 ++++- .../ModuleMessagingInAppTest.kt | 31 +++++++++++++++++++ .../messagingpush/di/DiGraphMessagingPush.kt | 8 ++--- .../ModuleMessagingConfigTest.kt | 12 +++---- sdk/api/sdk.api | 2 +- .../main/java/io/customer/sdk/CustomerIO.kt | 2 +- .../java/io/customer/sdk/CustomerIOConfig.kt | 4 +-- 12 files changed, 92 insertions(+), 24 deletions(-) diff --git a/common-test/src/main/java/io/customer/commontest/BaseTest.kt b/common-test/src/main/java/io/customer/commontest/BaseTest.kt index e52279dbf..9994157f1 100644 --- a/common-test/src/main/java/io/customer/commontest/BaseTest.kt +++ b/common-test/src/main/java/io/customer/commontest/BaseTest.kt @@ -11,7 +11,7 @@ import io.customer.sdk.data.store.Client import io.customer.sdk.data.store.DeviceStore import io.customer.sdk.di.CustomerIOComponent import io.customer.sdk.di.CustomerIOStaticComponent -import io.customer.sdk.module.CustomerIOModuleConfig +import io.customer.sdk.module.CustomerIOModule import io.customer.sdk.util.* import okhttp3.ResponseBody.Companion.toResponseBody import okhttp3.mockwebserver.MockWebServer @@ -67,7 +67,7 @@ abstract class BaseTest { backgroundQueueTaskExpiredSeconds: Double = Seconds.fromDays(3).value, logLevel: CioLogLevel = CioLogLevel.DEBUG, trackingApiUrl: String? = null, - configurations: Map = emptyMap() + modules: Map> = emptyMap() ) = CustomerIOConfig( client = client, siteId = siteId, @@ -81,7 +81,7 @@ abstract class BaseTest { backgroundQueueTaskExpiredSeconds = backgroundQueueTaskExpiredSeconds, logLevel = logLevel, trackingApiUrl = trackingApiUrl, - configurations = configurations + modules = modules ) // override in test class to override SDK config for all test functions in the class. diff --git a/messaginginapp/api/messaginginapp.api b/messaginginapp/api/messaginginapp.api index 8b6e25348..e9ab97b57 100644 --- a/messaginginapp/api/messaginginapp.api +++ b/messaginginapp/api/messaginginapp.api @@ -15,18 +15,28 @@ public final class io/customer/messaginginapp/MessagingInAppModuleConfig$Compani } public final class io/customer/messaginginapp/ModuleMessagingInApp : io/customer/sdk/module/CustomerIOModule { + public static final field Companion Lio/customer/messaginginapp/ModuleMessagingInApp$Companion; + public static final field moduleName Ljava/lang/String; public fun ()V public fun (Lio/customer/messaginginapp/MessagingInAppModuleConfig;)V public synthetic fun (Lio/customer/messaginginapp/MessagingInAppModuleConfig;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun (Ljava/lang/String;)V public fun (Ljava/lang/String;Lio/customer/messaginginapp/MessagingInAppModuleConfig;)V public synthetic fun (Ljava/lang/String;Lio/customer/messaginginapp/MessagingInAppModuleConfig;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun dismissMessage ()V public fun getModuleConfig ()Lio/customer/messaginginapp/MessagingInAppModuleConfig; public synthetic fun getModuleConfig ()Lio/customer/sdk/module/CustomerIOModuleConfig; public fun getModuleName ()Ljava/lang/String; public fun initialize ()V } +public final class io/customer/messaginginapp/ModuleMessagingInApp$Companion { +} + +public final class io/customer/messaginginapp/di/DIGraphMessaginIAppKt { + public static final fun inAppMessaging (Lio/customer/sdk/CustomerIO;)Lio/customer/messaginginapp/ModuleMessagingInApp; +} + public abstract interface class io/customer/messaginginapp/type/InAppEventListener { public abstract fun errorWithMessage (Lio/customer/messaginginapp/type/InAppMessage;)V public abstract fun messageActionTaken (Lio/customer/messaginginapp/type/InAppMessage;Ljava/lang/String;Ljava/lang/String;)V diff --git a/messaginginapp/src/main/java/io/customer/messaginginapp/ModuleMessagingInApp.kt b/messaginginapp/src/main/java/io/customer/messaginginapp/ModuleMessagingInApp.kt index a2a96d836..958c270a9 100644 --- a/messaginginapp/src/main/java/io/customer/messaginginapp/ModuleMessagingInApp.kt +++ b/messaginginapp/src/main/java/io/customer/messaginginapp/ModuleMessagingInApp.kt @@ -15,8 +15,7 @@ import io.customer.sdk.module.CustomerIOModule import io.customer.sdk.repository.TrackRepository class ModuleMessagingInApp -@VisibleForTesting -@InternalCustomerIOApi +@VisibleForTesting @InternalCustomerIOApi internal constructor( override val moduleConfig: MessagingInAppModuleConfig = MessagingInAppModuleConfig.default(), private val overrideDiGraph: CustomerIOComponent? @@ -43,8 +42,7 @@ internal constructor( overrideDiGraph = null ) - override val moduleName: String - get() = "MessagingInApp" + override val moduleName: String = ModuleMessagingInApp.moduleName private val diGraph: CustomerIOComponent get() = overrideDiGraph ?: CustomerIO.instance().diGraph @@ -64,6 +62,14 @@ internal constructor( private val config: CustomerIOConfig get() = diGraph.sdkConfig + companion object { + const val moduleName: String = "MessagingInApp" + } + + fun dismissMessage() { + gistProvider.dismissMessage() + } + override fun initialize() { initializeGist(config) setupHooks() diff --git a/messaginginapp/src/main/java/io/customer/messaginginapp/di/DIGraphMessaginIApp.kt b/messaginginapp/src/main/java/io/customer/messaginginapp/di/DIGraphMessaginIApp.kt index 9f32cb026..422249aa6 100644 --- a/messaginginapp/src/main/java/io/customer/messaginginapp/di/DIGraphMessaginIApp.kt +++ b/messaginginapp/src/main/java/io/customer/messaginginapp/di/DIGraphMessaginIApp.kt @@ -1,9 +1,11 @@ package io.customer.messaginginapp.di +import io.customer.messaginginapp.ModuleMessagingInApp import io.customer.messaginginapp.provider.GistApi import io.customer.messaginginapp.provider.GistApiProvider import io.customer.messaginginapp.provider.GistInAppMessagesProvider import io.customer.messaginginapp.provider.InAppMessagesProvider +import io.customer.sdk.CustomerIO import io.customer.sdk.di.CustomerIOComponent internal val CustomerIOComponent.gistApiProvider: GistApi @@ -11,3 +13,8 @@ internal val CustomerIOComponent.gistApiProvider: GistApi internal val CustomerIOComponent.gistProvider: InAppMessagesProvider get() = override() ?: GistInAppMessagesProvider(gistApiProvider) + +fun CustomerIO.inAppMessaging(): ModuleMessagingInApp { + return diGraph.sdkConfig.modules[ModuleMessagingInApp.moduleName] as? ModuleMessagingInApp + ?: throw IllegalStateException("ModuleMessagingInApp not initialized") +} diff --git a/messaginginapp/src/main/java/io/customer/messaginginapp/provider/GistApiProvider.kt b/messaginginapp/src/main/java/io/customer/messaginginapp/provider/GistApiProvider.kt index dc1b60250..b21d44d09 100644 --- a/messaginginapp/src/main/java/io/customer/messaginginapp/provider/GistApiProvider.kt +++ b/messaginginapp/src/main/java/io/customer/messaginginapp/provider/GistApiProvider.kt @@ -15,6 +15,7 @@ internal interface GistApi { fun setCurrentRoute(route: String) fun clearUserToken() fun addListener(listener: GistListener) + fun dismissMessage() fun subscribeToEvents( onMessageShown: (deliveryId: String) -> Unit, onAction: (deliveryId: String?, currentRoute: String, action: String, name: String) -> Unit, @@ -47,6 +48,10 @@ internal class GistApiProvider : GistApi { GistSdk.addListener(listener) } + override fun dismissMessage() { + GistSdk.dismissMessage() + } + override fun subscribeToEvents( onMessageShown: (String) -> Unit, onAction: (deliveryId: String?, currentRoute: String, action: String, name: String) -> Unit, @@ -56,7 +61,12 @@ internal class GistApiProvider : GistApi { override fun embedMessage(message: Message, elementId: String) { } - override fun onAction(message: Message, currentRoute: String, action: String, name: String) { + override fun onAction( + message: Message, + currentRoute: String, + action: String, + name: String + ) { val deliveryID = GistMessageProperties.getGistProperties(message).campaignId onAction(deliveryID, currentRoute, action, name) } diff --git a/messaginginapp/src/main/java/io/customer/messaginginapp/provider/GistInAppMessagesProvider.kt b/messaginginapp/src/main/java/io/customer/messaginginapp/provider/GistInAppMessagesProvider.kt index a369b588c..855d8121b 100644 --- a/messaginginapp/src/main/java/io/customer/messaginginapp/provider/GistInAppMessagesProvider.kt +++ b/messaginginapp/src/main/java/io/customer/messaginginapp/provider/GistInAppMessagesProvider.kt @@ -12,6 +12,7 @@ internal interface InAppMessagesProvider { fun setCurrentRoute(route: String) fun clearUserToken() fun setListener(listener: InAppEventListener) + fun dismissMessage() fun subscribeToEvents( onMessageShown: (deliveryId: String) -> Unit, onAction: (deliveryId: String, currentRoute: String, action: String, name: String) -> Unit, @@ -23,7 +24,8 @@ internal interface InAppMessagesProvider { * Wrapper around Gist SDK */ internal class GistInAppMessagesProvider(private val provider: GistApi) : - InAppMessagesProvider, GistListener { + InAppMessagesProvider, + GistListener { private var listener: InAppEventListener? = null @@ -51,6 +53,10 @@ internal class GistInAppMessagesProvider(private val provider: GistApi) : this.listener = listener } + override fun dismissMessage() { + provider.dismissMessage() + } + override fun subscribeToEvents( onMessageShown: (String) -> Unit, onAction: (deliveryId: String, currentRoute: String, action: String, name: String) -> Unit, diff --git a/messaginginapp/src/sharedTest/java/io/customer/messaginginapp/ModuleMessagingInAppTest.kt b/messaginginapp/src/sharedTest/java/io/customer/messaginginapp/ModuleMessagingInAppTest.kt index bdc290346..9a1125c6f 100644 --- a/messaginginapp/src/sharedTest/java/io/customer/messaginginapp/ModuleMessagingInAppTest.kt +++ b/messaginginapp/src/sharedTest/java/io/customer/messaginginapp/ModuleMessagingInAppTest.kt @@ -2,11 +2,16 @@ package io.customer.messaginginapp import androidx.test.ext.junit.runners.AndroidJUnit4 import io.customer.commontest.BaseTest +import io.customer.messaginginapp.di.inAppMessaging import io.customer.messaginginapp.provider.InAppMessagesProvider import io.customer.messaginginapp.type.InAppEventListener +import io.customer.sdk.CustomerIO +import io.customer.sdk.CustomerIOConfig +import io.customer.sdk.data.model.Region import io.customer.sdk.extensions.random import io.customer.sdk.hooks.HookModule import io.customer.sdk.hooks.HooksManager +import io.customer.sdk.module.CustomerIOModule import io.customer.sdk.repository.preference.SitePreferenceRepository import java.lang.reflect.Field import org.amshove.kluent.shouldBe @@ -25,6 +30,12 @@ internal class ModuleMessagingInAppTest : BaseTest() { private val prefRepository: SitePreferenceRepository get() = di.sitePreferenceRepository + private val modules = hashMapOf>() + + override fun setupConfig(): CustomerIOConfig = createConfig( + modules = modules + ) + @Before override fun setup() { super.setup() @@ -37,6 +48,7 @@ internal class ModuleMessagingInAppTest : BaseTest() { .build(), overrideDiGraph = di ) + modules[ModuleMessagingInApp.moduleName] = module } @Test @@ -112,4 +124,23 @@ internal class ModuleMessagingInAppTest : BaseTest() { organizationId?.isAccessible = true (organizationId?.get(module)) shouldBe null } + + @Test + fun whenDismissMessageCalledOnCustomerIO_thenDismissMessageIsCalledOnGist() { + // initialize the SDK + val customerIO = CustomerIO.Builder( + siteId = siteId, + apiKey = String.random, + region = Region.US, + appContext = application + ).apply { + overrideDiGraph = di + }.build() + + // call dismissMessage on the CustomerIO instance + customerIO.inAppMessaging().dismissMessage() + + // verify that the module's dismissMessage method was called + verify(gistInAppMessagesProvider).dismissMessage() + } } diff --git a/messagingpush/src/main/java/io/customer/messagingpush/di/DiGraphMessagingPush.kt b/messagingpush/src/main/java/io/customer/messagingpush/di/DiGraphMessagingPush.kt index f5e5f7b83..15f6a51ba 100644 --- a/messagingpush/src/main/java/io/customer/messagingpush/di/DiGraphMessagingPush.kt +++ b/messagingpush/src/main/java/io/customer/messagingpush/di/DiGraphMessagingPush.kt @@ -20,11 +20,9 @@ internal val CustomerIOComponent.fcmTokenProvider: DeviceTokenProvider get() = override() ?: FCMTokenProviderImpl(logger = logger, context = context) internal val CustomerIOComponent.moduleConfig: MessagingPushModuleConfig - get() = override() ?: sdkConfig.configurations.getOrElse( - ModuleMessagingPushFCM.MODULE_NAME - ) { - MessagingPushModuleConfig.default() - } as MessagingPushModuleConfig + get() = override() + ?: sdkConfig.modules[ModuleMessagingPushFCM.MODULE_NAME]?.moduleConfig as? MessagingPushModuleConfig + ?: MessagingPushModuleConfig.default() internal val CustomerIOComponent.deepLinkUtil: DeepLinkUtil get() = override() ?: DeepLinkUtilImpl(logger, moduleConfig) diff --git a/messagingpush/src/sharedTest/java/io/customer/messagingpush/ModuleMessagingConfigTest.kt b/messagingpush/src/sharedTest/java/io/customer/messagingpush/ModuleMessagingConfigTest.kt index 68ee7cc58..52f279675 100644 --- a/messagingpush/src/sharedTest/java/io/customer/messagingpush/ModuleMessagingConfigTest.kt +++ b/messagingpush/src/sharedTest/java/io/customer/messagingpush/ModuleMessagingConfigTest.kt @@ -7,7 +7,7 @@ import io.customer.messagingpush.di.moduleConfig import io.customer.sdk.CustomerIOConfig import io.customer.sdk.CustomerIOInstance import io.customer.sdk.device.DeviceTokenProvider -import io.customer.sdk.module.CustomerIOModuleConfig +import io.customer.sdk.module.CustomerIOModule import org.amshove.kluent.shouldBeFalse import org.amshove.kluent.shouldBeNull import org.amshove.kluent.shouldBeTrue @@ -24,10 +24,10 @@ internal class ModuleMessagingConfigTest : BaseTest() { private val customerIOMock: CustomerIOInstance = mock() private val fcmTokenProviderMock: DeviceTokenProvider = mock() - private val configurations = hashMapOf() + private val modules = hashMapOf>() override fun setupConfig(): CustomerIOConfig = createConfig( - configurations = configurations + modules = modules ) @Before @@ -48,7 +48,7 @@ internal class ModuleMessagingConfigTest : BaseTest() { overrideDiGraph = di ) - configurations[ModuleMessagingPushFCM.MODULE_NAME] = module.moduleConfig + modules[ModuleMessagingPushFCM.MODULE_NAME] = module val moduleConfig = di.moduleConfig moduleConfig.notificationCallback.shouldBeNull() @@ -63,7 +63,7 @@ internal class ModuleMessagingConfigTest : BaseTest() { overrideDiGraph = di ) - configurations[ModuleMessagingPushFCM.MODULE_NAME] = module.moduleConfig + modules[ModuleMessagingPushFCM.MODULE_NAME] = module val moduleConfig = di.moduleConfig moduleConfig.autoTrackPushEvents.shouldBeTrue() @@ -83,7 +83,7 @@ internal class ModuleMessagingConfigTest : BaseTest() { overrideDiGraph = di ) - configurations[ModuleMessagingPushFCM.MODULE_NAME] = module.moduleConfig + modules[ModuleMessagingPushFCM.MODULE_NAME] = module val moduleConfig = di.moduleConfig moduleConfig.autoTrackPushEvents.shouldBeFalse() diff --git a/sdk/api/sdk.api b/sdk/api/sdk.api index 6b9fc51e9..4a6a1356e 100644 --- a/sdk/api/sdk.api +++ b/sdk/api/sdk.api @@ -84,8 +84,8 @@ public final class io/customer/sdk/CustomerIOConfig { public final fun getBackgroundQueueSecondsDelay ()D public final fun getBackgroundQueueTaskExpiredSeconds ()D public final fun getClient ()Lio/customer/sdk/data/store/Client; - public final fun getConfigurations ()Ljava/util/Map; public final fun getLogLevel ()Lio/customer/sdk/util/CioLogLevel; + public final fun getModules ()Ljava/util/Map; public final fun getRegion ()Lio/customer/sdk/data/model/Region; public final fun getSiteId ()Ljava/lang/String; public final fun getTimeout ()J diff --git a/sdk/src/main/java/io/customer/sdk/CustomerIO.kt b/sdk/src/main/java/io/customer/sdk/CustomerIO.kt index 4e214b3e1..58b9722af 100644 --- a/sdk/src/main/java/io/customer/sdk/CustomerIO.kt +++ b/sdk/src/main/java/io/customer/sdk/CustomerIO.kt @@ -332,7 +332,7 @@ class CustomerIO internal constructor( backgroundQueueTaskExpiredSeconds = Seconds.fromDays(3).value, logLevel = logLevel, trackingApiUrl = trackingApiUrl, - configurations = modules.entries.associate { entry -> entry.key to entry.value.moduleConfig } + modules = modules.entries.associate { entry -> entry.key to entry.value } ) sharedInstance.attachSDKConfig(sdkConfig = config, context = appContext) diff --git a/sdk/src/main/java/io/customer/sdk/CustomerIOConfig.kt b/sdk/src/main/java/io/customer/sdk/CustomerIOConfig.kt index 1bd5fceda..a63a4252b 100644 --- a/sdk/src/main/java/io/customer/sdk/CustomerIOConfig.kt +++ b/sdk/src/main/java/io/customer/sdk/CustomerIOConfig.kt @@ -2,7 +2,7 @@ package io.customer.sdk import io.customer.sdk.data.model.Region import io.customer.sdk.data.store.Client -import io.customer.sdk.module.CustomerIOModuleConfig +import io.customer.sdk.module.CustomerIOModule import io.customer.sdk.util.CioLogLevel data class CustomerIOConfig( @@ -32,7 +32,7 @@ data class CustomerIOConfig( val backgroundQueueTaskExpiredSeconds: Double, val logLevel: CioLogLevel, var trackingApiUrl: String?, - val configurations: Map + val modules: Map> ) { internal val trackingApiHostname: String get() {