diff --git a/README.md b/README.md index 8be288e..51d2aa1 100644 --- a/README.md +++ b/README.md @@ -64,9 +64,11 @@ me to not be stuck in my bed at least once a day because of pain. ## Screenshots -Main activity: -[](docs/screenshot-dark.jpg) -[](docs/screenshot-light.jpg) +Main activity: + +| Dark theme | Light theme | +|:-----------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:| +| [](docs/screenshot-dark.png) | [](docs/screenshot-light.png) | ## What is this? @@ -100,20 +102,12 @@ drawbacks: (Note: Each module repo can be disabled in the settings of the app) (NoteĀ²: I do not own or actively monitor any of the repos or modules, **download at your own risk**) -#### [https://github.com/Magisk-Modules-Alt-Repo](https://github.com/Magisk-Modules-Alt-Repo) - -- Accepting new modules [here](https://github.com/Magisk-Modules-Alt-Repo/submission) -- Less restrictive than the original repo -- Officially supported by Fox's mmm - -Support: - -[![GitHub issues](https://img.shields.io/github/issues/Magisk-Modules-Alt-Repo/submission)](https://github.com/Magisk-Modules-Alt-Repo/submission/issues) #### [https://www.androidacy.com/modules-repo/](https://www.androidacy.com/modules-repo/) - Accepting new modules [here](https://www.androidacy.com/module-repository-applications/) - Modules downloadable easily outside the app +- Rigorously reviewed and tested modules - Officially supported by Fox's mmm - May show ads to help cover infrastrcture costs. - [Read more](https://www.androidacycom/doing-it-alone-the-what-the-how-and-the-why/) @@ -124,6 +118,18 @@ Support: [![Telegram Group](https://img.shields.io/endpoint?color=neon&style=flat&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fandroidacy_discussions)](https://telegram.dog/androidacy_discussions) + +#### [Magisk Alt Repo](https://github.com/Magisk-Modules-Alt-Repo) + +- Accepting new modules [here](https://github.com/Magisk-Modules-Alt-Repo/submission) +- Less restrictive than the original repo + - May have lower quality, untested, or otherwise broken modules due to this +- Officially supported by Fox's mmm + +Support: + +[![GitHub issues](https://img.shields.io/github/issues/Magisk-Modules-Alt-Repo/submission)](https://github.com/Magisk-Modules-Alt-Repo/submission/issues) + If a module is in multiple repos, the manager will just pick the most up to date version of the module, if a module is in multiple repos it will just use first registered repo. @@ -149,14 +155,14 @@ For more information please check the [developer documentation](docs/DEVELOPERS. **We need your help!** The app has started lagging behind in translations, and we need your help to catch up! As a reminder, translations are required to be at 60% or more to be included in the app. -### Recommended method +### Weblate (recommended) We use Weblate for translations: [https://translate.nift4.org/engage/foxmmm/](https://translate.nift4.org/engage/foxmmm/) - You can create an account and start translating - You may need to check your spam folder for the confirmation email -### GitHub method for advanced users +### GitHub method (advanced users) See [`app/src/main/res/values/strings.xml`](https://github.com/Fox2Code/FoxMagiskModuleManager/blob/master/app/src/main/res/values/strings.xml) @@ -186,18 +192,13 @@ later portions of the code are copyright 2022-present [Androidacy](https://www.androidacy.com/?utm_source=fox-repo&utm_medium=web). See [LICENSE](LICENCE) for details. Library licenses can be found in the licenses section of the app. -Modules are not covered by this license, please check the license of each module before using it. +Modules and their files, names, and other assets are not covered by this license, please check the license of each module before using it. -Some third party backend services may be proprietary, please check their terms of service before +Some third party backend services may be proprietary or have additional terms, please check their terms of service before using them. -## Disclaimer +## EULA -In no event shall the developer be liable for any special, direct, indirect, consequential, or -incidental damages or any damages whatsoever, whether in an action of contract, negligence or other -tort, arising out of or in connection with the use of the app or the contents of the app. The -developer reserves the right to make additions, deletions, or modification to the contents on the -app at any time without prior notice. +The EULA can be found [here](https://www.androidacy.com/foxmmm-eula/). By downloading, installing, or using this app you agree to the terms of the EULA. -This app is not affiliated with Magisk or its developers, nor with any of the module repos or -developers of the modules. +`IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.` diff --git a/app/build.gradle b/app/build.gradle index 83b9b51..aef7713 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,6 +28,25 @@ android { keyPassword properties.getProperty('keystore.password') } } + enableV3Signing = true + enableV4Signing = true + } + debug { + // Everything comes from local.properties + Properties properties = new Properties() + if (project.rootProject.file('local.properties').exists()) { + properties.load(project.rootProject.file('local.properties').newDataInputStream()) + // java.lang.IllegalArgumentException: path may not be null or empty string. path='null' + if (properties.getProperty('keystore.file') != null) { + // FFS DO NOT CHANGE THIS, IT WILL BREAK THE BUILD + storeFile file(properties.getProperty('keystore.file')) + storePassword properties.getProperty('keystore.password') + keyAlias 'key0' + keyPassword properties.getProperty('keystore.password') + } + } + enableV3Signing = true + enableV4Signing = true } } @@ -37,7 +56,6 @@ android { targetSdk 33 versionCode 64 versionName "2.0.0-beta.1" - signingConfig signingConfigs.release archivesBaseName = "FoxMMM-v$versionName" } @@ -69,10 +87,12 @@ android { shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release } debug { applicationIdSuffix '.debug' debuggable true + signingConfig signingConfigs.debug // ONLY FOR TESTING SENTRY // minifyEnabled true diff --git a/app/src/main/java/com/fox2code/mmm/MainApplication.java b/app/src/main/java/com/fox2code/mmm/MainApplication.java index 7c2fc63..6223d15 100644 --- a/app/src/main/java/com/fox2code/mmm/MainApplication.java +++ b/app/src/main/java/com/fox2code/mmm/MainApplication.java @@ -35,6 +35,7 @@ import com.topjohnwu.superuser.Shell; import java.io.File; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Date; import java.util.HashSet; import java.util.List; @@ -47,12 +48,12 @@ import io.noties.markwon.html.HtmlPlugin; import io.noties.markwon.image.ImagesPlugin; import io.noties.markwon.image.network.OkHttpNetworkSchemeHandler; import io.realm.Realm; -import io.sentry.IHub; import io.sentry.Sentry; import io.sentry.SentryLevel; import io.sentry.android.timber.SentryTimberTree; import timber.log.Timber; +@SuppressWarnings("CommentedOutCode") public class MainApplication extends FoxApplication implements androidx.work.Configuration.Provider { // Warning! Locales that are't exist will crash the app // Anything that is commented out is supported but the translation is not complete to at least 60% @@ -288,8 +289,8 @@ public class MainApplication extends FoxApplication implements androidx.work.Con Timber.plant(new Timber.DebugTree()); } else { if (isCrashReportingEnabled()) { - @SuppressWarnings("UnstableApiUsage") IHub hub = Sentry.getCurrentHub(); - Timber.plant(new SentryTimberTree(hub, SentryLevel.ERROR, SentryLevel.ERROR)); + //noinspection UnstableApiUsage + Timber.plant(new SentryTimberTree(Sentry.getCurrentHub(), SentryLevel.ERROR, SentryLevel.ERROR)); } else { Timber.plant(new ReleaseTree()); } @@ -335,9 +336,9 @@ public class MainApplication extends FoxApplication implements androidx.work.Con try { // Get the signature of the key used to sign the app @SuppressLint("PackageManagerGetSignatures") Signature[] signatures = this.getPackageManager().getPackageInfo(this.getPackageName(), PackageManager.GET_SIGNATURES).signatures; - String officialSignatureHash = "7bec7c4462f4aac616612d9f56a023ee3046e83afa956463b5fab547fd0a0be6"; + String[] officialSignatureHashArray = new String[]{"7bec7c4462f4aac616612d9f56a023ee3046e83afa956463b5fab547fd0a0be6", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}; String ourSignatureHash = Hashing.sha256().hashBytes(signatures[0].toByteArray()).toString(); - isOfficial = ourSignatureHash.equals(officialSignatureHash); + isOfficial = Arrays.asList(officialSignatureHashArray).contains(ourSignatureHash); } catch ( PackageManager.NameNotFoundException ignored) { } diff --git a/app/src/main/java/com/fox2code/mmm/SetupActivity.java b/app/src/main/java/com/fox2code/mmm/SetupActivity.java index 7a58a8e..00465ea 100644 --- a/app/src/main/java/com/fox2code/mmm/SetupActivity.java +++ b/app/src/main/java/com/fox2code/mmm/SetupActivity.java @@ -300,7 +300,7 @@ public class SetupActivity extends FoxActivity implements LanguageActivity { androidacy_repo.setLastUpdate(0); androidacy_repo.setWebsite(RepoManager.ANDROIDACY_MAGISK_REPO_HOMEPAGE); // now copy the data from the data class to the realm object using copyToRealmOrUpdate - realm1.copyToRealmOrUpdate(androidacy_repo); + realm1.insertOrUpdate(androidacy_repo); } // create magisk_alt_repo if (realm1.where(ReposList.class).equalTo("id", "magisk_alt_repo").findFirst() == null) { @@ -314,7 +314,7 @@ public class SetupActivity extends FoxActivity implements LanguageActivity { magisk_alt_repo.setSubmitModule(RepoManager.MAGISK_ALT_REPO_HOMEPAGE + "/submission"); magisk_alt_repo.setLastUpdate(0); // commit the changes - realm1.copyToRealmOrUpdate(magisk_alt_repo); + realm1.insertOrUpdate(magisk_alt_repo); } realm1.commitTransaction(); realm1.close(); @@ -325,7 +325,9 @@ public class SetupActivity extends FoxActivity implements LanguageActivity { assert reposLists != null; Timber.d("ReposList.realm"); for (ReposList reposList : reposLists) { - Timber.d(reposList.toString()); + Timber.d("Record: %s", reposList.getId()); + // log the data + Timber.d("Name: %s, Donate: %s, Support: %s, Submit Module: %s, Website: %s, Enabled: %s, Last Update: %s", reposList.getName(), reposList.getDonate(), reposList.getSupport(), reposList.getSubmitModule(), reposList.getWebsite(), reposList.isEnabled(), reposList.getLastUpdate()); } realm3.close(); } diff --git a/app/src/main/java/com/fox2code/mmm/repo/RepoData.java b/app/src/main/java/com/fox2code/mmm/repo/RepoData.java index 32a2567..8d2eaeb 100644 --- a/app/src/main/java/com/fox2code/mmm/repo/RepoData.java +++ b/app/src/main/java/com/fox2code/mmm/repo/RepoData.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Objects; import io.realm.Realm; import io.realm.RealmConfiguration; @@ -114,15 +115,11 @@ public class RepoData extends XRepo { ReposList reposList = realm.where(ReposList.class).equalTo("id", this.id).findFirst(); Timber.d("RepoData: " + this.id + ". record in database: " + (reposList != null ? reposList.toString() : "none")); this.enabled = (!this.forceHide && reposList != null && reposList.isEnabled()); - this.enabled = (!this.forceHide) && MainApplication.getSharedPreferences().getBoolean("pref_" + this.getPreferenceId() + "_enabled", true); this.defaultWebsite = "https://" + Uri.parse(url).getHost() + "/"; // open realm database // load metadata from realm database if (this.enabled) { try { - RealmConfiguration realmConfiguration2 = new RealmConfiguration.Builder().name("ReposList.realm").allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(MainApplication.getINSTANCE().getDataDirWithPath("realms")).schemaVersion(1).build(); - // load metadata from realm database - Realm.getInstance(realmConfiguration2); this.metaDataCache = ModuleListCache.getRepoModulesAsJson(this.id); // load repo metadata from ReposList unless it's a built-in repo if (RepoManager.isBuiltInRepo(this.id)) { @@ -133,18 +130,14 @@ public class RepoData extends XRepo { this.submitModule = this.defaultSubmitModule; } else { // get everything from ReposList realm database - RealmConfiguration realmConfiguration3 = new RealmConfiguration.Builder().name("ReposList.realm").allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(MainApplication.getINSTANCE().getDataDirWithPath("realms")).schemaVersion(1).build(); - // load metadata from realm database - Realm.getInstance(realmConfiguration3); - this.name = ReposList.getRepo(this.id).getName(); - this.website = ReposList.getRepo(this.id).getWebsite(); - this.support = ReposList.getRepo(this.id).getSupport(); - this.donate = ReposList.getRepo(this.id).getDonate(); - this.submitModule = ReposList.getRepo(this.id).getSubmitModule(); + this.name = Objects.requireNonNull(realm.where(ReposList.class).equalTo("id", this.id).findFirst()).getName(); + this.website = Objects.requireNonNull(realm.where(ReposList.class).equalTo("id", this.id).findFirst()).getWebsite(); + this.support = Objects.requireNonNull(realm.where(ReposList.class).equalTo("id", this.id).findFirst()).getSupport(); + this.donate = Objects.requireNonNull(realm.where(ReposList.class).equalTo("id", this.id).findFirst()).getDonate(); + this.submitModule = Objects.requireNonNull(realm.where(ReposList.class).equalTo("id", this.id).findFirst()).getSubmitModule(); } } catch (Exception e) { - e.printStackTrace(); - Timber.w("If this is a first install, this is normal."); + Timber.w("Failed to load repo metadata from database: " + e.getMessage() + ". If this is a first time run, this is normal."); } } } diff --git a/docs/screenshot-dark.jpg b/docs/screenshot-dark.jpg deleted file mode 100644 index 8f797a5..0000000 Binary files a/docs/screenshot-dark.jpg and /dev/null differ diff --git a/docs/screenshot-dark.png b/docs/screenshot-dark.png new file mode 100644 index 0000000..019207e Binary files /dev/null and b/docs/screenshot-dark.png differ diff --git a/docs/screenshot-light.jpg b/docs/screenshot-light.jpg deleted file mode 100644 index a019815..0000000 Binary files a/docs/screenshot-light.jpg and /dev/null differ diff --git a/docs/screenshot-light.png b/docs/screenshot-light.png new file mode 100644 index 0000000..37e981a Binary files /dev/null and b/docs/screenshot-light.png differ