Skip to content

Commit

Permalink
Merge pull request #189 from superwall/develop
Browse files Browse the repository at this point in the history
1.3.0
  • Loading branch information
ianrumac authored Oct 11, 2024
2 parents 9cc25f8 + ed46be0 commit f547ffc
Show file tree
Hide file tree
Showing 25 changed files with 279 additions and 50 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

The changelog for `Superwall`. Also see the [releases](https://github.com/superwall/Superwall-Android/releases) on GitHub.

## 1.3.0

### Enhancements
- The existing `getPaywall` method has been deprecated and renamed to `getPaywallOrThrow`. The new `getPaywall` method now returns a `kotlin.Result<PaywallView>` instead of throwing an exception.
- Adds a new option to `SuperwallOptions` - `passIdentifiersToPlayStore` which allows you to pass the user's identifiers (from `Superwall.instance.identify(userId: String, ...)`) to the Play Store when making a purchase. Note: When passing in identifiers to use with the play store, please make sure to follow their [guidelines](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.Builder#setObfuscatedAccountId(java.lang.String).
- Adds `Superwall.instance.confirmAllAssignments()`, which confirms assignments for all placements and returns an array of all confirmed experiment assignments. Note that the assignments may be different when a placement is registered due to changes in user, placement, or device parameters used in audience filters.

### Fixes

- Fixes issues with Paywall sometimes not displaying when returning from background
- Fixes issue with SDK crashing when WebView is not available
- Fixes issue with `SuperwallPaywallActivity` NPE
- Update visibility of internal `getPaywall` methods to `internal` to prevent misuse

## 1.2.9

### Fixes
Expand Down
12 changes: 6 additions & 6 deletions app/src/main/java/com/superwall/superapp/test/UITestHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ object UITestHandler {
// Present using the convenience `SuperwallPaywallActivity` activity and verify test case.
SuperwallPaywallActivity.startWithView(
context = this@UITestInfo,
view = viewController,
view = viewController.getOrThrow(),
)
},
)
Expand Down Expand Up @@ -679,7 +679,7 @@ object UITestHandler {
Superwall.instance.getPaywall(event = "present_data", delegate = delegate)

// Present using the convenience `SuperwallPaywallActivity` activity and verify test case.
SuperwallPaywallActivity.startWithView(context = this, view = view)
SuperwallPaywallActivity.startWithView(context = this, view = view.getOrThrow())
},
)
var test36Info =
Expand All @@ -699,7 +699,7 @@ object UITestHandler {
Superwall.instance.getPaywall(event = "present_data", delegate = delegate)

// Present using the convenience `SuperwallPaywallActivity` activity and verify test case.
SuperwallPaywallActivity.startWithView(context = this, view = viewController)
SuperwallPaywallActivity.startWithView(context = this, view = viewController.getOrThrow())
},
)
var test37Info =
Expand All @@ -720,7 +720,7 @@ object UITestHandler {
Superwall.instance.getPaywall(event = "restore", delegate = delegate)

// Present using the convenience `SuperwallPaywallActivity` activity and verify test case.
SuperwallPaywallActivity.startWithView(context = this, view = viewController)
SuperwallPaywallActivity.startWithView(context = this, view = viewController.getOrThrow())
},
)

Expand Down Expand Up @@ -1053,7 +1053,7 @@ object UITestHandler {
Superwall.instance.getPaywall(event = "restore", delegate = delegate)

// Present using the convenience `SuperwallPaywallActivity` activity and verify test case.
SuperwallPaywallActivity.startWithView(context = this, view = viewController)
SuperwallPaywallActivity.startWithView(context = this, view = viewController.getOrThrow())
},
)
var test64Info =
Expand Down Expand Up @@ -1275,7 +1275,7 @@ object UITestHandler {
)

// Present using the convenience `SuperwallPaywallActivity` activity and verify test case.
SuperwallPaywallActivity.startWithView(context = this, view = viewController)
SuperwallPaywallActivity.startWithView(context = this, view = viewController.getOrThrow())
},
)
var test71Info =
Expand Down
2 changes: 1 addition & 1 deletion superwall/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ plugins {
id("signing")
}

version = "1.2.9"
version = "1.3.0"

