rework UI a little

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/287/head
androidacy-user 1 year ago
parent a3b3c8b547
commit dbc4797c80

@ -56,6 +56,7 @@ import org.chromium.net.CronetEngine;
import java.io.File;
import java.net.URL;
import java.util.Objects;
import timber.log.Timber;
@ -135,7 +136,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
}
setContentView(R.layout.activity_main);
this.setTitle(R.string.app_name);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, 0);
this.getWindow().setFlags(WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW, WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW);
setActionBarBackground(null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
WindowManager.LayoutParams layoutParams = this.getWindow().getAttributes();
@ -285,9 +286,8 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
// On every preferences change, log the change if debug is enabled
if (BuildConfig.DEBUG) {
Timber.d("onCreate: Preferences: %s", MainApplication.getSharedPreferences("mmm").getAll());
// Log all preferences changes
MainApplication.getSharedPreferences("mmm").registerOnSharedPreferenceChangeListener((prefs, key) -> Timber.i("onSharedPreferenceChanged: " + key + " = " + prefs.getAll().get(key)));
MainApplication.getSharedPreferences().registerOnSharedPreferenceChangeListener((prefs, key) -> Timber.i("onSharedPreferenceChanged: " + key + " = " + prefs.getAll().get(key)));
}
Timber.i("Scanning for modules!");
@ -379,17 +379,21 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
private void updateScreenInsets(Configuration configuration) {
boolean landscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE;
int bottomInset = (landscape ? 0 : this.getNavigationBarHeight());
int statusBarHeight = getStatusBarHeight();
int statusBarHeight = getStatusBarHeight() + FoxDisplay.dpToPixel(2);
int actionBarHeight = getActionBarHeight();
int combinedBarsHeight = statusBarHeight + actionBarHeight;
this.swipeRefreshLayout.setProgressViewOffset(false, swipeRefreshLayoutOrigStartOffset + combinedBarsHeight, swipeRefreshLayoutOrigEndOffset + combinedBarsHeight);
this.moduleViewListBuilder.setHeaderPx(Math.max(statusBarHeight, combinedBarsHeight - FoxDisplay.dpToPixel(4)));
this.moduleViewListBuilder.setHeaderPx(Math.max(statusBarHeight, combinedBarsHeight));
this.moduleViewListBuilderOnline.setHeaderPx(Math.max(statusBarHeight, combinedBarsHeight));
this.moduleViewListBuilder.setFooterPx(FoxDisplay.dpToPixel(4) + bottomInset + this.searchCard.getHeight());
this.moduleViewListBuilderOnline.setFooterPx(FoxDisplay.dpToPixel(4) + bottomInset + this.searchCard.getHeight());
this.searchCard.setRadius(this.searchCard.getHeight() / 2F);
this.moduleViewListBuilder.updateInsets();
//this.actionBarBlur.invalidate();
this.overScrollInsetTop = combinedBarsHeight;
this.overScrollInsetBottom = bottomInset;
// set root_container to have zero padding
findViewById(R.id.root_container).setPadding(0, statusBarHeight, 0, 0);
Timber.i("(" + this.searchCard.getHeight() + ")");
}
@ -705,11 +709,18 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
private void checkShowInitialSetup() {
if (BuildConfig.DEBUG)
Timber.i("Checking if we need to run setup");
// Check if this is the first launch
SharedPreferences prefs = MainApplication.getSharedPreferences("mmm");
boolean firstLaunch = prefs.getString("last_shown_setup", null) == null;
if (BuildConfig.DEBUG)
Timber.i("First launch: %s", firstLaunch);
// Check if this is the first launch using prefs and if doSetupRestarting was passed in the intent
SharedPreferences prefs = MainApplication.getSharedPreferences();
boolean firstLaunch = !Objects.equals(prefs.getString("last_shown_setup", null), "v1");
// First launch
// this is intentionally separate from the above if statement, because it needs to be checked even if the first launch check is true due to some weird edge cases
if (getIntent().getBooleanExtra("doSetupRestarting", false)) {
// Restarting setup
firstLaunch = false;
}
if (BuildConfig.DEBUG) {
Timber.i("First launch: %s, pref value: %s", firstLaunch, prefs.getString("last_shown_setup", null));
}
if (firstLaunch) {
doSetupNowRunning = true;
// Launch setup wizard

@ -12,8 +12,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.SystemClock;
import android.security.keystore.KeyProperties;
import android.util.Base64;
import android.util.Log;
import androidx.annotation.NonNull;
@ -36,16 +34,6 @@ import com.google.common.hash.Hashing;
import com.topjohnwu.superuser.Shell;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
@ -55,13 +43,6 @@ import java.util.Locale;
import java.util.Objects;
import java.util.Random;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import io.noties.markwon.Markwon;
import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.ImagesPlugin;
@ -125,6 +106,10 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
intent.putExtra("secret", secret);
}
public static SharedPreferences getSharedPreferences() {
return INSTANCE.getSharedPreferences("mmm", MODE_PRIVATE);
}
// Is application wrapped, and therefore must reduce it's feature set.
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public static boolean isWrapped() {
@ -135,62 +120,58 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
return intent != null && intent.getLongExtra("secret", ~secret) == secret;
}
public static SharedPreferences getSharedPreferences(String store) {
return FoxApplication.getInitialApplication().getSharedPreferences(store, Context.MODE_PRIVATE);
}
public static boolean isShowcaseMode() {
return getSharedPreferences("mmm").getBoolean("pref_showcase_mode", false);
return getSharedPreferences().getBoolean("pref_showcase_mode", false);
}
public static boolean shouldPreventReboot() {
return getSharedPreferences("mmm").getBoolean("pref_prevent_reboot", true);
return getSharedPreferences().getBoolean("pref_prevent_reboot", true);
}
public static boolean isShowIncompatibleModules() {
return getSharedPreferences("mmm").getBoolean("pref_show_incompatible", false);
return getSharedPreferences().getBoolean("pref_show_incompatible", false);
}
public static boolean isForceDarkTerminal() {
return getSharedPreferences("mmm").getBoolean("pref_force_dark_terminal", false);
return getSharedPreferences().getBoolean("pref_force_dark_terminal", false);
}
public static boolean isTextWrapEnabled() {
return getSharedPreferences("mmm").getBoolean("pref_wrap_text", false);
return getSharedPreferences().getBoolean("pref_wrap_text", false);
}
public static boolean isDohEnabled() {
return getSharedPreferences("mmm").getBoolean("pref_dns_over_https", true);
return getSharedPreferences().getBoolean("pref_dns_over_https", true);
}
public static boolean isMonetEnabled() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && getSharedPreferences("mmm").getBoolean("pref_enable_monet", true);
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && getSharedPreferences().getBoolean("pref_enable_monet", true);
}
public static boolean isBlurEnabled() {
return getSharedPreferences("mmm").getBoolean("pref_enable_blur", false);
return getSharedPreferences().getBoolean("pref_enable_blur", false);
}
public static boolean isDeveloper() {
if (BuildConfig.DEBUG)
return true;
return getSharedPreferences("mmm").getBoolean("developer", false);
return getSharedPreferences().getBoolean("developer", false);
}
public static boolean isDisableLowQualityModuleFilter() {
return getSharedPreferences("mmm").getBoolean("pref_disable_low_quality_module_filter", false) && isDeveloper();
return getSharedPreferences().getBoolean("pref_disable_low_quality_module_filter", false) && isDeveloper();
}
public static boolean isUsingMagiskCommand() {
return InstallerInitializer.peekMagiskVersion() >= Constants.MAGISK_VER_CODE_INSTALL_COMMAND && getSharedPreferences("mmm").getBoolean("pref_use_magisk_install_command", false) && isDeveloper();
return InstallerInitializer.peekMagiskVersion() >= Constants.MAGISK_VER_CODE_INSTALL_COMMAND && getSharedPreferences().getBoolean("pref_use_magisk_install_command", false) && isDeveloper();
}
public static boolean isBackgroundUpdateCheckEnabled() {
return !wrapped && getSharedPreferences("mmm").getBoolean("pref_background_update_check", true);
return !wrapped && getSharedPreferences().getBoolean("pref_background_update_check", true);
}
public static boolean isAndroidacyTestMode() {
return isDeveloper() && getSharedPreferences("mmm").getBoolean("pref_androidacy_test_mode", false);
return isDeveloper() && getSharedPreferences().getBoolean("pref_androidacy_test_mode", false);
}
public static boolean isFirstBoot() {
@ -198,11 +179,11 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
}
public static void setHasGottenRootAccess(boolean bool) {
getSharedPreferences("mmm").edit().putBoolean("has_root_access", bool).apply();
getSharedPreferences().edit().putBoolean("has_root_access", bool).apply();
}
public static boolean isCrashReportingEnabled() {
return SentryMain.IS_SENTRY_INSTALLED && getSharedPreferences("mmm").getBoolean("pref_crash_reporting", BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING);
return SentryMain.IS_SENTRY_INSTALLED && getSharedPreferences().getBoolean("pref_crash_reporting", BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING);
}
public static SharedPreferences getBootSharedPreferences() {
@ -243,7 +224,7 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
@StyleRes int themeResId;
String theme;
boolean monet = isMonetEnabled();
switch (theme = getSharedPreferences("mmm").getString("pref_theme", "system")) {
switch (theme = getSharedPreferences().getString("pref_theme", "system")) {
default:
Timber.w("Unknown theme id: %s", theme);
case "system":
@ -289,9 +270,7 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
(this.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES;
case R.style.Theme_MagiskModuleManager_Monet_Light, R.style.Theme_MagiskModuleManager_Light ->
true;
case R.style.Theme_MagiskModuleManager_Monet_Dark, R.style.Theme_MagiskModuleManager_Dark ->
false;
case R.style.Theme_MagiskModuleManager_Monet_Black, R.style.Theme_MagiskModuleManager_Black ->
case R.style.Theme_MagiskModuleManager_Monet_Dark, R.style.Theme_MagiskModuleManager_Dark, R.style.Theme_MagiskModuleManager_Monet_Black, R.style.Theme_MagiskModuleManager_Black ->
false;
default -> super.isLightTheme();
};
@ -363,9 +342,9 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
} catch (
PackageManager.NameNotFoundException ignored) {
}
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("mmm");
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences();
// We are only one process so it's ok to do this
SharedPreferences bootPrefs = MainApplication.bootSharedPreferences = MainApplication.getSharedPreferences("mmm_boot");
SharedPreferences bootPrefs = MainApplication.bootSharedPreferences = MainApplication.getINSTANCE().getSharedPreferences("mmm_boot", Context.MODE_PRIVATE);
long lastBoot = System.currentTimeMillis() - SystemClock.elapsedRealtime();
long lastBootPrefs = bootPrefs.getLong("last_boot", 0);
if (lastBootPrefs == 0 || Math.abs(lastBoot - lastBootPrefs) > 100) {
@ -506,63 +485,6 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
}
}
// Access the encrypted key in the keystore, decrypt it with the secret,
// and use it to open and read from the realm again
public byte[] getExistingKey() {
Timber.d("Getting existing key...");
long startTime = System.currentTimeMillis();
// open a connection to the android keystore
KeyStore keyStore;
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
} catch (KeyStoreException | NoSuchAlgorithmException
| CertificateException | IOException e) {
throw new RuntimeException(e);
}
// access the encrypted key that's stored in shared preferences
byte[] initializationVectorAndEncryptedKey = Base64.decode(getSharedPreferences("realm_key")
.getString("iv_and_encrypted_key", null), Base64.DEFAULT);
ByteBuffer buffer = ByteBuffer.wrap(initializationVectorAndEncryptedKey);
buffer.order(ByteOrder.BIG_ENDIAN);
// extract the length of the initialization vector from the buffer
int initializationVectorLength = buffer.getInt();
// extract the initialization vector based on that length
byte[] initializationVector = new byte[initializationVectorLength];
buffer.get(initializationVector);
// extract the encrypted key
byte[] encryptedKey = new byte[initializationVectorAndEncryptedKey.length
- Integer.BYTES
- initializationVectorLength];
buffer.get(encryptedKey);
// create a cipher that uses AES encryption to decrypt our key
Cipher cipher;
try {
cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES
+ "/" + KeyProperties.BLOCK_MODE_CBC
+ "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new RuntimeException(e);
}
// decrypt the encrypted key with the secret key stored in the keystore
byte[] decryptedKey;
try {
final SecretKey secretKey =
(SecretKey) keyStore.getKey("realm_key", null);
final IvParameterSpec initializationVectorSpec =
new IvParameterSpec(initializationVector);
cipher.init(Cipher.DECRYPT_MODE, secretKey, initializationVectorSpec);
decryptedKey = cipher.doFinal(encryptedKey);
} catch (InvalidKeyException | UnrecoverableKeyException | NoSuchAlgorithmException |
BadPaddingException | KeyStoreException | IllegalBlockSizeException |
InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
}
long endTime = System.currentTimeMillis();
Timber.d("Got existing key in %d ms", endTime - startTime);
return decryptedKey; // pass to a realm configuration via encryptionKey()
}
private static class ReleaseTree extends Timber.Tree {
@Override
protected void log(int priority, String tag, @NonNull String message, Throwable t) {

@ -3,14 +3,13 @@ package com.fox2code.mmm;
import static com.fox2code.mmm.utils.IntentHelper.getActivity;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.util.Base64;
import android.view.View;
import android.view.WindowManager;
@ -34,26 +33,8 @@ import com.topjohnwu.superuser.internal.UiThreadHandler;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Objects;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import timber.log.Timber;
@ -78,7 +59,7 @@ public class SetupActivity extends FoxActivity implements LanguageActivity {
createFiles();
disableUpdateActivityForFdroidFlavor();
// Set theme
SharedPreferences prefs = MainApplication.getSharedPreferences("mmm");
SharedPreferences prefs = MainApplication.getSharedPreferences();
switch (prefs.getString("theme", "system")) {
case "light" -> setTheme(R.style.Theme_MagiskModuleManager_Monet_Light);
case "dark" -> setTheme(R.style.Theme_MagiskModuleManager_Monet_Dark);
@ -209,8 +190,12 @@ public class SetupActivity extends FoxActivity implements LanguageActivity {
}
// Restart the activity
MainActivity.doSetupRestarting = true;
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
PendingIntent intent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_IMMUTABLE);
try {
intent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
finish();
});
// Cancel button
@ -230,7 +215,7 @@ public class SetupActivity extends FoxActivity implements LanguageActivity {
public Resources.Theme getTheme() {
Resources.Theme theme = super.getTheme();
// Set the theme
SharedPreferences prefs = MainApplication.getSharedPreferences("mmm");
SharedPreferences prefs = MainApplication.getSharedPreferences();
switch (prefs.getString("pref_theme", "system")) {
case "light" -> theme.applyStyle(R.style.Theme_MagiskModuleManager_Monet_Light, true);
case "dark" -> theme.applyStyle(R.style.Theme_MagiskModuleManager_Monet_Dark, true);
@ -314,10 +299,16 @@ public class SetupActivity extends FoxActivity implements LanguageActivity {
File cookieFile = new File(MainApplication.getINSTANCE().getFilesDir(), cookieFileName);
// if the file exists, delete it
if (cookieFile.exists()) {
cookieFile.delete();
if (!cookieFile.delete()) {
Timber.e("Failed to delete cookie file");
throw new IllegalStateException("Failed to create cookie file. This probably means that the app doesn't have permission to write to the files directory");
}
}
// create the file
cookieFile.createNewFile();
if (!cookieFile.createNewFile()) {
Timber.e("Failed to create cookie file");
throw new IllegalStateException("Failed to create cookie file. This probably means that the app doesn't have permission to write to the files directory");
}
// create the file output stream
FileOutputStream fileOutputStream = new FileOutputStream(cookieFile);
// write the initial cookie to the file
@ -357,75 +348,4 @@ public class SetupActivity extends FoxActivity implements LanguageActivity {
}
}
}
@SuppressLint("NewApi")
public byte[] getNewKey() {
long startTime;
if (MainApplication.getSharedPreferences("mmm").getBoolean("keygen", false)) {
Timber.d("Key already generated, returning");
return MainApplication.getINSTANCE().getExistingKey();
} else {
startTime = System.currentTimeMillis();
Timber.d("Generating new key for realm");
}
// open a connection to the android keystore
KeyStore keyStore;
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
} catch (java.security.KeyStoreException | NoSuchAlgorithmException | CertificateException |
IOException e) {
throw new RuntimeException(e);
}
// create a securely generated random asymmetric RSA key
byte[] realmKey = new byte[Realm.ENCRYPTION_KEY_LENGTH];
new SecureRandom().nextBytes(realmKey);
// create a cipher that uses AES encryption -- we'll use this to encrypt our key
Cipher cipher;
try {
cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new RuntimeException(e);
}
// generate secret key
KeyGenerator keyGenerator;
try {
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new RuntimeException(e);
}
KeyGenParameterSpec keySpec = new KeyGenParameterSpec.Builder("realm_key", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT).setBlockModes(KeyProperties.BLOCK_MODE_CBC).setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7).setUserAuthenticationRequired(false).build();
try {
keyGenerator.init(keySpec);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
}
keyGenerator.generateKey();
// access the generated key in the android keystore, then
// use the cipher to create an encrypted version of the key
byte[] initializationVector;
byte[] encryptedKeyForRealm;
try {
SecretKey secretKey = (SecretKey) keyStore.getKey("realm_key", null);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
encryptedKeyForRealm = cipher.doFinal(realmKey);
initializationVector = cipher.getIV();
} catch (InvalidKeyException | UnrecoverableKeyException | NoSuchAlgorithmException |
KeyStoreException | BadPaddingException | IllegalBlockSizeException e) {
throw new RuntimeException(e);
}
// keep the encrypted key in shared preferences
// to persist it across application runs
byte[] initializationVectorAndEncryptedKey = new byte[Integer.BYTES + initializationVector.length + encryptedKeyForRealm.length];
ByteBuffer buffer = ByteBuffer.wrap(initializationVectorAndEncryptedKey);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.putInt(initializationVector.length);
buffer.put(initializationVector);
buffer.put(encryptedKeyForRealm);
MainApplication.getSharedPreferences("realm_key").edit().putString("iv_and_encrypted_key", Base64.encodeToString(initializationVectorAndEncryptedKey, Base64.NO_WRAP)).apply();
MainApplication.getSharedPreferences("mmm").edit().putBoolean("keygen", true).apply();
long endTime = System.currentTimeMillis();
Timber.d("Key generation took %s ms", endTime - startTime);
return realmKey; // pass to a realm configuration via encryptionKey()
}
}

@ -1,6 +1,7 @@
package com.fox2code.mmm.androidacy;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
@ -43,7 +44,7 @@ import timber.log.Timber;
@SuppressWarnings("KotlinInternalInJava")
public final class AndroidacyRepoData extends RepoData {
public static String token = MainApplication.getSharedPreferences("androidacy").getString("pref_androidacy_api_token", null);
public static String token = MainApplication.getINSTANCE().getSharedPreferences("androidacy", Context.MODE_PRIVATE).getString("pref_androidacy_api_token", null);
static {
HttpUrl.Builder OK_HTTP_URL_BUILDER = new HttpUrl.Builder().scheme("https");
@ -54,7 +55,7 @@ public final class AndroidacyRepoData extends RepoData {
@SuppressWarnings("unused")
public final String ClientID = BuildConfig.ANDROIDACY_CLIENT_ID;
public final SharedPreferences cachedPreferences = MainApplication.getSharedPreferences("androidacy");
public final SharedPreferences cachedPreferences = MainApplication.getINSTANCE().getSharedPreferences("androidacy", Context.MODE_PRIVATE);
private final boolean testMode;
private final String host;
public String[][] userInfo = new String[][]{{"role", null}, {"permissions", null}};
@ -88,7 +89,7 @@ public final class AndroidacyRepoData extends RepoData {
// limiting and fraud detection.
public static String generateDeviceId() {
// Try to get the device ID from the shared preferences
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("androidacy");
SharedPreferences sharedPreferences = MainApplication.getINSTANCE().getSharedPreferences("androidacy", Context.MODE_PRIVATE);
String deviceIdPref = sharedPreferences.getString("device_id", null);
if (deviceIdPref != null) {
return deviceIdPref;
@ -181,7 +182,7 @@ public final class AndroidacyRepoData extends RepoData {
protected boolean prepare() {
// If ANDROIDACY_CLIENT_ID is not set or is empty, disable this repo and return
if (Objects.equals(BuildConfig.ANDROIDACY_CLIENT_ID, "")) {
SharedPreferences.Editor editor = MainApplication.getSharedPreferences("mmm").edit();
SharedPreferences.Editor editor = MainApplication.getSharedPreferences().edit();
editor.putBoolean("pref_androidacy_repo_enabled", false);
editor.apply();
return false;
@ -272,7 +273,7 @@ public final class AndroidacyRepoData extends RepoData {
return false;
}
// Save token to shared preference
SharedPreferences.Editor editor = MainApplication.getSharedPreferences("androidacy").edit();
SharedPreferences.Editor editor = MainApplication.getINSTANCE().getSharedPreferences("androidacy", Context.MODE_PRIVATE).edit();
editor.putString("pref_androidacy_api_token", token);
editor.apply();
} catch (

@ -43,6 +43,7 @@ import java.util.concurrent.TimeUnit;
import timber.log.Timber;
@SuppressWarnings("SpellCheckingInspection")
public class BackgroundUpdateChecker extends Worker {
public static final String NOTIFICATION_CHANNEL_ID = "background_update";
public static final String NOTIFICATION_CHANNEL_ID_APP = "background_update_app";
@ -59,7 +60,7 @@ public class BackgroundUpdateChecker extends Worker {
static void doCheck(Context context) {
// first, check if the user has enabled background update checking
if (!MainApplication.getSharedPreferences("mmm").getBoolean("pref_background_update_check", false)) {
if (!MainApplication.getSharedPreferences().getBoolean("pref_background_update_check", false)) {
return;
}
if (MainApplication.getINSTANCE().isInForeground()) {
@ -67,7 +68,7 @@ public class BackgroundUpdateChecker extends Worker {
return;
}
// next, check if user requires wifi
if (MainApplication.getSharedPreferences("mmm").getBoolean("pref_background_update_check_wifi", true)) {
if (MainApplication.getSharedPreferences().getBoolean("pref_background_update_check_wifi", true)) {
// check if wifi is connected
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Network networkInfo = connectivityManager.getActiveNetwork();
@ -106,7 +107,7 @@ public class BackgroundUpdateChecker extends Worker {
continue;
// exclude all modules with id's stored in the pref pref_background_update_check_excludes
try {
if (MainApplication.getSharedPreferences("mmm").getStringSet("pref_background_update_check_excludes", null).contains(localModuleInfo.id))
if (MainApplication.getSharedPreferences().getStringSet("pref_background_update_check_excludes", null).contains(localModuleInfo.id))
continue;
} catch (
Exception ignored) {
@ -126,7 +127,7 @@ public class BackgroundUpdateChecker extends Worker {
}
});
// check for app updates
if (MainApplication.getSharedPreferences("mmm").getBoolean("pref_background_update_check_app", false)) {
if (MainApplication.getSharedPreferences().getBoolean("pref_background_update_check_app", false)) {
try {
boolean shouldUpdate = AppUpdateManager.getAppUpdateManager().checkUpdate(true);
if (shouldUpdate) {
@ -208,7 +209,7 @@ public class BackgroundUpdateChecker extends Worker {
public static void onMainActivityCreate(Context context) {
// Refuse to run if first_launch pref is not false
if (!Objects.equals(MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", null), "v1"))
if (!Objects.equals(MainApplication.getSharedPreferences().getString("last_shown_setup", null), "v1"))
return;
// create notification channel group
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

@ -55,7 +55,7 @@ public final class ModuleManager extends SyncManager {
protected void scanInternal(@NonNull UpdateListener updateListener) {
// if last_shown_setup is not "v1", them=n refuse to continue
if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v1")) {
if (!MainApplication.getSharedPreferences().getString("last_shown_setup", "").equals("v1")) {
return;
}
boolean firstScan = this.bootPrefs.getBoolean("mm_first_scan", true);

@ -148,7 +148,7 @@ public final class RepoManager extends SyncManager {
@SuppressWarnings("StatementWithEmptyBody")
private void populateDefaultCache(RepoData repoData) {
// if last_shown_setup is not "v1", them=n refuse to continue
if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v1")) {
if (!MainApplication.getSharedPreferences().getString("last_shown_setup", "").equals("v1")) {
return;
}
// make sure repodata is not null

@ -194,7 +194,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
@SuppressWarnings("ConstantConditions")
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
PreferenceManager preferenceManager = getPreferenceManager();
preferenceManager.setPreferenceDataStore(EncryptedPreferenceDataStore.getInstance());
preferenceManager.setSharedPreferencesName("mmm");
setPreferencesFromResource(R.xml.root_preferences, rootKey);
applyMaterial3(getPreferenceScreen());
// add bottom navigation bar to the settings
@ -262,10 +262,6 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
((ListPreference) findPreference("pref_theme")).setValue("system");
// Refresh activity
devModeStep = 0;
UiThreadHandler.handler.postDelayed(() -> {
MainApplication.getINSTANCE().updateTheme();
FoxActivity.getFoxActivity(this).setThemeRecreate(MainApplication.getINSTANCE().getManagerThemeResId());
}, 1);
}).show();
} else {
findPreference("pref_enable_monet").setEnabled(true);
@ -273,11 +269,11 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
findPreference("pref_enable_blur").setEnabled(true);
findPreference("pref_enable_blur").setSummary(null);
devModeStep = 0;
UiThreadHandler.handler.postDelayed(() -> {
MainApplication.getINSTANCE().updateTheme();
FoxActivity.getFoxActivity(this).setThemeRecreate(MainApplication.getINSTANCE().getManagerThemeResId());
}, 1);
}
UiThreadHandler.handler.postDelayed(() -> {
MainApplication.getINSTANCE().updateTheme();
FoxActivity.getFoxActivity(this).setThemeRecreate(MainApplication.getINSTANCE().getManagerThemeResId());
}, 1);
return true;
});
// Crash reporting
@ -460,7 +456,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
// set the box to unchecked
((SwitchPreferenceCompat) backgroundUpdateCheck).setChecked(false);
// ensure that the preference is false
MainApplication.getSharedPreferences("mmm").edit().putBoolean("pref_background_update_check", false).apply();
MainApplication.getSharedPreferences().edit().putBoolean("pref_background_update_check", false).apply();
new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.permission_notification_title).setMessage(R.string.permission_notification_message).setPositiveButton(R.string.ok, (dialog, which) -> {
// Open the app settings
Intent intent = new Intent();
@ -497,7 +493,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
int i = 0;
for (LocalModuleInfo localModuleInfo : localModuleInfos) {
moduleNames[i] = localModuleInfo.name;
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("mmm");
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences();
// get the stringset pref_background_update_check_excludes
Set<String> stringSet = sharedPreferences.getStringSet("pref_background_update_check_excludes", new HashSet<>());
// Stringset uses id, we show name
@ -507,7 +503,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
}
new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.background_update_check_excludes).setMultiChoiceItems(moduleNames, checkedItems, (dialog, which, isChecked) -> {
// get the stringset pref_background_update_check_excludes
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("mmm");
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences();
Set<String> stringSet = new HashSet<>(sharedPreferences.getStringSet("pref_background_update_check_excludes", new HashSet<>()));
// get id from name
String id;
@ -595,11 +591,11 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
if (devModeStep == 2) {
devModeStep = 0;
if (MainApplication.isDeveloper() && !BuildConfig.DEBUG) {
MainApplication.getSharedPreferences("mmm").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("mmm").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();
}
@ -811,7 +807,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
// Use MaterialAlertDialogBuilder
new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.warning).setCancelable(false).setMessage(R.string.androidacy_test_mode_warning).setPositiveButton(android.R.string.ok, (dialog, which) -> {
// User clicked OK button
MainApplication.getSharedPreferences("mmm").edit().putBoolean("androidacy_test_mode", true).apply();
MainApplication.getSharedPreferences().edit().putBoolean("androidacy_test_mode", true).apply();
// Check the switch
Intent mStartActivity = new Intent(requireContext(), MainActivity.class);
mStartActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
@ -829,10 +825,10 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
SwitchPreferenceCompat switchPreferenceCompat = (SwitchPreferenceCompat) androidacyTestMode;
switchPreferenceCompat.setChecked(false);
// There's probably a better way to do this than duplicate code but I'm too lazy to figure it out
MainApplication.getSharedPreferences("mmm").edit().putBoolean("androidacy_test_mode", false).apply();
MainApplication.getSharedPreferences().edit().putBoolean("androidacy_test_mode", false).apply();
}).show();
} else {
MainApplication.getSharedPreferences("mmm").edit().putBoolean("androidacy_test_mode", false).apply();
MainApplication.getSharedPreferences().edit().putBoolean("androidacy_test_mode", false).apply();
// Show dialog to restart app with ok button
new MaterialAlertDialogBuilder(this.requireContext()).setTitle(R.string.warning).setCancelable(false).setMessage(R.string.androidacy_test_mode_disable_warning).setNeutralButton(android.R.string.ok, (dialog, which) -> {
// User clicked OK button

@ -28,12 +28,12 @@ public class SentryMain {
@SuppressLint({"RestrictedApi", "UnspecifiedImmutableFlag"})
public static void initialize(final MainApplication mainApplication) {
// If first_launch pref is not false, refuse to initialize Sentry
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("mmm");
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences();
if (!Objects.equals(sharedPreferences.getString("last_shown_setup", null), "v1")) {
return;
}
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
SharedPreferences.Editor editor = MainApplication.getSharedPreferences("sentry").edit();
SharedPreferences.Editor editor = MainApplication.getINSTANCE().getSharedPreferences("sentry", Context.MODE_PRIVATE).edit();
editor.putString("lastExitReason", "crash");
editor.putLong("lastExitTime", System.currentTimeMillis());
editor.apply();

@ -4,8 +4,9 @@
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_container"
android:layout_width="match_parent"
android:paddingVertical="0dp"
android:layout_height="match_parent"
app:fitsSystemWindowsInsets="left|right"
app:fitsSystemWindowsInsets="start|end|bottom|top"
tools:context=".MainActivity">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
@ -21,7 +22,7 @@
android:id="@+id/blur_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="56dp">
android:paddingBottom="84dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/module_list"
@ -102,8 +103,8 @@
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/backgroundColor"
android:visibility="visible"
android:paddingBottom="0dp"
app:compatShadowEnabled="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"

@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:layout_marginVertical="2dp"
android:layout_marginVertical="3dp"
android:filterTouchesWhenObscured="true"
android:gravity="center_vertical"
android:orientation="vertical"

@ -18,7 +18,6 @@
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/backgroundColor"
android:visibility="visible"
app:compatShadowEnabled="true"
app:layout_constraintBottom_toBottomOf="parent"

@ -2,30 +2,31 @@
<style name="Theme.MagiskModuleManager.Monet.Light" parent="Theme.Material3.DynamicColors.Light">
<item name="android:statusBarColor">@color/status_bar_color</item>
<item name="colorBackgroundFloating">@color/system_accent2_200</item>
<item name="android:windowBackground">@color/system_accent2_100</item>
<item name="colorBackgroundFloating">@color/system_accent2_10</item>
<item name="android:windowBackground">@color/system_neutral1_10</item>
<item name="chipStyle">@style/Widget.Material3.Chip.Choice.Light</item>
<!-- fix bottom navigation bar color -->
<item name="android:navigationBarColor">@color/system_accent2_100</item>
</style>
<style name="Widget.Material3.Chip.Choice.Light" parent="Widget.Material3.Chip.Assist">
<item name="chipBackgroundColor">@color/system_accent2_300</item>
<item name="chipBackgroundColor">@color/system_accent2_100</item>
<item name="chipStrokeWidth">0dp</item>
<item name="chipIconTint">?attr/colorControlNormal</item>
</style>
<style name="Theme.MagiskModuleManager.Monet.Dark" parent="Theme.Material3.DynamicColors.Dark">
<item name="android:statusBarColor">@color/status_bar_color</item>
<item name="colorBackgroundFloating">@color/system_accent2_800</item>
<item name="android:windowBackground">@color/system_accent2_900</item>
<item name="colorBackgroundFloating">@color/system_neutral1_800</item>
<item name="android:windowBackground">@color/system_neutral1_900</item>
<item name="chipStyle">@style/Widget.Material3.Chip.Choice.Dark</item>
</style>
<!-- Black monet theme, which is just dark monet theme with black background -->
<style name="Theme.MagiskModuleManager.Monet.Black" parent="Theme.MagiskModuleManager.Monet.Dark">
<item name="colorBackgroundFloating">@color/black</item>
<item name="colorBackgroundFloating">@color/system_neutral2_900</item>
<item name="boxBackgroundColor">@color/black</item>
<item name="android:windowBackground">@color/black</item>
<item name="boxBackgroundColor">@color/dark_backgroundColor</item>
<item name="cardBackgroundColor">@color/cardview_dark_background</item>
<item name="backgroundColor">@color/black</item>
<item name="colorSurface">@color/black</item>
<!-- Darker variants of the monet colors -->
@ -37,7 +38,7 @@
<item name="chipBackgroundColor">@color/system_accent2_700</item>
<item name="chipSurfaceColor">@color/system_accent2_700</item>
<!-- chips should be dark, not black -->
<item name="chipStyle">@style/Widget.Material.Chip.Choice.Dark</item>
<item name="chipStyle">@style/Widget.Material.Chip.Choice.Black</item>
</style>
<style name="Widget.Material3.Chip.Choice.Dark" parent="Widget.Material3.Chip.Assist">
@ -46,8 +47,14 @@
<item name="chipIconTint">?attr/colorControlNormal</item>
</style>
<!-- I have no idea why this is needed, but it is -->
<style name="Widget.Material.Chip.Choice.Black" parent="Widget.Material3.Chip.Choice.Dark">
<item name="chipBackgroundColor">@color/system_accent2_800</item>
<item name="chipStrokeWidth">0dp</item>
<item name="chipIconTint">?attr/colorControlNormal</item>
</style>
<!-- Base application theme. -->
<!-- Base application theme. -->
<style name="Theme.MagiskModuleManager.Monet" parent="Theme.MagiskModuleManager.Monet.Light" />
</resources>

@ -37,15 +37,15 @@
<item name="chipIconTint">?attr/colorControlNormal</item>
</style>
<style name="Theme.MagiskModuleManager.Transparent.Light" parent="Theme.MagiskModuleManager.Monet.Dark">
<style name="Theme.MagiskModuleManager.Transparent.Light" parent="Theme.Material3.Light">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:statusBarColor">@color/status_bar_color</item>
<item name="android:windowShowWallpaper">true</item>
<!-- Fix text color in transparent theme -->
<item name="android:textColor">@color/white</item>
@ -56,7 +56,6 @@
<item name="actionBarStyle">@style/Widget.Material3.ActionBar.Solid</item>
<item name="chipStyle">@style/Widget.Material3.Chip.Choice.Light</item>
</style>
<style name="Theme.MagiskModuleManager.Dark" parent="Theme.Material3.Dark">
<item name="android:isLightTheme"
tools:targetApi="q">false</item>
@ -127,7 +126,7 @@
<item name="android:backgroundDimEnabled">false</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="windowNoTitle">true</item>
</style>

@ -21,7 +21,7 @@ buildscript {
project.ext.kotlin_version = "1.8.0"
project.ext.sentry_version = "6.14.0"
dependencies {
classpath 'com.android.tools.build:gradle:7.4.1'
classpath 'com.android.tools.build:gradle:7.4.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10"
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${latestAboutLibsRelease}"
classpath 'io.sentry:sentry-android:6.14.0'

Loading…
Cancel
Save