Merge branch 'Fox2Code:master' into master

pull/27/head
007 3 years ago committed by GitHub
commit b8c1063754
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,13 +7,16 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import com.fox2code.mmm.compat.CompatActivity;
import com.fox2code.mmm.installer.InstallerInitializer;
@ -25,15 +28,25 @@ import com.fox2code.mmm.utils.Http;
import com.fox2code.mmm.utils.IntentHelper;
import com.google.android.material.progressindicator.LinearProgressIndicator;
import eightbitlab.com.blurview.BlurView;
import eightbitlab.com.blurview.RenderScriptBlur;
public class MainActivity extends CompatActivity implements SwipeRefreshLayout.OnRefreshListener,
SearchView.OnQueryTextListener, SearchView.OnCloseListener {
SearchView.OnQueryTextListener, SearchView.OnCloseListener,
OverScrollManager.OverScrollHelper {
private static final String TAG = "MainActivity";
private static final int PRECISION = 10000;
public final ModuleViewListBuilder moduleViewListBuilder;
public LinearProgressIndicator progressIndicator;
private ModuleViewAdapter moduleViewAdapter;
private SwipeRefreshLayout swipeRefreshLayout;
private int swipeRefreshLayoutOrigStartOffset;
private int swipeRefreshLayoutOrigEndOffset;
private long swipeRefreshBlocker = 0;
private int overScrollInsetTop;
private int overScrollInsetBottom;
private TextView actionBarPadding;
private BlurView actionBarBlur;
private RecyclerView moduleList;
private CardView searchCard;
private SearchView searchView;
@ -55,10 +68,25 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
setContentView(R.layout.activity_main);
this.setTitle(R.string.app_name);
this.getWindow().setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
setActionBarBackground(null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
WindowManager.LayoutParams layoutParams = this.getWindow().getAttributes();
layoutParams.layoutInDisplayCutoutMode = // Support cutout in Android 9
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
this.getWindow().setAttributes(layoutParams);
}
this.actionBarPadding = findViewById(R.id.action_bar_padding);
this.actionBarBlur = findViewById(R.id.action_bar_blur);
this.progressIndicator = findViewById(R.id.progress_bar);
this.swipeRefreshLayout = findViewById(R.id.swipe_refresh);
this.swipeRefreshLayoutOrigStartOffset =
this.swipeRefreshLayout.getProgressViewStartOffset();
this.swipeRefreshLayoutOrigEndOffset =
this.swipeRefreshLayout.getProgressViewEndOffset();
this.swipeRefreshBlocker = Long.MAX_VALUE;
this.moduleList = findViewById(R.id.module_list);
this.searchCard = findViewById(R.id.search_card);
@ -67,7 +95,13 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
this.moduleList.setAdapter(this.moduleViewAdapter);
this.moduleList.setLayoutManager(new LinearLayoutManager(this));
this.moduleList.setItemViewCacheSize(4); // Default is 2
OverScrollManager.install(this.moduleList, this);
this.swipeRefreshLayout.setOnRefreshListener(this);
this.actionBarBlur.setupWith(this.moduleList).setFrameClearDrawable(
this.getWindow().getDecorView().getBackground())
.setBlurAlgorithm(new RenderScriptBlur(this))
.setBlurRadius(5F).setBlurAutoUpdate(true)
.setHasFixedTransformationMatrix(true);
this.moduleList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
@ -76,7 +110,7 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
}
});
this.searchView.setImeOptions(EditorInfo.IME_ACTION_SEARCH |
EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_FLAG_FORCE_ASCII);
EditorInfo.IME_FLAG_NO_FULLSCREEN);
this.searchView.setOnQueryTextListener(this);
this.searchView.setOnCloseListener(this);
this.searchView.setOnQueryTextFocusChangeListener((v, h) -> {
@ -121,6 +155,8 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
runOnUiThread(() -> {
progressIndicator.setIndeterminate(false);
progressIndicator.setMax(PRECISION);
// Fix insets not being accounted for correctly
updateScreenInsets(getResources().getConfiguration());
});
Log.i(TAG, "Scanning for modules!");
final int max = ModuleManager.getINSTANCE().getUpdatableModuleCount();
@ -158,6 +194,7 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
progressIndicator.setProgressCompat(PRECISION, true);
progressIndicator.setVisibility(View.GONE);
searchView.setEnabled(true);
setActionBarBackground(null);
});
moduleViewListBuilder.appendRemoteModules();
moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter);
@ -175,12 +212,32 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
TypedValue value = new TypedValue();
theme.resolveAttribute(backgroundAttr, value, true);
this.searchCard.setCardBackgroundColor(value.data);
this.searchCard.setAlpha(iconified ? 0.70F : 1F);
this.searchCard.setAlpha(iconified ? 0.80F : 1F);
}
private void updateScreenInsets() {
this.runOnUiThread(() -> this.updateScreenInsets(
this.getResources().getConfiguration()));
}
private void updateScreenInsets(Configuration configuration) {
boolean landscape = configuration.orientation ==
Configuration.ORIENTATION_LANDSCAPE;
int statusBarHeight = getStatusBarHeight();
int actionBarHeight = getActionBarHeight();
int combinedBarsHeight = statusBarHeight + actionBarHeight;
this.actionBarPadding.setMinHeight(combinedBarsHeight);
this.swipeRefreshLayout.setProgressViewOffset(false,
swipeRefreshLayoutOrigStartOffset + combinedBarsHeight,
swipeRefreshLayoutOrigEndOffset + combinedBarsHeight);
this.moduleViewListBuilder.setHeaderPx(actionBarHeight);
int bottomInset = (landscape ? 0 : this.getNavigationBarHeight());
this.moduleViewListBuilder.setFooterPx(
this.getNavigationBarHeight() + this.searchCard.getHeight());
bottomInset + this.searchCard.getHeight());
this.moduleViewListBuilder.updateInsets();
this.actionBarBlur.invalidate();
this.overScrollInsetTop = combinedBarsHeight;
this.overScrollInsetBottom = bottomInset;
}
@Override
@ -234,6 +291,12 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
this.initMode = false;
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
this.updateScreenInsets(newConfig);
super.onConfigurationChanged(newConfig);
}
@Override
public void onRefresh() {
if (this.swipeRefreshBlocker > System.currentTimeMillis() ||
@ -301,4 +364,14 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
}
return false;
}
@Override
public int getOverScrollInsetTop() {
return this.overScrollInsetTop;
}
@Override
public int getOverScrollInsetBottom() {
return this.overScrollInsetBottom;
}
}

