(misc) UI tweaks

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/299/head
androidacy-user 1 year ago
parent 8ba2d2d98e
commit c79f081879

@ -330,9 +330,9 @@ dependencies {
// logging interceptor
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.10'
// Chromium cronet from androidacy
implementation 'com.androidacy:cronet-common:111.0.5563.75'
implementation 'com.androidacy:cronet-native:111.0.5563.75'
implementation 'com.androidacy:cronet-api:111.0.5563.75'
implementation 'com.androidacy:cronet-common:112.0.5615.62'
implementation 'com.androidacy:cronet-native:112.0.5615.62'
implementation 'com.androidacy:cronet-api:112.0.5615.62'
// protobuf - fixes a crash on some devices
implementation 'com.google.protobuf:protobuf-javalite:3.22.2'

@ -71,11 +71,13 @@
tools:targetApi="tiramisu">
<activity
android:name=".UpdateActivity"
android:exported="false" />
android:exported="false"
android:theme="@style/Theme.MagiskModuleManager.NoActionBar" />
<activity
android:name=".CrashHandler"
android:exported="false"
android:process=":crash" />
android:process=":crash"
android:theme="@style/Theme.MagiskModuleManager.NoActionBar" />
<activity
android:name=".SetupActivity"
android:exported="false"
@ -104,7 +106,8 @@
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name_short"
android:launchMode="singleTask">
android:launchMode="singleTask"
android:theme="@style/Theme.MagiskModuleManager.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@ -130,7 +133,7 @@
<activity
android:name=".utils.ZipFileOpener"
android:exported="true"
android:theme="@style/Theme.MagiskModuleManager">
android:theme="@style/Theme.MagiskModuleManager.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@ -146,13 +149,13 @@
android:name=".markdown.MarkdownActivity"
android:exported="false"
android:parentActivityName=".MainActivity"
android:theme="@style/Theme.MagiskModuleManager" />
android:theme="@style/Theme.MagiskModuleManager.NoActionBar" />
<activity
android:name=".androidacy.AndroidacyActivity"
android:exported="false"
android:parentActivityName=".MainActivity"
android:theme="@style/Theme.MagiskModuleManager">
android:theme="@style/Theme.MagiskModuleManager.NoActionBar" >
<!--
<intent-filter>

@ -18,6 +18,7 @@ import android.os.Bundle;
import android.provider.Settings;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.CheckBox;
@ -119,7 +120,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
setContentView(R.layout.activity_main);
this.setTitle(R.string.app_name);
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();
layoutParams.layoutInDisplayCutoutMode = // Support cutout in Android 9
@ -146,8 +146,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
this.swipeRefreshLayout.setOnRefreshListener(this);
// add background blur if enabled
this.updateBlurState();
hideActionBar();
this.updateBlurState();
//hideActionBar();
checkShowInitialSetup();
this.moduleList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
@ -208,11 +207,19 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
// set search view to cleared
this.searchView.setQuery("", false);
}
// update the padding of blur_frame to match the new bottom nav height
View blurFrame = findViewById(R.id.blur_frame);
blurFrame.setPadding(blurFrame.getPaddingLeft(), blurFrame.getPaddingTop(), blurFrame.getPaddingRight(), bottomNavigationView.getHeight());
return true;
});
// update the padding of blur_frame to match the new bottom nav height
View blurFrame = findViewById(R.id.blur_frame);
blurFrame.post(() -> blurFrame.setPadding(blurFrame.getPaddingLeft(), blurFrame.getPaddingTop(), blurFrame.getPaddingRight(), bottomNavigationView.getHeight()));
// for some reason, root_container has a margin at the top. remove it.
View rootContainer = findViewById(R.id.root_container);
rootContainer.post(() -> {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) rootContainer.getLayoutParams();
params.topMargin = 0;
rootContainer.setLayoutParams(params);
rootContainer.setY(0F);
});
InstallerInitializer.tryGetMagiskPathAsync(new InstallerInitializer.Callback() {
@Override
public void onPathReceived(String path) {
@ -272,12 +279,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
updateScreenInsets(getResources().getConfiguration());
});
// On every preferences change, log the change if debug is enabled
if (BuildConfig.DEBUG) {
// Log all preferences changes
MainApplication.getPreferences("mmm").registerOnSharedPreferenceChangeListener((prefs, key) -> Timber.i("onSharedPreferenceChanged: " + key + " = " + prefs.getAll().get(key)));
}
Timber.i("Scanning for modules!");
if (BuildConfig.DEBUG) Timber.i("Initialize Update");
final int max = ModuleManager.getINSTANCE().getUpdatableModuleCount();
@ -307,7 +308,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
progressIndicator.setProgressCompat(PRECISION, true);
progressIndicator.setVisibility(View.GONE);
searchView.setEnabled(false);
setActionBarBackground(null);
updateScreenInsets(getResources().getConfiguration());
});
return;
@ -339,7 +339,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
progressIndicator.setProgressCompat(PRECISION, true);
progressIndicator.setVisibility(View.GONE);
searchView.setEnabled(true);
setActionBarBackground(null);
updateScreenInsets(getResources().getConfiguration());
});
if (BuildConfig.DEBUG) Timber.i("Apply");
@ -377,17 +376,15 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
boolean landscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE;
int bottomInset = (landscape ? 0 : this.getNavigationBarHeight());
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));
this.moduleViewListBuilderOnline.setHeaderPx(Math.max(statusBarHeight, combinedBarsHeight));
this.swipeRefreshLayout.setProgressViewOffset(false, swipeRefreshLayoutOrigStartOffset + statusBarHeight, swipeRefreshLayoutOrigEndOffset + statusBarHeight);
this.moduleViewListBuilder.setHeaderPx(statusBarHeight);
this.moduleViewListBuilderOnline.setHeaderPx(statusBarHeight);
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.overScrollInsetTop = statusBarHeight;
this.overScrollInsetBottom = bottomInset;
// set root_container to have zero padding
findViewById(R.id.root_container).setPadding(0, statusBarHeight, 0, 0);

