Skip to content

Commit a9e3fe7

Browse files
committed
version 3.14.0
1 parent ba9bf54 commit a9e3fe7

39 files changed

+969
-803
lines changed

adapty-ui/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ dependencies {
5252
implementation 'androidx.compose.material3:material3'
5353
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.8.0'
5454

55-
implementation 'androidx.webkit:webkit:1.5.0'
56-
5755
debugCompileOnly 'androidx.compose.ui:ui-tooling'
5856
debugCompileOnly 'androidx.compose.ui:ui-test-manifest'
5957
}

adapty-ui/src/main/java/com/adapty/ui/internal/ui/element/ButtonElement.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.adapty.internal.utils.InternalAdaptyApi
1010
import com.adapty.ui.internal.ui.attributes.toComposeShape
1111
import com.adapty.ui.internal.ui.clickIndication
1212
import com.adapty.ui.internal.utils.EventCallback
13+
import com.adapty.ui.internal.utils.handleInitialProductSelection
1314
import com.adapty.ui.internal.utils.getProductGroupKey
1415

1516
@InternalAdaptyApi
@@ -40,10 +41,16 @@ public class ButtonElement internal constructor(
4041
}
4142
selectedCondition is Condition.SelectedProduct -> {
4243
val productGroupKey = getProductGroupKey(selectedCondition.groupId)
43-
if (state[productGroupKey] as? String == selectedCondition.productId)
44-
selected
45-
else
46-
normal
44+
(state[productGroupKey] as? String == selectedCondition.productId)
45+
.also { isSelected ->
46+
handleInitialProductSelection(
47+
selectedCondition.productId,
48+
selectedCondition.groupId,
49+
isSelected,
50+
eventCallback,
51+
)
52+
}
53+
.let { isSelected -> if (isSelected) selected else normal }
4754
}
4855
else -> normal
4956
}

adapty-ui/src/main/java/com/adapty/ui/internal/ui/element/ToggleElement.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.adapty.ui.AdaptyUI.LocalizedViewConfiguration.Asset
1212
import com.adapty.ui.internal.ui.attributes.Shape
1313
import com.adapty.ui.internal.ui.attributes.toComposeFill
1414
import com.adapty.ui.internal.utils.EventCallback
15+
import com.adapty.ui.internal.utils.handleInitialProductSelection
1516
import com.adapty.ui.internal.utils.getAsset
1617
import com.adapty.ui.internal.utils.getProductGroupKey
1718

@@ -54,7 +55,15 @@ public class ToggleElement internal constructor(
5455
}
5556
is Condition.SelectedProduct -> {
5657
val productGroupKey = getProductGroupKey(onCondition.groupId)
57-
state[productGroupKey] as? String == onCondition.productId
58+
(state[productGroupKey] as? String == onCondition.productId)
59+
.also { isChecked ->
60+
handleInitialProductSelection(
61+
onCondition.productId,
62+
onCondition.groupId,
63+
isChecked,
64+
eventCallback,
65+
)
66+
}
5867
}
5968
else -> false
6069
},

adapty-ui/src/main/java/com/adapty/ui/internal/utils/consts.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ internal const val DARK_THEME_ASSET_SUFFIX = "@dark"
99
internal const val CUSTOM_ASSET_SUFFIX = "\$\$custom"
1010
internal const val NO_SHRINK = 0b0
1111
internal const val HOUR_MILLIS = 3600 * 1000L
12-
internal const val VERSION_NAME = "3.12.0"
12+
internal const val VERSION_NAME = "3.14.0"
1313
internal const val LOG_PREFIX = "UI v${VERSION_NAME}:"
1414
internal const val LOG_PREFIX_ERROR = "UI v${VERSION_NAME} error:"
1515
internal const val CONFIGURATION_FORMAT_VERSION = "4.4.0"

adapty-ui/src/main/java/com/adapty/ui/internal/utils/utils.kt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import android.provider.Settings
1010
import android.util.TypedValue
1111
import androidx.compose.foundation.isSystemInDarkTheme
1212
import androidx.compose.runtime.Composable
13+
import androidx.compose.runtime.LaunchedEffect
14+
import androidx.compose.runtime.mutableStateOf
15+
import androidx.compose.runtime.saveable.rememberSaveable
1316
import androidx.compose.ui.platform.LocalConfiguration
1417
import androidx.compose.ui.platform.LocalDensity
1518
import androidx.compose.ui.platform.LocalLayoutDirection
@@ -22,9 +25,11 @@ import com.adapty.ui.AdaptyUI
2225
import com.adapty.ui.AdaptyUI.LocalizedViewConfiguration.Asset
2326
import com.adapty.ui.R
2427
import com.adapty.ui.internal.mapping.element.Assets
28+
import com.adapty.ui.internal.ui.element.Action
2529
import com.adapty.utils.AdaptyLogLevel
2630
import com.adapty.utils.AdaptyLogLevel.Companion.ERROR
2731
import com.adapty.utils.AdaptyLogLevel.Companion.WARN
32+
import kotlinx.coroutines.CoroutineScope
2833
import java.util.Locale
2934
import java.util.concurrent.Executors
3035

