finish room and kotlin migration
SettingsActivity.java cannot be converted right now because AS crashes silently Signed-off-by: androidacy-user <opensource@androidacy.com>pull/89/head
parent
0b05dfe29b
commit
743cd3f46d
@ -0,0 +1,142 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 1,
|
||||
"identityHash": "2abfd2dad332c887d96cdda63d92a639",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "modulelistcache",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`codename` TEXT NOT NULL, `version` TEXT NOT NULL, `versionCode` INTEGER NOT NULL, `author` TEXT NOT NULL, `description` TEXT NOT NULL, `minApi` INTEGER NOT NULL, `maxApi` INTEGER NOT NULL, `minMagisk` INTEGER NOT NULL, `needRamdisk` INTEGER NOT NULL, `support` TEXT NOT NULL, `donate` TEXT NOT NULL, `config` TEXT NOT NULL, `changeBoot` INTEGER NOT NULL, `mmtReborn` INTEGER NOT NULL, `repoId` TEXT NOT NULL, `lastUpdate` INTEGER NOT NULL, `name` TEXT NOT NULL, `safe` INTEGER NOT NULL, `stats` INTEGER NOT NULL, PRIMARY KEY(`codename`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "codename",
|
||||
"columnName": "codename",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "version",
|
||||
"columnName": "version",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "versionCode",
|
||||
"columnName": "versionCode",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "author",
|
||||
"columnName": "author",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "description",
|
||||
"columnName": "description",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "minApi",
|
||||
"columnName": "minApi",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "maxApi",
|
||||
"columnName": "maxApi",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "minMagisk",
|
||||
"columnName": "minMagisk",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "needRamdisk",
|
||||
"columnName": "needRamdisk",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "support",
|
||||
"columnName": "support",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "donate",
|
||||
"columnName": "donate",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "config",
|
||||
"columnName": "config",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "changeBoot",
|
||||
"columnName": "changeBoot",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "mmtReborn",
|
||||
"columnName": "mmtReborn",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "repoId",
|
||||
"columnName": "repoId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdate",
|
||||
"columnName": "lastUpdate",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "safe",
|
||||
"columnName": "safe",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "stats",
|
||||
"columnName": "stats",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"codename"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2abfd2dad332c887d96cdda63d92a639')"
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 1,
|
||||
"identityHash": "5a217dbf3caa5a6b70e7eee98636866c",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "ReposList",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `url` TEXT NOT NULL, `enabled` INTEGER NOT NULL, `donate` TEXT, `support` TEXT, `submitModule` TEXT, `lastUpdate` INTEGER NOT NULL, `name` TEXT NOT NULL, `website` TEXT, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "url",
|
||||
"columnName": "url",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "enabled",
|
||||
"columnName": "enabled",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "donate",
|
||||
"columnName": "donate",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "support",
|
||||
"columnName": "support",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "submitModule",
|
||||
"columnName": "submitModule",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdate",
|
||||
"columnName": "lastUpdate",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "website",
|
||||
"columnName": "website",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5a217dbf3caa5a6b70e7eee98636866c')"
|
||||
]
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -1,376 +1,430 @@
|
||||
/*
|
||||
* Copyright (c) 2023 to present Androidacy and contributors. Names, logos, icons, and the Androidacy name are all trademarks of Androidacy and may not be used without license. See LICENSE for more information.
|
||||
*/
|
||||
package com.fox2code.mmm.module
|
||||
|
||||
package com.fox2code.mmm.module;
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.DialogInterface
|
||||
import android.net.Uri
|
||||
import android.text.Spanned
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.fox2code.foxcompat.app.FoxActivity
|
||||
import com.fox2code.foxcompat.view.FoxDisplay
|
||||
import com.fox2code.mmm.MainApplication.Companion.INSTANCE
|
||||
import com.fox2code.mmm.MainApplication.Companion.isShowcaseMode
|
||||
import com.fox2code.mmm.R
|
||||
import com.fox2code.mmm.androidacy.AndroidacyUtil.Companion.isAndroidacyLink
|
||||
import com.fox2code.mmm.installer.InstallerInitializer.Companion.peekMagiskPath
|
||||
import com.fox2code.mmm.manager.ModuleInfo
|
||||
import com.fox2code.mmm.manager.ModuleManager.Companion.instance
|
||||
import com.fox2code.mmm.utils.ExternalHelper
|
||||
import com.fox2code.mmm.utils.IntentHelper.Companion.openConfig
|
||||
import com.fox2code.mmm.utils.IntentHelper.Companion.openCustomTab
|
||||
import com.fox2code.mmm.utils.IntentHelper.Companion.openInstaller
|
||||
import com.fox2code.mmm.utils.IntentHelper.Companion.openMarkdown
|
||||
import com.fox2code.mmm.utils.IntentHelper.Companion.openUrl
|
||||
import com.fox2code.mmm.utils.IntentHelper.Companion.openUrlAndroidacy
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import io.noties.markwon.Markwon
|
||||
import org.matomo.sdk.extra.TrackHelper
|
||||
import timber.log.Timber
|
||||
import java.util.Objects
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.text.Spanned;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.fox2code.foxcompat.app.FoxActivity;
|
||||
import com.fox2code.foxcompat.view.FoxDisplay;
|
||||
import com.fox2code.mmm.MainApplication;
|
||||
import com.fox2code.mmm.R;
|
||||
import com.fox2code.mmm.androidacy.AndroidacyUtil;
|
||||
import com.fox2code.mmm.installer.InstallerInitializer;
|
||||
import com.fox2code.mmm.manager.LocalModuleInfo;
|
||||
import com.fox2code.mmm.manager.ModuleInfo;
|
||||
import com.fox2code.mmm.manager.ModuleManager;
|
||||
import com.fox2code.mmm.utils.ExternalHelper;
|
||||
import com.fox2code.mmm.utils.IntentHelper;
|
||||
import com.google.android.material.chip.Chip;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import org.matomo.sdk.extra.TrackHelper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import io.noties.markwon.Markwon;
|
||||
import timber.log.Timber;
|
||||
|
||||
@SuppressWarnings("ReplaceNullCheck")
|
||||
@Suppress("SENSELESS_COMPARISON")
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
public enum ActionButtonType {
|
||||
INFO() {
|
||||
@Override
|
||||
public void update(Chip button, ModuleHolder moduleHolder) {
|
||||
button.setChipIcon(button.getContext().getDrawable(R.drawable.ic_baseline_info_24));
|
||||
button.setText(R.string.description);
|
||||
enum class ActionButtonType {
|
||||
INFO {
|
||||
override fun update(button: Chip, moduleHolder: ModuleHolder) {
|
||||
button.chipIcon = button.context.getDrawable(R.drawable.ic_baseline_info_24)
|
||||
button.setText(R.string.description)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAction(Chip button, ModuleHolder moduleHolder) {
|
||||
String name;
|
||||
if (moduleHolder.moduleInfo != null) {
|
||||
name = moduleHolder.moduleInfo.name;
|
||||
override fun doAction(button: Chip, moduleHolder: ModuleHolder) {
|
||||
val name: String? = if (moduleHolder.moduleInfo != null) {
|
||||
moduleHolder.moduleInfo!!.name
|
||||
} else {
|
||||
name = moduleHolder.repoModule.moduleInfo.name;
|
||||
moduleHolder.repoModule?.moduleInfo?.name
|
||||
}
|
||||
TrackHelper.track().event("view_notes", name).with(MainApplication.getINSTANCE().getTracker());
|
||||
String notesUrl = moduleHolder.repoModule.notesUrl;
|
||||
if (AndroidacyUtil.Companion.isAndroidacyLink(notesUrl)) {
|
||||
IntentHelper.openUrlAndroidacy(button.getContext(), notesUrl, false, moduleHolder.repoModule.moduleInfo.name, moduleHolder.getMainModuleConfig());
|
||||
TrackHelper.track().event("view_notes", name).with(INSTANCE!!.getTracker())
|
||||
val notesUrl = moduleHolder.repoModule?.notesUrl
|
||||
if (isAndroidacyLink(notesUrl)) {
|
||||
openUrlAndroidacy(
|
||||
button.context,
|
||||
notesUrl,
|
||||
false,
|
||||
moduleHolder.repoModule?.moduleInfo?.name,
|
||||
moduleHolder.mainModuleConfig
|
||||
)
|
||||
} else {
|
||||
IntentHelper.openMarkdown(button.getContext(), notesUrl, moduleHolder.repoModule.moduleInfo.name, moduleHolder.getMainModuleConfig(), moduleHolder.repoModule.moduleInfo.changeBoot, moduleHolder.repoModule.moduleInfo.needRamdisk, moduleHolder.repoModule.moduleInfo.minMagisk, moduleHolder.repoModule.moduleInfo.minApi, moduleHolder.repoModule.moduleInfo.maxApi);
|
||||
openMarkdown(
|
||||
button.context,
|
||||
notesUrl,
|
||||
moduleHolder.repoModule?.moduleInfo?.name,
|
||||
moduleHolder.mainModuleConfig,
|
||||
moduleHolder.repoModule?.moduleInfo?.changeBoot,
|
||||
moduleHolder.repoModule?.moduleInfo?.needRamdisk,
|
||||
moduleHolder.repoModule?.moduleInfo?.minMagisk ?: 0,
|
||||
moduleHolder.repoModule?.moduleInfo?.minApi ?: 0,
|
||||
moduleHolder.repoModule?.moduleInfo?.maxApi ?: 9999
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doActionLong(Chip button, ModuleHolder moduleHolder) {
|
||||
Context context = button.getContext();
|
||||
Toast.makeText(context, context.getString(R.string.module_id_prefix) + moduleHolder.moduleId, Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
override fun doActionLong(button: Chip, moduleHolder: ModuleHolder): Boolean {
|
||||
val context = button.context
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.module_id_prefix) + moduleHolder.moduleId,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
return true
|
||||
}
|
||||
}, UPDATE_INSTALL() {
|
||||
@Override
|
||||
public void update(Chip button, ModuleHolder moduleHolder) {
|
||||
int icon;
|
||||
},
|
||||
UPDATE_INSTALL {
|
||||
override fun update(button: Chip, moduleHolder: ModuleHolder) {
|
||||
val icon: Int
|
||||
if (moduleHolder.hasUpdate()) {
|
||||
icon = R.drawable.ic_baseline_update_24;
|
||||
button.setText(R.string.update);
|
||||
icon = R.drawable.ic_baseline_update_24
|
||||
button.setText(R.string.update)
|
||||
} else if (moduleHolder.moduleInfo != null) {
|
||||
icon = R.drawable.ic_baseline_refresh_24;
|
||||
button.setText(R.string.reinstall);
|
||||
icon = R.drawable.ic_baseline_refresh_24
|
||||
button.setText(R.string.reinstall)
|
||||
} else {
|
||||
icon = R.drawable.ic_baseline_system_update_24;
|
||||
button.setText(R.string.install);
|
||||
icon = R.drawable.ic_baseline_system_update_24
|
||||
button.setText(R.string.install)
|
||||
}
|
||||
button.setChipIcon(button.getContext().getDrawable(icon));
|
||||
button.chipIcon = button.context.getDrawable(icon)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAction(Chip button, ModuleHolder moduleHolder) {
|
||||
ModuleInfo moduleInfo = moduleHolder.getMainModuleInfo();
|
||||
if (moduleInfo == null) return;
|
||||
|
||||
String name;
|
||||
if (moduleHolder.moduleInfo != null) {
|
||||
name = moduleHolder.moduleInfo.name;
|
||||
override fun doAction(button: Chip, moduleHolder: ModuleHolder) {
|
||||
// if mainmoduleinfo is null, we are in repo mode
|
||||
val moduleInfo: ModuleInfo = if (moduleHolder.mainModuleInfo != null) {
|
||||
moduleHolder.mainModuleInfo
|
||||
} else {
|
||||
name = moduleHolder.repoModule.moduleInfo.name;
|
||||
moduleHolder.repoModule?.moduleInfo ?: return
|
||||
}
|
||||
TrackHelper.track().event("view_update_install", name).with(MainApplication.getINSTANCE().getTracker());
|
||||
val name: String? = if (moduleHolder.moduleInfo != null) {
|
||||
moduleHolder.moduleInfo!!.name
|
||||
} else {
|
||||
moduleHolder.repoModule?.moduleInfo?.name
|
||||
}
|
||||
TrackHelper.track().event("view_update_install", name).with(INSTANCE!!.getTracker())
|
||||
// if icon is reinstall, we need to uninstall first - warn the user but don't proceed
|
||||
if (moduleHolder.moduleInfo != null) {
|
||||
// get icon of the button
|
||||
Drawable icon = button.getChipIcon();
|
||||
if (icon != null && icon.getConstantState() != null) {
|
||||
Drawable reinstallIcon = button.getContext().getDrawable(R.drawable.ic_baseline_refresh_24);
|
||||
if (reinstallIcon != null && reinstallIcon.getConstantState() != null) {
|
||||
if (icon.getConstantState().equals(reinstallIcon.getConstantState())) {
|
||||
new MaterialAlertDialogBuilder(button.getContext())
|
||||
.setTitle(R.string.reinstall)
|
||||
.setMessage(R.string.reinstall_warning)
|
||||
.setPositiveButton(R.string.reinstall, null)
|
||||
.show();
|
||||
return;
|
||||
val icon = button.chipIcon
|
||||
if (icon != null && icon.constantState != null) {
|
||||
val reinstallIcon =
|
||||
button.context.getDrawable(R.drawable.ic_baseline_refresh_24)
|
||||
if (reinstallIcon != null && reinstallIcon.constantState != null) {
|
||||
if (icon.constantState == reinstallIcon.constantState) {
|
||||
MaterialAlertDialogBuilder(button.context)
|
||||
.setTitle(R.string.reinstall)
|
||||
.setMessage(R.string.reinstall_warning)
|
||||
.setPositiveButton(R.string.reinstall, null)
|
||||
.show()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String updateZipUrl = moduleHolder.getUpdateZipUrl();
|
||||
if (updateZipUrl == null) return;
|
||||
val updateZipUrl = moduleHolder.updateZipUrl ?: return
|
||||
// Androidacy manage the selection between download and install
|
||||
if (AndroidacyUtil.Companion.isAndroidacyLink(updateZipUrl)) {
|
||||
IntentHelper.openUrlAndroidacy(button.getContext(), updateZipUrl, true, moduleInfo.name, moduleInfo.config);
|
||||
return;
|
||||
if (isAndroidacyLink(updateZipUrl)) {
|
||||
openUrlAndroidacy(
|
||||
button.context,
|
||||
updateZipUrl,
|
||||
true,
|
||||
moduleInfo.name,
|
||||
moduleInfo.config
|
||||
)
|
||||
return
|
||||
}
|
||||
boolean hasRoot = InstallerInitializer.peekMagiskPath() != null && !MainApplication.Companion.isShowcaseMode();
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(button.getContext());
|
||||
builder.setTitle(moduleInfo.name).setCancelable(true).setIcon(R.drawable.ic_baseline_extension_24);
|
||||
CharSequence desc = moduleInfo.description;
|
||||
Markwon markwon = null;
|
||||
LocalModuleInfo localModuleInfo = moduleHolder.moduleInfo;
|
||||
if (localModuleInfo != null && !localModuleInfo.updateChangeLog.isEmpty()) {
|
||||
markwon = MainApplication.getINSTANCE().getMarkwon();
|
||||
val hasRoot = peekMagiskPath() != null && !isShowcaseMode
|
||||
val builder = MaterialAlertDialogBuilder(button.context)
|
||||
builder.setTitle(moduleInfo.name).setCancelable(true)
|
||||
.setIcon(R.drawable.ic_baseline_extension_24)
|
||||
var desc: CharSequence? = moduleInfo.description
|
||||
var markwon: Markwon? = null
|
||||
val localModuleInfo = moduleHolder.moduleInfo
|
||||
if (localModuleInfo != null && localModuleInfo.updateChangeLog.isNotEmpty()) {
|
||||
markwon = INSTANCE!!.getMarkwon()
|
||||
// Re-render each time in cse of config changes
|
||||
desc = markwon.toMarkdown(localModuleInfo.updateChangeLog);
|
||||
desc = markwon!!.toMarkdown(localModuleInfo.updateChangeLog)
|
||||
}
|
||||
|
||||
if (desc == null || desc.length() == 0) {
|
||||
builder.setMessage(R.string.no_desc_found);
|
||||
if (desc.isNullOrEmpty()) {
|
||||
builder.setMessage(R.string.no_desc_found)
|
||||
} else {
|
||||
builder.setMessage(desc);
|
||||
builder.setMessage(desc)
|
||||
}
|
||||
Timber.i("URL: %s", updateZipUrl)
|
||||
builder.setNegativeButton(R.string.download_module) { _: DialogInterface?, _: Int ->
|
||||
openCustomTab(
|
||||
button.context,
|
||||
updateZipUrl
|
||||
)
|
||||
}
|
||||
Timber.i("URL: %s", updateZipUrl);
|
||||
builder.setNegativeButton(R.string.download_module, (x, y) -> IntentHelper.openCustomTab(button.getContext(), updateZipUrl));
|
||||
if (hasRoot) {
|
||||
builder.setPositiveButton(moduleHolder.hasUpdate() ? R.string.update_module : R.string.install_module, (x, y) -> {
|
||||
String updateZipChecksum = moduleHolder.getUpdateZipChecksum();
|
||||
IntentHelper.openInstaller(button.getContext(), updateZipUrl, moduleInfo.name, moduleInfo.config, updateZipChecksum, moduleInfo.mmtReborn);
|
||||
});
|
||||
builder.setPositiveButton(if (moduleHolder.hasUpdate()) R.string.update_module else R.string.install_module) { _: DialogInterface?, _: Int ->
|
||||
val updateZipChecksum = moduleHolder.updateZipChecksum
|
||||
openInstaller(
|
||||
button.context,
|
||||
updateZipUrl,
|
||||
moduleInfo.name,
|
||||
moduleInfo.config,
|
||||
updateZipChecksum,
|
||||
moduleInfo.mmtReborn
|
||||
)
|
||||
}
|
||||
}
|
||||
ExternalHelper.INSTANCE.injectButton(builder, () -> Uri.parse(updateZipUrl), moduleHolder.getUpdateZipRepo());
|
||||
int dim5dp = FoxDisplay.dpToPixel(5);
|
||||
builder.setBackgroundInsetStart(dim5dp).setBackgroundInsetEnd(dim5dp);
|
||||
AlertDialog alertDialog = builder.show();
|
||||
for (int i = -3; i < 0; i++) {
|
||||
Button alertButton = alertDialog.getButton(i);
|
||||
if (alertButton != null && alertButton.getPaddingStart() > dim5dp) {
|
||||
alertButton.setPadding(dim5dp, dim5dp, dim5dp, dim5dp);
|
||||
ExternalHelper.INSTANCE.injectButton(
|
||||
builder,
|
||||
{ Uri.parse(updateZipUrl) },
|
||||
moduleHolder.updateZipRepo
|
||||
)
|
||||
val dim5dp = FoxDisplay.dpToPixel(5f)
|
||||
builder.setBackgroundInsetStart(dim5dp).setBackgroundInsetEnd(dim5dp)
|
||||
val alertDialog = builder.show()
|
||||
for (i in -3..-1) {
|
||||
val alertButton = alertDialog.getButton(i)
|
||||
if (alertButton != null && alertButton.paddingStart > dim5dp) {
|
||||
alertButton.setPadding(dim5dp, dim5dp, dim5dp, dim5dp)
|
||||
}
|
||||
}
|
||||
if (markwon != null) {
|
||||
TextView messageView = Objects.requireNonNull(alertDialog.getWindow()).findViewById(android.R.id.message);
|
||||
markwon.setParsedMarkdown(messageView, (Spanned) desc);
|
||||
val messageView = alertDialog.window!!.findViewById<TextView>(android.R.id.message)
|
||||
markwon.setParsedMarkdown(messageView, (desc as Spanned?)!!)
|
||||
}
|
||||
}
|
||||
}, UNINSTALL() {
|
||||
@Override
|
||||
public void update(Chip button, ModuleHolder moduleHolder) {
|
||||
int icon = moduleHolder.hasFlag(ModuleInfo.FLAG_MODULE_UNINSTALLING) ? R.drawable.ic_baseline_delete_outline_24 : (!moduleHolder.hasFlag(ModuleInfo.FLAG_MODULE_UPDATING) || moduleHolder.hasFlag(ModuleInfo.FLAGS_MODULE_ACTIVE)) ? R.drawable.ic_baseline_delete_24 : R.drawable.ic_baseline_delete_forever_24;
|
||||
button.setChipIcon(button.getContext().getDrawable(icon));
|
||||
button.setText(R.string.uninstall);
|
||||
},
|
||||
UNINSTALL {
|
||||
override fun update(button: Chip, moduleHolder: ModuleHolder) {
|
||||
val icon =
|
||||
if (moduleHolder.hasFlag(ModuleInfo.FLAG_MODULE_UNINSTALLING)) R.drawable.ic_baseline_delete_outline_24 else if (!moduleHolder.hasFlag(
|
||||
ModuleInfo.FLAG_MODULE_UPDATING
|
||||
) || moduleHolder.hasFlag(ModuleInfo.FLAGS_MODULE_ACTIVE)
|
||||
) R.drawable.ic_baseline_delete_24 else R.drawable.ic_baseline_delete_forever_24
|
||||
button.chipIcon = button.context.getDrawable(icon)
|
||||
button.setText(R.string.uninstall)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAction(Chip button, ModuleHolder moduleHolder) {
|
||||
if (!moduleHolder.hasFlag(ModuleInfo.FLAGS_MODULE_ACTIVE | ModuleInfo.FLAG_MODULE_UNINSTALLING) && moduleHolder.hasFlag(ModuleInfo.FLAG_MODULE_UPDATING)) {
|
||||
doActionLong(button, moduleHolder);
|
||||
return;
|
||||
override fun doAction(button: Chip, moduleHolder: ModuleHolder) {
|
||||
if (!moduleHolder.hasFlag(ModuleInfo.FLAGS_MODULE_ACTIVE or ModuleInfo.FLAG_MODULE_UNINSTALLING) && moduleHolder.hasFlag(
|
||||
ModuleInfo.FLAG_MODULE_UPDATING
|
||||
)
|
||||
) {
|
||||
doActionLong(button, moduleHolder)
|
||||
return
|
||||
}
|
||||
String name;
|
||||
if (moduleHolder.moduleInfo != null) {
|
||||
name = moduleHolder.moduleInfo.name;
|
||||
val name: String? = if (moduleHolder.moduleInfo != null) {
|
||||
moduleHolder.moduleInfo!!.name
|
||||
} else {
|
||||
name = moduleHolder.repoModule.moduleInfo.name;
|
||||
moduleHolder.repoModule?.moduleInfo?.name
|
||||
}
|
||||
TrackHelper.track().event("uninstall_module", name).with(MainApplication.getINSTANCE().getTracker());
|
||||
Timber.i(Integer.toHexString(moduleHolder.moduleInfo.flags));
|
||||
if (!Objects.requireNonNull(ModuleManager.getInstance()).setUninstallState(moduleHolder.moduleInfo, !moduleHolder.hasFlag(ModuleInfo.FLAG_MODULE_UNINSTALLING))) {
|
||||
Timber.e("Failed to switch uninstalled state!");
|
||||
TrackHelper.track().event("uninstall_module", name).with(INSTANCE!!.getTracker())
|
||||
Timber.i(Integer.toHexString(moduleHolder.moduleInfo?.flags ?: 0))
|
||||
if (!instance!!.setUninstallState(
|
||||
moduleHolder.moduleInfo!!, !moduleHolder.hasFlag(
|
||||
ModuleInfo.FLAG_MODULE_UNINSTALLING
|
||||
)
|
||||
)
|
||||
) {
|
||||
Timber.e("Failed to switch uninstalled state!")
|
||||
}
|
||||
update(button, moduleHolder);
|
||||
update(button, moduleHolder)
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doActionLong(Chip button, ModuleHolder moduleHolder) {
|
||||
override fun doActionLong(button: Chip, moduleHolder: ModuleHolder): Boolean {
|
||||
if (moduleHolder.moduleInfo == null) {
|
||||
return false
|
||||
}
|
||||
// Actually a module having mount is the only issue when deleting module
|
||||
if (moduleHolder.moduleInfo.hasFlag(ModuleInfo.FLAG_MODULE_HAS_ACTIVE_MOUNT))
|
||||
return false; // We can't trust active flag on first boot
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(button.getContext());
|
||||
builder.setTitle(R.string.master_delete);
|
||||
builder.setPositiveButton(R.string.master_delete_yes, (dialog, which) -> {
|
||||
String moduleId = moduleHolder.moduleInfo.id;
|
||||
if (!Objects.requireNonNull(ModuleManager.getInstance()).masterClear(moduleHolder.moduleInfo)) {
|
||||
Toast.makeText(button.getContext(), R.string.master_delete_fail, Toast.LENGTH_SHORT).show();
|
||||
if (moduleHolder.moduleInfo!!.hasFlag(ModuleInfo.FLAG_MODULE_HAS_ACTIVE_MOUNT)) return false // We can't trust active flag on first boot
|
||||
val builder = MaterialAlertDialogBuilder(button.context)
|
||||
builder.setTitle(R.string.master_delete)
|
||||
builder.setPositiveButton(R.string.master_delete_yes) { _: DialogInterface?, _: Int ->
|
||||
val moduleId = moduleHolder.moduleInfo!!.id
|
||||
if (!instance!!.masterClear(moduleHolder.moduleInfo!!)) {
|
||||
Toast.makeText(button.context, R.string.master_delete_fail, Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
} else {
|
||||
moduleHolder.moduleInfo = null;
|
||||
FoxActivity.getFoxActivity(button).refreshUI();
|
||||
Timber.e("Cleared: %s", moduleId);
|
||||
moduleHolder.moduleInfo = null
|
||||
FoxActivity.getFoxActivity(button).refreshUI()
|
||||
Timber.e("Cleared: %s", moduleId)
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.master_delete_no, (v, i) -> {
|
||||
});
|
||||
builder.create();
|
||||
builder.show();
|
||||
return true;
|
||||
}
|
||||
builder.setNegativeButton(R.string.master_delete_no) { _: DialogInterface?, _: Int -> }
|
||||
builder.create()
|
||||
builder.show()
|
||||
return true
|
||||
}
|
||||
}, CONFIG() {
|
||||
@Override
|
||||
public void update(Chip button, ModuleHolder moduleHolder) {
|
||||
button.setChipIcon(button.getContext().getDrawable(R.drawable.ic_baseline_app_settings_alt_24));
|
||||
button.setText(R.string.config);
|
||||
},
|
||||
CONFIG {
|
||||
override fun update(button: Chip, moduleHolder: ModuleHolder) {
|
||||
button.chipIcon =
|
||||
button.context.getDrawable(R.drawable.ic_baseline_app_settings_alt_24)
|
||||
button.setText(R.string.config)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAction(Chip button, ModuleHolder moduleHolder) {
|
||||
String config = moduleHolder.getMainModuleConfig();
|
||||
if (config == null) return;
|
||||
|
||||
String name;
|
||||
if (moduleHolder.moduleInfo != null) {
|
||||
name = moduleHolder.moduleInfo.name;
|
||||
override fun doAction(button: Chip, moduleHolder: ModuleHolder) {
|
||||
if (moduleHolder.moduleInfo == null) {
|
||||
return
|
||||
}
|
||||
val config = moduleHolder.mainModuleConfig ?: return
|
||||
val name: String? = if (moduleHolder.moduleInfo != null) {
|
||||
moduleHolder.moduleInfo!!.name
|
||||
} else {
|
||||
name = moduleHolder.repoModule.moduleInfo.name;
|
||||
moduleHolder.repoModule?.moduleInfo?.name
|
||||
}
|
||||
TrackHelper.track().event("config_module", name).with(MainApplication.getINSTANCE().getTracker());
|
||||
if (AndroidacyUtil.Companion.isAndroidacyLink(config)) {
|
||||
IntentHelper.openUrlAndroidacy(button.getContext(), config, true);
|
||||
TrackHelper.track().event("config_module", name).with(INSTANCE!!.getTracker())
|
||||
if (isAndroidacyLink(config)) {
|
||||
openUrlAndroidacy(button.context, config, true)
|
||||
} else {
|
||||
IntentHelper.openConfig(button.getContext(), config);
|
||||
openConfig(button.context, config)
|
||||
}
|
||||
}
|
||||
}, SUPPORT() {
|
||||
@Override
|
||||
public void update(Chip button, ModuleHolder moduleHolder) {
|
||||
ModuleInfo moduleInfo = moduleHolder.getMainModuleInfo();
|
||||
button.setChipIcon(button.getContext().getDrawable(supportIconForUrl(moduleInfo.support)));
|
||||
button.setText(R.string.support);
|
||||
},
|
||||
SUPPORT {
|
||||
override fun update(button: Chip, moduleHolder: ModuleHolder) {
|
||||
val moduleInfo = moduleHolder.mainModuleInfo
|
||||
button.chipIcon = button.context.getDrawable(
|
||||
supportIconForUrl(moduleInfo.support)
|
||||
)
|
||||
button.setText(R.string.support)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAction(Chip button, ModuleHolder moduleHolder) {
|
||||
|
||||
String name;
|
||||
if (moduleHolder.moduleInfo != null) {
|
||||
name = moduleHolder.moduleInfo.name;
|
||||
override fun doAction(button: Chip, moduleHolder: ModuleHolder) {
|
||||
val name: String? = if (moduleHolder.moduleInfo != null) {
|
||||
moduleHolder.moduleInfo!!.name
|
||||
} else {
|
||||
name = moduleHolder.repoModule.moduleInfo.name;
|
||||
moduleHolder.repoModule?.moduleInfo?.name
|
||||
}
|
||||
TrackHelper.track().event("support_module", name).with(MainApplication.getINSTANCE().getTracker());
|
||||
IntentHelper.Companion.openUrl(button.getContext(), Objects.requireNonNull(moduleHolder.getMainModuleInfo().support));
|
||||
TrackHelper.track().event("support_module", name).with(INSTANCE!!.getTracker())
|
||||
openUrl(button.context, Objects.requireNonNull(moduleHolder.mainModuleInfo.support))
|
||||
}
|
||||
}, DONATE() {
|
||||
@Override
|
||||
public void update(Chip button, ModuleHolder moduleHolder) {
|
||||
ModuleInfo moduleInfo = moduleHolder.getMainModuleInfo();
|
||||
button.setChipIcon(button.getContext().getDrawable(donateIconForUrl(moduleInfo.donate)));
|
||||
button.setText(R.string.donate);
|
||||
},
|
||||
DONATE {
|
||||
override fun update(button: Chip, moduleHolder: ModuleHolder) {
|
||||
val moduleInfo = moduleHolder.mainModuleInfo
|
||||
button.chipIcon = button.context.getDrawable(
|
||||
donateIconForUrl(moduleInfo.donate)
|
||||
)
|
||||
button.setText(R.string.donate)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAction(Chip button, ModuleHolder moduleHolder) {
|
||||
String name;
|
||||
if (moduleHolder.moduleInfo != null) {
|
||||
name = moduleHolder.moduleInfo.name;
|
||||
override fun doAction(button: Chip, moduleHolder: ModuleHolder) {
|
||||
val name: String? = if (moduleHolder.moduleInfo != null) {
|
||||
moduleHolder.moduleInfo!!.name
|
||||
} else {
|
||||
name = moduleHolder.repoModule.moduleInfo.name;
|
||||
moduleHolder.repoModule?.moduleInfo?.name
|
||||
}
|
||||
TrackHelper.track().event("donate_module", name).with(MainApplication.getINSTANCE().getTracker());
|
||||
IntentHelper.Companion.openUrl(button.getContext(), moduleHolder.getMainModuleInfo().donate);
|
||||
TrackHelper.track().event("donate_module", name).with(INSTANCE!!.getTracker())
|
||||
openUrl(button.context, moduleHolder.mainModuleInfo.donate)
|
||||
}
|
||||
}, WARNING() {
|
||||
@Override
|
||||
public void update(Chip button, ModuleHolder moduleHolder) {
|
||||
button.setChipIcon(button.getContext().getDrawable(R.drawable.ic_baseline_warning_24));
|
||||
button.setText(R.string.warning);
|
||||
},
|
||||
WARNING {
|
||||
override fun update(button: Chip, moduleHolder: ModuleHolder) {
|
||||
button.chipIcon = button.context.getDrawable(R.drawable.ic_baseline_warning_24)
|
||||
button.setText(R.string.warning)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAction(Chip button, ModuleHolder moduleHolder) {
|
||||
String name;
|
||||
if (moduleHolder.moduleInfo != null) {
|
||||
name = moduleHolder.moduleInfo.name;
|
||||
override fun doAction(button: Chip, moduleHolder: ModuleHolder) {
|
||||
val name: String? = if (moduleHolder.moduleInfo != null) {
|
||||
moduleHolder.moduleInfo!!.name
|
||||
} else {
|
||||
name = moduleHolder.repoModule.moduleInfo.name;
|
||||
moduleHolder.repoModule?.moduleInfo?.name
|
||||
}
|
||||
TrackHelper.track().event("warning_module", name).with(MainApplication.getINSTANCE().getTracker());
|
||||
new MaterialAlertDialogBuilder(button.getContext()).setTitle(R.string.warning).setMessage(R.string.warning_message).setPositiveButton(R.string.understand, (v, i) -> {
|
||||
}).create().show();
|
||||
TrackHelper.track().event("warning_module", name).with(INSTANCE!!.getTracker())
|
||||
MaterialAlertDialogBuilder(button.context).setTitle(R.string.warning)
|
||||
.setMessage(R.string.warning_message).setPositiveButton(
|
||||
R.string.understand
|
||||
) { _: DialogInterface?, _: Int -> }
|
||||
.create().show()
|
||||
}
|
||||
}, SAFE() {
|
||||
},
|
||||
SAFE {
|
||||
// SAFE is for modules that the api says are clean. only supported by androidacy currently
|
||||
@Override
|
||||
public void update(Chip button, ModuleHolder moduleHolder) {
|
||||
button.setChipIcon(button.getContext().getDrawable(R.drawable.baseline_verified_user_24));
|
||||
button.setText(R.string.safe);
|
||||
override fun update(button: Chip, moduleHolder: ModuleHolder) {
|
||||
button.chipIcon =
|
||||
button.context.getDrawable(R.drawable.baseline_verified_user_24)
|
||||
button.setText(R.string.safe)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAction(Chip button, ModuleHolder moduleHolder) {
|
||||
String name;
|
||||
if (moduleHolder.moduleInfo != null) {
|
||||
name = moduleHolder.moduleInfo.name;
|
||||
override fun doAction(button: Chip, moduleHolder: ModuleHolder) {
|
||||
val name: String? = if (moduleHolder.moduleInfo != null) {
|
||||
moduleHolder.moduleInfo!!.name
|
||||
} else {
|
||||
name = moduleHolder.repoModule.moduleInfo.name;
|
||||
moduleHolder.repoModule?.moduleInfo?.name
|
||||
}
|
||||
TrackHelper.track().event("safe_module", name).with(MainApplication.getINSTANCE().getTracker());
|
||||
new MaterialAlertDialogBuilder(button.getContext()).setTitle(R.string.safe_module).setMessage(R.string.safe_message).setPositiveButton(R.string.understand, (v, i) -> {
|
||||
}).create().show();
|
||||
TrackHelper.track().event("safe_module", name).with(INSTANCE!!.getTracker())
|
||||
MaterialAlertDialogBuilder(button.context).setTitle(R.string.safe_module)
|
||||
.setMessage(R.string.safe_message).setPositiveButton(
|
||||
R.string.understand
|
||||
) { _: DialogInterface?, _: Int -> }
|
||||
.create().show()
|
||||
}
|
||||
};
|
||||
|
||||
@DrawableRes
|
||||
private final int iconId;
|
||||
private val iconId: Int
|
||||
|
||||
ActionButtonType() {
|
||||
this.iconId = 0;
|
||||
constructor() {
|
||||
iconId = 0
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
ActionButtonType(int iconId) {
|
||||
this.iconId = iconId;
|
||||
@Suppress("unused")
|
||||
constructor(iconId: Int) {
|
||||
this.iconId = iconId
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public static int supportIconForUrl(String url) {
|
||||
int icon = R.drawable.ic_baseline_support_24;
|
||||
if (url == null) {
|
||||
return icon;
|
||||
} else if (url.startsWith("https://t.me/")) {
|
||||
icon = R.drawable.ic_baseline_telegram_24;
|
||||
} else if (url.startsWith("https://discord.gg/") || url.startsWith("https://discord.com/invite/")) {
|
||||
icon = R.drawable.ic_baseline_discord_24;
|
||||
} else if (url.startsWith("https://github.com/")) {
|
||||
icon = R.drawable.ic_github;
|
||||
} else if (url.startsWith("https://gitlab.com/")) {
|
||||
icon = R.drawable.ic_gitlab;
|
||||
} else if (url.startsWith("https://forum.xda-developers.com/")) {
|
||||
icon = R.drawable.ic_xda;
|
||||
}
|
||||
return icon;
|
||||
open fun update(button: Chip, moduleHolder: ModuleHolder) {
|
||||
button.chipIcon = button.context.getDrawable(iconId)
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public static int donateIconForUrl(String url) {
|
||||
int icon = R.drawable.ic_baseline_monetization_on_24;
|
||||
if (url == null) {
|
||||
return icon;
|
||||
} else if (url.startsWith("https://www.paypal.me/") || url.startsWith("https://www.paypal.com/paypalme/") || url.startsWith("https://www.paypal.com/donate/")) {
|
||||
icon = R.drawable.ic_baseline_paypal_24;
|
||||
} else if (url.startsWith("https://patreon.com/") || url.startsWith("https://www.patreon.com/")) {
|
||||
icon = R.drawable.ic_patreon;
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void update(Chip button, ModuleHolder moduleHolder) {
|
||||
button.setChipIcon(button.getContext().getDrawable(this.iconId));
|
||||
abstract fun doAction(button: Chip, moduleHolder: ModuleHolder)
|
||||
open fun doActionLong(button: Chip, moduleHolder: ModuleHolder): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
public abstract void doAction(Chip button, ModuleHolder moduleHolder);
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@DrawableRes
|
||||
fun supportIconForUrl(url: String?): Int {
|
||||
var icon = R.drawable.ic_baseline_support_24
|
||||
if (url == null) {
|
||||
return icon
|
||||
} else if (url.startsWith("https://t.me/")) {
|
||||
icon = R.drawable.ic_baseline_telegram_24
|
||||
} else if (url.startsWith("https://discord.gg/") || url.startsWith("https://discord.com/invite/")) {
|
||||
icon = R.drawable.ic_baseline_discord_24
|
||||
} else if (url.startsWith("https://github.com/")) {
|
||||
icon = R.drawable.ic_github
|
||||
} else if (url.startsWith("https://gitlab.com/")) {
|
||||
icon = R.drawable.ic_gitlab
|
||||
} else if (url.startsWith("https://forum.xda-developers.com/")) {
|
||||
icon = R.drawable.ic_xda
|
||||
}
|
||||
return icon
|
||||
}
|
||||
|
||||
public boolean doActionLong(Chip button, ModuleHolder moduleHolder) {
|
||||
return false;
|
||||
@JvmStatic
|
||||
@DrawableRes
|
||||
fun donateIconForUrl(url: String?): Int {
|
||||
var icon = R.drawable.ic_baseline_monetization_on_24
|
||||
if (url == null) {
|
||||
return icon
|
||||
} else if (url.startsWith("https://www.paypal.me/") || url.startsWith("https://www.paypal.com/paypalme/") || url.startsWith(
|
||||
"https://www.paypal.com/donate/"
|
||||
)
|
||||
) {
|
||||
icon = R.drawable.ic_baseline_paypal_24
|
||||
} else if (url.startsWith("https://patreon.com/") || url.startsWith("https://www.patreon.com/")) {
|
||||
icon = R.drawable.ic_patreon
|
||||
}
|
||||
return icon
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,374 +1,420 @@
|
||||
/*
|
||||
* Copyright (c) 2023 to present Androidacy and contributors. Names, logos, icons, and the Androidacy name are all trademarks of Androidacy and may not be used without license. See LICENSE for more information.
|
||||
*/
|
||||
|
||||
package com.fox2code.mmm.module;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import com.fox2code.mmm.MainApplication;
|
||||
import com.fox2code.mmm.NotificationType;
|
||||
import com.fox2code.mmm.R;
|
||||
import com.fox2code.mmm.XHooks;
|
||||
import com.fox2code.mmm.manager.LocalModuleInfo;
|
||||
import com.fox2code.mmm.manager.ModuleInfo;
|
||||
import com.fox2code.mmm.repo.RepoModule;
|
||||
import com.fox2code.mmm.utils.IntentHelper;
|
||||
import com.fox2code.mmm.utils.io.PropUtils;
|
||||
import com.fox2code.mmm.utils.io.net.Http;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
public final class ModuleHolder implements Comparable<ModuleHolder> {
|
||||
|
||||
public final String moduleId;
|
||||
public final NotificationType notificationType;
|
||||
public final Type separator;
|
||||
public int footerPx;
|
||||
public View.OnClickListener onClickListener;
|
||||
|
||||
public LocalModuleInfo moduleInfo;
|
||||
public RepoModule repoModule;
|
||||
public int filterLevel;
|
||||
|
||||
public ModuleHolder(String moduleId) {
|
||||
this.moduleId = Objects.requireNonNull(moduleId);
|
||||
this.notificationType = null;
|
||||
this.separator = null;
|
||||
this.footerPx = -1;
|
||||
}
|
||||
|
||||
public ModuleHolder(NotificationType notificationType) {
|
||||
this.moduleId = "";
|
||||
this.notificationType = Objects.requireNonNull(notificationType);
|
||||
this.separator = null;
|
||||
this.footerPx = -1;
|
||||
}
|
||||
|
||||
public ModuleHolder(Type separator) {
|
||||
this.moduleId = "";
|
||||
this.notificationType = null;
|
||||
this.separator = separator;
|
||||
this.footerPx = -1;
|
||||
package com.fox2code.mmm.module
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.view.View
|
||||
import androidx.annotation.StringRes
|
||||
import com.fox2code.mmm.MainApplication.Companion.INSTANCE
|
||||
import com.fox2code.mmm.MainApplication.Companion.formatTime
|
||||
import com.fox2code.mmm.MainApplication.Companion.getSharedPreferences
|
||||
import com.fox2code.mmm.MainApplication.Companion.isDisableLowQualityModuleFilter
|
||||
import com.fox2code.mmm.NotificationType
|
||||
import com.fox2code.mmm.R
|
||||
import com.fox2code.mmm.XHooks.Companion.checkConfigTargetExists
|
||||
import com.fox2code.mmm.manager.LocalModuleInfo
|
||||
import com.fox2code.mmm.manager.ModuleInfo
|
||||
import com.fox2code.mmm.repo.RepoModule
|
||||
import com.fox2code.mmm.utils.IntentHelper.Companion.getPackageOfConfig
|
||||
import com.fox2code.mmm.utils.io.PropUtils.Companion.isLowQualityModule
|
||||
import com.fox2code.mmm.utils.io.net.Http.Companion.hasWebView
|
||||
import timber.log.Timber
|
||||
import java.util.Objects
|
||||
|
||||
@Suppress("unused", "KotlinConstantConditions")
|
||||
class ModuleHolder : Comparable<ModuleHolder?> {
|
||||
val moduleId: String
|
||||
val notificationType: NotificationType?
|
||||
val separator: Type?
|
||||
var footerPx: Int
|
||||
var onClickListener: View.OnClickListener? = null
|
||||
var moduleInfo: LocalModuleInfo? = null
|
||||
var repoModule: RepoModule? = null
|
||||
var filterLevel = 0
|
||||
|
||||
constructor(moduleId: String) {
|
||||
this.moduleId = Objects.requireNonNull(moduleId)
|
||||
notificationType = null
|
||||
separator = null
|
||||
footerPx = -1
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public ModuleHolder(int footerPx, boolean header) {
|
||||
this.moduleId = "";
|
||||
this.notificationType = null;
|
||||
this.separator = null;
|
||||
this.footerPx = footerPx;
|
||||
this.filterLevel = header ? 1 : 0;
|
||||
constructor(notificationType: NotificationType) {
|
||||
moduleId = ""
|
||||
this.notificationType = Objects.requireNonNull(notificationType)
|
||||
separator = null
|
||||
footerPx = -1
|
||||
}
|
||||
|
||||
public boolean isModuleHolder() {
|
||||
return this.notificationType == null && this.separator == null && this.footerPx == -1;
|
||||
constructor(separator: Type?) {
|
||||
moduleId = ""
|
||||
notificationType = null
|
||||
this.separator = separator
|
||||
footerPx = -1
|
||||
}
|
||||
|
||||
public ModuleInfo getMainModuleInfo() {
|
||||
return this.repoModule != null && (this.moduleInfo == null || this.moduleInfo.versionCode < this.repoModule.moduleInfo.versionCode) ? this.repoModule.moduleInfo : this.moduleInfo;
|
||||
@Suppress("unused")
|
||||
constructor(footerPx: Int, header: Boolean) {
|
||||
moduleId = ""
|
||||
notificationType = null
|
||||
separator = null
|
||||
this.footerPx = footerPx
|
||||
filterLevel = if (header) 1 else 0
|
||||
}
|
||||
|
||||
public String getUpdateZipUrl() {
|
||||
return this.moduleInfo == null || (this.repoModule != null && this.moduleInfo.updateVersionCode < this.repoModule.moduleInfo.versionCode) ? this.repoModule.zipUrl : this.moduleInfo.updateZipUrl;
|
||||
}
|
||||
|
||||
public String getUpdateZipRepo() {
|
||||
return this.moduleInfo == null || (this.repoModule != null && this.moduleInfo.updateVersionCode < this.repoModule.moduleInfo.versionCode) ? this.repoModule.repoData.preferenceId : "update_json";
|
||||
}
|
||||
|
||||
public String getUpdateZipChecksum() {
|
||||
return this.moduleInfo == null || (this.repoModule != null && this.moduleInfo.updateVersionCode < this.repoModule.moduleInfo.versionCode) ? this.repoModule.checksum : this.moduleInfo.updateChecksum;
|
||||
}
|
||||
|
||||
public String getMainModuleName() {
|
||||
ModuleInfo moduleInfo = this.getMainModuleInfo();
|
||||
if (moduleInfo == null || moduleInfo.name == null)
|
||||
throw new Error("Error for " + this.getType().name() + " id " + this.moduleId);
|
||||
return moduleInfo.name;
|
||||
}
|
||||
|
||||
public String getMainModuleNameLowercase() {
|
||||
return this.getMainModuleName().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public String getMainModuleConfig() {
|
||||
if (this.moduleInfo == null) return null;
|
||||
String config = this.moduleInfo.config;
|
||||
if (config == null && this.repoModule != null) {
|
||||
config = this.repoModule.moduleInfo.config;
|
||||
val isModuleHolder: Boolean
|
||||
get() = notificationType == null && separator == null && footerPx == -1
|
||||
val mainModuleInfo: ModuleInfo
|
||||
get() = if (repoModule != null && (moduleInfo == null || moduleInfo!!.versionCode < repoModule!!.moduleInfo.versionCode)) repoModule!!.moduleInfo else moduleInfo!!
|
||||
val updateZipUrl: String?
|
||||
get() = if (moduleInfo == null || repoModule != null && moduleInfo!!.updateVersionCode < repoModule!!.moduleInfo.versionCode) repoModule!!.zipUrl else moduleInfo!!.updateZipUrl
|
||||
val updateZipRepo: String?
|
||||
get() = if (moduleInfo == null || repoModule != null && moduleInfo!!.updateVersionCode < repoModule!!.moduleInfo.versionCode) repoModule!!.repoData.preferenceId else "update_json"
|
||||
val updateZipChecksum: String?
|
||||
get() = if (moduleInfo == null || repoModule != null && moduleInfo!!.updateVersionCode < repoModule!!.moduleInfo.versionCode) repoModule!!.checksum else moduleInfo!!.updateChecksum
|
||||
val mainModuleName: String?
|
||||
get() {
|
||||
val moduleInfo = mainModuleInfo
|
||||
if (moduleInfo.name == null) throw Error("Error for " + type.name + " id " + moduleId)
|
||||
return moduleInfo.name
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
public String getUpdateTimeText() {
|
||||
if (this.repoModule == null) return "";
|
||||
long timeStamp = this.repoModule.lastUpdated;
|
||||
return timeStamp <= 0 ? "" : MainApplication.formatTime(timeStamp);
|
||||
}
|
||||
|
||||
public String getRepoName() {
|
||||
if (this.repoModule == null) return "";
|
||||
return this.repoModule.repoName;
|
||||
}
|
||||
val mainModuleNameLowercase: String
|
||||
get() = mainModuleName!!.lowercase()
|
||||
val mainModuleConfig: String?
|
||||
get() {
|
||||
if (moduleInfo == null) return null
|
||||
var config = moduleInfo!!.config
|
||||
if (config == null && repoModule != null) {
|
||||
config = repoModule!!.moduleInfo.config
|
||||
}
|
||||
return config
|
||||
}
|
||||
val updateTimeText: String
|
||||
get() {
|
||||
if (repoModule == null) return ""
|
||||
val timeStamp = repoModule!!.lastUpdated
|
||||
return if (timeStamp <= 0) "" else formatTime(timeStamp)
|
||||
}
|
||||
val repoName: String?
|
||||
get() = if (repoModule == null) "" else repoModule!!.repoName
|
||||
|
||||
public boolean hasFlag(int flag) {
|
||||
return this.moduleInfo != null && this.moduleInfo.hasFlag(flag);
|
||||
fun hasFlag(flag: Int): Boolean {
|
||||
return moduleInfo != null && moduleInfo!!.hasFlag(flag)
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
if (this.footerPx != -1) {
|
||||
Timber.i("Module %s is footer", this.moduleId);
|
||||
return Type.FOOTER;
|
||||
} else if (this.separator != null) {
|
||||
Timber.i("Module %s is separator", this.moduleId);
|
||||
return Type.SEPARATOR;
|
||||
} else if (this.notificationType != null) {
|
||||
Timber.i("Module %s is notification", this.moduleId);
|
||||
return Type.NOTIFICATION;
|
||||
} else if (this.moduleInfo == null) {
|
||||
return Type.INSTALLABLE;
|
||||
} else if (this.moduleInfo.versionCode < this.moduleInfo.updateVersionCode || (this.repoModule != null && this.moduleInfo.versionCode < this.repoModule.moduleInfo.versionCode)) {
|
||||
boolean ignoreUpdate = false;
|
||||
val type: Type
|
||||
get() = if (footerPx != -1) {
|
||||
Timber.i("Module %s is footer", moduleId)
|
||||
Type.FOOTER
|
||||
} else if (separator != null) {
|
||||
Timber.i("Module %s is separator", moduleId)
|
||||
Type.SEPARATOR
|
||||
} else if (notificationType != null) {
|
||||
Timber.i("Module %s is notification", moduleId)
|
||||
Type.NOTIFICATION
|
||||
} else if (moduleInfo == null) {
|
||||
Type.INSTALLABLE
|
||||
} else if (moduleInfo!!.versionCode < moduleInfo!!.updateVersionCode || repoModule != null && moduleInfo!!.versionCode < repoModule!!.moduleInfo.versionCode) {
|
||||
var ignoreUpdate = false
|
||||
try {
|
||||
if (Objects.requireNonNull(Objects.requireNonNull(MainApplication.getSharedPreferences("mmm")).getStringSet("pref_background_update_check_excludes", new HashSet<>())).contains(moduleInfo.id))
|
||||
ignoreUpdate = true;
|
||||
} catch (Exception ignored) {
|
||||
if (getSharedPreferences("mmm")?.getStringSet("pref_background_update_check_excludes", HashSet())!!
|
||||
.contains(
|
||||
moduleInfo!!.id
|
||||
)
|
||||
) ignoreUpdate = true
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
// now, we just had to make it more fucking complicated, didn't we?
|
||||
// we now have pref_background_update_check_excludes_version, which is a id:version stringset of versions the user may want to "skip"
|
||||
// oh, and because i hate myself, i made ^ at the beginning match that version and newer, and $ at the end match that version and older
|
||||
Set<String> stringSetT = Objects.requireNonNull(MainApplication.getSharedPreferences("mmm")).getStringSet("pref_background_update_check_excludes_version", new HashSet<>());
|
||||
String version = "";
|
||||
Timber.d(stringSetT.toString());
|
||||
val stringSetT = getSharedPreferences("mmm")?.getStringSet("pref_background_update_check_excludes_version", HashSet())
|
||||
var version = ""
|
||||
Timber.d(stringSetT.toString())
|
||||
// unfortunately, stringset.contains() doesn't work for partial matches
|
||||
// so we have to iterate through the set
|
||||
for (String s : stringSetT) {
|
||||
if (s.startsWith(this.moduleInfo.id)) {
|
||||
version = s;
|
||||
Timber.d("igV: %s", version);
|
||||
break;
|
||||
for (s in stringSetT!!) {
|
||||
if (s.startsWith(moduleInfo!!.id)) {
|
||||
version = s
|
||||
Timber.d("igV: %s", version)
|
||||
break
|
||||
}
|
||||
}
|
||||
String remoteVersionCode = String.valueOf(moduleInfo.updateVersionCode);
|
||||
var remoteVersionCode = moduleInfo!!.updateVersionCode.toString()
|
||||
if (repoModule != null) {
|
||||
remoteVersionCode = String.valueOf(repoModule.moduleInfo.versionCode);
|
||||
remoteVersionCode = repoModule!!.moduleInfo.versionCode.toString()
|
||||
}
|
||||
if (!version.isEmpty()) {
|
||||
if (version.isNotEmpty()) {
|
||||
// now, coerce everything into an int
|
||||
int remoteVersionCodeInt = Integer.parseInt(remoteVersionCode);
|
||||
int wantsVersion = Integer.parseInt(version.split(":")[1].replaceAll("[^0-9]", ""));
|
||||
val remoteVersionCodeInt = remoteVersionCode.toInt()
|
||||
val wantsVersion = version.split(":".toRegex()).dropLastWhile { it.isEmpty() }
|
||||
.toTypedArray()[1].replace("[^0-9]".toRegex(), "").toInt()
|
||||
// now find out if user wants up to and including this version, or this version and newer
|
||||
Timber.d("igV start with");
|
||||
version = version.split(":")[1];
|
||||
Timber.d("igV start with")
|
||||
version =
|
||||
version.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
|
||||
// this version and newer
|
||||
if (version.startsWith("^")) {
|
||||
Timber.d("igV: newer");
|
||||
Timber.d("igV: newer")
|
||||
// the wantsversion and newer
|
||||
if (remoteVersionCodeInt >= wantsVersion) {
|
||||
Timber.d("igV: skipping");
|
||||
Timber.d("igV: skipping")
|
||||
// if it is, we skip it
|
||||
ignoreUpdate = true;
|
||||
ignoreUpdate = true
|
||||
}
|
||||
} else if (version.endsWith("$")) {
|
||||
Timber.d("igV: older");
|
||||
Timber.d("igV: older")
|
||||
// this wantsversion and older
|
||||
if (remoteVersionCodeInt <= wantsVersion) {
|
||||
Timber.d("igV: skipping");
|
||||
Timber.d("igV: skipping")
|
||||
// if it is, we skip it
|
||||
ignoreUpdate = true;
|
||||
ignoreUpdate = true
|
||||
}
|
||||
} else if (wantsVersion == remoteVersionCodeInt) {
|
||||
Timber.d("igV: equal");
|
||||
Timber.d("igV: equal")
|
||||
// if it is, we skip it
|
||||
ignoreUpdate = true;
|
||||
ignoreUpdate = true
|
||||
}
|
||||
|
||||
}
|
||||
if (ignoreUpdate) {
|
||||
Timber.d("Module %s has update, but is ignored", this.moduleId);
|
||||
return Type.INSTALLABLE;
|
||||
Timber.d("Module %s has update, but is ignored", moduleId)
|
||||
Type.INSTALLABLE
|
||||
} else {
|
||||
Objects.requireNonNull(MainApplication.getINSTANCE()).modulesHaveUpdates = true;
|
||||
if (!MainApplication.getINSTANCE().updateModules.contains(this.moduleId)) {
|
||||
MainApplication.getINSTANCE().updateModules.add(this.moduleId);
|
||||
MainApplication.getINSTANCE().updateModuleCount++;
|
||||
INSTANCE!!.modulesHaveUpdates = true
|
||||
if (!INSTANCE!!.updateModules.contains(moduleId)) {
|
||||
INSTANCE!!.updateModules += moduleId
|
||||
INSTANCE!!.updateModuleCount++
|
||||
}
|
||||
Timber.d("modulesHaveUpdates = %s, updateModuleCount = %s", MainApplication.getINSTANCE().modulesHaveUpdates, MainApplication.getINSTANCE().updateModuleCount);
|
||||
Timber.d("Module %s has update", this.moduleId);
|
||||
return Type.UPDATABLE;
|
||||
Timber.d(
|
||||
"modulesHaveUpdates = %s, updateModuleCount = %s",
|
||||
INSTANCE!!.modulesHaveUpdates,
|
||||
INSTANCE!!.updateModuleCount
|
||||
)
|
||||
Timber.d("Module %s has update", moduleId)
|
||||
Type.UPDATABLE
|
||||
}
|
||||
} else {
|
||||
return Type.INSTALLED;
|
||||
Type.INSTALLED
|
||||
}
|
||||
}
|
||||
|
||||
public Type getCompareType(Type type) {
|
||||
if (this.separator != null) {
|
||||
return this.separator;
|
||||
} else if (this.notificationType != null && this.notificationType.special) {
|
||||
return Type.SPECIAL_NOTIFICATIONS;
|
||||
} else {
|
||||
return type;
|
||||
}
|
||||
fun getCompareType(type: Type?): Type? {
|
||||
return separator
|
||||
?: if (notificationType != null && notificationType.special) {
|
||||
Type.SPECIAL_NOTIFICATIONS
|
||||
} else {
|
||||
type
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldRemove() {
|
||||
if (this.repoModule != null && this.moduleInfo != null && !hasUpdate()) {
|
||||
return true;
|
||||
fun shouldRemove(): Boolean {
|
||||
if (repoModule != null && moduleInfo != null && !hasUpdate()) {
|
||||
return true
|
||||
}
|
||||
return this.notificationType != null ? this.notificationType.shouldRemove() : this.footerPx == -1 && this.moduleInfo == null && (this.repoModule == null || !this.repoModule.repoData.isEnabled() || (PropUtils.isLowQualityModule(this.repoModule.moduleInfo) && !MainApplication.Companion.isDisableLowQualityModuleFilter()));
|
||||
return notificationType?.shouldRemove()
|
||||
?: (footerPx == -1 && moduleInfo == null && (repoModule == null || !repoModule!!.repoData.isEnabled || isLowQualityModule(
|
||||
repoModule!!.moduleInfo
|
||||
) && !isDisableLowQualityModuleFilter))
|
||||
}
|
||||
|
||||
public void getButtons(Context context, List<ActionButtonType> buttonTypeList, boolean showcaseMode) {
|
||||
if (!this.isModuleHolder()) return;
|
||||
LocalModuleInfo localModuleInfo = this.moduleInfo;
|
||||
fun getButtons(
|
||||
context: Context?,
|
||||
buttonTypeList: MutableList<ActionButtonType?>,
|
||||
showcaseMode: Boolean
|
||||
) {
|
||||
if (!isModuleHolder) return
|
||||
val localModuleInfo = moduleInfo
|
||||
// Add warning button if module id begins with a dot - this is a hidden module which could indicate malware
|
||||
if (this.moduleId.startsWith(".") || !this.moduleId.matches("^[a-zA-Z][a-zA-Z0-9._-]+$")) {
|
||||
buttonTypeList.add(ActionButtonType.WARNING);
|
||||
if (moduleId.startsWith(".") || !moduleId.matches("^[a-zA-Z][a-zA-Z0-9._-]+$".toRegex())) {
|
||||
buttonTypeList.add(ActionButtonType.WARNING)
|
||||
}
|
||||
if (localModuleInfo != null && !showcaseMode) {
|
||||
buttonTypeList.add(ActionButtonType.UNINSTALL);
|
||||
buttonTypeList.add(ActionButtonType.UNINSTALL)
|
||||
}
|
||||
if (this.repoModule != null && this.repoModule.notesUrl != null) {
|
||||
buttonTypeList.add(ActionButtonType.INFO);
|
||||
if (repoModule != null && repoModule!!.notesUrl != null) {
|
||||
buttonTypeList.add(ActionButtonType.INFO)
|
||||
}
|
||||
if ((this.repoModule != null || (localModuleInfo != null && localModuleInfo.updateZipUrl != null))) {
|
||||
buttonTypeList.add(ActionButtonType.UPDATE_INSTALL);
|
||||
if (repoModule != null || localModuleInfo?.updateZipUrl != null) {
|
||||
buttonTypeList.add(ActionButtonType.UPDATE_INSTALL)
|
||||
}
|
||||
String config = this.getMainModuleConfig();
|
||||
val config = mainModuleConfig
|
||||
if (config != null) {
|
||||
if (config.startsWith("https://www.androidacy.com/") && Http.hasWebView()) {
|
||||
buttonTypeList.add(ActionButtonType.CONFIG);
|
||||
if (config.startsWith("https://www.androidacy.com/") && hasWebView()) {
|
||||
buttonTypeList.add(ActionButtonType.CONFIG)
|
||||
} else {
|
||||
String pkg = IntentHelper.getPackageOfConfig(config);
|
||||
val pkg = getPackageOfConfig(config)
|
||||
try {
|
||||
XHooks.checkConfigTargetExists(context, pkg, config);
|
||||
buttonTypeList.add(ActionButtonType.CONFIG);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Timber.w("Config package \"" + pkg + "\" missing for module \"" + this.moduleId + "\"");
|
||||
checkConfigTargetExists(context!!, pkg, config)
|
||||
buttonTypeList.add(ActionButtonType.CONFIG)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
Timber.w("Config package \"$pkg\" missing for module \"$moduleId\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
ModuleInfo moduleInfo = this.getMainModuleInfo();
|
||||
var moduleInfo: ModuleInfo? = mainModuleInfo
|
||||
if (moduleInfo == null) { // Avoid concurrency NPE
|
||||
if (localModuleInfo == null) return;
|
||||
moduleInfo = localModuleInfo;
|
||||
if (localModuleInfo == null) return
|
||||
moduleInfo = localModuleInfo
|
||||
}
|
||||
if (moduleInfo.support != null) {
|
||||
buttonTypeList.add(ActionButtonType.SUPPORT);
|
||||
buttonTypeList.add(ActionButtonType.SUPPORT)
|
||||
}
|
||||
if (moduleInfo.donate != null) {
|
||||
buttonTypeList.add(ActionButtonType.DONATE);
|
||||
buttonTypeList.add(ActionButtonType.DONATE)
|
||||
}
|
||||
if (moduleInfo.safe) {
|
||||
buttonTypeList.add(ActionButtonType.SAFE);
|
||||
buttonTypeList.add(ActionButtonType.SAFE)
|
||||
} else {
|
||||
Timber.d("Module %s is not safe", this.moduleId);
|
||||
Timber.d("Module %s is not safe", moduleId)
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasUpdate() {
|
||||
return this.moduleInfo != null && this.repoModule != null && this.moduleInfo.versionCode < this.repoModule.moduleInfo.versionCode;
|
||||
fun hasUpdate(): Boolean {
|
||||
return moduleInfo != null && repoModule != null && moduleInfo!!.versionCode < repoModule!!.moduleInfo.versionCode
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ModuleHolder o) {
|
||||
override operator fun compareTo(other: ModuleHolder?): Int {
|
||||
// Compare depend on type, also allow type spoofing
|
||||
Type selfTypeReal = this.getType();
|
||||
Type otherTypeReal = o.getType();
|
||||
Type selfType = this.getCompareType(selfTypeReal);
|
||||
Type otherType = o.getCompareType(otherTypeReal);
|
||||
int compare = selfType.compareTo(otherType);
|
||||
return compare != 0 ? compare : selfTypeReal == otherTypeReal ? selfTypeReal.compare(this, o) : selfTypeReal.compareTo(otherTypeReal);
|
||||
val selfTypeReal = type
|
||||
val otherTypeReal = other!!.type
|
||||
val selfType = getCompareType(selfTypeReal)
|
||||
val otherType = other.getCompareType(otherTypeReal)
|
||||
val compare = selfType!!.compareTo(otherType!!)
|
||||
return if (compare != 0) compare else if (selfTypeReal === otherTypeReal) selfTypeReal.compare(
|
||||
this,
|
||||
other
|
||||
) else selfTypeReal.compareTo(otherTypeReal)
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ModuleHolder{" + "moduleId='" + moduleId + '\'' + ", notificationType=" + notificationType + ", separator=" + separator + ", footerPx=" + footerPx + '}';
|
||||
override fun toString(): String {
|
||||
return "ModuleHolder{moduleId='$moduleId', notificationType=$notificationType, separator=$separator, footerPx=$footerPx}"
|
||||
}
|
||||
|
||||
public enum Type implements Comparator<ModuleHolder> {
|
||||
HEADER(R.string.loading, false, false), SEPARATOR(R.string.loading, false, false) {
|
||||
@Override
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public int compare(ModuleHolder o1, ModuleHolder o2) {
|
||||
return o1.separator.compareTo(o2.separator);
|
||||
enum class Type(
|
||||
@field:StringRes @param:StringRes val title: Int,
|
||||
val hasBackground: Boolean,
|
||||
val moduleHolder: Boolean
|
||||
) : Comparator<ModuleHolder?> {
|
||||
HEADER(R.string.loading, false, false) {
|
||||
override fun compare(o1: ModuleHolder?, o2: ModuleHolder?): Int {
|
||||
if (o1 != null && o2 != null) {
|
||||
return o1.separator!!.compareTo(o2.separator!!)
|
||||
} else if (o1 != null) {
|
||||
return -1
|
||||
} else if (o2 != null) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}, NOTIFICATION(R.string.loading, true, false) {
|
||||
@Override
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public int compare(ModuleHolder o1, ModuleHolder o2) {
|
||||
return o1.notificationType.compareTo(o2.notificationType);
|
||||
}, SEPARATOR(R.string.loading, false, false) {
|
||||
override fun compare(o1: ModuleHolder?, o2: ModuleHolder?): Int {
|
||||
if (o1 != null && o2 != null) {
|
||||
return o1.separator!!.compareTo(o2.separator!!)
|
||||
} else if (o1 != null) {
|
||||
return -1
|
||||
} else if (o2 != null) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}, UPDATABLE(R.string.updatable, true, true) {
|
||||
@Override
|
||||
public int compare(ModuleHolder o1, ModuleHolder o2) {
|
||||
int cmp = Integer.compare(o1.filterLevel, o2.filterLevel);
|
||||
if (cmp != 0) return cmp;
|
||||
long lastUpdated1 = o1.repoModule == null ? 0L : o1.repoModule.lastUpdated;
|
||||
long lastUpdated2 = o2.repoModule == null ? 0L : o2.repoModule.lastUpdated;
|
||||
cmp = Long.compare(lastUpdated2, lastUpdated1);
|
||||
if (cmp != 0) return cmp;
|
||||
return o1.getMainModuleName().compareTo(o2.getMainModuleName());
|
||||
},
|
||||
NOTIFICATION(R.string.loading, true, false) {
|
||||
override fun compare(o1: ModuleHolder?, o2: ModuleHolder?): Int {
|
||||
if (o1 != null && o2 != null) {
|
||||
return o1.notificationType!!.compareTo(o2.notificationType!!)
|
||||
} else if (o1 != null) {
|
||||
return -1
|
||||
} else if (o2 != null) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}, INSTALLED(R.string.installed, true, true) {
|
||||
},
|
||||
UPDATABLE(R.string.updatable, true, true) {
|
||||
override fun compare(o1: ModuleHolder?, o2: ModuleHolder?): Int {
|
||||
if (o1 != null && o2 != null) {
|
||||
var cmp = o1.filterLevel.compareTo(o2.filterLevel)
|
||||
if (cmp != 0) return cmp
|
||||
val lastUpdated1 =
|
||||
if (o1.repoModule == null) 0L else o1.repoModule!!.lastUpdated
|
||||
val lastUpdated2 =
|
||||
if (o2.repoModule == null) 0L else o2.repoModule!!.lastUpdated
|
||||
cmp = lastUpdated2.compareTo(lastUpdated1)
|
||||
return if (cmp != 0) cmp else o1.mainModuleName!!.compareTo(o2.mainModuleName!!)
|
||||
} else if (o1 != null) {
|
||||
return -1
|
||||
} else if (o2 != null) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
},
|
||||
INSTALLED(R.string.installed, true, true) {
|
||||
// get stacktrace for debugging
|
||||
@Override
|
||||
public int compare(ModuleHolder o1, ModuleHolder o2) {
|
||||
int cmp = Integer.compare(o1.filterLevel, o2.filterLevel);
|
||||
if (cmp != 0) return cmp;
|
||||
return o1.getMainModuleNameLowercase().compareTo(o2.getMainModuleNameLowercase());
|
||||
override fun compare(o1: ModuleHolder?, o2: ModuleHolder?): Int {
|
||||
if (o1 != null && o2 != null) {
|
||||
val cmp = o1.filterLevel.compareTo(o2.filterLevel)
|
||||
return if (cmp != 0) cmp else o1.mainModuleNameLowercase.compareTo(o2.mainModuleNameLowercase)
|
||||
} else if (o1 != null) {
|
||||
return -1
|
||||
} else if (o2 != null) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}, SPECIAL_NOTIFICATIONS(R.string.loading, true, false), INSTALLABLE(R.string.online_repo, true, true) {
|
||||
@Override
|
||||
public int compare(ModuleHolder o1, ModuleHolder o2) {
|
||||
int cmp = Integer.compare(o1.filterLevel, o2.filterLevel);
|
||||
if (cmp != 0) return cmp;
|
||||
long lastUpdated1 = o1.repoModule == null ? 0L : o1.repoModule.lastUpdated;
|
||||
long lastUpdated2 = o2.repoModule == null ? 0L : o2.repoModule.lastUpdated;
|
||||
cmp = Long.compare(lastUpdated2, lastUpdated1);
|
||||
if (cmp != 0) return cmp;
|
||||
return o1.getMainModuleName().compareTo(o2.getMainModuleName());
|
||||
},
|
||||
SPECIAL_NOTIFICATIONS(R.string.loading, true, false) {
|
||||
override fun compare(o1: ModuleHolder?, o2: ModuleHolder?): Int {
|
||||
if (o1 != null && o2 != null) {
|
||||
var cmp = o1.filterLevel.compareTo(o2.filterLevel)
|
||||
if (cmp != 0) return cmp
|
||||
val lastUpdated1 =
|
||||
if (o1.repoModule == null) 0L else o1.repoModule!!.lastUpdated
|
||||
val lastUpdated2 =
|
||||
if (o2.repoModule == null) 0L else o2.repoModule!!.lastUpdated
|
||||
cmp = lastUpdated2.compareTo(lastUpdated1)
|
||||
return if (cmp != 0) cmp else o1.mainModuleName!!.compareTo(o2.mainModuleName!!)
|
||||
} else if (o1 != null) {
|
||||
return -1
|
||||
} else if (o2 != null) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}, FOOTER(R.string.loading, false, false);
|
||||
|
||||
@StringRes
|
||||
public final int title;
|
||||
public final boolean hasBackground;
|
||||
public final boolean moduleHolder;
|
||||
|
||||
Type(@StringRes int title, boolean hasBackground, boolean moduleHolder) {
|
||||
this.title = title;
|
||||
this.hasBackground = hasBackground;
|
||||
this.moduleHolder = moduleHolder;
|
||||
}
|
||||
|
||||
// Note: This method should only be called if both element have the same type
|
||||
@Override
|
||||
public int compare(ModuleHolder o1, ModuleHolder o2) {
|
||||
if (o1 == o2) {
|
||||
return 0;
|
||||
} else if (o1 == null) {
|
||||
return -1;
|
||||
} else if (o2 == null) {
|
||||
return 1;
|
||||
} else {
|
||||
return o1.moduleId.compareTo(o2.moduleId);
|
||||
}, INSTALLABLE(
|
||||
R.string.online_repo,
|
||||
true,
|
||||
true
|
||||
) {
|
||||
override fun compare(o1: ModuleHolder?, o2: ModuleHolder?): Int {
|
||||
if (o1 != null && o2 != null) {
|
||||
var cmp = o1.filterLevel.compareTo(o2.filterLevel)
|
||||
if (cmp != 0) return cmp
|
||||
val lastUpdated1 =
|
||||
if (o1.repoModule == null) 0L else o1.repoModule!!.lastUpdated
|
||||
val lastUpdated2 =
|
||||
if (o2.repoModule == null) 0L else o2.repoModule!!.lastUpdated
|
||||
cmp = lastUpdated2.compareTo(lastUpdated1)
|
||||
return if (cmp != 0) cmp else o1.mainModuleName!!.compareTo(o2.mainModuleName!!)
|
||||
} else if (o1 != null) {
|
||||
return -1
|
||||
} else if (o2 != null) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
},
|
||||
FOOTER(R.string.loading, false, false) {
|
||||
override fun compare(o1: ModuleHolder?, o2: ModuleHolder?): Int {
|
||||
if (o1 != null && o2 != null) {
|
||||
return o1.footerPx.compareTo(o2.footerPx)
|
||||
} else if (o1 != null) {
|
||||
return -1
|
||||
} else if (o2 != null) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue