separate interceptors; added language interceptor for api responses

This commit is contained in:
2024-07-13 17:04:18 +03:00
parent f545a9c4e5
commit dfdc48b682
10 changed files with 124 additions and 13 deletions
@@ -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()
}
@@ -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<Resources> { androidContext().resources }
factory<PowerManager> { androidContext().getSystemService(Context.POWER_SERVICE) as PowerManager }
singleOf(::ApiLanguageProvider) bind Provider::class
viewModelOf(::MainViewModelImpl) {
qualifier = qualifier("main")
}
@@ -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<ApiLanguage> {
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)
}
}
@@ -0,0 +1,3 @@
package com.meloda.app.fast.common
data class ApiLanguage(val value: String)
@@ -0,0 +1,5 @@
package com.meloda.app.fast.common.provider
interface Provider<T> {
fun provide(): T?
}
@@ -13,6 +13,7 @@ interface UserSettings {
val online: StateFlow<Boolean>
val debugSettingsEnabled: StateFlow<Boolean>
val useContactNames: StateFlow<Boolean>
val language: StateFlow<String>
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 }
}
}
@@ -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<AuthInterceptor>())
.addInterceptor(get<AccessTokenInterceptor>())
.addInterceptor(get<VersionInterceptor>())
.addInterceptor(get<LanguageInterceptor>())
.addInterceptor(get<ChuckerInterceptor>())
.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<Retrofit>(named("oauth")).create(OAuthService::class.java) }
single { service(PhotosService::class.java) }
single { service(UsersService::class.java) }
single { service(VideosService::class.java) }
@@ -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())
}
}
@@ -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<ApiLanguage>) : 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())
}
}
@@ -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())
}
}