refactor: use correct coroutine scopes

This commit is contained in:
Ax333l 2023-06-29 10:35:23 +02:00
parent 18cbe51e6b
commit 81f485da6b
6 changed files with 41 additions and 32 deletions

View File

@ -19,13 +19,14 @@ import app.revanced.manager.domain.sources.RemoteSource
import app.revanced.manager.domain.sources.Source import app.revanced.manager.domain.sources.Source
import app.revanced.manager.ui.viewmodel.SourcesViewModel import app.revanced.manager.ui.viewmodel.SourcesViewModel
import app.revanced.manager.util.uiSafe import app.revanced.manager.util.uiSafe
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.InputStream import java.io.InputStream
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun SourceItem(source: Source, onDelete: () -> Unit) { fun SourceItem(source: Source, onDelete: () -> Unit, coroutineScope: CoroutineScope) {
val coroutineScope = rememberCoroutineScope() val composableScope = rememberCoroutineScope()
var sheetActive by rememberSaveable { mutableStateOf(false) } var sheetActive by rememberSaveable { mutableStateOf(false) }
val bundle by source.bundle.collectAsStateWithLifecycle() val bundle by source.bundle.collectAsStateWithLifecycle()
@ -53,14 +54,15 @@ fun SourceItem(source: Source, onDelete: () -> Unit) {
) )
when (source) { when (source) {
is RemoteSource -> RemoteSourceItem(source) is RemoteSource -> RemoteSourceItem(source, coroutineScope)
is LocalSource -> LocalSourceItem(source) is LocalSource -> LocalSourceItem(source, coroutineScope)
} }
Button( Button(
onClick = { onClick = {
coroutineScope.launch { composableScope.launch {
modalSheetState.hide() modalSheetState.hide()
sheetActive = false
onDelete() onDelete()
} }
} }
@ -101,8 +103,7 @@ fun SourceItem(source: Source, onDelete: () -> Unit) {
} }
@Composable @Composable
private fun RemoteSourceItem(source: RemoteSource) { private fun RemoteSourceItem(source: RemoteSource, coroutineScope: CoroutineScope) {
val coroutineScope = rememberCoroutineScope()
val androidContext = LocalContext.current val androidContext = LocalContext.current
Text(text = "(api url here)") Text(text = "(api url here)")
@ -118,12 +119,16 @@ private fun RemoteSourceItem(source: RemoteSource) {
} }
@Composable @Composable
private fun LocalSourceItem(source: LocalSource) { private fun LocalSourceItem(source: LocalSource, coroutineScope: CoroutineScope) {
val coroutineScope = rememberCoroutineScope()
val androidContext = LocalContext.current val androidContext = LocalContext.current
val resolver = remember { androidContext.contentResolver!! } val resolver = remember { androidContext.contentResolver!! }
fun loadAndReplace(uri: Uri, @StringRes toastMsg: Int, errorLogMsg: String, callback: suspend (InputStream) -> Unit) = coroutineScope.launch { fun loadAndReplace(
uri: Uri,
@StringRes toastMsg: Int,
errorLogMsg: String,
callback: suspend (InputStream) -> Unit
) = coroutineScope.launch {
uiSafe(androidContext, toastMsg, errorLogMsg) { uiSafe(androidContext, toastMsg, errorLogMsg) {
resolver.openInputStream(uri)!!.use { resolver.openInputStream(uri)!!.use {
callback(it) callback(it)
@ -138,7 +143,11 @@ private fun LocalSourceItem(source: LocalSource) {
} }
}, },
onIntegrationsSelection = { uri -> onIntegrationsSelection = { uri ->
loadAndReplace(uri, R.string.source_replace_integrations_fail, "Failed to replace integrations") { loadAndReplace(
uri,
R.string.source_replace_integrations_fail,
"Failed to replace integrations"
) {
source.replace(null, it) source.replace(null, it)
} }
} }

View File

@ -40,7 +40,7 @@ fun DashboardScreen(
val pages: Array<DashboardPage> = DashboardPage.values() val pages: Array<DashboardPage> = DashboardPage.values()
val pagerState = rememberPagerState() val pagerState = rememberPagerState()
val coroutineScope = rememberCoroutineScope() val composableScope = rememberCoroutineScope()
Scaffold( Scaffold(
topBar = { topBar = {
@ -74,7 +74,7 @@ fun DashboardScreen(
pages.forEachIndexed { index, page -> pages.forEachIndexed { index, page ->
Tab( Tab(
selected = pagerState.currentPage == index, selected = pagerState.currentPage == index,
onClick = { coroutineScope.launch { pagerState.animateScrollToPage(index) } }, onClick = { composableScope.launch { pagerState.animateScrollToPage(index) } },
text = { Text(stringResource(page.titleResId)) }, text = { Text(stringResource(page.titleResId)) },
icon = { Icon(page.icon, null) }, icon = { Icon(page.icon, null) },
selectedContentColor = MaterialTheme.colorScheme.primary, selectedContentColor = MaterialTheme.colorScheme.primary,

View File

@ -59,7 +59,7 @@ fun PatchesSelectorScreen(
vm: PatchesSelectorViewModel vm: PatchesSelectorViewModel
) { ) {
val pagerState = rememberPagerState() val pagerState = rememberPagerState()
val coroutineScope = rememberCoroutineScope() val composableScope = rememberCoroutineScope()
val bundles by vm.bundlesFlow.collectAsStateWithLifecycle(initialValue = emptyArray()) val bundles by vm.bundlesFlow.collectAsStateWithLifecycle(initialValue = emptyArray())
@ -92,7 +92,7 @@ fun PatchesSelectorScreen(
text = { Text(stringResource(R.string.patch)) }, text = { Text(stringResource(R.string.patch)) },
icon = { Icon(Icons.Default.Build, null) }, icon = { Icon(Icons.Default.Build, null) },
onClick = { onClick = {
coroutineScope.launch { composableScope.launch {
onPatchClick(vm.getAndSaveSelection()) onPatchClick(vm.getAndSaveSelection())
} }
} }
@ -112,7 +112,7 @@ fun PatchesSelectorScreen(
bundles.forEachIndexed { index, bundle -> bundles.forEachIndexed { index, bundle ->
Tab( Tab(
selected = pagerState.currentPage == index, selected = pagerState.currentPage == index,
onClick = { coroutineScope.launch { pagerState.animateScrollToPage(index) } }, onClick = { composableScope.launch { pagerState.animateScrollToPage(index) } },
text = { Text(bundle.name) }, text = { Text(bundle.name) },
selectedContentColor = MaterialTheme.colorScheme.primary, selectedContentColor = MaterialTheme.colorScheme.primary,
unselectedContentColor = MaterialTheme.colorScheme.onSurfaceVariant unselectedContentColor = MaterialTheme.colorScheme.onSurfaceVariant

View File

@ -7,33 +7,27 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewModelScope
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.ui.component.sources.NewSourceDialog import app.revanced.manager.ui.component.sources.NewSourceDialog
import app.revanced.manager.ui.component.sources.SourceItem import app.revanced.manager.ui.component.sources.SourceItem
import app.revanced.manager.ui.viewmodel.SourcesViewModel import app.revanced.manager.ui.viewmodel.SourcesViewModel
import kotlinx.coroutines.launch
import org.koin.androidx.compose.getViewModel import org.koin.androidx.compose.getViewModel
@Composable @Composable
fun SourcesScreen(vm: SourcesViewModel = getViewModel()) { fun SourcesScreen(vm: SourcesViewModel = getViewModel()) {
var showNewSourceDialog by rememberSaveable { mutableStateOf(false) } var showNewSourceDialog by rememberSaveable { mutableStateOf(false) }
val scope = rememberCoroutineScope()
val sources by vm.sources.collectAsStateWithLifecycle(initialValue = emptyList()) val sources by vm.sources.collectAsStateWithLifecycle(initialValue = emptyList())
if (showNewSourceDialog) NewSourceDialog( if (showNewSourceDialog) NewSourceDialog(
onDismissRequest = { showNewSourceDialog = false }, onDismissRequest = { showNewSourceDialog = false },
onLocalSubmit = { name, patches, integrations -> onLocalSubmit = { name, patches, integrations ->
showNewSourceDialog = false showNewSourceDialog = false
scope.launch { vm.addLocal(name, patches, integrations)
vm.addLocal(name, patches, integrations)
}
}, },
onRemoteSubmit = { name, url -> onRemoteSubmit = { name, url ->
showNewSourceDialog = false showNewSourceDialog = false
scope.launch { vm.addRemote(name, url)
vm.addRemote(name, url)
}
} }
) )
@ -46,7 +40,8 @@ fun SourcesScreen(vm: SourcesViewModel = getViewModel()) {
source = it, source = it,
onDelete = { onDelete = {
vm.delete(it) vm.delete(it)
} },
coroutineScope = vm.viewModelScope
) )
} }

View File

@ -80,9 +80,11 @@ class PatchesSelectorViewModel(
if (patches.contains(name)) patches.remove(name) else patches.add(name) if (patches.contains(name)) patches.remove(name) else patches.add(name)
} }
suspend fun getAndSaveSelection(): PatchesSelection = withContext(Dispatchers.Default) { suspend fun getAndSaveSelection(): PatchesSelection =
selectedPatches.also { selectedPatches.also {
selectionRepository.updateSelection(appInfo.packageName, it) withContext(Dispatchers.Default) {
selectionRepository.updateSelection(appInfo.packageName, it)
}
}.mapValues { it.value.toMutableList() }.apply { }.mapValues { it.value.toMutableList() }.apply {
if (allowExperimental) { if (allowExperimental) {
return@apply return@apply
@ -93,7 +95,6 @@ class PatchesSelectorViewModel(
this[it.uid]?.removeAll(it.unsupported.map { patch -> patch.name }) this[it.uid]?.removeAll(it.unsupported.map { patch -> patch.name })
} }
} }
}
init { init {
viewModelScope.launch(Dispatchers.Default) { viewModelScope.launch(Dispatchers.Default) {

View File

@ -12,7 +12,10 @@ import app.revanced.manager.util.uiSafe
import io.ktor.http.* import io.ktor.http.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class SourcesViewModel(private val app: Application, private val sourceRepository: SourceRepository) : ViewModel() { class SourcesViewModel(
private val app: Application,
private val sourceRepository: SourceRepository
) : ViewModel() {
val sources = sourceRepository.sources val sources = sourceRepository.sources
private val contentResolver: ContentResolver = app.contentResolver private val contentResolver: ContentResolver = app.contentResolver
@ -26,7 +29,7 @@ class SourcesViewModel(private val app: Application, private val sourceRepositor
} }
} }
suspend fun addLocal(name: String, patchBundle: Uri, integrations: Uri?) { fun addLocal(name: String, patchBundle: Uri, integrations: Uri?) = viewModelScope.launch {
contentResolver.openInputStream(patchBundle)!!.use { patchesStream -> contentResolver.openInputStream(patchBundle)!!.use { patchesStream ->
val integrationsStream = integrations?.let { contentResolver.openInputStream(it) } val integrationsStream = integrations?.let { contentResolver.openInputStream(it) }
try { try {
@ -37,7 +40,8 @@ class SourcesViewModel(private val app: Application, private val sourceRepositor
} }
} }
suspend fun addRemote(name: String, apiUrl: Url) = sourceRepository.createRemoteSource(name, apiUrl) fun addRemote(name: String, apiUrl: Url) =
viewModelScope.launch { sourceRepository.createRemoteSource(name, apiUrl) }
fun delete(source: Source) = viewModelScope.launch { sourceRepository.remove(source) } fun delete(source: Source) = viewModelScope.launch { sourceRepository.remove(source) }