Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/27/head
androidacy-user 2 years ago
parent 4638823c4d
commit bf8578de2a

@ -398,14 +398,14 @@ configurations {
dependencies {
// UI
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.activity:activity-ktx:1.7.1")
implementation("androidx.activity:activity-ktx:1.7.2")
implementation("androidx.emoji2:emoji2:1.3.0")
implementation("androidx.emoji2:emoji2-views-helper:1.3.0")
implementation("androidx.preference:preference-ktx:1.2.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.recyclerview:recyclerview:1.3.0")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.webkit:webkit:1.6.1")
implementation("androidx.webkit:webkit:1.7.0")
implementation("com.google.android.material:material:1.9.0")
implementation("dev.rikka.rikkax.layoutinflater:layoutinflater:1.3.0")
implementation("dev.rikka.rikkax.insets:insets:1.3.0")
@ -426,7 +426,7 @@ dependencies {
// implementation("com.google.protobuf:protobuf-javalite:3.22.2")
// google guava, maybe fix a bug
implementation("com.google.guava:guava:31.1-jre")
implementation("com.google.guava:guava:32.0.0-jre")
val libsuVersion = "5.0.5"
@ -443,12 +443,12 @@ dependencies {
implementation("com.github.Fox2Code:AndroidANSI:1.2.1")
// sentry
implementation("io.sentry:sentry-android:6.19.1")
implementation("io.sentry:sentry-android-timber:6.19.1")
implementation("io.sentry:sentry-android-fragment:6.19.1")
implementation("io.sentry:sentry-android-okhttp:6.19.1")
implementation("io.sentry:sentry-kotlin-extensions:6.19.1")
implementation("io.sentry:sentry-android-ndk:6.19.1")
implementation("io.sentry:sentry-android:6.20.0")
implementation("io.sentry:sentry-android-timber:6.20.0")
implementation("io.sentry:sentry-android-fragment:6.20.0")
implementation("io.sentry:sentry-android-okhttp:6.20.0")
implementation("io.sentry:sentry-kotlin-extensions:6.20.0")
implementation("io.sentry:sentry-android-ndk:6.20.0")
// Markdown
// TODO: switch to an updated implementation
@ -488,7 +488,7 @@ dependencies {
}
android {
ndkVersion = "23.0.7344513"
ndkVersion = "25.2.9519653"
dependenciesInfo {
includeInApk = false
includeInBundle = false

@ -1,231 +0,0 @@
package com.fox2code.mmm;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.AttrRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.StringRes;
import com.fox2code.foxcompat.app.FoxActivity;
import com.fox2code.mmm.installer.InstallerInitializer;
import com.fox2code.mmm.module.ModuleViewListBuilder;
import com.fox2code.mmm.repo.RepoManager;
import com.fox2code.mmm.utils.IntentHelper;
import com.fox2code.mmm.utils.io.Files;
import com.fox2code.mmm.utils.io.net.Http;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import timber.log.Timber;
public enum NotificationType implements NotificationTypeCst {
DEBUG(R.string.debug_build, R.drawable.ic_baseline_bug_report_24, com.google.android.material.R.attr.colorSecondary, com.google.android.material.R.attr.colorOnSecondary) {
@Override
public boolean shouldRemove() {
return !BuildConfig.DEBUG;
}
},
SHOWCASE_MODE(R.string.showcase_mode, R.drawable.ic_baseline_lock_24,
androidx.appcompat.R.attr.colorPrimary, com.google.android.material.R.attr.colorOnPrimary) {
@Override
public boolean shouldRemove() {
return !MainApplication.isShowcaseMode();
}
},
NO_MAGISK(R.string.fail_magisk_missing, R.drawable.ic_baseline_numbers_24, v ->
IntentHelper.openUrl(v.getContext(),
"https://github.com/topjohnwu/Magisk/blob/master/docs/install.md")) {
@Override
public boolean shouldRemove() {
return InstallerInitializer.getErrorNotification() != this;
}
},
NO_ROOT(R.string.fail_root_magisk, R.drawable.ic_baseline_numbers_24) {
@Override
public boolean shouldRemove() {
return InstallerInitializer.getErrorNotification() != this;
}
},
ROOT_DENIED(R.string.fail_root_denied, R.drawable.ic_baseline_numbers_24) {
@Override
public boolean shouldRemove() {
return InstallerInitializer.getErrorNotification() != this;
}
},
MAGISK_OUTDATED(R.string.magisk_outdated, R.drawable.ic_baseline_update_24, v -> IntentHelper.openUrl(v.getContext(), "https://github.com/topjohnwu/Magisk/releases")) {
@Override
public boolean shouldRemove() {
return InstallerInitializer.peekMagiskPath() == null ||
InstallerInitializer.peekMagiskVersion() >=
Constants.MAGISK_VER_CODE_INSTALL_COMMAND;
}
},
NO_INTERNET(R.string.fail_internet, R.drawable.ic_baseline_cloud_off_24) {
@Override
public boolean shouldRemove() {
return RepoManager.getINSTANCE().hasConnectivity();
}
},
REPO_UPDATE_FAILED(R.string.repo_update_failed, R.drawable.ic_baseline_cloud_off_24) {
@Override
public boolean shouldRemove() {
return RepoManager.getINSTANCE().isLastUpdateSuccess();
}
},
NEED_CAPTCHA_ANDROIDACY(R.string.androidacy_need_captcha, R.drawable.ic_baseline_refresh_24, v ->
IntentHelper.openUrlAndroidacy(v.getContext(),
"https://" + Http.needCaptchaAndroidacyHost() + "/", false)) {
@Override
public boolean shouldRemove() {
return !RepoManager.isAndroidacyRepoEnabled()
|| !Http.needCaptchaAndroidacy();
}
},
NO_WEB_VIEW(R.string.no_web_view, R.drawable.ic_baseline_android_24) {
@Override
public boolean shouldRemove() {
return Http.hasWebView();
}
},
UPDATE_AVAILABLE(R.string.app_update_available, R.drawable.ic_baseline_system_update_24,
androidx.appcompat.R.attr.colorPrimary, com.google.android.material.R.attr.colorOnPrimary, v -> IntentHelper.openUrl(v.getContext(),
"https://github.com/Androidacy/MagiskModuleManager/releases"), false) {
@Override
public boolean shouldRemove() {
return !AppUpdateManager.getAppUpdateManager().peekShouldUpdate();
}
},
INSTALL_FROM_STORAGE(R.string.install_from_storage, R.drawable.ic_baseline_storage_24,
androidx.appcompat.R.attr.colorBackgroundFloating, com.google.android.material.R.attr.colorOnBackground, v -> {
FoxActivity compatActivity = FoxActivity.getFoxActivity(v);
final File module = new File(compatActivity.getCacheDir(),
"installer" + File.separator + "module.zip");
IntentHelper.openFileTo(compatActivity, module, (d, u, s) -> {
if (s == IntentHelper.RESPONSE_FILE) {
try {
if (needPatch(d)) {
Files.patchModuleSimple(Files.read(d),
new FileOutputStream(d));
}
if (needPatch(d)) {
if (d.exists() && !d.delete())
Timber.w("Failed to delete non module zip");
Toast.makeText(compatActivity,
R.string.invalid_format, Toast.LENGTH_SHORT).show();
} else {
IntentHelper.openInstaller(compatActivity, d.getAbsolutePath(),
compatActivity.getString(
R.string.local_install_title), null, null, false,
BuildConfig.DEBUG && // Use debug mode if no root
InstallerInitializer.peekMagiskPath() == null);
}
} catch (IOException ignored) {
if (d.exists() && !d.delete())
Timber.w("Failed to delete invalid module");
Toast.makeText(compatActivity,
R.string.invalid_format, Toast.LENGTH_SHORT).show();
}
} else if (s == IntentHelper.RESPONSE_URL) {
IntentHelper.openInstaller(compatActivity, u.toString(),
compatActivity.getString(
R.string.remote_install_title), null, null, false,
BuildConfig.DEBUG && // Use debug mode if no root
InstallerInitializer.peekMagiskPath() == null);
}
});
}, false) {
@Override
public boolean shouldRemove() {
return !BuildConfig.DEBUG &&
(MainApplication.isShowcaseMode() ||
InstallerInitializer.peekMagiskPath() == null);
}
};
public static boolean needPatch(File target) {
try (ZipFile zipFile = new ZipFile(target)) {
boolean validEntries = zipFile.getEntry("module.prop") != null;
// ensure there's no anykernel.sh
validEntries &= zipFile.getEntry("anykernel.sh") == null;
if (validEntries) {
// Ensure id of module is not empty and matches ^[a-zA-Z][a-zA-Z0-9._-]+$ regex
// We need to get the module.prop and parse the id= line
ZipEntry moduleProp = zipFile.getEntry("module.prop");
// Parse the module.prop
if (moduleProp != null) {
// Find the line with id=, and check if it matches the regex
try (BufferedReader reader = new BufferedReader(new InputStreamReader(zipFile.getInputStream(moduleProp)))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("id=")) {
String id = line.substring(3);
return id.isEmpty() || !id.matches("^[a-zA-Z][a-zA-Z0-9._-]+$");
}
}
}
} else {
return true;
}
} else {
return true;
}
} catch (IOException e) {
return true;
}
return false;
}
@StringRes
public final int textId;
@DrawableRes
public final int iconId;
@AttrRes
public final int backgroundAttr;
@AttrRes
public final int foregroundAttr;
public final View.OnClickListener onClickListener;
public final boolean special;
NotificationType(@StringRes int textId, int iconId) {
this(textId, iconId, androidx.appcompat.R.attr.colorError, com.google.android.material.R.attr.colorOnPrimary);
}
NotificationType(@StringRes int textId, int iconId, View.OnClickListener onClickListener) {
this(textId, iconId, androidx.appcompat.R.attr.colorError, com.google.android.material.R.attr.colorOnPrimary, onClickListener);
}
NotificationType(@StringRes int textId, int iconId, int backgroundAttr, int foregroundAttr) {
this(textId, iconId, backgroundAttr, foregroundAttr, null);
}
NotificationType(@StringRes int textId, int iconId, int backgroundAttr, int foregroundAttr,
View.OnClickListener onClickListener) {
this(textId, iconId, backgroundAttr, foregroundAttr, onClickListener, false);
}
NotificationType(@StringRes int textId, int iconId, int backgroundAttr, int foregroundAttr,
View.OnClickListener onClickListener, @SuppressWarnings("SameParameterValue") boolean special) {
this.textId = textId;
this.iconId = iconId;
this.backgroundAttr = backgroundAttr;
this.foregroundAttr = foregroundAttr;
this.onClickListener = onClickListener;
this.special = special;
}
public boolean shouldRemove() {
// By default, remove the notification`
return false;
}
public final void autoAdd(ModuleViewListBuilder moduleViewListBuilder) {
if (!shouldRemove()) moduleViewListBuilder.addNotification(this);
}
}

@ -0,0 +1,256 @@
@file:Suppress("KotlinConstantConditions", "UNINITIALIZED_ENUM_COMPANION_WARNING",
"ktConcatNullable", "BlockingMethodInNonBlockingContext"
)
package com.fox2code.mmm
import android.net.Uri
import android.view.View
import android.widget.Toast
import androidx.annotation.AttrRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import com.fox2code.foxcompat.app.FoxActivity
import com.fox2code.mmm.installer.InstallerInitializer
import com.fox2code.mmm.module.ModuleViewListBuilder
import com.fox2code.mmm.repo.RepoManager
import com.fox2code.mmm.utils.IntentHelper
import com.fox2code.mmm.utils.io.Files.Companion.patchModuleSimple
import com.fox2code.mmm.utils.io.Files.Companion.read
import com.fox2code.mmm.utils.io.net.Http
import timber.log.Timber
import java.io.BufferedReader
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStreamReader
import java.util.zip.ZipFile
enum class NotificationType constructor(
@field:StringRes @param:StringRes val textId: Int,
@field:DrawableRes val iconId: Int,
@field:AttrRes val backgroundAttr: Int = androidx.appcompat.R.attr.colorError,
@field:AttrRes val foregroundAttr: Int = com.google.android.material.R.attr.colorOnPrimary,
val onClickListener: View.OnClickListener? = null,
val special: Boolean = false
) : NotificationTypeCst {
DEBUG(
R.string.debug_build,
R.drawable.ic_baseline_bug_report_24,
com.google.android.material.R.attr.colorSecondary,
com.google.android.material.R.attr.colorOnSecondary
) {
override fun shouldRemove(): Boolean {
return !BuildConfig.DEBUG
}
},
SHOWCASE_MODE(
R.string.showcase_mode, R.drawable.ic_baseline_lock_24,
androidx.appcompat.R.attr.colorPrimary, com.google.android.material.R.attr.colorOnPrimary
) {
override fun shouldRemove(): Boolean {
return !MainApplication.isShowcaseMode()
}
},
NO_MAGISK(
R.string.fail_magisk_missing,
R.drawable.ic_baseline_numbers_24,
View.OnClickListener { v: View ->
IntentHelper.openUrl(
v.context,
"https://github.com/topjohnwu/Magisk/blob/master/docs/install.md"
)
}) {
override fun shouldRemove(): Boolean {
return InstallerInitializer.getErrorNotification() !== this
}
},
NO_ROOT(R.string.fail_root_magisk, R.drawable.ic_baseline_numbers_24) {
override fun shouldRemove(): Boolean {
return InstallerInitializer.getErrorNotification() !== this
}
},
ROOT_DENIED(R.string.fail_root_denied, R.drawable.ic_baseline_numbers_24) {
override fun shouldRemove(): Boolean {
return InstallerInitializer.getErrorNotification() !== this
}
},
MAGISK_OUTDATED(
R.string.magisk_outdated,
R.drawable.ic_baseline_update_24,
View.OnClickListener { v: View ->
IntentHelper.openUrl(
v.context,
"https://github.com/topjohnwu/Magisk/releases"
)
}) {
override fun shouldRemove(): Boolean {
return InstallerInitializer.peekMagiskPath() == null ||
InstallerInitializer.peekMagiskVersion() >=
Constants.MAGISK_VER_CODE_INSTALL_COMMAND
}
},
NO_INTERNET(R.string.fail_internet, R.drawable.ic_baseline_cloud_off_24) {
override fun shouldRemove(): Boolean {
return RepoManager.getINSTANCE().hasConnectivity()
}
},
REPO_UPDATE_FAILED(R.string.repo_update_failed, R.drawable.ic_baseline_cloud_off_24) {
override fun shouldRemove(): Boolean {
return RepoManager.getINSTANCE().isLastUpdateSuccess
}
},
NEED_CAPTCHA_ANDROIDACY(
R.string.androidacy_need_captcha,
R.drawable.ic_baseline_refresh_24,
View.OnClickListener { v: View ->
IntentHelper.openUrlAndroidacy(
v.context,
"https://" + Http.needCaptchaAndroidacyHost() + "/", false
)
}) {
override fun shouldRemove(): Boolean {
return (!RepoManager.isAndroidacyRepoEnabled()
|| !Http.needCaptchaAndroidacy())
}
},
NO_WEB_VIEW(R.string.no_web_view, R.drawable.ic_baseline_android_24) {
override fun shouldRemove(): Boolean {
return Http.hasWebView()
}
},
UPDATE_AVAILABLE(
R.string.app_update_available,
R.drawable.ic_baseline_system_update_24,
androidx.appcompat.R.attr.colorPrimary,
com.google.android.material.R.attr.colorOnPrimary,
View.OnClickListener { v: View ->
IntentHelper.openUrl(
v.context,
"https://github.com/Androidacy/MagiskModuleManager/releases"
)
},
false
) {
override fun shouldRemove(): Boolean {
return !AppUpdateManager.getAppUpdateManager().peekShouldUpdate()
}
},
INSTALL_FROM_STORAGE(
R.string.install_from_storage,
R.drawable.ic_baseline_storage_24,
androidx.appcompat.R.attr.colorBackgroundFloating,
com.google.android.material.R.attr.colorOnBackground,
View.OnClickListener { v: View? ->
val compatActivity = FoxActivity.getFoxActivity(v)
val module = File(
compatActivity.cacheDir,
"installer" + File.separator + "module.zip"
)
IntentHelper.openFileTo(compatActivity, module) { d: File, u: Uri, s: Int ->
if (s == IntentHelper.RESPONSE_FILE) {
try {
if (needPatch(d)) {
patchModuleSimple(
read(d),
FileOutputStream(d)
)
}
if (needPatch(d)) {
if (d.exists() && !d.delete()) Timber.w("Failed to delete non module zip")
Toast.makeText(
compatActivity,
R.string.invalid_format, Toast.LENGTH_SHORT
).show()
} else {
IntentHelper.openInstaller(
compatActivity, d.absolutePath,
compatActivity.getString(
R.string.local_install_title
), null, null, false,
BuildConfig.DEBUG && // Use debug mode if no root
InstallerInitializer.peekMagiskPath() == null
)
}
} catch (ignored: IOException) {
if (d.exists() && !d.delete()) Timber.w("Failed to delete invalid module")
Toast.makeText(
compatActivity,
R.string.invalid_format, Toast.LENGTH_SHORT
).show()
}
} else if (s == IntentHelper.RESPONSE_URL) {
IntentHelper.openInstaller(
compatActivity, u.toString(),
compatActivity.getString(
R.string.remote_install_title
), null, null, false,
BuildConfig.DEBUG && // Use debug mode if no root
InstallerInitializer.peekMagiskPath() == null
)
}
}
},
false
) {
override fun shouldRemove(): Boolean {
return !BuildConfig.DEBUG &&
(MainApplication.isShowcaseMode() ||
InstallerInitializer.peekMagiskPath() == null)
}
};
constructor(@StringRes textId: Int, iconId: Int, onClickListener: View.OnClickListener) : this(
textId,
iconId,
androidx.appcompat.R.attr.colorError,
com.google.android.material.R.attr.colorOnPrimary,
onClickListener
)
open fun shouldRemove(): Boolean {
// By default, remove the notification`
return false
}
fun autoAdd(moduleViewListBuilder: ModuleViewListBuilder) {
if (!shouldRemove()) moduleViewListBuilder.addNotification(this)
}
companion object {
fun needPatch(target: File?): Boolean {
try {
ZipFile(target).use { zipFile ->
var validEntries = zipFile.getEntry("module.prop") != null
// ensure there's no anykernel.sh
validEntries = validEntries and (zipFile.getEntry("anykernel.sh") == null)
if (validEntries) {
// Ensure id of module is not empty and matches ^[a-zA-Z][a-zA-Z0-9._-]+$ regex
// We need to get the module.prop and parse the id= line
val moduleProp = zipFile.getEntry("module.prop")
// Parse the module.prop
if (moduleProp != null) {
// Find the line with id=, and check if it matches the regex
BufferedReader(InputStreamReader(zipFile.getInputStream(moduleProp))).use { reader ->
var line: String
while (reader.readLine().also { line = it } != null) {
if (line.startsWith("id=")) {
val id = line.substring(3)
return id.isEmpty() || !id.matches(Regex("^[a-zA-Z][a-zA-Z0-9._-]+$"))
}
}
}
} else {
return true
}
} else {
return true
}
}
} catch (e: IOException) {
return true
}
return false
}
}
}

@ -14,14 +14,14 @@ buildscript {
set("sentryVersion", "6.18.1")
}
dependencies {
classpath("com.android.tools.build:gradle:8.0.1")
classpath("com.android.tools.build:gradle:8.0.2")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.21")
classpath("com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:10.6.2")
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath("io.realm:realm-gradle-plugin:10.15.1")
classpath("io.sentry:sentry-android-gradle-plugin:3.5.0")
classpath("io.sentry:sentry-android-gradle-plugin:3.7.0")
}
}

@ -10,7 +10,7 @@
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Mon May 08 13:44:15 EDT 2023
#Mon May 29 11:36:28 EDT 2023
android.defaults.buildfeatures.buildconfig=true
android.enableJetifier=false
android.enableR8.fullMode=true
@ -18,5 +18,5 @@ android.useAndroidX=true
org.gradle.caching=true
org.gradle.configuration-cache=true
org.gradle.configuration-cache.problems=warn
org.gradle.jvmargs=-Xmx1024M -Dkotlin.daemon.jvm.options\="-Xmx1024M" -Dfile.encoding\=UTF-8 -XX\:+UseParallelGC -XX\:ReservedCodeCacheSize\=768m
org.gradle.jvmargs=-Xmx1536M -Dkotlin.daemon.jvm.options\="-Xmx1536M" -Dfile.encoding\=UTF-8 -XX\:+UseParallelGC -XX\:ReservedCodeCacheSize\=768m
org.gradle.parallel=true

Loading…
Cancel
Save