@@ -55,6 +60,34 @@ internal fun AdaptyPaywallProduct.firstDiscountOfferOrNull(): AdaptyProductDisco
5560

5661
internal fun getProductGroupKey(groupId: String) = "group_${groupId}"
5762

63+
@Composable
64+
internal fun handleInitialProductSelection(
65+
productId: String,
66+
groupId: String,
67+
isSelected: Boolean,
68+
eventCallback: EventCallback,
69+
) {
70+
LaunchedEffectSaveable(productId, groupId) {
71+
if (!isSelected) return@LaunchedEffectSaveable
72+
val action = Action.SelectProduct(productId, groupId)
73+
eventCallback.onActions(listOf(action))
74+
}
75+
}
76+
77+
@Composable
78+
internal fun LaunchedEffectSaveable(
79+
vararg keys: Any?,
80+
effect: suspend CoroutineScope.() -> Unit
81+
) {
82+
val hasExecuted = rememberSaveable(*keys) { mutableStateOf(false) }
83+
LaunchedEffect(*keys) {
84+
if (!hasExecuted.value) {
85+
hasExecuted.value = true
86+
effect()
87+
}
88+
}
89+
}
90+
5891
@Composable
5992
internal fun getScreenHeightDp(): Float {
6093
val insets = getInsets()

adapty-ui/src/main/java/com/adapty/ui/onboardings/AdaptyOnboardingView.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ import android.view.LayoutInflater
1212
import android.view.View
1313
import android.webkit.JavascriptInterface
1414
import android.webkit.SslErrorHandler
15+
import android.webkit.WebResourceError
1516
import android.webkit.WebResourceRequest
1617
import android.webkit.WebResourceResponse
1718
import android.webkit.WebView
19+
import android.webkit.WebViewClient
1820
import android.widget.FrameLayout
1921
import android.widget.ProgressBar
2022
import androidx.core.graphics.Insets
@@ -23,8 +25,6 @@ import androidx.core.view.WindowInsetsCompat
2325
import androidx.lifecycle.ViewModel
2426
import androidx.lifecycle.ViewModelProvider
2527
import androidx.lifecycle.findViewTreeViewModelStoreOwner
26-
import androidx.webkit.WebResourceErrorCompat
27-
import androidx.webkit.WebViewClientCompat
2828
import com.adapty.internal.di.Dependencies
2929
import com.adapty.internal.utils.InternalAdaptyApi
3030
import com.adapty.ui.internal.utils.LOG_PREFIX
@@ -104,8 +104,8 @@ public class AdaptyOnboardingView @JvmOverloads constructor(
104104
}
105105
}, "Android")
106106

