diff --git a/app/src/main/java/app/revanced/manager/ui/component/sources/SourceItem.kt b/app/src/main/java/app/revanced/manager/ui/component/sources/SourceItem.kt index 624ff4d6..9d4be932 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/sources/SourceItem.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/sources/SourceItem.kt @@ -19,13 +19,14 @@ import app.revanced.manager.domain.sources.RemoteSource import app.revanced.manager.domain.sources.Source import app.revanced.manager.ui.viewmodel.SourcesViewModel import app.revanced.manager.util.uiSafe +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import java.io.InputStream @OptIn(ExperimentalMaterial3Api::class) @Composable -fun SourceItem(source: Source, onDelete: () -> Unit) { - val coroutineScope = rememberCoroutineScope() +fun SourceItem(source: Source, onDelete: () -> Unit, coroutineScope: CoroutineScope) { + val composableScope = rememberCoroutineScope() var sheetActive by rememberSaveable { mutableStateOf(false) } val bundle by source.bundle.collectAsStateWithLifecycle() @@ -53,14 +54,15 @@ fun SourceItem(source: Source, onDelete: () -> Unit) { ) when (source) { - is RemoteSource -> RemoteSourceItem(source) - is LocalSource -> LocalSourceItem(source) + is RemoteSource -> RemoteSourceItem(source, coroutineScope) + is LocalSource -> LocalSourceItem(source, coroutineScope) } Button( onClick = { - coroutineScope.launch { + composableScope.launch { modalSheetState.hide() + sheetActive = false onDelete() } } @@ -101,8 +103,7 @@ fun SourceItem(source: Source, onDelete: () -> Unit) { } @Composable -private fun RemoteSourceItem(source: RemoteSource) { - val coroutineScope = rememberCoroutineScope() +private fun RemoteSourceItem(source: RemoteSource, coroutineScope: CoroutineScope) { val androidContext = LocalContext.current Text(text = "(api url here)") @@ -118,12 +119,16 @@ private fun RemoteSourceItem(source: RemoteSource) { } @Composable -private fun LocalSourceItem(source: LocalSource) { - val coroutineScope = rememberCoroutineScope() +private fun LocalSourceItem(source: LocalSource, coroutineScope: CoroutineScope) { val androidContext = LocalContext.current 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) { resolver.openInputStream(uri)!!.use { callback(it) @@ -138,7 +143,11 @@ private fun LocalSourceItem(source: LocalSource) { } }, 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) } } diff --git a/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt index 1df9ac17..c0667643 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt @@ -40,7 +40,7 @@ fun DashboardScreen( val pages: Array = DashboardPage.values() val pagerState = rememberPagerState() - val coroutineScope = rememberCoroutineScope() + val composableScope = rememberCoroutineScope() Scaffold( topBar = { @@ -74,7 +74,7 @@ fun DashboardScreen( pages.forEachIndexed { index, page -> Tab( selected = pagerState.currentPage == index, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(index) } }, + onClick = { composableScope.launch { pagerState.animateScrollToPage(index) } }, text = { Text(stringResource(page.titleResId)) }, icon = { Icon(page.icon, null) }, selectedContentColor = MaterialTheme.colorScheme.primary, diff --git a/app/src/main/java/app/revanced/manager/ui/screen/PatchesSelectorScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/PatchesSelectorScreen.kt index 4f04057f..44d37c50 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/PatchesSelectorScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/PatchesSelectorScreen.kt @@ -59,7 +59,7 @@ fun PatchesSelectorScreen( vm: PatchesSelectorViewModel ) { val pagerState = rememberPagerState() - val coroutineScope = rememberCoroutineScope() + val composableScope = rememberCoroutineScope() val bundles by vm.bundlesFlow.collectAsStateWithLifecycle(initialValue = emptyArray()) @@ -92,7 +92,7 @@ fun PatchesSelectorScreen( text = { Text(stringResource(R.string.patch)) }, icon = { Icon(Icons.Default.Build, null) }, onClick = { - coroutineScope.launch { + composableScope.launch { onPatchClick(vm.getAndSaveSelection()) } } @@ -112,7 +112,7 @@ fun PatchesSelectorScreen( bundles.forEachIndexed { index, bundle -> Tab( selected = pagerState.currentPage == index, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(index) } }, + onClick = { composableScope.launch { pagerState.animateScrollToPage(index) } }, text = { Text(bundle.name) }, selectedContentColor = MaterialTheme.colorScheme.primary, unselectedContentColor = MaterialTheme.colorScheme.onSurfaceVariant diff --git a/app/src/main/java/app/revanced/manager/ui/screen/SourcesScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/SourcesScreen.kt index f42702a3..bc8f7649 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/SourcesScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/SourcesScreen.kt @@ -7,33 +7,27 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.viewModelScope import app.revanced.manager.R import app.revanced.manager.ui.component.sources.NewSourceDialog import app.revanced.manager.ui.component.sources.SourceItem import app.revanced.manager.ui.viewmodel.SourcesViewModel -import kotlinx.coroutines.launch import org.koin.androidx.compose.getViewModel @Composable fun SourcesScreen(vm: SourcesViewModel = getViewModel()) { var showNewSourceDialog by rememberSaveable { mutableStateOf(false) } - val scope = rememberCoroutineScope() - val sources by vm.sources.collectAsStateWithLifecycle(initialValue = emptyList()) if (showNewSourceDialog) NewSourceDialog( onDismissRequest = { showNewSourceDialog = false }, onLocalSubmit = { name, patches, integrations -> showNewSourceDialog = false - scope.launch { - vm.addLocal(name, patches, integrations) - } + vm.addLocal(name, patches, integrations) }, onRemoteSubmit = { name, url -> showNewSourceDialog = false - scope.launch { - vm.addRemote(name, url) - } + vm.addRemote(name, url) } ) @@ -46,7 +40,8 @@ fun SourcesScreen(vm: SourcesViewModel = getViewModel()) { source = it, onDelete = { vm.delete(it) - } + }, + coroutineScope = vm.viewModelScope ) } diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/PatchesSelectorViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/PatchesSelectorViewModel.kt index 14e68375..27269b2a 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/PatchesSelectorViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/PatchesSelectorViewModel.kt @@ -80,9 +80,11 @@ class PatchesSelectorViewModel( if (patches.contains(name)) patches.remove(name) else patches.add(name) } - suspend fun getAndSaveSelection(): PatchesSelection = withContext(Dispatchers.Default) { + suspend fun getAndSaveSelection(): PatchesSelection = selectedPatches.also { - selectionRepository.updateSelection(appInfo.packageName, it) + withContext(Dispatchers.Default) { + selectionRepository.updateSelection(appInfo.packageName, it) + } }.mapValues { it.value.toMutableList() }.apply { if (allowExperimental) { return@apply @@ -93,7 +95,6 @@ class PatchesSelectorViewModel( this[it.uid]?.removeAll(it.unsupported.map { patch -> patch.name }) } } - } init { viewModelScope.launch(Dispatchers.Default) { diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/SourcesViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/SourcesViewModel.kt index 7a816116..68f34d2a 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/SourcesViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/SourcesViewModel.kt @@ -12,7 +12,10 @@ import app.revanced.manager.util.uiSafe import io.ktor.http.* 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 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 -> val integrationsStream = integrations?.let { contentResolver.openInputStream(it) } 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) }