Proper implementation for black theme

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/230/head
androidacy-user 1 year ago
parent ff1cb4fbb6
commit 0339dd7525

@ -47,37 +47,33 @@ import io.noties.markwon.syntax.SyntaxHighlightPlugin;
import io.noties.prism4j.Prism4j; import io.noties.prism4j.Prism4j;
import io.noties.prism4j.annotations.PrismBundle; import io.noties.prism4j.annotations.PrismBundle;
@PrismBundle( @PrismBundle(includeAll = true, grammarLocatorClassName = ".Prism4jGrammarLocator")
includeAll = true, public class MainApplication extends FoxApplication implements androidx.work.Configuration.Provider {
grammarLocatorClassName = ".Prism4jGrammarLocator"
)
public class MainApplication extends FoxApplication
implements androidx.work.Configuration.Provider {
private static final String TAG = "MainApplication"; private static final String TAG = "MainApplication";
private static final String timeFormatString = "dd MMM yyyy"; // Example: 13 july 2001 private static final String timeFormatString = "dd MMM yyyy"; // Example: 13 july 2001
private static Locale timeFormatLocale =
Resources.getSystem().getConfiguration().locale;
private static SimpleDateFormat timeFormat =
new SimpleDateFormat(timeFormatString, timeFormatLocale);
private static final Shell.Builder shellBuilder; private static final Shell.Builder shellBuilder;
private static final long secret; private static final long secret;
@SuppressLint("RestrictedApi") // Use FoxProcess wrapper helper. @SuppressLint("RestrictedApi") // Use FoxProcess wrapper helper.
private static final boolean wrapped = !FoxProcessExt.isRootLoader(); private static final boolean wrapped = !FoxProcessExt.isRootLoader();
private static Locale timeFormatLocale = Resources.getSystem().getConfiguration().locale;
private static SimpleDateFormat timeFormat = new SimpleDateFormat(timeFormatString, timeFormatLocale);
private static SharedPreferences bootSharedPreferences; private static SharedPreferences bootSharedPreferences;
private static String relPackageName = BuildConfig.APPLICATION_ID; private static String relPackageName = BuildConfig.APPLICATION_ID;
private static MainApplication INSTANCE; private static MainApplication INSTANCE;
private static boolean firstBoot; private static boolean firstBoot;
// Provides the Context for the base application
public Context FoxApplication = this;
static { static {
Shell.setDefaultBuilder(shellBuilder = Shell.Builder.create() Shell.setDefaultBuilder(shellBuilder = Shell.Builder.create().setFlags(Shell.FLAG_REDIRECT_STDERR).setTimeout(10).setInitializers(InstallerInitializer.class));
.setFlags(Shell.FLAG_REDIRECT_STDERR)
.setTimeout(10).setInitializers(InstallerInitializer.class)
);
secret = new Random().nextLong(); secret = new Random().nextLong();
} }
// Provides the Context for the base application
public Context FoxApplication = this;
@StyleRes
private int managerThemeResId = R.style.Theme_MagiskModuleManager;
private FoxThemeWrapper markwonThemeContext;
private Markwon markwon;
public MainApplication() { public MainApplication() {
if (INSTANCE != null && INSTANCE != this) if (INSTANCE != null && INSTANCE != this)
throw new IllegalStateException("Duplicate application instance!"); throw new IllegalStateException("Duplicate application instance!");
@ -90,10 +86,8 @@ public class MainApplication extends FoxApplication
public static void addSecret(Intent intent) { public static void addSecret(Intent intent) {
ComponentName componentName = intent.getComponent(); ComponentName componentName = intent.getComponent();
String packageName = componentName != null ? String packageName = componentName != null ? componentName.getPackageName() : intent.getPackage();
componentName.getPackageName() : intent.getPackage(); if (!BuildConfig.APPLICATION_ID.equalsIgnoreCase(packageName) && !relPackageName.equals(packageName)) {
if (!BuildConfig.APPLICATION_ID.equalsIgnoreCase(packageName) &&
!relPackageName.equals(packageName)) {
// Code safeguard, we should never reach here. // Code safeguard, we should never reach here.
throw new IllegalArgumentException("Can't add secret to outbound Intent"); throw new IllegalArgumentException("Can't add secret to outbound Intent");
} }
@ -139,29 +133,23 @@ public class MainApplication extends FoxApplication
} }
public static boolean isMonetEnabled() { public static boolean isMonetEnabled() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && getSharedPreferences().getBoolean("pref_enable_monet", true);
getSharedPreferences().getBoolean("pref_enable_monet", true);
} }
public static boolean isBlurEnabled() { public static boolean isBlurEnabled() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && getSharedPreferences().getBoolean("pref_enable_blur", false);
getSharedPreferences().getBoolean("pref_enable_blur", false);
} }
public static boolean isDeveloper() { public static boolean isDeveloper() {
return BuildConfig.DEBUG || return BuildConfig.DEBUG || getSharedPreferences().getBoolean("developer", false);
getSharedPreferences().getBoolean("developer", false);
} }
public static boolean isDisableLowQualityModuleFilter() { public static boolean isDisableLowQualityModuleFilter() {
return getSharedPreferences().getBoolean("pref_disable_low_quality_module_filter", return getSharedPreferences().getBoolean("pref_disable_low_quality_module_filter", false) && isDeveloper();
false) && isDeveloper();
} }
public static boolean isUsingMagiskCommand() { public static boolean isUsingMagiskCommand() {
return InstallerInitializer.peekMagiskVersion() >= Constants.MAGISK_VER_CODE_INSTALL_COMMAND return InstallerInitializer.peekMagiskVersion() >= Constants.MAGISK_VER_CODE_INSTALL_COMMAND && getSharedPreferences().getBoolean("pref_use_magisk_install_command", false) && isDeveloper();
&& getSharedPreferences().getBoolean("pref_use_magisk_install_command", false)
&& isDeveloper();
} }
public static boolean isBackgroundUpdateCheckEnabled() { public static boolean isBackgroundUpdateCheckEnabled() {
@ -169,8 +157,7 @@ public class MainApplication extends FoxApplication
} }
public static boolean isAndroidacyTestMode() { public static boolean isAndroidacyTestMode() {
return isDeveloper() && return isDeveloper() && getSharedPreferences().getBoolean("pref_androidacy_test_mode", false);
getSharedPreferences().getBoolean("pref_androidacy_test_mode", false);
} }
public static boolean isFirstBoot() { public static boolean isFirstBoot() {
@ -186,8 +173,7 @@ public class MainApplication extends FoxApplication
} }
public static boolean isCrashReportingEnabled() { public static boolean isCrashReportingEnabled() {
return getSharedPreferences().getBoolean("pref_crash_reporting", return getSharedPreferences().getBoolean("pref_crash_reporting", BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING && !BuildConfig.DEBUG);
BuildConfig.DEFAULT_ENABLE_CRASH_REPORTING && !BuildConfig.DEBUG);
} }
public static SharedPreferences getBootSharedPreferences() { public static SharedPreferences getBootSharedPreferences() {
@ -203,28 +189,17 @@ public class MainApplication extends FoxApplication
return timeFormat.format(new Date(timeStamp)); return timeFormat.format(new Date(timeStamp));
} }
@StyleRes
private int managerThemeResId = R.style.Theme_MagiskModuleManager;
private FoxThemeWrapper markwonThemeContext;
private Markwon markwon;
public static boolean isNotificationPermissionGranted() { public static boolean isNotificationPermissionGranted() {
return NotificationManagerCompat.from(INSTANCE).areNotificationsEnabled(); return NotificationManagerCompat.from(INSTANCE).areNotificationsEnabled();
} }
public Markwon getMarkwon() { public Markwon getMarkwon() {
if (this.markwon != null) if (this.markwon != null) return this.markwon;
return this.markwon;
FoxThemeWrapper contextThemeWrapper = this.markwonThemeContext; FoxThemeWrapper contextThemeWrapper = this.markwonThemeContext;
if (contextThemeWrapper == null) { if (contextThemeWrapper == null) {
contextThemeWrapper = this.markwonThemeContext = contextThemeWrapper = this.markwonThemeContext = new FoxThemeWrapper(this, this.managerThemeResId);
new FoxThemeWrapper(this, this.managerThemeResId);
} }
Markwon markwon = Markwon.builder(contextThemeWrapper).usePlugin(HtmlPlugin.create()) Markwon markwon = Markwon.builder(contextThemeWrapper).usePlugin(HtmlPlugin.create()).usePlugin(SyntaxHighlightPlugin.create(new Prism4j(new Prism4jGrammarLocator()), new Prism4jSwitchTheme())).usePlugin(ImagesPlugin.create().addSchemeHandler(OkHttpNetworkSchemeHandler.create(Http.getHttpClientWithCache()))).build();
.usePlugin(SyntaxHighlightPlugin.create(
new Prism4j(new Prism4jGrammarLocator()), new Prism4jSwitchTheme()))
.usePlugin(ImagesPlugin.create().addSchemeHandler(
OkHttpNetworkSchemeHandler.create(Http.getHttpClientWithCache()))).build();
return this.markwon = markwon; return this.markwon = markwon;
} }
@ -238,43 +213,6 @@ public class MainApplication extends FoxApplication
return new androidx.work.Configuration.Builder().build(); return new androidx.work.Configuration.Builder().build();
} }
private class Prism4jSwitchTheme implements Prism4jTheme {
private final Prism4jTheme light = new Prism4jThemeDefault(Color.TRANSPARENT);
private final Prism4jTheme dark = new Prism4jThemeDarkula(Color.TRANSPARENT);
// Black theme
private final Prism4jTheme black = new Prism4jThemeDefault(Color.BLACK);
private Prism4jTheme getTheme() {
// isLightTheme() means light, isDarkTheme() means dark, and isBlackTheme() means black
return isLightTheme() ? light : isDarkTheme() ? dark : black;
}
@Override
public int background() {
return this.getTheme().background();
}
@Override
public int textColor() {
return this.getTheme().textColor();
}
@Override
public void apply(@NonNull String language, @NonNull Prism4j.Syntax syntax,
@NonNull SpannableStringBuilder builder, int start, int end) {
this.getTheme().apply(language, syntax, builder, start, end);
}
}
@SuppressLint("NonConstantResourceId")
public void setManagerThemeResId(@StyleRes int resId) {
this.managerThemeResId = resId;
if (this.markwonThemeContext != null) {
this.markwonThemeContext.setTheme(resId);
}
this.markwon = null;
}
public void updateTheme() { public void updateTheme() {
@StyleRes int themeResId; @StyleRes int themeResId;
String theme; String theme;
@ -283,27 +221,22 @@ public class MainApplication extends FoxApplication
default: default:
Log.w("MainApplication", "Unknown theme id: " + theme); Log.w("MainApplication", "Unknown theme id: " + theme);
case "system": case "system":
themeResId = monet ? themeResId = monet ? R.style.Theme_MagiskModuleManager_Monet : R.style.Theme_MagiskModuleManager;
R.style.Theme_MagiskModuleManager_Monet :
R.style.Theme_MagiskModuleManager;
break; break;
case "dark": case "dark":
themeResId = monet ? themeResId = monet ? R.style.Theme_MagiskModuleManager_Monet_Dark : R.style.Theme_MagiskModuleManager_Dark;
R.style.Theme_MagiskModuleManager_Monet_Dark : break;
R.style.Theme_MagiskModuleManager_Dark; case "black":
themeResId = monet ? R.style.Theme_MagiskModuleManager_Monet_Black : R.style.Theme_MagiskModuleManager_Black;
break; break;
case "light": case "light":
themeResId = monet ? themeResId = monet ? R.style.Theme_MagiskModuleManager_Monet_Light : R.style.Theme_MagiskModuleManager_Light;
R.style.Theme_MagiskModuleManager_Monet_Light :
R.style.Theme_MagiskModuleManager_Light;
break; break;
} }
// Handle force black theme // Handle force black theme
if (theme.equals("dark") && isForceBlackThemeEnabled()) { if (theme.equals("dark") && isForceBlackThemeEnabled()) {
// just black background // just black background
themeResId = monet ? themeResId = monet ? R.style.Theme_MagiskModuleManager_Monet_Black : R.style.Theme_MagiskModuleManager_Black;
R.style.Theme_MagiskModuleManager_Monet_Black :
R.style.Theme_MagiskModuleManager_Black;
} }
this.setManagerThemeResId(themeResId); this.setManagerThemeResId(themeResId);
} }
@ -317,14 +250,21 @@ public class MainApplication extends FoxApplication
return managerThemeResId; return managerThemeResId;
} }
@SuppressLint("NonConstantResourceId")
public void setManagerThemeResId(@StyleRes int resId) {
this.managerThemeResId = resId;
if (this.markwonThemeContext != null) {
this.markwonThemeContext.setTheme(resId);
}
this.markwon = null;
}
@SuppressLint("NonConstantResourceId") @SuppressLint("NonConstantResourceId")
public boolean isLightTheme() { public boolean isLightTheme() {
switch (this.managerThemeResId) { switch (this.managerThemeResId) {
case R.style.Theme_MagiskModuleManager: case R.style.Theme_MagiskModuleManager:
case R.style.Theme_MagiskModuleManager_Monet: case R.style.Theme_MagiskModuleManager_Monet:
return (this.getResources().getConfiguration().uiMode return (this.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES;
& Configuration.UI_MODE_NIGHT_MASK)
!= Configuration.UI_MODE_NIGHT_YES;
case R.style.Theme_MagiskModuleManager_Monet_Light: case R.style.Theme_MagiskModuleManager_Monet_Light:
case R.style.Theme_MagiskModuleManager_Light: case R.style.Theme_MagiskModuleManager_Light:
return true; return true;
@ -353,14 +293,12 @@ public class MainApplication extends FoxApplication
}*/ }*/
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences(); SharedPreferences sharedPreferences = MainApplication.getSharedPreferences();
// We are only one process so it's ok to do this // We are only one process so it's ok to do this
SharedPreferences bootPrefs = MainApplication.bootSharedPreferences = SharedPreferences bootPrefs = MainApplication.bootSharedPreferences = this.getSharedPreferences("mmm_boot", MODE_PRIVATE);
this.getSharedPreferences("mmm_boot", MODE_PRIVATE);
long lastBoot = System.currentTimeMillis() - SystemClock.elapsedRealtime(); long lastBoot = System.currentTimeMillis() - SystemClock.elapsedRealtime();
long lastBootPrefs = bootPrefs.getLong("last_boot", 0); long lastBootPrefs = bootPrefs.getLong("last_boot", 0);
if (lastBootPrefs == 0 || Math.abs(lastBoot - lastBootPrefs) > 100) { if (lastBootPrefs == 0 || Math.abs(lastBoot - lastBootPrefs) > 100) {
boolean firstBoot = sharedPreferences.getBoolean("first_boot", true); boolean firstBoot = sharedPreferences.getBoolean("first_boot", true);
bootPrefs.edit().clear().putLong("last_boot", lastBoot) bootPrefs.edit().clear().putLong("last_boot", lastBoot).putBoolean("first_boot", firstBoot).apply();
.putBoolean("first_boot", firstBoot).apply();
if (firstBoot) { if (firstBoot) {
sharedPreferences.edit().putBoolean("first_boot", false).apply(); sharedPreferences.edit().putBoolean("first_boot", false).apply();
} }
@ -374,12 +312,10 @@ public class MainApplication extends FoxApplication
// Update SSL Ciphers if update is possible // Update SSL Ciphers if update is possible
GMSProviderInstaller.installIfNeeded(this); GMSProviderInstaller.installIfNeeded(this);
// Update emoji config // Update emoji config
FontRequestEmojiCompatConfig fontRequestEmojiCompatConfig = FontRequestEmojiCompatConfig fontRequestEmojiCompatConfig = DefaultEmojiCompatConfig.create(this);
DefaultEmojiCompatConfig.create(this);
if (fontRequestEmojiCompatConfig != null) { if (fontRequestEmojiCompatConfig != null) {
fontRequestEmojiCompatConfig.setReplaceAll(true); fontRequestEmojiCompatConfig.setReplaceAll(true);
fontRequestEmojiCompatConfig fontRequestEmojiCompatConfig.setMetadataLoadStrategy(EmojiCompat.LOAD_STRATEGY_MANUAL);
.setMetadataLoadStrategy(EmojiCompat.LOAD_STRATEGY_MANUAL);
EmojiCompat emojiCompat = EmojiCompat.init(fontRequestEmojiCompatConfig); EmojiCompat emojiCompat = EmojiCompat.init(fontRequestEmojiCompatConfig);
new Thread(() -> { new Thread(() -> {
Log.d("MainApplication", "Loading emoji compat..."); Log.d("MainApplication", "Loading emoji compat...");
@ -408,9 +344,35 @@ public class MainApplication extends FoxApplication
Locale newTimeFormatLocale = newConfig.locale; Locale newTimeFormatLocale = newConfig.locale;
if (timeFormatLocale != newTimeFormatLocale) { if (timeFormatLocale != newTimeFormatLocale) {
timeFormatLocale = newTimeFormatLocale; timeFormatLocale = newTimeFormatLocale;
timeFormat = new SimpleDateFormat( timeFormat = new SimpleDateFormat(timeFormatString, timeFormatLocale);
timeFormatString, timeFormatLocale);
} }
super.onConfigurationChanged(newConfig); super.onConfigurationChanged(newConfig);
} }
private class Prism4jSwitchTheme implements Prism4jTheme {
private final Prism4jTheme light = new Prism4jThemeDefault(Color.TRANSPARENT);
private final Prism4jTheme dark = new Prism4jThemeDarkula(Color.TRANSPARENT);
// Black theme
private final Prism4jTheme black = new Prism4jThemeDefault(Color.BLACK);
private Prism4jTheme getTheme() {
// isLightTheme() means light, isDarkTheme() means dark, and isBlackTheme() means black
return isLightTheme() ? light : isDarkTheme() ? dark : black;
}
@Override
public int background() {
return this.getTheme().background();
}
@Override
public int textColor() {
return this.getTheme().textColor();
}
@Override
public void apply(@NonNull String language, @NonNull Prism4j.Syntax syntax, @NonNull SpannableStringBuilder builder, int start, int end) {
this.getTheme().apply(language, syntax, builder, start, end);
}
}
} }

@ -137,20 +137,6 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
}, 1); }, 1);
return true; return true;
}); });
// Force black theme - depends on themePreference being system or dark
SwitchPreferenceCompat forceBlackPreference = findPreference("pref_force_black_theme");
// Set invisible if theme is not dark or system
forceBlackPreference.setVisible(themePreference.getValue().equals("dark") ||
themePreference.getValue().equals("system"));
forceBlackPreference.setOnPreferenceChangeListener((preference, newValue) -> {
devModeStep = 0;
UiThreadHandler.handler.postDelayed(() -> {
MainApplication.getINSTANCE().updateTheme();
FoxActivity.getFoxActivity(this).setThemeRecreate(
MainApplication.getINSTANCE().getManagerThemeResId());
}, 1);
return true;
});
// Crash reporting // Crash reporting
TwoStatePreference crashReportingPreference = findPreference("pref_crash_reporting"); TwoStatePreference crashReportingPreference = findPreference("pref_crash_reporting");
if (!SentryMain.IS_SENTRY_INSTALLED) crashReportingPreference.setVisible(false); if (!SentryMain.IS_SENTRY_INSTALLED) crashReportingPreference.setVisible(false);

