166 lines
5.1 KiB
Kotlin
166 lines
5.1 KiB
Kotlin
package com.vanced.manager.ui.viewmodel
|
|
|
|
import android.content.pm.PackageInstaller
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.compose.runtime.mutableStateListOf
|
|
import androidx.compose.runtime.mutableStateOf
|
|
import androidx.compose.runtime.setValue
|
|
import androidx.lifecycle.ViewModel
|
|
import androidx.lifecycle.viewModelScope
|
|
import com.vanced.manager.downloader.base.AppDownloader
|
|
import com.vanced.manager.downloader.impl.MicrogDownloader
|
|
import com.vanced.manager.downloader.impl.MusicDownloader
|
|
import com.vanced.manager.downloader.impl.VancedDownloader
|
|
import com.vanced.manager.installer.impl.MicrogInstaller
|
|
import com.vanced.manager.installer.impl.MusicInstaller
|
|
import com.vanced.manager.installer.impl.VancedInstaller
|
|
import com.vanced.manager.installer.util.PMRootResult
|
|
import com.vanced.manager.network.util.MICROG_NAME
|
|
import com.vanced.manager.network.util.MUSIC_NAME
|
|
import com.vanced.manager.network.util.VANCED_NAME
|
|
import com.vanced.manager.preferences.holder.managerVariantPref
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.launch
|
|
|
|
class InstallViewModel(
|
|
private val vancedDownloader: VancedDownloader,
|
|
private val musicDownloader: MusicDownloader,
|
|
private val microgDownloader: MicrogDownloader,
|
|
|
|
private val vancedInstaller: VancedInstaller,
|
|
private val musicInstaller: MusicInstaller,
|
|
private val microgInstaller: MicrogInstaller,
|
|
) : ViewModel() {
|
|
|
|
private val isRoot
|
|
get() = managerVariantPref == "root"
|
|
|
|
sealed class Log {
|
|
data class Info(val infoText: String) : Log()
|
|
data class Success(val successText: String) : Log()
|
|
data class Error(
|
|
val displayText: String,
|
|
val stacktrace: String,
|
|
) : Log()
|
|
}
|
|
|
|
sealed class Status {
|
|
object Idle : Status()
|
|
object Installing : Status()
|
|
object Installed : Status()
|
|
object Failure : Status()
|
|
data class Progress(val progress: Float) : Status()
|
|
}
|
|
|
|
val logs = mutableStateListOf<Log>()
|
|
|
|
var status by mutableStateOf<Status>(Status.Idle)
|
|
private set
|
|
|
|
//TODO Move to WorkManager
|
|
fun startAppProcess(
|
|
appName: String,
|
|
appVersions: List<String>?
|
|
) {
|
|
viewModelScope.launch(Dispatchers.IO) {
|
|
downloadApp(appName, appVersions)
|
|
}
|
|
}
|
|
|
|
fun postInstallStatus(pmStatus: Int, extra: String) {
|
|
if (pmStatus == PackageInstaller.STATUS_SUCCESS) {
|
|
status = Status.Installed
|
|
log(Log.Success("Successfully installed"))
|
|
} else {
|
|
status = Status.Failure
|
|
log(Log.Error("Failed to install app", extra))
|
|
}
|
|
}
|
|
|
|
fun clear() {
|
|
logs.clear()
|
|
status = Status.Idle
|
|
}
|
|
|
|
private suspend fun downloadApp(
|
|
appName: String,
|
|
appVersions: List<String>?,
|
|
) {
|
|
val downloader = getDownloader(appName)
|
|
|
|
val onProgress: (Float) -> Unit = { progress ->
|
|
status = Status.Progress(progress / 100)
|
|
}
|
|
val onFile: (String) -> Unit = { file ->
|
|
log(Log.Info("Downloading $file"))
|
|
}
|
|
|
|
val download =
|
|
if (isRoot)
|
|
downloader.downloadRoot(appVersions, onProgress, onFile)
|
|
else
|
|
downloader.download(appVersions, onProgress, onFile)
|
|
|
|
when (download) {
|
|
is AppDownloader.DownloadStatus.Success -> {
|
|
log(Log.Success("Successfully downloaded $appName"))
|
|
installApp(appName, appVersions)
|
|
}
|
|
is AppDownloader.DownloadStatus.Error -> {
|
|
log(
|
|
Log.Error(
|
|
displayText = "Failed to download ${download.fileName}",
|
|
stacktrace = download.error
|
|
)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun installApp(
|
|
appName: String,
|
|
appVersions: List<String>?,
|
|
) {
|
|
val installer = getInstaller(appName)
|
|
|
|
status = Status.Installing
|
|
|
|
if (isRoot) {
|
|
when (val installStatus = installer.installRoot(appVersions)) {
|
|
is PMRootResult.Success -> {
|
|
status = Status.Installed
|
|
log(Log.Success("Successfully installed"))
|
|
}
|
|
is PMRootResult.Error -> {
|
|
status = Status.Failure
|
|
log(Log.Error("Failed to install app", installStatus.message))
|
|
}
|
|
}
|
|
} else {
|
|
installer.install(appVersions)
|
|
}
|
|
}
|
|
|
|
private fun getDownloader(
|
|
appName: String
|
|
) = when (appName) {
|
|
VANCED_NAME -> vancedDownloader
|
|
MUSIC_NAME -> musicDownloader
|
|
MICROG_NAME -> microgDownloader
|
|
else -> throw IllegalArgumentException("$appName is not a valid app")
|
|
}
|
|
|
|
private fun getInstaller(
|
|
appName: String
|
|
) = when (appName) {
|
|
VANCED_NAME -> vancedInstaller
|
|
MUSIC_NAME -> musicInstaller
|
|
MICROG_NAME -> microgInstaller
|
|
else -> throw IllegalArgumentException("$appName is not a valid app")
|
|
}
|
|
|
|
private fun log(data: Log) {
|
|
logs.add(data)
|
|
}
|
|
|
|
} |