diff --git a/app/src/main/java/app/revanced/manager/data/room/Converters.kt b/app/src/main/java/app/revanced/manager/data/room/Converters.kt index f20e2636..f8aa073d 100644 --- a/app/src/main/java/app/revanced/manager/data/room/Converters.kt +++ b/app/src/main/java/app/revanced/manager/data/room/Converters.kt @@ -7,10 +7,7 @@ import java.io.File class Converters { @TypeConverter - fun sourceFromString(value: String) = when(value) { - Source.Local.SENTINEL -> Source.Local - else -> Source.Remote(Url(value)) - } + fun sourceFromString(value: String) = Source.from(value) @TypeConverter fun sourceToString(value: Source) = value.toString() diff --git a/app/src/main/java/app/revanced/manager/data/room/bundles/PatchBundleEntity.kt b/app/src/main/java/app/revanced/manager/data/room/bundles/PatchBundleEntity.kt index 391e4aa3..b801800a 100644 --- a/app/src/main/java/app/revanced/manager/data/room/bundles/PatchBundleEntity.kt +++ b/app/src/main/java/app/revanced/manager/data/room/bundles/PatchBundleEntity.kt @@ -10,9 +10,23 @@ sealed class Source { override fun toString() = SENTINEL } + object API : Source() { + const val SENTINEL = "manager://api" + + override fun toString() = SENTINEL + } + data class Remote(val url: Url) : Source() { override fun toString() = url.toString() } + + companion object { + fun from(value: String) = when(value) { + Local.SENTINEL -> Local + API.SENTINEL -> API + else -> Remote(Url(value)) + } + } } data class VersionInfo( 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 5edfa618..43f86e72 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 @@ -11,10 +11,10 @@ class LocalPatchBundle(name: String, id: Int, directory: File) : PatchBundleSour suspend fun replace(patches: InputStream? = null, integrations: InputStream? = null) { withContext(Dispatchers.IO) { patches?.let { - Files.copy(it, patchesJar.toPath(), StandardCopyOption.REPLACE_EXISTING) + Files.copy(it, patchesFile.toPath(), StandardCopyOption.REPLACE_EXISTING) } integrations?.let { - Files.copy(it, this@LocalPatchBundle.integrations.toPath(), StandardCopyOption.REPLACE_EXISTING) + Files.copy(it, this@LocalPatchBundle.integrationsFile.toPath(), StandardCopyOption.REPLACE_EXISTING) } } 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 6117df71..609bdf40 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 @@ -12,19 +12,19 @@ import java.io.File */ @Stable sealed class PatchBundleSource(val name: String, val uid: Int, directory: File) { - protected val patchesJar = directory.resolve("patches.jar") - protected val integrations = directory.resolve("integrations.apk") + protected val patchesFile = directory.resolve("patches.jar") + protected val integrationsFile = directory.resolve("integrations.apk") /** * Returns true if the bundle has been downloaded to local storage. */ - fun hasInstalled() = patchesJar.exists() + fun hasInstalled() = patchesFile.exists() private fun load(): State { if (!hasInstalled()) return State.Missing return try { - State.Loaded(PatchBundle(patchesJar, integrations.takeIf(File::exists))) + State.Loaded(PatchBundle(patchesFile, integrationsFile.takeIf(File::exists))) } catch (t: Throwable) { State.Failed(t) } @@ -48,6 +48,7 @@ sealed class PatchBundleSource(val name: String, val uid: Int, directory: File) companion object { val PatchBundleSource.isDefault get() = uid == 0 - fun PatchBundleSource.propsOrNullFlow() = (this as? RemotePatchBundle)?.propsFlow() ?: flowOf(null) + val PatchBundleSource.asRemoteOrNull get() = this as? RemotePatchBundle<*> + fun PatchBundleSource.propsOrNullFlow() = asRemoteOrNull?.propsFlow() ?: flowOf(null) } } \ 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 118c66ba..af2fe1f3 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 @@ -1,44 +1,66 @@ 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.Assets import app.revanced.manager.domain.repository.PatchBundlePersistenceRepository -import app.revanced.manager.network.api.ManagerAPI +import app.revanced.manager.domain.repository.ReVancedRepository +import app.revanced.manager.network.dto.BundleInfo +import app.revanced.manager.network.service.HttpService +import app.revanced.manager.network.utils.getOrThrow +import app.revanced.manager.util.ghIntegrations +import app.revanced.manager.util.ghPatches +import io.ktor.client.request.url +import io.ktor.http.Url import kotlinx.coroutines.Dispatchers +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 -class RemotePatchBundle(name: String, id: Int, directory: File, val apiUrl: String) : +sealed class RemotePatchBundle(name: String, id: Int, directory: File, val endpoint: String) : PatchBundleSource(name, id, directory), KoinComponent { private val configRepository: PatchBundlePersistenceRepository by inject() - private val api: ManagerAPI by inject() + protected val http: HttpService by inject() - private suspend fun currentVersion() = configRepository.getProps(uid).first().versionInfo - private suspend fun saveVersion(patches: String, integrations: String) = - configRepository.updateVersion(uid, patches, integrations) + protected abstract suspend fun download(metadata: Meta) + protected abstract suspend fun getLatestMetadata(): Meta + protected abstract fun getVersionInfo(metadata: Meta): VersionInfo - suspend fun downloadLatest() = withContext(Dispatchers.IO) { - api.downloadBundle(apiUrl, patchesJar, integrations).also { (patchesVer, integrationsVer) -> - saveVersion(patchesVer, integrationsVer) - reload() - } + suspend fun downloadLatest() { + download(getLatestMetadata()) + } - return@withContext + protected suspend fun downloadAssets(assets: Map) = coroutineScope { + assets.forEach { (asset, file) -> + launch { + http.download(file) { + url(asset) + } + } + } } suspend fun update(): Boolean = withContext(Dispatchers.IO) { - val current = currentVersion().let { it.patches to it.integrations } - if (!hasInstalled() || current != api.getLatestBundleVersion(apiUrl)) { - downloadLatest() - true - } else false + val metadata = getLatestMetadata() + if (hasInstalled() && getVersionInfo(metadata) == currentVersion()) { + return@withContext false + } + + download(metadata) + true } - suspend fun deleteLocalFiles() = withContext(Dispatchers.IO) { - arrayOf(patchesJar, integrations).forEach(File::delete) + private suspend fun currentVersion() = configRepository.getProps(uid).first().versionInfo + protected 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() } @@ -49,4 +71,60 @@ class RemotePatchBundle(name: String, id: Int, directory: File, val apiUrl: Stri companion object { const val updateFailMsg = "Failed to update patch bundle(s)" } +} + +class JsonPatchBundle(name: String, id: Int, directory: File, endpoint: String) : + RemotePatchBundle(name, id, directory, endpoint) { + override suspend fun getLatestMetadata() = withContext(Dispatchers.IO) { + http.request { + url(endpoint) + }.getOrThrow() + } + + override fun getVersionInfo(metadata: BundleInfo) = + VersionInfo(metadata.patches.version, metadata.integrations.version) + + override suspend fun download(metadata: BundleInfo) = withContext(Dispatchers.IO) { + val (patches, integrations) = metadata + downloadAssets( + mapOf( + patches.url to patchesFile, + integrations.url to integrationsFile + ) + ) + + saveVersion(patches.version, integrations.version) + reload() + } +} + +class APIPatchBundle(name: String, id: Int, directory: File, endpoint: String) : + RemotePatchBundle(name, id, directory, endpoint) { + private val api: ReVancedRepository by inject() + + override suspend fun getLatestMetadata() = api.getAssets() + override fun getVersionInfo(metadata: Assets) = metadata.let { (patches, integrations) -> + VersionInfo( + patches.version, + integrations.version + ) + } + + override suspend fun download(metadata: Assets) = withContext(Dispatchers.IO) { + val (patches, integrations) = metadata + downloadAssets( + mapOf( + patches.downloadUrl to patchesFile, + integrations.downloadUrl to integrationsFile + ) + ) + + saveVersion(patches.version, integrations.version) + reload() + } + + private companion object { + operator fun Assets.component1() = find(ghPatches, ".jar") + operator fun Assets.component2() = find(ghIntegrations, ".apk") + } } \ No newline at end of file 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 e7a21e42..c33e7ba2 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 @@ -16,7 +16,7 @@ class PatchBundlePersistenceRepository(db: AppDatabase) { uid = 0, name = "Main", versionInfo = VersionInfo(), - source = Source.Remote(Url("manager://api")), + source = Source.API, autoUpdate = false ) } @@ -33,25 +33,23 @@ class PatchBundlePersistenceRepository(db: AppDatabase) { suspend fun reset() = dao.reset() - suspend fun create(name: String, source: Source, autoUpdate: Boolean = false): Int { - val uid = generateUid() - dao.add( - PatchBundleEntity( - uid = uid, - name = name, - versionInfo = VersionInfo(), - source = source, - autoUpdate = autoUpdate - ) - ) - return uid - } + suspend fun create(name: String, source: Source, autoUpdate: Boolean = false) = + PatchBundleEntity( + uid = generateUid(), + name = name, + versionInfo = VersionInfo(), + source = source, + autoUpdate = autoUpdate + ).also { + dao.add(it) + } suspend fun delete(uid: Int) = dao.remove(uid) 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) fun getProps(id: Int) = dao.getPropsById(id).distinctUntilChanged() 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 a9419194..d10928ea 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 @@ -5,14 +5,14 @@ import android.content.Context import android.util.Log import app.revanced.manager.data.platform.NetworkInfo import app.revanced.manager.data.room.bundles.PatchBundleEntity +import app.revanced.manager.domain.bundles.APIPatchBundle +import app.revanced.manager.domain.bundles.JsonPatchBundle import app.revanced.manager.data.room.bundles.Source as SourceInfo -import app.revanced.manager.domain.manager.PreferencesManager import app.revanced.manager.domain.bundles.LocalPatchBundle import app.revanced.manager.domain.bundles.RemotePatchBundle import app.revanced.manager.domain.bundles.PatchBundleSource import app.revanced.manager.util.flatMapLatestAndCombine import app.revanced.manager.util.tag -import io.ktor.http.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.first @@ -21,18 +21,17 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.withContext -import java.io.File import java.io.InputStream class PatchBundleRepository( app: Application, private val persistenceRepo: PatchBundlePersistenceRepository, private val networkInfo: NetworkInfo, - private val prefs: PreferencesManager ) { private val bundlesDir = app.getDir("patch_bundles", Context.MODE_PRIVATE) - private val _sources: MutableStateFlow> = MutableStateFlow(emptyMap()) + private val _sources: MutableStateFlow> = + MutableStateFlow(emptyMap()) val sources = _sources.map { it.values.toList() } val bundles = sources.flatMapLatestAndCombine( @@ -51,14 +50,19 @@ class PatchBundleRepository( */ private fun directoryOf(uid: Int) = bundlesDir.resolve(uid.toString()).also { it.mkdirs() } - private suspend fun PatchBundleEntity.load(dir: File) = when (source) { - is SourceInfo.Local -> LocalPatchBundle(name, uid, dir) - is SourceInfo.Remote -> RemotePatchBundle( - name, - uid, - dir, - if (uid != 0) source.url.toString() else prefs.api.get() - ) + private fun PatchBundleEntity.load(): PatchBundleSource { + val dir = directoryOf(uid) + + return when (source) { + is SourceInfo.Local -> LocalPatchBundle(name, uid, dir) + is SourceInfo.API -> APIPatchBundle(name, uid, dir, SourceInfo.API.SENTINEL) + is SourceInfo.Remote -> JsonPatchBundle( + name, + uid, + dir, + source.url.toString() + ) + } } suspend fun load() = withContext(Dispatchers.Default) { @@ -67,10 +71,7 @@ class PatchBundleRepository( } _sources.value = entities.associate { - val dir = directoryOf(it.uid) - val bundle = it.load(dir) - - it.uid to bundle + it.uid to it.load() } } @@ -100,23 +101,26 @@ class PatchBundleRepository( _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) - val source = LocalPatchBundle(name, id, directoryOf(id)) - - addBundle(source) + val id = persistenceRepo.create(name, SourceInfo.Local).uid + val bundle = LocalPatchBundle(name, id, directoryOf(id)) - source.replace(patches, integrations) + bundle.replace(patches, integrations) + addBundle(bundle) } - suspend fun createRemote(name: String, apiUrl: Url, autoUpdate: Boolean) { - val id = persistenceRepo.create(name, SourceInfo.Remote(apiUrl), autoUpdate) - addBundle(RemotePatchBundle(name, id, directoryOf(id), apiUrl.toString())) + suspend fun createRemote(name: String, url: String, autoUpdate: Boolean) { + val entity = persistenceRepo.create(name, SourceInfo.from(url), autoUpdate) + addBundle(entity.load()) } - private suspend fun getRemoteBundles() = sources.first().filterIsInstance() + private suspend fun getRemoteBundles() = + sources.first().filterIsInstance>() + + suspend fun reloadApiBundles() { + sources.first().filterIsInstance().forEach { + it.deleteLocalFiles() + } - suspend fun reloadDefaultBundle() { - _sources.value[0]?.let { it as? RemotePatchBundle }?.deleteLocalFiles() load() } diff --git a/app/src/main/java/app/revanced/manager/domain/repository/ReVancedRepository.kt b/app/src/main/java/app/revanced/manager/domain/repository/ReVancedRepository.kt index c0bb24ee..5d35fddd 100644 --- a/app/src/main/java/app/revanced/manager/domain/repository/ReVancedRepository.kt +++ b/app/src/main/java/app/revanced/manager/domain/repository/ReVancedRepository.kt @@ -11,9 +11,11 @@ class ReVancedRepository( private val service: ReVancedService, private val prefs: PreferencesManager ) { - suspend fun getContributors() = service.getContributors(prefs.api.get()) + private suspend fun apiUrl() = prefs.api.get() - suspend fun getAssets(api: String? = null) = Assets(service.getAssets(api ?: prefs.api.get()).getOrThrow()) + suspend fun getContributors() = service.getContributors(apiUrl()) + + suspend fun getAssets() = Assets(service.getAssets(apiUrl()).getOrThrow()) } class Assets(private val releases: ReVancedReleases): List by releases.tools { diff --git a/app/src/main/java/app/revanced/manager/network/api/ManagerAPI.kt b/app/src/main/java/app/revanced/manager/network/api/ManagerAPI.kt index e92baedd..49c6f360 100644 --- a/app/src/main/java/app/revanced/manager/network/api/ManagerAPI.kt +++ b/app/src/main/java/app/revanced/manager/network/api/ManagerAPI.kt @@ -33,28 +33,11 @@ class ManagerAPI( downloadProgress = null } - suspend fun getLatestBundleVersion(api: String) = revancedRepository.getAssets(api).let { (patches, integrations) -> - patches.version to integrations.version - } - - suspend fun downloadBundle(api: String, patchBundle: File, integrations: File): Pair { - val (patchBundleAsset, integrationsAsset) = revancedRepository.getAssets(api) - - downloadAsset(patchBundleAsset, patchBundle) - downloadAsset(integrationsAsset, integrations) - - return patchBundleAsset.version to integrationsAsset.version - } - suspend fun downloadManager(location: File) { val managerAsset = revancedRepository.getAssets().find(ghManager, ".apk") downloadAsset(managerAsset, location) } - private companion object { - operator fun Assets.component1() = find(ghPatches, ".jar") - operator fun Assets.component2() = find(ghIntegrations, ".apk") - } } class MissingAssetException : Exception() \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/network/dto/BundleInfo.kt b/app/src/main/java/app/revanced/manager/network/dto/BundleInfo.kt new file mode 100644 index 00000000..e2b56a87 --- /dev/null +++ b/app/src/main/java/app/revanced/manager/network/dto/BundleInfo.kt @@ -0,0 +1,9 @@ +package app.revanced.manager.network.dto + +import kotlinx.serialization.Serializable + +@Serializable +data class BundleInfo(val patches: BundleAsset, val integrations: BundleAsset) + +@Serializable +data class BundleAsset(val version: String, val url: String) \ No newline at end of file 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 23f70bdf..e2498e39 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 @@ -24,6 +24,7 @@ import app.revanced.manager.R import app.revanced.manager.domain.bundles.LocalPatchBundle import app.revanced.manager.domain.bundles.RemotePatchBundle 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 kotlinx.coroutines.flow.map @@ -99,13 +100,13 @@ fun BundleInformationDialog( modifier = Modifier.padding(paddingValues), isDefault = bundle.isDefault, name = bundle.name, - remoteUrl = (bundle as? RemotePatchBundle)?.apiUrl, + remoteUrl = bundle.asRemoteOrNull?.endpoint, patchCount = patchCount, version = props?.versionInfo?.patches, autoUpdate = props?.autoUpdate ?: false, onAutoUpdateChange = { composableScope.launch { - (bundle as? RemotePatchBundle)?.setAutoUpdate(it) + bundle.asRemoteOrNull?.setAutoUpdate(it) } }, onPatchesClick = { 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 54aa4263..236603d2 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 @@ -32,13 +32,12 @@ import app.revanced.manager.R import app.revanced.manager.util.APK_MIMETYPE import app.revanced.manager.util.JAR_MIMETYPE import app.revanced.manager.util.parseUrlOrNull -import io.ktor.http.Url @OptIn(ExperimentalMaterial3Api::class) @Composable fun ImportBundleDialog( onDismissRequest: () -> Unit, - onRemoteSubmit: (String, Url, Boolean) -> Unit, + onRemoteSubmit: (String, String, Boolean) -> Unit, onLocalSubmit: (String, Uri, Uri?) -> Unit ) { var name by rememberSaveable { mutableStateOf("") } @@ -102,7 +101,7 @@ fun ImportBundleDialog( } else { onRemoteSubmit( name, - remoteUrl.parseUrlOrNull()!!, + remoteUrl, autoUpdate ) } diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/AdvancedSettingsViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/AdvancedSettingsViewModel.kt index 8b7f50fe..6b084005 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/AdvancedSettingsViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/AdvancedSettingsViewModel.kt @@ -22,7 +22,7 @@ class AdvancedSettingsViewModel( if (value == apiUrl.get()) return@launch apiUrl.update(value) - patchBundleRepository.reloadDefaultBundle() + patchBundleRepository.reloadApiBundles() } fun redownloadBundles() = viewModelScope.launch { diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/BundlesViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/BundlesViewModel.kt index 194742cd..5568e349 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/BundlesViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/BundlesViewModel.kt @@ -19,7 +19,7 @@ class BundlesViewModel( fun delete(bundle: PatchBundleSource) = viewModelScope.launch { patchBundleRepository.remove(bundle) } fun update(bundle: PatchBundleSource) = viewModelScope.launch { - if (bundle !is RemotePatchBundle) return@launch + if (bundle !is RemotePatchBundle<*>) return@launch uiSafe( app, 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 3edfb235..362aff44 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 @@ -30,6 +30,6 @@ class DashboardViewModel( } } - fun createRemoteSource(name: String, apiUrl: Url, autoUpdate: Boolean) = + fun createRemoteSource(name: String, apiUrl: String, autoUpdate: Boolean) = viewModelScope.launch { patchBundleRepository.createRemote(name, apiUrl, autoUpdate) } } \ 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 b01bbf44..9900a1b7 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 @@ -2,6 +2,7 @@ package app.revanced.manager.ui.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import app.revanced.manager.domain.bundles.PatchBundleSource.Companion.asRemoteOrNull import app.revanced.manager.domain.bundles.RemotePatchBundle import app.revanced.manager.domain.manager.PreferencesManager import app.revanced.manager.domain.repository.PatchBundleRepository @@ -31,7 +32,7 @@ class MainViewModel( sources .first() .find { it.uid == 0 } - ?.let { it as? RemotePatchBundle } + ?.asRemoteOrNull ?.setAutoUpdate(true) updateCheck()