android {
compileSdk = 34
Expand Down
67 changes: 67 additions & 0 deletions superwall/src/main/java/com/superwall/sdk/Superwall.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@ import com.superwall.sdk.logger.LogScope
import com.superwall.sdk.logger.Logger
import com.superwall.sdk.misc.ActivityProvider
import com.superwall.sdk.misc.SerialTaskManager
import com.superwall.sdk.models.assignment.ConfirmedAssignment
import com.superwall.sdk.models.events.EventData
import com.superwall.sdk.network.device.InterfaceStyle
import com.superwall.sdk.paywall.presentation.PaywallCloseReason
import com.superwall.sdk.paywall.presentation.PaywallInfo
import com.superwall.sdk.paywall.presentation.PresentationItems
import com.superwall.sdk.paywall.presentation.internal.PresentationRequestType
import com.superwall.sdk.paywall.presentation.internal.confirmAssignment
import com.superwall.sdk.paywall.presentation.internal.dismiss
import com.superwall.sdk.paywall.presentation.internal.request.PresentationInfo
import com.superwall.sdk.paywall.presentation.internal.state.PaywallResult
import com.superwall.sdk.paywall.vc.PaywallView
import com.superwall.sdk.paywall.vc.SuperwallPaywallActivity
Expand Down Expand Up @@ -52,6 +57,7 @@ import kotlinx.coroutines.flow.take
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Date

class Superwall(
context: Context,
Expand Down Expand Up @@ -556,6 +562,67 @@ class Superwall(
}
//endregion

/**
* Gets an array of all confirmed experiment assignments.
* @return An array of `ConfirmedAssignments` objects.
* */

fun getAssignments(): List<ConfirmedAssignment> =
dependencyContainer.storage.getConfirmedAssignments().map { ConfirmedAssignment(it.key, it.value) }

/**
* Confirms all experiment assignments and returns them in an array.
*
* This tracks ``SuperwallEvent/confirmAllAssignments`` in the delegate.
*
* Note that the assignments may be different when a placement is registered due to changes
* in user, placement, or device parameters used in audience filters.
* @return An array of `ConfirmedAssignments` objects.
*/

suspend fun confirmAllAssignments(): List<ConfirmedAssignment> {
val event = InternalSuperwallEvent.ConfirmAllAssignments
track(event)
val triggers = dependencyContainer.configManager.config?.triggers ?: return emptyList()
val storedAssignments = dependencyContainer.storage.getConfirmedAssignments()
val assignments =
storedAssignments
.map {
ConfirmedAssignment(it.key, it.value)
}.toMutableSet()

triggers.forEach {
val eventData = EventData(name = it.eventName, parameters = emptyMap(), createdAt = Date())
val request =
dependencyContainer.makePresentationRequest(
presentationInfo = PresentationInfo.ExplicitTrigger(eventData),
paywallOverrides = null,
isPaywallPresented = false,
type = PresentationRequestType.ConfirmAllAssignments,
)
confirmAssignment(request)?.let {
assignments.add(it)
}
}
return assignments.toList()
}

/**
* Confirms all experiment assignments and returns them in an array.
*
* This tracks ``SuperwallEvent/ConfirmAllAssignments`` in the delegate.
*
* Note that the assignments may be different when a placement is registered due to changes
* in user, placement, or device parameters used in audience filters.
* @param callback callback that will receive the confirmed assignments.
*/
fun Superwall.confirmAllAssignments(callback: (List<ConfirmedAssignment>) -> Unit) {
ioScope.launch {
val assignments = confirmAllAssignments()
callback(assignments)
}
}

override suspend fun eventDidOccur(
paywallEvent: PaywallWebEvent,
paywallView: PaywallView,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,12 @@ sealed class InternalSuperwallEvent(
override val canImplicitlyTriggerPaywall: Boolean = true
}

object ConfirmAllAssignments : InternalSuperwallEvent(SuperwallEvent.ConfirmAllAssignments) {
override val audienceFilterParams: Map<String, Any> = emptyMap()

override suspend fun getSuperwallParameters(): Map<String, Any> = emptyMap()
}

internal data class ErrorThrown(
val message: String,
val stacktrace: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,12 @@ sealed class SuperwallEvent {
get() = "config_fail"
}

// When `confirmAllAssignments` is invoked
object ConfirmAllAssignments : SuperwallEvent() {
override val rawName: String
get() = "confirm_all_assignments"
}

// When Superwall.instance.reset is called
object Reset : SuperwallEvent() {
override val rawName: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ enum class SuperwallEvents(
RestoreComplete("restore_complete"),
CustomPlacement("custom_placement"),
ConfigAttributes("config_attributes"),
ConfirmAllAssignments("confirm_all_assignments"),
ConfigFail("config_fail"),
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,16 @@ fun PaywallComposable(
val context = LocalContext.current

LaunchedEffect(Unit) {
try {
val newView = Superwall.instance.getPaywall(event, params, paywallOverrides, delegate)
newView.encapsulatingActivity = WeakReference(context as? Activity)
newView.setupWith(ShimmerView(context), LoadingView(context))
newView.beforeViewCreated()
viewState.value = newView
} catch (e: Throwable) {
errorState.value = e
}
Superwall.instance
.getPaywall(event, params, paywallOverrides, delegate)
.onSuccess { newView ->
newView.encapsulatingActivity = WeakReference(context as? Activity)
newView.setupWith(ShimmerView(context), LoadingView(context))
newView.beforeViewCreated()
viewState.value = newView
}.onFailure {
errorState.value = it
}
}

when {
Expand All @@ -91,9 +92,11 @@ fun PaywallComposable(
)
}
}

errorState.value != null -> {
errorComposable(errorState.value!!)
}

else -> {
loadingComposable()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.superwall.sdk.config

import android.content.Context
import android.webkit.WebView
import com.superwall.sdk.dependencies.RequestFactory
import com.superwall.sdk.dependencies.RuleAttributesFactory
import com.superwall.sdk.models.config.Config
Expand All @@ -12,6 +11,7 @@ import com.superwall.sdk.paywall.manager.PaywallManager
import com.superwall.sdk.paywall.presentation.rule_logic.expression_evaluator.ExpressionEvaluator
import com.superwall.sdk.paywall.presentation.rule_logic.javascript.JavascriptEvaluator
import com.superwall.sdk.paywall.request.ResponseIdentifiers
import com.superwall.sdk.paywall.vc.web_view.webViewExists
import com.superwall.sdk.storage.LocalStorage
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
Expand Down Expand Up @@ -87,8 +87,7 @@ class PaywallPreload(

// Preloads paywalls referenced by triggers.
private suspend fun preloadPaywalls(paywallIdentifiers: Set<String>) {
val webviewExists =
WebView.getCurrentWebViewPackage() != null
val webviewExists = webViewExists()

if (webviewExists) {
scope.launch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ class SuperwallOptions {
// Set this to `true` to forward events from the Game Controller to the Paywall via ``Superwall/gamepadValueChanged(gamepad:element:)``.
var isGameControllerEnabled: Boolean = false

// Enables passing identifier to the Play Store as AccountId's. Defaults to `false`.
var passIdentifiersToPlayStore: Boolean = false

// Configuration for printing to the console.
class Logging {
// Defines the minimum log level to print to the console. Defaults to `warn`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import com.superwall.sdk.paywall.vc.web_view.SWWebView
import com.superwall.sdk.paywall.vc.web_view.messaging.PaywallMessageHandler
import com.superwall.sdk.paywall.vc.web_view.templating.models.JsonVariables
import com.superwall.sdk.paywall.vc.web_view.templating.models.Variables
import com.superwall.sdk.paywall.vc.web_view.webViewExists
import com.superwall.sdk.storage.EventsQueue
import com.superwall.sdk.storage.LocalStorage
import com.superwall.sdk.store.InternalPurchaseController
Expand Down Expand Up @@ -332,7 +333,9 @@ class DependencyContainer(
* For more info check https://issuetracker.google.com/issues/245155339
*/
ioScope.launch {
WebSettings.getDefaultUserAgent(context)
if (webViewExists()) {
WebSettings.getDefaultUserAgent(context)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.superwall.sdk.models.assignment

import com.superwall.sdk.models.triggers.Experiment
import com.superwall.sdk.models.triggers.ExperimentID

class ConfirmedAssignment(
val experimentId: ExperimentID,
val variant: Experiment.Variant,
)
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ data class PaywallComponents(
}

@Throws(Throwable::class)
suspend fun Superwall.getPaywall(
internal suspend fun Superwall.getPaywall(
request: PresentationRequest,
publisher: MutableSharedFlow<PaywallState> = MutableSharedFlow(),
): PaywallView =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

@Throws(Throwable::class)
suspend fun Superwall.getPaywall(
@Deprecated("Will be removed in the upcoming versions, use Superwall.getPaywall instead")
suspend fun Superwall.getPaywallOrThrow(
event: String,
params: Map<String, Any>? = null,
paywallOverrides: PaywallOverrides? = null,
Expand All @@ -38,6 +39,36 @@ suspend fun Superwall.getPaywall(
return@withContext view
}

@Throws(Throwable::class)
suspend fun Superwall.getPaywall(
event: String,
params: Map<String, Any>? = null,
paywallOverrides: PaywallOverrides? = null,
delegate: PaywallViewCallback,
): Result<PaywallView> =
withContext(Dispatchers.Main) {
try {
val view =
internallyGetPaywall(
event = event,
params = params,
paywallOverrides = paywallOverrides,
delegate = PaywallViewDelegateAdapter(kotlinDelegate = delegate),
)

// Note: Deviation from iOS. Unique to Android. This is also done in `InternalPresentation.kt`.
// Ideally `InternalPresentation` would call this function to get the paywall, and `InternalPresentation.kt`
// would only handle presentation. This cannot be done is the shared `GetPaywallComponents.kt` because it's
// also used for getting a presentation result, and we don't want that to have side effects. Opting to
// do at the top-most point.
view.prepareToDisplay()

return@withContext Result.success(view)
} catch (error: Throwable) {
return@withContext Result.failure(error)
}
}

@Throws(Throwable::class)
private suspend fun Superwall.internallyGetPaywall(
event: String,
Expand Down
Loading

0 comments on commit f547ffc

Please sign in to comment.