Skip to content
This repository was archived by the owner on May 4, 2023. It is now read-only.

Commit 2f8bc37

Browse files
authored
Merge branch 'Fox2Code:master' into master
2 parents b9b75b0 + 5324f5a commit 2f8bc37

22 files changed

+419
-64
lines changed

app/build.gradle

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ android {
1010
applicationId "com.fox2code.mmm"
1111
minSdk 21
1212
targetSdk 32
13-
versionCode 30
14-
versionName "0.3.2"
13+
versionCode 32
14+
versionName "0.4.0-rc1"
1515

1616
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1717
}
@@ -35,7 +35,6 @@ android {
3535
lint {
3636
disable 'MissingTranslation'
3737
}
38-
namespace 'com.fox2code.mmm'
3938
}
4039

4140
aboutLibraries {
@@ -65,7 +64,7 @@ dependencies {
6564
// Utils
6665
implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.3'
6766
implementation 'com.squareup.okhttp3:okhttp-brotli:4.9.3'
68-
implementation 'com.github.topjohnwu.libsu:io:3.2.1'
67+
implementation 'com.github.topjohnwu.libsu:io:4.0.0'
6968

7069
// Markdown
7170
implementation "io.noties.markwon:core:4.6.2"
@@ -75,6 +74,9 @@ dependencies {
7574
annotationProcessor "io.noties:prism4j-bundler:2.0.0"
7675
implementation "com.caverock:androidsvg:1.4"
7776

77+
// Utils for compat (Needs to be outsourced ASAP)
78+
// compileOnly "org.robolectric:android-all:11-robolectric-6757853"
79+
7880
// Test
7981
testImplementation 'junit:junit:4.+'
8082
androidTestImplementation 'androidx.test.ext:junit:1.1.3'

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:tools="http://schemas.android.com/tools"
4+
package="com.fox2code.mmm"
45
tools:ignore="QueryAllPackagesPermission">
56

67
<!-- Wifi is not the only way to get an internet connection -->
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package android.os;
2+
3+
import androidx.annotation.Keep;
4+
5+
import com.topjohnwu.superuser.ShellUtils;
6+
7+
@Keep
8+
public class SystemProperties {
9+
@Keep
10+
public static String get(String key) {
11+
String prop = ShellUtils.fastCmd("getprop " + key).trim();
12+
if (prop.endsWith("\n"))
13+
prop = prop.substring(0, prop.length() - 1).trim();
14+
return prop;
15+
}
16+
}

app/src/main/java/com/fox2code/mmm/AppUpdateManager.java

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,63 @@
22

33
import android.util.Log;
44

5+
import com.fox2code.mmm.utils.Files;
56
import com.fox2code.mmm.utils.Http;
67

78
import org.json.JSONArray;
89
import org.json.JSONObject;
910

11+
import java.io.BufferedReader;
12+
import java.io.ByteArrayInputStream;
13+
import java.io.File;
14+
import java.io.FileInputStream;
15+
import java.io.IOException;
16+
import java.io.InputStream;
17+
import java.io.InputStreamReader;
1018
import java.nio.charset.StandardCharsets;
19+
import java.util.HashMap;
1120

1221
// See https://docs.github.com/en/rest/reference/repos#releases
1322
public class AppUpdateManager {
23+
public static int FLAG_COMPAT_LOW_QUALITY = 0x01;
24+
public static int FLAG_COMPAT_NO_EXT = 0x02;
25+
public static int FLAG_COMPAT_MAGISK_CMD = 0x04;
26+
public static int FLAG_COMPAT_NEED_32BIT = 0x08;
1427
private static final String TAG = "AppUpdateManager";
1528
private static final AppUpdateManager INSTANCE = new AppUpdateManager();
1629
private static final String RELEASES_API_URL =
1730
"https://api.github.com/repos/Fox2Code/FoxMagiskModuleManager/releases";
31+
private static final String COMPAT_API_URL =
32+
"https://api.github.com/repos/Fox2Code/FoxMagiskModuleManager/releases";
1833

1934
public static AppUpdateManager getAppUpdateManager() {
2035
return INSTANCE;
2136
}
2237

38+
private final HashMap<String, Integer> compatDataId = new HashMap<>();
2339
private final Object updateLock = new Object();
40+
private final File compatFile;
2441
private String latestRelease;
2542
private String latestPreRelease;
2643
private long lastChecked;
2744
private boolean preReleaseNewer;
2845
private boolean lastCheckSuccess;
2946

3047
private AppUpdateManager() {
48+
this.compatFile = new File(MainApplication.getINSTANCE().getFilesDir(), "compat.txt");
3149
this.latestRelease = MainApplication.getBootSharedPreferences()
3250
.getString("updater_latest_release", BuildConfig.VERSION_NAME);
3351
this.latestPreRelease = MainApplication.getBootSharedPreferences()
3452
.getString("updater_latest_pre_release", BuildConfig.VERSION_NAME);
3553
this.lastChecked = 0;
3654
this.preReleaseNewer = true;
55+
if (this.compatFile.isFile()) {
56+
try {
57+
this.parseCompatibilityFlags(new FileInputStream(this.compatFile));
58+
} catch (IOException e) {
59+
e.printStackTrace();
60+
}
61+
}
3762
}
3863

3964
// Return true if should show a notification
@@ -95,6 +120,31 @@ public boolean checkUpdate(boolean force) {
95120
return this.peekShouldUpdate();
96121
}
97122

123+
public void checkUpdateCompat() {
124+
if (this.compatFile.exists()) {
125+
long lastUpdate = this.compatFile.lastModified();
126+
if (lastUpdate <= System.currentTimeMillis() &&
127+
lastUpdate + 600_000L > System.currentTimeMillis()) {
128+
return; // Skip update
129+
}
130+
}
131+
try {
132+
JSONObject object = new JSONObject(new String(Http.doHttpGet(
133+
COMPAT_API_URL, false), StandardCharsets.UTF_8));
134+
if (object.isNull("body")) {
135+
compatDataId.clear();
136+
Files.write(compatFile, new byte[0]);
137+
return;
138+
}
139+
byte[] rawData = object.getString("body")
140+
.getBytes(StandardCharsets.UTF_8);
141+
this.parseCompatibilityFlags(new ByteArrayInputStream(rawData));
142+
Files.write(compatFile, rawData);
143+
} catch (Exception e) {
144+
Log.e("AppUpdateManager", "Failed to update compat list", e);
145+
}
146+
}
147+
98148
public boolean peekShouldUpdate() {
99149
return !(BuildConfig.VERSION_NAME.equals(this.latestRelease) ||
100150
(this.preReleaseNewer &&
@@ -109,4 +159,46 @@ public boolean peekHasUpdate() {
109159
public boolean isLastCheckSuccess() {
110160
return lastCheckSuccess;
111161
}
162+
163+
private void parseCompatibilityFlags(InputStream inputStream) throws IOException {
164+
compatDataId.clear();
165+
BufferedReader bufferedReader = new BufferedReader(
166+
new InputStreamReader(inputStream, StandardCharsets.UTF_8));
167+
String line;
168+
while ((line = bufferedReader.readLine()) != null) {
169+
line = line.trim();
170+
if (line.isEmpty() || line.startsWith("#")) continue;
171+
int i = line.indexOf('/');
172+
if (i == -1) continue;
173+
int value = 0;
174+
for (String arg : line.substring(i + 1).split(",")) {
175+
switch (arg) {
176+
default:
177+
break;
178+
case "lowQuality":
179+
value |= FLAG_COMPAT_LOW_QUALITY;
180+
break;
181+
case "noExt":
182+
value |= FLAG_COMPAT_NO_EXT;
183+
break;
184+
case "magiskCmd":
185+
value |= FLAG_COMPAT_MAGISK_CMD;
186+
break;
187+
case "need32bit":
188+
value |= FLAG_COMPAT_NEED_32BIT;
189+
break;
190+
}
191+
}
192+
compatDataId.put(line.substring(0, i), value);
193+
}
194+
}
195+
196+
public int getCompatibilityFlags(String moduleId) {
197+
Integer compatFlags = compatDataId.get(moduleId);
198+
return compatFlags == null ? 0 : compatFlags;
199+
}
200+
201+
public static int getFlagsForModule(String moduleId) {
202+
return INSTANCE.getCompatibilityFlags(moduleId);
203+
}
112204
}

app/src/main/java/com/fox2code/mmm/MainActivity.java

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import androidx.appcompat.widget.SearchView;
55
import androidx.cardview.widget.CardView;
66
import androidx.core.content.ContextCompat;
7+
import androidx.core.graphics.ColorUtils;
78
import androidx.recyclerview.widget.LinearLayoutManager;
89
import androidx.recyclerview.widget.RecyclerView;
910
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@@ -22,6 +23,7 @@
2223
import android.widget.TextView;
2324

2425
import com.fox2code.mmm.compat.CompatActivity;
26+
import com.fox2code.mmm.compat.CompatDisplay;
2527
import com.fox2code.mmm.installer.InstallerInitializer;
2628
import com.fox2code.mmm.manager.LocalModuleInfo;
2729
import com.fox2code.mmm.manager.ModuleManager;
@@ -32,6 +34,7 @@
3234
import com.google.android.material.progressindicator.LinearProgressIndicator;
3335

3436
import eightbitlab.com.blurview.BlurView;
37+
import eightbitlab.com.blurview.BlurViewFacade;
3538
import eightbitlab.com.blurview.RenderScriptBlur;
3639

3740
public class MainActivity extends CompatActivity implements SwipeRefreshLayout.OnRefreshListener,
@@ -72,10 +75,8 @@ protected void onCreate(Bundle savedInstanceState) {
7275
setContentView(R.layout.activity_main);
7376
this.setTitle(R.string.app_name);
7477
this.getWindow().setFlags(
75-
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION |
76-
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
77-
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION |
78-
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
78+
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
79+
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
7980
setActionBarBackground(null);
8081
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
8182
WindowManager.LayoutParams layoutParams = this.getWindow().getAttributes();
@@ -106,7 +107,7 @@ protected void onCreate(Bundle savedInstanceState) {
106107
this.actionBarBlur.setupWith(this.moduleList).setFrameClearDrawable(
107108
this.getWindow().getDecorView().getBackground())
108109
.setBlurAlgorithm(new RenderScriptBlur(this))
109-
.setBlurRadius(5F).setBlurAutoUpdate(true)
110+
.setBlurRadius(4F).setBlurAutoUpdate(true)
110111
.setHasFixedTransformationMatrix(true);
111112
this.updateBlurState();
112113
this.moduleList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@@ -116,6 +117,8 @@ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newStat
116117
MainActivity.this.searchView.clearFocus();
117118
}
118119
});
120+
this.searchCard.setRadius(this.searchCard.getHeight() / 2F);
121+
this.searchView.setMinimumHeight(CompatDisplay.dpToPixel(16));
119122
this.searchView.setImeOptions(EditorInfo.IME_ACTION_SEARCH |
120123
EditorInfo.IME_FLAG_NO_FULLSCREEN);
121124
this.searchView.setOnQueryTextListener(this);
@@ -177,6 +180,8 @@ public void commonNext() {
177180
} else {
178181
if (AppUpdateManager.getAppUpdateManager().checkUpdate(true))
179182
moduleViewListBuilder.addNotification(NotificationType.UPDATE_AVAILABLE);
183+
if (AppUpdateManager.getAppUpdateManager().isLastCheckSuccess())
184+
AppUpdateManager.getAppUpdateManager().checkUpdateCompat();
180185
if (max != 0) {
181186
int current = 0;
182187
for (LocalModuleInfo localModuleInfo :
@@ -238,32 +243,38 @@ private void updateScreenInsets(Configuration configuration) {
238243
this.swipeRefreshLayout.setProgressViewOffset(false,
239244
swipeRefreshLayoutOrigStartOffset + combinedBarsHeight,
240245
swipeRefreshLayoutOrigEndOffset + combinedBarsHeight);
241-
this.moduleViewListBuilder.setHeaderPx(actionBarHeight);
246+
this.moduleViewListBuilder.setHeaderPx(
247+
actionBarHeight + CompatDisplay.dpToPixel(8));
242248
this.moduleViewListBuilder.setFooterPx(
243249
bottomInset + this.searchCard.getHeight());
250+
this.searchCard.setRadius(this.searchCard.getHeight() / 2F);
244251
this.moduleViewListBuilder.updateInsets();
245252
this.actionBarBlur.invalidate();
246253
this.overScrollInsetTop = combinedBarsHeight;
247254
this.overScrollInsetBottom = bottomInset;
255+
Log.d(TAG, "( " + bottomInset + ", " +
256+
this.searchCard.getHeight() + ")");
248257
}
249258

250259
private void updateBlurState() {
260+
boolean isLightMode = this.isLightTheme();
261+
int colorBackground;
262+
try {
263+
colorBackground = this.getColorCompat(
264+
android.R.attr.windowBackground);
265+
} catch (Resources.NotFoundException e) {
266+
colorBackground = this.getColorCompat(isLightMode ?
267+
R.color.white : R.color.black);
268+
}
251269
if (MainApplication.isBlurEnabled()) {
252270
this.actionBarBlur.setBlurEnabled(true);
253-
int transparent = this.getColorCompat(R.color.transparent);
254-
this.actionBarBackground.setColor(transparent);
271+
this.actionBarBackground.setColor(ColorUtils
272+
.setAlphaComponent(colorBackground, 0x02));
273+
this.actionBarBackground.setColor(Color.TRANSPARENT);
255274
} else {
256275
this.actionBarBlur.setBlurEnabled(false);
257-
boolean isLightMode = this.isLightTheme();
258-
int colorOpaque;
259-
try {
260-
colorOpaque = this.getColorCompat(
261-
android.R.attr.windowBackground);
262-
} catch (Resources.NotFoundException e) {
263-
colorOpaque = this.getColorCompat(isLightMode ?
264-
R.color.white : R.color.black);
265-
}
266-
this.actionBarBackground.setColor(colorOpaque);
276+
this.actionBarBlur.setOverlayColor(Color.TRANSPARENT);
277+
this.actionBarBackground.setColor(colorBackground);
267278
}
268279
}
269280

app/src/main/java/com/fox2code/mmm/ModuleViewAdapter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public ViewHolder(@NonNull View itemView) {
104104
}
105105
}
106106
});
107+
this.buttonAction.setClickable(false);
107108
this.switchMaterial.setEnabled(false);
108109
this.switchMaterial.setOnCheckedChangeListener((v, checked) -> {
109110
if (this.initState) return; // Skip if non user

app/src/main/java/com/fox2code/mmm/ModuleViewListBuilder.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public void appendRemoteModules() {
7676
RepoManager repoManager = RepoManager.getINSTANCE();
7777
repoManager.runAfterUpdate(() -> {
7878
Log.i(TAG, "A2: " + repoManager.getModules().size());
79+
boolean no32bitSupport = Build.SUPPORTED_32_BIT_ABIS.length == 0;
7980
for (RepoModule repoModule : repoManager.getModules().values()) {
8081
if (!repoModule.repoData.isEnabled()) continue;
8182
ModuleInfo moduleInfo = repoModule.moduleInfo;
@@ -84,9 +85,11 @@ public void appendRemoteModules() {
8485
// Only check Magisk compatibility if root is present
8586
(InstallerInitializer.peekMagiskPath() != null &&
8687
repoModule.moduleInfo.minMagisk >
87-
InstallerInitializer.peekMagiskVersion()
88-
)))
89-
continue; // Skip adding incompatible modules
88+
InstallerInitializer.peekMagiskVersion())) ||
89+
// If 64bit only system, skip 32bit only modules
90+
(no32bitSupport && (AppUpdateManager.getFlagsForModule(repoModule.id)
91+
& AppUpdateManager.FLAG_COMPAT_NEED_32BIT) != 0)
92+
) continue; // Skip adding incompatible modules
9093
ModuleHolder moduleHolder = this.mappedModuleHolders.get(repoModule.id);
9194
if (moduleHolder == null) {
9295
this.mappedModuleHolders.put(repoModule.id,

app/src/main/java/com/fox2code/mmm/NotificationType.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,17 @@ public boolean shouldRemove() {
3131
return !MainApplication.isShowcaseMode();
3232
}
3333
},
34-
NO_ROOT(R.string.fail_root_magisk, R.drawable.ic_baseline_numbers_24) {
34+
NO_ROOT(R.string.fail_root_magisk, R.drawable.ic_baseline_numbers_24, v -> {
35+
IntentHelper.openUrl(v.getContext(), "https://github.com/topjohnwu/Magisk");
36+
}) {
3537
@Override
3638
public boolean shouldRemove() {
3739
return InstallerInitializer.peekMagiskPath() != null;
3840
}
3941
},
40-
MAGISK_OUTDATED(R.string.magisk_outdated, R.drawable.ic_baseline_update_24) {
42+
MAGISK_OUTDATED(R.string.magisk_outdated, R.drawable.ic_baseline_update_24, v -> {
43+
IntentHelper.openUrl(v.getContext(), "https://github.com/topjohnwu/Magisk");
44+
}) {
4145
@Override
4246
public boolean shouldRemove() {
4347
return InstallerInitializer.peekMagiskPath() == null ||
@@ -128,7 +132,11 @@ public boolean shouldRemove() {
128132
public final boolean special;
129133

130134
NotificationType(@StringRes int textId, int iconId) {
131-
this(textId, iconId, R.attr.colorError, R.attr.colorOnPrimary); //R.attr.colorOnError);
135+
this(textId, iconId, R.attr.colorError, R.attr.colorOnPrimary);
136+
}
137+
138+
NotificationType(@StringRes int textId, int iconId, View.OnClickListener onClickListener) {
139+
this(textId, iconId, R.attr.colorError, R.attr.colorOnPrimary, onClickListener);
132140
}
133141

134142
NotificationType(@StringRes int textId, int iconId, int backgroundAttr, int foregroundAttr) {

0 commit comments

Comments
 (0)