mirror of
https://github.com/izzy2lost/WeeU.git
synced 2026-07-06 00:19:59 -07:00
Added option to show graphic packs for installed games only
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
#include "GameIconLoader.h"
|
||||
#include "JNIUtils.h"
|
||||
|
||||
class AndroidGameIconLoadedCallback : public GameIconLoadedCallback {
|
||||
class AndroidGameIconLoadedCallback : public GameIconLoadedCallback
|
||||
{
|
||||
jmethodID m_onGameIconLoadedMID;
|
||||
JNIUtils::Scopedjobject m_gameTitleLoadedCallbackObj;
|
||||
|
||||
@@ -18,7 +19,7 @@ class AndroidGameIconLoadedCallback : public GameIconLoadedCallback {
|
||||
JNIUtils::ScopedJNIENV env;
|
||||
jintArray jIconData = env->NewIntArray(width * height);
|
||||
env->SetIntArrayRegion(jIconData, 0, width * height, reinterpret_cast<const jint*>(colors));
|
||||
env->CallVoidMethod(*m_gameTitleLoadedCallbackObj, m_onGameIconLoadedMID, *reinterpret_cast<const jlong*>(&titleId), jIconData, width, height);
|
||||
env->CallVoidMethod(*m_gameTitleLoadedCallbackObj, m_onGameIconLoadedMID, static_cast<jlong>(titleId), jIconData, width, height);
|
||||
env->DeleteLocalRef(jIconData);
|
||||
}
|
||||
};
|
||||
@@ -15,7 +15,7 @@ class AndroidGameTitleLoadedCallback : public GameTitleLoadedCallback {
|
||||
{
|
||||
JNIUtils::ScopedJNIENV env;
|
||||
jstring name = env->NewStringUTF(game.name.c_str());
|
||||
jlong titleId = *reinterpret_cast<const jlong*>(&game.titleId);
|
||||
jlong titleId = static_cast<const jlong>(game.titleId);
|
||||
env->CallVoidMethod(*m_gameTitleLoadedCallbackObj, m_onGameTitleLoadedMID, titleId, name);
|
||||
env->DeleteLocalRef(name);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,17 @@ jobject JNIUtils::createArrayList(JNIEnv* env, const std::vector<jobject>& objec
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
jobject JNIUtils::createJavaLongArrayList(JNIEnv* env, const std::vector<uint64_t>& values)
|
||||
{
|
||||
jclass longClass = env->FindClass("java/lang/Long");
|
||||
jmethodID valueOf = env->GetStaticMethodID(longClass, "valueOf", "(J)Ljava/lang/Long;");
|
||||
std::vector<jobject> valuesJava;
|
||||
for (auto&& value : values)
|
||||
valuesJava.push_back(env->CallStaticObjectMethod(longClass, valueOf, static_cast<jlong>(value)));
|
||||
env->DeleteLocalRef(longClass);
|
||||
return JNIUtils::createArrayList(env, valuesJava);
|
||||
}
|
||||
|
||||
jobject JNIUtils::createJavaStringArrayList(JNIEnv* env, const std::vector<std::wstring>& strings)
|
||||
{
|
||||
jclass arrayListClass = env->FindClass("java/util/ArrayList");
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace JNIUtils
|
||||
|
||||
jobject createJavaStringArrayList(JNIEnv* env, const std::vector<std::wstring>& stringList);
|
||||
|
||||
class ScopedJNIENV {
|
||||
class ScopedJNIENV
|
||||
{
|
||||
public:
|
||||
ScopedJNIENV()
|
||||
{
|
||||
@@ -51,7 +52,8 @@ namespace JNIUtils
|
||||
bool m_threadWasAttached = false;
|
||||
};
|
||||
|
||||
class Scopedjobject {
|
||||
class Scopedjobject
|
||||
{
|
||||
public:
|
||||
Scopedjobject() = default;
|
||||
|
||||
@@ -103,7 +105,8 @@ namespace JNIUtils
|
||||
jobject m_jobject = nullptr;
|
||||
};
|
||||
|
||||
class Scopedjclass {
|
||||
class Scopedjclass
|
||||
{
|
||||
public:
|
||||
Scopedjclass() = default;
|
||||
|
||||
@@ -155,4 +158,5 @@ namespace JNIUtils
|
||||
|
||||
Scopedjobject getEnumValue(JNIEnv* env, const std::string& enumClassName, const std::string& enumName);
|
||||
jobject createArrayList(JNIEnv* env, const std::vector<jobject>& objects);
|
||||
jobject createJavaLongArrayList(JNIEnv* env, const std::vector<uint64_t>& values);
|
||||
} // namespace JNIUtils
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
EmulationState s_emulationState;
|
||||
|
||||
static_assert(sizeof(TitleId) == sizeof(jlong));
|
||||
|
||||
extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, [[maybe_unused]] void* reserved)
|
||||
{
|
||||
JNIUtils::g_jvm = vm;
|
||||
@@ -27,7 +29,7 @@ Java_info_cemu_Cemu_NativeLibrary_setSurfaceSize([[maybe_unused]] JNIEnv* env, [
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_startGame([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jlong title_id)
|
||||
{
|
||||
s_emulationState.startGame(*reinterpret_cast<TitleId*>(&title_id));
|
||||
s_emulationState.startGame(static_cast<TitleId>(title_id));
|
||||
}
|
||||
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
@@ -50,7 +52,7 @@ Java_info_cemu_Cemu_NativeLibrary_setGameIconLoadedCallback(JNIEnv* env, [[maybe
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_requestGameIcon([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jlong title_id)
|
||||
{
|
||||
s_emulationState.requestGameIcon(*reinterpret_cast<TitleId*>(&title_id));
|
||||
s_emulationState.requestGameIcon(static_cast<TitleId>(title_id));
|
||||
}
|
||||
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
@@ -297,10 +299,10 @@ Java_info_cemu_Cemu_NativeLibrary_refreshGraphicPacks([[maybe_unused]] JNIEnv* e
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobject JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_getGraphicPackIdsAndVirtualPaths(JNIEnv* env, [[maybe_unused]] jclass clazz)
|
||||
Java_info_cemu_Cemu_NativeLibrary_getGraphicPackBasicInfos(JNIEnv* env, [[maybe_unused]] jclass clazz)
|
||||
{
|
||||
auto graphicPackInfoClass = env->FindClass("info/cemu/Cemu/NativeLibrary$GraphicPackIdAndVirtualPath");
|
||||
auto graphicPackInfoCtorId = env->GetMethodID(graphicPackInfoClass, "<init>", "(JLjava/lang/String;)V");
|
||||
auto graphicPackInfoClass = env->FindClass("info/cemu/Cemu/NativeLibrary$GraphicPackBasicInfo");
|
||||
auto graphicPackInfoCtorId = env->GetMethodID(graphicPackInfoClass, "<init>", "(JLjava/lang/String;Ljava/util/ArrayList;)V");
|
||||
|
||||
auto graphicPacks = s_emulationState.getGraphicPacks();
|
||||
std::vector<jobject> graphicPackInfoJObjects;
|
||||
@@ -308,7 +310,8 @@ Java_info_cemu_Cemu_NativeLibrary_getGraphicPackIdsAndVirtualPaths(JNIEnv* env,
|
||||
{
|
||||
jstring virtualPath = env->NewStringUTF(graphicPack.second->GetVirtualPath().c_str());
|
||||
jlong id = graphicPack.first;
|
||||
jobject jGraphicPack = env->NewObject(graphicPackInfoClass, graphicPackInfoCtorId, id, virtualPath);
|
||||
jobject titleIds = JNIUtils::createJavaLongArrayList(env, graphicPack.second->GetTitleIds());
|
||||
jobject jGraphicPack = env->NewObject(graphicPackInfoClass, graphicPackInfoCtorId, id, virtualPath, titleIds);
|
||||
graphicPackInfoJObjects.push_back(jGraphicPack);
|
||||
}
|
||||
return JNIUtils::createArrayList(env, graphicPackInfoJObjects);
|
||||
@@ -589,3 +592,9 @@ Java_info_cemu_Cemu_NativeLibrary_onTouchMove([[maybe_unused]] JNIEnv* env, [[ma
|
||||
{
|
||||
s_emulationState.onTouchMove(x, y, isTV);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobject JNICALL
|
||||
Java_info_cemu_Cemu_NativeLibrary_getInstalledGamesTitleIds(JNIEnv* env, [[maybe_unused]] jclass clazz)
|
||||
{
|
||||
return JNIUtils::createJavaLongArrayList(env, CafeTitleList::GetAllTitleIds());
|
||||
}
|
||||
@@ -241,10 +241,12 @@ public class NativeLibrary {
|
||||
|
||||
public static native int getAudioDeviceVolume(boolean tv);
|
||||
|
||||
public record GraphicPackIdAndVirtualPath(long id, String virtualPath) {
|
||||
public record GraphicPackBasicInfo(long id, String virtualPath, ArrayList<Long> titleIds) {
|
||||
}
|
||||
|
||||
public static native ArrayList<GraphicPackIdAndVirtualPath> getGraphicPackIdsAndVirtualPaths();
|
||||
public static native ArrayList<Long> getInstalledGamesTitleIds();
|
||||
|
||||
public static native ArrayList<GraphicPackBasicInfo> getGraphicPackBasicInfos();
|
||||
|
||||
public static class GraphicPackPreset {
|
||||
private final long graphicPackId;
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package info.cemu.Cemu.guibasecomponents;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class FilterableRecyclerViewAdapter<T extends RecyclerViewItem> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
private Predicate<T> predicate;
|
||||
private final List<T> recyclerViewItems = new ArrayList<>();
|
||||
private List<T> filteredRecyclerViewItems = new ArrayList<>();
|
||||
|
||||
public void addRecyclerViewItem(T recyclerViewItem) {
|
||||
recyclerViewItems.add(recyclerViewItem);
|
||||
if (predicate == null || predicate.test(recyclerViewItem)) {
|
||||
filteredRecyclerViewItems.add(recyclerViewItem);
|
||||
notifyItemInserted(filteredRecyclerViewItems.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPredicate(@NonNull Predicate<T> predicate) {
|
||||
this.predicate = predicate;
|
||||
int oldSize = filteredRecyclerViewItems.size();
|
||||
filteredRecyclerViewItems = recyclerViewItems.stream().filter(predicate).collect(Collectors.toList());
|
||||
if (oldSize != filteredRecyclerViewItems.size())
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void clearPredicate() {
|
||||
int oldSize = filteredRecyclerViewItems.size();
|
||||
filteredRecyclerViewItems = new ArrayList<>(recyclerViewItems);
|
||||
if (oldSize != filteredRecyclerViewItems.size())
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
|
||||
return filteredRecyclerViewItems.get(position).onCreateViewHolder(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
filteredRecyclerViewItems.get(position).onBindViewHolder(holder, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return filteredRecyclerViewItems.size();
|
||||
}
|
||||
|
||||
public void clearRecyclerViewItems() {
|
||||
int size = filteredRecyclerViewItems.size();
|
||||
filteredRecyclerViewItems.clear();
|
||||
recyclerViewItems.clear();
|
||||
notifyItemRangeRemoved(0, size);
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -34,11 +34,13 @@ public class GraphicPackItemRecyclerViewItem implements RecyclerViewItem {
|
||||
}
|
||||
|
||||
private final String text;
|
||||
public final boolean hasInstalledTitleId;
|
||||
private final GraphicPackItemType graphicPackItemType;
|
||||
private final OnClickCallback onClickCallback;
|
||||
|
||||
public GraphicPackItemRecyclerViewItem(String text, GraphicPackItemType graphicPackItemType, OnClickCallback onClickCallback) {
|
||||
public GraphicPackItemRecyclerViewItem(String text, boolean hasInstalledTitleId, GraphicPackItemType graphicPackItemType, OnClickCallback onClickCallback) {
|
||||
this.text = text;
|
||||
this.hasInstalledTitleId = hasInstalledTitleId;
|
||||
this.graphicPackItemType = graphicPackItemType;
|
||||
this.onClickCallback = onClickCallback;
|
||||
}
|
||||
|
||||
+1
@@ -63,6 +63,7 @@ public class GraphicPacksFragment extends Fragment {
|
||||
? GraphicPackItemRecyclerViewItem.GraphicPackItemType.SECTION
|
||||
: GraphicPackItemRecyclerViewItem.GraphicPackItemType.GRAPHIC_PACK;
|
||||
GraphicPackItemRecyclerViewItem graphicPackItemRecyclerViewItem = new GraphicPackItemRecyclerViewItem(node.name,
|
||||
node.hasTitleIdInstalled(),
|
||||
graphicPackItemType,
|
||||
() -> {
|
||||
graphicPackCurrentViewModel.setGraphicPackNode(node);
|
||||
|
||||
+35
-9
@@ -40,11 +40,13 @@ public class GraphicPacksRecyclerViewAdapter extends RecyclerView.Adapter<Recycl
|
||||
|
||||
private final String name;
|
||||
private final String path;
|
||||
private final boolean hasInstalledTitleId;
|
||||
private final OnClickCallback onClickCallback;
|
||||
|
||||
private GraphicPackSearchItemRecyclerViewItem(String name, String path, OnClickCallback onClickCallback) {
|
||||
private GraphicPackSearchItemRecyclerViewItem(String name, String path, boolean hasInstalledTitleId, OnClickCallback onClickCallback) {
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
this.hasInstalledTitleId = hasInstalledTitleId;
|
||||
this.onClickCallback = onClickCallback;
|
||||
}
|
||||
|
||||
@@ -67,6 +69,8 @@ public class GraphicPacksRecyclerViewAdapter extends RecyclerView.Adapter<Recycl
|
||||
}
|
||||
|
||||
private final OnItemClickCallback onItemClickCallback;
|
||||
private boolean showInstalledGamesOnly;
|
||||
private String filterText = "";
|
||||
|
||||
public GraphicPacksRecyclerViewAdapter(OnItemClickCallback onItemClickCallback) {
|
||||
this.onItemClickCallback = onItemClickCallback;
|
||||
@@ -75,6 +79,11 @@ public class GraphicPacksRecyclerViewAdapter extends RecyclerView.Adapter<Recycl
|
||||
private List<GraphicPackSearchItemRecyclerViewItem> recyclerViewItems = new ArrayList<>();
|
||||
private List<GraphicPackSearchItemRecyclerViewItem> filteredViewItems = new ArrayList<>();
|
||||
|
||||
public void setShowInstalledOnly(boolean showInstalledGamesOnly) {
|
||||
this.showInstalledGamesOnly = showInstalledGamesOnly;
|
||||
filter();
|
||||
}
|
||||
|
||||
public void setItems(List<GraphicPacksRootFragment.GraphicPackDataNode> graphicPackDataNodes) {
|
||||
clearItems();
|
||||
recyclerViewItems = graphicPackDataNodes.stream()
|
||||
@@ -83,28 +92,44 @@ public class GraphicPacksRecyclerViewAdapter extends RecyclerView.Adapter<Recycl
|
||||
new GraphicPackSearchItemRecyclerViewItem(
|
||||
graphicPackDataNode.getName(),
|
||||
graphicPackDataNode.getPath(),
|
||||
graphicPackDataNode.hasTitleIdInstalled(),
|
||||
() -> GraphicPacksRecyclerViewAdapter.this.onItemClickCallback.onClick(graphicPackDataNode)
|
||||
)).collect(Collectors.toList());
|
||||
filteredViewItems = recyclerViewItems;
|
||||
if (showInstalledGamesOnly)
|
||||
filteredViewItems = filteredViewItems.stream().filter(g -> g.hasInstalledTitleId).collect(Collectors.toList());
|
||||
notifyItemRangeInserted(0, filteredViewItems.size());
|
||||
}
|
||||
|
||||
public void filter(String text) {
|
||||
if (text.isBlank()) {
|
||||
filteredViewItems = recyclerViewItems;
|
||||
notifyDataSetChanged();
|
||||
private void resetFilteredItems() {
|
||||
filteredViewItems = recyclerViewItems;
|
||||
if (showInstalledGamesOnly)
|
||||
filteredViewItems = filteredViewItems.stream().filter(g -> g.hasInstalledTitleId).collect(Collectors.toList());
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setFilterText(String filterText) {
|
||||
this.filterText = filterText;
|
||||
filter();
|
||||
}
|
||||
|
||||
public void filter() {
|
||||
if (filterText.isBlank()) {
|
||||
resetFilteredItems();
|
||||
return;
|
||||
}
|
||||
var stringBuilder = new StringBuilder();
|
||||
String pattern = Arrays.stream(text.split(" "))
|
||||
String pattern = Arrays.stream(filterText.split(" "))
|
||||
.map(s -> "(?=.*" + Pattern.quote(s) + ")")
|
||||
.collect(() -> stringBuilder, StringBuilder::append, StringBuilder::append)
|
||||
.append(".*")
|
||||
.toString();
|
||||
var regex = Pattern.compile(pattern, CASE_INSENSITIVE);
|
||||
filteredViewItems = recyclerViewItems.stream()
|
||||
.filter(g -> regex.matcher(g.path).matches())
|
||||
.collect(Collectors.toList());
|
||||
var filteredData = recyclerViewItems.stream();
|
||||
if (showInstalledGamesOnly)
|
||||
filteredData = filteredData.filter(g -> g.hasInstalledTitleId);
|
||||
filteredData = filteredData.filter(g -> regex.matcher(g.path).matches());
|
||||
filteredViewItems = filteredData.collect(Collectors.toList());
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@@ -112,6 +137,7 @@ public class GraphicPacksRecyclerViewAdapter extends RecyclerView.Adapter<Recycl
|
||||
if (filteredViewItems.isEmpty()) return;
|
||||
int itemsCount = filteredViewItems.size();
|
||||
filteredViewItems.clear();
|
||||
recyclerViewItems.clear();
|
||||
notifyItemRangeRemoved(0, itemsCount);
|
||||
}
|
||||
|
||||
|
||||
+38
-10
@@ -40,6 +40,7 @@ import java.util.Optional;
|
||||
|
||||
import info.cemu.Cemu.R;
|
||||
import info.cemu.Cemu.databinding.GenericRecyclerViewLayoutBinding;
|
||||
import info.cemu.Cemu.guibasecomponents.FilterableRecyclerViewAdapter;
|
||||
import info.cemu.Cemu.guibasecomponents.GenericRecyclerViewAdapter;
|
||||
import info.cemu.Cemu.NativeLibrary;
|
||||
import info.cemu.Cemu.utils.FileUtil;
|
||||
@@ -53,8 +54,13 @@ import okhttp3.ResponseBody;
|
||||
|
||||
public class GraphicPacksRootFragment extends Fragment {
|
||||
public abstract static class GraphicPackNode {
|
||||
protected boolean titleIdInstalled;
|
||||
protected String name;
|
||||
|
||||
public boolean hasTitleIdInstalled() {
|
||||
return titleIdInstalled;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -64,10 +70,11 @@ public class GraphicPacksRootFragment extends Fragment {
|
||||
private final long id;
|
||||
private final String path;
|
||||
|
||||
public GraphicPackDataNode(long id, String name, String path) {
|
||||
public GraphicPackDataNode(long id, String name, String path, boolean hasTitleIdInstalled) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
this.titleIdInstalled = hasTitleIdInstalled;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
@@ -82,8 +89,9 @@ public class GraphicPacksRootFragment extends Fragment {
|
||||
public static class GraphicPackSectionNode extends GraphicPackNode {
|
||||
ArrayList<GraphicPackNode> children = new ArrayList<>();
|
||||
|
||||
public GraphicPackSectionNode(String name) {
|
||||
public GraphicPackSectionNode(String name, boolean hasTitleIdInstalled) {
|
||||
this.name = name;
|
||||
this.titleIdInstalled = hasTitleIdInstalled;
|
||||
}
|
||||
|
||||
public GraphicPackSectionNode() {
|
||||
@@ -96,17 +104,17 @@ public class GraphicPacksRootFragment extends Fragment {
|
||||
private void addGraphicPackDataByTokens(List<String> tokens, GraphicPackDataNode dataNode) {
|
||||
var node = this;
|
||||
for (var token : tokens) {
|
||||
node = getOrAddSectionByToken(token, node.children);
|
||||
node = getOrAddSectionByToken(token, node.children, dataNode.titleIdInstalled);
|
||||
}
|
||||
node.children.add(dataNode);
|
||||
}
|
||||
|
||||
private GraphicPackSectionNode getOrAddSectionByToken(String token, ArrayList<GraphicPackNode> graphicPackNodes) {
|
||||
private GraphicPackSectionNode getOrAddSectionByToken(String token, ArrayList<GraphicPackNode> graphicPackNodes, boolean hasTitleIdInstalled) {
|
||||
var sectionNodeOptional = graphicPackNodes.stream()
|
||||
.filter(g -> (g instanceof GraphicPackSectionNode) && g.name.equals(token))
|
||||
.findFirst();
|
||||
if (!sectionNodeOptional.isPresent()) {
|
||||
var sectionNode = new GraphicPackSectionNode(token);
|
||||
var sectionNode = new GraphicPackSectionNode(token, hasTitleIdInstalled);
|
||||
graphicPackNodes.add(sectionNode);
|
||||
return sectionNode;
|
||||
}
|
||||
@@ -136,8 +144,9 @@ public class GraphicPacksRootFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
private final ArrayList<Long> installedTitleIds = NativeLibrary.getInstalledGamesTitleIds();
|
||||
private final GraphicPackSectionNode graphicPackSectionRootNode = new GraphicPackSectionNode();
|
||||
private final GenericRecyclerViewAdapter genericRecyclerViewAdapter = new GenericRecyclerViewAdapter();
|
||||
private final FilterableRecyclerViewAdapter<GraphicPackItemRecyclerViewItem> genericRecyclerViewAdapter = new FilterableRecyclerViewAdapter<>();
|
||||
private GraphicPackViewModel graphicPackViewModel;
|
||||
private final GraphicPacksRecyclerViewAdapter graphicPacksRecyclerViewAdapter = new GraphicPacksRecyclerViewAdapter(graphicPackDataNode -> {
|
||||
graphicPackViewModel.setGraphicPackNode(graphicPackDataNode);
|
||||
@@ -153,6 +162,8 @@ public class GraphicPacksRootFragment extends Fragment {
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
genericRecyclerViewAdapter.setPredicate(g -> g.hasInstalledTitleId);
|
||||
graphicPacksRecyclerViewAdapter.setShowInstalledOnly(true);
|
||||
fillGraphicPacks();
|
||||
var navController = NavHostFragment.findNavController(GraphicPacksRootFragment.this);
|
||||
graphicPackViewModel = new ViewModelProvider(Objects.requireNonNull(navController.getCurrentBackStackEntry()))
|
||||
@@ -173,13 +184,13 @@ public class GraphicPacksRootFragment extends Fragment {
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
graphicPacksRecyclerViewAdapter.filter(query);
|
||||
graphicPacksRecyclerViewAdapter.setFilterText(query);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
graphicPacksRecyclerViewAdapter.filter(newText);
|
||||
graphicPacksRecyclerViewAdapter.setFilterText(newText);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@@ -198,6 +209,14 @@ public class GraphicPacksRootFragment extends Fragment {
|
||||
});
|
||||
}
|
||||
|
||||
private void showInstalledOnly(boolean installedOnly) {
|
||||
if (installedOnly) {
|
||||
genericRecyclerViewAdapter.setPredicate(g -> g.hasInstalledTitleId);
|
||||
return;
|
||||
}
|
||||
genericRecyclerViewAdapter.clearPredicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemSelected(@NonNull MenuItem menuItem) {
|
||||
if (menuItem.getItemId() == R.id.action_graphic_packs_download && !updateInProgress) {
|
||||
@@ -207,6 +226,13 @@ public class GraphicPacksRootFragment extends Fragment {
|
||||
if (menuItem.getItemId() == R.id.action_graphic_packs_search) {
|
||||
return true;
|
||||
}
|
||||
if (menuItem.getItemId() == R.id.show_installed_games_only) {
|
||||
boolean installedOnly = !menuItem.isChecked();
|
||||
graphicPacksRecyclerViewAdapter.setShowInstalledOnly(installedOnly);
|
||||
menuItem.setChecked(installedOnly);
|
||||
showInstalledOnly(installedOnly);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, getViewLifecycleOwner(), Lifecycle.State.RESUMED);
|
||||
@@ -214,12 +240,13 @@ public class GraphicPacksRootFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void fillGraphicPacks() {
|
||||
var nativeGraphicPacks = NativeLibrary.getGraphicPackIdsAndVirtualPaths();
|
||||
var nativeGraphicPacks = NativeLibrary.getGraphicPackBasicInfos();
|
||||
graphicPackSectionRootNode.clear();
|
||||
List<GraphicPackDataNode> graphicPackDataNodes = new ArrayList<>();
|
||||
nativeGraphicPacks.forEach(graphicPack -> {
|
||||
var tokens = Arrays.asList(graphicPack.virtualPath().split("/"));
|
||||
var dataNode = new GraphicPackDataNode(graphicPack.id(), tokens.get(tokens.size() - 1), graphicPack.virtualPath());
|
||||
boolean hasTitleIdInstalled = graphicPack.titleIds().stream().anyMatch(installedTitleIds::contains);
|
||||
var dataNode = new GraphicPackDataNode(graphicPack.id(), tokens.get(tokens.size() - 1), graphicPack.virtualPath(), hasTitleIdInstalled);
|
||||
graphicPackDataNodes.add(dataNode);
|
||||
graphicPackSectionRootNode.addGraphicPackDataByTokens(tokens.subList(0, tokens.size() - 1), dataNode);
|
||||
});
|
||||
@@ -232,6 +259,7 @@ public class GraphicPacksRootFragment extends Fragment {
|
||||
? GraphicPackItemRecyclerViewItem.GraphicPackItemType.SECTION
|
||||
: GraphicPackItemRecyclerViewItem.GraphicPackItemType.GRAPHIC_PACK;
|
||||
GraphicPackItemRecyclerViewItem graphicPackItemRecyclerViewItem = new GraphicPackItemRecyclerViewItem(node.name,
|
||||
node.hasTitleIdInstalled(),
|
||||
graphicPackItemType,
|
||||
() -> {
|
||||
graphicPackViewModel.setGraphicPackNode(node);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_graphic_packs_search"
|
||||
@@ -15,4 +14,10 @@
|
||||
android:icon="@drawable/ic_download"
|
||||
android:title="@string/download_graphic_packs_title"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/show_installed_games_only"
|
||||
android:checkable="true"
|
||||
android:checked="true"
|
||||
android:title="@string/installed_games_title" />
|
||||
</menu>
|
||||
@@ -163,4 +163,5 @@
|
||||
<string name="edit_inputs">Edit inputs</string>
|
||||
<string name="show_pad">Show pad</string>
|
||||
<string name="replace_tv_with_pad">Replace TV with PAD</string>
|
||||
<string name="installed_games_title">Installed games</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user