@ -30,6 +30,9 @@
<item name="cardBackgroundColor">@color/black</item> <item name="cardBackgroundColor">@color/black</item>
<item name="backgroundColor">@color/black</item> <item name="backgroundColor">@color/black</item>
<item name="colorSurface">@color/black</item> <item name="colorSurface">@color/black</item>
<!-- Darker variants of the colors -->
<item name="colorPrimaryVariant">@color/system_accent2_900</item>
<item name="colorSecondaryVariant">@color/system_accent2_900</item>
</style> </style>
<style name="Widget.Material3.Chip.Choice.Dark" parent="Widget.Material3.Chip.Assist"> <style name="Widget.Material3.Chip.Choice.Dark" parent="Widget.Material3.Chip.Assist">

@ -3,12 +3,14 @@
<string-array name="theme_values" translatable="false"> <string-array name="theme_values" translatable="false">
<item>system</item> <item>system</item>
<item>dark</item> <item>dark</item>
<item>black</item>
<item>light</item> <item>light</item>
</string-array> </string-array>
<string-array name="theme_values_names"> <string-array name="theme_values_names">
<item>System</item> <item>System</item>
<item>Dark</item> <item>Dark</item>
<item>AMOLED Black</item>
<item>Light</item> <item>Light</item>
</string-array> </string-array>
<string-array name="permission_notification_dont_ask_again">Don't prompt again</string-array> <string-array name="permission_notification_dont_ask_again">Don't prompt again</string-array>