@ -24,7 +24,7 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
public final String moduleId;
public final NotificationType notificationType;
public final Type separator;
public final int footerPx;
public int footerPx;
public View.OnClickListener onClickListener;
public LocalModuleInfo moduleInfo;
public RepoModule repoModule;
@ -34,32 +34,33 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
this.moduleId = Objects.requireNonNull(moduleId);
this.notificationType = null;
this.separator = null;
this.footerPx = 0;
this.footerPx = -1;
}
public ModuleHolder(NotificationType notificationType) {
this.moduleId = "";
this.notificationType = Objects.requireNonNull(notificationType);
this.separator = null;
this.footerPx = 0;
this.footerPx = -1;
}
public ModuleHolder(Type separator) {
this.moduleId = "";
this.notificationType = null;
this.separator = separator;
this.footerPx = 0;
this.footerPx = -1;
}
public ModuleHolder(int footerPx) {
public ModuleHolder(int footerPx,boolean header) {
this.moduleId = "";
this.notificationType = null;
this.separator = null;
this.footerPx = footerPx;
this.filterLevel = header ? 1 : 0;
}
public boolean isModuleHolder() {
return this.notificationType == null && this.separator == null && this.footerPx == 0;
return this.notificationType == null && this.separator == null && this.footerPx == -1;
}
public ModuleInfo getMainModuleInfo() {
@ -115,7 +116,7 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
}
public Type getType() {
if (this.footerPx != 0) {
if (this.footerPx != -1) {
return Type.FOOTER;
} else if (this.separator != null) {
return Type.SEPARATOR;
@ -145,7 +146,7 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
public boolean shouldRemove() {
return this.notificationType != null ? this.notificationType.shouldRemove() :
this.footerPx == 0 && this.moduleInfo == null &&
this.footerPx == -1 && this.moduleInfo == null &&
(this.repoModule == null || !this.repoModule.repoData.isEnabled() ||
(PropUtils.isLowQualityModule(this.repoModule.moduleInfo) &&
!MainApplication.isDisableLowQualityModuleFilter()));
@ -207,6 +208,7 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
}
public enum Type implements Comparator<ModuleHolder> {
HEADER(R.string.loading, false, false),
SEPARATOR(R.string.loading, false, false) {
@Override
@SuppressWarnings("ConstantConditions")

@ -26,6 +26,7 @@ import com.google.android.material.switchmaterial.SwitchMaterial;
import com.topjohnwu.superuser.internal.UiThreadHandler;
import java.util.ArrayList;
import java.util.Objects;
public final class ModuleViewAdapter extends RecyclerView.Adapter<ModuleViewAdapter.ViewHolder> {
private static final boolean DEBUG = false;
@ -182,14 +183,16 @@ public final class ModuleViewAdapter extends RecyclerView.Adapter<ModuleViewAdap
if (localModuleInfo == null || moduleInfo.versionCode >
localModuleInfo.updateVersionCode) {
this.creditText.setText((localModuleInfo == null ||
moduleInfo.version.equals(localModuleInfo.version) ?
Objects.equals(moduleInfo.version, localModuleInfo.version) ?
moduleInfo.version : localModuleInfo.version + " (" +
this.getString(R.string.module_last_update) +
moduleInfo.version + ")") + " " +
this.getString(R.string.module_by) + " " + moduleInfo.author);
} else {
this.creditText.setText(localModuleInfo.version + (
localModuleInfo.version.equals(localModuleInfo.updateVersion) ?
(localModuleInfo.updateVersion != null &&
Objects.equals(localModuleInfo.version,
localModuleInfo.updateVersion)) ?
"" : " (" + this.getString(R.string.module_last_update) +
localModuleInfo.updateVersion + ")") + " " +
this.getString(R.string.module_by) + " " + localModuleInfo.author);

@ -23,6 +23,7 @@ import java.util.Locale;
public class ModuleViewListBuilder {
private static final String TAG = "ModuleViewListBuilder";
private static final Runnable RUNNABLE = () -> {};
private final EnumSet<NotificationType> notifications = EnumSet.noneOf(NotificationType.class);
private final HashMap<String, ModuleHolder> mappedModuleHolders = new HashMap<>();
private final Object updateLock = new Object();
@ -31,8 +32,10 @@ public class ModuleViewListBuilder {
@NonNull
private String query = "";
private boolean updating;
private int headerPx;
private int footerPx;
private ModuleSorter moduleSorter = ModuleSorter.UPDATE;
private Runnable updateInsets = RUNNABLE;
public ModuleViewListBuilder(Activity activity) {
this.activity = activity;
@ -100,6 +103,8 @@ public class ModuleViewListBuilder {
this.updating = true;
final ArrayList<ModuleHolder> moduleHolders;
final int newNotificationsLen;
final boolean first;
final ModuleHolder[] headerFooter = new ModuleHolder[2];
try {
synchronized (this.updateLock) {
// Build start
@ -116,7 +121,8 @@ public class ModuleViewListBuilder {
moduleHolders.add(new ModuleHolder(notificationType));
}
}
newNotificationsLen = this.notifications.size() - special;
first = moduleViewAdapter.moduleHolders.isEmpty();
newNotificationsLen = this.notifications.size() + 1 - special;
EnumSet<ModuleHolder.Type> headerTypes = EnumSet.of(ModuleHolder.Type.SEPARATOR,
ModuleHolder.Type.NOTIFICATION, ModuleHolder.Type.FOOTER);
Iterator<ModuleHolder> moduleHolderIterator = this.mappedModuleHolders.values().iterator();
@ -150,9 +156,12 @@ public class ModuleViewListBuilder {
}
}
Collections.sort(moduleHolders, this.moduleSorter);
if (this.footerPx != 0) { // Footer is always last
moduleHolders.add(new ModuleHolder(this.footerPx));
}
// Header is always first
moduleHolders.add(0, headerFooter[0] =
new ModuleHolder(this.headerPx, true));
// Footer is always last
moduleHolders.add(headerFooter[1] =
new ModuleHolder(this.footerPx, false));
Log.i(TAG, "Got " + moduleHolders.size() + " entries!");
// Build end
}
@ -160,9 +169,10 @@ public class ModuleViewListBuilder {
this.updating = false;
}
this.activity.runOnUiThread(() -> {
this.updateInsets = RUNNABLE;
final EnumSet<NotificationType> oldNotifications =
EnumSet.noneOf(NotificationType.class);
boolean isTop = !moduleList.canScrollVertically(-1);
boolean isTop = first || !moduleList.canScrollVertically(-1);
boolean isBottom = !isTop && !moduleList.canScrollVertically(1);
int oldNotificationsLen = 0;
int oldOfflineModulesLen = 0;
@ -172,7 +182,9 @@ public class ModuleViewListBuilder {
oldNotifications.add(notificationType);
if (!notificationType.special)
oldNotificationsLen++;
}
} else if (moduleHolder.footerPx != -1 &&
moduleHolder.filterLevel == 1)
oldNotificationsLen++; // Fix header
if (moduleHolder.separator == ModuleHolder.Type.INSTALLABLE)
break;
oldOfflineModulesLen++;
@ -190,10 +202,16 @@ public class ModuleViewListBuilder {
int oldLen = moduleViewAdapter.moduleHolders.size();
moduleViewAdapter.moduleHolders.clear();
moduleViewAdapter.moduleHolders.addAll(moduleHolders);
synchronized (this.updateLock) {
headerFooter[0].footerPx = this.headerPx;
headerFooter[1].footerPx = this.footerPx;
}
if (oldNotificationsLen != newNotificationsLen ||
!oldNotifications.equals(this.notifications)) {
notifySizeChanged(moduleViewAdapter, 0,
oldNotificationsLen, newNotificationsLen);
} else {
notifySizeChanged(moduleViewAdapter, 0, 1, 1);
}
if (newLen - newNotificationsLen == 0) {
notifySizeChanged(moduleViewAdapter, newNotificationsLen,
@ -208,6 +226,13 @@ public class ModuleViewListBuilder {
}
if (isTop) moduleList.scrollToPosition(0);
if (isBottom) moduleList.scrollToPosition(newLen);
this.updateInsets = () -> {
headerFooter[0].footerPx = this.headerPx;
headerFooter[1].footerPx = this.footerPx;
notifySizeChanged(moduleViewAdapter, 0, 1, 1);
notifySizeChanged(moduleViewAdapter,
moduleHolders.size(), 1, 1);
};
});
}
@ -281,6 +306,14 @@ public class ModuleViewListBuilder {
return true;
}
public void setHeaderPx(int headerPx) {
if (this.headerPx != headerPx) {
synchronized (this.updateLock) {
this.headerPx = headerPx;
}
}
}
public void setFooterPx(int footerPx) {
if (this.footerPx != footerPx) {
synchronized (this.updateLock) {
@ -288,4 +321,8 @@ public class ModuleViewListBuilder {
}
}
}
public void updateInsets() {
this.updateInsets.run();
}
}

@ -0,0 +1,92 @@
package com.fox2code.mmm;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.fox2code.mmm.compat.CompatDisplay;
import com.mikepenz.aboutlibraries.LibsConfiguration;
public class OverScrollManager {
private static final String TAG = "OverScrollManager";
public interface OverScrollHelper {
int getOverScrollInsetTop();
int getOverScrollInsetBottom();
}
public static class LibsOverScroll implements LibsConfiguration.LibsUIListener {
private final OverScrollHelper overScrollHelper;
public LibsOverScroll() {
this.overScrollHelper = null;
}
public LibsOverScroll(OverScrollHelper overScrollHelper) {
this.overScrollHelper = overScrollHelper;
}
@NonNull
@Override
public View preOnCreateView(@NonNull View view) {
return view;
}
@NonNull
@Override
public View postOnCreateView(@NonNull View view) {
OverScrollManager.install(
view.findViewById(R.id.cardListView),
this.overScrollHelper);
return view;
}
}
public static void install(final RecyclerView recyclerView) {
OverScrollManager.install(recyclerView, null);
}
public static void install(final RecyclerView recyclerView,
final OverScrollHelper overScrollHelper) {
if (recyclerView == null) return;
recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
int prevState = -1, lastTranslation = 0;
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE && this.prevState != newState) {
if (recyclerView.getOverScrollMode() != View.OVER_SCROLL_NEVER)
recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
final int threshold = CompatDisplay.dpToPixel(16);
final int lastTranslation = this.lastTranslation;
if (lastTranslation < threshold) {
this.prevState = newState;
return;
}
final int insetTop;
final int insetBottom;
if (overScrollHelper == null) {
insetTop = 0;
insetBottom = 0;
} else {
insetTop = overScrollHelper.getOverScrollInsetTop();
insetBottom = overScrollHelper.getOverScrollInsetBottom();
}
Log.d(TAG, "Overscroll: " + lastTranslation + " -> ("
+ insetTop + ", " + insetBottom + ")");
// TODO Overscroll effect for 5.0 (With settings toggle)
}
this.prevState = newState;
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
this.lastTranslation = dy;
}
});
}
}

@ -78,11 +78,16 @@ public class AndroidacyActivity extends CompatActivity {
String title = intent.getStringExtra(Constants.EXTRA_ANDROIDACY_ACTIONBAR_TITLE);
String config = intent.getStringExtra(Constants.EXTRA_ANDROIDACY_ACTIONBAR_CONFIG);
this.setContentView(R.layout.webview);
setActionBarBackground(null);
this.setDisplayHomeAsUpEnabled(true);
if (title == null || title.isEmpty()) {
this.setTitle(title);
} else {
this.setTitle("Androidacy");
}
if (allowInstall || title == null || title.isEmpty()) {
this.hideActionBar();
} else { // Only used for note section
this.setTitle(title);
this.setDisplayHomeAsUpEnabled(true);
if (config != null && !config.isEmpty()) {
String configPkg = IntentHelper.getPackageOfConfig(config);
try {

@ -165,13 +165,17 @@ public class AndroidacyWebAPI {
/**
* Show action bar if not visible, the action bar is only visible by default on notes.
* Optional title param to set action bar title.
*/
@JavascriptInterface
public void showActionBar() {
public void showActionBar(final String title) {
if (this.consumedAction) return;
this.consumedAction = true;
this.activity.runOnUiThread(() -> {
this.activity.showActionBar();
if (title != null && !title.isEmpty()) {
this.activity.setTitle(title);
}
this.consumedAction = false;
});
}

@ -5,7 +5,9 @@ import android.app.Application;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
@ -16,6 +18,7 @@ import android.view.View;
import androidx.annotation.CallSuper;
import androidx.annotation.Dimension;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.annotation.StringRes;
@ -198,6 +201,35 @@ public class CompatActivity extends AppCompatActivity {
}
}
public void setActionBarBackground(Drawable drawable) {
androidx.appcompat.app.ActionBar compatActionBar;
try {
compatActionBar = this.getSupportActionBar();
} catch (Exception e) {
Log.e(TAG, "Failed to call getSupportActionBar", e);
compatActionBar = null; // Allow fallback to builtin actionBar.
}
if (compatActionBar != null) {
compatActionBar.setBackgroundDrawable(drawable);
} else {
android.app.ActionBar actionBar = this.getActionBar();
if (actionBar != null)
actionBar.setBackgroundDrawable(drawable);
}
}
@Dimension @Px
public int getStatusBarHeight() { // How to improve this?
int height = WindowInsetsCompat.CONSUMED.getInsets(
WindowInsetsCompat.Type.statusBars()).top;
if (height == 0) { // Fallback to system resources
int id = Resources.getSystem().getIdentifier(
"status_bar_height", "dimen", "android");
if (id > 0) return Resources.getSystem().getDimensionPixelSize(id);
}
return height;
}
public int getNavigationBarHeight() { // How to improve this?
int height = WindowInsetsCompat.CONSUMED.getInsets(
WindowInsetsCompat.Type.navigationBars()).bottom;
@ -292,6 +324,13 @@ public class CompatActivity extends AppCompatActivity {
}
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
this.compatConfigHelper.checkResourcesOverrides(this.getTheme(),
this.forceEnglish, this.nightModeOverride);
super.onConfigurationChanged(newConfig);
}
public void setOnBackPressedCallback(OnBackPressedCallback onBackPressedCallback) {
this.onBackPressedCallback = onBackPressedCallback;
}

@ -14,9 +14,13 @@ import java.util.Locale;
final class CompatConfigHelper {
// ENGLISH like this is an unnatural local, as it doesn't precise the country
// All english locales settable by the user precise the country (Ex: en-US)
private static final Locale english = Locale.ENGLISH;
private static final Locale englishLocale = Locale.ENGLISH;
private static final Object englishLocales =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ?
new LocaleList(englishLocale) : null;
private final Context context;
private Object userLocales;
private Locale userLocale;
CompatConfigHelper(Context context) {
@ -32,22 +36,35 @@ final class CompatConfigHelper {
void checkResourcesOverrides(Resources.Theme theme, boolean forceEnglish,
Boolean nightModeOverride) {
final Resources res = theme.getResources();
final Configuration conf = res.getConfiguration();
Resources res = theme.getResources();
if (this.checkResourcesOverrides(res.getConfiguration(),
forceEnglish, nightModeOverride)) {
res.updateConfiguration(
res.getConfiguration(),
res.getDisplayMetrics());
}
}
boolean checkResourcesOverrides(Configuration conf, boolean forceEnglish,
Boolean nightModeOverride) {
Locale current = conf.locale;
boolean didChange = false;
if (forceEnglish != current.equals(english)) {
boolean wasForceEnglish = englishLocale.equals(current);
if (forceEnglish != wasForceEnglish) {
didChange = true;
if (forceEnglish) {
this.userLocale = conf.locale;
conf.locale = english;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
conf.setLocales(LocaleList.getEmptyLocaleList());
this.userLocales = conf.getLocales();
}
conf.locale = englishLocale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
conf.setLocales((LocaleList) englishLocales);
}
} else {
conf.locale = this.userLocale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
conf.setLocales(LocaleList.getAdjustedDefault());
conf.setLocales((LocaleList) this.userLocales);
}
}
}
@ -62,15 +79,16 @@ final class CompatConfigHelper {
Configuration.UI_MODE_NIGHT_YES : Configuration.UI_MODE_NIGHT_NO;
conf.uiMode = nightMode | (conf.uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
}
if (didChange) {
res.updateConfiguration(conf, null);
if (!forceEnglish) this.userLocale = null;
if (!forceEnglish && !wasForceEnglish) {
this.userLocale = null;
this.userLocales = null;
}
return didChange;
}
public Locale getUserLocale() {
// Only use cached value if force english
Locale locale = this.context.getResources().getConfiguration().locale;
return english.equals(locale) ? this.userLocale : locale;
return englishLocale.equals(locale) ? this.userLocale : locale;
}
}

@ -57,6 +57,7 @@ public class InstallerActivity extends CompatActivity {
Log.e(TAG, "Failed to mkdir module cache dir!");
super.onCreate(savedInstanceState);
this.setDisplayHomeAsUpEnabled(true);
setActionBarBackground(null);
this.setOnBackPressedCallback(a -> {
this.canceled = true; return false;
});

@ -15,6 +15,8 @@ import java.util.ArrayList;
public class InstallerInitializer extends Shell.Initializer {
private static final String TAG = "InstallerInitializer";
private static final File MAGISK_SYSTEM =
new File("/system/bin/magisk");
private static String MAGISK_PATH;
private static int MAGISK_VERSION_CODE;
@ -64,6 +66,9 @@ public class InstallerInitializer extends Shell.Initializer {
}
if (forceCheck) {
InstallerInitializer.MAGISK_PATH = MAGISK_PATH;
if (MAGISK_PATH == null) {
InstallerInitializer.MAGISK_VERSION_CODE = 0;
}
}
if (MAGISK_PATH != null) {
MainApplication.setHasGottenRootAccess(true);
@ -112,9 +117,15 @@ public class InstallerInitializer extends Shell.Initializer {
Log.w(TAG, "Unable to detect magisk path!");
} else {
newJob.add("export ASH_STANDALONE=1");
newJob.add("export PATH=\"" + MAGISK_PATH + "/.magisk/busybox;$PATH\"");
if (!MAGISK_PATH.equals("/sbin") && !MAGISK_SYSTEM.exists()) {
newJob.add("export PATH=" + MAGISK_PATH + ";$PATH;" +
MAGISK_PATH + "/.magisk/busybox");
} else {
newJob.add("export PATH=$PATH;" +
MAGISK_PATH + "/.magisk/busybox");
}
newJob.add("export MAGISKTMP=\"" + MAGISK_PATH + "/.magisk\"");
newJob.add("busybox sh");
newJob.add("$(which busybox 2> /dev/null) sh");
}
return true;
}

@ -43,8 +43,9 @@ public class MarkdownActivity extends CompatActivity {
String config = intent.getExtras()
.getString(Constants.EXTRA_MARKDOWN_CONFIG);
if (title != null && !title.isEmpty()) {
setTitle(title);
this.setTitle(title);
}
setActionBarBackground(null);
this.getWindow().setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

@ -1,19 +1,23 @@
package com.fox2code.mmm.settings;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.fox2code.mmm.AppUpdateManager;
import com.fox2code.mmm.BuildConfig;
import com.fox2code.mmm.Constants;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.OverScrollManager;
import com.fox2code.mmm.R;
import com.fox2code.mmm.compat.CompatActivity;
import com.fox2code.mmm.compat.CompatThemeWrapper;
@ -23,6 +27,8 @@ import com.fox2code.mmm.repo.RepoManager;
import com.fox2code.mmm.utils.Http;
import com.fox2code.mmm.utils.IntentHelper;
import com.mikepenz.aboutlibraries.LibsBuilder;
import com.mikepenz.aboutlibraries.LibsConfiguration;
import com.mikepenz.aboutlibraries.ui.LibsSupportFragment;
import com.topjohnwu.superuser.internal.UiThreadHandler;
public class SettingsActivity extends CompatActivity {
@ -35,6 +41,7 @@ public class SettingsActivity extends CompatActivity {
this.setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.settings_activity);
setTitle(R.string.app_name);
setActionBarBackground(null);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
@ -50,6 +57,7 @@ public class SettingsActivity extends CompatActivity {
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
getPreferenceManager().setSharedPreferencesName("mmm");
setPreferencesFromResource(R.xml.root_preferences, rootKey);
OverScrollManager.install(getListView());
findPreference("pref_manage_repos").setOnPreferenceClickListener(p -> {
devModeStep = 0;
openFragment(new RepoFragment(), R.string.manage_repos_pref);
@ -100,7 +108,8 @@ public class SettingsActivity extends CompatActivity {
}
final LibsBuilder libsBuilder = new LibsBuilder().withShowLoadingProgress(false)
.withLicenseShown(true).withAboutMinimalDesign(false);
.withLicenseShown(true).withAboutMinimalDesign(false)
.withUiListener(new OverScrollManager.LibsOverScroll());
Preference update = findPreference("pref_update");
update.setVisible(AppUpdateManager.getAppUpdateManager().peekHasUpdate());
update.setOnPreferenceClickListener(p -> {
@ -162,6 +171,7 @@ public class SettingsActivity extends CompatActivity {
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
getPreferenceManager().setSharedPreferencesName("mmm");
setPreferencesFromResource(R.xml.repo_preferences, rootKey);
OverScrollManager.install(getListView());
setRepoData(RepoManager.MAGISK_ALT_REPO,
"Magisk Modules Alt Repo", RepoManager.MAGISK_ALT_REPO_HOMEPAGE,
null, null,

@ -2,9 +2,10 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:fitsSystemWindowsInsets="top"
app:fitsSystemWindowsInsets="left|right"
tools:context=".MainActivity">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
@ -19,9 +20,23 @@
android:id="@+id/module_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
app:edgeToEdge="true" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<eightbitlab.com.blurview.BlurView
android:id="@+id/action_bar_blur"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/action_bar_padding"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</eightbitlab.com.blurview.BlurView>
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progress_bar"
android:layout_height="wrap_content"
@ -29,21 +44,21 @@
android:indeterminate="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toBottomOf="@+id/action_bar_blur" />
<LinearLayout
android:id="@+id/search_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:gravity="center_vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:gravity="right"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:fitsSystemWindowsInsets="bottom">
app:fitsSystemWindowsInsets="bottom"
tools:ignore="RtlHardcoded">
<androidx.cardview.widget.CardView
android:id="@+id/search_card"
android:layout_gravity="center"
@ -53,11 +68,13 @@
android:background="@null"
app:cardCornerRadius="75dp"
app:strokeColor="@android:color/transparent"
app:cardElevation="0dp"
app:strokeWidth="0dp">
<androidx.appcompat.widget.SearchView
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:background="@null" />
</androidx.cardview.widget.CardView>
</LinearLayout>

@ -17,6 +17,8 @@
android:layout_height="wrap_content"
app:cardCornerRadius="@dimen/card_corner_radius"
app:strokeColor="@android:color/transparent"
app:cardPreventCornerOverlap="true"
app:cardElevation="0dp"
app:strokeWidth="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="status_bar_color">@color/transparent</color>
</resources>

@ -7,6 +7,10 @@
<color name="teal_700">#FF018786</color>
<color name="orange_700">#EF6C00</color>
<color name="orange_200">#FFA726</color>
<color name="black_transparent">#80000000</color>
<color name="white_transparent">#80FFFFFF</color>
<color name="transparent">#00000000</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="status_bar_color">@color/black_transparent</color>
</resources>

@ -4,7 +4,7 @@
tools:targetApi="q">true</item>
<item name="isLightTheme">true</item>
<!-- Primary brand color. -->
<item name="colorPrimary">@color/white</item>
<item name="colorPrimary">@color/orange_200</item>
<item name="colorPrimaryVariant">@color/white</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
@ -12,7 +12,8 @@
<item name="colorSecondaryVariant">@color/orange_200</item>
<item name="colorOnSecondary">@color/white</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="android:statusBarColor">@color/status_bar_color</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
<!-- Customize your theme here. -->
<item name="android:windowActivityTransitions">true</item>
<!-- <item name="android:activityOpenEnterAnimation">@*android:anim/slide_in_right</item>
@ -25,13 +26,12 @@
<item name="dialogCornerRadius">@dimen/card_corner_radius</item>
</style>
<!-- Base application theme. -->
<style name="Theme.MagiskModuleManager.Dark" parent="Theme.MaterialComponents">
<item name="android:isLightTheme"
tools:targetApi="q">false</item>
<item name="isLightTheme">false</item>
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimary">@color/orange_200</item>
<item name="colorPrimaryVariant">@color/black</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
@ -39,7 +39,8 @@
<item name="colorSecondaryVariant">@color/orange_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="android:statusBarColor">@color/status_bar_color</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>
<!-- Customize your theme here. -->
<item name="android:windowActivityTransitions">true</item>
<!-- <item name="android:activityOpenEnterAnimation">@*android:anim/slide_in_right</item>

Loading…
Cancel
Save