From dfdc48b6827ed66d5b1938dbbf04d3bd4f105452 Mon Sep 17 00:00:00 2001 From: Danil Nikolaev Date: Sat, 13 Jul 2024 17:04:18 +0300 Subject: [PATCH] separate interceptors; added language interceptor for api responses --- .../com/meloda/app/fast/MainActivity.kt | 18 ++++++++++++ .../app/fast/common/di/ApplicationModule.kt | 5 ++++ .../app/fast/provider/ApiLanguageProvider.kt | 20 +++++++++++++ .../com/meloda/app/fast/common/ApiLanguage.kt | 3 ++ .../app/fast/common/provider/Provider.kt | 5 ++++ .../meloda/app/fast/datastore/UserSettings.kt | 8 ++++++ .../app/fast/network/di/NetworkModule.kt | 13 ++++++--- .../interceptor/AccessTokenInterceptor.kt | 25 +++++++++++++++++ .../interceptor/LanguageInterceptor.kt | 28 +++++++++++++++++++ .../interceptor/VersionInterceptor.kt} | 12 ++------ 10 files changed, 124 insertions(+), 13 deletions(-) create mode 100644 app/src/main/kotlin/com/meloda/app/fast/provider/ApiLanguageProvider.kt create mode 100644 core/common/src/main/kotlin/com/meloda/app/fast/common/ApiLanguage.kt create mode 100644 core/common/src/main/kotlin/com/meloda/app/fast/common/provider/Provider.kt create mode 100644 core/network/src/main/kotlin/com/meloda/app/fast/network/interceptor/AccessTokenInterceptor.kt create mode 100644 core/network/src/main/kotlin/com/meloda/app/fast/network/interceptor/LanguageInterceptor.kt rename core/{common/src/main/kotlin/com/meloda/app/fast/common/AuthInterceptor.kt => network/src/main/kotlin/com/meloda/app/fast/network/interceptor/VersionInterceptor.kt} (68%) diff --git a/app/src/main/kotlin/com/meloda/app/fast/MainActivity.kt b/app/src/main/kotlin/com/meloda/app/fast/MainActivity.kt index c4d94d0c..ab704389 100644 --- a/app/src/main/kotlin/com/meloda/app/fast/MainActivity.kt +++ b/app/src/main/kotlin/com/meloda/app/fast/MainActivity.kt @@ -27,6 +27,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.rememberPermissionState import com.meloda.app.fast.common.UiText +import com.meloda.app.fast.common.extensions.ifEmpty import com.meloda.app.fast.common.extensions.isSdkAtLeast import com.meloda.app.fast.datastore.SettingsController import com.meloda.app.fast.datastore.SettingsKeys @@ -55,6 +56,23 @@ class MainActivity : AppCompatActivity() { setContent { KoinContext { val userSettings: UserSettings = koinInject() + + LifecycleResumeEffect(true) { + userSettings.onLanguageChanged( + AppCompatDelegate.getApplicationLocales() + .toLanguageTags() + .ifEmpty { null } + ?: LocaleListCompat.getDefault() + .toLanguageTags() + .split(",") + .firstOrNull() + .orEmpty() + .take(5) + ) + + onPauseOrDispose {} + } + LaunchedEffect(true) { userSettings.updateUsingDarkTheme() } diff --git a/app/src/main/kotlin/com/meloda/app/fast/common/di/ApplicationModule.kt b/app/src/main/kotlin/com/meloda/app/fast/common/di/ApplicationModule.kt index 7751dd78..c0e640fa 100644 --- a/app/src/main/kotlin/com/meloda/app/fast/common/di/ApplicationModule.kt +++ b/app/src/main/kotlin/com/meloda/app/fast/common/di/ApplicationModule.kt @@ -7,6 +7,7 @@ import androidx.preference.PreferenceManager import com.meloda.app.fast.MainViewModelImpl import com.meloda.app.fast.auth.authModule import com.meloda.app.fast.chatmaterials.di.chatMaterialsModule +import com.meloda.app.fast.common.provider.Provider import com.meloda.app.fast.conversations.di.conversationsModule import com.meloda.app.fast.data.di.dataModule import com.meloda.app.fast.friends.di.friendsModule @@ -14,12 +15,14 @@ import com.meloda.app.fast.languagepicker.di.languagePickerModule import com.meloda.app.fast.messageshistory.di.messagesHistoryModule import com.meloda.app.fast.photoviewer.di.photoViewModule import com.meloda.app.fast.profile.di.profileModule +import com.meloda.app.fast.provider.ApiLanguageProvider import com.meloda.app.fast.service.longpolling.di.longPollModule import com.meloda.app.fast.settings.di.settingsModule import org.koin.android.ext.koin.androidContext import org.koin.androidx.viewmodel.dsl.viewModelOf import org.koin.core.module.dsl.singleOf import org.koin.core.qualifier.qualifier +import org.koin.dsl.bind import org.koin.dsl.module val applicationModule = module { @@ -43,6 +46,8 @@ val applicationModule = module { single { androidContext().resources } factory { androidContext().getSystemService(Context.POWER_SERVICE) as PowerManager } + singleOf(::ApiLanguageProvider) bind Provider::class + viewModelOf(::MainViewModelImpl) { qualifier = qualifier("main") } diff --git a/app/src/main/kotlin/com/meloda/app/fast/provider/ApiLanguageProvider.kt b/app/src/main/kotlin/com/meloda/app/fast/provider/ApiLanguageProvider.kt new file mode 100644 index 00000000..f1d3fd7a --- /dev/null +++ b/app/src/main/kotlin/com/meloda/app/fast/provider/ApiLanguageProvider.kt @@ -0,0 +1,20 @@ +package com.meloda.app.fast.provider + +import com.meloda.app.fast.common.ApiLanguage +import com.meloda.app.fast.common.provider.Provider +import com.meloda.app.fast.datastore.UserSettings + +class ApiLanguageProvider(private val userSettings: UserSettings) : Provider { + + override fun provide(): ApiLanguage? { + val language = userSettings.language.value + + return when { + language == "ru-RU" -> "ru" + language.startsWith("en") -> "en" + language == "uk-UA" -> "ua" + else -> null + }?.let(::ApiLanguage) + } + +} diff --git a/core/common/src/main/kotlin/com/meloda/app/fast/common/ApiLanguage.kt b/core/common/src/main/kotlin/com/meloda/app/fast/common/ApiLanguage.kt new file mode 100644 index 00000000..d6e4bdba --- /dev/null +++ b/core/common/src/main/kotlin/com/meloda/app/fast/common/ApiLanguage.kt @@ -0,0 +1,3 @@ +package com.meloda.app.fast.common + +data class ApiLanguage(val value: String) diff --git a/core/common/src/main/kotlin/com/meloda/app/fast/common/provider/Provider.kt b/core/common/src/main/kotlin/com/meloda/app/fast/common/provider/Provider.kt new file mode 100644 index 00000000..5918cef0 --- /dev/null +++ b/core/common/src/main/kotlin/com/meloda/app/fast/common/provider/Provider.kt @@ -0,0 +1,5 @@ +package com.meloda.app.fast.common.provider + +interface Provider { + fun provide(): T? +} diff --git a/core/datastore/src/main/kotlin/com/meloda/app/fast/datastore/UserSettings.kt b/core/datastore/src/main/kotlin/com/meloda/app/fast/datastore/UserSettings.kt index 40b4014f..70a4718c 100644 --- a/core/datastore/src/main/kotlin/com/meloda/app/fast/datastore/UserSettings.kt +++ b/core/datastore/src/main/kotlin/com/meloda/app/fast/datastore/UserSettings.kt @@ -13,6 +13,7 @@ interface UserSettings { val online: StateFlow val debugSettingsEnabled: StateFlow val useContactNames: StateFlow + val language: StateFlow fun updateUsingDarkTheme() fun useDarkThemeChanged(use: Boolean) @@ -24,6 +25,7 @@ interface UserSettings { fun setOnline(use: Boolean) fun enableDebugSettings(enable: Boolean) fun onUseContactNamesChanged(use: Boolean) + fun onLanguageChanged(newLanguage: String) } class UserSettingsImpl( @@ -69,6 +71,8 @@ class UserSettingsImpl( ) ) + override val language = MutableStateFlow("") + override fun updateUsingDarkTheme() { useDarkThemeChanged( isUsingDarkMode( @@ -117,4 +121,8 @@ class UserSettingsImpl( override fun onUseContactNamesChanged(use: Boolean) { useContactNames.update { use } } + + override fun onLanguageChanged(newLanguage: String) { + language.update { newLanguage } + } } diff --git a/core/network/src/main/kotlin/com/meloda/app/fast/network/di/NetworkModule.kt b/core/network/src/main/kotlin/com/meloda/app/fast/network/di/NetworkModule.kt index 03695e86..a3ca84d1 100644 --- a/core/network/src/main/kotlin/com/meloda/app/fast/network/di/NetworkModule.kt +++ b/core/network/src/main/kotlin/com/meloda/app/fast/network/di/NetworkModule.kt @@ -3,11 +3,13 @@ package com.meloda.app.fast.network.di import com.chuckerteam.chucker.api.ChuckerCollector import com.chuckerteam.chucker.api.ChuckerInterceptor import com.meloda.app.fast.common.AppConstants -import com.meloda.app.fast.common.AuthInterceptor import com.meloda.app.fast.network.JsonConverter import com.meloda.app.fast.network.MoshiConverter import com.meloda.app.fast.network.OAuthResultCallFactory import com.meloda.app.fast.network.ResponseConverterFactory +import com.meloda.app.fast.network.interceptor.AccessTokenInterceptor +import com.meloda.app.fast.network.interceptor.LanguageInterceptor +import com.meloda.app.fast.network.interceptor.VersionInterceptor import com.meloda.app.fast.network.service.account.AccountService import com.meloda.app.fast.network.service.audios.AudiosService import com.meloda.app.fast.network.service.auth.AuthService @@ -39,12 +41,16 @@ val networkModule = module { singleOf(::MoshiConverter) bind JsonConverter::class single { ChuckerCollector(get()) } single { ChuckerInterceptor.Builder(get()).collector(get()).build() } - singleOf(::AuthInterceptor) + singleOf(::AccessTokenInterceptor) + singleOf(::VersionInterceptor) + singleOf(::LanguageInterceptor) single { OkHttpClient.Builder() .connectTimeout(20, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) - .addInterceptor(get()) + .addInterceptor(get()) + .addInterceptor(get()) + .addInterceptor(get()) .addInterceptor(get()) .followRedirects(true) .followSslRedirects(true) @@ -84,7 +90,6 @@ val networkModule = module { single { service(LongPollService::class.java) } single { service(MessagesService::class.java) } single { service(OAuthService::class.java) } -// single { get(named("oauth")).create(OAuthService::class.java) } single { service(PhotosService::class.java) } single { service(UsersService::class.java) } single { service(VideosService::class.java) } diff --git a/core/network/src/main/kotlin/com/meloda/app/fast/network/interceptor/AccessTokenInterceptor.kt b/core/network/src/main/kotlin/com/meloda/app/fast/network/interceptor/AccessTokenInterceptor.kt new file mode 100644 index 00000000..c38ed1dc --- /dev/null +++ b/core/network/src/main/kotlin/com/meloda/app/fast/network/interceptor/AccessTokenInterceptor.kt @@ -0,0 +1,25 @@ +package com.meloda.app.fast.network.interceptor + +import androidx.core.net.toUri +import com.meloda.app.fast.common.UserConfig +import okhttp3.Interceptor +import okhttp3.Response +import java.net.URLEncoder + +class AccessTokenInterceptor : Interceptor { + + override fun intercept(chain: Interceptor.Chain): Response { + val builder = chain.request().url.newBuilder() + + val uri = builder.build().toUri().toString().toUri() + + if (uri.getQueryParameter("access_token") == null) { + builder.addQueryParameter( + "access_token", + URLEncoder.encode(UserConfig.accessToken, "utf-8") + ) + } + + return chain.proceed(chain.request().newBuilder().apply { url(builder.build()) }.build()) + } +} diff --git a/core/network/src/main/kotlin/com/meloda/app/fast/network/interceptor/LanguageInterceptor.kt b/core/network/src/main/kotlin/com/meloda/app/fast/network/interceptor/LanguageInterceptor.kt new file mode 100644 index 00000000..307e8b56 --- /dev/null +++ b/core/network/src/main/kotlin/com/meloda/app/fast/network/interceptor/LanguageInterceptor.kt @@ -0,0 +1,28 @@ +package com.meloda.app.fast.network.interceptor + +import androidx.core.net.toUri +import com.meloda.app.fast.common.ApiLanguage +import com.meloda.app.fast.common.provider.Provider +import okhttp3.Interceptor +import okhttp3.Response +import java.net.URLEncoder + +class LanguageInterceptor(private val provider: Provider) : Interceptor { + + override fun intercept(chain: Interceptor.Chain): Response { + val builder = chain.request().url.newBuilder() + + val uri = builder.build().toUri().toString().toUri() + + val apiLanguage = provider.provide()?.value ?: "ru" + + if (uri.getQueryParameter("lang") == null) { + builder.addQueryParameter( + name = "lang", + value = URLEncoder.encode(apiLanguage, "utf-8") + ) + } + + return chain.proceed(chain.request().newBuilder().apply { url(builder.build()) }.build()) + } +} diff --git a/core/common/src/main/kotlin/com/meloda/app/fast/common/AuthInterceptor.kt b/core/network/src/main/kotlin/com/meloda/app/fast/network/interceptor/VersionInterceptor.kt similarity index 68% rename from core/common/src/main/kotlin/com/meloda/app/fast/common/AuthInterceptor.kt rename to core/network/src/main/kotlin/com/meloda/app/fast/network/interceptor/VersionInterceptor.kt index 74a61c10..37312864 100644 --- a/core/common/src/main/kotlin/com/meloda/app/fast/common/AuthInterceptor.kt +++ b/core/network/src/main/kotlin/com/meloda/app/fast/network/interceptor/VersionInterceptor.kt @@ -1,11 +1,12 @@ -package com.meloda.app.fast.common +package com.meloda.app.fast.network.interceptor import androidx.core.net.toUri +import com.meloda.app.fast.common.AppConstants import okhttp3.Interceptor import okhttp3.Response import java.net.URLEncoder -class AuthInterceptor : Interceptor { +class VersionInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val builder = chain.request().url.newBuilder() @@ -19,13 +20,6 @@ class AuthInterceptor : Interceptor { ) } - if (UserConfig.accessToken.isNotBlank()) { - builder.addQueryParameter( - "access_token", - URLEncoder.encode(UserConfig.accessToken, "utf-8") - ) - } - return chain.proceed(chain.request().newBuilder().apply { url(builder.build()) }.build()) } }