diff --git a/app/src/main/java/com/topjohnwu/magisk/data/network/GithubApiServices.kt b/app/src/main/java/com/topjohnwu/magisk/data/network/GithubApiServices.kt index b784e9e37..90675a4ab 100644 --- a/app/src/main/java/com/topjohnwu/magisk/data/network/GithubApiServices.kt +++ b/app/src/main/java/com/topjohnwu/magisk/data/network/GithubApiServices.kt @@ -1,5 +1,6 @@ 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 @@ -12,7 +13,11 @@ interface GithubApiServices { fun fetchRepos( @Query("page") page: Int, @Query("per_page") count: Int = REPOS_PER_PAGE, - @Query("sort") sortOrder: String = "pushed" + @Query("sort") sortOrder: String = when (Config.get(Config.Key.REPO_ORDER)) { + Config.Value.ORDER_DATE -> "updated" + Config.Value.ORDER_NAME -> "full_name" + else -> "updated" + } ): Single> companion object { diff --git a/app/src/main/java/com/topjohnwu/magisk/data/network/GithubRawApiServices.kt b/app/src/main/java/com/topjohnwu/magisk/data/network/GithubRawApiServices.kt index 98a6e41d0..0323a81bf 100644 --- a/app/src/main/java/com/topjohnwu/magisk/data/network/GithubRawApiServices.kt +++ b/app/src/main/java/com/topjohnwu/magisk/data/network/GithubRawApiServices.kt @@ -48,7 +48,7 @@ interface GithubRawApiServices { @GET("$MAGISK_MODULES/{$MODULE}/master/{$FILE}") @Streaming - fun fetchFile(id: String, file: String): Single + fun fetchFile(@Path(MODULE) id: String, @Path(FILE) file: String): Single //endregion diff --git a/app/src/main/java/com/topjohnwu/magisk/data/repository/ModuleRepository.kt b/app/src/main/java/com/topjohnwu/magisk/data/repository/ModuleRepository.kt index 70800a950..a47fafd08 100644 --- a/app/src/main/java/com/topjohnwu/magisk/data/repository/ModuleRepository.kt +++ b/app/src/main/java/com/topjohnwu/magisk/data/repository/ModuleRepository.kt @@ -6,6 +6,7 @@ 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.writeToFile import com.topjohnwu.magisk.utils.writeToString import io.reactivex.Single @@ -18,9 +19,16 @@ class ModuleRepository( ) { fun fetchModules() = fetchAllRepos() - .flattenAsFlowable { it } - .flatMapSingle { fetchProperties(it.name, it.updatedAtMillis) } - .toList() + .map { + it.mapNotNull { + runCatching { + fetchProperties(it.name, it.updatedAtMillis).blockingGet() + }.getOrNull() + } + } + + fun fetchInstalledModules() = Single.fromCallable { Utils.loadModulesLeanback() } + .map { it.values.toList() } fun fetchInstallFile(module: String) = apiRaw .fetchFile(module, FILE_INSTALL_SH) diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/BaseModule.java b/app/src/main/java/com/topjohnwu/magisk/model/entity/BaseModule.java index 20ccc4bec..286eab295 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/BaseModule.java +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/BaseModule.java @@ -36,9 +36,18 @@ public abstract class BaseModule implements Comparable, Parcelable { mVersionCode = p.readInt(); } + protected BaseModule(MagiskModule m) { + mId = m.getId(); + mName = m.getName(); + mVersion = m.getVersion(); + mAuthor = m.getAuthor(); + mDescription = m.getDescription(); + mVersionCode = Integer.parseInt(m.getVersionCode()); + } + @Override public int compareTo(@NonNull BaseModule module) { - return this.getName().toLowerCase().compareTo(module.getName().toLowerCase()); + return getName().toLowerCase().compareTo(module.getName().toLowerCase()); } @Override @@ -71,7 +80,9 @@ public abstract class BaseModule implements Comparable, Parcelable { return values; } - protected void parseProps(List props) { parseProps(props.toArray(new String[0])); } + protected void parseProps(List props) { + parseProps(props.toArray(new String[0])); + } protected void parseProps(String[] props) throws NumberFormatException { for (String line : props) { diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/GithubRepo.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/GithubRepo.kt index 838812829..a77b271dd 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/GithubRepo.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/GithubRepo.kt @@ -3,10 +3,14 @@ package com.topjohnwu.magisk.model.entity import com.squareup.moshi.Json import com.topjohnwu.magisk.utils.timeFormatStandard import com.topjohnwu.magisk.utils.toTime +import timber.log.Timber data class GithubRepo( @Json(name = "name") val name: String, @Json(name = "updated_at") val updatedAt: String ) { - val updatedAtMillis by lazy { updatedAt.toTime(timeFormatStandard) } + val updatedAtMillis by lazy { + updatedAt.toTime(timeFormatStandard) + .apply { Timber.i("$name updated @ $this ($updatedAt)") } + } } \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskModule.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskModule.kt index 5f5a8bede..035630042 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskModule.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskModule.kt @@ -19,6 +19,7 @@ interface MagiskModule : Parcelable { val author: String val version: String val versionCode: String + val description: String } @Entity(tableName = "repos") @@ -30,6 +31,7 @@ data class Repository( override val author: String, override val version: String, override val versionCode: String, + override val description: String, val lastUpdate: Long ) : MagiskModule @@ -40,6 +42,7 @@ data class Module( override val author: String, override val version: String, override val versionCode: String, + override val description: String, val path: String ) : MagiskModule @@ -57,6 +60,7 @@ fun Map.toModule(path: String): Module { author = get("author").orEmpty(), version = get("version").orEmpty(), versionCode = get("versionCode").orEmpty(), + description = get("description").orEmpty(), path = path ) } @@ -77,5 +81,6 @@ fun Map.toRepository(lastUpdate: Long) = Repository( author = get("author").orEmpty(), version = get("version").orEmpty(), versionCode = get("versionCode").orEmpty(), + description = get("description").orEmpty(), lastUpdate = lastUpdate ) \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/Repo.java b/app/src/main/java/com/topjohnwu/magisk/model/entity/Repo.java index 4932ae1ea..f72b45a62 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/Repo.java +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/Repo.java @@ -29,6 +29,11 @@ public class Repo extends BaseModule { mLastUpdate = new Date(p.readLong()); } + public Repo(Repository repo) { + super(repo); + mLastUpdate = new Date(repo.getLastUpdate()); + } + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override @@ -49,7 +54,7 @@ public class Repo extends BaseModule { } public void update() throws IllegalRepoException { - String props[] = Utils.dlString(getPropUrl()).split("\\n"); + String[] props = Utils.dlString(getPropUrl()).split("\\n"); try { parseProps(props); } catch (NumberFormatException e) { diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt index d4a722956..805d77bf3 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt @@ -8,6 +8,7 @@ import com.skoumal.teanity.util.KObservableField import com.topjohnwu.magisk.R import com.topjohnwu.magisk.model.entity.OldModule import com.topjohnwu.magisk.model.entity.Repo +import com.topjohnwu.magisk.model.entity.Repository import com.topjohnwu.magisk.utils.get import com.topjohnwu.magisk.utils.toggle @@ -55,6 +56,8 @@ class ModuleRvItem(val item: OldModule) : ComparableRvItem() { class RepoRvItem(val item: Repo) : ComparableRvItem() { + constructor(repo: Repository) : this(Repo(repo)) + override val layoutRes: Int = R.layout.item_repo override fun contentSameAs(other: RepoRvItem): Boolean = item.version == other.item.version diff --git a/app/src/main/java/com/topjohnwu/magisk/model/update/UpdateCheckService.java b/app/src/main/java/com/topjohnwu/magisk/model/update/UpdateCheckService.java deleted file mode 100644 index c51378d6b..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/model/update/UpdateCheckService.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.topjohnwu.magisk.model.update; - -import androidx.annotation.NonNull; -import androidx.work.ListenableWorker; - -import com.topjohnwu.magisk.App; -import com.topjohnwu.magisk.BuildConfig; -import com.topjohnwu.magisk.Config; -import com.topjohnwu.magisk.model.worker.DelegateWorker; -import com.topjohnwu.magisk.tasks.CheckUpdates; -import com.topjohnwu.magisk.view.Notifications; -import com.topjohnwu.superuser.Shell; - -public class UpdateCheckService extends DelegateWorker { - - @NonNull - @Override - public ListenableWorker.Result doWork() { - if (App.foreground() == null) { - Shell.getShell(); - CheckUpdates.check(this::onCheckDone); - } - return ListenableWorker.Result.success(); - } - - private void onCheckDone() { - if (BuildConfig.VERSION_CODE < Config.remoteManagerVersionCode) { - Notifications.managerUpdate(); - } else if (Config.magiskVersionCode < Config.remoteMagiskVersionCode) { - Notifications.magiskUpdate(); - } - } -} diff --git a/app/src/main/java/com/topjohnwu/magisk/model/update/UpdateCheckService.kt b/app/src/main/java/com/topjohnwu/magisk/model/update/UpdateCheckService.kt new file mode 100644 index 000000000..56d6d3a51 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/model/update/UpdateCheckService.kt @@ -0,0 +1,31 @@ +package com.topjohnwu.magisk.model.update + +import androidx.work.ListenableWorker +import com.topjohnwu.magisk.BuildConfig +import com.topjohnwu.magisk.Config +import com.topjohnwu.magisk.data.repository.MagiskRepository +import com.topjohnwu.magisk.model.entity.MagiskConfig +import com.topjohnwu.magisk.model.worker.DelegateWorker +import com.topjohnwu.magisk.utils.inject +import com.topjohnwu.magisk.view.Notifications + +class UpdateCheckService : DelegateWorker() { + + private val magiskRepo: MagiskRepository by inject() + + override fun doWork(): ListenableWorker.Result { + val config = runCatching { magiskRepo.fetchConfig().blockingGet() } + config.getOrNull()?.let { checkUpdates(it) } + return when { + config.isFailure -> ListenableWorker.Result.failure() + else -> ListenableWorker.Result.success() + } + } + + private fun checkUpdates(config: MagiskConfig) { + when { + BuildConfig.VERSION_CODE < config.app.versionCode.toIntOrNull() ?: -1 -> Notifications.managerUpdate() + Config.magiskVersionCode < config.magisk.versionCode.toIntOrNull() ?: -1 -> Notifications.magiskUpdate() + } + } +} diff --git a/app/src/main/java/com/topjohnwu/magisk/tasks/CheckUpdates.java b/app/src/main/java/com/topjohnwu/magisk/tasks/CheckUpdates.java deleted file mode 100644 index f2e91e61f..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/tasks/CheckUpdates.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.topjohnwu.magisk.tasks; - -import android.os.SystemClock; - -import com.topjohnwu.magisk.Config; -import com.topjohnwu.magisk.Const; -import com.topjohnwu.magisk.utils.Event; -import com.topjohnwu.net.Networking; -import com.topjohnwu.net.Request; -import com.topjohnwu.net.ResponseListener; -import com.topjohnwu.superuser.ShellUtils; -import com.topjohnwu.superuser.internal.UiThreadHandler; - -import org.json.JSONException; -import org.json.JSONObject; - -@Deprecated -public class CheckUpdates { - - private static Request getRequest() { - String url; - switch ((int) Config.get(Config.Key.UPDATE_CHANNEL)) { - case Config.Value.BETA_CHANNEL: - url = Const.Url.BETA_URL; - break; - case Config.Value.CUSTOM_CHANNEL: - url = Config.get(Config.Key.CUSTOM_CHANNEL); - break; - case Config.Value.CANARY_CHANNEL: - url = Const.Url.CANARY_URL; - break; - case Config.Value.CANARY_DEBUG_CHANNEL: - url = Const.Url.CANARY_DEBUG_URL; - break; - default: - url = Const.Url.STABLE_URL; - break; - } - return Networking.get(url); - } - - public static void check() { - check(null); - } - - public static void check(Runnable cb) { - Request request = getRequest(); - UpdateListener listener = new UpdateListener(cb); - if (ShellUtils.onMainThread()) { - request.getAsJSONObject(listener); - } else { - JSONObject json = request.execForJSONObject().getResult(); - if (json != null) - listener.onResponse(json); - } - } - - private static class UpdateListener implements ResponseListener { - - private final Runnable cb; - private final long start; - - UpdateListener(Runnable callback) { - cb = callback; - start = SystemClock.uptimeMillis(); - } - - private int getInt(JSONObject json, String name, int defValue) { - if (json == null) - return defValue; - try { - return json.getInt(name); - } catch (JSONException e) { - return defValue; - } - } - - private String getString(JSONObject json, String name, String defValue) { - if (json == null) - return defValue; - try { - return json.getString(name); - } catch (JSONException e) { - return defValue; - } - } - - private JSONObject getJson(JSONObject json, String name) { - try { - return json.getJSONObject(name); - } catch (JSONException e) { - return null; - } - } - - @Override - public void onResponse(JSONObject json) { - JSONObject magisk = getJson(json, "magisk"); - Config.remoteMagiskVersionCode = getInt(magisk, "versionCode", -1); - - if ((int) Config.get(Config.Key.UPDATE_CHANNEL) == Config.Value.DEFAULT_CHANNEL) { - if (Config.magiskVersionCode > Config.remoteMagiskVersionCode) { - // If we are newer than current stable channel, switch to beta - Config.set(Config.Key.UPDATE_CHANNEL, Config.Value.BETA_CHANNEL); - check(cb); - return; - } else { - Config.set(Config.Key.UPDATE_CHANNEL, Config.Value.STABLE_CHANNEL); - } - } - - Config.remoteMagiskVersionString = getString(magisk, "version", null); - Config.magiskLink = getString(magisk, "link", null); - Config.magiskNoteLink = getString(magisk, "note", null); - Config.magiskMD5 = getString(magisk, "md5", null); - - JSONObject manager = getJson(json, "app"); - Config.remoteManagerVersionString = getString(manager, "version", null); - Config.remoteManagerVersionCode = getInt(manager, "versionCode", -1); - Config.managerLink = getString(manager, "link", null); - Config.managerNoteLink = getString(manager, "note", null); - - JSONObject uninstaller = getJson(json, "uninstaller"); - Config.uninstallerLink = getString(uninstaller, "link", null); - - UiThreadHandler.handler.postAtTime(() -> Event.trigger(Event.UPDATE_CHECK_DONE), - start + 1000 /* Add artificial delay to let UI behave correctly */); - - if (cb != null) - cb.run(); - } - } -} diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt b/app/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt index d3f862447..698a0417c 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt @@ -6,7 +6,6 @@ import android.text.TextUtils import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import com.topjohnwu.magisk.* -import com.topjohnwu.magisk.tasks.CheckUpdates import com.topjohnwu.magisk.tasks.UpdateRepos import com.topjohnwu.magisk.utils.LocaleManager import com.topjohnwu.magisk.utils.Utils @@ -59,7 +58,7 @@ open class SplashActivity : AppCompatActivity() { // Schedule periodic update checks Utils.scheduleUpdateCheck() - CheckUpdates.check() + //CheckUpdates.check() // Setup shortcuts Shortcuts.setup(this) diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt index 180b4091f..a360330e8 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt @@ -10,28 +10,22 @@ import com.skoumal.teanity.util.DiffObservableList 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.model.entity.OldModule -import com.topjohnwu.magisk.model.entity.Repo +import com.topjohnwu.magisk.data.repository.ModuleRepository import com.topjohnwu.magisk.model.entity.recycler.ModuleRvItem import com.topjohnwu.magisk.model.entity.recycler.RepoRvItem import com.topjohnwu.magisk.model.entity.recycler.SectionRvItem import com.topjohnwu.magisk.model.events.InstallModuleEvent 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.Event -import com.topjohnwu.magisk.utils.Utils import com.topjohnwu.magisk.utils.toSingle import com.topjohnwu.magisk.utils.update -import io.reactivex.Single import io.reactivex.disposables.Disposable import me.tatarka.bindingcollectionadapter2.OnItemBind class ModuleViewModel( - private val repoDatabase: RepoDatabaseHelper, - private val resources: Resources + private val resources: Resources, + private val moduleRepo: ModuleRepository ) : MagiskViewModel() { val query = KObservableField("") @@ -52,36 +46,15 @@ class ModuleViewModel( queryDisposable?.dispose() queryDisposable = query() } - Event.register(this) refresh() } - override fun getListeningEvents(): IntArray { - return intArrayOf(Event.MODULE_LOAD_DONE, Event.REPO_LOAD_DONE) - } - - override fun onEvent(event: Int) = when (event) { - Event.MODULE_LOAD_DONE -> updateModules(Event.getResult(event)) - Event.REPO_LOAD_DONE -> updateRepos() - else -> Unit - } - fun fabPressed() = OpenFilePickerEvent().publish() fun repoPressed(item: RepoRvItem) = OpenChangelogEvent(item.item).publish() fun downloadPressed(item: RepoRvItem) = InstallModuleEvent(item.item).publish() fun refresh() { - state = State.LOADING - Utils.loadModules(true) - UpdateRepos().exec(true) - } - - private fun updateModules(result: Map) = result.values - .map { ModuleRvItem(it) } - .let { itemsInstalled.update(it) } - - internal fun updateRepos() { - Single.fromCallable { repoDatabase.repoCursor.toList { Repo(it) } } + moduleRepo.fetchModules() .flattenAsFlowable { it } .map { RepoRvItem(it) } .toList() @@ -89,7 +62,13 @@ class ModuleViewModel( .flatMap { queryRaw() } .applyViewModel(this) .subscribeK { itemsRemote.update(it.first, it.second) } - .add() + + moduleRepo.fetchInstalledModules() + .flattenAsFlowable { it } + .map { ModuleRvItem(it) } + .toList() + .map { it to itemsInstalled.calculateDiff(it) } + .subscribeK { itemsInstalled.update(it.first, it.second) } } private fun query() = queryRaw() diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/module/ReposFragment.kt b/app/src/main/java/com/topjohnwu/magisk/ui/module/ReposFragment.kt index 51b6d8830..4cc750e68 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/module/ReposFragment.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/module/ReposFragment.kt @@ -56,7 +56,7 @@ class ReposFragment : MagiskFragment(), Config.get(Config.Key.REPO_ORDER)!! ) { d, which -> Config.set(Config.Key.REPO_ORDER, which) - viewModel.updateRepos() + viewModel.refresh() d.dismiss() }.show() } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.java b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.java index 90faae656..dbc1f8991 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.java @@ -12,7 +12,6 @@ import com.topjohnwu.magisk.BuildConfig; import com.topjohnwu.magisk.Config; import com.topjohnwu.magisk.Const; import com.topjohnwu.magisk.R; -import com.topjohnwu.magisk.tasks.CheckUpdates; import com.topjohnwu.magisk.ui.base.BasePreferenceFragment; import com.topjohnwu.magisk.utils.DownloadApp; import com.topjohnwu.magisk.utils.Event; @@ -218,7 +217,7 @@ public class SettingsFragment extends BasePreferenceFragment { break; case Config.Key.UPDATE_CHANNEL: case Config.Key.CUSTOM_CHANNEL: - CheckUpdates.check(); + //CheckUpdates.check(); break; case Config.Key.CHECK_UPDATES: Utils.scheduleUpdateCheck(); diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index 9ae151e8c..843d6469d 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -27,6 +27,7 @@ import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; +import androidx.annotation.WorkerThread; import androidx.work.Constraints; import androidx.work.ExistingPeriodicWorkPolicy; import androidx.work.NetworkType; @@ -84,22 +85,16 @@ public class Utils { .replace("#", "").replace("@", "").replace("\\", "_"); } + @Deprecated public static void loadModules() { loadModules(true); } + @Deprecated public static void loadModules(boolean async) { Event.reset(Event.MODULE_LOAD_DONE); Runnable run = () -> { - Map moduleMap = new ValueSortedMap<>(); - SuFile path = new SuFile(Const.MAGISK_PATH); - SuFile[] modules = path.listFiles( - (file, name) -> !name.equals("lost+found") && !name.equals(".core")); - for (SuFile file : modules) { - if (file.isFile()) continue; - OldModule module = new OldModule(Const.MAGISK_PATH + "/" + file.getName()); - moduleMap.put(module.getId(), module); - } + Map moduleMap = loadModulesLeanback(); Event.trigger(Event.MODULE_LOAD_DONE, moduleMap); }; if (async) @@ -108,6 +103,21 @@ public class Utils { run.run(); } + @WorkerThread + public static Map loadModulesLeanback() { + final Map moduleMap = new ValueSortedMap<>(); + final SuFile path = new SuFile(Const.MAGISK_PATH); + final SuFile[] modules = path.listFiles((file, name) -> + !name.equals("lost+found") && !name.equals(".core") + ); + for (SuFile file : modules) { + if (file.isFile()) continue; + OldModule module = new OldModule(Const.MAGISK_PATH + "/" + file.getName()); + moduleMap.put(module.getId(), module); + } + return moduleMap; + } + public static boolean showSuperUser() { return Shell.rootAccess() && (Const.USER_ID == 0 || (int) Config.get(Config.Key.SU_MULTIUSER_MODE) != diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/XTime.kt b/app/src/main/java/com/topjohnwu/magisk/utils/XTime.kt index b2588a540..3c4bf54ca 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/XTime.kt +++ b/app/src/main/java/com/topjohnwu/magisk/utils/XTime.kt @@ -14,5 +14,5 @@ fun String.toTime(format: SimpleDateFormat) = try { } private val locale get() = Locale.getDefault() -val timeFormatFull by lazy { SimpleDateFormat("YYYY/MM/DD_HH:mm:ss", locale) } -val timeFormatStandard by lazy { SimpleDateFormat("YYYY-MM-DD'T'HH:mm:ss'Z'", locale) } \ No newline at end of file +val timeFormatFull by lazy { SimpleDateFormat("yyyy/MM/dd_HH:mm:ss", locale) } +val timeFormatStandard by lazy { SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", locale) } \ No newline at end of file