Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for grouping by artist to beatmap carousel v2 #31801

Merged
merged 9 commits into from
Feb 6, 2025

Conversation

peppy
Copy link
Member

@peppy peppy commented Feb 5, 2025

One of the final pieces to the puzzle – an example of how groups and sets can interact together.

Note that selection behaviour still needs some thought when for instance opening a group via click then hitting left/right arrows, but this isn't any new breakage so I will address separately.

osu.Game.Tests.2025-02-05.at.10.50.50.mp4

@bdach bdach self-requested a review February 5, 2025 13:21
@bdach
Copy link
Collaborator

bdach commented Feb 5, 2025

Additionally, when clicking on a group header when beatmap set headers are also active, the selection doesn't actually change to the first beatmap of the first beatmap set of the group, which leads to you getting scrolled away from the group header that you just clicked:

2025-02-05.14-43-34.mp4

@peppy
Copy link
Member Author

peppy commented Feb 5, 2025

Additionally, when clicking on a group header when beatmap set headers are also active, the selection doesn't actually change to the first beatmap of the first beatmap set of the group, which leads to you getting scrolled away from the group header that you just clicked

Yeah I was leaving this to fix the scroll part later, rather than make it select. In stable it doesn't automatically select so I'm leaning towards keeping that behaviour.

@bdach
Copy link
Collaborator

bdach commented Feb 5, 2025

Yeah I was leaving this to fix the scroll part later, rather than make it select.

Should I be expect the fix to be in this PR or no? To me this is the bigger blocker than the double iteration discussed above I think. This should behave correctly first and foremost and we can optimise later as required.

@pull-request-size pull-request-size bot added size/L and removed size/M labels Feb 6, 2025
@peppy peppy force-pushed the carousel-v2-artist-grouping branch from ba25671 to 6e93790 Compare February 6, 2025 05:53
peppy added 4 commits February 6, 2025 15:09
I had a bit of a struggle getting header traversal logic to work well.
The constraints I had in place were a bit weird:

- Group panels should toggle or potentially fall into the prev/next
  group
- Set panels should just traverse around them

The current method of using `CheckValidForGroupSelection` return type
for traversal did not mesh with the above two cases. Just trust me on
this one since it's quite hard to explain in words.

After some re-thinking, I've gone with a simpler approach with one
important change to UX: Now when group traversing with a beatmap set
header currently keyboard focused, the first operation will be to reset
keyboard selection to the selected beatmap, rather than traverse.

I find this non-offensive – at most it means a user will need to press
their group traversal key one extra time.

I've also changed group headers to always toggle expansion when doing
group traversal with them selected.

To make all this work, the meaning of `Activation` has changed somewhat.
It is now the primary path for carousel implementations to change
selection of an item. It is what the `Drawable` panels call when they
are clicked.

Selection changes are not performed implicitly by `Carousel` – an
implementation should decide when it actually wants to change the
selection, usually in `HandleItemActivated`.

Having less things mutating `CurrentSelection` is better in my eyes, as
we see this variable as only being mutated internally when utmost
required (ie the user has requested the change). With this change,
`CurrentSelection` can no longer become of a non-`T` type (in the
beatmap carousel implementation at least).

This might pave a path forward for making `CurrentSelection` typed, but
that comes with a few other concerns so I'll look at that as a
follow-up.
@peppy peppy force-pushed the carousel-v2-artist-grouping branch from 6e93790 to 024fbde Compare February 6, 2025 08:04
@pull-request-size pull-request-size bot added size/XL and removed size/L labels Feb 6, 2025
@peppy peppy requested a review from bdach February 6, 2025 08:23
@peppy
Copy link
Member Author

peppy commented Feb 6, 2025

Apologies for the size increase of this PR, but it's going to be hard to split out the new logic (and a lot is tests anyway).

Please read over 024fbde carefully.

@peppy
Copy link
Member Author

peppy commented Feb 6, 2025

@frenzibyte could you also check the changes to see if they work okay in your eyes?

@frenzibyte frenzibyte self-requested a review February 6, 2025 09:01
Copy link
Member

@frenzibyte frenzibyte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside from a general thought I had on part of the current structure of carousel (which is, again, not a blocker), the changes in this PR look pretty sane to my eyes.

