diff --git a/app/src/main/java/com/fox2code/mmm/MainActivity.java b/app/src/main/java/com/fox2code/mmm/MainActivity.java index 9e96bb8..011b846 100644 --- a/app/src/main/java/com/fox2code/mmm/MainActivity.java +++ b/app/src/main/java/com/fox2code/mmm/MainActivity.java @@ -26,7 +26,7 @@ import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.ActionBar; import androidx.appcompat.widget.SearchView; import androidx.cardview.widget.CardView; import androidx.core.app.ActivityCompat; @@ -52,6 +52,7 @@ import com.fox2code.mmm.utils.BlurUtils; import com.fox2code.mmm.utils.ExternalHelper; import com.fox2code.mmm.utils.Http; import com.fox2code.mmm.utils.IntentHelper; +import com.google.android.material.button.MaterialButton; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.materialswitch.MaterialSwitch; import com.google.android.material.progressindicator.LinearProgressIndicator; @@ -128,10 +129,12 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe } BackgroundUpdateChecker.onMainActivityCreate(this); super.onCreate(savedInstanceState); - this.setActionBarExtraMenuButton(R.drawable.ic_baseline_settings_24, v -> { - IntentHelper.startActivity(this, SettingsActivity.class); - return true; - }, R.string.pref_category_settings); + if (!MainApplication.getSharedPreferences().getBoolean("first_run", true)) { + this.setActionBarExtraMenuButton(R.drawable.ic_baseline_settings_24, v -> { + IntentHelper.startActivity(this, SettingsActivity.class); + return true; + }, R.string.pref_category_settings); + } setContentView(R.layout.activity_main); this.setTitle(R.string.app_name); this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); @@ -740,53 +743,47 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe Log.i("SetupWizard", "First launch: " + firstLaunch); if (firstLaunch) { doSetupNowRunning = true; - // Show setup box - runOnUiThread(() -> { - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this); - builder.setCancelable(false); - builder.setTitle(R.string.setup_title); - // Create a view from R.xml.setup_box - View view = getLayoutInflater().inflate(R.layout.setup_box, null); - builder.setView(view); - // For sdk >= 31, use MaterialSwitch instead of MaterialSwitch - // For now, we'll just have the positive button save the preferences and dismiss the dialog - builder.setPositiveButton(R.string.setup_button, (dialog, which) -> { - // Set the preferences and pref_first_launch to false - prefs.edit().putBoolean("first_launch", false).putBoolean("pref_background_update_check", ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_background_update_check))).isChecked()).putBoolean("pref_crash_reporting", ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_crash_reporting))).isChecked()).putBoolean("pref_androidacy_repo_enabled", ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_androidacy_repo))).isChecked()).putBoolean("pref_magisk_alt_repo_enabled", ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_magisk_alt_repo))).isChecked()).commit(); - // For debug builds, log the preferences - if (BuildConfig.DEBUG) { - Log.i("SetupWizard", "First launch: " + prefs.getBoolean("first_launch", true)); - Log.i("SetupWizard", "Background update check: " + prefs.getBoolean("pref_background_update_check", false)); - Log.i("SetupWizard", "Crash reporting: " + prefs.getBoolean("pref_crash_reporting", false)); - Log.i("SetupWizard", "Androidacy repo: " + prefs.getBoolean("pref_androidacy_repo_enabled", false)); - Log.i("SetupWizard", "Magisk alt repo: " + prefs.getBoolean("pref_magisk_alt_repo_enabled", false)); - } - dialog.dismiss(); - // Sleep for 100ms. Who knows, it might fix it? - try { - Thread.sleep(750); - } catch (InterruptedException e) { - e.printStackTrace(); - } - doSetupRestarting = true; - // Restart the app - Intent intent = new Intent(this, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - finish(); - startActivity(intent); - }); - builder.setNegativeButton(R.string.setup_button_skip, (dialog, which) -> { - MainApplication.getSharedPreferences().edit().putBoolean("first_launch", false).commit(); - dialog.dismiss(); - ensurePermissions(); - }); - builder.show(); - // Set the switches appropriately - ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_background_update_check))).setChecked(BuildConfig.ENABLE_AUTO_UPDATER); - ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_crash_reporting))).setChecked(BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING); - // Repos are a little harder, as the enabled_repos build config is an arraylist - ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_androidacy_repo))).setChecked(BuildConfig.ENABLED_REPOS.contains("androidacy_repo")); - ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_magisk_alt_repo))).setChecked(BuildConfig.ENABLED_REPOS.contains("magisk_alt_repo")); + // Show setup box. Put the setup_box in the main activity layout + View view = getLayoutInflater().inflate(R.layout.setup_box, null); + // Make the setup_box linear layout the sole child of the root_container constraint layout + setContentView(view); + // Handle action bar. Set it to setup_title and make it visible + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setTitle(R.string.app_name); + // Set solid color background + actionBar.show(); + } + ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_background_update_check))).setChecked(BuildConfig.ENABLE_AUTO_UPDATER); + ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_crash_reporting))).setChecked(BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING); + // Repos are a little harder, as the enabled_repos build config is an arraylist + ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_androidacy_repo))).setChecked(BuildConfig.ENABLED_REPOS.contains("androidacy_repo")); + ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_magisk_alt_repo))).setChecked(BuildConfig.ENABLED_REPOS.contains("magisk_alt_repo")); + // Set up the buttons + // Cancel button + MaterialButton cancelButton = view.findViewById(R.id.setup_cancel); + cancelButton.setText(R.string.cancel); + cancelButton.setOnClickListener(v -> { + // Set first launch to false and finish the activity + prefs.edit().putBoolean("first_launch", false).commit(); + finish(); + }); + // Setup button + MaterialButton setupButton = view.findViewById(R.id.setup_continue); + setupButton.setText(R.string.setup_button); + setupButton.setOnClickListener(v -> { + // Set first launch to false + prefs.edit().putBoolean("first_launch", false).commit(); + // Set the background update check pref + prefs.edit().putBoolean("pref_background_update_check", ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_background_update_check))).isChecked()).commit(); + // Set the crash reporting pref + prefs.edit().putBoolean("pref_crash_reporting", ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_crash_reporting))).isChecked()).commit(); + // Set the repos + // first pref_magisk_alt_repo_enabled then pref_androidacy_repo_enabled + prefs.edit().putBoolean("pref_magisk_alt_repo_enabled", ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_magisk_alt_repo))).isChecked()).commit(); + prefs.edit().putBoolean("pref_androidacy_repo_enabled", ((MaterialSwitch) Objects.requireNonNull(view.findViewById(R.id.setup_androidacy_repo))).isChecked()).commit(); + // Finish the activity + finish(); }); } else { ensurePermissions(); diff --git a/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java b/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java index 5f79d11..c97c345 100644 --- a/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java +++ b/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java @@ -1,11 +1,13 @@ package com.fox2code.mmm.background; +import android.Manifest; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; -import android.os.Build; +import android.content.pm.PackageManager; import androidx.annotation.NonNull; +import androidx.core.app.ActivityCompat; import androidx.core.app.NotificationChannelCompat; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; @@ -31,46 +33,30 @@ import java.util.Random; import java.util.concurrent.TimeUnit; public class BackgroundUpdateChecker extends Worker { - private static boolean easterEggActive = false; - static final Object lock = new Object(); // Avoid concurrency issues public static final String NOTIFICATION_CHANNEL_ID = "background_update"; public static final int NOTIFICATION_ID = 1; + static final Object lock = new Object(); // Avoid concurrency issues + private static boolean easterEggActive = false; - public BackgroundUpdateChecker(@NonNull Context context, - @NonNull WorkerParameters workerParams) { + public BackgroundUpdateChecker(@NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); } - @NonNull - @Override - public Result doWork() { - if (!NotificationManagerCompat.from(this.getApplicationContext()).areNotificationsEnabled() - || !MainApplication.isBackgroundUpdateCheckEnabled()) return Result.success(); - synchronized (lock) { - doCheck(this.getApplicationContext()); - } - return Result.success(); - } - static void doCheck(Context context) { Thread.currentThread().setPriority(2); ModuleManager.getINSTANCE().scanAsync(); RepoManager.getINSTANCE().update(null); ModuleManager.getINSTANCE().runAfterScan(() -> { int moduleUpdateCount = 0; - HashMap repoModules = - RepoManager.getINSTANCE().getModules(); - for (LocalModuleInfo localModuleInfo : - ModuleManager.getINSTANCE().getModules().values()) { - if ("twrp-keep".equals(localModuleInfo.id)) continue; + HashMap repoModules = RepoManager.getINSTANCE().getModules(); + for (LocalModuleInfo localModuleInfo : ModuleManager.getINSTANCE().getModules().values()) { + if ("twrp-keep".equals(localModuleInfo.id)) + continue; RepoModule repoModule = repoModules.get(localModuleInfo.id); localModuleInfo.checkModuleUpdate(); - if (localModuleInfo.updateVersionCode > localModuleInfo.versionCode && - !PropUtils.isNullString(localModuleInfo.updateVersion)) { + if (localModuleInfo.updateVersionCode > localModuleInfo.versionCode && !PropUtils.isNullString(localModuleInfo.updateVersion)) { moduleUpdateCount++; - } else if (repoModule != null && - repoModule.moduleInfo.versionCode > localModuleInfo.versionCode && - !PropUtils.isNullString(repoModule.moduleInfo.version)) { + } else if (repoModule != null && repoModule.moduleInfo.versionCode > localModuleInfo.versionCode && !PropUtils.isNullString(repoModule.moduleInfo.version)) { moduleUpdateCount++; } } @@ -81,43 +67,39 @@ public class BackgroundUpdateChecker extends Worker { } public static void postNotification(Context context, int updateCount) { - if (!easterEggActive) easterEggActive = new Random().nextInt(100) <= updateCount; - NotificationCompat.Builder builder = new NotificationCompat.Builder( - context, NOTIFICATION_CHANNEL_ID) - .setContentTitle(context.getString(easterEggActive ? - R.string.notification_update_title_easter_egg : - R.string.notification_update_title) - .replace("%i", String.valueOf(updateCount))) - .setContentText(context.getString(R.string.notification_update_subtitle)) - .setSmallIcon(R.drawable.ic_baseline_extension_24) - .setPriority(NotificationCompat.PRIORITY_HIGH) - .setContentIntent(PendingIntent.getActivity(context, 0, - new Intent(context, MainActivity.class).setFlags( - Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK), - Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? - PendingIntent.FLAG_IMMUTABLE : 0)).setAutoCancel(true); + if (!easterEggActive) + easterEggActive = new Random().nextInt(100) <= updateCount; + NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID).setContentTitle(context.getString(easterEggActive ? R.string.notification_update_title_easter_egg : R.string.notification_update_title).replace("%i", String.valueOf(updateCount))).setContentText(context.getString(R.string.notification_update_subtitle)).setSmallIcon(R.drawable.ic_baseline_extension_24).setPriority(NotificationCompat.PRIORITY_HIGH).setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK), PendingIntent.FLAG_IMMUTABLE)).setAutoCancel(true); + if (ActivityCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { + return; + } NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, builder.build()); } public static void onMainActivityCreate(Context context) { - NotificationManagerCompat notificationManagerCompat = - NotificationManagerCompat.from(context); - notificationManagerCompat.createNotificationChannel( - new NotificationChannelCompat.Builder(NOTIFICATION_CHANNEL_ID, - NotificationManagerCompat.IMPORTANCE_HIGH).setShowBadge(true) - .setName(context.getString(R.string.notification_update_pref)).build()); + // Refuse to run if first_launch pref is not false + if (MainApplication.getSharedPreferences().getBoolean("first_launch", true)) + return; + NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context); + notificationManagerCompat.createNotificationChannel(new NotificationChannelCompat.Builder(NOTIFICATION_CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_HIGH).setShowBadge(true).setName(context.getString(R.string.notification_update_pref)).build()); notificationManagerCompat.cancel(BackgroundUpdateChecker.NOTIFICATION_ID); BackgroundUpdateChecker.easterEggActive = false; - WorkManager.getInstance(context).enqueueUniquePeriodicWork("background_checker", - ExistingPeriodicWorkPolicy.REPLACE, new PeriodicWorkRequest.Builder( - BackgroundUpdateChecker.class, 6, TimeUnit.HOURS) - .setConstraints(new Constraints.Builder().setRequiresBatteryNotLow(true) - .setRequiredNetworkType(NetworkType.UNMETERED).build()).build()); + WorkManager.getInstance(context).enqueueUniquePeriodicWork("background_checker", ExistingPeriodicWorkPolicy.REPLACE, new PeriodicWorkRequest.Builder(BackgroundUpdateChecker.class, 6, TimeUnit.HOURS).setConstraints(new Constraints.Builder().setRequiresBatteryNotLow(true).setRequiredNetworkType(NetworkType.UNMETERED).build()).build()); } public static void onMainActivityResume(Context context) { - NotificationManagerCompat.from(context).cancel( - BackgroundUpdateChecker.NOTIFICATION_ID); + NotificationManagerCompat.from(context).cancel(BackgroundUpdateChecker.NOTIFICATION_ID); BackgroundUpdateChecker.easterEggActive = false; } + + @NonNull + @Override + public Result doWork() { + if (!NotificationManagerCompat.from(this.getApplicationContext()).areNotificationsEnabled() || !MainApplication.isBackgroundUpdateCheckEnabled()) + return Result.success(); + synchronized (lock) { + doCheck(this.getApplicationContext()); + } + return Result.success(); + } } diff --git a/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java b/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java index 3375c60..f5d92c2 100644 --- a/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java +++ b/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java @@ -30,7 +30,6 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashMap; @@ -245,13 +244,6 @@ public final class RepoManager extends SyncManager { if (!repoUpdaters[i].repoData.isEnabled()) { if (BuildConfig.DEBUG) Log.i("RepoManager", "Skipping disabled repo: " + repoUpdaters[i].repoData.getName()); - // Remove the repo from the list - try { - this.repoData.remove(repoUpdaters[i].repoData.getUrl()); - } catch ( - NoSuchAlgorithmException e) { - e.printStackTrace(); - } continue; } List repoModules = repoUpdaters[i].toUpdate(); diff --git a/app/src/main/java/com/fox2code/mmm/repo/RepoUpdater.java b/app/src/main/java/com/fox2code/mmm/repo/RepoUpdater.java index 76abda3..f9f9719 100644 --- a/app/src/main/java/com/fox2code/mmm/repo/RepoUpdater.java +++ b/app/src/main/java/com/fox2code/mmm/repo/RepoUpdater.java @@ -41,13 +41,6 @@ public class RepoUpdater { return 0; } this.indexRaw = Http.doHttpGet(this.repoData.getUrl(), false); - // Ensure it's a valid json and response code is 200 - /*if (Arrays.hashCode(this.indexRaw) == 0) { - this.indexRaw = null; - this.toUpdate = Collections.emptyList(); - this.toApply = this.repoData.moduleHashMap.values(); - return 0; - }*/ this.toUpdate = this.repoData.populate(new JSONObject( new String(this.indexRaw, StandardCharsets.UTF_8))); // Since we reuse instances this should work diff --git a/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java b/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java index e75ac46..eb70bed 100644 --- a/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java +++ b/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java @@ -117,7 +117,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { } int maxCpuFreq = freqResolved == 0 ? -1 : (int) Math.ceil(totalCpuFreq / (float) freqResolved); - if (androidVersion < 21 || cpuCount <= 2 || memoryClass <= 100 || cpuCount <= 4 && maxCpuFreq != -1 && maxCpuFreq <= 1250 || cpuCount <= 4 && maxCpuFreq <= 1600 && memoryClass <= 128 && androidVersion <= 21 || cpuCount <= 4 && maxCpuFreq <= 1300 && memoryClass <= 128 && androidVersion <= 24) { + if (androidVersion < 21 || cpuCount <= 2 || memoryClass <= 100 || cpuCount <= 4 && maxCpuFreq != -1 && maxCpuFreq <= 1250 || cpuCount <= 4 && maxCpuFreq <= 1600 && memoryClass <= 128 && androidVersion == 21 || cpuCount <= 4 && maxCpuFreq <= 1300 && memoryClass <= 128 && androidVersion <= 24) { devicePerformanceClass = PERFORMANCE_CLASS_LOW; } else if (cpuCount < 8 || memoryClass <= 160 || maxCpuFreq != -1 && maxCpuFreq <= 2050 || maxCpuFreq == -1 && cpuCount == 8 && androidVersion <= 23) { devicePerformanceClass = PERFORMANCE_CLASS_AVERAGE; @@ -950,14 +950,19 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { private void setRepoData(final RepoData repoData, String preferenceName) { ClipboardManager clipboard = (ClipboardManager) requireContext().getSystemService(Context.CLIPBOARD_SERVICE); - if (repoData == null || repoData.isForceHide()) { - hideRepoData(preferenceName); - return; - } Preference preference = findPreference(preferenceName); if (preference == null) return; - preference.setVisible(true); - preference.setTitle(repoData.getName()); + if (!preferenceName.contains("androidacy") && !preferenceName.contains("magisk_alt_repo")) { + if (BuildConfig.DEBUG) { + Log.i(TAG, "Setting preference " + preferenceName + " because it is not the Androidacy repo or the Magisk Alt Repo"); + } + if (repoData == null || repoData.isForceHide()) { + hideRepoData(preferenceName); + return; + } + preference.setTitle(repoData.getName()); + preference.setVisible(true); + } preference = findPreference(preferenceName + "_enabled"); if (preference != null) { // Handle custom repo separately @@ -971,6 +976,8 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { preference.setTitle(repoData.isEnabled() ? R.string.repo_enabled : R.string.repo_disabled); preference.setOnPreferenceChangeListener((p, newValue) -> { p.setTitle(((Boolean) newValue) ? R.string.repo_enabled : R.string.repo_disabled); + // Show snackbar telling the user to refresh the modules list or restart the app + Snackbar.make(requireView(), R.string.repo_enabled_changed, Snackbar.LENGTH_LONG).show(); return true; }); } diff --git a/app/src/main/res/layout/setup_box.xml b/app/src/main/res/layout/setup_box.xml index d808cd6..e0ad932 100644 --- a/app/src/main/res/layout/setup_box.xml +++ b/app/src/main/res/layout/setup_box.xml @@ -1,24 +1,45 @@ - + + + + + + + + + + + + + + + + android:textAppearance="@android:style/TextAppearance.Material.Subhead" /> + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5a3e9d7..2f66425 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -224,17 +224,29 @@ First time setup Welcome! This app will help you install and manage Magisk modules. To get started, please select the options below. These and more can be configured from settings later. Finish setup - Allow us to check for updates in the background.\nThis feature may use more battery. - Enable the Androidacy repo\nFeatures user reviews, automatic virus scans, fast updates, a wide selection, and is backed by Androidacy. + Background update check + Allow us to check for module and app updates in the background. This feature may use more battery, and may use more data. + Enable the Androidacy repo + Features user reviews, automatic virus scans, fast updates, a wide selection, and is backed by Androidacy. - Enable the Magisk Alt Repo\nMuch more lax than the original. Has a lot of modules at the cost of some safety. - Enable Sentry crash reporting and performance monitoring.\nAll reports are striclty anonymous and confidential. + Enable the Magisk Alt Repo + Much more lax than the original. Has a lot of modules at the cost of some safety. + Enable Sentry + Crash reporting and performance monitoring. All reports are striclty anonymous and confidential. You can add custom repos later in settings. Repos Miscellaneous Skip Enabling blur on lower-end device You are trying to enable blur on a device that may not perform well with it.\nYou may enable it, but this may lead to a poor user experience and we recommend you don\'t. - This repo has less restrictions and reviews, which may lead to lower quality modules. Pretty barebones but has a lot of modules.You are about to reboot your device. If you\'ve saved your work, hit ok to continue. Otherwise, hit cancel.Package %s is missing for module config, so we cannot launch it.Clear app dataClear app data?You\'re about to clear the app data. Please confirm this action.This is a debug build. Expect some bugs and worse performance. + This repo has less restrictions and reviews, which may lead to lower quality modules. Pretty barebones but has a lot of modules. + You are about to reboot your device. If you\'ve saved your work, hit OK to continue. Otherwise, hit cancel. + Package %s is missing for module config, so we cannot launch it. + Clear app dataClear app data? + You\'re about to clear the app data. Please confirm this action. + This is a debug build. Expect some bugs and worse performance. + Androidacy Repo + Magisk Alt Repo + You\'ve enabled or disabled a repo. Please refresh the module list or restart the app.Finish diff --git a/app/src/main/res/xml/repo_preferences.xml b/app/src/main/res/xml/repo_preferences.xml index 4ad416c..93a03ea 100644 --- a/app/src/main/res/xml/repo_preferences.xml +++ b/app/src/main/res/xml/repo_preferences.xml @@ -2,7 +2,7 @@ + app:title="@string/androidacy_repo_name"> + app:title="@string/magisk_alt_repo_name">