From 1ce56af3b160439ebc19aa6e6e662d2dfc02cbd3 Mon Sep 17 00:00:00 2001 From: Ax333l Date: Tue, 2 Jul 2024 21:50:28 +0200 Subject: [PATCH] feat: get bundle information from jar manifest (#2027) --- .../data/room/bundles/PatchBundleDao.kt | 5 +- .../domain/bundles/LocalPatchBundle.kt | 13 +++- .../domain/bundles/PatchBundleSource.kt | 62 ++++++++++++++++--- .../domain/bundles/RemotePatchBundle.kt | 12 +--- .../PatchBundlePersistenceRepository.kt | 7 ++- .../repository/PatchBundleRepository.kt | 14 ++--- .../manager/patcher/patch/PatchBundle.kt | 13 ++++ .../ui/component/bundle/BaseBundleDialog.kt | 50 ++++++++------- .../bundle/BundleInformationDialog.kt | 15 +++-- .../manager/ui/component/bundle/BundleItem.kt | 11 ++-- .../ui/component/bundle/BundleSelector.kt | 5 +- .../ui/component/bundle/ImportBundleDialog.kt | 20 +++--- .../revanced/manager/ui/model/BundleInfo.kt | 2 +- .../manager/ui/screen/DashboardScreen.kt | 10 +-- .../ui/viewmodel/DashboardViewModel.kt | 19 +++--- .../manager/ui/viewmodel/MainViewModel.kt | 2 +- app/src/main/res/values/strings.xml | 2 + 17 files changed, 162 insertions(+), 100 deletions(-) diff --git a/app/src/main/java/app/revanced/manager/data/room/bundles/PatchBundleDao.kt b/app/src/main/java/app/revanced/manager/data/room/bundles/PatchBundleDao.kt index 28f54e5c..77de9b03 100644 --- a/app/src/main/java/app/revanced/manager/data/room/bundles/PatchBundleDao.kt +++ b/app/src/main/java/app/revanced/manager/data/room/bundles/PatchBundleDao.kt @@ -9,7 +9,7 @@ interface PatchBundleDao { suspend fun all(): List @Query("SELECT version, integrations_version, auto_update FROM patch_bundles WHERE uid = :uid") - fun getPropsById(uid: Int): Flow + fun getPropsById(uid: Int): Flow @Query("UPDATE patch_bundles SET version = :patches, integrations_version = :integrations WHERE uid = :uid") suspend fun updateVersion(uid: Int, patches: String?, integrations: String?) @@ -17,6 +17,9 @@ interface PatchBundleDao { @Query("UPDATE patch_bundles SET auto_update = :value WHERE uid = :uid") suspend fun setAutoUpdate(uid: Int, value: Boolean) + @Query("UPDATE patch_bundles SET name = :value WHERE uid = :uid") + suspend fun setName(uid: Int, value: String) + @Query("DELETE FROM patch_bundles WHERE uid != 0") suspend fun purgeCustomBundles() diff --git a/app/src/main/java/app/revanced/manager/domain/bundles/LocalPatchBundle.kt b/app/src/main/java/app/revanced/manager/domain/bundles/LocalPatchBundle.kt index 9b6d1d60..1d8b41f3 100644 --- a/app/src/main/java/app/revanced/manager/domain/bundles/LocalPatchBundle.kt +++ b/app/src/main/java/app/revanced/manager/domain/bundles/LocalPatchBundle.kt @@ -7,7 +7,8 @@ import java.io.InputStream import java.nio.file.Files import java.nio.file.StandardCopyOption -class LocalPatchBundle(name: String, id: Int, directory: File) : PatchBundleSource(name, id, directory) { +class LocalPatchBundle(name: String, id: Int, directory: File) : + PatchBundleSource(name, id, directory) { suspend fun replace(patches: InputStream? = null, integrations: InputStream? = null) { withContext(Dispatchers.IO) { patches?.let { inputStream -> @@ -16,10 +17,16 @@ class LocalPatchBundle(name: String, id: Int, directory: File) : PatchBundleSour } } integrations?.let { - Files.copy(it, this@LocalPatchBundle.integrationsFile.toPath(), StandardCopyOption.REPLACE_EXISTING) + Files.copy( + it, + this@LocalPatchBundle.integrationsFile.toPath(), + StandardCopyOption.REPLACE_EXISTING + ) } } - reload() + reload()?.also { + saveVersion(it.readManifestAttribute("Version"), null) + } } } diff --git a/app/src/main/java/app/revanced/manager/domain/bundles/PatchBundleSource.kt b/app/src/main/java/app/revanced/manager/domain/bundles/PatchBundleSource.kt index ebff077c..712d6534 100644 --- a/app/src/main/java/app/revanced/manager/domain/bundles/PatchBundleSource.kt +++ b/app/src/main/java/app/revanced/manager/domain/bundles/PatchBundleSource.kt @@ -1,12 +1,20 @@ package app.revanced.manager.domain.bundles +import android.app.Application import android.util.Log +import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import app.revanced.manager.R +import app.revanced.manager.domain.repository.PatchBundlePersistenceRepository import app.revanced.manager.patcher.patch.PatchBundle import app.revanced.manager.util.tag import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject import java.io.File import java.io.OutputStream @@ -14,13 +22,21 @@ import java.io.OutputStream * A [PatchBundle] source. */ @Stable -sealed class PatchBundleSource(val name: String, val uid: Int, directory: File) { +sealed class PatchBundleSource(initialName: String, val uid: Int, directory: File) : KoinComponent { + protected val configRepository: PatchBundlePersistenceRepository by inject() + private val app: Application by inject() protected val patchesFile = directory.resolve("patches.jar") protected val integrationsFile = directory.resolve("integrations.apk") private val _state = MutableStateFlow(load()) val state = _state.asStateFlow() + private val _nameFlow = MutableStateFlow(initialName) + val nameFlow = + _nameFlow.map { it.ifEmpty { app.getString(if (isDefault) R.string.bundle_name_default else R.string.bundle_name_fallback) } } + + suspend fun getName() = nameFlow.first() + /** * Returns true if the bundle has been downloaded to local storage. */ @@ -42,13 +58,38 @@ sealed class PatchBundleSource(val name: String, val uid: Int, directory: File) return try { State.Loaded(PatchBundle(patchesFile, integrationsFile.takeIf(File::exists))) } catch (t: Throwable) { - Log.e(tag, "Failed to load patch bundle $name", t) + Log.e(tag, "Failed to load patch bundle with UID $uid", t) State.Failed(t) } } - fun reload() { - _state.value = load() + suspend fun reload(): PatchBundle? { + val newState = load() + _state.value = newState + + val bundle = newState.patchBundleOrNull() + // Try to read the name from the patch bundle manifest if the bundle does not have a name. + if (bundle != null && _nameFlow.value.isEmpty()) { + bundle.readManifestAttribute("Name")?.let { setName(it) } + } + + return bundle + } + + /** + * Create a flow that emits the [app.revanced.manager.data.room.bundles.BundleProperties] of this [PatchBundleSource]. + * The flow will emit null if the associated [PatchBundleSource] is deleted. + */ + fun propsFlow() = configRepository.getProps(uid) + suspend fun getProps() = configRepository.getProps(uid).first()!! + + suspend fun currentVersion() = getProps().versionInfo + protected suspend fun saveVersion(patches: String?, integrations: String?) = + configRepository.updateVersion(uid, patches, integrations) + + suspend fun setName(name: String) { + configRepository.setName(uid, name) + _nameFlow.value = name } sealed interface State { @@ -61,9 +102,12 @@ sealed class PatchBundleSource(val name: String, val uid: Int, directory: File) } } - companion object { - val PatchBundleSource.isDefault get() = uid == 0 - val PatchBundleSource.asRemoteOrNull get() = this as? RemotePatchBundle - fun PatchBundleSource.propsOrNullFlow() = asRemoteOrNull?.propsFlow() ?: flowOf(null) + companion object Extensions { + val PatchBundleSource.isDefault inline get() = uid == 0 + val PatchBundleSource.asRemoteOrNull inline get() = this as? RemotePatchBundle + val PatchBundleSource.nameState + @Composable inline get() = nameFlow.collectAsStateWithLifecycle( + "" + ) } } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/domain/bundles/RemotePatchBundle.kt b/app/src/main/java/app/revanced/manager/domain/bundles/RemotePatchBundle.kt index 1c857051..8bbc230d 100644 --- a/app/src/main/java/app/revanced/manager/domain/bundles/RemotePatchBundle.kt +++ b/app/src/main/java/app/revanced/manager/domain/bundles/RemotePatchBundle.kt @@ -2,7 +2,6 @@ package app.revanced.manager.domain.bundles import androidx.compose.runtime.Stable import app.revanced.manager.data.room.bundles.VersionInfo -import app.revanced.manager.domain.repository.PatchBundlePersistenceRepository import app.revanced.manager.network.api.ReVancedAPI import app.revanced.manager.network.api.ReVancedAPI.Extensions.findAssetByType import app.revanced.manager.network.dto.BundleAsset @@ -15,17 +14,14 @@ import io.ktor.client.request.url import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.koin.core.component.KoinComponent import org.koin.core.component.inject import java.io.File @Stable sealed class RemotePatchBundle(name: String, id: Int, directory: File, val endpoint: String) : - PatchBundleSource(name, id, directory), KoinComponent { - private val configRepository: PatchBundlePersistenceRepository by inject() + PatchBundleSource(name, id, directory) { protected val http: HttpService by inject() protected abstract suspend fun getLatestInfo(): BundleInfo @@ -70,17 +66,11 @@ sealed class RemotePatchBundle(name: String, id: Int, directory: File, val endpo true } - private suspend fun currentVersion() = configRepository.getProps(uid).first().versionInfo - private suspend fun saveVersion(patches: String, integrations: String) = - configRepository.updateVersion(uid, patches, integrations) - suspend fun deleteLocalFiles() = withContext(Dispatchers.Default) { arrayOf(patchesFile, integrationsFile).forEach(File::delete) reload() } - fun propsFlow() = configRepository.getProps(uid) - suspend fun setAutoUpdate(value: Boolean) = configRepository.setAutoUpdate(uid, value) companion object { diff --git a/app/src/main/java/app/revanced/manager/domain/repository/PatchBundlePersistenceRepository.kt b/app/src/main/java/app/revanced/manager/domain/repository/PatchBundlePersistenceRepository.kt index 2784841c..4b853ecf 100644 --- a/app/src/main/java/app/revanced/manager/domain/repository/PatchBundlePersistenceRepository.kt +++ b/app/src/main/java/app/revanced/manager/domain/repository/PatchBundlePersistenceRepository.kt @@ -22,7 +22,6 @@ class PatchBundlePersistenceRepository(db: AppDatabase) { suspend fun reset() = dao.reset() - suspend fun create(name: String, source: Source, autoUpdate: Boolean = false) = PatchBundleEntity( uid = generateUid(), @@ -36,17 +35,19 @@ class PatchBundlePersistenceRepository(db: AppDatabase) { suspend fun delete(uid: Int) = dao.remove(uid) - suspend fun updateVersion(uid: Int, patches: String, integrations: String) = + suspend fun updateVersion(uid: Int, patches: String?, integrations: String?) = dao.updateVersion(uid, patches, integrations) suspend fun setAutoUpdate(uid: Int, value: Boolean) = dao.setAutoUpdate(uid, value) + suspend fun setName(uid: Int, name: String) = dao.setName(uid, name) + fun getProps(id: Int) = dao.getPropsById(id).distinctUntilChanged() private companion object { val defaultSource = PatchBundleEntity( uid = 0, - name = "Default", + name = "", versionInfo = VersionInfo(), source = Source.API, autoUpdate = false diff --git a/app/src/main/java/app/revanced/manager/domain/repository/PatchBundleRepository.kt b/app/src/main/java/app/revanced/manager/domain/repository/PatchBundleRepository.kt index 73debb82..4f3ec2f5 100644 --- a/app/src/main/java/app/revanced/manager/domain/repository/PatchBundleRepository.kt +++ b/app/src/main/java/app/revanced/manager/domain/repository/PatchBundleRepository.kt @@ -137,16 +137,16 @@ class PatchBundleRepository( private fun addBundle(patchBundle: PatchBundleSource) = _sources.update { it.toMutableMap().apply { put(patchBundle.uid, patchBundle) } } - suspend fun createLocal(name: String, patches: InputStream, integrations: InputStream?) { - val id = persistenceRepo.create(name, SourceInfo.Local).uid - val bundle = LocalPatchBundle(name, id, directoryOf(id)) + suspend fun createLocal(patches: InputStream, integrations: InputStream?) { + val uid = persistenceRepo.create("", SourceInfo.Local).uid + val bundle = LocalPatchBundle("", uid, directoryOf(uid)) bundle.replace(patches, integrations) addBundle(bundle) } - suspend fun createRemote(name: String, url: String, autoUpdate: Boolean) { - val entity = persistenceRepo.create(name, SourceInfo.from(url), autoUpdate) + suspend fun createRemote(url: String, autoUpdate: Boolean) { + val entity = persistenceRepo.create("", SourceInfo.from(url), autoUpdate) addBundle(entity.load()) } @@ -174,8 +174,8 @@ class PatchBundleRepository( getBundlesByType().forEach { launch { - if (!it.propsFlow().first().autoUpdate) return@launch - Log.d(tag, "Updating patch bundle: ${it.name}") + if (!it.getProps().autoUpdate) return@launch + Log.d(tag, "Updating patch bundle: ${it.getName()}") it.update() } } diff --git a/app/src/main/java/app/revanced/manager/patcher/patch/PatchBundle.kt b/app/src/main/java/app/revanced/manager/patcher/patch/PatchBundle.kt index a463998f..8dbcf153 100644 --- a/app/src/main/java/app/revanced/manager/patcher/patch/PatchBundle.kt +++ b/app/src/main/java/app/revanced/manager/patcher/patch/PatchBundle.kt @@ -5,6 +5,8 @@ import app.revanced.manager.util.tag import app.revanced.patcher.PatchBundleLoader import app.revanced.patcher.patch.Patch import java.io.File +import java.io.IOException +import java.util.jar.JarFile class PatchBundle(val patchesJar: File, val integrations: File?) { private val loader = object : Iterable> { @@ -25,6 +27,17 @@ class PatchBundle(val patchesJar: File, val integrations: File?) { */ val patches = loader.map(::PatchInfo) + /** + * The [java.util.jar.Manifest] of [patchesJar]. + */ + private val manifest = try { + JarFile(patchesJar).use { it.manifest } + } catch (_: IOException) { + null + } + + fun readManifestAttribute(name: String) = manifest?.mainAttributes?.getValue(name) + /** * Load all patches compatible with the specified package. */ diff --git a/app/src/main/java/app/revanced/manager/ui/component/bundle/BaseBundleDialog.kt b/app/src/main/java/app/revanced/manager/ui/component/bundle/BaseBundleDialog.kt index 32f625e2..c2e1feca 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/bundle/BaseBundleDialog.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/bundle/BaseBundleDialog.kt @@ -30,7 +30,7 @@ import app.revanced.manager.util.isDebuggable fun BaseBundleDialog( modifier: Modifier = Modifier, isDefault: Boolean, - name: String, + name: String?, onNameChange: ((String) -> Unit)? = null, remoteUrl: String?, onRemoteUrlChange: ((String) -> Unit)? = null, @@ -52,32 +52,34 @@ fun BaseBundleDialog( ) .then(modifier) ) { - var showNameInputDialog by rememberSaveable { - mutableStateOf(false) - } - if (showNameInputDialog) { - TextInputDialog( - initial = name, - title = stringResource(R.string.bundle_input_name), - onDismissRequest = { - showNameInputDialog = false - }, - onConfirm = { - showNameInputDialog = false - onNameChange?.invoke(it) - }, - validator = { - it.length in 1..19 + if (name != null) { + var showNameInputDialog by rememberSaveable { + mutableStateOf(false) + } + if (showNameInputDialog) { + TextInputDialog( + initial = name, + title = stringResource(R.string.bundle_input_name), + onDismissRequest = { + showNameInputDialog = false + }, + onConfirm = { + showNameInputDialog = false + onNameChange?.invoke(it) + }, + validator = { + it.length in 1..19 + } + ) + } + BundleListItem( + headlineText = stringResource(R.string.bundle_input_name), + supportingText = name.ifEmpty { stringResource(R.string.field_not_set) }, + modifier = Modifier.clickable(enabled = onNameChange != null) { + showNameInputDialog = true } ) } - BundleListItem( - headlineText = stringResource(R.string.bundle_input_name), - supportingText = name.ifEmpty { stringResource(R.string.field_not_set) }, - modifier = Modifier.clickable(enabled = onNameChange != null) { - showNameInputDialog = true - } - ) remoteUrl?.takeUnless { isDefault }?.let { url -> var showUrlInputDialog by rememberSaveable { diff --git a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleInformationDialog.kt b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleInformationDialog.kt index 7634fb64..1c67f360 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleInformationDialog.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleInformationDialog.kt @@ -23,9 +23,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import app.revanced.manager.R import app.revanced.manager.domain.bundles.LocalPatchBundle import app.revanced.manager.domain.bundles.PatchBundleSource -import app.revanced.manager.domain.bundles.PatchBundleSource.Companion.asRemoteOrNull -import app.revanced.manager.domain.bundles.PatchBundleSource.Companion.isDefault -import app.revanced.manager.domain.bundles.PatchBundleSource.Companion.propsOrNullFlow +import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.asRemoteOrNull +import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.isDefault +import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.nameState import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @@ -44,7 +44,7 @@ fun BundleInformationDialog( bundle.state.map { it.patchBundleOrNull()?.patches?.size ?: 0 } }.collectAsStateWithLifecycle(0) val props by remember(bundle) { - bundle.propsOrNullFlow() + bundle.propsFlow() }.collectAsStateWithLifecycle(null) if (viewCurrentBundlePatches) { @@ -63,10 +63,12 @@ fun BundleInformationDialog( dismissOnBackPress = true ) ) { + val bundleName by bundle.nameState + Scaffold( topBar = { BundleTopBar( - title = bundle.name, + title = bundleName, onBackClick = onDismissRequest, onBackIcon = { Icon( @@ -98,7 +100,8 @@ fun BundleInformationDialog( BaseBundleDialog( modifier = Modifier.padding(paddingValues), isDefault = bundle.isDefault, - name = bundle.name, + name = bundleName, + onNameChange = { composableScope.launch { bundle.setName(it) } }, remoteUrl = bundle.asRemoteOrNull?.endpoint, patchCount = patchCount, version = props?.versionInfo?.patches, diff --git a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleItem.kt b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleItem.kt index 6cb13891..31f4fef6 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleItem.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleItem.kt @@ -27,7 +27,7 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import app.revanced.manager.R import app.revanced.manager.domain.bundles.PatchBundleSource -import app.revanced.manager.domain.bundles.PatchBundleSource.Companion.propsOrNullFlow +import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.nameState import kotlinx.coroutines.flow.map @OptIn(ExperimentalFoundationApi::class) @@ -45,8 +45,9 @@ fun BundleItem( val state by bundle.state.collectAsStateWithLifecycle() val version by remember(bundle) { - bundle.propsOrNullFlow().map { props -> props?.versionInfo?.patches } + bundle.propsFlow().map { props -> props?.versionInfo?.patches } }.collectAsStateWithLifecycle(null) + val name by bundle.nameState if (viewBundleDialogPage) { BundleInformationDialog( @@ -77,10 +78,10 @@ fun BundleItem( } } else null, - headlineContent = { Text(text = bundle.name) }, + headlineContent = { Text(name) }, supportingContent = { state.patchBundleOrNull()?.patches?.size?.let { patchCount -> - Text(text = pluralStringResource(R.plurals.patch_count, patchCount, patchCount)) + Text(pluralStringResource(R.plurals.patch_count, patchCount, patchCount)) } }, trailingContent = { @@ -95,7 +96,7 @@ fun BundleItem( icon?.let { (vector, description) -> Icon( - imageVector = vector, + vector, contentDescription = stringResource(description), modifier = Modifier.size(24.dp), tint = MaterialTheme.colorScheme.error diff --git a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleSelector.kt b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleSelector.kt index 55da7e0f..8ea55e22 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleSelector.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleSelector.kt @@ -12,10 +12,12 @@ import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import app.revanced.manager.domain.bundles.PatchBundleSource +import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.nameState @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -51,6 +53,7 @@ fun BundleSelector(bundles: List, onFinish: (PatchBundleSourc ) } bundles.forEach { + val name by it.nameState Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, @@ -62,7 +65,7 @@ fun BundleSelector(bundles: List, onFinish: (PatchBundleSourc } ) { Text( - text = it.name, + name, style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.onSurface ) diff --git a/app/src/main/java/app/revanced/manager/ui/component/bundle/ImportBundleDialog.kt b/app/src/main/java/app/revanced/manager/ui/component/bundle/ImportBundleDialog.kt index 1402cf82..481056df 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/bundle/ImportBundleDialog.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/bundle/ImportBundleDialog.kt @@ -35,11 +35,10 @@ import app.revanced.manager.util.JAR_MIMETYPE @Composable fun ImportBundleDialog( onDismissRequest: () -> Unit, - onRemoteSubmit: (String, String, Boolean) -> Unit, - onLocalSubmit: (String, Uri, Uri?) -> Unit, + onRemoteSubmit: (String, Boolean) -> Unit, + onLocalSubmit: (Uri, Uri?) -> Unit, initialBundleType: BundleType ) { - var name by rememberSaveable { mutableStateOf("") } var remoteUrl by rememberSaveable { mutableStateOf("") } var autoUpdate by rememberSaveable { mutableStateOf(true) } var bundleType by rememberSaveable { mutableStateOf(initialBundleType) } @@ -48,7 +47,7 @@ fun ImportBundleDialog( val inputsAreValid by remember { derivedStateOf { - name.isNotEmpty() && if (bundleType == BundleType.Local) patchBundle != null else remoteUrl.isNotEmpty() + if (bundleType == BundleType.Local) patchBundle != null else remoteUrl.isNotEmpty() } } @@ -56,6 +55,7 @@ fun ImportBundleDialog( rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri -> uri?.let { patchBundle = it } } + fun launchPatchActivity() { patchActivityLauncher.launch(JAR_MIMETYPE) } @@ -64,6 +64,7 @@ fun ImportBundleDialog( rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri -> uri?.let { integrations = it } } + fun launchIntegrationsActivity() { integrationsActivityLauncher.launch(APK_MIMETYPE) } @@ -91,12 +92,8 @@ fun ImportBundleDialog( enabled = inputsAreValid, onClick = { when (bundleType) { - BundleType.Local -> onLocalSubmit( - name, - patchBundle!!, - integrations - ) - BundleType.Remote -> onRemoteSubmit(name, remoteUrl, autoUpdate) + BundleType.Local -> onLocalSubmit(patchBundle!!, integrations) + BundleType.Remote -> onRemoteSubmit(remoteUrl, autoUpdate) } }, modifier = Modifier.padding(end = 16.dp) @@ -110,8 +107,7 @@ fun ImportBundleDialog( BaseBundleDialog( modifier = Modifier.padding(paddingValues), isDefault = false, - name = name, - onNameChange = { name = it }, + name = null, remoteUrl = remoteUrl.takeUnless { bundleType == BundleType.Local }, onRemoteUrlChange = { remoteUrl = it }, patchCount = 0, diff --git a/app/src/main/java/app/revanced/manager/ui/model/BundleInfo.kt b/app/src/main/java/app/revanced/manager/ui/model/BundleInfo.kt index db295724..e8dc938d 100644 --- a/app/src/main/java/app/revanced/manager/ui/model/BundleInfo.kt +++ b/app/src/main/java/app/revanced/manager/ui/model/BundleInfo.kt @@ -75,7 +75,7 @@ data class BundleInfo( targetList.add(it) } - BundleInfo(source.name, source.uid, supported, unsupported, universal) + BundleInfo(source.getName(), source.uid, supported, unsupported, universal) } } } 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 03b0e26c..59ed6f4e 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 @@ -46,7 +46,7 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import app.revanced.manager.R import app.revanced.manager.data.room.apps.installed.InstalledApp -import app.revanced.manager.domain.bundles.PatchBundleSource.Companion.isDefault +import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.isDefault import app.revanced.manager.patcher.aapt.Aapt import app.revanced.manager.ui.component.AppTopBar import app.revanced.manager.ui.component.AutoUpdatesDialog @@ -102,13 +102,13 @@ fun DashboardScreen( ImportBundleDialog( onDismissRequest = ::dismiss, - onLocalSubmit = { name, patches, integrations -> + onLocalSubmit = { patches, integrations -> dismiss() - vm.createLocalSource(name, patches, integrations) + vm.createLocalSource(patches, integrations) }, - onRemoteSubmit = { name, url, autoUpdate -> + onRemoteSubmit = { url, autoUpdate -> dismiss() - vm.createRemoteSource(name, url, autoUpdate) + vm.createRemoteSource(url, autoUpdate) }, initialBundleType = it ) diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/DashboardViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/DashboardViewModel.kt index 22b83770..c2dd6d64 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/DashboardViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/DashboardViewModel.kt @@ -12,7 +12,7 @@ import androidx.lifecycle.viewModelScope import app.revanced.manager.R import app.revanced.manager.data.platform.NetworkInfo import app.revanced.manager.domain.bundles.PatchBundleSource -import app.revanced.manager.domain.bundles.PatchBundleSource.Companion.asRemoteOrNull +import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.asRemoteOrNull import app.revanced.manager.domain.bundles.RemotePatchBundle import app.revanced.manager.domain.manager.PreferencesManager import app.revanced.manager.domain.repository.PatchBundleRepository @@ -80,20 +80,17 @@ class DashboardViewModel( fun cancelSourceSelection() { selectedSources.clear() } - fun createLocalSource(name: String, patchBundle: Uri, integrations: Uri?) = + fun createLocalSource(patchBundle: Uri, integrations: Uri?) = viewModelScope.launch { contentResolver.openInputStream(patchBundle)!!.use { patchesStream -> - val integrationsStream = integrations?.let { contentResolver.openInputStream(it) } - try { - patchBundleRepository.createLocal(name, patchesStream, integrationsStream) - } finally { - integrationsStream?.close() + integrations?.let { contentResolver.openInputStream(it) }.use { integrationsStream -> + patchBundleRepository.createLocal(patchesStream, integrationsStream) } } } - fun createRemoteSource(name: String, apiUrl: String, autoUpdate: Boolean) = - viewModelScope.launch { patchBundleRepository.createRemote(name, apiUrl, autoUpdate) } + fun createRemoteSource(apiUrl: String, autoUpdate: Boolean) = + viewModelScope.launch { patchBundleRepository.createRemote(apiUrl, autoUpdate) } fun delete(bundle: PatchBundleSource) = viewModelScope.launch { patchBundleRepository.remove(bundle) } @@ -107,9 +104,9 @@ class DashboardViewModel( RemotePatchBundle.updateFailMsg ) { if (bundle.update()) - app.toast(app.getString(R.string.bundle_update_success, bundle.name)) + app.toast(app.getString(R.string.bundle_update_success, bundle.getName())) else - app.toast(app.getString(R.string.bundle_update_unavailable, bundle.name)) + app.toast(app.getString(R.string.bundle_update_unavailable, bundle.getName())) } } } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/MainViewModel.kt index b512749a..4f0fbcd9 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/MainViewModel.kt @@ -11,7 +11,7 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import app.revanced.manager.R -import app.revanced.manager.domain.bundles.PatchBundleSource.Companion.asRemoteOrNull +import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.asRemoteOrNull import app.revanced.manager.domain.manager.KeystoreManager import app.revanced.manager.domain.manager.PreferencesManager import app.revanced.manager.domain.repository.PatchBundleRepository diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f77fc91e..6d3dc16f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -25,6 +25,8 @@ Missing Error + Default + Unnamed %1$s • %2$d available patches