Implement Online repo alphabetical sorting. (Implement #8)

pull/27/head
Fox2Code 4 years ago
parent 4ced3453de
commit af02c41c32

@ -3,6 +3,7 @@ package com.fox2code.mmm;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.util.Log; import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
@ -24,6 +25,7 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
public final NotificationType notificationType; public final NotificationType notificationType;
public final Type separator; public final Type separator;
public final int footerPx; public final int footerPx;
public View.OnClickListener onClickListener;
public LocalModuleInfo moduleInfo; public LocalModuleInfo moduleInfo;
public RepoModule repoModule; public RepoModule repoModule;
public int filterLevel; public int filterLevel;
@ -205,21 +207,21 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
} }
public enum Type implements Comparator<ModuleHolder> { public enum Type implements Comparator<ModuleHolder> {
SEPARATOR(R.string.loading, false) { SEPARATOR(R.string.loading, false, false) {
@Override @Override
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
public int compare(ModuleHolder o1, ModuleHolder o2) { public int compare(ModuleHolder o1, ModuleHolder o2) {
return o1.separator.compareTo(o2.separator); return o1.separator.compareTo(o2.separator);
} }
}, },
NOTIFICATION(R.string.loading, true) { NOTIFICATION(R.string.loading, true, false) {
@Override @Override
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
public int compare(ModuleHolder o1, ModuleHolder o2) { public int compare(ModuleHolder o1, ModuleHolder o2) {
return o1.notificationType.compareTo(o2.notificationType); return o1.notificationType.compareTo(o2.notificationType);
} }
}, },
UPDATABLE(R.string.updatable, true) { UPDATABLE(R.string.updatable, true, true) {
@Override @Override
public int compare(ModuleHolder o1, ModuleHolder o2) { public int compare(ModuleHolder o1, ModuleHolder o2) {
int cmp = Integer.compare(o1.filterLevel, o2.filterLevel); int cmp = Integer.compare(o1.filterLevel, o2.filterLevel);
@ -227,7 +229,7 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
return Long.compare(o2.repoModule.lastUpdated, o1.repoModule.lastUpdated); return Long.compare(o2.repoModule.lastUpdated, o1.repoModule.lastUpdated);
} }
}, },
INSTALLED(R.string.installed, true) { INSTALLED(R.string.installed, true, true) {
@Override @Override
public int compare(ModuleHolder o1, ModuleHolder o2) { public int compare(ModuleHolder o1, ModuleHolder o2) {
int cmp = Integer.compare(o1.filterLevel, o2.filterLevel); int cmp = Integer.compare(o1.filterLevel, o2.filterLevel);
@ -235,8 +237,8 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
return o1.getMainModuleName().compareTo(o2.getMainModuleName()); return o1.getMainModuleName().compareTo(o2.getMainModuleName());
} }
}, },
SPECIAL_NOTIFICATIONS(R.string.loading, true), SPECIAL_NOTIFICATIONS(R.string.loading, true, false),
INSTALLABLE(R.string.online_repo, true) { INSTALLABLE(R.string.online_repo, true, true) {
@Override @Override
public int compare(ModuleHolder o1, ModuleHolder o2) { public int compare(ModuleHolder o1, ModuleHolder o2) {
int cmp = Integer.compare(o1.filterLevel, o2.filterLevel); int cmp = Integer.compare(o1.filterLevel, o2.filterLevel);
@ -244,15 +246,17 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
return Long.compare(o2.repoModule.lastUpdated, o1.repoModule.lastUpdated); return Long.compare(o2.repoModule.lastUpdated, o1.repoModule.lastUpdated);
} }
}, },
FOOTER(R.string.loading, false); FOOTER(R.string.loading, false, false);
@StringRes @StringRes
public final int title; public final int title;
public final boolean hasBackground; public final boolean hasBackground;
public final boolean moduleHolder;
Type(@StringRes int title, boolean hasBackground) { Type(@StringRes int title, boolean hasBackground, boolean moduleHolder) {
this.title = title; this.title = title;
this.hasBackground = hasBackground; this.hasBackground = hasBackground;
this.moduleHolder = moduleHolder;
} }
// Note: This method should only be called if both element have the same type // Note: This method should only be called if both element have the same type

@ -0,0 +1,48 @@
package com.fox2code.mmm;
import androidx.annotation.DrawableRes;
import java.util.Comparator;
public enum ModuleSorter implements Comparator<ModuleHolder> {
UPDATE(R.drawable.ic_baseline_update_24) {
@Override
public ModuleSorter next() {
return ALPHA;
}
},
ALPHA(R.drawable.ic_baseline_sort_by_alpha_24) {
@Override
public int compare(ModuleHolder holder1, ModuleHolder holder2) {
ModuleHolder.Type type1 = holder1.getType();
ModuleHolder.Type type2 = holder2.getType();
if (type1 == type2 && type1 == ModuleHolder.Type.INSTALLABLE) {
int compare = Integer.compare(holder1.filterLevel, holder2.filterLevel);
if (compare != 0) return compare;
compare = holder1.getMainModuleName()
.compareTo(holder2.getMainModuleName());
if (compare != 0) return compare;
}
return super.compare(holder1, holder2);
}
@Override
public ModuleSorter next() {
return UPDATE;
}
};
@DrawableRes
public final int icon;
ModuleSorter(int icon) {
this.icon = icon;
}
@Override
public int compare(ModuleHolder holder1, ModuleHolder holder2) {
return holder1.compareTo(holder2);
}
public abstract ModuleSorter next();
}

@ -93,12 +93,14 @@ public final class ModuleViewAdapter extends RecyclerView.Adapter<ModuleViewAdap
// Apply default // Apply default
this.cardView.setOnClickListener(v -> { this.cardView.setOnClickListener(v -> {
ModuleHolder moduleHolder = this.moduleHolder; ModuleHolder moduleHolder = this.moduleHolder;
if (moduleHolder != null && if (moduleHolder != null) {
moduleHolder.notificationType != null) { View.OnClickListener onClickListener = moduleHolder.onClickListener;
View.OnClickListener onClickListener = if (onClickListener != null) {
moduleHolder.notificationType.onClickListener;
if (onClickListener != null)
onClickListener.onClick(v); onClickListener.onClick(v);
} else if (moduleHolder.notificationType != null) {
onClickListener = moduleHolder.notificationType.onClickListener;
if (onClickListener != null) onClickListener.onClick(v);
}
} }
}); });
this.switchMaterial.setEnabled(false); this.switchMaterial.setEnabled(false);
@ -239,9 +241,14 @@ public final class ModuleViewAdapter extends RecyclerView.Adapter<ModuleViewAdap
this.titleText.setTypeface(Typeface.DEFAULT); this.titleText.setTypeface(Typeface.DEFAULT);
} }
} else { } else {
this.buttonAction.setVisibility( if (type == ModuleHolder.Type.SEPARATOR && moduleHolder.filterLevel != 0) {
type == ModuleHolder.Type.NOTIFICATION ? this.buttonAction.setVisibility(View.VISIBLE);
View.VISIBLE : View.GONE); this.buttonAction.setImageResource(moduleHolder.filterLevel);
} else {
this.buttonAction.setVisibility(
type == ModuleHolder.Type.NOTIFICATION ?
View.VISIBLE : View.GONE);
}
this.switchMaterial.setVisibility(View.GONE); this.switchMaterial.setVisibility(View.GONE);
this.creditText.setVisibility(View.GONE); this.creditText.setVisibility(View.GONE);
this.descriptionText.setVisibility(View.GONE); this.descriptionText.setVisibility(View.GONE);
@ -258,11 +265,13 @@ public final class ModuleViewAdapter extends RecyclerView.Adapter<ModuleViewAdap
NotificationType notificationType = moduleHolder.notificationType; NotificationType notificationType = moduleHolder.notificationType;
this.titleText.setText(notificationType.textId); this.titleText.setText(notificationType.textId);
this.buttonAction.setImageResource(notificationType.iconId); this.buttonAction.setImageResource(notificationType.iconId);
this.cardView.setClickable(notificationType.onClickListener != null); this.cardView.setClickable(
notificationType.onClickListener != null ||
moduleHolder.onClickListener != null);
this.titleText.setTypeface(notificationType.special ? this.titleText.setTypeface(notificationType.special ?
Typeface.DEFAULT_BOLD : Typeface.DEFAULT); Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
} else { } else {
this.cardView.setClickable(false); this.cardView.setClickable(moduleHolder.onClickListener != null);
this.titleText.setTypeface(Typeface.DEFAULT); this.titleText.setTypeface(Typeface.DEFAULT);
} }
} }

@ -30,8 +30,9 @@ public class ModuleViewListBuilder {
private final Activity activity; private final Activity activity;
@NonNull @NonNull
private String query = ""; private String query = "";
private boolean noUpdate; private boolean updating;
private int footerPx; private int footerPx;
private ModuleSorter moduleSorter = ModuleSorter.UPDATE;
public ModuleViewListBuilder(Activity activity) { public ModuleViewListBuilder(Activity activity) {
this.activity = activity; this.activity = activity;
@ -94,9 +95,9 @@ public class ModuleViewListBuilder {
} }
} }
public void applyTo(RecyclerView moduleList, ModuleViewAdapter moduleViewAdapter) { public void applyTo(final RecyclerView moduleList,final ModuleViewAdapter moduleViewAdapter) {
if (this.noUpdate) return; if (this.updating) return;
this.noUpdate = true; this.updating = true;
final ArrayList<ModuleHolder> moduleHolders; final ArrayList<ModuleHolder> moduleHolders;
final int newNotificationsLen; final int newNotificationsLen;
try { try {
@ -128,14 +129,27 @@ public class ModuleViewListBuilder {
ModuleHolder.Type type = moduleHolder.getType(); ModuleHolder.Type type = moduleHolder.getType();
if (matchFilter(moduleHolder)) { if (matchFilter(moduleHolder)) {
if (headerTypes.add(type)) { if (headerTypes.add(type)) {
moduleHolders.add(new ModuleHolder(type)); ModuleHolder separator = new ModuleHolder(type);
if (type == ModuleHolder.Type.INSTALLABLE) {
ModuleSorter moduleSorter = this.moduleSorter;
separator.filterLevel = this.moduleSorter.icon;
separator.onClickListener = v -> {
if (this.updating || this.moduleSorter != moduleSorter)
return; // Do not allow spams calls
this.moduleSorter = this.moduleSorter.next();
new Thread(() -> // Apply async
this.applyTo(moduleList, moduleViewAdapter),
"Sorter apply Thread").start();
};
}
moduleHolders.add(separator);
} }
moduleHolders.add(moduleHolder); moduleHolders.add(moduleHolder);
} }
} }
} }
} }
Collections.sort(moduleHolders, ModuleHolder::compareTo); Collections.sort(moduleHolders, this.moduleSorter);
if (this.footerPx != 0) { // Footer is always last if (this.footerPx != 0) { // Footer is always last
moduleHolders.add(new ModuleHolder(this.footerPx)); moduleHolders.add(new ModuleHolder(this.footerPx));
} }
@ -143,7 +157,7 @@ public class ModuleViewListBuilder {
// Build end // Build end
} }
} finally { } finally {
this.noUpdate = false; this.updating = false;
} }
this.activity.runOnUiThread(() -> { this.activity.runOnUiThread(() -> {
final EnumSet<NotificationType> oldNotifications = final EnumSet<NotificationType> oldNotifications =
@ -272,7 +286,6 @@ public class ModuleViewListBuilder {
synchronized (this.updateLock) { synchronized (this.updateLock) {
this.footerPx = footerPx; this.footerPx = footerPx;
} }
this.noUpdate = false;
} }
} }
} }

@ -21,8 +21,8 @@
<item name="android:activityCloseExitAnimation">@*android:anim/slide_out_right</item> --> <item name="android:activityCloseExitAnimation">@*android:anim/slide_out_right</item> -->
<item name="android:windowEnterAnimation">@android:anim/fade_in</item> <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
<item name="android:windowExitAnimation">@android:anim/fade_out</item> <item name="android:windowExitAnimation">@android:anim/fade_out</item>
<item name="android:dialogCornerRadius" tools:targetApi="p">8dp</item> <item name="android:dialogCornerRadius" tools:targetApi="p">@dimen/card_corner_radius</item>
<item name="dialogCornerRadius">8dp</item> <item name="dialogCornerRadius">@dimen/card_corner_radius</item>
</style> </style>
<!-- Base application theme. --> <!-- Base application theme. -->
@ -48,8 +48,8 @@
<item name="android:activityCloseExitAnimation">@*android:anim/slide_out_right</item> --> <item name="android:activityCloseExitAnimation">@*android:anim/slide_out_right</item> -->
<item name="android:windowEnterAnimation">@android:anim/fade_in</item> <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
<item name="android:windowExitAnimation">@android:anim/fade_out</item> <item name="android:windowExitAnimation">@android:anim/fade_out</item>
<item name="android:dialogCornerRadius" tools:targetApi="p">6dp</item> <item name="android:dialogCornerRadius" tools:targetApi="p">@dimen/card_corner_radius</item>
<item name="dialogCornerRadius">6dp</item> <item name="dialogCornerRadius">@dimen/card_corner_radius</item>
</style> </style>
<!-- Base application theme. --> <!-- Base application theme. -->

Loading…
Cancel
Save