107-
webViewClient = object : WebViewClientCompat() {
108-
override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceErrorCompat) {
107+
webViewClient = object : WebViewClient() {
108+
override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError) {
109109
log(ERROR) { "$LOG_PREFIX_ERROR onReceivedError: ${error.toLog()})" }
110110
if (!request.isForMainFrame) return
111111
withViewModel { it.emitError(AdaptyOnboardingError.WebKit.WebResource(error)) }

adapty-ui/src/main/java/com/adapty/ui/onboardings/errors/AdaptyOnboardingError.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
package com.adapty.ui.onboardings.errors
22

33
import android.net.http.SslError
4+
import android.webkit.WebResourceError
45
import android.webkit.WebResourceResponse
5-
import androidx.webkit.WebResourceErrorCompat
66
import com.adapty.ui.onboardings.internal.util.toLog
77

88
public sealed class AdaptyOnboardingError {
99
public class WrongApiKey: AdaptyOnboardingError()
1010
public class NotActivated: AdaptyOnboardingError()
1111
public class ActivateOnce: AdaptyOnboardingError()
1212
public sealed class WebKit: AdaptyOnboardingError() {
13-
public class WebResource(public val originalError: WebResourceErrorCompat): WebKit() {
13+
public class WebResource(public val originalError: WebResourceError): WebKit() {
1414
override fun toString(): String {
1515
return "AdaptyOnboardingError.WebResource(originalError=${originalError.toLog()})"
1616
}

adapty-ui/src/main/java/com/adapty/ui/onboardings/internal/util/util.kt

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
package com.adapty.ui.onboardings.internal.util
22

33
import android.net.http.SslError
4+
import android.os.Build
5+
import android.webkit.WebResourceError
46
import android.webkit.WebResourceResponse
5-
import androidx.webkit.WebResourceErrorCompat
6-
import androidx.webkit.WebViewFeature
7-
import androidx.webkit.WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE
8-
import androidx.webkit.WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION
97

10-
internal fun WebResourceErrorCompat.toLog(): String =
11-
"WebResourceErrorCompat(errorCode=${getErrorCodeIfSupported()}, description=${getDescriptionIfSupported()})"
8+
internal fun WebResourceError.toLog(): String =
9+
"WebResourceError(errorCode=${getErrorCodeIfSupported()}, description=${getDescriptionIfSupported()})"
1210

13-
private fun WebResourceErrorCompat.getErrorCodeIfSupported() =
14-
if (WebViewFeature.isFeatureSupported(WEB_RESOURCE_ERROR_GET_CODE)) errorCode else -1
11+
private fun WebResourceError.getErrorCodeIfSupported() =
12+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) errorCode else -1
1513

16-
private fun WebResourceErrorCompat.getDescriptionIfSupported() =
17-
if (WebViewFeature.isFeatureSupported(WEB_RESOURCE_ERROR_GET_DESCRIPTION)) description else "unknown"
14+
private fun WebResourceError.getDescriptionIfSupported() =
15+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) description else "unknown"
1816

1917
internal fun WebResourceResponse.toLog(): String =
2018
"WebResourceResponse(mimeType=$mimeType, statusCode=$statusCode, reason=$reasonPhrase, headers={${responseHeaders.entries.joinToString { "${it.key}=${it.value}" }}})"
Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,7 @@
11
package com.adapty.errors
22

3-
import com.adapty.internal.data.models.BackendError
4-
import java.io.IOException
5-
6-
public class AdaptyError internal constructor(
3+
public open class AdaptyError internal constructor(
74
public val originalError: Throwable? = null,
85
message: String = "",
96
public val adaptyErrorCode: AdaptyErrorCode = AdaptyErrorCode.UNKNOWN,
10-
@get:JvmSynthetic internal val backendError: BackendError? = null,
11-
) : Exception(message, originalError) {
12-
13-
@JvmSynthetic
14-
internal fun getRetryType(isInfinite: Boolean) = when {
15-
adaptyErrorCode == AdaptyErrorCode.SERVER_ERROR -> if (isInfinite) RetryType.PROGRESSIVE else RetryType.SIMPLE
16-
originalError is IOException -> RetryType.SIMPLE
17-
else -> RetryType.NONE
18-
}
19-
20-
internal enum class RetryType {
21-
@JvmSynthetic
22-
SIMPLE,
23-
24-
@JvmSynthetic
25-
PROGRESSIVE,
26-
27-
@JvmSynthetic
28-
NONE
29-
}
30-
}
7+
) : Exception(message, originalError)

adapty/src/main/java/com/adapty/internal/data/cache/CacheRepository.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import com.adapty.internal.utils.getLanguageCode
2020
import com.adapty.internal.utils.orDefault
2121
import com.adapty.internal.utils.unlockQuietly
2222
import com.adapty.internal.utils.withLockSafe
23+
import com.adapty.models.AdaptyConfig.ServerCluster
2324
import com.adapty.utils.AdaptyResult
2425
import com.adapty.utils.FileLocation
2526
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -35,6 +36,7 @@ internal class CacheRepository(
3536
private val crossPlacementInfoLock: ReentrantReadWriteLock,
3637
private val productPALMappingLock: ReentrantReadWriteLock,
3738
private val validateDataLock: ReentrantReadWriteLock,
39+
serverCluster: ServerCluster,
3840
) {
3941

4042
private val currentProfile = MutableSharedFlow<ProfileDto>()
@@ -337,7 +339,7 @@ internal class CacheRepository(
337339
if (isSystemLog) ANALYTICS_LOW_PRIORITY_DATA else ANALYTICS_DATA
338340

339341
@Volatile
340-
var analyticsConfig = AnalyticsConfig.DEFAULT
342+
var netConfig = NetConfig.createDefault(serverCluster)
341343

342344
fun getPaywall(id: String, locale: String, maxAgeMillis: Long? = null) =
343345
getVariation(id, setOf(locale), VariationType.Paywall, maxAgeMillis) as? PaywallDto

0 commit comments

Comments
 (0)