@ -54,6 +54,7 @@ import java.security.cert.CertificateException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
@ -96,6 +97,7 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
@SuppressLint("StaticFieldLeak")
private static MainApplication INSTANCE;
private static boolean firstBoot;
private static HashMap<Object, Object> mSharedPrefs;
static {
Shell.setDefaultBuilder(shellBuilder = Shell.Builder.create().setFlags(Shell.FLAG_REDIRECT_STDERR).setTimeout(10).setInitializers(InstallerInitializer.class));
@ -133,13 +135,24 @@ public class MainApplication extends FoxApplication implements androidx.work.Con
public static SharedPreferences getPreferences(String name) {
// encryptedSharedPreferences is used
Context context = getINSTANCE();
Context mContext = getINSTANCE();
if (mSharedPrefs == null) {
Timber.d("Creating shared prefs map");
mSharedPrefs = new HashMap<>();
}
if (mSharedPrefs.containsKey(name)) {
Timber.d("Returning cached shared prefs");
return (SharedPreferences) mSharedPrefs.get(name);
}
try {
MasterKey masterKey = new MasterKey.Builder(context).setKeyScheme(MasterKey.KeyScheme.AES256_GCM).build();
return EncryptedSharedPreferences.create(context, name, masterKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);
Timber.d("Creating encrypted shared prefs");
MasterKey masterKey = new MasterKey.Builder(mContext).setKeyScheme(MasterKey.KeyScheme.AES256_GCM).build();
SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(mContext, name, masterKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);
mSharedPrefs.put(name, sharedPreferences);
return sharedPreferences;
} catch (Exception e) {
Timber.e(e, "Failed to create encrypted shared preferences");
return context.getSharedPreferences(name, Context.MODE_PRIVATE);
return mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
}
}

@ -16,7 +16,6 @@ import android.webkit.CookieManager;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.fragment.app.FragmentActivity;
import com.fox2code.foxcompat.app.FoxActivity;
@ -51,11 +50,11 @@ public class SetupActivity extends FoxActivity implements LanguageActivity {
super.onCreate(savedInstanceState);
this.setTitle(R.string.setup_title);
// set action bar
ActionBar actionBar = getSupportActionBar();
/**ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
// back button is close button
actionBar.hide();
}
}*/
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, 0);
createFiles();
disableUpdateActivityForFdroidFlavor();

@ -1,7 +1,6 @@
package com.fox2code.mmm.background;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.PendingIntent;
@ -25,16 +24,9 @@ import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import com.fox2code.mmm.AppUpdateManager;
import com.fox2code.mmm.MainActivity;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.R;
import com.fox2code.mmm.UpdateActivity;
import com.fox2code.mmm.manager.LocalModuleInfo;
import com.fox2code.mmm.manager.ModuleManager;
import com.fox2code.mmm.repo.RepoManager;
import com.fox2code.mmm.repo.RepoModule;
import com.fox2code.mmm.utils.io.PropUtils;
import java.util.HashMap;
import java.util.Map;
@ -46,13 +38,9 @@ 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";
public static final String NOTIFICATION_CHANNEL_ID_ONGOING = "background_update_status";
public static final int NOTIFICATION_ID = 1;
public static final int NOTIFICATION_ID_ONGOING = 2;
public static final String NOTFIICATION_GROUP = "updates";
static final Object lock = new Object(); // Avoid concurrency issues
private static final int NOTIFICATION_ID_APP = 3;
public BackgroundUpdateChecker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
@ -77,100 +65,10 @@ public class BackgroundUpdateChecker extends Worker {
return;
}
}
// post checking notification if notofiications are enabled
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.createNotificationChannel(new NotificationChannelCompat.Builder(NOTIFICATION_CHANNEL_ID_ONGOING, NotificationManagerCompat.IMPORTANCE_LOW).setName(context.getString(R.string.notification_channel_category_background_update)).setDescription(context.getString(R.string.notification_channel_category_background_update_description)).setGroup(NOTFIICATION_GROUP).build());
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
builder.setSmallIcon(R.drawable.ic_baseline_update_24);
builder.setPriority(NotificationCompat.PRIORITY_LOW);
builder.setCategory(NotificationCompat.CATEGORY_RECOMMENDATION);
builder.setShowWhen(false);
builder.setOnlyAlertOnce(true);
builder.setOngoing(true);
builder.setAutoCancel(false);
builder.setGroup("update");
builder.setContentTitle(context.getString(R.string.notification_channel_background_update));
builder.setContentText(context.getString(R.string.notification_channel_background_update_description));
notificationManager.notify(NOTIFICATION_ID_ONGOING, builder.build());
}
Thread.currentThread().setPriority(2);
ModuleManager.getINSTANCE().scanAsync();
RepoManager.getINSTANCE().update(null);
ModuleManager.getINSTANCE().runAfterScan(() -> {
int moduleUpdateCount = 0;
HashMap<String, RepoModule> repoModules = RepoManager.getINSTANCE().getModules();
// hasmap of updateable modules names
HashMap<String, String> updateableModules = new HashMap<>();
for (LocalModuleInfo localModuleInfo : ModuleManager.getINSTANCE().getModules().values()) {
if ("twrp-keep".equals(localModuleInfo.id))
continue;
// exclude all modules with id's stored in the pref pref_background_update_check_excludes
try {
if (MainApplication.getPreferences("mmm").getStringSet("pref_background_update_check_excludes", null).contains(localModuleInfo.id))
continue;
} catch (
Exception ignored) {
}
RepoModule repoModule = repoModules.get(localModuleInfo.id);
localModuleInfo.checkModuleUpdate();
if (localModuleInfo.updateVersionCode > localModuleInfo.versionCode && !PropUtils.isNullString(localModuleInfo.updateVersion)) {
moduleUpdateCount++;
updateableModules.put(localModuleInfo.name, localModuleInfo.version);
} else if (repoModule != null && repoModule.moduleInfo.versionCode > localModuleInfo.versionCode && !PropUtils.isNullString(repoModule.moduleInfo.version)) {
moduleUpdateCount++;
updateableModules.put(localModuleInfo.name, localModuleInfo.version);
}
}
if (moduleUpdateCount != 0) {
postNotification(context, updateableModules, moduleUpdateCount, false);
}
});
// check for app updates
if (MainApplication.getPreferences("mmm").getBoolean("pref_background_update_check_app", false)) {
try {
boolean shouldUpdate = AppUpdateManager.getAppUpdateManager().checkUpdate(true);
if (shouldUpdate) {
postNotificationForAppUpdate(context);
}
} catch (
Exception e) {
e.printStackTrace();
}
}
// remove checking notification
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancel(NOTIFICATION_ID_ONGOING);
}
}
@SuppressLint("RestrictedApi")
private static void postNotificationForAppUpdate(Context context) {
// create the notification channel if not already created
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.createNotificationChannel(new NotificationChannelCompat.Builder(NOTIFICATION_CHANNEL_ID_APP, NotificationManagerCompat.IMPORTANCE_HIGH).setName(context.getString(R.string.notification_channel_category_app_update)).setDescription(context.getString(R.string.notification_channel_category_app_update_description)).setGroup(NOTFIICATION_GROUP).build());
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID_APP);
builder.setSmallIcon(R.drawable.baseline_system_update_24);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setCategory(NotificationCompat.CATEGORY_RECOMMENDATION);
builder.setShowWhen(false);
builder.setOnlyAlertOnce(true);
builder.setOngoing(false);
builder.setAutoCancel(true);
builder.setGroup(NOTFIICATION_GROUP);
// open app on click
Intent intent = new Intent(context, UpdateActivity.class);
// set action to ACTIONS.DOWNLOAD
intent.setAction(String.valueOf(UpdateActivity.ACTIONS.DOWNLOAD));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
builder.setContentIntent(android.app.PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE));
// set summary to Found X
builder.setContentTitle(context.getString(R.string.notification_channel_background_update_app));
builder.setContentText(context.getString(R.string.notification_channel_background_update_app_description));
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(NOTIFICATION_ID_APP, builder.build());
}
// start foreground service
Intent intent = new Intent(context, BackgroundUpdateCheckerService.class);
intent.setAction(BackgroundUpdateCheckerService.ACTION_START_FOREGROUND_SERVICE);
ContextCompat.startForegroundService(context, intent);
}
public static void postNotification(Context context, HashMap<String, String> updateable, int updateCount, boolean test) {
@ -202,8 +100,7 @@ public class BackgroundUpdateChecker extends Worker {
return;
}
// check if app is in foreground. if so, don't show notification
if (MainApplication.getINSTANCE().isInForeground() && !test)
return;
if (MainApplication.getINSTANCE().isInForeground() && !test) return;
NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, builder.build());
}