@ -91,6 +91,9 @@
<item name="cardBackgroundColor">@color/black</item> <item name="cardBackgroundColor">@color/black</item>
<item name="backgroundColor">@color/black</item> <item name="backgroundColor">@color/black</item>
<item name="colorSurface">@color/black</item> <item name="colorSurface">@color/black</item>
<!-- Darker variants of the colors -->
<item name="colorPrimaryVariant">@color/system_accent2_900</item>
<item name="colorSecondaryVariant">@color/system_accent2_900</item>
</style> </style>
<style name="Widget.Material.Chip.Choice.Dark" parent="Widget.MaterialComponents.Chip.Action"> <style name="Widget.Material.Chip.Choice.Dark" parent="Widget.MaterialComponents.Chip.Action">

@ -56,15 +56,6 @@
app:singleLineTitle="false" app:singleLineTitle="false"
app:title="@string/theme_pref" /> app:title="@string/theme_pref" />
<!-- Force black theme -->
<SwitchPreferenceCompat
app:defaultValue="false"
app:icon="@drawable/ic_baseline_palette_24"
app:key="pref_force_black_theme"
app:singleLineTitle="false"
app:summary="@string/force_black_theme_desc"
app:title="@string/force_black_theme_pref" />
<Preference <Preference
app:icon="@drawable/ic_baseline_language_24" app:icon="@drawable/ic_baseline_language_24"
app:key="pref_language_selector" app:key="pref_language_selector"

Loading…
Cancel
Save