diff --git a/android/src/androidTest/assets/Environment.json b/android/src/androidTest/assets/Environment.json index 962cb8b..9706a22 100644 --- a/android/src/androidTest/assets/Environment.json +++ b/android/src/androidTest/assets/Environment.json @@ -12,7 +12,7 @@ ], "project": { "clickOutsideClose": true, - "darkOverlay": false, + "overlay": "none", "id": "cm6ovvfnv0003sf0k7zi8r3ac", "inAppSurveyBranding": true, "placement": "bottomRight", diff --git a/android/src/androidTest/java/com/formbricks/android/manager/SurveyManagerInstrumentedTest.kt b/android/src/androidTest/java/com/formbricks/android/manager/SurveyManagerInstrumentedTest.kt index 9d4b56f..bf6aec4 100644 --- a/android/src/androidTest/java/com/formbricks/android/manager/SurveyManagerInstrumentedTest.kt +++ b/android/src/androidTest/java/com/formbricks/android/manager/SurveyManagerInstrumentedTest.kt @@ -15,6 +15,8 @@ class SurveyManagerInstrumentedTest { fun setup() { // Reset UserManager state before each test UserManager.lastDisplayedAt = null + // Reset SurveyManager environment state + setBackingEnvironmentDataHolder(null) } @Test @@ -430,6 +432,155 @@ class SurveyManagerInstrumentedTest { assertEquals(survey6.id, result5[0].id) } + // region resolveOverlay tests + + @Test + fun testResolveOverlay_nullSurvey_nullEnvironment_returnsNone() { + setBackingEnvironmentDataHolder(null) + val result = SurveyManager.resolveOverlay(null) + assertEquals(SurveyOverlay.NONE, result) + } + + @Test + fun testResolveOverlay_nullSurvey_projectOverlayDark_returnsDark() { + setBackingEnvironmentDataHolder(createEnvHolder(projectOverlay = SurveyOverlay.DARK)) + val result = SurveyManager.resolveOverlay(null) + assertEquals(SurveyOverlay.DARK, result) + } + + @Test + fun testResolveOverlay_nullSurvey_projectOverlayLight_returnsLight() { + setBackingEnvironmentDataHolder(createEnvHolder(projectOverlay = SurveyOverlay.LIGHT)) + val result = SurveyManager.resolveOverlay(null) + assertEquals(SurveyOverlay.LIGHT, result) + } + + @Test + fun testResolveOverlay_nullSurvey_projectOverlayNone_returnsNone() { + setBackingEnvironmentDataHolder(createEnvHolder(projectOverlay = SurveyOverlay.NONE)) + val result = SurveyManager.resolveOverlay(null) + assertEquals(SurveyOverlay.NONE, result) + } + + @Test + fun testResolveOverlay_nullSurvey_projectOverlayNull_returnsNone() { + setBackingEnvironmentDataHolder(createEnvHolder(projectOverlay = null)) + val result = SurveyManager.resolveOverlay(null) + assertEquals(SurveyOverlay.NONE, result) + } + + @Test + fun testResolveOverlay_surveyWithoutProjectOverwrites_fallsBackToProject() { + setBackingEnvironmentDataHolder(createEnvHolder(projectOverlay = SurveyOverlay.DARK)) + val survey = createTestSurvey() // projectOverwrites defaults to null + val result = SurveyManager.resolveOverlay(survey) + assertEquals(SurveyOverlay.DARK, result) + } + + @Test + fun testResolveOverlay_surveyOverwritesOverlayNull_fallsBackToProject() { + setBackingEnvironmentDataHolder(createEnvHolder(projectOverlay = SurveyOverlay.DARK)) + val survey = createSurveyWithOverwrites(overlay = null) + val result = SurveyManager.resolveOverlay(survey) + assertEquals(SurveyOverlay.DARK, result) + } + + @Test + fun testResolveOverlay_surveyOverwritesOverlayLight_overridesProjectDark() { + setBackingEnvironmentDataHolder(createEnvHolder(projectOverlay = SurveyOverlay.DARK)) + val survey = createSurveyWithOverwrites(overlay = SurveyOverlay.LIGHT) + val result = SurveyManager.resolveOverlay(survey) + assertEquals(SurveyOverlay.LIGHT, result) + } + + @Test + fun testResolveOverlay_surveyOverwritesOverlayDark_overridesProjectNone() { + setBackingEnvironmentDataHolder(createEnvHolder(projectOverlay = SurveyOverlay.NONE)) + val survey = createSurveyWithOverwrites(overlay = SurveyOverlay.DARK) + val result = SurveyManager.resolveOverlay(survey) + assertEquals(SurveyOverlay.DARK, result) + } + + @Test + fun testResolveOverlay_surveyOverwritesOverlayNone_overridesProjectDark() { + setBackingEnvironmentDataHolder(createEnvHolder(projectOverlay = SurveyOverlay.DARK)) + val survey = createSurveyWithOverwrites(overlay = SurveyOverlay.NONE) + val result = SurveyManager.resolveOverlay(survey) + assertEquals(SurveyOverlay.NONE, result) + } + + @Test + fun testResolveOverlay_environmentDataHolderDataNull_returnsNone() { + // data=null forces the ?.data?.project?.overlay chain to short-circuit at each null check + val envHolder = EnvironmentDataHolder(data = null, originalResponseMap = mapOf()) + setBackingEnvironmentDataHolder(envHolder) + val result = SurveyManager.resolveOverlay(null) + assertEquals(SurveyOverlay.NONE, result) + } + + @Test + fun testResolveOverlay_surveyWithOverwritesNoOverlay_environmentDataNull_returnsNone() { + val envHolder = EnvironmentDataHolder(data = null, originalResponseMap = mapOf()) + setBackingEnvironmentDataHolder(envHolder) + val survey = createSurveyWithOverwrites(overlay = null) + val result = SurveyManager.resolveOverlay(survey) + assertEquals(SurveyOverlay.NONE, result) + } + + // endregion + + // region helper methods + + private fun setBackingEnvironmentDataHolder(value: EnvironmentDataHolder?) { + val field = SurveyManager::class.java.getDeclaredField("backingEnvironmentDataHolder") + field.isAccessible = true + field.set(SurveyManager, value) + } + + private fun createEnvHolder(projectOverlay: SurveyOverlay?): EnvironmentDataHolder { + val project = Project( + id = "proj1", + recontactDays = null, + clickOutsideClose = null, + overlay = projectOverlay, + placement = null, + inAppSurveyBranding = null, + styling = null + ) + val envData = EnvironmentData( + surveys = emptyList(), + actionClasses = null, + project = project + ) + val envResponseData = EnvironmentResponseData( + data = envData, + expiresAt = null + ) + return EnvironmentDataHolder( + data = envResponseData, + originalResponseMap = mapOf() + ) + } + + private fun createSurveyWithOverwrites(overlay: SurveyOverlay?): Survey { + return Survey( + id = "test", + name = "Test Survey", + triggers = null, + recontactDays = null, + displayLimit = null, + delay = null, + displayPercentage = null, + displayOption = null, + segment = null, + styling = null, + languages = null, + projectOverwrites = SurveyProjectOverwrites(overlay = overlay) + ) + } + + // endregion + private fun createTestSurvey( id: String = "test", displayOption: String? = null, @@ -466,4 +617,4 @@ class SurveyManagerInstrumentedTest { languages = null ) } -} \ No newline at end of file +} \ No newline at end of file diff --git a/android/src/androidTest/java/com/formbricks/android/webview/FormbricksViewModelInstrumentedTest.kt b/android/src/androidTest/java/com/formbricks/android/webview/FormbricksViewModelInstrumentedTest.kt index d3f7556..6b37dbc 100644 --- a/android/src/androidTest/java/com/formbricks/android/webview/FormbricksViewModelInstrumentedTest.kt +++ b/android/src/androidTest/java/com/formbricks/android/webview/FormbricksViewModelInstrumentedTest.kt @@ -8,6 +8,8 @@ import com.formbricks.android.model.environment.EnvironmentResponseData import com.formbricks.android.model.environment.EnvironmentData import com.formbricks.android.model.environment.Project import com.formbricks.android.model.environment.Survey +import com.formbricks.android.model.environment.SurveyOverlay +import com.formbricks.android.model.environment.SurveyProjectOverwrites import org.junit.Assert.* import org.junit.Before import org.junit.Test @@ -48,7 +50,7 @@ class FormbricksViewModelInstrumentedTest { id = "proj1", recontactDays = null, clickOutsideClose = null, - darkOverlay = null, + overlay = null, placement = null, inAppSurveyBranding = null, styling = null @@ -77,5 +79,315 @@ class FormbricksViewModelInstrumentedTest { assertTrue(json.contains("env123")) assertTrue(json.contains("contact123")) assertTrue(json.contains("\"languageCode\":\"default\"")) + // defaults: clickOutside=false, overlay="none" when both project and survey are null + assertTrue(json.contains("\"clickOutside\":false")) + assertTrue(json.contains("\"overlay\":\"none\"")) } -} \ No newline at end of file + + // region clickOutside tests + + @Test + fun testGetJson_clickOutside_projectTrue_noOverwrites_returnsTrue() { + val json = invokeGetJson( + projectClickOutsideClose = true, + surveyOverwrites = null + ) + assertTrue(json.contains("\"clickOutside\":true")) + } + + @Test + fun testGetJson_clickOutside_projectFalse_noOverwrites_returnsFalse() { + val json = invokeGetJson( + projectClickOutsideClose = false, + surveyOverwrites = null + ) + assertTrue(json.contains("\"clickOutside\":false")) + } + + @Test + fun testGetJson_clickOutside_projectNull_noOverwrites_returnsFalse() { + val json = invokeGetJson( + projectClickOutsideClose = null, + surveyOverwrites = null + ) + assertTrue(json.contains("\"clickOutside\":false")) + } + + @Test + fun testGetJson_clickOutside_surveyOverwriteTrue_overridesProjectFalse() { + val json = invokeGetJson( + projectClickOutsideClose = false, + surveyOverwrites = SurveyProjectOverwrites(clickOutsideClose = true) + ) + assertTrue(json.contains("\"clickOutside\":true")) + } + + @Test + fun testGetJson_clickOutside_surveyOverwriteFalse_overridesProjectTrue() { + val json = invokeGetJson( + projectClickOutsideClose = true, + surveyOverwrites = SurveyProjectOverwrites(clickOutsideClose = false) + ) + assertTrue(json.contains("\"clickOutside\":false")) + } + + @Test + fun testGetJson_clickOutside_surveyOverwriteNull_fallsBackToProject() { + val json = invokeGetJson( + projectClickOutsideClose = true, + surveyOverwrites = SurveyProjectOverwrites(clickOutsideClose = null) + ) + assertTrue(json.contains("\"clickOutside\":true")) + } + + // endregion + + // region overlay tests + + @Test + fun testGetJson_overlay_projectDark_noOverwrites_returnsDark() { + val json = invokeGetJson( + projectOverlay = SurveyOverlay.DARK, + surveyOverwrites = null + ) + assertTrue(json.contains("\"overlay\":\"dark\"")) + } + + @Test + fun testGetJson_overlay_projectLight_noOverwrites_returnsLight() { + val json = invokeGetJson( + projectOverlay = SurveyOverlay.LIGHT, + surveyOverwrites = null + ) + assertTrue(json.contains("\"overlay\":\"light\"")) + } + + @Test + fun testGetJson_overlay_projectNone_noOverwrites_returnsNone() { + val json = invokeGetJson( + projectOverlay = SurveyOverlay.NONE, + surveyOverwrites = null + ) + assertTrue(json.contains("\"overlay\":\"none\"")) + } + + @Test + fun testGetJson_overlay_projectNull_noOverwrites_returnsNone() { + val json = invokeGetJson( + projectOverlay = null, + surveyOverwrites = null + ) + assertTrue(json.contains("\"overlay\":\"none\"")) + } + + @Test + fun testGetJson_overlay_surveyOverwriteDark_overridesProjectNone() { + val json = invokeGetJson( + projectOverlay = SurveyOverlay.NONE, + surveyOverwrites = SurveyProjectOverwrites(overlay = SurveyOverlay.DARK) + ) + assertTrue(json.contains("\"overlay\":\"dark\"")) + } + + @Test + fun testGetJson_overlay_surveyOverwriteLight_overridesProjectDark() { + val json = invokeGetJson( + projectOverlay = SurveyOverlay.DARK, + surveyOverwrites = SurveyProjectOverwrites(overlay = SurveyOverlay.LIGHT) + ) + assertTrue(json.contains("\"overlay\":\"light\"")) + } + + @Test + fun testGetJson_overlay_surveyOverwriteNone_overridesProjectDark() { + val json = invokeGetJson( + projectOverlay = SurveyOverlay.DARK, + surveyOverwrites = SurveyProjectOverwrites(overlay = SurveyOverlay.NONE) + ) + assertTrue(json.contains("\"overlay\":\"none\"")) + } + + @Test + fun testGetJson_overlay_surveyOverwriteNull_fallsBackToProject() { + val json = invokeGetJson( + projectOverlay = SurveyOverlay.DARK, + surveyOverwrites = SurveyProjectOverwrites(overlay = null) + ) + assertTrue(json.contains("\"overlay\":\"dark\"")) + } + + // endregion + + // region combined clickOutside + overlay tests + + @Test + fun testGetJson_clickOutsideAndOverlay_bothFromSurveyOverwrites() { + val json = invokeGetJson( + projectClickOutsideClose = true, + projectOverlay = SurveyOverlay.NONE, + surveyOverwrites = SurveyProjectOverwrites( + clickOutsideClose = false, + overlay = SurveyOverlay.DARK + ) + ) + assertTrue(json.contains("\"clickOutside\":false")) + assertTrue(json.contains("\"overlay\":\"dark\"")) + } + + @Test + fun testGetJson_clickOutsideAndOverlay_bothFromProject() { + val json = invokeGetJson( + projectClickOutsideClose = true, + projectOverlay = SurveyOverlay.LIGHT, + surveyOverwrites = null + ) + assertTrue(json.contains("\"clickOutside\":true")) + assertTrue(json.contains("\"overlay\":\"light\"")) + } + + // endregion + + // region matchedSurvey null tests (surveys=null forces matchedSurvey to null) + + @Test + fun testGetJson_noMatchedSurvey_clickOutsideFallsBackToProject() { + val json = invokeGetJsonWithNoSurveys( + projectClickOutsideClose = true, + projectOverlay = SurveyOverlay.NONE + ) + assertTrue(json.contains("\"clickOutside\":true")) + } + + @Test + fun testGetJson_noMatchedSurvey_clickOutsideProjectNull_returnsFalse() { + val json = invokeGetJsonWithNoSurveys( + projectClickOutsideClose = null, + projectOverlay = SurveyOverlay.NONE + ) + assertTrue(json.contains("\"clickOutside\":false")) + } + + @Test + fun testGetJson_noMatchedSurvey_overlayFallsBackToProject() { + val json = invokeGetJsonWithNoSurveys( + projectClickOutsideClose = null, + projectOverlay = SurveyOverlay.DARK + ) + assertTrue(json.contains("\"overlay\":\"dark\"")) + } + + @Test + fun testGetJson_noMatchedSurvey_overlayProjectNull_returnsNone() { + val json = invokeGetJsonWithNoSurveys( + projectClickOutsideClose = null, + projectOverlay = null + ) + assertTrue(json.contains("\"overlay\":\"none\"")) + } + + @Test + fun testGetJson_noMatchedSurvey_bothFallBackToProject() { + val json = invokeGetJsonWithNoSurveys( + projectClickOutsideClose = true, + projectOverlay = SurveyOverlay.LIGHT + ) + assertTrue(json.contains("\"clickOutside\":true")) + assertTrue(json.contains("\"overlay\":\"light\"")) + } + + // endregion + + // region helpers + + private fun invokeGetJson( + projectClickOutsideClose: Boolean? = null, + projectOverlay: SurveyOverlay? = null, + surveyOverwrites: SurveyProjectOverwrites? = null + ): String { + val surveyId = "survey1" + val survey = Survey( + id = surveyId, + name = "Test Survey", + triggers = null, + recontactDays = null, + displayLimit = null, + delay = null, + displayPercentage = null, + displayOption = null, + segment = null, + styling = null, + languages = null, + projectOverwrites = surveyOverwrites + ) + val project = Project( + id = "proj1", + recontactDays = null, + clickOutsideClose = projectClickOutsideClose, + overlay = projectOverlay, + placement = null, + inAppSurveyBranding = null, + styling = null + ) + val envData = EnvironmentData( + surveys = listOf(survey), + actionClasses = null, + project = project + ) + val envResponseData = EnvironmentResponseData( + data = envData, + expiresAt = null + ) + val envHolder = EnvironmentDataHolder( + data = envResponseData, + originalResponseMap = mapOf() + ) + return callGetJson(envHolder, surveyId) + } + + /** + * Creates an environment with surveys=null so that matchedSurvey resolves to null. + * This forces clickOutside and overlay to fall through entirely to project-level values, + * covering the bytecode branches where matchedSurvey is null. + */ + private fun invokeGetJsonWithNoSurveys( + projectClickOutsideClose: Boolean? = null, + projectOverlay: SurveyOverlay? = null + ): String { + val project = Project( + id = "proj1", + recontactDays = null, + clickOutsideClose = projectClickOutsideClose, + overlay = projectOverlay, + placement = null, + inAppSurveyBranding = null, + styling = null + ) + val envData = EnvironmentData( + surveys = null, + actionClasses = null, + project = project + ) + val envResponseData = EnvironmentResponseData( + data = envData, + expiresAt = null + ) + val envHolder = EnvironmentDataHolder( + data = envResponseData, + originalResponseMap = mapOf() + ) + return callGetJson(envHolder, "any-survey-id") + } + + private fun callGetJson(envHolder: EnvironmentDataHolder, surveyId: String): String { + val viewModel = FormbricksViewModel() + return viewModel.javaClass.getDeclaredMethod( + "getJson", + EnvironmentDataHolder::class.java, + String::class.java + ) + .apply { isAccessible = true } + .invoke(viewModel, envHolder, surveyId) as String + } + + // endregion +} \ No newline at end of file diff --git a/android/src/main/java/com/formbricks/android/Formbricks.kt b/android/src/main/java/com/formbricks/android/Formbricks.kt index 3d3704e..f490359 100644 --- a/android/src/main/java/com/formbricks/android/Formbricks.kt +++ b/android/src/main/java/com/formbricks/android/Formbricks.kt @@ -10,6 +10,7 @@ import com.formbricks.android.helper.FormbricksConfig import com.formbricks.android.logger.Logger import com.formbricks.android.manager.SurveyManager import com.formbricks.android.manager.UserManager +import com.formbricks.android.model.environment.SurveyOverlay import com.formbricks.android.model.error.SDKError import com.formbricks.android.webview.FormbricksFragment import java.lang.RuntimeException @@ -216,7 +217,7 @@ object Formbricks { } /// Assembles the survey fragment and presents it - internal fun showSurvey(id: String) { + internal fun showSurvey(id: String, overlay: SurveyOverlay = SurveyOverlay.NONE) { if (fragmentManager == null) { val error = SDKError.fragmentManagerIsNotSet Logger.e(error) @@ -224,7 +225,7 @@ object Formbricks { } fragmentManager?.let { - FormbricksFragment.show(it, surveyId = id) + FormbricksFragment.show(it, surveyId = id, overlay = overlay) } } diff --git a/android/src/main/java/com/formbricks/android/manager/SurveyManager.kt b/android/src/main/java/com/formbricks/android/manager/SurveyManager.kt index 042b2de..16e1a2b 100644 --- a/android/src/main/java/com/formbricks/android/manager/SurveyManager.kt +++ b/android/src/main/java/com/formbricks/android/manager/SurveyManager.kt @@ -10,6 +10,7 @@ import com.formbricks.android.model.environment.EnvironmentDataHolder import com.formbricks.android.model.environment.SegmentFilterResource import com.formbricks.android.model.environment.SegmentFilterResourceDeserializer import com.formbricks.android.model.environment.Survey +import com.formbricks.android.model.environment.SurveyOverlay import com.formbricks.android.model.error.SDKError import com.formbricks.android.model.user.Display import com.google.gson.Gson @@ -192,10 +193,11 @@ object SurveyManager { val surveyName = firstSurveyWithActionClass.name Logger.d("Delaying survey \"$surveyName\" by $timeout seconds") } + val overlay = resolveOverlay(firstSurveyWithActionClass) stopDisplayTimer() displayTimer.schedule(object : TimerTask() { override fun run() { - Formbricks.showSurvey(it) + Formbricks.showSurvey(it, overlay) } }, Date(System.currentTimeMillis() + timeout.toLong() * 1000)) @@ -391,4 +393,13 @@ object SurveyManager { // 6) Otherwise return its code return selected.language.code } + + /** + * Resolves the overlay style for the given survey, falling back to the project-level default. + * Survey-level `projectOverwrites.overlay` takes precedence over `project.overlay`. + */ + fun resolveOverlay(survey: Survey?): SurveyOverlay { + survey?.projectOverwrites?.overlay?.let { return it } + return environmentDataHolder?.data?.data?.project?.overlay ?: SurveyOverlay.NONE + } } \ No newline at end of file diff --git a/android/src/main/java/com/formbricks/android/model/environment/Project.kt b/android/src/main/java/com/formbricks/android/model/environment/Project.kt index a749378..f2dedf5 100644 --- a/android/src/main/java/com/formbricks/android/model/environment/Project.kt +++ b/android/src/main/java/com/formbricks/android/model/environment/Project.kt @@ -8,7 +8,7 @@ data class Project( @SerializedName("id") val id: String?, @SerializedName("recontactDays") val recontactDays: Double?, @SerializedName("clickOutsideClose") val clickOutsideClose: Boolean?, - @SerializedName("darkOverlay") val darkOverlay: Boolean?, + @SerializedName("overlay") val overlay: SurveyOverlay?, @SerializedName("placement") val placement: String?, @SerializedName("inAppSurveyBranding") val inAppSurveyBranding: Boolean?, @SerializedName("styling") val styling: Styling? diff --git a/android/src/main/java/com/formbricks/android/model/environment/Survey.kt b/android/src/main/java/com/formbricks/android/model/environment/Survey.kt index 0d84b8e..4c7a756 100644 --- a/android/src/main/java/com/formbricks/android/model/environment/Survey.kt +++ b/android/src/main/java/com/formbricks/android/model/environment/Survey.kt @@ -1,6 +1,7 @@ package com.formbricks.android.model.environment import com.google.gson.annotations.SerializedName +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable @@ -34,11 +35,19 @@ data class Survey( @SerializedName("projectOverwrites") val projectOverwrites: SurveyProjectOverwrites? = null ) +/// Defines the overlay style displayed behind a survey modal. +@Serializable +enum class SurveyOverlay(val value: String) { + @SerialName("none") NONE("none"), + @SerialName("light") LIGHT("light"), + @SerialName("dark") DARK("dark"); +} + @Serializable data class SurveyProjectOverwrites( @SerializedName("brandColor") val brandColor: String? = null, @SerializedName("highlightBorderColor") val highlightBorderColor: String? = null, @SerializedName("clickOutsideClose") val clickOutsideClose: Boolean? = null, @SerializedName("placement") val placement: String? = null, - @SerializedName("darkOverlay") val darkOverlay: Boolean? = null + @SerializedName("overlay") val overlay: SurveyOverlay? = null ) \ No newline at end of file diff --git a/android/src/main/java/com/formbricks/android/webview/FormbricksFragment.kt b/android/src/main/java/com/formbricks/android/webview/FormbricksFragment.kt index 80b0b07..5ee121e 100644 --- a/android/src/main/java/com/formbricks/android/webview/FormbricksFragment.kt +++ b/android/src/main/java/com/formbricks/android/webview/FormbricksFragment.kt @@ -29,6 +29,7 @@ import com.formbricks.android.R import com.formbricks.android.databinding.FragmentFormbricksBinding import com.formbricks.android.logger.Logger import com.formbricks.android.manager.SurveyManager +import com.formbricks.android.model.environment.SurveyOverlay import com.formbricks.android.model.error.SDKError import com.formbricks.android.model.javascript.FileUploadData import com.google.android.material.bottomsheet.BottomSheetBehavior @@ -40,6 +41,7 @@ import java.io.InputStream class FormbricksFragment : BottomSheetDialogFragment() { private lateinit var binding: FragmentFormbricksBinding private lateinit var surveyId: String + private var overlay: SurveyOverlay = SurveyOverlay.NONE private val viewModel: FormbricksViewModel by viewModels() private var isDismissing = false @@ -123,6 +125,9 @@ class FormbricksFragment : BottomSheetDialogFragment() { super.onCreate(savedInstanceState) arguments?.let { surveyId = it.getString(ARG_SURVEY_ID) ?: throw IllegalArgumentException("Survey ID is required") + overlay = it.getString(ARG_OVERLAY)?.let { name -> + try { SurveyOverlay.valueOf(name) } catch (_: Exception) { SurveyOverlay.NONE } + } ?: SurveyOverlay.NONE } } @@ -192,7 +197,7 @@ class FormbricksFragment : BottomSheetDialogFragment() { } override fun onPageCommitVisible(view: WebView?, url: String?) { - dialog?.window?.setDimAmount(0.5f) + dialog?.window?.setDimAmount(dimAmountFor(overlay)) super.onPageCommitVisible(view, url) } } @@ -267,11 +272,22 @@ class FormbricksFragment : BottomSheetDialogFragment() { companion object { private val TAG: String by lazy { FormbricksFragment::class.java.simpleName } private const val ARG_SURVEY_ID = "survey_id" + private const val ARG_OVERLAY = "overlay" + + /// Returns the appropriate dim amount for the given overlay style. + fun dimAmountFor(overlay: SurveyOverlay): Float { + return when (overlay) { + SurveyOverlay.DARK -> 0.6f + SurveyOverlay.LIGHT -> 0.3f + SurveyOverlay.NONE -> 0.0f + } + } - fun show(childFragmentManager: FragmentManager, surveyId: String) { + fun show(childFragmentManager: FragmentManager, surveyId: String, overlay: SurveyOverlay = SurveyOverlay.NONE) { val fragment = FormbricksFragment().apply { arguments = Bundle().apply { putString(ARG_SURVEY_ID, surveyId) + putString(ARG_OVERLAY, overlay.name) } } fragment.show(childFragmentManager, TAG) diff --git a/android/src/main/java/com/formbricks/android/webview/FormbricksViewModel.kt b/android/src/main/java/com/formbricks/android/webview/FormbricksViewModel.kt index 6d3b127..ba49b20 100644 --- a/android/src/main/java/com/formbricks/android/webview/FormbricksViewModel.kt +++ b/android/src/main/java/com/formbricks/android/webview/FormbricksViewModel.kt @@ -9,6 +9,7 @@ import com.formbricks.android.extensions.guard import com.formbricks.android.manager.SurveyManager import com.formbricks.android.manager.UserManager import com.formbricks.android.model.environment.EnvironmentDataHolder +import com.formbricks.android.model.environment.SurveyOverlay import com.formbricks.android.model.environment.getProjectStylingJson import com.formbricks.android.model.environment.getStyling import com.formbricks.android.model.environment.getSurveyJson @@ -147,8 +148,11 @@ class FormbricksViewModel : ViewModel() { val placement = matchedSurvey?.projectOverwrites?.placement ?: project?.placement if (placement != null) jsonObject.addProperty("placement", placement) - val darkOverlay = matchedSurvey?.projectOverwrites?.darkOverlay ?: project?.darkOverlay - if (darkOverlay != null) jsonObject.addProperty("darkOverlay", darkOverlay) + val clickOutside = matchedSurvey?.projectOverwrites?.clickOutsideClose ?: project?.clickOutsideClose ?: false + jsonObject.addProperty("clickOutside", clickOutside) + + val overlay = (matchedSurvey?.projectOverwrites?.overlay ?: project?.overlay ?: SurveyOverlay.NONE).value + jsonObject.addProperty("overlay", overlay) val enabled = project?.styling?.allowStyleOverwrite ?: false if (hasCustomStyling && enabled) {