@ -0,0 +1,150 @@
package com.fox2code.mmm.background;
import static com.fox2code.mmm.background.BackgroundUpdateChecker.NOTFIICATION_GROUP;
import static com.fox2code.mmm.background.BackgroundUpdateChecker.postNotification;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import androidx.core.app.NotificationChannelCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import com.fox2code.foxcompat.app.internal.FoxIntentActivity;
import com.fox2code.mmm.AppUpdateManager;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.R;
import com.fox2code.mmm.UpdateActivity;
import com.fox2code.mmm.manager.LocalModuleInfo;
import com.fox2code.mmm.manager.ModuleManager;
import com.fox2code.mmm.repo.RepoManager;
import com.fox2code.mmm.repo.RepoModule;
import com.fox2code.mmm.utils.io.PropUtils;
import java.util.HashMap;
import timber.log.Timber;
@SuppressLint("RestrictedApi")
public class BackgroundUpdateCheckerService extends FoxIntentActivity {
public static final String NOTIFICATION_CHANNEL_ID = "background_update";
public static final String NOTIFICATION_CHANNEL_ID_APP = "background_update_app";
public static final String ACTION_START_FOREGROUND_SERVICE = "ACTION_START_FOREGROUND_SERVICE";
static final Object lock = new Object(); // Avoid concurrency issues
private static final int NOTIFICATION_ID_ONGOING = 2;
private static final String NOTIFICATION_CHANNEL_ID_ONGOING = "mmm_background_update";
private static final int NOTIFICATION_ID_APP = 3;
@SuppressLint("RestrictedApi")
private static void postNotificationForAppUpdate(Context context) {
// create the notification channel if not already created
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.createNotificationChannel(new NotificationChannelCompat.Builder(NOTIFICATION_CHANNEL_ID_APP, NotificationManagerCompat.IMPORTANCE_HIGH).setName(context.getString(R.string.notification_channel_category_app_update)).setDescription(context.getString(R.string.notification_channel_category_app_update_description)).setGroup(NOTFIICATION_GROUP).build());
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID_APP);
builder.setSmallIcon(R.drawable.baseline_system_update_24);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setCategory(NotificationCompat.CATEGORY_RECOMMENDATION);
builder.setShowWhen(false);
builder.setOnlyAlertOnce(true);
builder.setOngoing(false);
builder.setAutoCancel(true);
builder.setGroup(NOTFIICATION_GROUP);
// open app on click
Intent intent = new Intent(context, UpdateActivity.class);
// set action to ACTIONS.DOWNLOAD
intent.setAction(String.valueOf(UpdateActivity.ACTIONS.DOWNLOAD));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
builder.setContentIntent(android.app.PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE));
// set summary to Found X
builder.setContentTitle(context.getString(R.string.notification_channel_background_update_app));
builder.setContentText(context.getString(R.string.notification_channel_background_update_app_description));
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(NOTIFICATION_ID_APP, builder.build());
}
}
public void onCreate() {
Context context = MainApplication.getINSTANCE().getApplicationContext();
// check if action is ACTION_START_FOREGROUND_SERVICE, bail out if not
if (!ACTION_START_FOREGROUND_SERVICE.equals(getIntent().getAction())) {
return;
}
Timber.d("Starting background update checker service");
// acquire lock
synchronized (lock) {
// post checking notification if notofiications are enabled
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.createNotificationChannel(new NotificationChannelCompat.Builder(NOTIFICATION_CHANNEL_ID_ONGOING, NotificationManagerCompat.IMPORTANCE_MIN).setName(context.getString(R.string.notification_channel_category_background_update)).setDescription(context.getString(R.string.notification_channel_category_background_update_description)).setGroup(NOTFIICATION_GROUP).build());
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
builder.setSmallIcon(R.drawable.ic_baseline_update_24);
builder.setPriority(NotificationCompat.PRIORITY_MIN);
builder.setCategory(NotificationCompat.CATEGORY_SERVICE);
builder.setShowWhen(false);
builder.setOnlyAlertOnce(true);
builder.setOngoing(true);
builder.setAutoCancel(false);
builder.setGroup("update");
builder.setContentTitle(context.getString(R.string.notification_channel_background_update));
builder.setContentText(context.getString(R.string.notification_channel_background_update_description));
notificationManager.notify(NOTIFICATION_ID_ONGOING, builder.build());
} else {
Timber.d("Not posting notification because of missing permission");
}
Thread.currentThread().setPriority(2);
ModuleManager.getINSTANCE().scanAsync();
RepoManager.getINSTANCE().update(null);
ModuleManager.getINSTANCE().runAfterScan(() -> {
int moduleUpdateCount = 0;
HashMap<String, RepoModule> repoModules = RepoManager.getINSTANCE().getModules();
// hasmap of updateable modules names
HashMap<String, String> updateableModules = new HashMap<>();
for (LocalModuleInfo localModuleInfo : ModuleManager.getINSTANCE().getModules().values()) {
if ("twrp-keep".equals(localModuleInfo.id)) continue;
// exclude all modules with id's stored in the pref pref_background_update_check_excludes
try {
if (MainApplication.getPreferences("mmm").getStringSet("pref_background_update_check_excludes", null).contains(localModuleInfo.id))
continue;
} catch (Exception ignored) {
}
RepoModule repoModule = repoModules.get(localModuleInfo.id);
localModuleInfo.checkModuleUpdate();
if (localModuleInfo.updateVersionCode > localModuleInfo.versionCode && !PropUtils.isNullString(localModuleInfo.updateVersion)) {
moduleUpdateCount++;
updateableModules.put(localModuleInfo.name, localModuleInfo.version);
} else if (repoModule != null && repoModule.moduleInfo.versionCode > localModuleInfo.versionCode && !PropUtils.isNullString(repoModule.moduleInfo.version)) {
moduleUpdateCount++;
updateableModules.put(localModuleInfo.name, localModuleInfo.version);
}
}
if (moduleUpdateCount != 0) {
Timber.d("Found %d updates", moduleUpdateCount);
postNotification(context, updateableModules, moduleUpdateCount, false);
}
});
// check for app updates
if (MainApplication.getPreferences("mmm").getBoolean("pref_background_update_check_app", false)) {
try {
boolean shouldUpdate = AppUpdateManager.getAppUpdateManager().checkUpdate(true);
if (shouldUpdate) {
Timber.d("Found app update");
postNotificationForAppUpdate(context);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// remove checking notification
if (ContextCompat.checkSelfPermission(MainApplication.getINSTANCE(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
Timber.d("Removing notification");
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancel(NOTIFICATION_ID_ONGOING);
}
}
}
}

@ -57,7 +57,8 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
this.footerPx = -1;
}
public ModuleHolder(int footerPx,boolean header) {
@SuppressWarnings("unused")
public ModuleHolder(int footerPx, boolean header) {
this.moduleId = "";
this.notificationType = null;
this.separator = null;

@ -226,7 +226,7 @@ public final class ModuleViewAdapter extends RecyclerView.Adapter<ModuleViewAdap
} else if (moduleHolder.moduleId.equals("hosts")) {
this.updateText.setVisibility(View.VISIBLE);
this.updateText.setText(R.string.magisk_builtin_module);
} else if (moduleHolder.moduleId.equals("substratum")) {
} else if (moduleHolder.moduleId.contains("substratum")) {
this.updateText.setVisibility(View.VISIBLE);
this.updateText.setText(R.string.substratum_builtin_module);
} else {
@ -292,6 +292,8 @@ public final class ModuleViewAdapter extends RecyclerView.Adapter<ModuleViewAdap
if (type == ModuleHolder.Type.NOTIFICATION) {
NotificationType notificationType = moduleHolder.notificationType;
this.titleText.setText(notificationType.textId);
// set title text appearance
this.titleText.setTextAppearance(com.google.android.material.R.style.TextAppearance_Material3_BodyLarge);
this.buttonAction.setImageResource(notificationType.iconId);
this.cardView.setClickable(notificationType.onClickListener != null || moduleHolder.onClickListener != null);
this.titleText.setTypeface(notificationType.special ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);

@ -188,6 +188,7 @@ public class ModuleViewListBuilder {
moduleHolders = new ArrayList<>(Math.min(64,
this.mappedModuleHolders.size() + 5));
int special = 0;
// add notifications
Iterator<NotificationType> notificationTypeIterator = this.notifications.iterator();
while (notificationTypeIterator.hasNext()) {
NotificationType notificationType = notificationTypeIterator.next();

@ -163,7 +163,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
setTitle(R.string.app_name);
hideActionBar();
//hideActionBar();
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnItemSelectedListener(onItemSelectedListener);
if (savedInstanceState == null) {
@ -194,7 +194,7 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
@SuppressWarnings("ConstantConditions")
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
String name = "mmm";
Context context = requireContext();
Context context = MainApplication.getINSTANCE();
MasterKey masterKey;
PreferenceManager preferenceManager = getPreferenceManager();
SharedPreferenceDataStore dataStore;

@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
app:fitsSystemWindowsInsets="start|end|bottom|top"
app:layout_constraintTop_toTopOf="parent"
tools:context=".MainActivity">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout

@ -9,17 +9,20 @@
android:filterTouchesWhenObscured="true"
android:gravity="center_vertical"
android:orientation="vertical"
android:padding="1dp"
tools:ignore="RtlHardcoded,RtlSymmetry">
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_view"
style="?attr/materialCardViewElevatedStyle"
android:layout_width="match_parent"
android:padding="0dp"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp"
android:orientation="vertical">
<LinearLayout
@ -27,14 +30,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="6dp"
android:padding="2dp"
app:layout_constraintTop_toTopOf="parent">
<!-- Module components -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:gravity="fill"
android:orientation="horizontal">
<com.google.android.material.chip.Chip
@ -56,10 +59,10 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:maxLines="2"
android:paddingStart="2dp"
android:paddingStart="4dp"
android:layout_gravity="center_vertical"
android:text="@string/loading"
android:textAppearance="?attr/textAppearanceTitleMedium"
android:textSize="16sp" />
android:textSize="19sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switch_action"
@ -83,7 +86,7 @@
android:id="@+id/credit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="2dp"
android:paddingStart="4dp"
android:text="@string/loading"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:textColor="?android:attr/textColorSecondary"
@ -91,10 +94,10 @@
<TextView
android:id="@+id/description_text"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:paddingStart="2dp"
android:layout_marginVertical="4dp"
android:padding="4dp"
android:text="@string/loading"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:textColor="?android:attr/textColorSecondary"
@ -106,7 +109,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginTop="8dp"
android:paddingStart="2dp"
android:paddingStart="4dp"
android:text="@string/loading"
android:textSize="12sp" />
@ -127,6 +130,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:layout_marginHorizontal="2dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/module_layout_helper">

@ -7,6 +7,13 @@
<item name="chipStyle">@style/Widget.Material3.Chip.Choice.Light</item>
<!-- fix bottom navigation bar color -->
<item name="android:navigationBarColor">@color/system_accent2_100</item>
<!-- fonts -->
<item name="android:fontFamily">@font/inter</item>
<item name="font">@font/inter</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="Widget.Material3.Chip.Choice.Light" parent="Widget.Material3.Chip.Assist">
@ -20,6 +27,13 @@
<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>
<!-- fonts -->
<item name="android:fontFamily">@font/inter</item>
<item name="font">@font/inter</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<!-- Black monet theme, which is just dark monet theme with black background -->
@ -39,6 +53,13 @@
<item name="chipSurfaceColor">@color/system_accent2_700</item>
<!-- chips should be dark, not black -->
<item name="chipStyle">@style/Widget.Material.Chip.Choice.Black</item>
<!-- fonts -->
<item name="android:fontFamily">@font/inter</item>
<item name="font">@font/inter</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="Widget.Material3.Chip.Choice.Dark" parent="Widget.Material3.Chip.Assist">

@ -31,7 +31,11 @@
<item name="chipStyle">@style/Widget.Material3.Chip.Choice.Light</item>
<!-- fonts -->
<item name="android:fontFamily">@font/inter</item>
<item name="font">@font/inter</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="Widget.Material3.Chip.Choice.Light" parent="Widget.Material3.Chip.Assist">
@ -60,7 +64,11 @@
<item name="chipStyle">@style/Widget.Material3.Chip.Choice.Light</item>
<!-- fonts -->
<item name="android:fontFamily">@font/inter</item>
<item name="font">@font/inter</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="Theme.MagiskModuleManager.Dark" parent="Theme.Material3.Dark">
@ -93,7 +101,11 @@
<item name="backgroundColor">@color/dark_backgroundColor</item>
<!-- fonts -->
<item name="android:fontFamily">@font/inter</item>
<item name="font">@font/inter</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<!-- Black theme, which is just a dark theme with a black background -->
@ -116,7 +128,13 @@
<item name="android:colorBackgroundCacheHint">@null</item>
<!-- chips should be dark, not black -->
<item name="chipStyle">@style/Widget.Material.Chip.Choice.Dark</item>
<!-- fonts -->
<item name="android:fontFamily">@font/inter</item>
<item name="font">@font/inter</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="Widget.Material.Chip.Choice.Dark" parent="Widget.MaterialComponents.Chip.Action">
@ -130,22 +148,28 @@
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<!-- fonts -->
<item name="android:fontFamily">@font/inter</item>
<item name="font">@font/inter</item>
</style>
<style name="Theme.MagiskModuleManager" parent="Theme.MagiskModuleManager.Light" />
<style name="Theme.MagiskModuleManager.NoActionBar">
<style name="Theme.MagiskModuleManager.NoActionBar" parent="Theme.MagiskModuleManager" >
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="Theme.MagiskModuleManager.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

Loading…
Cancel
Save