Moves ExoPlayer to OkHttp in order to enable Tor support.
This commit is contained in:
@@ -140,6 +140,8 @@ dependencies {
|
|||||||
|
|
||||||
// view videos
|
// view videos
|
||||||
implementation 'com.google.android.exoplayer:exoplayer:2.18.7'
|
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.
|
// Load images from the web.
|
||||||
implementation "io.coil-kt:coil-compose:$coil_version"
|
implementation "io.coil-kt:coil-compose:$coil_version"
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
package com.vitorpamplona.amethyst
|
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.Account
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
import com.vitorpamplona.amethyst.service.HttpClient
|
import com.vitorpamplona.amethyst.service.HttpClient
|
||||||
@@ -19,14 +26,30 @@ import com.vitorpamplona.amethyst.service.relays.Client
|
|||||||
object ServiceManager {
|
object ServiceManager {
|
||||||
private var account: Account? = null
|
private var account: Account? = null
|
||||||
|
|
||||||
fun start(account: Account) {
|
fun start(account: Account, context: Context) {
|
||||||
this.account = account
|
this.account = account
|
||||||
start()
|
start(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun start() {
|
fun start(context: Context) {
|
||||||
val myAccount = account
|
val myAccount = account
|
||||||
|
|
||||||
|
// Resets Proxy Use
|
||||||
HttpClient.start(account)
|
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) {
|
if (myAccount != null) {
|
||||||
Client.connect(myAccount.activeRelays() ?: myAccount.convertLocalRelays())
|
Client.connect(myAccount.activeRelays() ?: myAccount.convertLocalRelays())
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ package com.vitorpamplona.amethyst
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider
|
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.CacheDataSource
|
||||||
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor
|
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor
|
||||||
import com.google.android.exoplayer2.upstream.cache.SimpleCache
|
import com.google.android.exoplayer2.upstream.cache.SimpleCache
|
||||||
|
import com.vitorpamplona.amethyst.service.HttpClient
|
||||||
|
|
||||||
object VideoCache {
|
object VideoCache {
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ object VideoCache {
|
|||||||
cacheDataSourceFactory = CacheDataSource.Factory()
|
cacheDataSourceFactory = CacheDataSource.Factory()
|
||||||
.setCache(simpleCache)
|
.setCache(simpleCache)
|
||||||
.setUpstreamDataSourceFactory(
|
.setUpstreamDataSourceFactory(
|
||||||
DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true)
|
OkHttpDataSource.Factory(HttpClient.getHttpClient())
|
||||||
)
|
)
|
||||||
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
|
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.vitorpamplona.amethyst.ui
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build.VERSION.SDK_INT
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
@@ -12,15 +11,9 @@ import androidx.compose.material.Surface
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
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.LocalPreferences
|
||||||
import com.vitorpamplona.amethyst.ServiceManager
|
import com.vitorpamplona.amethyst.ServiceManager
|
||||||
import com.vitorpamplona.amethyst.VideoCache
|
import com.vitorpamplona.amethyst.VideoCache
|
||||||
import com.vitorpamplona.amethyst.service.HttpClient
|
|
||||||
import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent
|
import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent
|
import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent
|
||||||
@@ -52,20 +45,6 @@ class MainActivity : FragmentActivity() {
|
|||||||
// Initializes video cache.
|
// Initializes video cache.
|
||||||
VideoCache.init(this.applicationContext)
|
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()
|
LocalPreferences.migrateSingleUserPrefs()
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
@@ -73,7 +52,7 @@ class MainActivity : FragmentActivity() {
|
|||||||
// A surface container using the 'background' color from the theme
|
// A surface container using the 'background' color from the theme
|
||||||
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
||||||
val accountStateViewModel: AccountStateViewModel = viewModel {
|
val accountStateViewModel: AccountStateViewModel = viewModel {
|
||||||
AccountStateViewModel()
|
AccountStateViewModel(this@MainActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountScreen(accountStateViewModel, startingPage)
|
AccountScreen(accountStateViewModel, startingPage)
|
||||||
@@ -92,7 +71,7 @@ class MainActivity : FragmentActivity() {
|
|||||||
|
|
||||||
// Only starts after login
|
// Only starts after login
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
ServiceManager.start()
|
ServiceManager.start(this@MainActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
PushNotificationUtils().init(LocalPreferences.allSavedAccounts())
|
PushNotificationUtils().init(LocalPreferences.allSavedAccounts())
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.navigation
|
package com.vitorpamplona.amethyst.ui.navigation
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
@@ -43,6 +44,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
@@ -335,6 +337,8 @@ fun ListContent(
|
|||||||
AccountBackupDialog(account, onClose = { backupDialogOpen = false })
|
AccountBackupDialog(account, onClose = { backupDialogOpen = false })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
if (conectOrbotDialogOpen) {
|
if (conectOrbotDialogOpen) {
|
||||||
ConnectOrbotDialog(
|
ConnectOrbotDialog(
|
||||||
onClose = { conectOrbotDialogOpen = false },
|
onClose = { conectOrbotDialogOpen = false },
|
||||||
@@ -342,7 +346,7 @@ fun ListContent(
|
|||||||
conectOrbotDialogOpen = false
|
conectOrbotDialogOpen = false
|
||||||
disconnectTorDialog = false
|
disconnectTorDialog = false
|
||||||
checked = true
|
checked = true
|
||||||
enableTor(account, true, proxyPort)
|
enableTor(account, true, proxyPort, context = context)
|
||||||
},
|
},
|
||||||
proxyPort
|
proxyPort
|
||||||
)
|
)
|
||||||
@@ -364,7 +368,7 @@ fun ListContent(
|
|||||||
onClick = {
|
onClick = {
|
||||||
disconnectTorDialog = false
|
disconnectTorDialog = false
|
||||||
checked = false
|
checked = false
|
||||||
enableTor(account, false, proxyPort)
|
enableTor(account, false, proxyPort, context)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(R.string.yes))
|
Text(text = stringResource(R.string.yes))
|
||||||
@@ -386,13 +390,14 @@ fun ListContent(
|
|||||||
private fun enableTor(
|
private fun enableTor(
|
||||||
account: Account,
|
account: Account,
|
||||||
checked: Boolean,
|
checked: Boolean,
|
||||||
portNumber: MutableState<String>
|
portNumber: MutableState<String>,
|
||||||
|
context: Context
|
||||||
) {
|
) {
|
||||||
account.proxyPort = portNumber.value.toInt()
|
account.proxyPort = portNumber.value.toInt()
|
||||||
account.proxy = HttpClient.initProxy(checked, "127.0.0.1", account.proxyPort)
|
account.proxy = HttpClient.initProxy(checked, "127.0.0.1", account.proxyPort)
|
||||||
LocalPreferences.saveToEncryptedStorage(account)
|
LocalPreferences.saveToEncryptedStorage(account)
|
||||||
ServiceManager.pause()
|
ServiceManager.pause()
|
||||||
ServiceManager.start()
|
ServiceManager.start(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.screen
|
package com.vitorpamplona.amethyst.ui.screen
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.vitorpamplona.amethyst.LocalPreferences
|
import com.vitorpamplona.amethyst.LocalPreferences
|
||||||
import com.vitorpamplona.amethyst.ServiceManager
|
import com.vitorpamplona.amethyst.ServiceManager
|
||||||
@@ -21,7 +22,7 @@ import nostr.postr.Persona
|
|||||||
import nostr.postr.bechToBytes
|
import nostr.postr.bechToBytes
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
class AccountStateViewModel() : ViewModel() {
|
class AccountStateViewModel(val context: Context) : ViewModel() {
|
||||||
private val _accountContent = MutableStateFlow<AccountState>(AccountState.LoggedOff)
|
private val _accountContent = MutableStateFlow<AccountState>(AccountState.LoggedOff)
|
||||||
val accountContent = _accountContent.asStateFlow()
|
val accountContent = _accountContent.asStateFlow()
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ class AccountStateViewModel() : ViewModel() {
|
|||||||
}
|
}
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.IO)
|
val scope = CoroutineScope(Job() + Dispatchers.IO)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
ServiceManager.start(account)
|
ServiceManager.start(account, context)
|
||||||
}
|
}
|
||||||
GlobalScope.launch(Dispatchers.Main) {
|
GlobalScope.launch(Dispatchers.Main) {
|
||||||
account.saveable.observeForever(saveListener)
|
account.saveable.observeForever(saveListener)
|
||||||
|
|||||||
Reference in New Issue
Block a user