From 4c6d748be316e19610915bc26eea8d2938f0cf68 Mon Sep 17 00:00:00 2001 From: Howard Wu <40033067+Howard20181@users.noreply.github.com> Date: Tue, 18 Oct 2022 13:54:59 +0800 Subject: [PATCH] Update updateLatestVersion after preference change (#2182) --- .../org/lsposed/manager/repo/RepoLoader.java | 115 +++++++++++------- .../manager/repo/model/OnlineModule.java | 4 +- .../manager/ui/fragment/RepoFragment.java | 5 +- .../manager/ui/fragment/RepoItemFragment.java | 4 +- .../manager/ui/fragment/SettingsFragment.java | 83 ++++++------- 5 files changed, 118 insertions(+), 93 deletions(-) diff --git a/app/src/main/java/org/lsposed/manager/repo/RepoLoader.java b/app/src/main/java/org/lsposed/manager/repo/RepoLoader.java index 5ed7a9c40d3..7da61bd2a9a 100644 --- a/app/src/main/java/org/lsposed/manager/repo/RepoLoader.java +++ b/app/src/main/java/org/lsposed/manager/repo/RepoLoader.java @@ -89,7 +89,7 @@ public boolean isRepoLoaded() { public static synchronized RepoLoader getInstance() { if (instance == null) { instance = new RepoLoader(); - App.getExecutorService().submit(instance::loadRemoteData); + App.getExecutorService().submit(() -> instance.loadLocalData(true)); } return instance; } @@ -97,53 +97,15 @@ public static synchronized RepoLoader getInstance() { synchronized public void loadRemoteData() { repoLoaded = false; try { - var response = App.getOkHttpClient().newCall(new Request.Builder() - .url(repoUrl + "modules.json") - .build()).execute(); + var response = App.getOkHttpClient().newCall(new Request.Builder().url(repoUrl + "modules.json").build()).execute(); if (response.isSuccessful()) { ResponseBody body = response.body(); if (body != null) { try { String bodyString = body.string(); - Gson gson = new Gson(); - Map modules = new HashMap<>(); - OnlineModule[] repoModules = gson.fromJson(bodyString, OnlineModule[].class); - Arrays.stream(repoModules).forEach(onlineModule -> modules.put(onlineModule.getName(), onlineModule)); - var channel = App.getPreferences().getString("update_channel", channels[0]); - Map versions = new ConcurrentHashMap<>(); - for (var module : repoModules) { - String release = module.getLatestRelease(); - if (channel.equals(channels[1]) && !(module.getLatestBetaRelease() != null && module.getLatestBetaRelease().isEmpty())) { - release = module.getLatestBetaRelease(); - } else if (channel.equals(channels[2])) { - if (!(module.getLatestSnapshotRelease() != null && module.getLatestSnapshotRelease().isEmpty())) - release = module.getLatestSnapshotRelease(); - else if (!(module.getLatestBetaRelease() != null && module.getLatestBetaRelease().isEmpty())) - release = module.getLatestBetaRelease(); - } - if (release == null || release.isEmpty()) continue; - var splits = release.split("-", 2); - if (splits.length < 2) continue; - long verCode; - String verName; - try { - verCode = Long.parseLong(splits[0]); - verName = splits[1]; - } catch (NumberFormatException ignored) { - continue; - } - String pkgName = module.getName(); - versions.put(pkgName, new ModuleVersion(verCode, verName)); - } - - latestVersion = versions; - onlineModules = modules; Files.write(repoFile, bodyString.getBytes(StandardCharsets.UTF_8)); - repoLoaded = true; - for (RepoListener listener : listeners) { - listener.onRepoLoaded(); - } + loadLocalData(false); } catch (Throwable t) { Log.e(App.TAG, Log.getStackTraceString(t)); for (RepoListener listener : listeners) { @@ -161,11 +123,78 @@ else if (!(module.getLatestBetaRelease() != null && module.getLatestBetaRelease( repoUrl = backupRepoUrl; loadRemoteData(); } + } + } + + synchronized public void loadLocalData(boolean updateRemoteRepo) { + repoLoaded = false; + try { + if (Files.notExists(repoFile)) { + loadRemoteData(); + updateRemoteRepo = false; + } + byte[] encoded = Files.readAllBytes(repoFile); + String bodyString = new String(encoded, StandardCharsets.UTF_8); + Gson gson = new Gson(); + Map modules = new HashMap<>(); + OnlineModule[] repoModules = gson.fromJson(bodyString, OnlineModule[].class); + Arrays.stream(repoModules).forEach(onlineModule -> modules.put(onlineModule.getName(), onlineModule)); + var channel = App.getPreferences().getString("update_channel", channels[0]); + updateLatestVersion(repoModules, channel); + onlineModules = modules; + } catch (Throwable t) { + Log.e(App.TAG, Log.getStackTraceString(t)); + for (RepoListener listener : listeners) { + listener.onThrowable(t); + } } finally { repoLoaded = true; + for (RepoListener listener : listeners) { + listener.onRepoLoaded(); + } + if (updateRemoteRepo) loadRemoteData(); } } + synchronized private void updateLatestVersion(OnlineModule[] onlineModules, String channel) { + repoLoaded = false; + Map versions = new ConcurrentHashMap<>(); + for (var module : onlineModules) { + String release = module.getLatestRelease(); + if (channel.equals(channels[1]) && module.getLatestBetaRelease() != null && !module.getLatestBetaRelease().isEmpty()) { + release = module.getLatestBetaRelease(); + } else if (channel.equals(channels[2])) { + if (module.getLatestSnapshotRelease() != null && !module.getLatestSnapshotRelease().isEmpty()) + release = module.getLatestSnapshotRelease(); + else if (module.getLatestBetaRelease() != null && !module.getLatestBetaRelease().isEmpty()) + release = module.getLatestBetaRelease(); + } + if (release == null || release.isEmpty()) continue; + var splits = release.split("-", 2); + if (splits.length < 2) continue; + long verCode; + String verName; + try { + verCode = Long.parseLong(splits[0]); + verName = splits[1]; + } catch (NumberFormatException ignored) { + continue; + } + String pkgName = module.getName(); + versions.put(pkgName, new ModuleVersion(verCode, verName)); + } + latestVersion = versions; + repoLoaded = true; + for (RepoListener listener : listeners) { + listener.onRepoLoaded(); + } + } + + public void updateLatestVersion(String channel) { + if (repoLoaded) + updateLatestVersion(onlineModules.keySet().parallelStream().map(onlineModules::get).toArray(OnlineModule[]::new), channel); + } + @Nullable public ModuleVersion getModuleLatestVersion(String packageName) { return repoLoaded ? latestVersion.getOrDefault(packageName, null) : null; @@ -207,9 +236,7 @@ public String getLatestReleaseTime(String packageName, String channel) { } public void loadRemoteReleases(String packageName) { - App.getOkHttpClient().newCall(new Request.Builder() - .url(String.format(repoUrl + "module/%s.json", packageName)) - .build()).enqueue(new Callback() { + App.getOkHttpClient().newCall(new Request.Builder().url(String.format(repoUrl + "module/%s.json", packageName)).build()).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { Log.e(App.TAG, call.request().url() + e.getMessage()); diff --git a/app/src/main/java/org/lsposed/manager/repo/model/OnlineModule.java b/app/src/main/java/org/lsposed/manager/repo/model/OnlineModule.java index e3fe31066dd..4f4ab436509 100644 --- a/app/src/main/java/org/lsposed/manager/repo/model/OnlineModule.java +++ b/app/src/main/java/org/lsposed/manager/repo/model/OnlineModule.java @@ -68,10 +68,10 @@ public class OnlineModule { private List releases = new ArrayList<>(); @SerializedName("betaReleases") @Expose - private List betaReleases = new ArrayList<>(); + private final List betaReleases = new ArrayList<>(); @SerializedName("snapshotReleases") @Expose - private List snapshotReleases = new ArrayList<>(); + private final List snapshotReleases = new ArrayList<>(); @SerializedName("readme") @Expose private String readme; diff --git a/app/src/main/java/org/lsposed/manager/ui/fragment/RepoFragment.java b/app/src/main/java/org/lsposed/manager/ui/fragment/RepoFragment.java index 5ef6d651b71..eeedd023792 100644 --- a/app/src/main/java/org/lsposed/manager/ui/fragment/RepoFragment.java +++ b/app/src/main/java/org/lsposed/manager/ui/fragment/RepoFragment.java @@ -293,8 +293,8 @@ public void onBindViewHolder(@NonNull RepoAdapter.ViewHolder holder, int positio holder.appPackageName.setText(module.getName()); Instant instant; channel = App.getPreferences().getString("update_channel", channels[0]); - - instant = Instant.parse(repoLoader.getLatestReleaseTime(module.getName(), channel)); + var latestReleaseTime = repoLoader.getLatestReleaseTime(module.getName(), channel); + instant = Instant.parse(latestReleaseTime != null ? latestReleaseTime : module.getLatestReleaseTime()); var formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT) .withLocale(App.getLocale()).withZone(ZoneId.systemDefault()); holder.publishedTime.setText(String.format(getString(R.string.module_repo_updated_time), formatter.format(instant))); @@ -356,7 +356,6 @@ public void setData(Collection modules) { int sort = App.getPreferences().getInt("repo_sort", 0); boolean upgradableFirst = App.getPreferences().getBoolean("upgradable_first", true); ConcurrentHashMap upgradable = new ConcurrentHashMap<>(); - fullList = modules.parallelStream().filter((onlineModule -> !onlineModule.isHide() && !onlineModule.getReleases().isEmpty())) .sorted((a, b) -> { if (upgradableFirst) { diff --git a/app/src/main/java/org/lsposed/manager/ui/fragment/RepoItemFragment.java b/app/src/main/java/org/lsposed/manager/ui/fragment/RepoItemFragment.java index 327d722372c..b882c553f74 100644 --- a/app/src/main/java/org/lsposed/manager/ui/fragment/RepoItemFragment.java +++ b/app/src/main/java/org/lsposed/manager/ui/fragment/RepoItemFragment.java @@ -384,9 +384,7 @@ public void loadItems() { var name = t.getName().toLowerCase(LocaleDelegate.getDefaultLocale()); return !name.startsWith("snapshot") && !name.startsWith("nightly"); }).collect(Collectors.toList()); - } else { - tmpList = releases; - } + } else tmpList = releases; runOnUiThread(() -> { items = tmpList; notifyDataSetChanged(); diff --git a/app/src/main/java/org/lsposed/manager/ui/fragment/SettingsFragment.java b/app/src/main/java/org/lsposed/manager/ui/fragment/SettingsFragment.java index c3e341e7609..27ca432cc14 100644 --- a/app/src/main/java/org/lsposed/manager/ui/fragment/SettingsFragment.java +++ b/app/src/main/java/org/lsposed/manager/ui/fragment/SettingsFragment.java @@ -36,7 +36,9 @@ import androidx.core.text.HtmlCompat; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; + import rikka.material.preference.MaterialSwitchPreference; + import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.color.DynamicColors; @@ -47,6 +49,7 @@ import org.lsposed.manager.R; import org.lsposed.manager.databinding.FragmentSettingsBinding; import org.lsposed.manager.receivers.LSPManagerServiceHolder; +import org.lsposed.manager.repo.RepoLoader; import org.lsposed.manager.ui.activity.MainActivity; import org.lsposed.manager.util.BackupUtils; import org.lsposed.manager.util.LangList; @@ -75,15 +78,12 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c setupToolbar(binding.toolbar, binding.clickView, R.string.Settings); binding.toolbar.setNavigationIcon(null); if (savedInstanceState == null) { - getChildFragmentManager().beginTransaction() - .add(R.id.setting_container, new PreferenceFragment()).commitNow(); + getChildFragmentManager().beginTransaction().add(R.id.setting_container, new PreferenceFragment()).commitNow(); } if (ConfigManager.isBinderAlive()) { - binding.toolbar.setSubtitle(String.format(LocaleDelegate.getDefaultLocale(), "%s (%d) - %s", - ConfigManager.getXposedVersionName(), ConfigManager.getXposedVersionCode(), ConfigManager.getApi())); + binding.toolbar.setSubtitle(String.format(LocaleDelegate.getDefaultLocale(), "%s (%d) - %s", ConfigManager.getXposedVersionName(), ConfigManager.getXposedVersionCode(), ConfigManager.getApi())); } else { - binding.toolbar.setSubtitle(String.format(LocaleDelegate.getDefaultLocale(), "%s (%d) - %s", - BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, getString(R.string.not_installed))); + binding.toolbar.setSubtitle(String.format(LocaleDelegate.getDefaultLocale(), "%s (%d) - %s", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, getString(R.string.not_installed))); } return binding.getRoot(); } @@ -98,30 +98,28 @@ public void onDestroyView() { public static class PreferenceFragment extends PreferenceFragmentCompat { private SettingsFragment parentFragment; - ActivityResultLauncher backupLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument("application/gzip"), - uri -> { - if (uri == null || parentFragment == null) return; - parentFragment.runAsync(() -> { - try { - BackupUtils.backup(uri); - } catch (Exception e) { - var text = App.getInstance().getString(R.string.settings_backup_failed2, e.getMessage()); - parentFragment.showHint(text, false); - } - }); - }); - ActivityResultLauncher restoreLauncher = registerForActivityResult(new ActivityResultContracts.OpenDocument(), - uri -> { - if (uri == null || parentFragment == null) return; - parentFragment.runAsync(() -> { - try { - BackupUtils.restore(uri); - } catch (Exception e) { - var text = App.getInstance().getString(R.string.settings_restore_failed2, e.getMessage()); - parentFragment.showHint(text, false); - } - }); - }); + ActivityResultLauncher backupLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument("application/gzip"), uri -> { + if (uri == null || parentFragment == null) return; + parentFragment.runAsync(() -> { + try { + BackupUtils.backup(uri); + } catch (Exception e) { + var text = App.getInstance().getString(R.string.settings_backup_failed2, e.getMessage()); + parentFragment.showHint(text, false); + } + }); + }); + ActivityResultLauncher restoreLauncher = registerForActivityResult(new ActivityResultContracts.OpenDocument(), uri -> { + if (uri == null || parentFragment == null) return; + parentFragment.runAsync(() -> { + try { + BackupUtils.restore(uri); + } catch (Exception e) { + var text = App.getInstance().getString(R.string.settings_restore_failed2, e.getMessage()); + parentFragment.showHint(text, false); + } + }); + }); @Override public void onAttach(@NonNull Context context) { @@ -148,8 +146,7 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { if (prefVerboseLogs != null) { prefVerboseLogs.setEnabled(!BuildConfig.DEBUG && installed); prefVerboseLogs.setChecked(!installed || !ConfigManager.isVerboseLogEnabled()); - prefVerboseLogs.setOnPreferenceChangeListener((preference, newValue) -> - ConfigManager.setVerboseLogEnabled(!(boolean) newValue)); + prefVerboseLogs.setOnPreferenceChangeListener((preference, newValue) -> ConfigManager.setVerboseLogEnabled(!(boolean) newValue)); } MaterialSwitchPreference prefDexObfuscate = findPreference("enable_dex_obfuscate"); @@ -157,8 +154,7 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { prefDexObfuscate.setEnabled(installed); prefDexObfuscate.setChecked(!installed || ConfigManager.isDexObfuscateEnabled()); prefDexObfuscate.setOnPreferenceChangeListener((preference, newValue) -> { - parentFragment.showHint(R.string.reboot_required, true, R.string.reboot, - v -> ConfigManager.reboot(false)); + parentFragment.showHint(R.string.reboot_required, true, R.string.reboot, v -> ConfigManager.reboot(false)); return ConfigManager.setDexObfuscateEnabled((boolean) newValue); }); } @@ -189,8 +185,7 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { backup.setOnPreferenceClickListener(preference -> { LocalDateTime now = LocalDateTime.now(); try { - backupLauncher.launch(String.format(LocaleDelegate.getDefaultLocale(), - "LSPosed_%s.lsp", now.toString())); + backupLauncher.launch(String.format(LocaleDelegate.getDefaultLocale(), "LSPosed_%s.lsp", now.toString())); return true; } catch (ActivityNotFoundException e) { parentFragment.showHint(R.string.enable_documentui, true); @@ -253,11 +248,9 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { if (prefShowHiddenIcons != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (ConfigManager.isBinderAlive()) { prefShowHiddenIcons.setEnabled(true); - prefShowHiddenIcons.setOnPreferenceChangeListener((preference, newValue) -> - ConfigManager.setHiddenIcon(!(boolean) newValue)); + prefShowHiddenIcons.setOnPreferenceChangeListener((preference, newValue) -> ConfigManager.setHiddenIcon(!(boolean) newValue)); } - prefShowHiddenIcons.setChecked(Settings.Global.getInt( - requireActivity().getContentResolver(), "show_hidden_icon_apps_enabled", 1) != 0); + prefShowHiddenIcons.setChecked(Settings.Global.getInt(requireActivity().getContentResolver(), "show_hidden_icon_apps_enabled", 1) != 0); } MaterialSwitchPreference prefFollowSystemAccent = findPreference("follow_system_accent"); @@ -299,7 +292,7 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { } language.setOnPreferenceChangeListener((preference, newValue) -> { var app = App.getInstance(); - var locale = App.getLocale((String)newValue); + var locale = App.getLocale((String) newValue); var res = app.getResources(); var config = res.getConfiguration(); config.setLocale(locale); @@ -332,6 +325,14 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { translation_contributors.setSummary(translators); } } + SimpleMenuPreference channel = findPreference("update_channel"); + if (channel != null) { + channel.setOnPreferenceChangeListener((preference, newValue) -> { + var repoLoader = RepoLoader.getInstance(); + repoLoader.updateLatestVersion(String.valueOf(newValue)); + return true; + }); + } } @NonNull