diff --git a/README.md b/README.md index f2ec466..6540557 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ ## Fox Module contest -[NoStorageRestrict](https://github.com/Magisk-Modules-Alt-Repo/NoStorageRestrict) -by [@DanGLES3](https://github.com/DanGLES3) won via vote in community telegram server. +[NoStorageRestrict](https://github.com/Magisk-Modules-Alt-Repo/NoStorageRestrict) by [@DanGLES3](https://github.com/DanGLES3) won via vote in community telegram server. Module description: Removes the restriction when selecting folders (Downloads/Android) through the file manager on Android 11 and higher @@ -19,12 +18,11 @@ Main activity: ## What is this? -The official Magisk is dropping support to download online modules... -So I made my own app to do that! :3 +The official Magisk has dropped support to download online modules, so I made Fox's Magisk Module Manager to help you download and install Magisk modules. **This app is not officially supported by Magisk or its developers** -**The modules shown in this app are not affiliated with this app** +**The modules shown in this app are not affiliated with this app or Magisk** (Please contact repo owners instead) ## Requirements diff --git a/app/build.gradle b/app/build.gradle index aa4c246..94fb2f7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,6 +34,7 @@ android { "default" { dimension "type" buildConfigField "boolean", "ENABLE_AUTO_UPDATER", "true" + buildConfigField "boolean", "DEFAULT_ENABLE_CRASH_REPORTING", "true" buildConfigField( "java.util.List", "ENABLED_REPOS", @@ -50,6 +51,9 @@ android { // with our keys, so the APK wouldn't install anyways). buildConfigField "boolean", "ENABLE_AUTO_UPDATER", "false" + // Disable crash reporting for F-Droid flavor by default + buildConfigField "boolean", "DEFAULT_ENABLE_CRASH_REPORTING", "false" + // Repo with ads or tracking feature are disabled by default for the // F-Droid flavor. buildConfigField( @@ -79,6 +83,8 @@ configurations { } dependencies { + // Error reporting + implementation 'io.sentry:sentry-android:6.4.0' // UI implementation 'androidx.appcompat:appcompat:1.5.0' implementation 'androidx.emoji2:emoji2:1.2.0' @@ -87,7 +93,7 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' - implementation 'androidx.webkit:webkit:1.4.0' + implementation 'androidx.webkit:webkit:1.5.0' implementation 'com.google.android.material:material:1.6.1' implementation "com.mikepenz:aboutlibraries:${latestAboutLibsRelease}" implementation "dev.rikka.rikkax.layoutinflater:layoutinflater:1.2.0" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 70ef911..d55947b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,7 +5,9 @@ tools:ignore="QueryAllPackagesPermission"> - + @@ -16,7 +18,8 @@ - @@ -24,30 +27,32 @@ - + + + android:label="@string/title_activity_settings" + android:parentActivityName=".MainActivity"> @@ -55,8 +60,8 @@ + android:label="@string/app_name_short" + android:launchMode="singleTask"> @@ -64,10 +69,10 @@ @@ -75,30 +80,45 @@ - + android:parentActivityName=".MainActivity" + android:theme="@style/Theme.MagiskModuleManager"> - + + - - + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/fox2code/mmm/MainActivity.java b/app/src/main/java/com/fox2code/mmm/MainActivity.java index ed9bd2e..8084b52 100644 --- a/app/src/main/java/com/fox2code/mmm/MainActivity.java +++ b/app/src/main/java/com/fox2code/mmm/MainActivity.java @@ -37,6 +37,7 @@ import com.google.android.material.progressindicator.LinearProgressIndicator; import eightbitlab.com.blurview.BlurView; import eightbitlab.com.blurview.RenderScriptBlur; +import io.sentry.android.core.SentryAndroid; public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRefreshListener, SearchView.OnQueryTextListener, SearchView.OnCloseListener, diff --git a/app/src/main/java/com/fox2code/mmm/MainApplication.java b/app/src/main/java/com/fox2code/mmm/MainApplication.java index 16cf224..9f4b278 100644 --- a/app/src/main/java/com/fox2code/mmm/MainApplication.java +++ b/app/src/main/java/com/fox2code/mmm/MainApplication.java @@ -27,6 +27,8 @@ import com.fox2code.mmm.utils.Http; import com.fox2code.rosettax.LanguageSwitcher; import com.topjohnwu.superuser.Shell; +import java.io.IOException; +import java.io.Writer; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; @@ -42,6 +44,9 @@ import io.noties.markwon.syntax.Prism4jThemeDefault; import io.noties.markwon.syntax.SyntaxHighlightPlugin; import io.noties.prism4j.Prism4j; import io.noties.prism4j.annotations.PrismBundle; +import io.sentry.JsonObjectWriter; +import io.sentry.NoOpLogger; +import io.sentry.android.core.SentryAndroid; @PrismBundle( includeAll = true, @@ -49,6 +54,7 @@ import io.noties.prism4j.annotations.PrismBundle; ) public class MainApplication extends FoxApplication implements androidx.work.Configuration.Provider { + private static final String TAG = "MainApplication"; private static final String timeFormatString = "dd MMM yyyy"; // Example: 13 july 2001 private static Locale timeFormatLocale = Resources.getSystem().getConfiguration().locale; @@ -168,6 +174,11 @@ public class MainApplication extends FoxApplication getSharedPreferences().edit().putBoolean("has_root_access", bool).apply(); } + public static boolean isCrashReportingEnabled() { + return getSharedPreferences().getBoolean( + "crash_reporting", BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING); + } + public static SharedPreferences getBootSharedPreferences() { return bootSharedPreferences; } @@ -341,6 +352,57 @@ public class MainApplication extends FoxApplication Log.d("MainApplication", "Emoji compat loaded!"); }, "Emoji compat init.").start(); } + SentryAndroid.init(this, options -> { + // Note: Sentry library only take a screenshot of Fox Magisk Module Manager. + // The screen shot doesn't and cannot contain other applications (if in multi windows) + // status bar and notifications (even if notification shade is pulled down) + + // In the possibility you find this library sending anything listed above, + // it's a serious bug and a security issue you should report to Google + // Google bug bounties on Android are huge, so you can also get rich by doing that. + options.setAttachScreenshot(true); + // Add a callback that will be used before the event is sent to Sentry. + // With this callback, you can modify the event or, when returning null, also discard the event. + options.setBeforeSend((event, hint) -> { + if (BuildConfig.DEBUG) { // Debug sentry events for debug. + StringBuilder stringBuilder = new StringBuilder("Sentry report debug: "); + try { + event.serialize(new JsonObjectWriter(new Writer() { + @Override + public void write(char[] cbuf) { + stringBuilder.append(cbuf); + } + + @Override + public void write(char[] chars, int i, int i1) { + stringBuilder.append(chars, i, i1); + } + + @Override + public void write(String str, int off, int len) { + stringBuilder.append(str, off, len); + } + + @Override + public void flush() {} + + @Override + public void close() {} + }, 4), NoOpLogger.getInstance()); + } catch (IOException ignored) {} + Log.i(TAG, stringBuilder.toString()); + } + // Check saved preferences to see if the user has opted out of crash reporting. + // If the user has opted out, return null. + if (isCrashReportingEnabled()) { + Log.i(TAG, "Relayed sentry report according to user preference"); + return event; + } else { + Log.i(TAG, "Blocked sentry report according to user preference"); + return null; + } + }); + }); } @Override diff --git a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java index 6f068eb..0806db7 100644 --- a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java +++ b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java @@ -21,24 +21,23 @@ import org.json.JSONObject; import java.io.File; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; -import okhttp3.Cookie; import okhttp3.HttpUrl; @SuppressWarnings("KotlinInternalInJava") public final class AndroidacyRepoData extends RepoData { private static final String TAG = "AndroidacyRepoData"; - private static final HttpUrl OK_HTTP_URL; + static { HttpUrl.Builder OK_HTTP_URL_BUILDER = new HttpUrl.Builder().scheme("https"); // Using HttpUrl.Builder.host(String) crash the app OK_HTTP_URL_BUILDER.setHost$okhttp(".androidacy.com"); - OK_HTTP_URL = OK_HTTP_URL_BUILDER.build(); + OK_HTTP_URL_BUILDER.build(); } + // Avoid spamming requests to Androidacy private long androidacyBlockade = 0; private String token = null; @@ -60,30 +59,36 @@ public final class AndroidacyRepoData extends RepoData { this.defaultSupport = "https://t.me/androidacy_discussions"; this.defaultDonate = "https://www.androidacy.com/membership-join/?utm_source=foxmmm&utm-medium=app&utm_campaign=fox-inapp"; this.defaultSubmitModule = "https://www.androidacy.com/module-repository-applications/"; - this.host = testMode ? "staging-api.androidacy.com" : "api.androidacy.com"; + this.host = testMode ? "staging-api.androidacy.com" : "production-api.androidacy.com"; this.testMode = testMode; } - private static String getCookies() { - if (Http.hasWebView()) { - return CookieManager.getInstance().getCookie("https://.androidacy.com/"); - } else { - Iterator cookies = Http.getCookieJar() - .loadForRequest(OK_HTTP_URL).iterator(); - if (!cookies.hasNext()) return ""; - StringBuilder stringBuilder = new StringBuilder(); - while (true) { - stringBuilder.append(cookies.next().toString()); - if (!cookies.hasNext()) return stringBuilder.toString(); - stringBuilder.append(","); - } - } - } - public static AndroidacyRepoData getInstance() { return RepoManager.getINSTANCE().getAndroidacyRepoData(); } + public boolean isValidToken(string token) { + try { + Http.doHttpGet("https://" + this.host + "/auth/me?token=" + token, false); + } catch (Exception e) { + if ("Received error code: 419".equals(e.getMessage()) || + "Received error code: 429".equals(e.getMessage())) { + Log.e(TAG, "We are being rate limited!", e); + long time = System.currentTimeMillis(); + this.androidacyBlockade = time + 3_600_000L; + return false; + } + Log.w(TAG, "Invalid token, resetting..."); + // Remove saved preference + SharedPreferences.Editor editor = this.cachedPreferences.edit(); + editor.remove("androidacy_api_token"); + editor.apply(); + return false; + } + // If status code is 200, we are good + return true; + } + @Override protected boolean prepare() { // Implementation details discussed on telegram @@ -91,57 +96,33 @@ public final class AndroidacyRepoData extends RepoData { long time = System.currentTimeMillis(); if (this.androidacyBlockade > time) return false; this.androidacyBlockade = time + 30_000L; - String cookies = AndroidacyRepoData.getCookies(); - int start = cookies == null ? -1 : cookies.indexOf("USER=") + 5; - String token = null; - if (start != -1) { - int end = cookies.indexOf(";", start); - if (end != -1) - token = cookies.substring(start, end); - } + // Get token from androidacy_api_token shared preference + String token = this.cachedPreferences.getString("androidacy_api_token", null); if (token != null) { - try { - Http.doHttpGet("https://" + this.host + "/auth/me?token=" + token, true); - } catch (Exception e) { - if ("Received error code: 419".equals(e.getMessage()) || - "Received error code: 429".equals(e.getMessage())) { - Log.e(TAG, "We are being rate limited!", e); - this.androidacyBlockade = time + 3_600_000L; - return false; - } - Log.w(TAG, "Invalid token, resetting..."); - if (Http.hasWebView()) { - CookieManager.getInstance().setCookie("https://.androidacy.com/", - "USER=; expires=Thu, 01 Jan 1970 00:00:00 GMT;" + - " path=/; secure; domain=.androidacy.com"); - } else { - Http.getCookieJar().saveFromResponse( - OK_HTTP_URL, Collections.emptyList()); - } - this.token = token = null; + this.token = token; + if (!isValidToken(token)) { + token = null; } } if (token == null) { try { Log.i(TAG, "Refreshing token..."); + // POST request to https://production-api.androidacy.com/auth/register token = new String(Http.doHttpPost( "https://" + this.host + "/auth/register", - "",true), StandardCharsets.UTF_8); - if (Http.hasWebView()) { - CookieManager.getInstance().setCookie("https://.androidacy.com/", - "USER=" + token + "; expires=Fri, 31 Dec 9999 23:59:59 GMT;" + - " path=/; secure; domain=.androidacy.com"); - } else { - Http.getCookieJar().saveFromResponse(OK_HTTP_URL, - Collections.singletonList(Cookie.parse(OK_HTTP_URL, - "USER=" + token + "; expires=Fri, 31 Dec 9999 23:59:59 GMT;" + - " path=/; secure; domain=.androidacy.com"))); - } + "foxmmm=true", true), StandardCharsets.UTF_8); + // Parse token + JSONObject jsonObject = new JSONObject(token); + token = jsonObject.getString("token"); + // Save token to shared preference + SharedPreferences.Editor editor = this.cachedPreferences.edit(); + editor.putString("androidacy_api_token", token); + editor.apply(); } catch (Exception e) { if ("Received error code: 419".equals(e.getMessage()) || "Received error code: 429".equals(e.getMessage()) || "Received error code: 503".equals(e.getMessage()) - ) { + ) { Log.e(TAG, "We are being rate limited!", e); this.androidacyBlockade = time + 3_600_000L; } @@ -194,7 +175,7 @@ public final class AndroidacyRepoData extends RepoData { jsonObject.optString("zipUrl", "")); repoModule.notesUrl = filterURL( jsonObject.optString("notesUrl", "")); - if (repoModule.zipUrl == null) { + if (repoModule.zipUrl == null) { repoModule.zipUrl = // Fallback url in case the API doesn't have zipUrl "https://" + this.host + "/magisk/info/" + moduleId; } @@ -264,7 +245,8 @@ public final class AndroidacyRepoData extends RepoData { } @Override - public void storeMetadata(RepoModule repoModule, byte[] data) {} + public void storeMetadata(RepoModule repoModule, byte[] data) { + } @Override public boolean tryLoadMetadata(RepoModule repoModule) { 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 2b4b9dc..4d9baca 100644 --- a/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java +++ b/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java @@ -40,7 +40,7 @@ public final class RepoManager extends SyncManager { "https://cdn.jsdelivr.net/gh/Magisk-Modules-Alt-Repo/json@main/modules.json"; public static final String ANDROIDACY_MAGISK_REPO_ENDPOINT = - "https://api.androidacy.com/magisk/repo"; + "https://production-api.androidacy.com/magisk/repo"; public static final String ANDROIDACY_TEST_MAGISK_REPO_ENDPOINT = "https://staging-api.androidacy.com/magisk/repo"; public static final String ANDROIDACY_MAGISK_REPO_HOMEPAGE = 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 3f767f0..4761366 100644 --- a/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java +++ b/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java @@ -8,7 +8,10 @@ import android.content.Intent; import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.util.Log; +import android.view.inputmethod.EditorInfo; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.Toast; @@ -17,10 +20,13 @@ import androidx.annotation.NonNull; import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentTransaction; +import androidx.preference.EditTextPreference; import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.SwitchPreferenceCompat; import androidx.preference.TwoStatePreference; import com.fox2code.foxcompat.FoxActivity; @@ -32,6 +38,7 @@ import com.fox2code.mmm.Constants; import com.fox2code.mmm.MainActivity; import com.fox2code.mmm.MainApplication; import com.fox2code.mmm.R; +import com.fox2code.mmm.androidacy.AndroidacyRepoData; import com.fox2code.mmm.background.BackgroundUpdateChecker; import com.fox2code.mmm.installer.InstallerInitializer; import com.fox2code.mmm.module.ActionButtonType; @@ -45,6 +52,7 @@ import com.fox2code.rosettax.LanguageActivity; import com.fox2code.rosettax.LanguageSwitcher; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.internal.TextWatcherAdapter; +import com.google.android.material.snackbar.Snackbar; import com.google.android.material.textfield.MaterialAutoCompleteTextView; import com.mikepenz.aboutlibraries.LibsBuilder; import com.topjohnwu.superuser.internal.UiThreadHandler; @@ -70,10 +78,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { setTitle(R.string.app_name); setActionBarBackground(null); if (savedInstanceState == null) { - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.settings, new SettingsFragment()) - .commit(); + getSupportFragmentManager().beginTransaction().replace(R.id.settings, new SettingsFragment()).commit(); } } @@ -83,9 +88,8 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { Intent mStartActivity = new Intent(this, MainActivity.class); mStartActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); int mPendingIntentId = 123456; - PendingIntent mPendingIntent = PendingIntent.getActivity(this, mPendingIntentId, - mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); - AlarmManager mgr = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE); + PendingIntent mPendingIntent = PendingIntent.getActivity(this, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); + AlarmManager mgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE); mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent); System.exit(0); // Exit app process } @@ -96,8 +100,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { super.onPause(); } - public static class SettingsFragment extends PreferenceFragmentCompat - implements FoxActivity.OnBackPressedCallback { + public static class SettingsFragment extends PreferenceFragmentCompat implements FoxActivity.OnBackPressedCallback { @Override @SuppressWarnings("ConstantConditions") public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { @@ -119,11 +122,18 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { devModeStep = 0; UiThreadHandler.handler.postDelayed(() -> { MainApplication.getINSTANCE().updateTheme(); - FoxActivity.getFoxActivity(this).setThemeRecreate( - MainApplication.getINSTANCE().getManagerThemeResId()); + FoxActivity.getFoxActivity(this).setThemeRecreate(MainApplication.getINSTANCE().getManagerThemeResId()); }, 1); return true; }); + // Crash reporting + TwoStatePreference crashReportingPreference = findPreference("pref_crash_reporting"); + crashReportingPreference.setChecked(MainApplication.isCrashReportingEnabled()); + crashReportingPreference.setOnPreferenceChangeListener((preference, newValue) -> { + devModeStep = 0; + getCrashReportingEditor(requireActivity()).putBoolean("crash_reporting", (boolean) newValue).apply(); + return true; + }); Preference enableBlur = findPreference("pref_enable_blur"); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { enableBlur.setSummary(R.string.require_android_6); @@ -138,8 +148,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { disableMonet.setOnPreferenceClickListener(preference -> { UiThreadHandler.handler.postDelayed(() -> { MainApplication.getINSTANCE().updateTheme(); - ((FoxActivity) this.requireActivity()).setThemeRecreate( - MainApplication.getINSTANCE().getManagerThemeResId()); + ((FoxActivity) this.requireActivity()).setThemeRecreate(MainApplication.getINSTANCE().getManagerThemeResId()); }, 1); return true; }); @@ -182,8 +191,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { int level = this.currentLanguageLevel(); if (level != LANGUAGE_SUPPORT_LEVEL) { - Log.e(TAG, "Detected language level " + level + - ", latest is " + LANGUAGE_SUPPORT_LEVEL); + Log.e(TAG, "Detected language level " + level + ", latest is " + LANGUAGE_SUPPORT_LEVEL); languageSelector.setSummary(R.string.language_support_outdated); } else { if (!"Translated by Fox2Code".equals( // I don't "translate" english @@ -196,45 +204,45 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { if (!MainApplication.isDeveloper()) { findPreference("pref_disable_low_quality_module_filter").setVisible(false); + // Hide the pref_crash option if not in debug mode - stop users from purposely crashing the app + Objects.requireNonNull((Preference) findPreference("pref_crash")).setVisible(false); + } else { + findPreference("pref_crash").setOnPreferenceClickListener(preference -> { + // Hard crash the app + throw new RuntimeException("This is a test crash"); + }); } - if (InstallerInitializer.peekMagiskVersion() < Constants.MAGISK_VER_CODE_INSTALL_COMMAND - || !MainApplication.isDeveloper()) { + if (InstallerInitializer.peekMagiskVersion() < Constants.MAGISK_VER_CODE_INSTALL_COMMAND || !MainApplication.isDeveloper()) { findPreference("pref_use_magisk_install_command").setVisible(false); } Preference debugNotification = findPreference("pref_background_update_check_debug"); debugNotification.setEnabled(MainApplication.isBackgroundUpdateCheckEnabled()); debugNotification.setVisible(MainApplication.isDeveloper()); debugNotification.setOnPreferenceClickListener(preference -> { - BackgroundUpdateChecker.postNotification( - this.requireContext(), new Random().nextInt(4) + 2); + BackgroundUpdateChecker.postNotification(this.requireContext(), new Random().nextInt(4) + 2); return true; }); findPreference("pref_background_update_check").setOnPreferenceChangeListener((preference, newValue) -> { boolean enabled = Boolean.parseBoolean(String.valueOf(newValue)); debugNotification.setEnabled(enabled); if (!enabled) { - BackgroundUpdateChecker.onMainActivityResume( - this.requireContext()); + BackgroundUpdateChecker.onMainActivityResume(this.requireContext()); } return true; }); - final LibsBuilder libsBuilder = new LibsBuilder().withShowLoadingProgress(false) - .withLicenseShown(true).withAboutMinimalDesign(false); + final LibsBuilder libsBuilder = new LibsBuilder().withShowLoadingProgress(false).withLicenseShown(true).withAboutMinimalDesign(false); Preference update = findPreference("pref_update"); - update.setVisible(BuildConfig.ENABLE_AUTO_UPDATER && (BuildConfig.DEBUG || - AppUpdateManager.getAppUpdateManager().peekHasUpdate())); + update.setVisible(BuildConfig.ENABLE_AUTO_UPDATER && (BuildConfig.DEBUG || AppUpdateManager.getAppUpdateManager().peekHasUpdate())); update.setOnPreferenceClickListener(p -> { devModeStep = 0; - IntentHelper.openUrl(p.getContext(), - "https://github.com/Fox2Code/FoxMagiskModuleManager/releases"); + IntentHelper.openUrl(p.getContext(), "https://github.com/Fox2Code/FoxMagiskModuleManager/releases"); return true; }); if (BuildConfig.DEBUG || BuildConfig.ENABLE_AUTO_UPDATER) { findPreference("pref_report_bug").setOnPreferenceClickListener(p -> { devModeStep = 0; - IntentHelper.openUrl(p.getContext(), - "https://github.com/Fox2Code/FoxMagiskModuleManager/issues"); + IntentHelper.openUrl(p.getContext(), "https://github.com/Fox2Code/FoxMagiskModuleManager/issues"); return true; }); } else { @@ -244,20 +252,17 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { if (devModeStep == 2) { devModeStep = 0; if (MainApplication.isDeveloper() && !BuildConfig.DEBUG) { - MainApplication.getSharedPreferences().edit() - .putBoolean("developer", false).apply(); + MainApplication.getSharedPreferences().edit().putBoolean("developer", false).apply(); Toast.makeText(getContext(), // Tell the user something changed R.string.dev_mode_disabled, Toast.LENGTH_SHORT).show(); } else { - MainApplication.getSharedPreferences().edit() - .putBoolean("developer", true).apply(); + MainApplication.getSharedPreferences().edit().putBoolean("developer", true).apply(); Toast.makeText(getContext(), // Tell the user something changed R.string.dev_mode_enabled, Toast.LENGTH_SHORT).show(); } return true; } - IntentHelper.openUrl(p.getContext(), - "https://github.com/Fox2Code/FoxMagiskModuleManager"); + IntentHelper.openUrl(p.getContext(), "https://github.com/Fox2Code/FoxMagiskModuleManager"); return true; }); findPreference("pref_support").setOnPreferenceClickListener(p -> { @@ -271,43 +276,31 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { openFragment(libsBuilder.supportFragment(), R.string.licenses); return true; }); - findPreference("pref_pkg_info").setSummary( - BuildConfig.APPLICATION_ID + " v" + - BuildConfig.VERSION_NAME + " (" + - BuildConfig.VERSION_CODE + ")"); + findPreference("pref_pkg_info").setSummary(BuildConfig.APPLICATION_ID + " v" + BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")"); + } + + private SharedPreferences.Editor getCrashReportingEditor(FragmentActivity requireActivity) { + return requireActivity.getSharedPreferences("crash_reporting", Context.MODE_PRIVATE).edit(); } private void openFragment(Fragment fragment, @StringRes int title) { FoxActivity compatActivity = getFoxActivity(this); compatActivity.setOnBackPressedCallback(this); compatActivity.setTitle(title); - compatActivity.getSupportFragmentManager() - .beginTransaction() - .replace(R.id.settings, fragment) - .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) - .commit(); + compatActivity.getSupportFragmentManager().beginTransaction().replace(R.id.settings, fragment).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE).commit(); } @Override public boolean onBackPressed(FoxActivity compatActivity) { compatActivity.setTitle(R.string.app_name); - compatActivity.getSupportFragmentManager() - .beginTransaction().replace(R.id.settings, this) - .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) - .commit(); + compatActivity.getSupportFragmentManager().beginTransaction().replace(R.id.settings, this).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE).commit(); return true; } private int currentLanguageLevel() { - int declaredLanguageLevel = - this.getResources().getInteger(R.integer.language_support_level); - if (declaredLanguageLevel != LANGUAGE_SUPPORT_LEVEL) - return declaredLanguageLevel; - if (!this.getResources().getConfiguration().locale.getLanguage().equals("en") && - this.getResources().getString(R.string.notification_update_pref) - .equals("Background modules update check") && - this.getResources().getString(R.string.notification_update_desc) - .equals("May increase battery usage")) { + int declaredLanguageLevel = this.getResources().getInteger(R.integer.language_support_level); + if (declaredLanguageLevel != LANGUAGE_SUPPORT_LEVEL) return declaredLanguageLevel; + if (!this.getResources().getConfiguration().locale.getLanguage().equals("en") && this.getResources().getString(R.string.notification_update_pref).equals("Background modules update check") && this.getResources().getString(R.string.notification_update_desc).equals("May increase battery usage")) { return 0; } return LANGUAGE_SUPPORT_LEVEL; @@ -317,6 +310,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { public static class RepoFragment extends PreferenceFragmentCompat { private static final int CUSTOM_REPO_ENTRIES = 5; + @SuppressLint("RestrictedApi") @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { getPreferenceManager().setSharedPreferencesName("mmm"); @@ -326,28 +320,101 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { setRepoData(RepoManager.DG_MAGISK_REPO_GITHUB); updateCustomRepoList(true); if (!MainApplication.isDeveloper()) { - Objects.requireNonNull((Preference) findPreference( - "pref_androidacy_test_mode")).setVisible(false); + Objects.requireNonNull((Preference) findPreference("pref_androidacy_test_mode")).setVisible(false); + } else { + // Show a warning if user tries to enable test mode + Objects.requireNonNull((SwitchPreferenceCompat) findPreference("pref_androidacy_test_mode")).setOnPreferenceChangeListener((preference, newValue) -> { + if (Boolean.parseBoolean(String.valueOf(newValue))) { + new AlertDialog.Builder(this.requireContext()) + .setTitle(R.string.warning) + .setMessage(R.string.androidacy_test_mode_warning) + .setPositiveButton(android.R.string.ok, (dialog, which) -> { + // Do nothing + }) + .show(); + } + return true; + }); } + String originalApiKey = MainApplication.getSharedPreferences().getString("pref_androidacy_api_token", ""); + // Create the pref_androidacy_repo_api_key text input with validation + EditTextPreference prefAndroidacyRepoApiKey = findPreference("pref_androidacy_repo_api_key"); + assert prefAndroidacyRepoApiKey != null; + prefAndroidacyRepoApiKey.setOnBindEditTextListener(editText -> { + editText.setSingleLine(); + // Make the single line wrap + editText.setHorizontallyScrolling(false); + // Set the height to the height of 2 lines + editText.setHeight(editText.getLineHeight() * 3); + // Make ok button say "Save" + editText.setImeOptions(EditorInfo.IME_ACTION_DONE); + }); + prefAndroidacyRepoApiKey.setPositiveButtonText(R.string.save_api_key); + prefAndroidacyRepoApiKey.setOnPreferenceChangeListener((preference, newValue) -> { + // Curious if this actually works - so crash the app on purpose + // throw new RuntimeException("This is a test crash"); + // get original api key + String apiKey = String.valueOf(newValue); + // Show snack bar with indeterminate progress + Snackbar.make(requireView(), R.string.checking_api_key, Snackbar.LENGTH_INDEFINITE).setAction(R.string.cancel, v -> { + // Restore the original api key + prefAndroidacyRepoApiKey.setText(originalApiKey); + }).show(); + // Check the API key on a background thread + new Thread(() -> { + // If key is empty, just remove it and change the text of the snack bar + if (apiKey.isEmpty()) { + MainApplication.getSharedPreferences().edit().remove("pref_androidacy_repo_api_key").apply(); + new Handler(Looper.getMainLooper()).post(() -> Snackbar.make(requireView(), R.string.api_key_removed, Snackbar.LENGTH_SHORT).show()); + } else { + // If key < 64 chars, it's not valid + if (apiKey.length() < 64) { + new Handler(Looper.getMainLooper()).post(() -> { + Snackbar.make(requireView(), R.string.api_key_invalid, Snackbar.LENGTH_SHORT).show(); + // Save the original key + MainApplication.getSharedPreferences().edit().putString("pref_androidacy_api_token", originalApiKey).apply(); + // Re-show the dialog with an error + prefAndroidacyRepoApiKey.performClick(); + // Show error + prefAndroidacyRepoApiKey.setDialogMessage(getString(R.string.api_key_invalid)); + }); + } else { + boolean valid = AndroidacyRepoData.getInstance().isValidToken(apiKey); + // If the key is valid, save it + if (valid) { + MainApplication.getSharedPreferences().edit().putString("pref_androidacy_repo_api_key", apiKey).apply(); + new Handler(Looper.getMainLooper()).post(() -> Snackbar.make(requireView(), R.string.api_key_valid, Snackbar.LENGTH_SHORT).show()); + } else { + new Handler(Looper.getMainLooper()).post(() -> { + Snackbar.make(requireView(), R.string.api_key_invalid, Snackbar.LENGTH_SHORT).show(); + // Save the original key + MainApplication.getSharedPreferences().edit().putString("pref_androidacy_api_token", originalApiKey).apply(); + // Re-show the dialog with an error + prefAndroidacyRepoApiKey.performClick(); + // Show error + prefAndroidacyRepoApiKey.setDialogMessage(getString(R.string.api_key_invalid)); + }); + } + } + } + }).start(); + return true; + }); } @SuppressLint("RestrictedApi") public void updateCustomRepoList(boolean initial) { - final SharedPreferences sharedPreferences = Objects.requireNonNull( - this.getPreferenceManager().getSharedPreferences()); - final CustomRepoManager customRepoManager = - RepoManager.getINSTANCE().getCustomRepoManager(); + final SharedPreferences sharedPreferences = Objects.requireNonNull(this.getPreferenceManager().getSharedPreferences()); + final CustomRepoManager customRepoManager = RepoManager.getINSTANCE().getCustomRepoManager(); for (int i = 0; i < CUSTOM_REPO_ENTRIES; i++) { CustomRepoData repoData = customRepoManager.getRepo(i); setRepoData(repoData, "pref_custom_repo_" + i); if (initial) { - Preference preference = - findPreference("pref_custom_repo_" + i + "_delete"); + Preference preference = findPreference("pref_custom_repo_" + i + "_delete"); if (preference == null) continue; final int index = i; preference.setOnPreferenceClickListener(preference1 -> { - sharedPreferences.edit().putBoolean( - "pref_custom_repo_" + index + "_enabled", false).apply(); + sharedPreferences.edit().putBoolean("pref_custom_repo_" + index + "_enabled", false).apply(); customRepoManager.removeRepo(index); updateCustomRepoList(false); return true; @@ -356,16 +423,14 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { } Preference preference = findPreference("pref_custom_add_repo"); if (preference == null) return; - preference.setVisible(customRepoManager.canAddRepo() && - customRepoManager.getRepoCount() < CUSTOM_REPO_ENTRIES); + preference.setVisible(customRepoManager.canAddRepo() && customRepoManager.getRepoCount() < CUSTOM_REPO_ENTRIES); if (initial) { // Custom repo add button part. preference = findPreference("pref_custom_add_repo_button"); if (preference == null) return; preference.setOnPreferenceClickListener(preference1 -> { final Context context = this.requireContext(); MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context); - final MaterialAutoCompleteTextView input = - new MaterialAutoCompleteTextView(context); + final MaterialAutoCompleteTextView input = new MaterialAutoCompleteTextView(context); input.setHint(R.string.custom_url); builder.setIcon(R.drawable.ic_baseline_add_box_24); builder.setTitle(R.string.add_repo); @@ -373,28 +438,24 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { builder.setPositiveButton("OK", (dialog, which) -> { String text = String.valueOf(input.getText()); if (customRepoManager.canAddRepo(text)) { - final CustomRepoData customRepoData = - customRepoManager.addRepo(text); + final CustomRepoData customRepoData = customRepoManager.addRepo(text); customRepoData.setEnabled(true); new Thread("Add Custom Repo Thread") { @Override public void run() { try { customRepoData.quickPrePopulate(); - } catch (IOException|JSONException e) { + } catch (IOException | JSONException e) { Log.e(TAG, "Failed to preload repo values", e); } - UiThreadHandler.handler.post(() -> { - updateCustomRepoList(false); - }); + UiThreadHandler.handler.post(() -> updateCustomRepoList(false)); } }.start(); } }); builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel()); AlertDialog alertDialog = builder.show(); - final Button positiveButton = - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); + final Button positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); input.setValidator(new AutoCompleteTextView.Validator() { @Override public boolean isValid(CharSequence charSequence) { @@ -408,16 +469,12 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { }); input.addTextChangedListener(new TextWatcherAdapter() { @Override - public void onTextChanged( - @NonNull CharSequence charSequence, int i, int i1, int i2) { - positiveButton.setEnabled(customRepoManager - .canAddRepo(charSequence.toString()) && - customRepoManager.getRepoCount() < CUSTOM_REPO_ENTRIES); + public void onTextChanged(@NonNull CharSequence charSequence, int i, int i1, int i2) { + positiveButton.setEnabled(customRepoManager.canAddRepo(charSequence.toString()) && customRepoManager.getRepoCount() < CUSTOM_REPO_ENTRIES); } }); positiveButton.setEnabled(false); - int dp10 = FoxDisplay.dpToPixel(10), - dp20 = FoxDisplay.dpToPixel(20); + int dp10 = FoxDisplay.dpToPixel(10), dp20 = FoxDisplay.dpToPixel(20); FoxViewCompat.setMargin(input, dp20, dp10, dp20, dp10); return true; }); @@ -426,8 +483,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { private void setRepoData(String url) { final RepoData repoData = RepoManager.getINSTANCE().get(url); - setRepoData(repoData, "pref_" + (repoData == null ? - RepoManager.internalIdOfUrl(url) : repoData.getPreferenceId())); + setRepoData(repoData, "pref_" + (repoData == null ? RepoManager.internalIdOfUrl(url) : repoData.getPreferenceId())); } private void setRepoData(final RepoData repoData, String preferenceName) { @@ -442,11 +498,9 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { preference = findPreference(preferenceName + "_enabled"); if (preference != null) { ((TwoStatePreference) preference).setChecked(repoData.isEnabled()); - preference.setTitle(repoData.isEnabled() ? - R.string.repo_enabled : R.string.repo_disabled); + 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); + p.setTitle(((Boolean) newValue) ? R.string.repo_enabled : R.string.repo_disabled); return true; }); } @@ -457,8 +511,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { preference.setVisible(true); preference.setOnPreferenceClickListener(p -> { if (homepage.startsWith("https://www.androidacy.com/")) { - IntentHelper.openUrlAndroidacy( - getFoxActivity(this), homepage, true); + IntentHelper.openUrlAndroidacy(getFoxActivity(this), homepage, true); } else { IntentHelper.openUrl(getFoxActivity(this), homepage); } @@ -503,8 +556,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity { preference.setVisible(true); preference.setOnPreferenceClickListener(p -> { if (submissionUrl.startsWith("https://www.androidacy.com/")) { - IntentHelper.openUrlAndroidacy( - getFoxActivity(this), submissionUrl, true); + IntentHelper.openUrlAndroidacy(getFoxActivity(this), submissionUrl, true); } else { IntentHelper.openUrl(getFoxActivity(this), submissionUrl); } diff --git a/app/src/main/res/drawable/ic_baseline_vpn_key_24.xml b/app/src/main/res/drawable/ic_baseline_vpn_key_24.xml new file mode 100644 index 0000000..9cdda53 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_vpn_key_24.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 646f642..741e0e2 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -92,4 +92,6 @@ Povolit rozostření Repozitář povolen Repozitář zakázán + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 5a0b88a..c0e3ed8 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -94,7 +94,6 @@ Repo hinzufügen Repo entfernen Eigene URL - Das Androidacy-Repo enthält Anzeigen und Tracker. Backup Modules Module wiederherstellen Dieser Vorgang erfordert eine Internetverbindung @@ -103,4 +102,6 @@ Beschreibung Deinstallieren Konfig + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 75b93ef..5c26ca9 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -124,7 +124,6 @@ Προσθήκη αποθετηρίου Αφαίρεση αποθετηρίου Προσαρμοσμένη διεύθυνση url - Το αποθετήριο Androidacy έχει διαφημίσεις και ιχνηλάτες. Εφεδρικά modules Επαναφορά module Αυτή η λειτουργία απαιτεί σύνδεση στο Διαδίκτυο @@ -144,4 +143,6 @@ Ορισμένες μεταφράσεις για την τρέχουσα γλώσσα δεν είναι ενημερωμένες, παρακαλούμε να συνεισφέρετε στις μεταφράσεις εφαρμογών στο GitHub Μεταφράστηκε απο Tha_14 + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml index 7de0d58..e8ef531 100644 --- a/app/src/main/res/values-es-rMX/strings.xml +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -124,8 +124,9 @@ Añadir Repositorio Eliminar Repositorio URL Personalizado - El repositorio Androidacy tiene anuncios y trackers. Hacer copia de seguridad de los módulos Restaurar módulos Esta operación requiere una conexión a Internet. + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index efce5aa..33720c9 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -87,4 +87,6 @@ Hoidla lubatud Hoidla keelatud + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 88f5e11..205d017 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -124,8 +124,9 @@ Ajouter dépôt Supprimer dépôt URL personnalisée - Le dépôt Androidacy utilise des publicités et des pisteurs. Sauvegarder les modules Restaurer les modules Cette opération requière une connexion internet + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 3815c05..dbef5f2 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -93,4 +93,6 @@ Aktifkan blur Repo diaktifkan Repo dinonaktifkan + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 367addf..1725d8c 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -127,7 +127,6 @@ Aggiungi Repository Rimuovi Repository Url personalizzato - La repository di Androidacy contiene pubblicità e tracker. Salva moduli Ripristina moduli Questa operazione richiede una connessione ad internet @@ -149,4 +148,6 @@ Traduzione di tugaia56 + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 39f4e9a..78cb62a 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -40,4 +40,6 @@ ソースコード 開発者モードが有効です Force English language + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 37b3d3e..048de70 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -94,5 +94,6 @@ Tilsløring Pakkebrønn på Pakkebrønn av - Androidacy-pakkebrønnen har reklame og sporere. + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-night-v31/strings.xml b/app/src/main/res/values-night-v31/strings.xml new file mode 100644 index 0000000..1258a33 --- /dev/null +++ b/app/src/main/res/values-night-v31/strings.xml @@ -0,0 +1,5 @@ + + + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key + \ No newline at end of file diff --git a/app/src/main/res/values-night/strings.xml b/app/src/main/res/values-night/strings.xml new file mode 100644 index 0000000..1258a33 --- /dev/null +++ b/app/src/main/res/values-night/strings.xml @@ -0,0 +1,5 @@ + + + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key + \ No newline at end of file diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 659a1d7..7e9b6fd 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -124,7 +124,6 @@ Dodaj repozytorium Usuń repozytorium Niestandardowy URL - Repo Androidacy korzysta z reklam i trackerów. Kopia zapasowa modułów Przywracanie modułów Ta operacja wymaga połączenia internetowego @@ -147,4 +146,6 @@ prosimy o rozważenie uzupełnienia tłumaczeń aplikacji na GitHubie. Tłumaczenie: Daviteusz + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 3e13142..594810b 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -127,7 +127,6 @@ Adicionar Repositório Remover Repositórios URL Customizado - O Repositórios Androidacy possui anuncios e rastreadores. Fazer backup dos modulos Restaurar modulos Essa operação requer uma conexão com a internet @@ -149,4 +148,6 @@ Algumas traduções para sua lingua atual não esta em dia, por favor considere contribuir para as traduções do app no Github Traduzido por mi007d e DanGLES3 + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 2172cb1..33d5330 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -119,7 +119,6 @@ Adăugare depozit Eliminare depozit URL personalizat - Depozitul Androidacy utilizează reclame și instrumente de urmărire. Rezervare module Restabilire module Această operațiune necesită o conexiune la Internet @@ -138,4 +137,6 @@ nu sunt actualizate, vă rugăm să luați în considerare contribuția la traducerea aplicației pe GitHub Tradus de Fox2Code + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 143cc46..560cd61 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -120,8 +120,9 @@ Добавить репо Убрать репо Свой URL - Репо Androidacy содержит рекламу и трекеры. Резервное копирование модулей Восстановить модули Для этого действия потребуется подключение к Интернету + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 70f7e4a..41c29ec 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -92,4 +92,6 @@ Povoliť rozostrenia Repozitár povolený Repozitár zakázaný + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 947ec9f..547460b 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -127,7 +127,6 @@ Repo ekle Repo\'yu kaldır Özel url - Androidacy repo\'da reklamlar ve takipçiler vardır. Modülleri yedekle Modülleri geri yükle Bu işlem bir internet bağlantısı gerektirir @@ -147,4 +146,6 @@ Şimdiki dil için bazı çeviriler güncel değil, lütfen GitHub\'daki uygulama çevirilerine katkıda bulunmayı düşünün Alprnn357 tarafından çevrildi + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-v23/strings.xml b/app/src/main/res/values-v23/strings.xml new file mode 100644 index 0000000..1258a33 --- /dev/null +++ b/app/src/main/res/values-v23/strings.xml @@ -0,0 +1,5 @@ + + + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key + \ No newline at end of file diff --git a/app/src/main/res/values-v31/strings.xml b/app/src/main/res/values-v31/strings.xml new file mode 100644 index 0000000..1258a33 --- /dev/null +++ b/app/src/main/res/values-v31/strings.xml @@ -0,0 +1,5 @@ + + + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key + \ No newline at end of file diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index c560c0b..dd9348f 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -119,8 +119,9 @@ Thêm kho Gỡ kho Url tuỳ chỉnh - Kho Androidacy có các quảng cáo và trình theo dõi. Sao lưu mô-đun Khôi phục mô-đun Quá trình này yêu cầu kết nối internet + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 936a911..2f66551 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -129,7 +129,6 @@ 添加库 移除库 自定义网址 - Androidacy repo具有广告和跟踪器. 备份模块 还原模块 此操作需要互联网连接 @@ -150,4 +149,6 @@ 请考虑为 GitHub 上的应用程序翻译做出贡献 由ender-zhao翻译 + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 0d080eb..5021afb 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -120,7 +120,6 @@ 新增倉庫 移除倉庫 自定義網址 - Androidacy repo 內建廣告和跟蹤器. 備份模組 還原模組 需要網路連線 @@ -140,4 +139,6 @@ 如果您使用的當前語言沒有及時更新,請考慮在 GitHub 上的為翻譯做出貢獻。 由 OrStudio.tw(@crcky5322) 提供美妙的翻譯 + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index a552495..58a4726 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -24,4 +24,5 @@ #FFFFFFFF #FFFFFFFF #FFDADADA + #3A3A3A \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2dbccca..b2ba2b6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -129,7 +129,7 @@ Add Repo Remove Repo Custom url - The Androidacy repo has ads and trackers. + This repository may display some non-intrusive advertising to cover server and development costs. Backup modules Restore modules This operation require an internet connection @@ -152,4 +152,20 @@ not up-to-date, please consider contributing to the app translations on GitHub Translated by Fox2Code + Automatically report bugs and performance to the developers + If you disable this, the developer will not get automatic bug reports, and this may make troubleshooting harder + Androidacy API Key + Use a custom API key for Androidacy. Useful for premium subscribers, to remove ads and more. + Androidacy API key is empty + Current Androidacy API key + Could not validate API key. Please check it and try again. + API key is valid. + Validating API key... + Validating API key... + Please wait + Successfully reset API key + Validate + Warning! + You are setting the app to use a non-production endpoint for Androidacy. This may result in app instability and failure to load the online repo. Do NOT report bugs if you have this switch on. Change will take effect on app restart. + Crash the app for testing diff --git a/app/src/main/res/xml/repo_preferences.xml b/app/src/main/res/xml/repo_preferences.xml index a0b7c46..8cbb1a8 100644 --- a/app/src/main/res/xml/repo_preferences.xml +++ b/app/src/main/res/xml/repo_preferences.xml @@ -1,5 +1,6 @@ - + @@ -39,6 +40,27 @@ app:switchTextOn="@string/repo_enabled" app:switchTextOff="@string/repo_disabled" app:singleLineTitle="false" /> + + + - + app:key="pref_manage_repos" + app:singleLineTitle="false" + app:title="@string/manage_repos_pref" /> + app:title="@string/show_incompatible_pref" /> + app:title="@string/disable_low_quality_module_filter_pref" /> + app:title="@string/use_magisk_install_command_pref" /> + app:title="@string/notification_update_pref" /> + app:singleLineTitle="false" + app:title="@string/notification_update_debug_pref" /> + app:icon="@drawable/ic_baseline_palette_24" + app:key="pref_theme" + app:singleLineTitle="false" + app:title="@string/theme_pref" /> + app:key="pref_language_selector" + app:title="@string/language" /> + app:key="pref_enable_blur" + app:singleLineTitle="false" + app:title="@string/enable_blur_pref" /> + app:key="pref_force_dark_terminal" + app:singleLineTitle="false" + app:title="@string/force_dark_terminal_title" /> + app:key="pref_enable_monet" + app:singleLineTitle="false" + app:title="@string/enable_monet" /> + app:title="@string/wrap_text_pref" /> + app:title="@string/dns_over_https_pref" /> + app:title="@string/showcase_mode_pref" /> + app:title="@string/prevent_reboot_pref" /> + + + + - + + app:key="pref_update" + app:singleLineTitle="false" + app:title="@string/app_update" /> + app:key="pref_report_bug" + app:singleLineTitle="false" + app:title="@string/report_bugs" /> + app:key="pref_source_code" + app:singleLineTitle="false" + app:title="@string/source_code" /> + app:key="pref_support" + app:singleLineTitle="false" + app:title="@string/support" /> + app:key="pref_show_licenses" + app:singleLineTitle="false" + app:title="@string/show_licenses" /> + app:summary="@string/loading" /> \ No newline at end of file diff --git a/build.gradle b/build.gradle index 4ac6860..c4ee15e 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() gradlePluginPortal() } - project.ext.latestAboutLibsRelease = "10.3.1" + project.ext.latestAboutLibsRelease = "10.4.1-a01" dependencies { classpath 'com.android.tools.build:gradle:7.2.2' classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${latestAboutLibsRelease}"