Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-02 19:19:33 +05:00
parent 26bba893ff
commit 51e650c360
47 changed files with 1628 additions and 73 deletions

1
data/app-update/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,27 @@
plugins {
alias(deps.plugins.android.library)
alias(deps.plugins.kotlin.android)
alias(deps.plugins.kotlin.kapt)
alias(deps.plugins.hilt.android)
id("configuration")
}
android {
namespace = "com.tangem.data.appupdate"
}
dependencies {
implementation(projects.core.datasource)
implementation(projects.core.utils)
implementation(projects.domain.appUpdate)
implementation(deps.arrow.core)
implementation(deps.kotlin.coroutines)
// region DI
implementation(deps.hilt.android)
kapt(deps.hilt.kapt)
// endregion
}

View file

@ -0,0 +1,64 @@
package com.tangem.data.appupdate
import arrow.core.Either
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.ApplicationVersionsResponse
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull
import com.tangem.datasource.local.preferences.utils.getSyncOrNull
import com.tangem.datasource.local.preferences.utils.store
import com.tangem.datasource.local.preferences.utils.storeObject
import com.tangem.domain.appupdate.model.AppVersionInfo
import com.tangem.domain.appupdate.model.OptionalUpdateShown
import com.tangem.domain.appupdate.repository.AppUpdateRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.withContext
internal class DefaultAppUpdateRepository(
private val tangemTechApi: TangemTechApi,
private val appPreferencesStore: AppPreferencesStore,
private val dispatchers: CoroutineDispatcherProvider,
private val currentTimeMillis: () -> Long = System::currentTimeMillis,
) : AppUpdateRepository {
override suspend fun getCachedAppVersionInfo(): AppVersionInfo? = appPreferencesStore
.getObjectSyncOrNull<ApplicationVersionsResponse>(PreferencesKeys.CACHED_APP_VERSIONS_KEY)
?.toDomain()
override suspend fun getCachedAppVersionTimestamp(): Long? =
appPreferencesStore.getSyncOrNull(PreferencesKeys.CACHED_APP_VERSIONS_AT_KEY)
override suspend fun refreshAppVersionInfo(): Either<Throwable, AppVersionInfo> = withContext(dispatchers.io) {
Either.catch {
val response = tangemTechApi.getApplicationVersions().getOrThrow()
appPreferencesStore.storeObject(PreferencesKeys.CACHED_APP_VERSIONS_KEY, response)
appPreferencesStore.store(PreferencesKeys.CACHED_APP_VERSIONS_AT_KEY, currentTimeMillis())
response.toDomain()
}.onLeft { error -> TangemLogger.e("Unable to fetch application versions", error) }
}
override suspend fun getOptionalUpdateShown(): OptionalUpdateShown? {
val version = appPreferencesStore.getSyncOrNull(PreferencesKeys.LAST_OPTIONAL_UPDATE_SHOWN_VERSION_KEY)
?: return null
val shownAtMillis = appPreferencesStore.getSyncOrNull(PreferencesKeys.LAST_OPTIONAL_UPDATE_SHOWN_AT_KEY)
?: return null
return OptionalUpdateShown(version = version, shownAtMillis = shownAtMillis)
}
override suspend fun setOptionalUpdateShown(shown: OptionalUpdateShown) {
appPreferencesStore.store(PreferencesKeys.LAST_OPTIONAL_UPDATE_SHOWN_VERSION_KEY, shown.version)
appPreferencesStore.store(PreferencesKeys.LAST_OPTIONAL_UPDATE_SHOWN_AT_KEY, shown.shownAtMillis)
}
private fun ApplicationVersionsResponse.toDomain() = AppVersionInfo(
minSupportedVersion = minSupportedVersion,
minSupportedOSVersion = minSupportedOSVersion,
criticalVersion = criticalVersion,
criticalOSVersion = criticalOSVersion,
latestVersion = latestVersion,
)
}

View file

@ -0,0 +1,41 @@
package com.tangem.data.appupdate.di
import com.tangem.data.appupdate.DefaultAppUpdateRepository
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.domain.appupdate.repository.AppUpdateRepository
import com.tangem.domain.appupdate.usecase.GetAppUpdateStateUseCase
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.info.AppInfoProvider
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object AppUpdateDataModule {
@Provides
@Singleton
fun provideAppUpdateRepository(
tangemTechApi: TangemTechApi,
appPreferencesStore: AppPreferencesStore,
dispatchers: CoroutineDispatcherProvider,
): AppUpdateRepository = DefaultAppUpdateRepository(
tangemTechApi = tangemTechApi,
appPreferencesStore = appPreferencesStore,
dispatchers = dispatchers,
)
@Provides
@Singleton
fun provideGetAppUpdateStateUseCase(
repository: AppUpdateRepository,
appInfoProvider: AppInfoProvider,
): GetAppUpdateStateUseCase = GetAppUpdateStateUseCase(
repository = repository,
appInfoProvider = appInfoProvider,
)
}