You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FoxMagiskModuleManager/app/src/main/java/com/fox2code/mmm/NotificationType.java

235 lines
9.6 KiB
Java

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.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;
interface NotificationTypeCst {
}
public enum NotificationType implements NotificationTypeCst {
DEBUG(R.string.debug_build, R.drawable.ic_baseline_bug_report_24, R.attr.colorSecondary, R.attr.colorOnSecondary) {
@Override
public boolean shouldRemove() {
return !BuildConfig.DEBUG;
}
},
SHOWCASE_MODE(R.string.showcase_mode, R.drawable.ic_baseline_lock_24,
R.attr.colorPrimary, 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,
R.attr.colorPrimary, R.attr.colorOnPrimary, v -> IntentHelper.openUrl(v.getContext(),
"https://github.com/Fox2Code/FoxMagiskModuleManager/releases"), false) {
@Override
public boolean shouldRemove() {
return !AppUpdateManager.getAppUpdateManager().peekShouldUpdate();
}
},
INSTALL_FROM_STORAGE(R.string.install_from_storage, R.drawable.ic_baseline_storage_24,
R.attr.colorBackgroundFloating, 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, R.attr.colorError, R.attr.colorOnPrimary);
}
NotificationType(@StringRes int textId, int iconId, View.OnClickListener onClickListener) {
this(textId, iconId, R.attr.colorError, 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);
}
}