From ac006946907ef9bf13f8b005056384f7ad128b96 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 29 May 2023 18:00:29 -0400 Subject: [PATCH] Moves ExoPlayer to OkHttp in order to enable Tor support. --- app/build.gradle | 2 ++ .../vitorpamplona/amethyst/ServiceManager.kt | 29 +++++++++++++++++-- .../com/vitorpamplona/amethyst/VideoCache.kt | 5 ++-- .../vitorpamplona/amethyst/ui/MainActivity.kt | 25 ++-------------- .../amethyst/ui/navigation/DrawerContent.kt | 13 ++++++--- .../ui/screen/AccountStateViewModel.kt | 5 ++-- 6 files changed, 45 insertions(+), 34 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 3d51eda78..9d6f14e8a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -140,6 +140,8 @@ dependencies { // view videos implementation 'com.google.android.exoplayer:exoplayer:2.18.7' + // important for proxy / tor + implementation 'com.google.android.exoplayer:extension-okhttp:2.18.7' // Load images from the web. implementation "io.coil-kt:coil-compose:$coil_version" diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt index 3f0eab359..45d7bd379 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt @@ -1,5 +1,12 @@ package com.vitorpamplona.amethyst +import android.content.Context +import android.os.Build +import coil.Coil +import coil.ImageLoader +import coil.decode.GifDecoder +import coil.decode.ImageDecoderDecoder +import coil.decode.SvgDecoder import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.service.HttpClient @@ -19,14 +26,30 @@ import com.vitorpamplona.amethyst.service.relays.Client object ServiceManager { private var account: Account? = null - fun start(account: Account) { + fun start(account: Account, context: Context) { this.account = account - start() + start(context) } - fun start() { + fun start(context: Context) { val myAccount = account + + // Resets Proxy Use HttpClient.start(account) + Coil.setImageLoader { + ImageLoader.Builder(context).components { + if (Build.VERSION.SDK_INT >= 28) { + add(ImageDecoderDecoder.Factory()) + } else { + add(GifDecoder.Factory()) + } + add(SvgDecoder.Factory()) + } // .logger(DebugLogger()) + .okHttpClient { HttpClient.getHttpClient() } + .respectCacheHeaders(false) + .build() + } + if (myAccount != null) { Client.connect(myAccount.activeRelays() ?: myAccount.convertLocalRelays()) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/VideoCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/VideoCache.kt index bd785161b..aafaa1bb7 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/VideoCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/VideoCache.kt @@ -2,10 +2,11 @@ package com.vitorpamplona.amethyst import android.content.Context import com.google.android.exoplayer2.database.StandaloneDatabaseProvider -import com.google.android.exoplayer2.upstream.DefaultHttpDataSource +import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource import com.google.android.exoplayer2.upstream.cache.CacheDataSource import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor import com.google.android.exoplayer2.upstream.cache.SimpleCache +import com.vitorpamplona.amethyst.service.HttpClient object VideoCache { @@ -31,7 +32,7 @@ object VideoCache { cacheDataSourceFactory = CacheDataSource.Factory() .setCache(simpleCache) .setUpstreamDataSourceFactory( - DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true) + OkHttpDataSource.Factory(HttpClient.getHttpClient()) ) .setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt index d70a7adbf..ad7e35618 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt @@ -2,7 +2,6 @@ package com.vitorpamplona.amethyst.ui import android.content.Context import android.content.Intent -import android.os.Build.VERSION.SDK_INT import android.os.Bundle import androidx.activity.compose.setContent import androidx.activity.result.contract.ActivityResultContracts @@ -12,15 +11,9 @@ import androidx.compose.material.Surface import androidx.compose.ui.Modifier import androidx.fragment.app.FragmentActivity import androidx.lifecycle.viewmodel.compose.viewModel -import coil.Coil -import coil.ImageLoader -import coil.decode.GifDecoder -import coil.decode.ImageDecoderDecoder -import coil.decode.SvgDecoder import com.vitorpamplona.amethyst.LocalPreferences import com.vitorpamplona.amethyst.ServiceManager import com.vitorpamplona.amethyst.VideoCache -import com.vitorpamplona.amethyst.service.HttpClient import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent @@ -52,20 +45,6 @@ class MainActivity : FragmentActivity() { // Initializes video cache. VideoCache.init(this.applicationContext) - Coil.setImageLoader { - ImageLoader.Builder(this).components { - if (SDK_INT >= 28) { - add(ImageDecoderDecoder.Factory()) - } else { - add(GifDecoder.Factory()) - } - add(SvgDecoder.Factory()) - } // .logger(DebugLogger()) - .okHttpClient { HttpClient.getHttpClient() } - .respectCacheHeaders(false) - .build() - } - LocalPreferences.migrateSingleUserPrefs() setContent { @@ -73,7 +52,7 @@ class MainActivity : FragmentActivity() { // A surface container using the 'background' color from the theme Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { val accountStateViewModel: AccountStateViewModel = viewModel { - AccountStateViewModel() + AccountStateViewModel(this@MainActivity) } AccountScreen(accountStateViewModel, startingPage) @@ -92,7 +71,7 @@ class MainActivity : FragmentActivity() { // Only starts after login GlobalScope.launch(Dispatchers.IO) { - ServiceManager.start() + ServiceManager.start(this@MainActivity) } PushNotificationUtils().init(LocalPreferences.allSavedAccounts()) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt index ac088468b..a3e91471d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt @@ -1,5 +1,6 @@ package com.vitorpamplona.amethyst.ui.navigation +import android.content.Context import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -43,6 +44,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -335,6 +337,8 @@ fun ListContent( AccountBackupDialog(account, onClose = { backupDialogOpen = false }) } + val context = LocalContext.current + if (conectOrbotDialogOpen) { ConnectOrbotDialog( onClose = { conectOrbotDialogOpen = false }, @@ -342,7 +346,7 @@ fun ListContent( conectOrbotDialogOpen = false disconnectTorDialog = false checked = true - enableTor(account, true, proxyPort) + enableTor(account, true, proxyPort, context = context) }, proxyPort ) @@ -364,7 +368,7 @@ fun ListContent( onClick = { disconnectTorDialog = false checked = false - enableTor(account, false, proxyPort) + enableTor(account, false, proxyPort, context) } ) { Text(text = stringResource(R.string.yes)) @@ -386,13 +390,14 @@ fun ListContent( private fun enableTor( account: Account, checked: Boolean, - portNumber: MutableState + portNumber: MutableState, + context: Context ) { account.proxyPort = portNumber.value.toInt() account.proxy = HttpClient.initProxy(checked, "127.0.0.1", account.proxyPort) LocalPreferences.saveToEncryptedStorage(account) ServiceManager.pause() - ServiceManager.start() + ServiceManager.start(context) } @Composable diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt index bf25694a2..e906c987f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt @@ -1,5 +1,6 @@ package com.vitorpamplona.amethyst.ui.screen +import android.content.Context import androidx.lifecycle.ViewModel import com.vitorpamplona.amethyst.LocalPreferences import com.vitorpamplona.amethyst.ServiceManager @@ -21,7 +22,7 @@ import nostr.postr.Persona import nostr.postr.bechToBytes import java.util.regex.Pattern -class AccountStateViewModel() : ViewModel() { +class AccountStateViewModel(val context: Context) : ViewModel() { private val _accountContent = MutableStateFlow(AccountState.LoggedOff) val accountContent = _accountContent.asStateFlow() @@ -85,7 +86,7 @@ class AccountStateViewModel() : ViewModel() { } val scope = CoroutineScope(Job() + Dispatchers.IO) scope.launch { - ServiceManager.start(account) + ServiceManager.start(account, context) } GlobalScope.launch(Dispatchers.Main) { account.saveable.observeForever(saveListener)