hide search on scroll down

fixes #313

Signed-off-by: androidacy-user <opensource@androidacy.com>
master
androidacy-user 1 year ago
parent b9986b30c7
commit eae09bf812

@ -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). ### 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 ## 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. 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**. **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 ## Features
- Download and install modules - Download and install modules
- Manage your own modules - Manage your own modules

@ -23,6 +23,8 @@ import android.util.TypedValue;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.Toast; import android.widget.Toast;
@ -71,6 +73,8 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
private static final int PRECISION = 10000; private static final int PRECISION = 10000;
public static boolean doSetupNowRunning = true; public static boolean doSetupNowRunning = true;
public static boolean doSetupRestarting = false; public static boolean doSetupRestarting = false;
public static List<LocalModuleInfo> localModuleInfoList = new ArrayList<>();
public static List<RepoModule> onlineModuleInfoList = new ArrayList<>();
public final ModuleViewListBuilder moduleViewListBuilder; public final ModuleViewListBuilder moduleViewListBuilder;
public final ModuleViewListBuilder moduleViewListBuilderOnline; public final ModuleViewListBuilder moduleViewListBuilderOnline;
public LinearProgressIndicator progressIndicator; public LinearProgressIndicator progressIndicator;
@ -87,8 +91,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
private CardView searchCard; private CardView searchCard;
private SearchView searchView; private SearchView searchView;
private boolean initMode; private boolean initMode;
public static List<LocalModuleInfo> localModuleInfoList = new ArrayList<>();
public static List<RepoModule> onlineModuleInfoList = new ArrayList<>();
public MainActivity() { public MainActivity() {
this.moduleViewListBuilder = new ModuleViewListBuilder(this); 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) { public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
if (newState != RecyclerView.SCROLL_STATE_IDLE) if (newState != RecyclerView.SCROLL_STATE_IDLE)
MainActivity.this.searchView.clearFocus(); 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); 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); NotificationType.NEED_CAPTCHA_ANDROIDACY.autoAdd(moduleViewListBuilder);
RepoManager.getINSTANCE().updateEnabledStates(); RepoManager.getINSTANCE().updateEnabledStates();
RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilder::appendInstalledModules);
RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilderOnline::appendRemoteModules); RepoManager.getINSTANCE().runAfterUpdate(moduleViewListBuilderOnline::appendRemoteModules);
this.moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter); this.moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter);
this.moduleViewListBuilderOnline.applyTo(moduleListOnline, moduleViewAdapterOnline); 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"); 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 // Check if this is the first launch using prefs and if doSetupRestarting was passed in the intent
SharedPreferences prefs = MainApplication.getSharedPreferences("mmm"); 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 // 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 // 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)) { if (getIntent().getBooleanExtra("doSetupRestarting", false)) {

@ -153,12 +153,9 @@ public class SetupActivity extends FoxActivity implements LanguageActivity {
// Set up the buttons // Set up the buttons
// Setup button // Setup button
BottomNavigationItemView setupButton = view.findViewById(R.id.setup_finish); BottomNavigationItemView setupButton = view.findViewById(R.id.setup_finish);
// enable finish button when user scrolls to the bottom // on clicking setup_agree_eula, enable the setup button if it's checked, if it's not, disable it
findViewById(R.id.setupNestedScrollView).setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { MaterialSwitch agreeEula = view.findViewById(R.id.setup_agree_eula);
if (scrollY > oldScrollY) { agreeEula.setOnCheckedChangeListener((buttonView, isChecked) -> setupButton.setEnabled(isChecked));
setupButton.setEnabled(true);
}
});
setupButton.setOnClickListener(v -> { setupButton.setOnClickListener(v -> {
Timber.i("Setup button clicked"); Timber.i("Setup button clicked");
// get instance of editor // get instance of editor
@ -200,7 +197,7 @@ public class SetupActivity extends FoxActivity implements LanguageActivity {
r.close(); r.close();
Timber.d("Realm transaction committed"); Timber.d("Realm transaction committed");
}); });
editor.putString("last_shown_setup", "v1"); editor.putString("last_shown_setup", "v2");
// Commit the changes // Commit the changes
editor.commit(); editor.commit();
// sleep to allow the realm transaction to finish // sleep to allow the realm transaction to finish

@ -7,6 +7,8 @@ import androidx.annotation.Nullable;
import com.fox2code.mmm.BuildConfig; import com.fox2code.mmm.BuildConfig;
import java.util.Objects;
public enum AndroidacyUtil { public enum AndroidacyUtil {
; ;
public static final String REFERRER = "utm_source=FoxMMM&utm_medium=app"; 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) { static boolean isAndroidacyLink(@NonNull String url, @NonNull Uri uri) {
int i; // Check both string and Uri to mitigate parse exploit 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) { public static boolean isAndroidacyFileUrl(@Nullable String url) {
if (url == null) if (url == null)
return false; 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)) if (url.startsWith(prefix))
return true; return true;
} }

