Update updateLatestVersion after preference change (#2182)

This commit is contained in:
Howard Wu 2022-10-18 13:54:59 +08:00 committed by GitHub
parent f4ce1b6ed2
commit 4c6d748be3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 118 additions and 93 deletions

View File

@ -89,7 +89,7 @@ public class RepoLoader {
public static synchronized RepoLoader getInstance() { public static synchronized RepoLoader getInstance() {
if (instance == null) { if (instance == null) {
instance = new RepoLoader(); instance = new RepoLoader();
App.getExecutorService().submit(instance::loadRemoteData); App.getExecutorService().submit(() -> instance.loadLocalData(true));
} }
return instance; return instance;
} }
@ -97,53 +97,15 @@ public class RepoLoader {
synchronized public void loadRemoteData() { synchronized public void loadRemoteData() {
repoLoaded = false; repoLoaded = false;
try { try {
var response = App.getOkHttpClient().newCall(new Request.Builder() var response = App.getOkHttpClient().newCall(new Request.Builder().url(repoUrl + "modules.json").build()).execute();
.url(repoUrl + "modules.json")
.build()).execute();
if (response.isSuccessful()) { if (response.isSuccessful()) {
ResponseBody body = response.body(); ResponseBody body = response.body();
if (body != null) { if (body != null) {
try { try {
String bodyString = body.string(); String bodyString = body.string();
Gson gson = new Gson();
Map<String, OnlineModule> 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<String, ModuleVersion> 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)); Files.write(repoFile, bodyString.getBytes(StandardCharsets.UTF_8));
repoLoaded = true; loadLocalData(false);
for (RepoListener listener : listeners) {
listener.onRepoLoaded();
}
} catch (Throwable t) { } catch (Throwable t) {
Log.e(App.TAG, Log.getStackTraceString(t)); Log.e(App.TAG, Log.getStackTraceString(t));
for (RepoListener listener : listeners) { for (RepoListener listener : listeners) {
@ -161,11 +123,78 @@ public class RepoLoader {
repoUrl = backupRepoUrl; repoUrl = backupRepoUrl;
loadRemoteData(); 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<String, OnlineModule> 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 { } finally {
repoLoaded = true; repoLoaded = true;
for (RepoListener listener : listeners) {
listener.onRepoLoaded();
}
if (updateRemoteRepo) loadRemoteData();
} }
} }
synchronized private void updateLatestVersion(OnlineModule[] onlineModules, String channel) {
repoLoaded = false;
Map<String, ModuleVersion> 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 @Nullable
public ModuleVersion getModuleLatestVersion(String packageName) { public ModuleVersion getModuleLatestVersion(String packageName) {
return repoLoaded ? latestVersion.getOrDefault(packageName, null) : null; return repoLoaded ? latestVersion.getOrDefault(packageName, null) : null;
@ -207,9 +236,7 @@ public class RepoLoader {
} }
public void loadRemoteReleases(String packageName) { public void loadRemoteReleases(String packageName) {
App.getOkHttpClient().newCall(new Request.Builder() App.getOkHttpClient().newCall(new Request.Builder().url(String.format(repoUrl + "module/%s.json", packageName)).build()).enqueue(new Callback() {
.url(String.format(repoUrl + "module/%s.json", packageName))
.build()).enqueue(new Callback() {
@Override @Override
public void onFailure(@NonNull Call call, @NonNull IOException e) { public void onFailure(@NonNull Call call, @NonNull IOException e) {
Log.e(App.TAG, call.request().url() + e.getMessage()); Log.e(App.TAG, call.request().url() + e.getMessage());

View File

@ -68,10 +68,10 @@ public class OnlineModule {
private List<Release> releases = new ArrayList<>(); private List<Release> releases = new ArrayList<>();
@SerializedName("betaReleases") @SerializedName("betaReleases")
@Expose @Expose
private List<Release> betaReleases = new ArrayList<>(); private final List<Release> betaReleases = new ArrayList<>();
@SerializedName("snapshotReleases") @SerializedName("snapshotReleases")
@Expose @Expose
private List<Release> snapshotReleases = new ArrayList<>(); private final List<Release> snapshotReleases = new ArrayList<>();
@SerializedName("readme") @SerializedName("readme")
@Expose @Expose
private String readme; private String readme;

View File

@ -293,8 +293,8 @@ public class RepoFragment extends BaseFragment implements RepoLoader.RepoListene
holder.appPackageName.setText(module.getName()); holder.appPackageName.setText(module.getName());
Instant instant; Instant instant;
channel = App.getPreferences().getString("update_channel", channels[0]); channel = App.getPreferences().getString("update_channel", channels[0]);
var latestReleaseTime = repoLoader.getLatestReleaseTime(module.getName(), channel);
instant = Instant.parse(repoLoader.getLatestReleaseTime(module.getName(), channel)); instant = Instant.parse(latestReleaseTime != null ? latestReleaseTime : module.getLatestReleaseTime());
var formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT) var formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
.withLocale(App.getLocale()).withZone(ZoneId.systemDefault()); .withLocale(App.getLocale()).withZone(ZoneId.systemDefault());
holder.publishedTime.setText(String.format(getString(R.string.module_repo_updated_time), formatter.format(instant))); holder.publishedTime.setText(String.format(getString(R.string.module_repo_updated_time), formatter.format(instant)));
@ -356,7 +356,6 @@ public class RepoFragment extends BaseFragment implements RepoLoader.RepoListene
int sort = App.getPreferences().getInt("repo_sort", 0); int sort = App.getPreferences().getInt("repo_sort", 0);
boolean upgradableFirst = App.getPreferences().getBoolean("upgradable_first", true); boolean upgradableFirst = App.getPreferences().getBoolean("upgradable_first", true);
ConcurrentHashMap<String, Boolean> upgradable = new ConcurrentHashMap<>(); ConcurrentHashMap<String, Boolean> upgradable = new ConcurrentHashMap<>();
fullList = modules.parallelStream().filter((onlineModule -> !onlineModule.isHide() && !onlineModule.getReleases().isEmpty())) fullList = modules.parallelStream().filter((onlineModule -> !onlineModule.isHide() && !onlineModule.getReleases().isEmpty()))
.sorted((a, b) -> { .sorted((a, b) -> {
if (upgradableFirst) { if (upgradableFirst) {

View File

@ -384,9 +384,7 @@ public class RepoItemFragment extends BaseFragment implements RepoLoader.RepoLis
var name = t.getName().toLowerCase(LocaleDelegate.getDefaultLocale()); var name = t.getName().toLowerCase(LocaleDelegate.getDefaultLocale());
return !name.startsWith("snapshot") && !name.startsWith("nightly"); return !name.startsWith("snapshot") && !name.startsWith("nightly");
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} else { } else tmpList = releases;
tmpList = releases;
}
runOnUiThread(() -> { runOnUiThread(() -> {
items = tmpList; items = tmpList;
notifyDataSetChanged(); notifyDataSetChanged();

View File

@ -36,7 +36,9 @@ import androidx.annotation.Nullable;
import androidx.core.text.HtmlCompat; import androidx.core.text.HtmlCompat;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import rikka.material.preference.MaterialSwitchPreference; import rikka.material.preference.MaterialSwitchPreference;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.color.DynamicColors; import com.google.android.material.color.DynamicColors;
@ -47,6 +49,7 @@ import org.lsposed.manager.ConfigManager;
import org.lsposed.manager.R; import org.lsposed.manager.R;
import org.lsposed.manager.databinding.FragmentSettingsBinding; import org.lsposed.manager.databinding.FragmentSettingsBinding;
import org.lsposed.manager.receivers.LSPManagerServiceHolder; import org.lsposed.manager.receivers.LSPManagerServiceHolder;
import org.lsposed.manager.repo.RepoLoader;
import org.lsposed.manager.ui.activity.MainActivity; import org.lsposed.manager.ui.activity.MainActivity;
import org.lsposed.manager.util.BackupUtils; import org.lsposed.manager.util.BackupUtils;
import org.lsposed.manager.util.LangList; import org.lsposed.manager.util.LangList;
@ -75,15 +78,12 @@ public class SettingsFragment extends BaseFragment {
setupToolbar(binding.toolbar, binding.clickView, R.string.Settings); setupToolbar(binding.toolbar, binding.clickView, R.string.Settings);
binding.toolbar.setNavigationIcon(null); binding.toolbar.setNavigationIcon(null);
if (savedInstanceState == null) { if (savedInstanceState == null) {
getChildFragmentManager().beginTransaction() getChildFragmentManager().beginTransaction().add(R.id.setting_container, new PreferenceFragment()).commitNow();
.add(R.id.setting_container, new PreferenceFragment()).commitNow();
} }
if (ConfigManager.isBinderAlive()) { if (ConfigManager.isBinderAlive()) {
binding.toolbar.setSubtitle(String.format(LocaleDelegate.getDefaultLocale(), "%s (%d) - %s", binding.toolbar.setSubtitle(String.format(LocaleDelegate.getDefaultLocale(), "%s (%d) - %s", ConfigManager.getXposedVersionName(), ConfigManager.getXposedVersionCode(), ConfigManager.getApi()));
ConfigManager.getXposedVersionName(), ConfigManager.getXposedVersionCode(), ConfigManager.getApi()));
} else { } else {
binding.toolbar.setSubtitle(String.format(LocaleDelegate.getDefaultLocale(), "%s (%d) - %s", binding.toolbar.setSubtitle(String.format(LocaleDelegate.getDefaultLocale(), "%s (%d) - %s", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, getString(R.string.not_installed)));
BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, getString(R.string.not_installed)));
} }
return binding.getRoot(); return binding.getRoot();
} }
@ -98,30 +98,28 @@ public class SettingsFragment extends BaseFragment {
public static class PreferenceFragment extends PreferenceFragmentCompat { public static class PreferenceFragment extends PreferenceFragmentCompat {
private SettingsFragment parentFragment; private SettingsFragment parentFragment;
ActivityResultLauncher<String> backupLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument("application/gzip"), ActivityResultLauncher<String> backupLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument("application/gzip"), uri -> {
uri -> { if (uri == null || parentFragment == null) return;
if (uri == null || parentFragment == null) return; parentFragment.runAsync(() -> {
parentFragment.runAsync(() -> { try {
try { BackupUtils.backup(uri);
BackupUtils.backup(uri); } catch (Exception e) {
} catch (Exception e) { var text = App.getInstance().getString(R.string.settings_backup_failed2, e.getMessage());
var text = App.getInstance().getString(R.string.settings_backup_failed2, e.getMessage()); parentFragment.showHint(text, false);
parentFragment.showHint(text, false); }
} });
}); });
}); ActivityResultLauncher<String[]> restoreLauncher = registerForActivityResult(new ActivityResultContracts.OpenDocument(), uri -> {
ActivityResultLauncher<String[]> restoreLauncher = registerForActivityResult(new ActivityResultContracts.OpenDocument(), if (uri == null || parentFragment == null) return;
uri -> { parentFragment.runAsync(() -> {
if (uri == null || parentFragment == null) return; try {
parentFragment.runAsync(() -> { BackupUtils.restore(uri);
try { } catch (Exception e) {
BackupUtils.restore(uri); var text = App.getInstance().getString(R.string.settings_restore_failed2, e.getMessage());
} catch (Exception e) { parentFragment.showHint(text, false);
var text = App.getInstance().getString(R.string.settings_restore_failed2, e.getMessage()); }
parentFragment.showHint(text, false); });
} });
});
});
@Override @Override
public void onAttach(@NonNull Context context) { public void onAttach(@NonNull Context context) {
@ -148,8 +146,7 @@ public class SettingsFragment extends BaseFragment {
if (prefVerboseLogs != null) { if (prefVerboseLogs != null) {
prefVerboseLogs.setEnabled(!BuildConfig.DEBUG && installed); prefVerboseLogs.setEnabled(!BuildConfig.DEBUG && installed);
prefVerboseLogs.setChecked(!installed || !ConfigManager.isVerboseLogEnabled()); prefVerboseLogs.setChecked(!installed || !ConfigManager.isVerboseLogEnabled());
prefVerboseLogs.setOnPreferenceChangeListener((preference, newValue) -> prefVerboseLogs.setOnPreferenceChangeListener((preference, newValue) -> ConfigManager.setVerboseLogEnabled(!(boolean) newValue));
ConfigManager.setVerboseLogEnabled(!(boolean) newValue));
} }
MaterialSwitchPreference prefDexObfuscate = findPreference("enable_dex_obfuscate"); MaterialSwitchPreference prefDexObfuscate = findPreference("enable_dex_obfuscate");
@ -157,8 +154,7 @@ public class SettingsFragment extends BaseFragment {
prefDexObfuscate.setEnabled(installed); prefDexObfuscate.setEnabled(installed);
prefDexObfuscate.setChecked(!installed || ConfigManager.isDexObfuscateEnabled()); prefDexObfuscate.setChecked(!installed || ConfigManager.isDexObfuscateEnabled());
prefDexObfuscate.setOnPreferenceChangeListener((preference, newValue) -> { prefDexObfuscate.setOnPreferenceChangeListener((preference, newValue) -> {
parentFragment.showHint(R.string.reboot_required, true, R.string.reboot, parentFragment.showHint(R.string.reboot_required, true, R.string.reboot, v -> ConfigManager.reboot(false));
v -> ConfigManager.reboot(false));
return ConfigManager.setDexObfuscateEnabled((boolean) newValue); return ConfigManager.setDexObfuscateEnabled((boolean) newValue);
}); });
} }
@ -189,8 +185,7 @@ public class SettingsFragment extends BaseFragment {
backup.setOnPreferenceClickListener(preference -> { backup.setOnPreferenceClickListener(preference -> {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
try { try {
backupLauncher.launch(String.format(LocaleDelegate.getDefaultLocale(), backupLauncher.launch(String.format(LocaleDelegate.getDefaultLocale(), "LSPosed_%s.lsp", now.toString()));
"LSPosed_%s.lsp", now.toString()));
return true; return true;
} catch (ActivityNotFoundException e) { } catch (ActivityNotFoundException e) {
parentFragment.showHint(R.string.enable_documentui, true); parentFragment.showHint(R.string.enable_documentui, true);
@ -253,11 +248,9 @@ public class SettingsFragment extends BaseFragment {
if (prefShowHiddenIcons != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (prefShowHiddenIcons != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (ConfigManager.isBinderAlive()) { if (ConfigManager.isBinderAlive()) {
prefShowHiddenIcons.setEnabled(true); prefShowHiddenIcons.setEnabled(true);
prefShowHiddenIcons.setOnPreferenceChangeListener((preference, newValue) -> prefShowHiddenIcons.setOnPreferenceChangeListener((preference, newValue) -> ConfigManager.setHiddenIcon(!(boolean) newValue));
ConfigManager.setHiddenIcon(!(boolean) newValue));
} }
prefShowHiddenIcons.setChecked(Settings.Global.getInt( prefShowHiddenIcons.setChecked(Settings.Global.getInt(requireActivity().getContentResolver(), "show_hidden_icon_apps_enabled", 1) != 0);
requireActivity().getContentResolver(), "show_hidden_icon_apps_enabled", 1) != 0);
} }
MaterialSwitchPreference prefFollowSystemAccent = findPreference("follow_system_accent"); MaterialSwitchPreference prefFollowSystemAccent = findPreference("follow_system_accent");
@ -299,7 +292,7 @@ public class SettingsFragment extends BaseFragment {
} }
language.setOnPreferenceChangeListener((preference, newValue) -> { language.setOnPreferenceChangeListener((preference, newValue) -> {
var app = App.getInstance(); var app = App.getInstance();
var locale = App.getLocale((String)newValue); var locale = App.getLocale((String) newValue);
var res = app.getResources(); var res = app.getResources();
var config = res.getConfiguration(); var config = res.getConfiguration();
config.setLocale(locale); config.setLocale(locale);
@ -332,6 +325,14 @@ public class SettingsFragment extends BaseFragment {
translation_contributors.setSummary(translators); 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 @NonNull