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).
_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

@ -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<LocalModuleInfo> localModuleInfoList = new ArrayList<>();
public static List<RepoModule> 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<LocalModuleInfo> localModuleInfoList = new ArrayList<>();
public static List<RepoModule> 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)) {

@ -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

@ -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;
}

@ -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) {

@ -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);

@ -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

@ -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);

@ -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" />
<!-- Theme radio select. Options are system, light, dark, black, transparent_light -->
@ -284,14 +285,16 @@
android:text="@string/other_section"
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_height="wrap_content"
android:autoLink="web"
android:checked="false"
android:id="@+id/setup_agree_eula"
android:layout_marginHorizontal="2dp"
android:layout_marginVertical="4dp"
android:textColorLink="@color/blue"
android:text="@string/eula_agree"
android:text="@string/eula_agree_v2"
android:textAppearance="@android:style/TextAppearance.Material.Small"
android:drawableStart="@drawable/baseline_library_add_check_24"
android:drawablePadding="8dp" />

@ -5,6 +5,7 @@
<item
android:id="@+id/cancel_setup"
android:checked="false"
android:enabled="true"
android:icon="@drawable/baseline_close_24"
android:title="@string/cancel"
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="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_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="debug_cat">Debugging</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="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="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>

Loading…
Cancel
Save