@ -100,7 +100,7 @@ public class BackgroundUpdateChecker extends Worker {
// check if wifi is connected // check if wifi is connected
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Network networkInfo = connectivityManager.getActiveNetwork(); 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"); Timber.w("Background update check: wifi not connected but required");
return; return;
} }
@ -136,7 +136,7 @@ public class BackgroundUpdateChecker extends Worker {
if ("twrp-keep".equals(localModuleInfo.id)) continue; if ("twrp-keep".equals(localModuleInfo.id)) continue;
// exclude all modules with id's stored in the pref pref_background_update_check_excludes // exclude all modules with id's stored in the pref pref_background_update_check_excludes
try { 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; continue;
} catch (Exception ignored) { } catch (Exception ignored) {
} }
@ -213,7 +213,7 @@ public class BackgroundUpdateChecker extends Worker {
public static void onMainActivityCreate(Context context) { public static void onMainActivityCreate(Context context) {
// Refuse to run if first_launch pref is not false // 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; return;
// create notification channel group // create notification channel group
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

@ -57,8 +57,8 @@ public final class ModuleManager extends SyncManager {
} }
protected void scanInternal(@NonNull UpdateListener updateListener) { protected void scanInternal(@NonNull UpdateListener updateListener) {
// if last_shown_setup is not "v1", then refuse to continue // if last_shown_setup is not "v2", then refuse to continue
if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v1")) { if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v2")) {
return; return;
} }
boolean firstScan = this.bootPrefs.getBoolean("mm_first_scan", true); boolean firstScan = this.bootPrefs.getBoolean("mm_first_scan", true);

@ -149,8 +149,8 @@ public final class RepoManager extends SyncManager {
@SuppressWarnings("StatementWithEmptyBody") @SuppressWarnings("StatementWithEmptyBody")
private void populateDefaultCache(RepoData repoData) { private void populateDefaultCache(RepoData repoData) {
// if last_shown_setup is not "v1", them=n refuse to continue // if last_shown_setup is not "v2", them=n refuse to continue
if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v1")) { if (!MainApplication.getSharedPreferences("mmm").getString("last_shown_setup", "").equals("v2")) {
return; return;
} }
// make sure repodata is not null // make sure repodata is not null

@ -61,7 +61,7 @@ public class SentryMain {
}); });
// If first_launch pref is not false, refuse to initialize Sentry // If first_launch pref is not false, refuse to initialize Sentry
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("mmm"); 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; return;
} }
sentryEnabled = sharedPreferences.getBoolean("pref_crash_reporting_enabled", false); sentryEnabled = sharedPreferences.getBoolean("pref_crash_reporting_enabled", false);

@ -48,8 +48,9 @@
android:id="@+id/setup_scroll_down" android:id="@+id/setup_scroll_down"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="2dp" android:layout_marginHorizontal="2dp"
android:text="@string/setup_scroll_down" android:layout_marginVertical="4dp"
android:text="@string/setup_scroll_down_v2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium" /> android:textAppearance="@style/TextAppearance.Material3.BodyMedium" />
<!-- Theme radio select. Options are system, light, dark, black, transparent_light --> <!-- Theme radio select. Options are system, light, dark, black, transparent_light -->
@ -284,14 +285,16 @@
android:text="@string/other_section" android:text="@string/other_section"
android:textAppearance="@android:style/TextAppearance.Material.Headline" /> android:textAppearance="@android:style/TextAppearance.Material.Headline" />
<com.google.android.material.textview.MaterialTextView <com.google.android.material.materialswitch.MaterialSwitch
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:autoLink="web" android:autoLink="web"
android:checked="false"
android:id="@+id/setup_agree_eula"
android:layout_marginHorizontal="2dp" android:layout_marginHorizontal="2dp"
android:layout_marginVertical="4dp" android:layout_marginVertical="4dp"
android:textColorLink="@color/blue" android:textColorLink="@color/blue"
android:text="@string/eula_agree" android:text="@string/eula_agree_v2"
android:textAppearance="@android:style/TextAppearance.Material.Small" android:textAppearance="@android:style/TextAppearance.Material.Small"
android:drawableStart="@drawable/baseline_library_add_check_24" android:drawableStart="@drawable/baseline_library_add_check_24"
android:drawablePadding="8dp" /> android:drawablePadding="8dp" />

@ -5,6 +5,7 @@
<item <item
android:id="@+id/cancel_setup" android:id="@+id/cancel_setup"
android:checked="false" android:checked="false"
android:enabled="true"
android:icon="@drawable/baseline_close_24" android:icon="@drawable/baseline_close_24"
android:title="@string/cancel" android:title="@string/cancel"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />

@ -403,6 +403,7 @@
<string name="showcase_mode_dialogue_message">An app restart is required to enable showcase mode.</string> <string name="showcase_mode_dialogue_message">An app restart is required to enable showcase mode.</string>
<string name="other_section">Other</string> <string name="other_section">Other</string>
<string name="eula_agree">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/)</string> <string name="eula_agree">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/)</string>
<string name="eula_agree_v2">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.</string>
<string name="analytics_desc">Allow us to track app usage and installs. Fully GDPR compliant and uses Matomo, hosted by Androidacy.</string> <string name="analytics_desc">Allow us to track app usage and installs. Fully GDPR compliant and uses Matomo, hosted by Androidacy.</string>
<string name="debug_cat">Debugging</string> <string name="debug_cat">Debugging</string>
<string name="announcements">News and updates</string> <string name="announcements">News and updates</string>
@ -413,4 +414,5 @@
<string name="promo_code_copied">Use the copied code for half off your first month!</string> <string name="promo_code_copied">Use the copied code for half off your first month!</string>
<string name="warning_pls_restart">Please note that some settings may not take effect until you restart the app.</string> <string name="warning_pls_restart">Please note that some settings may not take effect until you restart the app.</string>
<string name="reinstall">Reinstall</string> <string name="reinstall">Reinstall</string>
<string name="setup_scroll_down_v2">To enable the finsih button, scroll to the bottom and acknowledge you have read and agree to the EULA and license(s).</string>
</resources> </resources>

Loading…
Cancel
Save