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

UI Improvements to the Main Collection View #405

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

yoshisuga
Copy link
Owner

@yoshisuga yoshisuga commented Jun 3, 2022

Updated the collection view so that:

  • The Recently Played section now scrolls horizontally and supports up to 100 entries.
  • Updated the expanding/collapsing UI so that it can be expanded/collapsed using a +/- button on the right side, instead of a chevron in the header. You can still tap the header to expand/collapse as well.
  • Added prefetching support: images are now cached using prefetching.
  • Changed the font of the header to Bold instead of Heavy

IMG_EF51DC71FBD5-1

yoshisuga added 3 commits June 2, 2022 05:29
… Support collapsing/expanding using a button instead of a chevron in the header
…. Adjusted position of button to accomodate for safe area
@yoshisuga yoshisuga requested a review from ToddLa June 3, 2022 06:00
if (_layoutMode == LayoutList || _layoutCollums == 0)
return layout.itemSize;

CGPoint row_height = [self heightForRowAtIndexPath:indexPath];
return CGSizeMake(layout.itemSize.width, row_height.x + row_height.y);
}

-(UICollectionViewFlowLayout*)layoutForRecentlyPlayedCell {
Copy link
Owner Author

Choose a reason for hiding this comment

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

Not really that happy with this, but this is done to provide a different collection view layout when the layoutMode is LayoutList, and the Recently Played section is displayed.

The Recently Played section adopts the size from the main collection view layout, but not in the LayoutList mode. For the LayoutList mode, I'm just choosing the CELL_SMALL_WIDTH size.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Did having a horz scrolling "list cell" look weird?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe the cells in the Recents view should be a little narrower, like 80% so the user can that you can scroll to the right

{
UICollectionViewFlowLayout* layout = (UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout;
GameInfo* game = [self getGameInfo:indexPath];
// compute the size(s) of a single game. returns: (x = image_height, y = text_height)
Copy link
Owner Author

Choose a reason for hiding this comment

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

Using a CGPoint as a tuple of floats is clever, but this should really be a struct 🙂I left it there for now.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It can't be a struct because we put it in an NSDictionary.

It can be a struct in Swift! But not ObjC

Copy link
Collaborator

@ToddLa ToddLa left a comment

Choose a reason for hiding this comment

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

First pass comments...

Overall pretty good, I would like to remove the ListView special case. It would make the code less complex and consistent. And I don't think ListView is used much, so if Recents looks. Little strange so be it.

let imageUrl = game.gameImageURLs.first else {
continue
}
guard ImageCache.sharedInstance().getImage(imageUrl) == nil else {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should add a NS_SWIFT_NAME so it is just ImageCache.shared

{
UICollectionViewFlowLayout* layout = (UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout;
GameInfo* game = [self getGameInfo:indexPath];
// compute the size(s) of a single game. returns: (x = image_height, y = text_height)
Copy link
Collaborator

Choose a reason for hiding this comment

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

It can't be a struct because we put it in an NSDictionary.

It can be a struct in Swift! But not ObjC

GameInfo* game = [self getGameInfo:indexPath];
// compute the size(s) of a single game. returns: (x = image_height, y = text_height)
-(CGPoint)heightForGameInfo:(GameInfo*)game usingLayout:(nullable UICollectionViewLayout*)layout {
UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm don't understand this, but I bet I will later. Prob related to ListView

if (_layoutMode == LayoutList || _layoutCollums == 0)
return layout.itemSize;

CGPoint row_height = [self heightForRowAtIndexPath:indexPath];
return CGSizeMake(layout.itemSize.width, row_height.x + row_height.y);
}

-(UICollectionViewFlowLayout*)layoutForRecentlyPlayedCell {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Did having a horz scrolling "list cell" look weird?


// get size of an item
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewFlowLayout *)layout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
if ([self hasRecentlyPlayed] && indexPath.section == 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Other code checks for recents by doing a string compare of sectionTitles, this code assumes Recents is always first

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also shouldn't this info be cached like every other row?

[cell setTextInsets:UIEdgeInsetsMake(CELL_INSET_Y, CELL_INSET_X, CELL_INSET_Y, CELL_INSET_X)];

CGFloat image_height = 0.0;
if (_layoutMode != LayoutList && _layoutCollums > 1) {
if (isRecentlyPlayedSection) {
// For the recently played section, don't use the layout-based cached image heights
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can't the special case of the Recents section be in heightForRow atIndexPath, then it will get advantage of being coached too

@@ -137,7 +137,7 @@ class GameInfoCell : UICollectionViewCell {
override func layoutSubviews() {
super.layoutSubviews()

var rect = bounds
var rect = bounds.inset(by: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 32))
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't like the hard coded constants of 30 and 28 should be based on the height of the cell, or line height of the font

ALao what happens on tvOS, do we still have these buttons?

backgroundColor = .clear
contentView.addSubview(collectionView)
collectionView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is This is really better than a A single line

collectionView.frame = contentView.bounds


import UIKit

@objcMembers class RecentlyPlayedCell: UICollectionViewCell {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I have a lot of experience with nested UICollectionView's and I am surprised how well they work, this looks good.

I like how you did not duplicate all the cell setup, and just made this a container for "the same cells" from the parent.

@@ -811,6 +813,10 @@ - (void)filterGameList
}
}

-(BOOL)hasRecentlyPlayed {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should probably be changed to isRecentsSection:IndexPath

This way the assumption of first section (or title name) a
Can live here

@@ -243,11 +243,45 @@ class GameInfoCell : UICollectionViewCell {
// MARK: GameInfoHeader - same as GameInfoCell

class GameInfoHeader : GameInfoCell {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I was expecting this header cell to get used like this!

@@ -330,11 +330,13 @@ - (void)viewDidLoad
// collection view
[self.collectionView registerClass:[GameInfoCell class] forCellWithReuseIdentifier:CELL_IDENTIFIER];
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should add identifiers to GameInfoCell and GameInfoHeader too

@ToddLa
Copy link
Collaborator

ToddLa commented Jun 3, 2022

Oh the nested collection view is gonna need to add some code to handle game controller navigation, aka HandleButtonPress, PV has some nasty nested CVs and the code was gross, M4i it should just be a few lines.

I can look into this if you want @yoshisuga

Should be as easy as adding a handleButtonPress to the RecentsCell, and have the parent CV check if the cell supports habdleButtonPress and pass the button code to it, but only in the left/right/select case.

TVAlertConyrolllrt does a similar thing

public func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
print("ChooseGameController: Start prefetch of images for indexPaths: \(indexPaths)")
for indexPath in indexPaths {
guard let game = getGameInfo(indexPath),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you can just call the gameLoadImage (same thing when setting up cell) and ignore the result

// Copyright © 2022 MAME4iOS Team. All rights reserved.
//

extension ChooseGameController: UICollectionViewDataSourcePrefetching {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am worried that iOS is gonna go crazy pre-loading and we will fire off a lot of net requests, we can't cancel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants