Skip to content

Commit 24733f6

Browse files
authored
Merge pull request #763 from qonversion/release-nocodes/1.4.0
2 parents f32d6cc + 4fb2140 commit 24733f6

113 files changed

Lines changed: 4690 additions & 1137 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ buildscript {
1010
versionCode: 1
1111
]
1212
nocodes = [
13-
versionName: "1.3.0",
13+
versionName: "1.4.0",
1414
versionCode: 1
1515
]
1616
}

config/detekt/baseline.xml

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
<ID>FinalNewline:com.qonversion.android.sdk.internal.storage.PurchasesCacheTest.kt:1</ID>
2828
<ID>FinalNewline:com.qonversion.android.sdk.internal.storage.util.kt:1</ID>
2929
<ID>FinalNewline:com.qonversion.android.sdk.utils.kt:1</ID>
30-
<ID>ImplicitDefaultLocale:HomeFragment.kt$HomeFragment$String.format( "%s %s", getStr(R.string.buy_for), inApp.prettyPrice )</ID>
3130
<ID>LargeClass:QProductCenterManager.kt$QProductCenterManager : PurchasesListenerUserStateProvider</ID>
3231
<ID>LongMethod:NoCodesSkeletonView.kt$NoCodesSkeletonView$private fun createSkeletonElements()</ID>
3332
<ID>MagicNumber:ApiErrorMapper.kt$ApiErrorMapper$10002</ID>
@@ -52,6 +51,8 @@
5251
<ID>MagicNumber:ApiErrorMapper.kt$ApiErrorMapper$20303</ID>
5352
<ID>MagicNumber:ApiErrorMapper.kt$ApiErrorMapper$20399</ID>
5453
<ID>MagicNumber:ApiInteractorImpl.kt$418</ID>
54+
<ID>MagicNumber:ImagePreloaderImpl.kt$ImagePreloaderImpl$200</ID>
55+
<ID>MagicNumber:ImagePreloaderImpl.kt$ImagePreloaderImpl$299</ID>
5556
<ID>MagicNumber:LogLevel.kt$LogLevel.Error$30</ID>
5657
<ID>MagicNumber:LogLevel.kt$LogLevel.Info$10</ID>
5758
<ID>MagicNumber:LogLevel.kt$LogLevel.Warning$20</ID>
@@ -126,7 +127,6 @@
126127
<ID>NoWildcardImports:com.qonversion.android.sdk.internal.storage.SharedPreferencesCacheTest.kt:5</ID>
127128
<ID>NoWildcardImports:com.qonversion.android.sdk.internal.storage.util.kt:24</ID>
128129
<ID>NoWildcardImports:com.qonversion.android.sdk.utils.kt:4</ID>
129-
<ID>NoWildcardImports:io.qonversion.sample.HomeFragment.kt:35</ID>
130130
<ID>ReturnCount:BillingClientWrapper.kt$BillingClientWrapper$override fun makePurchase( activity: Activity, product: QProduct, offerId: String?, applyOffer: Boolean?, updatePurchaseInfo: UpdatePurchaseInfo?, onFailed: (error: BillingError) -&gt; Unit )</ID>
131131
<ID>ReturnCount:ErrorUtils.kt$ErrorUtils$ fun isServerError(error: Exception): Boolean</ID>
132132
<ID>ReturnCount:ExceptionHandler.kt$ExceptionHandler$private fun isQonversionException(exception: Throwable): Boolean</ID>
@@ -144,17 +144,20 @@
144144
<ID>SpacingAroundParens:com.qonversion.android.sdk.utils.kt:66</ID>
145145
<ID>StringTemplate:com.qonversion.android.sdk.utils.kt:50</ID>
146146
<ID>SwallowedException:ApiErrorMapper.kt$ApiErrorMapper$catch (e: JSONException) { errorMessage = "$ERROR=failed to parse the backend response" }</ID>
147-
<ID>SwallowedException:AuthActivity.kt$AuthActivity$catch (e: ApiException) { showGoogleLoginError() }</ID>
148147
<ID>SwallowedException:EnvironmentProvider.kt$EnvironmentProvider$catch (throwable: Throwable) { UNKNOWN }</ID>
149148
<ID>SwallowedException:ExceptionHandler.kt$ExceptionHandler$catch (e: Exception) { "" }</ID>
150149
<ID>SwallowedException:FacebookAttribution.kt$FacebookAttribution$catch (e: Exception) { null }</ID>
151150
<ID>SwallowedException:FallbackUtils.kt$FallbackUtils$catch (e: Exception) { false }</ID>
151+
<ID>SwallowedException:ImagePreloaderImpl.kt$ImagePreloaderImpl$catch (e: Exception) { urlString to null }</ID>
152+
<ID>SwallowedException:OtherFragment.kt$OtherFragment$catch (e: Exception) { binding.progressBar.visibility = View.GONE Toast.makeText(context, getString(R.string.error_checking_fallback), Toast.LENGTH_SHORT).show() }</ID>
152153
<ID>SwallowedException:PurchasesCache.kt$PurchasesCache$catch (e: IOException) { setOf() }</ID>
154+
<ID>SwallowedException:RemoteConfigsAdapter.kt$RemoteConfigsAdapter$catch (e: Exception) { payloadJson.toString() }</ID>
153155
<ID>SwallowedException:ScreenFragment.kt$ScreenFragment$catch (e: ActivityNotFoundException) { logger.error("ScreenActivity -&gt; Couldn't find any Activity to handle the Intent with deeplink $url") delegate?.onActionFailedToExecute(action) }</ID>
154156
<ID>SwallowedException:ScreenFragment.kt$ScreenFragment$catch (e: ActivityNotFoundException) { logger.error("ScreenActivity -&gt; Couldn't find any Activity to handle the Intent with url $url") delegate?.onActionFailedToExecute(action) }</ID>
155157
<ID>SwallowedException:ScreenFragment.kt$ScreenFragment$catch (e: Exception) { delegate?.onActionFailedToExecute(action) }</ID>
156158
<ID>SwallowedException:ScreenPresenter.kt$ScreenPresenter$catch (e: Exception) { logger.error("ScreenPresenter -&gt; failed to open the screen with id $screenId") }</ID>
157159
<ID>SwallowedException:SharedPreferencesCache.kt$SharedPreferencesCache$catch (e: IOException) { null }</ID>
160+
<ID>SwallowedException:UserFragment.kt$UserFragment$catch (e: Exception) { Toast.makeText(context, getString(R.string.invalid_json_format), Toast.LENGTH_SHORT).show() }</ID>
158161
<ID>ThrowingExceptionsWithoutMessageOrCause:AdvertisingProvider.kt$AdvertisingProvider.AdvertisingConnection$IllegalStateException()</ID>
159162
<ID>ThrowsCount:ScreenServiceImpl.kt$ScreenServiceImpl$private suspend fun executeWithFallback( requestProvider: () -&gt; Request, fallbackProvider: suspend () -&gt; NoCodeScreen?, errorContext: String, methodName: String ): NoCodeScreen</ID>
160163
<ID>TooGenericExceptionCaught:AdvertisingProvider.kt$AdvertisingProvider$e: Exception</ID>
@@ -164,36 +167,21 @@
164167
<ID>TooGenericExceptionCaught:FacebookAttribution.kt$FacebookAttribution$e: Exception</ID>
165168
<ID>TooGenericExceptionCaught:FallbackServiceImpl.kt$FallbackServiceImpl$e: Exception</ID>
166169
<ID>TooGenericExceptionCaught:FallbackUtils.kt$FallbackUtils$e: Exception</ID>
170+
<ID>TooGenericExceptionCaught:ImagePreloaderImpl.kt$ImagePreloaderImpl$e: Exception</ID>
167171
<ID>TooGenericExceptionCaught:JsonSerializer.kt$JsonSerializer$cause: NullPointerException</ID>
168172
<ID>TooGenericExceptionCaught:NetworkClientImpl.kt$NetworkClientImpl$cause: Exception</ID>
169173
<ID>TooGenericExceptionCaught:NoCodesInternal.kt$NoCodesInternal$e: Exception</ID>
174+
<ID>TooGenericExceptionCaught:OtherFragment.kt$OtherFragment$e: Exception</ID>
170175
<ID>TooGenericExceptionCaught:QExceptionManager.kt$QExceptionManager$cause: Exception</ID>
171176
<ID>TooGenericExceptionCaught:QFallbacksService.kt$QFallbacksService$e: Exception</ID>
177+
<ID>TooGenericExceptionCaught:RemoteConfigsAdapter.kt$RemoteConfigsAdapter$e: Exception</ID>
172178
<ID>TooGenericExceptionCaught:ScreenControllerImpl.kt$ScreenControllerImpl$e: Exception</ID>
173179
<ID>TooGenericExceptionCaught:ScreenFragment.kt$ScreenFragment$e: Exception</ID>
174180
<ID>TooGenericExceptionCaught:ScreenFragment.kt$ScreenFragment$throwable: Throwable</ID>
175181
<ID>TooGenericExceptionCaught:ScreenPresenter.kt$ScreenPresenter$e: Exception</ID>
176182
<ID>TooGenericExceptionCaught:ScreenServiceImpl.kt$ScreenServiceImpl$e: Exception</ID>
177183
<ID>TooGenericExceptionCaught:ScreenServiceImpl.kt$ScreenServiceImpl$fallbackError: Exception</ID>
178-
<ID>TooManyFunctions:Api.kt$Api</ID>
179-
<ID>TooManyFunctions:AppComponent.kt$AppComponent</ID>
180-
<ID>TooManyFunctions:BillingClientWrapper.kt$BillingClientWrapper : IBillingClientWrapper</ID>
181-
<ID>TooManyFunctions:Cache.kt$Cache</ID>
182-
<ID>TooManyFunctions:DefaultRepository.kt$DefaultRepository : QRepository</ID>
183-
<ID>TooManyFunctions:HomeFragment.kt$HomeFragment : FragmentNoCodesDelegate</ID>
184-
<ID>TooManyFunctions:LaunchResultCacheWrapper.kt$LaunchResultCacheWrapper</ID>
185-
<ID>TooManyFunctions:NoCodesSkeletonView.kt$NoCodesSkeletonView : FrameLayout</ID>
186-
<ID>TooManyFunctions:QProductCenterManager.kt$QProductCenterManager : PurchasesListenerUserStateProvider</ID>
187-
<ID>TooManyFunctions:QRemoteConfigManager.kt$QRemoteConfigManager</ID>
188-
<ID>TooManyFunctions:QRepository.kt$QRepository</ID>
189-
<ID>TooManyFunctions:QUserPropertiesManager.kt$QUserPropertiesManager : FacebookAttributionListener</ID>
190-
<ID>TooManyFunctions:Qonversion.kt$Qonversion</ID>
191-
<ID>TooManyFunctions:QonversionBillingService.kt$QonversionBillingService : PurchasesUpdatedListenerConnectionListenerBillingService</ID>
192-
<ID>TooManyFunctions:QonversionInternal.kt$QonversionInternal : QonversionLifecycleDelegateAppStateProvider</ID>
193-
<ID>TooManyFunctions:RepositoryWithRateLimits.kt$RepositoryWithRateLimits : QRepository</ID>
194-
<ID>TooManyFunctions:ScreenFragment.kt$ScreenFragment : FragmentView</ID>
195-
<ID>TooManyFunctions:SharedPreferencesCache.kt$SharedPreferencesCache : Cache</ID>
196-
<ID>TooManyFunctions:extensions.kt$com.qonversion.android.sdk.internal.extensions.kt</ID>
184+
<ID>TooGenericExceptionCaught:UserFragment.kt$UserFragment$e: Exception</ID>
197185
<ID>UnnecessaryAbstractClass:BaseClass.kt$BaseClass</ID>
198186
<ID>UnnecessaryAbstractClass:RequestData.kt$RequestData</ID>
199187
<ID>UnusedPrivateMember:QonversionMappingAdapters.kt$QDateAdapter$@ToJson private fun toJson(date: Date): Long</ID>

config/detekt/detekt.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ complexity:
137137
excludeStringsWithLessThan5Characters: true
138138
ignoreStringsRegex: '$^'
139139
TooManyFunctions:
140-
active: true
140+
active: false
141141
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
142142
thresholdInFiles: 11
143143
thresholdInClasses: 11

fastlane/report.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77

8-
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000233">
8+
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000221">
99

1010
</testcase>
1111

nocodes/src/main/java/io/qonversion/nocodes/NoCodes.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package io.qonversion.nocodes
22

33
import android.util.Log
44
import io.qonversion.nocodes.dto.LogLevel
5+
import io.qonversion.nocodes.dto.NoCodesTheme
56
import io.qonversion.nocodes.interfaces.NoCodesDelegate
67
import io.qonversion.nocodes.interfaces.PurchaseDelegate
78
import io.qonversion.nocodes.interfaces.PurchaseDelegateWithCallbacks
@@ -145,4 +146,16 @@ interface NoCodes {
145146
* @param locale the custom locale code, or null to use system default.
146147
*/
147148
fun setLocale(locale: String?)
149+
150+
/**
151+
* Set the theme mode for No-Code screens.
152+
* Controls how screens adapt to light/dark themes.
153+
*
154+
* You may set theme both *after* Qonversion No-Codes SDK initializing with [NoCodes.setTheme]
155+
* and *while* Qonversion No-Codes initializing via [NoCodesConfig.Builder.setTheme]
156+
*
157+
* @param theme the desired theme mode. Use [NoCodesTheme.Auto] to follow device settings,
158+
* [NoCodesTheme.Light] to force light theme, or [NoCodesTheme.Dark] to force dark theme.
159+
*/
160+
fun setTheme(theme: NoCodesTheme)
148161
}

