Skip to content

Commit

Permalink
Merge pull request #111 from superwall/develop
Browse files Browse the repository at this point in the history
1.1.6
  • Loading branch information
yusuftor authored Jun 3, 2024
2 parents dcb693b + 94ef542 commit fef994b
Show file tree
Hide file tree
Showing 17 changed files with 182 additions and 38 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

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

## 1.1.6

### Enhancements

- SW-2833: Adds support for dark mode paywall background color.
- Adds ability to target devices based on their IP address location. Use `device.ipRegion`,
`device.ipRegionCode`, `device.ipCountry`, `device.ipCity`, `device.ipContinent`, or `device.ipTimezone`.
- Adds `event_name` to the event params for use with audience filters.

### Fixes

- Fixes issue with products whose labels weren't primary/secondary/tertiary.

## 1.1.5

### Fixes
Expand Down
2 changes: 1 addition & 1 deletion superwall/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ plugins {
id("signing")
}

version = "1.1.5"
version = "1.1.6"

android {
compileSdk = 33
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ sealed class TrackingLogic {

val eventParams: MutableMap<String, Any> = mutableMapOf(
"\$is_standard_event" to isStandardEvent,
"\$event_name" to eventName
"\$event_name" to eventName,
"event_name" to eventName
)

// Filter then assign Superwall parameters
Expand Down
32 changes: 18 additions & 14 deletions superwall/src/main/java/com/superwall/sdk/config/ConfigManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.superwall.sdk.config

import android.content.Context
import android.webkit.WebView
import com.superwall.sdk.billing.GoogleBillingWrapper
import com.superwall.sdk.config.models.ConfigState
import com.superwall.sdk.config.models.getConfig
import com.superwall.sdk.config.options.SuperwallOptions
Expand All @@ -21,6 +20,7 @@ import com.superwall.sdk.models.triggers.Experiment
import com.superwall.sdk.models.triggers.ExperimentID
import com.superwall.sdk.models.triggers.Trigger
import com.superwall.sdk.network.Network
import com.superwall.sdk.network.device.DeviceHelper
import com.superwall.sdk.paywall.manager.PaywallManager
import com.superwall.sdk.paywall.presentation.rule_logic.expression_evaluator.ExpressionEvaluator
import com.superwall.sdk.paywall.request.ResponseIdentifiers
Expand All @@ -43,12 +43,12 @@ open class ConfigManager(
private val storeKitManager: StoreKitManager,
private val storage: Storage,
private val network: Network,
options: SuperwallOptions? = null,
private val deviceHelper: DeviceHelper,
var options: SuperwallOptions,
private val paywallManager: PaywallManager,
private val factory: Factory
) {
interface Factory: RequestFactory, DeviceInfoFactory, RuleAttributesFactory {}
var options = SuperwallOptions()

// The configuration of the Superwall dashboard
val configState = MutableStateFlow<Result<ConfigState>>(Result.Success(ConfigState.Retrieving))
Expand Down Expand Up @@ -80,22 +80,27 @@ open class ConfigManager(
_unconfirmedAssignments = value.toMutableMap()
}

// Initializer
init {
if (options != null) {
this.options = options
}
}

// Remaining methods should be converted similarly, using Kotlin's coroutines for async tasks
// and other relevant Kotlin features. Here's an example of one method:
suspend fun fetchConfiguration() {
try {
val config = network.getConfig() {
CoroutineScope(Dispatchers.IO).launch {
configState.emit(Result.Success(ConfigState.Retrying))
val configDeferred = CoroutineScope(Dispatchers.IO).async {
network.getConfig {
CoroutineScope(Dispatchers.IO).launch {
// Emit retrying state
configState.emit(Result.Success(ConfigState.Retrying))
}
}
}

val geoDeferred = CoroutineScope(Dispatchers.IO).async {
deviceHelper.getGeoInfo()
}

// Await results from both operations
val config = configDeferred.await()
geoDeferred.await()

CoroutineScope(Dispatchers.IO).launch { sendProductsBack(config) }

Logger.debug(
Expand Down Expand Up @@ -222,7 +227,6 @@ open class ConfigManager(
)
}


// Preloads paywalls.
private suspend fun preloadPaywalls() {
if (!options.paywalls.shouldPreload) return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,20 +142,27 @@ class DependencyContainer(
factory = this,
)

val options = options ?: SuperwallOptions()
api = Api(networkEnvironment = options.networkEnvironment)

deviceHelper = DeviceHelper(
context = context,
storage = storage,
network = network,
factory = this
)

configManager = ConfigManager(
context = context,
storeKitManager = storeKitManager,
storage = storage,
network = network,
options = options,
factory = this,
paywallManager = paywallManager
paywallManager = paywallManager,
deviceHelper = deviceHelper
)

api = Api(networkEnvironment = configManager.options.networkEnvironment)

deviceHelper = DeviceHelper(context = context, storage = storage, factory = this)

eventsQueue = EventsQueue(context, configManager = configManager, network = network)

identityManager = IdentityManager(
Expand Down
17 changes: 17 additions & 0 deletions superwall/src/main/java/com/superwall/sdk/models/geo/GeoInfo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.superwall.sdk.models.geo

import kotlinx.serialization.Serializable

@Serializable
data class GeoInfo(
val city: String?,
val country: String?,
val longitude: Double?,
val latitude: Double?,
val region: String?,
val regionCode: String?,
val continent: String?,
val metroCode: String?,
val postalCode: String?,
val timezone: String?
)
11 changes: 11 additions & 0 deletions superwall/src/main/java/com/superwall/sdk/models/geo/GeoWrapper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.superwall.sdk.models.geo

import com.superwall.sdk.models.SerializableEntity
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class GeoWrapper(
@SerialName("geoInfo")
val info: GeoInfo
): SerializableEntity
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ data class Paywall(
private val presentationCondition: String,

val backgroundColorHex: String,
val darkBackgroundColorHex: String? = null,

// Declared as private to prevent direct access
@kotlinx.serialization.Transient()
Expand Down Expand Up @@ -131,6 +132,20 @@ data class Paywall(
}
}

val darkBackgroundColor: Int? by lazy {
try {
Color.parseColor(this.darkBackgroundColorHex)
} catch (e: Throwable) {
Logger.debug(
logLevel = LogLevel.warn,
scope = LogScope.paywallViewController,
message = "Invalid paywall background color: ${this.darkBackgroundColorHex}. " +
"Defaulting to white."
)
null
}
}

init {
productItems = _productItems
presentation = Presentation(
Expand Down Expand Up @@ -233,6 +248,7 @@ data class Paywall(
presentationStyle = "MODAL",
presentationCondition = "CHECK_USER_SUBSCRIPTION",
backgroundColorHex = "000000",
darkBackgroundColorHex = null,
productIds = arrayListOf(),
_productItems = emptyList(),
_products = emptyList(),
Expand Down
12 changes: 10 additions & 2 deletions superwall/src/main/java/com/superwall/sdk/network/API.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import com.superwall.sdk.config.options.SuperwallOptions
data class Api(
val hostDomain: String,
val base: Base,
val collector: Collector
val collector: Collector,
val geo: Geo
) {
companion object {
const val version1 = "/api/v1/"
Expand All @@ -18,7 +19,8 @@ data class Api(
constructor(networkEnvironment: SuperwallOptions.NetworkEnvironment) : this(
hostDomain = networkEnvironment.hostDomain,
base = Base(networkEnvironment),
collector = Collector(networkEnvironment)
collector = Collector(networkEnvironment),
geo = Geo(networkEnvironment)
)

data class Base(private val networkEnvironment: SuperwallOptions.NetworkEnvironment) {
Expand All @@ -32,4 +34,10 @@ data class Api(
// get() = "10.0.2.2:9909"
get() = networkEnvironment.collectorHost
}

data class Geo(private val networkEnvironment: SuperwallOptions.NetworkEnvironment) {
val host: String
// get() = "10.0.2.2:9909"
get() = "geo-api.superwall.com"
}
}
13 changes: 13 additions & 0 deletions superwall/src/main/java/com/superwall/sdk/network/Endpoint.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.superwall.sdk.models.config.Config
import com.superwall.sdk.models.events.EventData
import com.superwall.sdk.models.events.EventsRequest
import com.superwall.sdk.models.events.EventsResponse
import com.superwall.sdk.models.geo.GeoWrapper
import com.superwall.sdk.models.paywall.Paywall
import com.superwall.sdk.models.paywall.Paywalls
import com.superwall.sdk.models.postback.PostBackResponse
Expand Down Expand Up @@ -197,6 +198,18 @@ data class Endpoint<Response : SerializableEntity>(
)
}

fun geo(factory: ApiFactory): Endpoint<GeoWrapper> {
val geoHost = factory.api.geo.host
return Endpoint(
components = Components(
host = geoHost,
path = Api.version1 + "geo"
),
method = HttpMethod.GET,
factory = factory
)
}

fun paywall(
identifier: String? = null,
event: EventData? = null,
Expand Down
20 changes: 19 additions & 1 deletion superwall/src/main/java/com/superwall/sdk/network/Network.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.superwall.sdk.models.config.Config
import com.superwall.sdk.models.events.EventData
import com.superwall.sdk.models.events.EventsRequest
import com.superwall.sdk.models.events.EventsResponse
import com.superwall.sdk.models.geo.GeoInfo
import com.superwall.sdk.models.paywall.Paywall
import com.superwall.sdk.network.session.CustomHttpUrlConnection
import kotlinx.coroutines.flow.filter
Expand Down Expand Up @@ -154,7 +155,7 @@ open class Network(
val paywalls = urlSession.request(
Endpoint.paywalls(factory = factory)
)
return paywalls.paywalls
paywalls.paywalls
} catch (error: Throwable) {
Logger.debug(
logLevel = LogLevel.error,
Expand All @@ -166,6 +167,23 @@ open class Network(
}
}

suspend fun getGeoInfo(): GeoInfo? {
return try {
val geoWrapper = urlSession.request(
Endpoint.geo(factory = factory)
)
geoWrapper.info
} catch (error: Exception) {
Logger.debug(
logLevel = LogLevel.error,
scope = LogScope.network,
message = "Request Failed: /geo",
error = error
)
null
}
}

open suspend fun getAssignments(): List<Assignment> {
return try {
val result = urlSession.request(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import com.superwall.sdk.Superwall
import com.superwall.sdk.dependencies.IdentityInfoFactory
import com.superwall.sdk.dependencies.LocaleIdentifierFactory
import com.superwall.sdk.models.events.EventData
import com.superwall.sdk.models.geo.GeoInfo
import com.superwall.sdk.network.Network
import com.superwall.sdk.paywall.vc.web_view.templating.models.DeviceTemplate
import com.superwall.sdk.storage.Storage
import java.text.SimpleDateFormat
Expand All @@ -35,16 +37,13 @@ enum class InterfaceStyle(val rawValue: String) {
class DeviceHelper(
private val context: Context,
val storage: Storage,
val factory: DeviceHelper.Factory
val network: Network,
val factory: Factory
) {
interface Factory: IdentityInfoFactory, LocaleIdentifierFactory {}

private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
private val telephonyManager =
context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
private val packageManager = context.packageManager
private val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
private val appInfo = context.packageManager.getPackageInfo(context.packageName, 0)
private val appInstallDate = Date(appInfo.firstInstallTime)

Expand Down Expand Up @@ -93,6 +92,8 @@ class DeviceHelper(
return storage.get(TotalPaywallViews) ?: 0
}

private var geoInfo: GeoInfo? = null

val locale: String
get() {
val localeIdentifier = factory.makeLocaleIdentifier()
Expand Down Expand Up @@ -335,8 +336,7 @@ class DeviceHelper(
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
return packageInfo.versionCode.toString()
}



val sdkVersion: String
get() = BuildConfig.SDK_VERSION

Expand Down Expand Up @@ -424,9 +424,19 @@ class DeviceHelper(
sdkVersionPadded = sdkVersionPadded,
appBuildString = appBuildString,
appBuildStringNumber = appBuildString.toInt(),
interfaceStyleMode = if (interfaceStyleOverride == null) "automatic" else "manual"
interfaceStyleMode = if (interfaceStyleOverride == null) "automatic" else "manual",
ipRegion = geoInfo?.region,
ipRegionCode = geoInfo?.regionCode,
ipCountry = geoInfo?.country,
ipCity = geoInfo?.city,
ipContinent = geoInfo?.continent,
ipTimezone = geoInfo?.timezone
)

return deviceTemplate.toDictionary()
}

suspend fun getGeoInfo() {
geoInfo = network.getGeoInfo()
}
}
Loading

0 comments on commit fef994b

Please sign in to comment.