This commit is contained in:
topjohnwu 2019-05-30 01:05:48 -07:00
parent b31d3802eb
commit c0d1ce96d1
10 changed files with 8 additions and 223 deletions

View File

@ -1,27 +0,0 @@
package com.topjohnwu.magisk.data.network
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.model.entity.GithubRepo
import io.reactivex.Single
import retrofit2.http.GET
import retrofit2.http.Query
interface GithubApiServices {
@GET("users/Magisk-Modules-Repo/repos")
fun fetchRepos(
@Query("page") page: Int,
@Query("per_page") count: Int = REPOS_PER_PAGE,
@Query("sort") sortOrder: String = when (Config.get<Int>(Config.Key.REPO_ORDER)) {
Config.Value.ORDER_DATE -> "updated"
Config.Value.ORDER_NAME -> "full_name"
else -> "updated"
}
): Single<List<GithubRepo>>
companion object {
const val REPOS_PER_PAGE = 100
}
}

View File

@ -40,22 +40,6 @@ interface GithubRawApiServices {
//endregion
//region topjohnwu/Magisk/master
@GET("$MAGISK_MASTER/scripts/module_installer.sh")
@Streaming
fun fetchModuleInstaller(): Single<ResponseBody>
//endregion
//region Magisk-Modules-Repo
@GET("$MAGISK_MODULES/{$MODULE}/master/{$FILE}")
@Streaming
fun fetchFile(@Path(MODULE) id: String, @Path(FILE) file: String): Single<ResponseBody>
//endregion
/**
* This method shall be used exclusively for fetching files from urls from previous requests.
* Him, who uses it in a wrong way, shall die in an eternal flame.

View File

@ -1,21 +0,0 @@
package com.topjohnwu.magisk.data.network
import io.reactivex.Single
import okhttp3.ResponseBody
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Streaming
interface GithubServices {
@GET("Magisk-Modules-Repo/{$MODULE}/archive/master.zip")
@Streaming
fun fetchModuleZip(@Path(MODULE) module: String): Single<ResponseBody>
companion object {
private const val MODULE = "module"
}
}

View File

@ -1,98 +0,0 @@
package com.topjohnwu.magisk.data.repository
import android.content.Context
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.data.database.RepositoryDao
import com.topjohnwu.magisk.data.network.GithubApiServices
import com.topjohnwu.magisk.data.network.GithubRawApiServices
import com.topjohnwu.magisk.data.network.GithubServices
import com.topjohnwu.magisk.model.entity.GithubRepo
import com.topjohnwu.magisk.model.entity.toRepository
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.utils.toSingle
import com.topjohnwu.magisk.utils.writeToFile
import com.topjohnwu.magisk.utils.writeToString
import io.reactivex.Completable
import io.reactivex.Single
class ModuleRepository(
private val context: Context,
private val apiRaw: GithubRawApiServices,
private val api: GithubApiServices,
private val apiWeb: GithubServices,
private val repoDao: RepositoryDao
) {
fun fetchModules(force: Boolean = false) =
if (force) fetchRemoteRepos() else fetchCachedOrdered()
.flatMap { if (it.isEmpty()) fetchRemoteRepos() else it.toSingle() }
private fun fetchRemoteRepos() = fetchAllRepos()
.map {
it.mapNotNull {
runCatching {
fetchProperties(it.name, it.updatedAtMillis).blockingGet()
}.getOrNull()
}
}
//either github apparently returns repos incorrectly or ...
//either ways this fixes duplicates
.map { it.distinctBy { it.id } }
.doOnSuccess { repoDao.insert(it) }
private fun fetchCachedOrdered() = Single.fromCallable {
when (Config.get<Int>(Config.Key.REPO_ORDER)) {
Config.Value.ORDER_DATE -> repoDao.fetchAll()
Config.Value.ORDER_NAME -> repoDao.fetchAllOrderByName()
else -> repoDao.fetchAll()
}
}
fun fetchInstalledModules() = Single.fromCallable { Utils.loadModulesLeanback() }
.map { it.values.toList() }
fun fetchInstallFile(module: String) = apiRaw
.fetchFile(module, FILE_INSTALL_SH)
.map { it.writeToFile(context, FILE_INSTALL_SH) }
fun fetchReadme(module: String) = apiRaw
.fetchFile(module, FILE_README_MD)
.map { it.writeToString() }
fun fetchConfig(module: String) = apiRaw
.fetchFile(module, FILE_CONFIG_SH)
.map { it.writeToFile(context, FILE_CONFIG_SH) }
fun fetchInstallZip(module: String) = apiWeb
.fetchModuleZip(module)
.map { it.writeToFile(context, FILE_INSTALL_ZIP) }
fun fetchInstaller() = apiRaw
.fetchModuleInstaller()
.map { it.writeToFile(context, FILE_MODULE_INSTALLER_SH) }
fun deleteAllCached() = Completable.fromCallable { repoDao.deleteAll() }
private fun fetchProperties(module: String, lastChanged: Long) = apiRaw
.fetchFile(module, "module.prop")
.map { it.toRepository(lastChanged) }
private fun fetchAllRepos(page: Int = 0): Single<List<GithubRepo>> = api.fetchRepos(page)
.flatMap {
if (it.size == GithubApiServices.REPOS_PER_PAGE) {
fetchAllRepos(page + 1).map { newList -> it + newList }
} else {
Single.just(it)
}
}
companion object {
const val FILE_INSTALL_SH = "install.sh"
const val FILE_README_MD = "README.md"
const val FILE_CONFIG_SH = "config.sh"
const val FILE_INSTALL_ZIP = "install.zip"
const val FILE_MODULE_INSTALLER_SH = "module_installer.sh"
}
}

View File

@ -3,9 +3,7 @@ package com.topjohnwu.magisk.di
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import com.topjohnwu.magisk.Constants
import com.topjohnwu.magisk.data.network.GithubApiServices
import com.topjohnwu.magisk.data.network.GithubRawApiServices
import com.topjohnwu.magisk.data.network.GithubServices
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.koin.dsl.module
@ -23,8 +21,6 @@ val networkingModule = module {
single { createRetrofit(get(), get(), get()) }
single { createApiService<GithubServices>(get(), Constants.GITHUB_URL) }
single { createApiService<GithubApiServices>(get(), Constants.GITHUB_API_URL) }
single { createApiService<GithubRawApiServices>(get(), Constants.GITHUB_RAW_API_URL) }
}

View File

@ -6,7 +6,6 @@ import org.koin.dsl.module
val repositoryModule = module {
single { MagiskRepository(get(), get(), get()) }
single { ModuleRepository(get(), get(), get(), get(), get()) }
single { LogRepository(get()) }
single { AppRepository(get()) }
single { SettingRepository(get()) }

View File

@ -18,7 +18,7 @@ val viewModelModules = module {
viewModel { HomeViewModel(get()) }
viewModel { SuperuserViewModel(get(), get(), get(), get()) }
viewModel { HideViewModel(get(), get()) }
viewModel { ModuleViewModel(get(), get(), get(), get()) }
viewModel { ModuleViewModel(get(), get(), get()) }
viewModel { LogViewModel(get(), get()) }
viewModel { (action: String, uri: Uri?) -> FlashViewModel(action, uri, get()) }
viewModel { SuRequestViewModel(get(), get(), get(SUTimeout), get()) }

View File

@ -1,18 +0,0 @@
package com.topjohnwu.magisk.model.entity
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.topjohnwu.magisk.utils.timeFormatStandard
import com.topjohnwu.magisk.utils.toTime
import timber.log.Timber
@JsonClass(generateAdapter = true)
data class GithubRepo(
@Json(name = "name") val name: String,
@Json(name = "updated_at") val updatedAt: String
) {
val updatedAtMillis by lazy {
updatedAt.toTime(timeFormatStandard)
.apply { Timber.i("$name updated @ $this ($updatedAt)") }
}
}

View File

@ -16,7 +16,6 @@ import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.KConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.database.RepoDatabaseHelper
import com.topjohnwu.magisk.data.repository.ModuleRepository
import com.topjohnwu.magisk.data.repository.SettingRepository
import org.koin.android.ext.android.inject
@ -27,7 +26,6 @@ abstract class BasePreferenceFragment : PreferenceFragmentCompat(),
protected val prefs: SharedPreferences by inject()
protected val app: App by inject()
protected val settingRepo: SettingRepository by inject()
protected val moduleRepo: ModuleRepository by inject()
override fun onCreateView(
inflater: LayoutInflater,

View File

@ -11,7 +11,6 @@ import com.skoumal.teanity.util.KObservableField
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.database.RepoDatabaseHelper
import com.topjohnwu.magisk.data.repository.ModuleRepository
import com.topjohnwu.magisk.model.entity.Repo
import com.topjohnwu.magisk.model.entity.recycler.ModuleRvItem
import com.topjohnwu.magisk.model.entity.recycler.RepoRvItem
@ -21,18 +20,15 @@ import com.topjohnwu.magisk.model.events.OpenChangelogEvent
import com.topjohnwu.magisk.model.events.OpenFilePickerEvent
import com.topjohnwu.magisk.tasks.UpdateRepos
import com.topjohnwu.magisk.ui.base.MagiskViewModel
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.utils.toSingle
import com.topjohnwu.magisk.utils.update
import com.topjohnwu.magisk.utils.zip
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import me.tatarka.bindingcollectionadapter2.OnItemBind
class ModuleViewModel(
private val resources: Resources,
private val moduleRepo: ModuleRepository,
private val repoDatabase: RepoDatabaseHelper,
private val repoUpdater: UpdateRepos
) : MagiskViewModel() {
@ -62,33 +58,9 @@ class ModuleViewModel(
fun repoPressed(item: RepoRvItem) = OpenChangelogEvent(item.item).publish()
fun downloadPressed(item: RepoRvItem) = InstallModuleEvent(item.item).publish()
fun refreshNew(forceReload: Boolean) {
val updateInstalled = moduleRepo.fetchInstalledModules()
.flattenAsFlowable { it }
.map { ModuleRvItem(it) }
.toList()
.map { it to itemsInstalled.calculateDiff(it) }
val updateRemote = moduleRepo.fetchModules(forceReload)
zip(updateInstalled, updateRemote) { installed, remote -> installed to remote }
.observeOn(AndroidSchedulers.mainThread())
.map {
itemsInstalled.update(it.first.first, it.first.second)
it.second
}
.observeOn(Schedulers.computation())
.flattenAsFlowable { it }
.map { RepoRvItem(it) }
.toList()
.doOnSuccess { allItems.update(it) }
.flatMap { queryRaw() }
.applyViewModel(this)
.subscribeK { itemsRemote.update(it.first, it.second) }
}
fun refresh/*Old*/(force: Boolean) {
moduleRepo.fetchInstalledModules()
fun refresh(force: Boolean) {
Single.fromCallable { Utils.loadModulesLeanback() }
.map { it.values.toList() }
.flattenAsFlowable { it }
.map { ModuleRvItem(it) }
.toList()