implement new remote data type

This commit is contained in:
X1nto 2021-11-29 19:43:42 +04:00
parent b6533e3b37
commit ff510d7ce0
29 changed files with 257 additions and 219 deletions

View File

@ -16,7 +16,7 @@
*; *;
} }
-keep class com.vanced.manager.network.model.JsonDto { -keep class com.vanced.manager.network.model.DataDto {
*; *;
} }

View File

@ -8,6 +8,7 @@ import okhttp3.OkHttpClient
import org.koin.dsl.module import org.koin.dsl.module
import retrofit2.Retrofit import retrofit2.Retrofit
//TODO Add mirror support
val apiModule = module { val apiModule = module {
fun provideVancedAPI( fun provideVancedAPI(

View File

@ -3,7 +3,7 @@ package com.vanced.manager.di
import android.content.Context import android.content.Context
import com.vanced.manager.domain.datasource.PackageInformationDataSource import com.vanced.manager.domain.datasource.PackageInformationDataSource
import com.vanced.manager.network.model.AppDtoMapper import com.vanced.manager.network.model.AppDtoMapper
import com.vanced.manager.network.model.JsonDtoMapper import com.vanced.manager.network.model.DataDtoMapper
import org.koin.dsl.module import org.koin.dsl.module
val mapperModule = module { val mapperModule = module {
@ -15,9 +15,7 @@ val mapperModule = module {
fun provideJsonMapper( fun provideJsonMapper(
appDtoMapper: AppDtoMapper appDtoMapper: AppDtoMapper
): JsonDtoMapper = JsonDtoMapper( ) = DataDtoMapper(appDtoMapper)
appDtoMapper = appDtoMapper
)
single { provideAppMapper(get(), get()) } single { provideAppMapper(get(), get()) }
single { provideJsonMapper(get()) } single { provideJsonMapper(get()) }

View File

@ -5,9 +5,8 @@ import org.koin.dsl.module
val networkModule = module { val networkModule = module {
fun provideOkHttpClient(): OkHttpClient { fun provideOkHttpClient() =
return OkHttpClient() OkHttpClient()
}
single { provideOkHttpClient() } single { provideOkHttpClient() }
} }

View File

@ -11,19 +11,15 @@ val packageManagerModule = module {
fun providePackageManager( fun providePackageManager(
context: Context context: Context
): PkgManager { ): PkgManager =
return PkgManagerImpl( PkgManagerImpl(
packageManager = context.packageManager packageManager = context.packageManager
) )
}
fun providePackageInformationDataSource( fun providePackageInformationDataSource(
pkgManager: PkgManager pkgManager: PkgManager
): PackageInformationDataSource { ): PackageInformationDataSource =
return PackageInformationDataSourceImpl( PackageInformationDataSourceImpl(pkgManager)
pkgManager = pkgManager
)
}
single { providePackageManager(get()) } single { providePackageManager(get()) }
single { providePackageInformationDataSource(get()) } single { providePackageInformationDataSource(get()) }

View File

@ -4,6 +4,7 @@ import android.content.Context
import org.koin.dsl.module import org.koin.dsl.module
val preferenceModule = module { val preferenceModule = module {
fun provideDatastore( fun provideDatastore(
context: Context context: Context
) = context.getSharedPreferences("manager_settings", Context.MODE_PRIVATE) ) = context.getSharedPreferences("manager_settings", Context.MODE_PRIVATE)

View File

@ -1,20 +1,25 @@
package com.vanced.manager.di package com.vanced.manager.di
import com.vanced.manager.network.JsonService import com.vanced.manager.network.DataService
import com.vanced.manager.network.model.JsonDtoMapper import com.vanced.manager.network.model.DataDtoMapper
import com.vanced.manager.repository.JsonRepository import com.vanced.manager.repository.DataRepository
import com.vanced.manager.repository.JsonRepositoryImpl import com.vanced.manager.repository.MainRepository
import com.vanced.manager.repository.MirrorRepository
import org.koin.core.qualifier.named
import org.koin.dsl.module import org.koin.dsl.module
val repositoryModule = module { val repositoryModule = module {
fun provideJsonRepository( fun provideMainRepository(
jsonService: JsonService, dataService: DataService,
jsonDtoMapper: JsonDtoMapper dataDtoMapper: DataDtoMapper
): JsonRepository = JsonRepositoryImpl( ) = MainRepository(dataService, dataDtoMapper)
jsonService,
jsonDtoMapper
)
single { provideJsonRepository(get(), get()) } fun provideMirrorRepository(
dataService: DataService,
dataDtoMapper: DataDtoMapper
) = MirrorRepository(dataService, dataDtoMapper)
single { provideMainRepository(get(named("main")), get()) }
single { provideMirrorRepository(get(named("mirror")), get()) }
} }

View File

@ -1,22 +1,35 @@
package com.vanced.manager.di package com.vanced.manager.di
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.vanced.manager.network.JsonService import com.vanced.manager.network.DataService
import com.vanced.manager.network.util.BASE_GITHUB import com.vanced.manager.network.util.BASE_GITHUB
import com.vanced.manager.network.util.BASE_MIRROR
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.koin.core.qualifier.named
import org.koin.dsl.module import org.koin.dsl.module
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
val serviceModule = module { val serviceModule = module {
fun provideRetrofitService(okHttpClient: OkHttpClient): JsonService = fun provideMainService(
Retrofit.Builder() okHttpClient: OkHttpClient
.baseUrl(BASE_GITHUB) ) = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())) .baseUrl(BASE_GITHUB)
.client(okHttpClient) .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
.build() .client(okHttpClient)
.create(JsonService::class.java) .build()
.create(DataService::class.java)
single { provideRetrofitService(get()) } fun provideMirrorService(
okHttpClient: OkHttpClient
) = Retrofit.Builder()
.baseUrl(BASE_MIRROR)
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
.client(okHttpClient)
.build()
.create(DataService::class.java)
single(named("main")) { provideMainService(get()) }
single(named("mirror")) { provideMirrorService(get()) }
} }

View File

@ -1,5 +1,15 @@
package com.vanced.manager.di package com.vanced.manager.di
import android.app.Application
import com.vanced.manager.core.downloader.impl.MicrogDownloader
import com.vanced.manager.core.downloader.impl.MusicDownloader
import com.vanced.manager.core.downloader.impl.VancedDownloader
import com.vanced.manager.core.installer.impl.MicrogInstaller
import com.vanced.manager.core.installer.impl.MusicInstaller
import com.vanced.manager.core.installer.impl.VancedInstaller
import com.vanced.manager.repository.DataRepository
import com.vanced.manager.repository.MainRepository
import com.vanced.manager.repository.MirrorRepository
import com.vanced.manager.ui.viewmodel.InstallViewModel import com.vanced.manager.ui.viewmodel.InstallViewModel
import com.vanced.manager.ui.viewmodel.MainViewModel import com.vanced.manager.ui.viewmodel.MainViewModel
import org.koin.android.ext.koin.androidApplication import org.koin.android.ext.koin.androidApplication
@ -7,6 +17,23 @@ import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module import org.koin.dsl.module
val viewModelModule = module { val viewModelModule = module {
viewModel { MainViewModel(get(), androidApplication()) }
viewModel { InstallViewModel(get(), get(), get(), get(), get(), get()) } fun provideMainViewModel(
mainRepository: MainRepository,
mirrorRepository: MirrorRepository,
app: Application,
) = MainViewModel(mainRepository, mirrorRepository, app)
fun provideInstallViewModel(
vancedDownloader: VancedDownloader,
musicDownloader: MusicDownloader,
microgDownloader: MicrogDownloader,
vancedInstaller: VancedInstaller,
musicInstaller: MusicInstaller,
microgInstaller: MicrogInstaller,
) = InstallViewModel(vancedDownloader, musicDownloader, microgDownloader, vancedInstaller, musicInstaller, microgInstaller)
viewModel { provideMainViewModel(get(), get(), androidApplication()) }
viewModel { provideInstallViewModel(get(), get(), get(), get(), get(), get()) }
} }

View File

@ -6,13 +6,9 @@ data class App(
val remoteVersionCode: Int, val remoteVersionCode: Int,
val installedVersion: String?, val installedVersion: String?,
val installedVersionCode: Int?, val installedVersionCode: Int?,
val installedVersionRoot: String?,
val installedVersionCodeRoot: Int?,
val iconUrl: String?, val iconUrl: String?,
val appStatus: AppStatus, val appStatus: AppStatus,
val appStatusRoot: AppStatus,
val packageName: String, val packageName: String,
val packageNameRoot: String?,
val changelog: String, val changelog: String,
val url: String?, val url: String?,
val versions: List<String>?, val versions: List<String>?,

View File

@ -0,0 +1,6 @@
package com.vanced.manager.domain.model
data class Data(
val manager: App,
val apps: List<App>,
)

View File

@ -1,9 +0,0 @@
package com.vanced.manager.domain.model
data class Json(
val isMicrogBroken: Boolean,
val manager: App,
val vanced: App,
val music: App,
val microg: App
)

View File

@ -25,23 +25,25 @@ class PkgManagerImpl(
@SuppressLint("WrongConstant") @SuppressLint("WrongConstant")
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@Throws(PackageManager.NameNotFoundException::class) @Throws(PackageManager.NameNotFoundException::class)
override suspend fun getVersionCode(packageName: String): Int { override suspend fun getVersionCode(
return with(packageManager) { packageName: String
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { ) = with(packageManager) {
getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
.longVersionCode getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF)
.and(MAJOR_IGNORE) .longVersionCode
.toInt() .and(MAJOR_IGNORE)
} else { .toInt()
getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) } else {
.versionCode getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF)
} .versionCode
} }
} }
@SuppressLint("WrongConstant") @SuppressLint("WrongConstant")
@Throws(PackageManager.NameNotFoundException::class) @Throws(PackageManager.NameNotFoundException::class)
override suspend fun getVersionName(packageName: String): String = override suspend fun getVersionName(
packageManager.getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) packageName: String
.versionName ): String = packageManager
.getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF)
.versionName
} }

View File

@ -0,0 +1,11 @@
package com.vanced.manager.network
import com.vanced.manager.network.model.DataDto
import retrofit2.http.GET
interface DataService {
@GET("latest.json")
suspend fun get(): DataDto
}

View File

@ -1,11 +0,0 @@
package com.vanced.manager.network
import com.vanced.manager.network.model.JsonDto
import retrofit2.http.GET
interface JsonService {
@GET("latest.json")
suspend fun get(): JsonDto
}

View File

@ -5,11 +5,10 @@ import com.google.gson.annotations.SerializedName
data class AppDto( data class AppDto(
@SerializedName("name") val name: String, @SerializedName("name") val name: String,
@SerializedName("version") val version: String, @SerializedName("version") val version: String,
@SerializedName("versionCode") val versionCode: Int, @SerializedName("version_code") val versionCode: Int,
@SerializedName("changelog") val changelog: String, @SerializedName("changelog") val changelog: String,
@SerializedName("icon_url") val iconUrl: String? = null, @SerializedName("icon_url") val iconUrl: String,
@SerializedName("package_name") val packageName: String, @SerializedName("package_name") val packageName: String,
@SerializedName("package_name_root") val packageNameRoot: String? = null,
@SerializedName("url") val url: String? = null, @SerializedName("url") val url: String? = null,
@SerializedName("versions") val versions: List<String>? = null, @SerializedName("versions") val versions: List<String>? = null,
@SerializedName("themes") val themes: List<String>? = null, @SerializedName("themes") val themes: List<String>? = null,

View File

@ -17,8 +17,8 @@ import com.vanced.manager.network.util.VANCED_NAME
import java.util.* import java.util.*
class AppDtoMapper( class AppDtoMapper(
private val packageInformationDataSource: PackageInformationDataSource, private val pkgInfoDataSource: PackageInformationDataSource,
context: Context private val context: Context
) : EntityMapper<AppDto, App> { ) : EntityMapper<AppDto, App> {
private val latestVersionRadioButton = private val latestVersionRadioButton =
@ -27,46 +27,40 @@ class AppDtoMapper(
key = "latest" key = "latest"
) )
override suspend fun mapToModel(entity: AppDto): App = override suspend fun mapToModel(
with(entity) { entity: AppDto
val localVersionCode = packageInformationDataSource.getVersionCode(packageName) ) = with(entity) {
val localVersionCodeRoot = val localVersionCode = pkgInfoDataSource.getVersionCode(packageName)
packageInformationDataSource.getVersionCode(packageNameRoot ?: "") App(
val localVersionName = packageInformationDataSource.getVersionName(packageName) name = name,
val localVersionNameRoot = remoteVersion = version,
packageInformationDataSource.getVersionName(packageNameRoot ?: "") remoteVersionCode = versionCode,
App( installedVersion = pkgInfoDataSource.getVersionName(packageName),
name = name, installedVersionCode = localVersionCode,
remoteVersion = version, appStatus = compareVersionCodes(versionCode, localVersionCode),
remoteVersionCode = versionCode, packageName = packageName,
installedVersion = localVersionName, iconUrl = iconUrl,
installedVersionCode = localVersionCode, changelog = changelog,
installedVersionRoot = localVersionNameRoot, url = url,
installedVersionCodeRoot = localVersionCodeRoot, versions = versions,
appStatus = compareVersionCodes(versionCode, localVersionCode), themes = themes,
appStatusRoot = compareVersionCodes(versionCode, localVersionCodeRoot), languages = languages,
packageName = packageName, installationOptions = getInstallationOptions(name, themes, versions, languages)
packageNameRoot = packageNameRoot, )
iconUrl = iconUrl, }
changelog = changelog,
url = url,
versions = versions,
themes = themes,
languages = languages,
installationOptions = getInstallationOptions(name, themes, versions, languages)
)
}
private fun compareVersionCodes(remote: Int?, local: Int?) = private fun compareVersionCodes(
if (local != null && remote != null) { remote: Int?,
when { local: Int?
remote > local -> AppStatus.Update ) = if (local != null && remote != null) {
remote <= local -> AppStatus.Reinstall when {
else -> AppStatus.Install remote > local -> AppStatus.Update
} remote <= local -> AppStatus.Reinstall
} else { else -> AppStatus.Install
AppStatus.Install
} }
} else {
AppStatus.Install
}
private fun getInstallationOptions( private fun getInstallationOptions(
appName: String, appName: String,

View File

@ -0,0 +1,13 @@
package com.vanced.manager.network.model
import com.google.gson.annotations.SerializedName
data class DataDto(
@SerializedName("manager") val manager: AppDto,
@SerializedName("apps") val apps: DataAppDto
)
data class DataAppDto(
@SerializedName("nonroot") val nonroot: List<AppDto>,
@SerializedName("root") val root: List<AppDto>,
)

View File

@ -0,0 +1,26 @@
package com.vanced.manager.network.model
import com.vanced.manager.core.preferences.holder.managerVariantPref
import com.vanced.manager.domain.model.Data
import com.vanced.manager.domain.util.EntityMapper
class DataDtoMapper(
private val appDtoMapper: AppDtoMapper
) : EntityMapper<DataDto, Data> {
override suspend fun mapToModel(
entity: DataDto
) = with(entity) {
Data(
manager = appDtoMapper.mapToModel(manager),
apps =
if (managerVariantPref == "root") {
apps.root
} else {
apps.nonroot
}.map { appDto ->
appDtoMapper.mapToModel(appDto)
}
)
}
}

View File

@ -1,11 +0,0 @@
package com.vanced.manager.network.model
import com.google.gson.annotations.SerializedName
data class JsonDto(
@SerializedName("is_microg_broken") var isMicrogBroken: Boolean,
@SerializedName("manager") var manager: AppDto,
@SerializedName("vanced") var vanced: AppDto,
@SerializedName("music") var music: AppDto,
@SerializedName("microg") var microg: AppDto
)

View File

@ -1,21 +0,0 @@
package com.vanced.manager.network.model
import com.vanced.manager.domain.model.Json
import com.vanced.manager.domain.util.EntityMapper
class JsonDtoMapper(
private val appDtoMapper: AppDtoMapper
) : EntityMapper<JsonDto, Json> {
override suspend fun mapToModel(entity: JsonDto): Json =
with(entity) {
Json(
isMicrogBroken = isMicrogBroken,
manager = appDtoMapper.mapToModel(manager),
vanced = appDtoMapper.mapToModel(vanced),
music = appDtoMapper.mapToModel(music),
microg = appDtoMapper.mapToModel(microg)
)
}
}

View File

@ -1,7 +1,8 @@
package com.vanced.manager.network.util package com.vanced.manager.network.util
const val BASE = "https://api.vancedapp.com/api/v1/" const val BASE = "https://api.vancedapp.com/api/v1/"
const val BASE_GITHUB = "https://x1nto.github.io/VancedFiles/" const val BASE_MIRROR = "https://x1nto.github.io/VancedFiles/api/v2/" //TODO
const val BASE_GITHUB = "https://x1nto.github.io/VancedFiles/api/v2/"
const val VANCED_NAME = "YouTube Vanced" const val VANCED_NAME = "YouTube Vanced"
const val MUSIC_NAME = "YouTube Vanced Music" const val MUSIC_NAME = "YouTube Vanced Music"

View File

@ -0,0 +1,9 @@
package com.vanced.manager.repository
import com.vanced.manager.domain.model.Data
interface DataRepository {
suspend fun fetch(): Data
}

View File

@ -1,9 +0,0 @@
package com.vanced.manager.repository
import com.vanced.manager.domain.model.Json
interface JsonRepository {
suspend fun fetch(): Json
}

View File

@ -1,16 +0,0 @@
package com.vanced.manager.repository
import com.vanced.manager.domain.model.Json
import com.vanced.manager.network.JsonService
import com.vanced.manager.network.model.JsonDtoMapper
class JsonRepositoryImpl(
private val service: JsonService,
private val mapper: JsonDtoMapper
) : JsonRepository {
override suspend fun fetch(): Json {
return mapper.mapToModel(service.get())
}
}

View File

@ -0,0 +1,14 @@
package com.vanced.manager.repository
import com.vanced.manager.network.DataService
import com.vanced.manager.network.model.DataDtoMapper
class MainRepository(
private val mainService: DataService,
private val mapper: DataDtoMapper
) : DataRepository {
override suspend fun fetch() =
mapper.mapToModel(mainService.get())
}

View File

@ -0,0 +1,14 @@
package com.vanced.manager.repository
import com.vanced.manager.network.DataService
import com.vanced.manager.network.model.DataDtoMapper
class MirrorRepository(
private val mirrorService: DataService,
private val mapper: DataDtoMapper
) : DataRepository {
override suspend fun fetch() =
mapper.mapToModel(mirrorService.get())
}

View File

@ -30,7 +30,6 @@ import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem
import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.component.text.ManagerText
import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar
import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.resources.managerString
import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal
import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.util.Screen
import com.vanced.manager.ui.viewmodel.MainViewModel import com.vanced.manager.ui.viewmodel.MainViewModel
import com.vanced.manager.ui.widget.app.AppCard import com.vanced.manager.ui.widget.app.AppCard
@ -145,7 +144,6 @@ fun HomeLayout(
viewModel.launchApp( viewModel.launchApp(
appName = app.name, appName = app.name,
appPackage = app.packageName, appPackage = app.packageName,
appPackageRoot = app.packageNameRoot
) )
}, },
onAppInfoClick = { onAppInfoClick = {
@ -191,8 +189,7 @@ fun HomeLayout(
} }
managerCategory(homeCategorySupportUs) { managerCategory(homeCategorySupportUs) {
ScrollableItemRow( ScrollableItemRow(
modifier = Modifier modifier = Modifier.fillMaxWidth(),
.fillMaxWidth(),
items = sponsors items = sponsors
) { sponsor -> ) { sponsor ->
ManagerLinkCard( ManagerLinkCard(
@ -204,8 +201,7 @@ fun HomeLayout(
} }
managerCategory(homeCategorySocialMedia) { managerCategory(homeCategorySocialMedia) {
ScrollableItemRow( ScrollableItemRow(
modifier = Modifier modifier = Modifier.fillMaxWidth(),
.fillMaxWidth(),
items = socialMedia items = socialMedia
) { socialMedia -> ) { socialMedia ->
ManagerLinkCard( ManagerLinkCard(

View File

@ -12,22 +12,25 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.vanced.manager.core.installer.util.uninstallPackage import com.vanced.manager.core.installer.util.uninstallPackage
import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.managerVariantPref
import com.vanced.manager.core.preferences.holder.musicEnabled
import com.vanced.manager.core.preferences.holder.vancedEnabled
import com.vanced.manager.domain.model.App import com.vanced.manager.domain.model.App
import com.vanced.manager.network.util.MICROG_NAME import com.vanced.manager.network.util.MICROG_NAME
import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.MUSIC_NAME
import com.vanced.manager.network.util.VANCED_NAME import com.vanced.manager.network.util.VANCED_NAME
import com.vanced.manager.repository.JsonRepository import com.vanced.manager.repository.MainRepository
import com.vanced.manager.repository.MirrorRepository
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class MainViewModel( class MainViewModel(
private val repository: JsonRepository, private val mainRepository: MainRepository,
private val mirrorRepository: MirrorRepository,
private val app: Application private val app: Application
) : AndroidViewModel(app) { ) : AndroidViewModel(app) {
private val isNonroot private val isRoot
get() = managerVariantPref == "nonroot" get() = managerVariantPref == "root"
private val appCount: Int
get() = if (isRoot) 2 else 3
sealed class AppState { sealed class AppState {
data class Fetching(val placeholderAppsCount: Int) : AppState() data class Fetching(val placeholderAppsCount: Int) : AppState()
@ -42,37 +45,19 @@ class MainViewModel(
viewModelScope.launch { viewModelScope.launch {
appState = AppState.Fetching(appCount) appState = AppState.Fetching(appCount)
try { fetchData()
with(repository.fetch()) {
val apps = mutableListOf<App>()
apps.apply {
if (vancedEnabled) add(vanced)
if (musicEnabled) add(music)
if (isNonroot) add(microg)
}
appState = AppState.Success(apps)
}
} catch (e: Exception) {
val error = "failed to fetch: \n${e.stackTraceToString()}"
appState = AppState.Error(error)
Log.d(TAG, error)
}
} }
} }
fun launchApp( fun launchApp(
appName: String, appName: String,
appPackage: String, appPackage: String,
appPackageRoot: String?
) { ) {
val pkg = if (isNonroot) appPackage else appPackageRoot ?: appPackage
val component = ComponentName( val component = ComponentName(
/* pkg = */ appPackage, /* pkg = */ appPackage,
/* cls = */ when (appName) { /* cls = */ when (appName) {
VANCED_NAME -> "$pkg.HomeActivity" VANCED_NAME -> "com.google.android.youtube.HomeActivity"
MUSIC_NAME -> "$pkg.activities.MusicActivity" MUSIC_NAME -> "com.google.android.apps.youtube.music.activities.MusicActivity"
MICROG_NAME -> "org.microg.gms.ui.SettingsActivity" MICROG_NAME -> "org.microg.gms.ui.SettingsActivity"
else -> throw IllegalArgumentException("$appName is not a valid app") else -> throw IllegalArgumentException("$appName is not a valid app")
} }
@ -98,16 +83,25 @@ class MainViewModel(
uninstallPackage(appPackage, app) uninstallPackage(appPackage, app)
} }
private val appCount: Int private suspend fun fetchData(
get() { fromMirror: Boolean = false
var appsCount = 0 ) {
try {
val repository = if (fromMirror) mirrorRepository else mainRepository
with(repository.fetch()) {
appState = AppState.Success(apps)
}
} catch (e: Exception) {
if (!fromMirror) {
fetchData(true)
return
}
if (vancedEnabled) appsCount++ val error = "failed to fetch: \n${e.stackTraceToString()}"
if (musicEnabled) appsCount++ appState = AppState.Error(error)
if (isNonroot) appsCount++ Log.d(TAG, error)
return appsCount
} }
}
companion object { companion object {
const val TAG = "MainViewModel" const val TAG = "MainViewModel"