Comment on lines +186 to +197
case BeatmapSetInfo set:
// Case where there are set headers, header should be visible
// and items should use the set's expanded state.
i.IsVisible = true;
setExpansionStateOfSetItems(set, i.IsExpanded);
break;

default:
// Case where there are no set headers, all items should be visible.
if (!grouping.BeatmapSetsGroupedTogether)
i.IsVisible = true;
break;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment does not mean to block this PR or request changes in any way shape or form, but is basically a general question and fruit for thought.

Seeing this kind of logic really makes me wonder just how bad would it really be if CarouselItem acts as a basic tree model and this logic becomes recursive instead, removing the need for BeatmapSetsGroupedTogether or manual lookup of the containing group in which a beatmap is at.

I can imagine multiple things being tackled with this idea of a tree:

  • Removing the newly introduced CarouselItem.DepthLayer and/or computing it appropriately based on how deep an item is in the hierarchy.
  • Making the constant X offsets applied in design PR become based on the CarouselItem's depth in the hierarchy instead.
  • Allowing BeatmapCarousel to easily determine whether to choose a small beatmap difficulty panel or a "standalone" beatmap single-diff panel, by simply checking whether the beatmap carousel item is a parent of a BeatmapSetPanel model or a GroupDefinition/no parent.

Of course all three points above can be solved by totally different means, but I found a basic tree model approach to be the natural solution, so I may as well raise it up for discussion.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's something i've considered and will try in the future. It has potential to optimise things if we hit a brick wall with the current structure.

So far the code complexity with flat list is very manageable and I'm not sure it can be maintained with tree.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference I was party to an irl conversation on this exact question in December and my vague unsubstantiated feeling was also that a flat list was going to be more manageable than a hierarchical model - flat list does make some things more complicated, but also it will make some less so (e.g. I don't really want to think how the management of Y would look position if the backing model was no longer a flat list but hierarchical instead).

So far I see no strong indicators to change my opinion on this.

@bdach
Copy link
Collaborator

bdach commented Feb 6, 2025

Code-wise this seems okay, but I cannot hold myself from remarking on how little sense the "set/group traversal" operation - as in, left/right arrow - makes to me at this stage. It basically only seems to do the sensible thing I expect it to do when there is no keyboard selection.

When there is keyboard selection, many completely different things can happen:

  • If the keyboard-selected item is a group header, it gets expanded/collapsed.
  • If the keyboard-selected item is the set header of a currently-selected beatmap, the selection changes to the first beatmap of the set.
  • If the keyboard-selected item is a non-selected beatmap in the same set as the currently-selected beatmap, the selection changes to match keyboard selection.
  • If the keyboard-selected item is a non-selected set header, the selection changes to the first beatmap of that set.

Now that I typed it all up, I guess that makes "traversal" equivalent to... selection/enter? but only specifically when keyboard selection is present? That feels really weird to me. Unless this is all matching weird stable UX at which point I will have to concede to precedent.

In addition, the issue mentioned earlier about how the carousel can scroll away from what the user selected still does not seem to be resolved. Should I expect it to be? I didn't get an answer to #31801 (comment).

@peppy
Copy link
Member Author

peppy commented Feb 6, 2025

Fixing the scrolling will be a separate endeavour.

Group traversal to me follows a simple rule: in the normal case you are using it to traverse beatmap sets (or difficulties where not grouping by sets). It should traverse disregarding other grouping.

When you interrupt it, in the case it's not at a difficulty, it will mostly behave like a "select" press until it reverts to the standard behaviour.

This is how stable works, and personally I think it feels good once you are used to it.

The only thing i'm neutral on is the changed behaviour when at a set header because this case doesn't exist in stable and is a bit undefined. The resultant behaviour from this PR makes it align with "just being a select press" if you can get behind that.

Copy link
Collaborator

@bdach bdach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in that case there's only one thing left to do I guess

@bdach bdach merged commit 91bc23e into ppy:master Feb 6, 2025
8 of 10 checks passed
@peppy peppy deleted the carousel-v2-artist-grouping branch February 10, 2025 04:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants