Skip to content

Commit

Permalink
Merge pull request #215 from superwall/develop
Browse files Browse the repository at this point in the history
1.5.0-beta.2
  • Loading branch information
ianrumac authored Nov 29, 2024
2 parents db6d7ca + 330799f commit 23f1235
Show file tree
Hide file tree
Showing 16 changed files with 143 additions and 21 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

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

## 1.5.0-beta.2

## Enhancements
- Adds `shimmerView_start` and `shimmerView_complete` events to track the loading of the shimmer animation.
- Makes `hasFreeTrial` match iOS SDK behavior by returning `true` for both free trials and non-free introductory offers

## 1.5.0-beta.1

## Enhancements
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.5.0-beta.1"
version = "1.5.0-beta.2"

android {
compileSdk = 34
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ sealed class TrackingLogic {
}
}

if (event is InternalSuperwallEvent.ShimmerLoad) {
return !disableVerboseEvents
}

(event as? InternalSuperwallEvent.PaywallProductsLoad)?.let {
return when (it.state) {
is InternalSuperwallEvent.PaywallProductsLoad.State.Start,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,41 @@ sealed class InternalSuperwallEvent(
override val canImplicitlyTriggerPaywall: Boolean = true
}

data class ShimmerLoad(
val state: State,
val paywallId: String,
val visibleDuration: Double?,
val delay: Double,
val preloadingEnabled: Boolean,
) : InternalSuperwallEvent(
if (state ==
State.Started
) {
SuperwallEvent.ShimmerViewStart
} else {
SuperwallEvent.ShimmerViewComplete(visibleDuration ?: 0.0)
},
) {
enum class State {
Started,
Complete,
}

override val audienceFilterParams: Map<String, Any> = emptyMap()

override val rawName: String
get() = superwallEvent.rawName

override suspend fun getSuperwallParameters(): Map<String, Any> =
mapOf(
"paywall_id" to paywallId,
"preloading_enabled" to preloadingEnabled,
"visible_duration" to visibleDuration,
).filter { it.value != null }.toMap() as Map<String, Any>

override val canImplicitlyTriggerPaywall: Boolean = false
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,18 @@ sealed class SuperwallEvent {
override val rawName: String = SuperwallEvents.CustomPlacement.rawName
}

data object ShimmerViewStart : SuperwallEvent() {
override val rawName: String
get() = SuperwallEvents.ShimmerViewStart.rawName
}

data class ShimmerViewComplete(
val duration: Double,
) : SuperwallEvent() {
override val rawName: String
get() = SuperwallEvents.ShimmerViewComplete.rawName
}

internal object ErrorThrown : SuperwallEvent(), IsInternalEvent {
override val rawName: String
get() = "error_thrown"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ enum class SuperwallEvents(
RestoreFail("restore_fail"),
RestoreComplete("restore_complete"),
CustomPlacement("custom_placement"),
ShimmerViewStart("shimmerView_start"),
ShimmerViewComplete("shimmerView_complete"),
ConfigAttributes("config_attributes"),
ConfirmAllAssignments("confirm_all_assignments"),
ConfigFail("config_fail"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ class DependencyContainer(
track = {
Superwall.instance.track(it)
},
shouldTraceResults = makeFeatureFlags()?.enableCELLogging ?: false,
)
}

Expand Down Expand Up @@ -643,7 +644,7 @@ class DependencyContainer(

override fun makeTransactionVerifier(): GoogleBillingWrapper = googleBillingWrapper

override suspend fun makeSuperwallOptions(): SuperwallOptions = configManager.options
override fun makeSuperwallOptions(): SuperwallOptions = configManager.options

override suspend fun makeTriggers(): Set<String> = configManager.triggersByEventName.keys

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ interface StoreTransactionFactory {
}

interface OptionsFactory {
suspend fun makeSuperwallOptions(): SuperwallOptions
fun makeSuperwallOptions(): SuperwallOptions
}

interface TriggerFactory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ data class Config(
rawFeatureFlags.find { it.key == "enable_multiple_paywall_urls" }?.enabled
?: false,
enableConfigRefresh =
rawFeatureFlags.find { it.key == "enable_config_refresh" }?.enabled
rawFeatureFlags.find { it.key == "enable_config_refresh_v2" }?.enabled
?: false,
enableSessionEvents =
rawFeatureFlags.find { it.key == "enable_session_events" }?.enabled
Expand All @@ -55,6 +55,9 @@ data class Config(
disableVerboseEvents =
rawFeatureFlags.find { it.key == "disable_verbose_events" }?.enabled
?: false,
enableCELLogging =
rawFeatureFlags.find { it.key == "enable_cel_logging" }?.enabled
?: false,
)

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ data class RawFeatureFlag(

@Serializable
data class FeatureFlags(
@SerialName("enable_config_refresh") var enableConfigRefresh: Boolean = false,
@SerialName("enable_config_refresh_v2") var enableConfigRefresh: Boolean = false,
@SerialName("enable_session_events") var enableSessionEvents: Boolean,
@SerialName("enable_postback") var enablePostback: Boolean,
@SerialName("enable_userid_seed") var enableUserIdSeed: Boolean,
@SerialName("disable_verbose_events") var disableVerboseEvents: Boolean,
@SerialName("enable_multiple_paywall_urls") var enableMultiplePaywallUrls: Boolean,
@SerialName("enable_cel_logging") var enableCELLogging: Boolean,
)

fun List<RawFeatureFlag>.value(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ data class Paywall(
var webviewLoadingInfo: LoadingInfo = LoadingInfo(),
@kotlinx.serialization.Transient()
var productsLoadingInfo: LoadingInfo = LoadingInfo(),
@kotlinx.serialization.Transient()
var shimmerLoadingInfo: LoadingInfo = LoadingInfo(),
var productVariables: List<ProductVariable>? = null,
var swProductVariablesTemplate: List<ProductVariable>? = null,
var paywalljsVersion: String? = null,
Expand Down Expand Up @@ -209,6 +211,8 @@ data class Paywall(
productsLoadStartTime = productsLoadingInfo.startAt,
productsLoadFailTime = productsLoadingInfo.failAt,
productsLoadCompleteTime = productsLoadingInfo.endAt,
shimmerLoadStartTime = shimmerLoadingInfo.startAt,
shimmerLoadCompleteTime = shimmerLoadingInfo.endAt,
experiment = experiment,
paywalljsVersion = paywalljsVersion,
isFreeTrialAvailable = isFreeTrialAvailable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ data class PaywallInfo(
val productsLoadStartTime: String?,
val productsLoadCompleteTime: String?,
val productsLoadFailTime: String?,
val shimmerLoadStartTime: String?,
val shimmerLoadCompleteTime: String?,
val productsLoadDuration: Double?,
val paywalljsVersion: String?,
val isFreeTrialAvailable: Boolean,
Expand Down Expand Up @@ -83,6 +85,8 @@ data class PaywallInfo(
productsLoadStartTime: Date?,
productsLoadFailTime: Date?,
productsLoadCompleteTime: Date?,
shimmerLoadStartTime: Date?,
shimmerLoadCompleteTime: Date?,
experiment: Experiment? = null,
paywalljsVersion: String? = null,
isFreeTrialAvailable: Boolean,
Expand Down Expand Up @@ -167,6 +171,14 @@ data class PaywallInfo(
(endTime.time / 1000 - startTime.time / 1000).toDouble()
}
},
shimmerLoadStartTime =
webViewLoadStartTime?.let {
DateFormatterUtil.format(it)
} ?: "",
shimmerLoadCompleteTime =
webViewLoadStartTime?.let {
DateFormatterUtil.format(it)
} ?: "",
localNotifications = localNotifications,
computedPropertyRequests = computedPropertyRequests,
closeReason = closeReason,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ internal class CombinedExpressionEvaluator(
private val storage: LocalStorage,
private val factory: RuleAttributesFactory,
private val evaluator: JavascriptEvaluator,
private val shouldTraceResults: Boolean,
private val superscriptEvaluator: SuperscriptEvaluator,
private val track: suspend (InternalSuperwallEvent.ExpressionResult) -> Unit,
) : ExpressionEvaluating {
Expand All @@ -48,15 +49,17 @@ internal class CombinedExpressionEvaluator(
} catch (e: Exception) {
TriggerRuleOutcome.noMatch(UnmatchedRule.Source.EXPRESSION, rule.experiment.id)
}
track(
InternalSuperwallEvent.ExpressionResult(
liquidExpression = rule.expression,
celExpression = rule.expressionCEL,
celExpressionResult = if (celEvaluation is TriggerRuleOutcome.Match) true else false,
jsExpression = rule.expressionJs,
jsExpressionResult = if (result is TriggerRuleOutcome.Match) true else false,
),
)
if (shouldTraceResults) {
track(
InternalSuperwallEvent.ExpressionResult(
liquidExpression = rule.expression,
celExpression = rule.expressionCEL,
celExpressionResult = if (celEvaluation is TriggerRuleOutcome.Match) true else false,
jsExpression = rule.expressionJs,
jsExpressionResult = if (result is TriggerRuleOutcome.Match) true else false,
),
)
}
return result
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.superwall.sdk.analytics.internal.trackable.InternalSuperwallEvent
import com.superwall.sdk.analytics.superwall.SuperwallEvents
import com.superwall.sdk.config.models.OnDeviceCaching
import com.superwall.sdk.config.options.PaywallOptions
import com.superwall.sdk.dependencies.OptionsFactory
import com.superwall.sdk.dependencies.TriggerFactory
import com.superwall.sdk.game.GameControllerDelegate
import com.superwall.sdk.game.GameControllerEvent
Expand Down Expand Up @@ -66,6 +67,8 @@ import java.lang.ref.WeakReference
import java.net.MalformedURLException
import java.net.URI
import java.util.Date
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.DurationUnit

class PaywallView(
context: Context,
Expand Down Expand Up @@ -94,7 +97,9 @@ class PaywallView(
}
}

interface Factory : TriggerFactory
interface Factory :
TriggerFactory,
OptionsFactory
//region Public properties

// MUST be set prior to presentation
Expand Down Expand Up @@ -312,7 +317,8 @@ class PaywallView(
if (loadingState is PaywallLoadingState.Ready) {
webView.messageHandler.handle(PaywallMessage.TemplateParamsAndUserAttributes)
}

paywall.shimmerLoadingInfo.startAt = Date()
trackShimmerStart()
presentationWillPrepare = false
}

Expand Down Expand Up @@ -566,6 +572,20 @@ class PaywallView(
}
}

private fun trackShimmerStart() {
val trackedEvent =
InternalSuperwallEvent.ShimmerLoad(
state = InternalSuperwallEvent.ShimmerLoad.State.Started,
paywallId = paywall.identifier,
visibleDuration = null,
preloadingEnabled = factory.makeSuperwallOptions().paywalls.shouldPreload,
delay = paywall.presentation.delay.toDouble(),
)
ioScope.launch {
Superwall.instance.track(trackedEvent)
}
}

private fun showShimmerView() {
shimmerView?.let {
mainScope.launch {
Expand All @@ -580,6 +600,27 @@ class PaywallView(
it.hideShimmer()
}
}
val visible = paywall.shimmerLoadingInfo.startAt
val now = Date()
paywall.shimmerLoadingInfo.endAt = now
ioScope.launch {
val trackedEvent =
InternalSuperwallEvent.ShimmerLoad(
state = InternalSuperwallEvent.ShimmerLoad.State.Complete,
paywallId = paywall.identifier,
visibleDuration =
if (visible != null) {
(now.time - visible.time).milliseconds.toDouble(
DurationUnit.MILLISECONDS,
)
} else {
0.0
},
delay = paywall.presentation.delay.toDouble(),
preloadingEnabled = factory.makeSuperwallOptions().paywalls.shouldPreload,
)
Superwall.instance.track(trackedEvent)
}
}

fun showRefreshButtonAfterTimeout(isVisible: Boolean) {
Expand Down Expand Up @@ -711,7 +752,6 @@ class PaywallView(
}

webView.scrollEnabled = paywall.isScrollEnabled ?: true

mainScope.launch {
if (paywall.onDeviceCache is OnDeviceCaching.Enabled) {
webView.settings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
Expand All @@ -724,7 +764,6 @@ class PaywallView(
webView.loadUrl(url.value)
}
}

loadingState = PaywallLoadingState.LoadingURL()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ class RawStoreProduct(
// Check for free trial phase in pricing phases, excluding the base pricing
selectedOffer.pricingPhases.pricingPhaseList
.dropLast(1)
.any { it.priceAmountMicros == 0L }
.isNotEmpty()
}

override val localizedTrialPeriodPrice by lazy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ class ProductFetcherInstrumentedTest {
offerType = OfferType.Offer(id = "paid-offer"),
),
)
assert(!storeProduct.hasFreeTrial)
assert(storeProduct.hasFreeTrial)
assert(storeProduct.productIdentifier == "com.ui_tests.quarterly2")
assert(storeProduct.fullIdentifier == "com.ui_tests.quarterly2:test-4:paid-offer")
assert(storeProduct.currencyCode == "USD")
Expand Down Expand Up @@ -513,7 +513,7 @@ class ProductFetcherInstrumentedTest {
offerType = OfferType.Auto,
),
)
assert(!storeProduct.hasFreeTrial)
assert(storeProduct.hasFreeTrial)
assert(storeProduct.productIdentifier == "com.ui_tests.quarterly2")
assert(storeProduct.fullIdentifier == "com.ui_tests.quarterly2:test-3:sw-auto")
assert(storeProduct.currencyCode == "USD")
Expand Down

0 comments on commit 23f1235

Please sign in to comment.