From 329fa7a158ef9667dec934c2273533e72012a529 Mon Sep 17 00:00:00 2001 From: gabriel <gabriel> Date: Tue, 27 Feb 2024 16:28:48 -0400 Subject: [PATCH] Reimplement ishan game dialog. --- src/pandroid/app/build.gradle.kts | 1 - .../pandroid/app/base/GameAboutDialog.java | 43 +++++++ .../pandroid/app/main/GamesFragment.java | 8 ++ .../pandroid/view/gamesgrid/GameAdapter.java | 13 ++ .../view/gamesgrid/GamesGridView.java | 19 ++- .../pandroid/view/gamesgrid/ItemHolder.java | 39 ------ .../src/main/res/layout/dialog_game_about.xml | 121 ++++++++++++++++++ .../app/src/main/res/layout/game_dialog.xml | 99 -------------- .../app/src/main/res/values/strings.xml | 2 + 9 files changed, 205 insertions(+), 140 deletions(-) create mode 100644 src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/base/GameAboutDialog.java create mode 100644 src/pandroid/app/src/main/res/layout/dialog_game_about.xml delete mode 100644 src/pandroid/app/src/main/res/layout/game_dialog.xml diff --git a/src/pandroid/app/build.gradle.kts b/src/pandroid/app/build.gradle.kts index f37b5dba..201d5db1 100644 --- a/src/pandroid/app/build.gradle.kts +++ b/src/pandroid/app/build.gradle.kts @@ -53,5 +53,4 @@ dependencies { implementation("androidx.preference:preference:1.2.1") implementation("androidx.constraintlayout:constraintlayout:2.1.4") implementation("com.google.code.gson:gson:2.10.1") - implementation("com.google.android.flexbox:flexbox:3.0.0") } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/base/GameAboutDialog.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/base/GameAboutDialog.java new file mode 100644 index 00000000..ca2c3ca4 --- /dev/null +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/base/GameAboutDialog.java @@ -0,0 +1,43 @@ +package com.panda3ds.pandroid.app.base; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.google.android.material.bottomsheet.BottomSheetDialog; +import com.panda3ds.pandroid.R; +import com.panda3ds.pandroid.data.game.GameMetadata; +import com.panda3ds.pandroid.utils.FileUtils; +import com.panda3ds.pandroid.utils.GameUtils; +import com.panda3ds.pandroid.view.gamesgrid.GameIconView; + +public class GameAboutDialog extends BottomSheetDialog { + public GameAboutDialog(@NonNull Context context, GameMetadata game) { + super(context); + View content = LayoutInflater.from(context).inflate(R.layout.dialog_game_about, null, false); + setContentView(content); + + ((GameIconView)content.findViewById(R.id.game_icon)).setImageBitmap(game.getIcon()); + ((TextView)content.findViewById(R.id.game_title)).setText(game.getTitle()); + ((TextView)content.findViewById(R.id.game_publisher)).setText(game.getPublisher()); + ((TextView)content.findViewById(R.id.region)).setText(game.getRegions()[0].name()); + ((TextView)content.findViewById(R.id.directory)).setText(FileUtils.obtainUri(game.getRealPath()).getPath()); + + content.findViewById(R.id.play).setOnClickListener(v -> { + dismiss(); + GameUtils.launch(getContext(), game); + }); + + if (game.getRomPath().startsWith("folder:")){ + content.findViewById(R.id.remove).setVisibility(View.GONE); + } else { + content.findViewById(R.id.remove).setOnClickListener(v-> { + dismiss(); + GameUtils.removeGame(game); + }); + } + } +} diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/main/GamesFragment.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/main/GamesFragment.java index a5c673f5..337780b0 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/main/GamesFragment.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/main/GamesFragment.java @@ -14,6 +14,7 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; import com.panda3ds.pandroid.R; +import com.panda3ds.pandroid.app.base.GameAboutDialog; import com.panda3ds.pandroid.app.base.LoadingAlertDialog; import com.panda3ds.pandroid.data.game.GameMetadata; import com.panda3ds.pandroid.lang.Task; @@ -38,6 +39,13 @@ public class GamesFragment extends Fragment implements ActivityResultCallback<Ur public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); gameListView = view.findViewById(R.id.games); + gameListView.setItemLongClick((game)->{ + GameAboutDialog dialog = new GameAboutDialog(requireActivity(), game); + dialog.setOnDismissListener((x)-> { + gameListView.setGameList(GameUtils.getGames()); + }); + dialog.show(); + }); view.findViewById(R.id.add_rom).setOnClickListener((v) -> pickFileRequest.launch(new String[] {"*/*"})); } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/GameAdapter.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/GameAdapter.java index 1a3febd4..3a07fbf7 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/GameAdapter.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/GameAdapter.java @@ -8,12 +8,20 @@ import androidx.recyclerview.widget.RecyclerView; import com.panda3ds.pandroid.R; import com.panda3ds.pandroid.data.game.GameMetadata; +import com.panda3ds.pandroid.lang.Function; import java.util.ArrayList; import java.util.List; class GameAdapter extends RecyclerView.Adapter<ItemHolder> { private final ArrayList<GameMetadata> games = new ArrayList<>(); + private final Function<GameMetadata> clickListener; + private final Function<GameMetadata> longClickListener; + + GameAdapter(Function<GameMetadata> clickListener, Function<GameMetadata> longClickListener) { + this.clickListener = clickListener; + this.longClickListener = longClickListener; + } @NonNull @Override @@ -23,6 +31,11 @@ class GameAdapter extends RecyclerView.Adapter<ItemHolder> { @Override public void onBindViewHolder(@NonNull ItemHolder holder, int position) { + holder.itemView.setOnClickListener(v -> clickListener.run(games.get(position))); + holder.itemView.setOnLongClickListener(v -> { + longClickListener.run(games.get(position)); + return false; + }); holder.apply(games.get(position)); } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/GamesGridView.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/GamesGridView.java index 24e65e2f..2e09d966 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/GamesGridView.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/GamesGridView.java @@ -8,12 +8,15 @@ import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; import com.panda3ds.pandroid.data.game.GameMetadata; +import com.panda3ds.pandroid.lang.Function; +import com.panda3ds.pandroid.utils.GameUtils; import com.panda3ds.pandroid.view.recycler.AutoFitGridLayout; import java.util.List; public class GamesGridView extends RecyclerView { private final GameAdapter adapter; + private Function<GameMetadata> longClickListener = null; public GamesGridView(@NonNull Context context) { this(context, null); @@ -26,7 +29,21 @@ public class GamesGridView extends RecyclerView { public GamesGridView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setLayoutManager(new AutoFitGridLayout(getContext(), 170)); - setAdapter(adapter = new GameAdapter()); + setAdapter(adapter = new GameAdapter(this::onClickGame, this::onLongClickGame)); + } + + public void setItemLongClick(Function<GameMetadata> longClickListener) { + this.longClickListener = longClickListener; + } + + private void onClickGame(GameMetadata game) { + GameUtils.launch(getContext(), game); + } + + private void onLongClickGame(GameMetadata game) { + if (longClickListener != null){ + longClickListener.run(game); + } } public void setGameList(List<GameMetadata> games) { diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/ItemHolder.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/ItemHolder.java index 8f5c1014..2d55964f 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/ItemHolder.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/ItemHolder.java @@ -5,14 +5,8 @@ import android.view.View; import androidx.annotation.NonNull; import androidx.appcompat.widget.AppCompatTextView; import androidx.recyclerview.widget.RecyclerView; -import android.widget.TextView; -import com.google.android.material.imageview.ShapeableImageView; -import com.google.android.material.button.MaterialButton; -import com.google.android.material.bottomsheet.BottomSheetDialog; - import com.panda3ds.pandroid.R; import com.panda3ds.pandroid.data.game.GameMetadata; -import com.panda3ds.pandroid.utils.GameUtils; class ItemHolder extends RecyclerView.ViewHolder { public ItemHolder(@NonNull View itemView) { @@ -26,38 +20,5 @@ class ItemHolder extends RecyclerView.ViewHolder { .setImageBitmap(game.getIcon()); ((AppCompatTextView) itemView.findViewById(R.id.description)) .setText(game.getPublisher()); - - itemView.setOnLongClickListener((v) -> { - showBottomSheet(game); - return true; // Return true to consume the long click event - }); - - itemView.setOnClickListener((v) -> { - GameUtils.launch(v.getContext(), game); - }); - } - private void showBottomSheet(GameMetadata game) { - BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(itemView.getContext()); - View bottomSheetView = View.inflate(itemView.getContext(), R.layout.game_dialog, null); - bottomSheetDialog.setContentView(bottomSheetView); - - TextView gameTitleTextView = bottomSheetView.findViewById(R.id.game_title); - gameTitleTextView.setText(game.getTitle()); - - ShapeableImageView gameIconImageView = bottomSheetView.findViewById(R.id.game_icon); - gameIconImageView.setImageBitmap(game.getIcon()); - - TextView gamePublisherTextView = bottomSheetView.findViewById(R.id.game_author); - gamePublisherTextView.setText(game.getPublisher()); - - MaterialButton gamePlayButton = bottomSheetView.findViewById(R.id.game_play); - gamePlayButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - GameUtils.launch(v.getContext(), game); - } - }); - - bottomSheetDialog.show(); } } diff --git a/src/pandroid/app/src/main/res/layout/dialog_game_about.xml b/src/pandroid/app/src/main/res/layout/dialog_game_about.xml new file mode 100644 index 00000000..1d4b9017 --- /dev/null +++ b/src/pandroid/app/src/main/res/layout/dialog_game_about.xml @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:gravity="top|center" + android:padding="10dp" + android:background="@drawable/alert_dialog_background"> + + <View + android:layout_width="128dp" + android:layout_height="4dp" + android:background="?colorSurfaceVariant" + android:layout_margin="5dp"/> + + <com.google.android.material.card.MaterialCardView + android:layout_width="128dp" + android:layout_height="128dp" + app:cardCornerRadius="18dp" + android:layout_marginTop="10dp" + app:strokeWidth="0dp"> + <com.panda3ds.pandroid.view.gamesgrid.GameIconView + android:id="@+id/game_icon" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="?colorSurfaceVariant"/> + </com.google.android.material.card.MaterialCardView> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:gravity="center" + android:paddingHorizontal="30dp"> + + <TextView + android:id="@+id/game_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/app_name" + android:textSize="18sp" + android:layout_marginTop="20dp" + android:gravity="center" + android:textStyle="bold"/> + + <TextView + android:id="@+id/game_publisher" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/app_name" + android:textSize="14sp" + android:alpha="0.7"/> + + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/region" + android:textAllCaps="true" + android:textSize="12sp" + android:textStyle="bold" + android:layout_marginTop="20dp"/> + + <TextView + android:id="@+id/region" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/app_name" + android:alpha="0.76" + android:textSize="15sp"/> + + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/directory" + android:textAllCaps="true" + android:textSize="12sp" + android:textStyle="bold" + android:layout_marginTop="20dp"/> + + <TextView + android:id="@+id/directory" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/app_name" + android:alpha="0.76" + android:textSize="15sp"/> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:paddingHorizontal="10dp" + android:layout_marginVertical="10dp" + android:gravity="end|center"> + + <com.google.android.material.button.MaterialButton + android:id="@+id/remove" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/remove" + app:icon="@drawable/ic_delete" + app:iconTint="?colorOnSurfaceVariant" + android:textColor="?colorOnSurfaceVariant" + android:backgroundTint="?colorSurfaceVariant" + android:layout_marginHorizontal="10dp"/> + + <com.google.android.material.button.MaterialButton + android:id="@+id/play" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/play" + app:icon="@drawable/ic_play" + app:iconTint="?colorOnPrimary"/> + + </LinearLayout> +</LinearLayout> diff --git a/src/pandroid/app/src/main/res/layout/game_dialog.xml b/src/pandroid/app/src/main/res/layout/game_dialog.xml deleted file mode 100644 index 3a3b8816..00000000 --- a/src/pandroid/app/src/main/res/layout/game_dialog.xml +++ /dev/null @@ -1,99 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout 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" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <com.google.android.material.bottomsheet.BottomSheetDragHandleView - android:id="@+id/drag_handle" - android:layout_width="match_parent" - android:layout_height="wrap_content"/> - - <androidx.constraintlayout.widget.ConstraintLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:nextFocusRight="@id/game_play" - android:paddingHorizontal="16dp" - android:paddingBottom="8dp"> - - <com.google.android.material.imageview.ShapeableImageView - android:id="@+id/game_icon" - android:layout_width="140dp" - android:layout_height="140dp" - android:contentDescription="icon" - android:focusable="false" - app:layout_constraintBottom_toBottomOf="@+id/constraintLayout" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="@+id/constraintLayout" - app:shapeAppearance="?attr/shapeAppearanceCornerLarge" /> - - <androidx.constraintlayout.widget.ConstraintLayout - android:id="@+id/constraintLayout" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginStart="16dp" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHeight_min="140dp" - app:layout_constraintStart_toEndOf="@id/game_icon" - app:layout_constraintTop_toTopOf="parent"> - - <TextView - android:id="@+id/game_title" - style="?attr/textAppearanceTitleMedium" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAlignment="viewStart" - android:textSize="20sp" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - tools:text="Pokemon X" /> - - <TextView - android:id="@+id/game_author" - style="?attr/textAppearanceBodyMedium" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - app:layout_constraintStart_toStartOf="@id/game_title" - app:layout_constraintTop_toBottomOf="@id/game_title" - tools:text="Nintendo 3ds" /> - - </androidx.constraintlayout.widget.ConstraintLayout> - - <com.google.android.flexbox.FlexboxLayout - android:id="@+id/flexboxGeneral" - style="@style/ThemeOverlay.Material3.Button.IconButton.Filled.Tonal" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginTop="16dp" - app:flexWrap="nowrap" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/game_icon" - app:layout_constraintVertical_bias="1"> - - <com.google.android.material.button.MaterialButton - android:id="@+id/game_play" - style="@style/Widget.Material3.Button.Icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:contentDescription="play" - android:focusedByDefault="true" - android:text="Play" - app:icon="@drawable/ic_play" - app:layout_flexGrow="1" - app:layout_maxWidth="140dp"/> - - <com.google.android.material.button.MaterialButton - android:id="@+id/game_settings" - style="@style/Widget.Material3.Button.IconButton.Filled.Tonal" - android:layout_width="48dp" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:contentDescription="settings" - app:icon="@drawable/ic_settings"/> - - </com.google.android.flexbox.FlexboxLayout> - </androidx.constraintlayout.widget.ConstraintLayout> -</LinearLayout> diff --git a/src/pandroid/app/src/main/res/values/strings.xml b/src/pandroid/app/src/main/res/values/strings.xml index aa5b742e..6684badb 100644 --- a/src/pandroid/app/src/main/res/values/strings.xml +++ b/src/pandroid/app/src/main/res/values/strings.xml @@ -81,4 +81,6 @@ <string name="games_count_f">%d Games</string> <string name="directory">Directory</string> <string name="remove">Remove</string> + <string name="play">Play</string> + <string name="region">Region</string> </resources>