nocodes/src/main/java/io/qonversion/nocodes/NoCodesConfig.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package io.qonversion.nocodes
33
import android.app.Application
44
import android.content.Context
55
import io.qonversion.nocodes.dto.LogLevel
6+
import io.qonversion.nocodes.dto.NoCodesTheme
67
import io.qonversion.nocodes.interfaces.NoCodesDelegate
78
import io.qonversion.nocodes.interfaces.PurchaseDelegate
89
import io.qonversion.nocodes.interfaces.PurchaseDelegateWithCallbacks
@@ -32,6 +33,7 @@ class NoCodesConfig internal constructor(
3233
internal val purchaseDelegate: PurchaseDelegate?,
3334
internal val purchaseDelegateWithCallbacks: PurchaseDelegateWithCallbacks?,
3435
internal val locale: String?,
36+
internal val theme: NoCodesTheme,
3537
) {
3638

3739
/**
@@ -57,6 +59,7 @@ class NoCodesConfig internal constructor(
5759
private var logTag = DEFAULT_LOG_TAG
5860
private var customFallbackFileName: String? = null
5961
private var locale: String? = null
62+
private var theme: NoCodesTheme = NoCodesTheme.Auto
6063

6164
/**
6265
* Provide a delegate to be notified about the no-code screens events.
@@ -171,6 +174,18 @@ class NoCodesConfig internal constructor(
171174
this.locale = locale
172175
}
173176

177+
/**
178+
* Set the theme mode for No-Code screens.
179+
* Controls how screens adapt to light/dark themes.
180+
*
181+
* @param theme the desired theme mode. Use [NoCodesTheme.Auto] to follow device settings,
182+
* [NoCodesTheme.Light] to force light theme, or [NoCodesTheme.Dark] to force dark theme.
183+
* @return builder instance for chain calls.
184+
*/
185+
fun setTheme(theme: NoCodesTheme): Builder = apply {
186+
this.theme = theme
187+
}
188+
174189
/**
175190
* Generate [NoCodesConfig] instance with all the provided configurations.
176191
* This method also validates some of the provided data.
@@ -197,6 +212,7 @@ class NoCodesConfig internal constructor(
197212
purchaseDelegate,
198213
purchaseDelegateWithCallbacks,
199214
locale,
215+
theme,
200216
)
201217
}
202218
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.qonversion.nocodes.dto
2+
3+
/**
4+
* Enum representing the theme mode for No-Code screens.
5+
* Use this to control how screens adapt to light/dark themes.
6+
*/
7+
enum class NoCodesTheme(val value: String) {
8+
/**
9+
* Automatically follow the device's system appearance (default).
10+
* The screen will use light theme in light mode and dark theme in dark mode.
11+
*/
12+
Auto("auto"),
13+
14+
/**
15+
* Force light theme regardless of device settings.
16+
*/
17+
Light("light"),
18+
19+
/**
20+
* Force dark theme regardless of device settings.
21+
*/
22+
Dark("dark")
23+
}

nocodes/src/main/java/io/qonversion/nocodes/internal/NoCodesInternal.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package io.qonversion.nocodes.internal
22

33
import io.qonversion.nocodes.NoCodes
44
import io.qonversion.nocodes.dto.LogLevel
5+
import io.qonversion.nocodes.dto.NoCodesTheme
56
import io.qonversion.nocodes.interfaces.NoCodesDelegate
67
import io.qonversion.nocodes.interfaces.PurchaseDelegate
78
import io.qonversion.nocodes.interfaces.PurchaseDelegateWithCallbacks
@@ -73,4 +74,8 @@ internal class NoCodesInternal(
7374
override fun setLocale(locale: String?) {
7475
internalConfig.customLocale = locale
7576
}
77+
78+
override fun setTheme(theme: NoCodesTheme) {
79+
internalConfig.theme = theme
80+
}
7681
}

nocodes/src/main/java/io/qonversion/nocodes/internal/di/controllers/ControllersAssemblyImpl.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ internal class ControllersAssemblyImpl(
3535
miscAssembly.noCodesDelegateProvider(),
3636
miscAssembly.jsonSerializer(),
3737
mappersAssembly.actionMapper(),
38-
{ miscAssembly.customLocale() }
38+
{ miscAssembly.customLocale() },
39+
{ miscAssembly.theme() }
3940
)
4041
}
4142
}

nocodes/src/main/java/io/qonversion/nocodes/internal/di/misc/MiscAssembly.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.qonversion.nocodes.internal.di.misc
22

3+
import io.qonversion.nocodes.dto.NoCodesTheme
34
import io.qonversion.nocodes.internal.common.serializers.Serializer
45
import io.qonversion.nocodes.internal.logger.Logger
56
import io.qonversion.nocodes.internal.networkLayer.retryDelayCalculator.RetryDelayCalculator
@@ -19,6 +20,11 @@ internal interface MiscAssembly {
1920
*/
2021
fun customLocale(): String?
2122

23+
/**
24+
* Returns the current theme setting for No-Code screens.
25+
*/
26+
fun theme(): NoCodesTheme
27+
2228
fun jsonSerializer(): Serializer
2329

2430
fun exponentialDelayCalculator(): RetryDelayCalculator

0 commit comments

Comments
 (0)