forked from melod1n/fast-messenger
separate interceptors; added language interceptor for api responses
This commit is contained in:
@@ -27,6 +27,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
import com.google.accompanist.permissions.rememberPermissionState
|
import com.google.accompanist.permissions.rememberPermissionState
|
||||||
import com.meloda.app.fast.common.UiText
|
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.common.extensions.isSdkAtLeast
|
||||||
import com.meloda.app.fast.datastore.SettingsController
|
import com.meloda.app.fast.datastore.SettingsController
|
||||||
import com.meloda.app.fast.datastore.SettingsKeys
|
import com.meloda.app.fast.datastore.SettingsKeys
|
||||||
@@ -55,6 +56,23 @@ class MainActivity : AppCompatActivity() {
|
|||||||
setContent {
|
setContent {
|
||||||
KoinContext {
|
KoinContext {
|
||||||
val userSettings: UserSettings = koinInject()
|
val userSettings: UserSettings = koinInject()
|
||||||
|
|
||||||
|
LifecycleResumeEffect(true) {
|
||||||
|
userSettings.onLanguageChanged(
|
||||||
|
AppCompatDelegate.getApplicationLocales()
|
||||||
|
.toLanguageTags()
|
||||||
|
.ifEmpty { null }
|
||||||
|
?: LocaleListCompat.getDefault()
|
||||||
|
.toLanguageTags()
|
||||||
|
.split(",")
|
||||||
|
.firstOrNull()
|
||||||
|
.orEmpty()
|
||||||
|
.take(5)
|
||||||
|
)
|
||||||
|
|
||||||
|
onPauseOrDispose {}
|
||||||
|
}
|
||||||
|
|
||||||
LaunchedEffect(true) {
|
LaunchedEffect(true) {
|
||||||
userSettings.updateUsingDarkTheme()
|
userSettings.updateUsingDarkTheme()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import androidx.preference.PreferenceManager
|
|||||||
import com.meloda.app.fast.MainViewModelImpl
|
import com.meloda.app.fast.MainViewModelImpl
|
||||||
import com.meloda.app.fast.auth.authModule
|
import com.meloda.app.fast.auth.authModule
|
||||||
import com.meloda.app.fast.chatmaterials.di.chatMaterialsModule
|
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.conversations.di.conversationsModule
|
||||||
import com.meloda.app.fast.data.di.dataModule
|
import com.meloda.app.fast.data.di.dataModule
|
||||||
import com.meloda.app.fast.friends.di.friendsModule
|
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.messageshistory.di.messagesHistoryModule
|
||||||
import com.meloda.app.fast.photoviewer.di.photoViewModule
|
import com.meloda.app.fast.photoviewer.di.photoViewModule
|
||||||
import com.meloda.app.fast.profile.di.profileModule
|
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.service.longpolling.di.longPollModule
|
||||||
import com.meloda.app.fast.settings.di.settingsModule
|
import com.meloda.app.fast.settings.di.settingsModule
|
||||||
import org.koin.android.ext.koin.androidContext
|
import org.koin.android.ext.koin.androidContext
|
||||||
import org.koin.androidx.viewmodel.dsl.viewModelOf
|
import org.koin.androidx.viewmodel.dsl.viewModelOf
|
||||||
import org.koin.core.module.dsl.singleOf
|
import org.koin.core.module.dsl.singleOf
|
||||||
import org.koin.core.qualifier.qualifier
|
import org.koin.core.qualifier.qualifier
|
||||||
|
import org.koin.dsl.bind
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val applicationModule = module {
|
val applicationModule = module {
|
||||||
@@ -43,6 +46,8 @@ val applicationModule = module {
|
|||||||
single<Resources> { androidContext().resources }
|
single<Resources> { androidContext().resources }
|
||||||
factory<PowerManager> { androidContext().getSystemService(Context.POWER_SERVICE) as PowerManager }
|
factory<PowerManager> { androidContext().getSystemService(Context.POWER_SERVICE) as PowerManager }
|
||||||
|
|
||||||
|
singleOf(::ApiLanguageProvider) bind Provider::class
|
||||||
|
|
||||||
viewModelOf(::MainViewModelImpl) {
|
viewModelOf(::MainViewModelImpl) {
|
||||||
qualifier = qualifier("main")
|
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 online: StateFlow<Boolean>
|
||||||
val debugSettingsEnabled: StateFlow<Boolean>
|
val debugSettingsEnabled: StateFlow<Boolean>
|
||||||
val useContactNames: StateFlow<Boolean>
|
val useContactNames: StateFlow<Boolean>
|
||||||
|
val language: StateFlow<String>
|
||||||
|
|
||||||
fun updateUsingDarkTheme()
|
fun updateUsingDarkTheme()
|
||||||
fun useDarkThemeChanged(use: Boolean)
|
fun useDarkThemeChanged(use: Boolean)
|
||||||
@@ -24,6 +25,7 @@ interface UserSettings {
|
|||||||
fun setOnline(use: Boolean)
|
fun setOnline(use: Boolean)
|
||||||
fun enableDebugSettings(enable: Boolean)
|
fun enableDebugSettings(enable: Boolean)
|
||||||
fun onUseContactNamesChanged(use: Boolean)
|
fun onUseContactNamesChanged(use: Boolean)
|
||||||
|
fun onLanguageChanged(newLanguage: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserSettingsImpl(
|
class UserSettingsImpl(
|
||||||
@@ -69,6 +71,8 @@ class UserSettingsImpl(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override val language = MutableStateFlow("")
|
||||||
|
|
||||||
override fun updateUsingDarkTheme() {
|
override fun updateUsingDarkTheme() {
|
||||||
useDarkThemeChanged(
|
useDarkThemeChanged(
|
||||||
isUsingDarkMode(
|
isUsingDarkMode(
|
||||||
@@ -117,4 +121,8 @@ class UserSettingsImpl(
|
|||||||
override fun onUseContactNamesChanged(use: Boolean) {
|
override fun onUseContactNamesChanged(use: Boolean) {
|
||||||
useContactNames.update { use }
|
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.ChuckerCollector
|
||||||
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
||||||
import com.meloda.app.fast.common.AppConstants
|
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.JsonConverter
|
||||||
import com.meloda.app.fast.network.MoshiConverter
|
import com.meloda.app.fast.network.MoshiConverter
|
||||||
import com.meloda.app.fast.network.OAuthResultCallFactory
|
import com.meloda.app.fast.network.OAuthResultCallFactory
|
||||||
import com.meloda.app.fast.network.ResponseConverterFactory
|
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.account.AccountService
|
||||||
import com.meloda.app.fast.network.service.audios.AudiosService
|
import com.meloda.app.fast.network.service.audios.AudiosService
|
||||||
import com.meloda.app.fast.network.service.auth.AuthService
|
import com.meloda.app.fast.network.service.auth.AuthService
|
||||||
@@ -39,12 +41,16 @@ val networkModule = module {
|
|||||||
singleOf(::MoshiConverter) bind JsonConverter::class
|
singleOf(::MoshiConverter) bind JsonConverter::class
|
||||||
single { ChuckerCollector(get()) }
|
single { ChuckerCollector(get()) }
|
||||||
single { ChuckerInterceptor.Builder(get()).collector(get()).build() }
|
single { ChuckerInterceptor.Builder(get()).collector(get()).build() }
|
||||||
singleOf(::AuthInterceptor)
|
singleOf(::AccessTokenInterceptor)
|
||||||
|
singleOf(::VersionInterceptor)
|
||||||
|
singleOf(::LanguageInterceptor)
|
||||||
single {
|
single {
|
||||||
OkHttpClient.Builder()
|
OkHttpClient.Builder()
|
||||||
.connectTimeout(20, TimeUnit.SECONDS)
|
.connectTimeout(20, TimeUnit.SECONDS)
|
||||||
.readTimeout(30, TimeUnit.SECONDS)
|
.readTimeout(30, TimeUnit.SECONDS)
|
||||||
.addInterceptor(get<AuthInterceptor>())
|
.addInterceptor(get<AccessTokenInterceptor>())
|
||||||
|
.addInterceptor(get<VersionInterceptor>())
|
||||||
|
.addInterceptor(get<LanguageInterceptor>())
|
||||||
.addInterceptor(get<ChuckerInterceptor>())
|
.addInterceptor(get<ChuckerInterceptor>())
|
||||||
.followRedirects(true)
|
.followRedirects(true)
|
||||||
.followSslRedirects(true)
|
.followSslRedirects(true)
|
||||||
@@ -84,7 +90,6 @@ val networkModule = module {
|
|||||||
single { service(LongPollService::class.java) }
|
single { service(LongPollService::class.java) }
|
||||||
single { service(MessagesService::class.java) }
|
single { service(MessagesService::class.java) }
|
||||||
single { service(OAuthService::class.java) }
|
single { service(OAuthService::class.java) }
|
||||||
// single { get<Retrofit>(named("oauth")).create(OAuthService::class.java) }
|
|
||||||
single { service(PhotosService::class.java) }
|
single { service(PhotosService::class.java) }
|
||||||
single { service(UsersService::class.java) }
|
single { service(UsersService::class.java) }
|
||||||
single { service(VideosService::class.java) }
|
single { service(VideosService::class.java) }
|
||||||
|
|||||||
+25
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-9
@@ -1,11 +1,12 @@
|
|||||||
package com.meloda.app.fast.common
|
package com.meloda.app.fast.network.interceptor
|
||||||
|
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
import com.meloda.app.fast.common.AppConstants
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
|
|
||||||
class AuthInterceptor : Interceptor {
|
class VersionInterceptor : Interceptor {
|
||||||
|
|
||||||
override fun intercept(chain: Interceptor.Chain): Response {
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
val builder = chain.request().url.newBuilder()
|
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())
|
return chain.proceed(chain.request().newBuilder().apply { url(builder.build()) }.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user