From eae09bf81258ae9f3802c57a6037037d1e15a929 Mon Sep 17 00:00:00 2001 From: androidacy-user Date: Tue, 2 May 2023 16:30:38 -0400 Subject: [PATCH] hide search on scroll down fixes #313 Signed-off-by: androidacy-user --- README.md | 4 +- .../java/com/fox2code/mmm/MainActivity.java | 43 +++++++++++++++++-- .../java/com/fox2code/mmm/SetupActivity.java | 11 ++--- .../mmm/androidacy/AndroidacyUtil.java | 6 ++- .../background/BackgroundUpdateChecker.java | 6 +-- .../fox2code/mmm/manager/ModuleManager.java | 4 +- .../com/fox2code/mmm/repo/RepoManager.java | 4 +- .../fox2code/mmm/utils/sentry/SentryMain.java | 2 +- app/src/main/res/layout/activity_setup.xml | 11 +++-- app/src/main/res/menu/setup_bottom_nav.xml | 1 + app/src/main/res/values/strings.xml | 2 + 11 files changed, 68 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 47b7bb7..21dbefb 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ ### Developed by Androidacy. Find us on the web [here](https://www.androidacy.com/?utm_source=fox-readme&utm_medium=web&utm_campagin=github). +_If you're seeing this at the Fox2Code repo, the new repo is at [Androidacy/AndroidacyModuleManager](https://github.com/Androidacy/AndroidacyModuleManager)! The old repo may not receive consistent updates anymore!_ + ## About The official Magisk Manager app has dropped it's support for downloading online modules, leaving users without a way to easily search for and download them. This app was created to help users download and install modules, and manage their own modules. @@ -10,8 +12,6 @@ The official Magisk Manager app has dropped it's support for downloading online **The modules shown in this app are not affiliated with this app or Magisk**. -_If you're seeing this at the Fox2Code repo, the new repo is at [Androidacy/AndroidacyModuleManager](https://github.com/Androidacy/AndroidacyModuleManager)!_ - ## Features - Download and install modules - Manage your own modules diff --git a/app/src/main/java/com/fox2code/mmm/MainActivity.java b/app/src/main/java/com/fox2code/mmm/MainActivity.java index dcc3adf..3fee630 100644 --- a/app/src/main/java/com/fox2code/mmm/MainActivity.java +++ b/app/src/main/java/com/fox2code/mmm/MainActivity.java @@ -23,6 +23,8 @@ import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.EditorInfo; import android.widget.CheckBox; import android.widget.Toast; @@ -71,6 +73,8 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe private static final int PRECISION = 10000; public static boolean doSetupNowRunning = true; public static boolean doSetupRestarting = false; + public static List localModuleInfoList = new ArrayList<>(); + public static List onlineModuleInfoList = new ArrayList<>(); public final ModuleViewListBuilder moduleViewListBuilder; public final ModuleViewListBuilder moduleViewListBuilderOnline; public LinearProgressIndicator progressIndicator; @@ -87,8 +91,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe private CardView searchCard; private SearchView searchView; private boolean initMode; - public static List localModuleInfoList = new ArrayList<>(); - public static List onlineModuleInfoList = new ArrayList<>(); public MainActivity() { this.moduleViewListBuilder = new ModuleViewListBuilder(this); @@ -178,6 +180,40 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { if (newState != RecyclerView.SCROLL_STATE_IDLE) MainActivity.this.searchView.clearFocus(); + // hide search view when scrolling + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + MainActivity.this.searchCard.animate().translationY(-MainActivity.this.searchCard.getHeight()).setInterpolator(new AccelerateInterpolator(2)).start(); + } + } + + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + // if the user scrolled up, show the search bar + if (dy < 0) { + MainActivity.this.searchCard.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start(); + } + } + }); + // same for online + this.moduleListOnline.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + if (newState != RecyclerView.SCROLL_STATE_IDLE) + MainActivity.this.searchView.clearFocus(); + // hide search view when scrolling + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + MainActivity.this.searchCard.animate().translationY(-MainActivity.this.searchCard.getHeight()).setInterpolator(new AccelerateInterpolator(2)).start(); + } + } + + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + // if the user scrolled up, show the search bar + if (dy < 0) { + MainActivity.this.searchCard.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start(); + } } }); this.searchCard.setRadius(this.searchCard.getHeight() / 2F); @@ -596,6 +632,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe }); NotificationType.NEED_CAPTCHA_ANDROIDACY.autoAdd(moduleViewListBuilder); RepoManager.getINSTANCE().updateEnabledStates(); + RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilder::appendInstalledModules); RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilderOnline::appendRemoteModules); this.moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter); this.moduleViewListBuilderOnline.applyTo(moduleListOnline, moduleViewAdapterOnline); @@ -763,7 +800,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe if (BuildConfig.DEBUG) Timber.i("Checking if we need to run setup"); // Check if this is the first launch using prefs and if doSetupRestarting was passed in the intent SharedPreferences prefs = MainApplication.getSharedPreferences("mmm"); - boolean firstLaunch = !Objects.equals(prefs.getString("last_shown_setup", null), "v1"); + boolean firstLaunch = !Objects.equals(prefs.getString("last_shown_setup", null), "v2"); // First launch // this is intentionally separate from the above if statement, because it needs to be checked even if the first launch check is true due to some weird edge cases if (getIntent().getBooleanExtra("doSetupRestarting", false)) { diff --git a/app/src/main/java/com/fox2code/mmm/SetupActivity.java b/app/src/main/java/com/fox2code/mmm/SetupActivity.java index cc5463e..2042b76 100644 --- a/app/src/main/java/com/fox2code/mmm/SetupActivity.java +++ b/app/src/main/java/com/fox2code/mmm/SetupActivity.java @@ -153,12 +153,9 @@ public class SetupActivity extends FoxActivity implements LanguageActivity { // Set up the buttons // Setup button BottomNavigationItemView setupButton = view.findViewById(R.id.setup_finish); - // enable finish button when user scrolls to the bottom - findViewById(R.id.setupNestedScrollView).setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { - if (scrollY > oldScrollY) { - setupButton.setEnabled(true); - } - }); + // on clicking setup_agree_eula, enable the setup button if it's checked, if it's not, disable it + MaterialSwitch agreeEula = view.findViewById(R.id.setup_agree_eula); + agreeEula.setOnCheckedChangeListener((buttonView, isChecked) -> setupButton.setEnabled(isChecked)); setupButton.setOnClickListener(v -> { Timber.i("Setup button clicked"); // get instance of editor @@ -200,7 +197,7 @@ public class SetupActivity extends FoxActivity implements LanguageActivity { r.close(); Timber.d("Realm transaction committed"); }); - editor.putString("last_shown_setup", "v1"); + editor.putString("last_shown_setup", "v2"); // Commit the changes editor.commit(); // sleep to allow the realm transaction to finish diff --git a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyUtil.java b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyUtil.java index 97fe73a..3a3ca5d 100644 --- a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyUtil.java +++ b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyUtil.java @@ -7,6 +7,8 @@ import androidx.annotation.Nullable; import com.fox2code.mmm.BuildConfig; +import java.util.Objects; + public enum AndroidacyUtil { ; public static final String REFERRER = "utm_source=FoxMMM&utm_medium=app"; @@ -21,13 +23,13 @@ public enum AndroidacyUtil { static boolean isAndroidacyLink(@NonNull String url, @NonNull Uri uri) { int i; // Check both string and Uri to mitigate parse exploit - return url.startsWith("https://") && (i = url.indexOf("/", 8)) != -1 && url.substring(8, i).endsWith("api.androidacy.com") && uri.getHost().endsWith("api.androidacy.com"); + return url.startsWith("https://") && (i = url.indexOf("/", 8)) != -1 && url.substring(8, i).endsWith("api.androidacy.com") && Objects.requireNonNull(uri.getHost()).endsWith("api.androidacy.com"); } public static boolean isAndroidacyFileUrl(@Nullable String url) { if (url == null) return false; - for (String prefix : new String[]{"https://production-api.androidacy.com/magisk/file/", "https://staging-api.androidacy.com/magisk/file/"}) { // Make both staging and non staging act the same + for (String prefix : new String[]{"https://production-api.androidacy.com/downloads/", "https://production-api.androidacy.com/magisk/file/", "https://staging-api.androidacy.com/magisk/file/"}) { // Make both staging and non staging act the same if (url.startsWith(prefix)) return true; } diff --git a/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java b/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java index 8d72a20..bfe7b9c 100644 --- a/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java +++ b/app/src/main/java/com/fox2code/mmm/background/BackgroundUpdateChecker.java @@ -100,7 +100,7 @@ public class BackgroundUpdateChecker extends Worker { // check if wifi is connected ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); Network networkInfo = connectivityManager.getActiveNetwork(); - if (networkInfo == null || !connectivityManager.getNetworkCapabilities(networkInfo).hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) { + if (networkInfo == null || !Objects.requireNonNull(connectivityManager.getNetworkCapabilities(networkInfo)).hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) { Timber.w("Background update check: wifi not connected but required"); return; } @@ -136,7 +136,7 @@ public class BackgroundUpdateChecker extends Worker { if ("twrp-keep".equals(localModuleInfo.id)) continue; // exclude all modules with id's stored in the pref pref_background_update_check_excludes try { - if (MainApplication.getSharedPreferences("mmm").getStringSet("pref_background_update_check_excludes", null).contains(localModuleInfo.id)) + if (Objects.requireNonNull(MainApplication.getSharedPreferences("mmm").getStringSet("pref_background_update_check_excludes", null)).contains(localModuleInfo.id)) continue; } catch (Exception ignored) { } @@ -213,7 +213,7 @@ public class BackgroundUpdateChecker extends Worker { public static void onMainActivityCreate(Context context) { // Refuse to run if first_launch pref is not false - if (!Objects.equals(MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", null), "v1")) + if (!Objects.equals(MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", null), "v2")) return; // create notification channel group if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { diff --git a/app/src/main/java/com/fox2code/mmm/manager/ModuleManager.java b/app/src/main/java/com/fox2code/mmm/manager/ModuleManager.java index 4108b7c..74520c0 100644 --- a/app/src/main/java/com/fox2code/mmm/manager/ModuleManager.java +++ b/app/src/main/java/com/fox2code/mmm/manager/ModuleManager.java @@ -57,8 +57,8 @@ public final class ModuleManager extends SyncManager { } protected void scanInternal(@NonNull UpdateListener updateListener) { - // if last_shown_setup is not "v1", then refuse to continue - if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v1")) { + // if last_shown_setup is not "v2", then refuse to continue + if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v2")) { return; } boolean firstScan = this.bootPrefs.getBoolean("mm_first_scan", true); diff --git a/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java b/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java index 0b59d23..504872f 100644 --- a/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java +++ b/app/src/main/java/com/fox2code/mmm/repo/RepoManager.java @@ -149,8 +149,8 @@ public final class RepoManager extends SyncManager { @SuppressWarnings("StatementWithEmptyBody") private void populateDefaultCache(RepoData repoData) { - // if last_shown_setup is not "v1", them=n refuse to continue - if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v1")) { + // if last_shown_setup is not "v2", them=n refuse to continue + if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v2")) { return; } // make sure repodata is not null diff --git a/app/src/main/java/com/fox2code/mmm/utils/sentry/SentryMain.java b/app/src/main/java/com/fox2code/mmm/utils/sentry/SentryMain.java index 5bd69d3..c88b6ec 100644 --- a/app/src/main/java/com/fox2code/mmm/utils/sentry/SentryMain.java +++ b/app/src/main/java/com/fox2code/mmm/utils/sentry/SentryMain.java @@ -61,7 +61,7 @@ public class SentryMain { }); // If first_launch pref is not false, refuse to initialize Sentry SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("mmm"); - if (!Objects.equals(sharedPreferences.getString("last_shown_setup", null), "v1")) { + if (!Objects.equals(sharedPreferences.getString("last_shown_setup", null), "v2")) { return; } sentryEnabled = sharedPreferences.getBoolean("pref_crash_reporting_enabled", false); diff --git a/app/src/main/res/layout/activity_setup.xml b/app/src/main/res/layout/activity_setup.xml index d21806a..f8ae015 100644 --- a/app/src/main/res/layout/activity_setup.xml +++ b/app/src/main/res/layout/activity_setup.xml @@ -48,8 +48,9 @@ android:id="@+id/setup_scroll_down" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_margin="2dp" - android:text="@string/setup_scroll_down" + android:layout_marginHorizontal="2dp" + android:layout_marginVertical="4dp" + android:text="@string/setup_scroll_down_v2" android:textAppearance="@style/TextAppearance.Material3.BodyMedium" /> @@ -284,14 +285,16 @@ android:text="@string/other_section" android:textAppearance="@android:style/TextAppearance.Material.Headline" /> - diff --git a/app/src/main/res/menu/setup_bottom_nav.xml b/app/src/main/res/menu/setup_bottom_nav.xml index 7a08dee..df53a8e 100644 --- a/app/src/main/res/menu/setup_bottom_nav.xml +++ b/app/src/main/res/menu/setup_bottom_nav.xml @@ -5,6 +5,7 @@ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 258cd83..6afa77b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -403,6 +403,7 @@ An app restart is required to enable showcase mode. Other By clicking "finish", you are agreeing to be bound by the LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.en.html) license and the EULA (https://www.androidacy.com/foxmmm-eula/) + I agree to be bound by the LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.en.html) license and the EULA (https://www.androidacy.com/foxmmm-eula/), in addition to any third party terms. Allow us to track app usage and installs. Fully GDPR compliant and uses Matomo, hosted by Androidacy. Debugging News and updates @@ -413,4 +414,5 @@ Use the copied code for half off your first month! Please note that some settings may not take effect until you restart the app. Reinstall + To enable the finsih button, scroll to the bottom and acknowledge you have read and agree to the EULA and license(s).