mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-21 07:51:28 +00:00
Refactor class names
This commit is contained in:
parent
311c1f0dfd
commit
0a14f43f9c
@ -8,7 +8,7 @@ import com.topjohnwu.magisk.core.Info
|
|||||||
import com.topjohnwu.magisk.core.model.MagiskJson
|
import com.topjohnwu.magisk.core.model.MagiskJson
|
||||||
import com.topjohnwu.magisk.core.model.ManagerJson
|
import com.topjohnwu.magisk.core.model.ManagerJson
|
||||||
import com.topjohnwu.magisk.core.model.StubJson
|
import com.topjohnwu.magisk.core.model.StubJson
|
||||||
import com.topjohnwu.magisk.core.model.module.Repo
|
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||||
import com.topjohnwu.magisk.ktx.cachedFile
|
import com.topjohnwu.magisk.ktx.cachedFile
|
||||||
import com.topjohnwu.magisk.ktx.get
|
import com.topjohnwu.magisk.ktx.get
|
||||||
@ -26,7 +26,7 @@ sealed class Subject : Parcelable {
|
|||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
class Module(
|
class Module(
|
||||||
val module: Repo,
|
val module: OnlineModule,
|
||||||
override val action: Action
|
override val action: Action
|
||||||
) : Subject() {
|
) : Subject() {
|
||||||
override val url: String get() = module.zip_url
|
override val url: String get() = module.zip_url
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.core.model.module
|
|
||||||
|
|
||||||
abstract class BaseModule : Comparable<BaseModule> {
|
|
||||||
abstract var id: String
|
|
||||||
protected set
|
|
||||||
abstract var name: String
|
|
||||||
protected set
|
|
||||||
abstract var author: String
|
|
||||||
protected set
|
|
||||||
abstract var version: String
|
|
||||||
protected set
|
|
||||||
abstract var versionCode: Int
|
|
||||||
protected set
|
|
||||||
abstract var description: String
|
|
||||||
protected set
|
|
||||||
|
|
||||||
@Throws(NumberFormatException::class)
|
|
||||||
protected fun parseProps(props: List<String>) {
|
|
||||||
for (line in props) {
|
|
||||||
val prop = line.split("=".toRegex(), 2).map { it.trim() }
|
|
||||||
if (prop.size != 2)
|
|
||||||
continue
|
|
||||||
|
|
||||||
val key = prop[0]
|
|
||||||
val value = prop[1]
|
|
||||||
if (key.isEmpty() || key[0] == '#')
|
|
||||||
continue
|
|
||||||
|
|
||||||
when (key) {
|
|
||||||
"id" -> id = value
|
|
||||||
"name" -> name = value
|
|
||||||
"version" -> version = value
|
|
||||||
"versionCode" -> versionCode = value.toInt()
|
|
||||||
"author" -> author = value
|
|
||||||
"description" -> description = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override operator fun compareTo(other: BaseModule) = name.compareTo(other.name, true)
|
|
||||||
}
|
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.topjohnwu.magisk.core.model.module
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
|
import com.topjohnwu.superuser.Shell
|
||||||
|
import com.topjohnwu.superuser.io.SuFile
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class LocalModule(path: String) : Module() {
|
||||||
|
override var id: String = ""
|
||||||
|
override var name: String = ""
|
||||||
|
override var author: String = ""
|
||||||
|
override var version: String = ""
|
||||||
|
override var versionCode: Int = -1
|
||||||
|
override var description: String = ""
|
||||||
|
|
||||||
|
private val removeFile = SuFile(path, "remove")
|
||||||
|
private val disableFile = SuFile(path, "disable")
|
||||||
|
private val updateFile = SuFile(path, "update")
|
||||||
|
private val ruleFile = SuFile(path, "sepolicy.rule")
|
||||||
|
|
||||||
|
val updated: Boolean get() = updateFile.exists()
|
||||||
|
|
||||||
|
var enable: Boolean
|
||||||
|
get() = !disableFile.exists()
|
||||||
|
set(enable) {
|
||||||
|
val dir = "$PERSIST/$id"
|
||||||
|
if (enable) {
|
||||||
|
Shell.su("mkdir -p $dir", "cp -af $ruleFile $dir").submit()
|
||||||
|
disableFile.delete()
|
||||||
|
} else {
|
||||||
|
Shell.su("rm -rf $dir").submit()
|
||||||
|
!disableFile.createNewFile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var remove: Boolean
|
||||||
|
get() = removeFile.exists()
|
||||||
|
set(remove) {
|
||||||
|
if (remove) {
|
||||||
|
Shell.su("rm -rf $PERSIST/$id").submit()
|
||||||
|
removeFile.createNewFile()
|
||||||
|
} else {
|
||||||
|
Shell.su("cp -af $ruleFile $PERSIST/$id").submit()
|
||||||
|
!removeFile.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
runCatching {
|
||||||
|
parseProps(Shell.su("dos2unix < $path/module.prop").exec().out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id.isEmpty()) {
|
||||||
|
val sep = path.lastIndexOf('/')
|
||||||
|
id = path.substring(sep + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
name = id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val PERSIST get() = "${Const.MAGISKTMP}/mirror/persist/magisk"
|
||||||
|
|
||||||
|
suspend fun installed() = withContext(Dispatchers.IO) {
|
||||||
|
SuFile(Const.MAGISK_PATH)
|
||||||
|
.listFiles { _, name -> name != "lost+found" && name != ".core" }
|
||||||
|
.orEmpty()
|
||||||
|
.filter { !it.isFile }
|
||||||
|
.map { LocalModule("${Const.MAGISK_PATH}/${it.name}") }
|
||||||
|
.sortedBy { it.name.toLowerCase() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,77 +1,41 @@
|
|||||||
package com.topjohnwu.magisk.core.model.module
|
package com.topjohnwu.magisk.core.model.module
|
||||||
|
|
||||||
import com.topjohnwu.magisk.core.Const
|
abstract class Module : Comparable<Module> {
|
||||||
import com.topjohnwu.superuser.Shell
|
abstract var id: String
|
||||||
import com.topjohnwu.superuser.io.SuFile
|
protected set
|
||||||
import kotlinx.coroutines.Dispatchers
|
abstract var name: String
|
||||||
import kotlinx.coroutines.withContext
|
protected set
|
||||||
|
abstract var author: String
|
||||||
|
protected set
|
||||||
|
abstract var version: String
|
||||||
|
protected set
|
||||||
|
abstract var versionCode: Int
|
||||||
|
protected set
|
||||||
|
abstract var description: String
|
||||||
|
protected set
|
||||||
|
|
||||||
class Module(path: String) : BaseModule() {
|
@Throws(NumberFormatException::class)
|
||||||
override var id: String = ""
|
protected fun parseProps(props: List<String>) {
|
||||||
override var name: String = ""
|
for (line in props) {
|
||||||
override var author: String = ""
|
val prop = line.split("=".toRegex(), 2).map { it.trim() }
|
||||||
override var version: String = ""
|
if (prop.size != 2)
|
||||||
override var versionCode: Int = -1
|
continue
|
||||||
override var description: String = ""
|
|
||||||
|
|
||||||
private val removeFile = SuFile(path, "remove")
|
val key = prop[0]
|
||||||
private val disableFile = SuFile(path, "disable")
|
val value = prop[1]
|
||||||
private val updateFile = SuFile(path, "update")
|
if (key.isEmpty() || key[0] == '#')
|
||||||
private val ruleFile = SuFile(path, "sepolicy.rule")
|
continue
|
||||||
|
|
||||||
val updated: Boolean get() = updateFile.exists()
|
when (key) {
|
||||||
|
"id" -> id = value
|
||||||
var enable: Boolean
|
"name" -> name = value
|
||||||
get() = !disableFile.exists()
|
"version" -> version = value
|
||||||
set(enable) {
|
"versionCode" -> versionCode = value.toInt()
|
||||||
val dir = "$PERSIST/$id"
|
"author" -> author = value
|
||||||
if (enable) {
|
"description" -> description = value
|
||||||
Shell.su("mkdir -p $dir", "cp -af $ruleFile $dir").submit()
|
|
||||||
disableFile.delete()
|
|
||||||
} else {
|
|
||||||
Shell.su("rm -rf $dir").submit()
|
|
||||||
!disableFile.createNewFile()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var remove: Boolean
|
|
||||||
get() = removeFile.exists()
|
|
||||||
set(remove) {
|
|
||||||
if (remove) {
|
|
||||||
Shell.su("rm -rf $PERSIST/$id").submit()
|
|
||||||
removeFile.createNewFile()
|
|
||||||
} else {
|
|
||||||
Shell.su("cp -af $ruleFile $PERSIST/$id").submit()
|
|
||||||
!removeFile.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
runCatching {
|
|
||||||
parseProps(Shell.su("dos2unix < $path/module.prop").exec().out)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id.isEmpty()) {
|
|
||||||
val sep = path.lastIndexOf('/')
|
|
||||||
id = path.substring(sep + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.isEmpty()) {
|
|
||||||
name = id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
override operator fun compareTo(other: Module) = name.compareTo(other.name, true)
|
||||||
|
|
||||||
private val PERSIST get() = "${Const.MAGISKTMP}/mirror/persist/magisk"
|
|
||||||
|
|
||||||
suspend fun installed() = withContext(Dispatchers.IO) {
|
|
||||||
SuFile(Const.MAGISK_PATH)
|
|
||||||
.listFiles { _, name -> name != "lost+found" && name != ".core" }
|
|
||||||
.orEmpty()
|
|
||||||
.filter { !it.isFile }
|
|
||||||
.map { Module("${Const.MAGISK_PATH}/${it.name}") }
|
|
||||||
.sortedBy { it.name.toLowerCase() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,9 @@ import kotlinx.android.parcel.Parcelize
|
|||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Entity(tableName = "repos")
|
@Entity(tableName = "modules")
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class Repo(
|
data class OnlineModule(
|
||||||
@PrimaryKey override var id: String,
|
@PrimaryKey override var id: String,
|
||||||
override var name: String = "",
|
override var name: String = "",
|
||||||
override var author: String = "",
|
override var author: String = "",
|
||||||
@ -24,7 +24,7 @@ data class Repo(
|
|||||||
val prop_url: String,
|
val prop_url: String,
|
||||||
val zip_url: String,
|
val zip_url: String,
|
||||||
val notes_url: String
|
val notes_url: String
|
||||||
) : BaseModule(), Parcelable {
|
) : Module(), Parcelable {
|
||||||
|
|
||||||
private val svc: NetworkService get() = get()
|
private val svc: NetworkService get() = get()
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.core.tasks
|
package com.topjohnwu.magisk.core.tasks
|
||||||
|
|
||||||
import com.topjohnwu.magisk.core.model.module.Repo
|
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||||
import com.topjohnwu.magisk.data.database.RepoDao
|
import com.topjohnwu.magisk.data.database.RepoDao
|
||||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||||
import com.topjohnwu.magisk.ktx.synchronized
|
import com.topjohnwu.magisk.ktx.synchronized
|
||||||
@ -18,7 +18,7 @@ class RepoUpdater(
|
|||||||
|
|
||||||
suspend fun run(forced: Boolean) = withContext(Dispatchers.IO) {
|
suspend fun run(forced: Boolean) = withContext(Dispatchers.IO) {
|
||||||
val cachedMap = HashMap<String, Date>().also { map ->
|
val cachedMap = HashMap<String, Date>().also { map ->
|
||||||
repoDB.getRepoStubs().forEach { map[it.id] = Date(it.last_update) }
|
repoDB.getModuleStubs().forEach { map[it.id] = Date(it.last_update) }
|
||||||
}.synchronized()
|
}.synchronized()
|
||||||
val info = svc.fetchRepoInfo()
|
val info = svc.fetchRepoInfo()
|
||||||
coroutineScope {
|
coroutineScope {
|
||||||
@ -27,15 +27,15 @@ class RepoUpdater(
|
|||||||
val lastUpdated = cachedMap.remove(it.id)
|
val lastUpdated = cachedMap.remove(it.id)
|
||||||
if (forced || lastUpdated?.before(Date(it.last_update)) != false) {
|
if (forced || lastUpdated?.before(Date(it.last_update)) != false) {
|
||||||
try {
|
try {
|
||||||
val repo = Repo(it).apply { load() }
|
val repo = OnlineModule(it).apply { load() }
|
||||||
repoDB.addRepo(repo)
|
repoDB.addModule(repo)
|
||||||
} catch (e: Repo.IllegalRepoException) {
|
} catch (e: OnlineModule.IllegalRepoException) {
|
||||||
Timber.e(e)
|
Timber.e(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
repoDB.removeRepos(cachedMap.keys)
|
repoDB.removeModules(cachedMap.keys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
@file:JvmMultifileClass
|
|
||||||
|
|
||||||
package com.topjohnwu.magisk.data.database
|
|
||||||
|
|
||||||
import androidx.room.Dao
|
|
||||||
import androidx.room.Query
|
|
||||||
import com.topjohnwu.magisk.core.model.module.Repo
|
|
||||||
|
|
||||||
interface RepoBase {
|
|
||||||
|
|
||||||
fun getRepos(offset: Int, limit: Int = LIMIT): List<Repo>
|
|
||||||
fun searchRepos(query: String, offset: Int, limit: Int = LIMIT): List<Repo>
|
|
||||||
|
|
||||||
@Query("SELECT * FROM repos WHERE id = :id AND versionCode > :versionCode LIMIT 1")
|
|
||||||
fun getUpdatableRepoById(id: String, versionCode: Int): Repo?
|
|
||||||
|
|
||||||
@Query("SELECT * FROM repos WHERE id = :id LIMIT 1")
|
|
||||||
fun getRepoById(id: String): Repo?
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val LIMIT = 10
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
interface RepoByUpdatedDao : RepoBase {
|
|
||||||
|
|
||||||
@Query("SELECT * FROM repos ORDER BY last_update DESC LIMIT :limit OFFSET :offset")
|
|
||||||
override fun getRepos(offset: Int, limit: Int): List<Repo>
|
|
||||||
|
|
||||||
@Query(
|
|
||||||
"""SELECT *
|
|
||||||
FROM repos
|
|
||||||
WHERE
|
|
||||||
(author LIKE '%' || :query || '%') ||
|
|
||||||
(name LIKE '%' || :query || '%') ||
|
|
||||||
(description LIKE '%' || :query || '%')
|
|
||||||
ORDER BY last_update DESC
|
|
||||||
LIMIT :limit
|
|
||||||
OFFSET :offset"""
|
|
||||||
)
|
|
||||||
override fun searchRepos(query: String, offset: Int, limit: Int): List<Repo>
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
interface RepoByNameDao : RepoBase {
|
|
||||||
|
|
||||||
@Query("SELECT * FROM repos ORDER BY name COLLATE NOCASE LIMIT :limit OFFSET :offset")
|
|
||||||
override fun getRepos(offset: Int, limit: Int): List<Repo>
|
|
||||||
|
|
||||||
@Query(
|
|
||||||
"""SELECT *
|
|
||||||
FROM repos
|
|
||||||
WHERE
|
|
||||||
(author LIKE '%' || :query || '%') ||
|
|
||||||
(name LIKE '%' || :query || '%') ||
|
|
||||||
(description LIKE '%' || :query || '%')
|
|
||||||
ORDER BY name COLLATE NOCASE
|
|
||||||
LIMIT :limit
|
|
||||||
OFFSET :offset"""
|
|
||||||
)
|
|
||||||
override fun searchRepos(query: String, offset: Int, limit: Int): List<Repo>
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -2,54 +2,89 @@ package com.topjohnwu.magisk.data.database
|
|||||||
|
|
||||||
import androidx.room.*
|
import androidx.room.*
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.model.module.Repo
|
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@Database(version = 7, entities = [Repo::class], exportSchema = false)
|
@Database(version = 8, entities = [OnlineModule::class], exportSchema = false)
|
||||||
abstract class RepoDatabase : RoomDatabase() {
|
abstract class RepoDatabase : RoomDatabase() {
|
||||||
|
|
||||||
abstract fun repoDao() : RepoDao
|
abstract fun repoDao() : RepoDao
|
||||||
abstract fun repoByUpdatedDao(): RepoByUpdatedDao
|
|
||||||
abstract fun repoByNameDao(): RepoByNameDao
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
abstract class RepoDao(private val db: RepoDatabase) {
|
abstract class RepoDao(private val db: RepoDatabase) {
|
||||||
|
|
||||||
val repos: List<Repo> get() = when (Config.repoOrder) {
|
|
||||||
Config.Value.ORDER_NAME -> getReposNameOrder()
|
|
||||||
else -> getReposDateOrder()
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun clear() = withContext(Dispatchers.IO) { db.clearAllTables() }
|
suspend fun clear() = withContext(Dispatchers.IO) { db.clearAllTables() }
|
||||||
|
|
||||||
@Query("SELECT * FROM repos ORDER BY last_update DESC")
|
|
||||||
protected abstract fun getReposDateOrder(): List<Repo>
|
|
||||||
|
|
||||||
@Query("SELECT * FROM repos ORDER BY name COLLATE NOCASE")
|
|
||||||
protected abstract fun getReposNameOrder(): List<Repo>
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
abstract fun addRepo(repo: Repo)
|
abstract fun addModule(repo: OnlineModule)
|
||||||
|
|
||||||
@Query("SELECT * FROM repos WHERE id = :id")
|
|
||||||
abstract fun getRepo(id: String): Repo?
|
|
||||||
|
|
||||||
@Query("SELECT id, last_update FROM repos")
|
|
||||||
abstract fun getRepoStubs(): List<RepoStub>
|
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
abstract fun removeRepo(repo: Repo)
|
abstract fun removeModule(repo: OnlineModule)
|
||||||
|
|
||||||
@Query("DELETE FROM repos WHERE id = :id")
|
@Query("DELETE FROM modules WHERE id = :id")
|
||||||
abstract fun removeRepo(id: String)
|
abstract fun removeModule(id: String)
|
||||||
|
|
||||||
@Query("DELETE FROM repos WHERE id IN (:idList)")
|
@Query("DELETE FROM modules WHERE id IN (:idList)")
|
||||||
abstract fun removeRepos(idList: Collection<String>)
|
abstract fun removeModules(idList: Collection<String>)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM modules WHERE id = :id")
|
||||||
|
abstract fun getModule(id: String): OnlineModule?
|
||||||
|
|
||||||
|
@Query("SELECT id, last_update FROM modules")
|
||||||
|
abstract fun getModuleStubs(): List<ModuleStub>
|
||||||
|
|
||||||
|
fun getModules(offset: Int, limit: Int = LIMIT) = when (Config.repoOrder) {
|
||||||
|
Config.Value.ORDER_NAME -> getNameOrder(offset, limit)
|
||||||
|
else -> getDateOrder(offset, limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchModules(query: String, offset: Int, limit: Int = LIMIT) = when (Config.repoOrder) {
|
||||||
|
Config.Value.ORDER_NAME -> searchNameOrder(query, offset, limit)
|
||||||
|
else -> searchDateOrder(query, offset, limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Query("SELECT * FROM modules WHERE id = :id AND versionCode > :versionCode LIMIT 1")
|
||||||
|
abstract fun getUpdatableModule(id: String, versionCode: Int): OnlineModule?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM modules ORDER BY last_update DESC LIMIT :limit OFFSET :offset")
|
||||||
|
protected abstract fun getDateOrder(offset: Int, limit: Int): List<OnlineModule>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM modules ORDER BY name COLLATE NOCASE LIMIT :limit OFFSET :offset")
|
||||||
|
protected abstract fun getNameOrder(offset: Int, limit: Int): List<OnlineModule>
|
||||||
|
|
||||||
|
@Query(
|
||||||
|
"""SELECT *
|
||||||
|
FROM modules
|
||||||
|
WHERE
|
||||||
|
(author LIKE '%' || :query || '%') ||
|
||||||
|
(name LIKE '%' || :query || '%') ||
|
||||||
|
(description LIKE '%' || :query || '%')
|
||||||
|
ORDER BY last_update DESC
|
||||||
|
LIMIT :limit
|
||||||
|
OFFSET :offset"""
|
||||||
|
)
|
||||||
|
protected abstract fun searchDateOrder(query: String, offset: Int, limit: Int): List<OnlineModule>
|
||||||
|
|
||||||
|
@Query(
|
||||||
|
"""SELECT *
|
||||||
|
FROM modules
|
||||||
|
WHERE
|
||||||
|
(author LIKE '%' || :query || '%') ||
|
||||||
|
(name LIKE '%' || :query || '%') ||
|
||||||
|
(description LIKE '%' || :query || '%')
|
||||||
|
ORDER BY name COLLATE NOCASE
|
||||||
|
LIMIT :limit
|
||||||
|
OFFSET :offset"""
|
||||||
|
)
|
||||||
|
protected abstract fun searchNameOrder(query: String, offset: Int, limit: Int): List<OnlineModule>
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val LIMIT = 10
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class RepoStub(
|
data class ModuleStub(
|
||||||
@PrimaryKey val id: String,
|
@PrimaryKey val id: String,
|
||||||
val last_update: Long
|
val last_update: Long
|
||||||
)
|
)
|
||||||
|
@ -17,8 +17,6 @@ val databaseModule = module {
|
|||||||
single { StringDao() }
|
single { StringDao() }
|
||||||
single { createRepoDatabase(get()) }
|
single { createRepoDatabase(get()) }
|
||||||
single { get<RepoDatabase>().repoDao() }
|
single { get<RepoDatabase>().repoDao() }
|
||||||
single { get<RepoDatabase>().repoByNameDao() }
|
|
||||||
single { get<RepoDatabase>().repoByUpdatedDao() }
|
|
||||||
single { createSuLogDatabase(get(Protected)).suLogDao() }
|
single { createSuLogDatabase(get(Protected)).suLogDao() }
|
||||||
single { RepoUpdater(get(), get()) }
|
single { RepoUpdater(get(), get()) }
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ val viewModelModules = module {
|
|||||||
viewModel { HideViewModel() }
|
viewModel { HideViewModel() }
|
||||||
viewModel { HomeViewModel(get()) }
|
viewModel { HomeViewModel(get()) }
|
||||||
viewModel { LogViewModel(get()) }
|
viewModel { LogViewModel(get()) }
|
||||||
viewModel { ModuleViewModel(get(), get(), get()) }
|
viewModel { ModuleViewModel(get(), get()) }
|
||||||
viewModel { SafetynetViewModel() }
|
viewModel { SafetynetViewModel() }
|
||||||
viewModel { SettingsViewModel(get()) }
|
viewModel { SettingsViewModel(get()) }
|
||||||
viewModel { SuperuserViewModel(get(), get()) }
|
viewModel { SuperuserViewModel(get(), get()) }
|
||||||
|
@ -12,7 +12,7 @@ import com.topjohnwu.magisk.arch.*
|
|||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.base.ActivityResultCallback
|
import com.topjohnwu.magisk.core.base.ActivityResultCallback
|
||||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||||
import com.topjohnwu.magisk.core.model.module.Repo
|
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.utils.Utils
|
||||||
import com.topjohnwu.magisk.view.MarkDownWindow
|
import com.topjohnwu.magisk.view.MarkDownWindow
|
||||||
import com.topjohnwu.magisk.view.Shortcuts
|
import com.topjohnwu.magisk.view.Shortcuts
|
||||||
@ -22,7 +22,7 @@ class ViewActionEvent(val action: BaseActivity.() -> Unit) : ViewEvent(), Activi
|
|||||||
override fun invoke(activity: BaseUIActivity<*, *>) = action(activity)
|
override fun invoke(activity: BaseUIActivity<*, *>) = action(activity)
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenReadmeEvent(val item: Repo) : ViewEventWithScope(), ContextExecutor {
|
class OpenReadmeEvent(val item: OnlineModule) : ViewEventWithScope(), ContextExecutor {
|
||||||
override fun invoke(context: Context) {
|
override fun invoke(context: Context) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
MarkDownWindow.show(context, null, item::notes)
|
MarkDownWindow.show(context, null, item::notes)
|
||||||
|
@ -5,10 +5,10 @@ import com.topjohnwu.magisk.core.Info
|
|||||||
import com.topjohnwu.magisk.core.download.Action
|
import com.topjohnwu.magisk.core.download.Action
|
||||||
import com.topjohnwu.magisk.core.download.DownloadService
|
import com.topjohnwu.magisk.core.download.DownloadService
|
||||||
import com.topjohnwu.magisk.core.download.Subject
|
import com.topjohnwu.magisk.core.download.Subject
|
||||||
import com.topjohnwu.magisk.core.model.module.Repo
|
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
|
|
||||||
class ModuleInstallDialog(private val item: Repo) : DialogEvent() {
|
class ModuleInstallDialog(private val item: OnlineModule) : DialogEvent() {
|
||||||
|
|
||||||
override fun build(dialog: MagiskDialog) {
|
override fun build(dialog: MagiskDialog) {
|
||||||
with(dialog) {
|
with(dialog) {
|
||||||
|
@ -3,8 +3,8 @@ package com.topjohnwu.magisk.ui.module
|
|||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.core.model.module.Module
|
import com.topjohnwu.magisk.core.model.module.LocalModule
|
||||||
import com.topjohnwu.magisk.core.model.module.Repo
|
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||||
import com.topjohnwu.magisk.databinding.ObservableItem
|
import com.topjohnwu.magisk.databinding.ObservableItem
|
||||||
import com.topjohnwu.magisk.utils.set
|
import com.topjohnwu.magisk.utils.set
|
||||||
@ -39,7 +39,7 @@ class SectionTitle(
|
|||||||
override fun contentSameAs(other: SectionTitle): Boolean = this === other
|
override fun contentSameAs(other: SectionTitle): Boolean = this === other
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class RepoItem(val item: Repo) : ObservableItem<RepoItem>() {
|
sealed class RepoItem(val item: OnlineModule) : ObservableItem<RepoItem>() {
|
||||||
override val layoutRes: Int = R.layout.item_repo_md2
|
override val layoutRes: Int = R.layout.item_repo_md2
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
@ -51,21 +51,21 @@ sealed class RepoItem(val item: Repo) : ObservableItem<RepoItem>() {
|
|||||||
override fun contentSameAs(other: RepoItem): Boolean = item == other.item
|
override fun contentSameAs(other: RepoItem): Boolean = item == other.item
|
||||||
override fun itemSameAs(other: RepoItem): Boolean = item.id == other.item.id
|
override fun itemSameAs(other: RepoItem): Boolean = item.id == other.item.id
|
||||||
|
|
||||||
class Update(item: Repo) : RepoItem(item) {
|
class Update(item: OnlineModule) : RepoItem(item) {
|
||||||
override val isUpdate get() = true
|
override val isUpdate get() = true
|
||||||
}
|
}
|
||||||
|
|
||||||
class Remote(item: Repo) : RepoItem(item) {
|
class Remote(item: OnlineModule) : RepoItem(item) {
|
||||||
override val isUpdate get() = false
|
override val isUpdate get() = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ModuleItem(val item: Module) : ObservableItem<ModuleItem>() {
|
class ModuleItem(val item: LocalModule) : ObservableItem<ModuleItem>() {
|
||||||
|
|
||||||
override val layoutRes = R.layout.item_module_md2
|
override val layoutRes = R.layout.item_module_md2
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var repo: Repo? = null
|
var repo: OnlineModule? = null
|
||||||
set(value) = set(value, field, { field = it }, BR.repo)
|
set(value) = set(value, field, { field = it }, BR.repo)
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
|
@ -9,10 +9,9 @@ import com.topjohnwu.magisk.arch.*
|
|||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.core.download.Subject
|
import com.topjohnwu.magisk.core.download.Subject
|
||||||
import com.topjohnwu.magisk.core.model.module.Module
|
import com.topjohnwu.magisk.core.model.module.LocalModule
|
||||||
import com.topjohnwu.magisk.core.tasks.RepoUpdater
|
import com.topjohnwu.magisk.core.tasks.RepoUpdater
|
||||||
import com.topjohnwu.magisk.data.database.RepoByNameDao
|
import com.topjohnwu.magisk.data.database.RepoDao
|
||||||
import com.topjohnwu.magisk.data.database.RepoByUpdatedDao
|
|
||||||
import com.topjohnwu.magisk.databinding.RvItem
|
import com.topjohnwu.magisk.databinding.RvItem
|
||||||
import com.topjohnwu.magisk.events.OpenReadmeEvent
|
import com.topjohnwu.magisk.events.OpenReadmeEvent
|
||||||
import com.topjohnwu.magisk.events.SelectModuleEvent
|
import com.topjohnwu.magisk.events.SelectModuleEvent
|
||||||
@ -44,8 +43,7 @@ import kotlin.math.roundToInt
|
|||||||
* */
|
* */
|
||||||
|
|
||||||
class ModuleViewModel(
|
class ModuleViewModel(
|
||||||
private val repoName: RepoByNameDao,
|
private val repoDB: RepoDao,
|
||||||
private val repoUpdated: RepoByUpdatedDao,
|
|
||||||
private val repoUpdater: RepoUpdater
|
private val repoUpdater: RepoUpdater
|
||||||
) : BaseViewModel(), Queryable {
|
) : BaseViewModel(), Queryable {
|
||||||
|
|
||||||
@ -117,12 +115,6 @@ class ModuleViewModel(
|
|||||||
// ---
|
// ---
|
||||||
|
|
||||||
private var refetch = false
|
private var refetch = false
|
||||||
private val dao
|
|
||||||
get() = when (Config.repoOrder) {
|
|
||||||
Config.Value.ORDER_DATE -> repoUpdated
|
|
||||||
Config.Value.ORDER_NAME -> repoName
|
|
||||||
else -> throw IllegalArgumentException()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
@ -186,7 +178,7 @@ class ModuleViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun loadInstalled() {
|
private suspend fun loadInstalled() {
|
||||||
val installed = Module.installed().map { ModuleItem(it) }
|
val installed = LocalModule.installed().map { ModuleItem(it) }
|
||||||
val diff = withContext(Dispatchers.Default) {
|
val diff = withContext(Dispatchers.Default) {
|
||||||
itemsInstalled.calculateDiff(installed)
|
itemsInstalled.calculateDiff(installed)
|
||||||
}
|
}
|
||||||
@ -197,11 +189,11 @@ class ModuleViewModel(
|
|||||||
val (updates, diff) = withContext(Dispatchers.IO) {
|
val (updates, diff) = withContext(Dispatchers.IO) {
|
||||||
itemsInstalled.forEach {
|
itemsInstalled.forEach {
|
||||||
launch {
|
launch {
|
||||||
it.repo = dao.getRepoById(it.item.id)
|
it.repo = repoDB.getModule(it.item.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val updates = itemsInstalled
|
val updates = itemsInstalled
|
||||||
.mapNotNull { dao.getUpdatableRepoById(it.item.id, it.item.versionCode) }
|
.mapNotNull { repoDB.getUpdatableModule(it.item.id, it.item.versionCode) }
|
||||||
.map { RepoItem.Update(it) }
|
.map { RepoItem.Update(it) }
|
||||||
val diff = itemsUpdatable.calculateDiff(updates)
|
val diff = itemsUpdatable.calculateDiff(updates)
|
||||||
return@withContext updates to diff
|
return@withContext updates to diff
|
||||||
@ -219,7 +211,7 @@ class ModuleViewModel(
|
|||||||
|
|
||||||
remoteJob = viewModelScope.launch {
|
remoteJob = viewModelScope.launch {
|
||||||
suspend fun loadRemoteDB(offset: Int) = withContext(Dispatchers.IO) {
|
suspend fun loadRemoteDB(offset: Int) = withContext(Dispatchers.IO) {
|
||||||
dao.getRepos(offset).map { RepoItem.Remote(it) }
|
repoDB.getModules(offset).map { RepoItem.Remote(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
isRemoteLoading = true
|
isRemoteLoading = true
|
||||||
@ -253,7 +245,7 @@ class ModuleViewModel(
|
|||||||
listOf()
|
listOf()
|
||||||
} else {
|
} else {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
dao.searchRepos(query, offset).map { RepoItem.Remote(it) }
|
repoDB.searchModules(query, offset).map { RepoItem.Remote(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user