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

Video 8473 mobile grid mode #681

Merged
merged 39 commits into from
May 24, 2022
Merged

Conversation

olipyskoty
Copy link
Contributor

@olipyskoty olipyskoty commented May 24, 2022

Contributing to Twilio

All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under.

  • I acknowledge that all my contributions will be made under the project's license.

Pull Request Details

JIRA link(s):

Description

This PR adds support for grid view on mobile.

giridModeMobile

Burndown

Before review

  • Updated CHANGELOG.md if necessary
  • Added unit tests if necessary
  • Updated affected documentation
  • Verified locally with npm test
  • Manually sanity tested running locally
  • Included screenshot as PR comment (if needed)
  • Ready for review

Before merge

  • Got one or more +1s
  • Re-tested if necessary

@olipyskoty olipyskoty requested review from timmydoza and timrozum May 24, 2022 01:12
left: 0,
height: '100%',
'& .swiper': {
height: '100%',
Copy link
Contributor

Choose a reason for hiding this comment

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

Here I think we need to specify something so that we can see the inactive pagination dots. Digging through devtools, it looks like we can update the --swiper-pagination-bullet-inactive-color CSS variable to be white instead of black. I think adding this here seems to do the trick:

'--swiper-pagination-bullet-inactive-color': 'white',

Then we can see the total number of pages:
image

height: '100%',
},
'& .swiper-slide': {
height: '90%',
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
height: '90%',
height: '90%', // To leave room for the pagination indicators

Comment on lines 75 to 76
videoWidth = '97.5%';
videoHeight = '32%';
Copy link
Contributor

Choose a reason for hiding this comment

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

All the values in this function stood out to me. It looks strange that they aren't more even fractions, like one half (50%), or one third (33.33%). Looks like a little bit was taken off to account for the 0.2em of margin. This pattern seems funny to me, because it's reducing the size of a participant by an amount that's measured by a percentage of its parent container (here it's 2.5% for the height, and 1.33% for the width), to account for a margin that's measured as a fraction of the closest parent element's font-size. The units aren't the same (% vs. em), plus it's not clear how the percentage values were calculated (height is 48% in one spot and 47.5% in another). Here I think it's best to have exact math if we can (especially since a very small change in percentage can result in a visible discrepancy, so precision matters here. For instance, for a container that's 788px tall, there's going to be a difference of about 2.4px depending on whether or not we go with a height of 33.3% or 33.33%. Multiply this difference by three participants and we can see that the stack of three participants is about 7.2px shorter than a single participant with height of 100%).

So I went ahead and changed the values to more exact percentages (100%, 50%, and 33.33%). This broke the layout because the margin makes the participants too large, but it turns out that there's an easy way to accommodate for this:

Instead of margin: 0.2em, we can use padding: 0.2em, which looks just as bad, but with padding, we can tell the browser to take padding into account when we specify a container size. This is done with box-sizing: 'border-box'. More info on what that does here: https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing

So with a new CSS class that has padding: 0.2em and box-sizing: border-box, and the precise percentage values, this layout seems to work out just perfect (literally 🙂 ).

{pages.map((page, i) => (
<SwiperSlide key={i} className={classes.swiperSlide}>
{page.map(participant => (
<div style={getVideoWidth()} key={i}>
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the switch statement. It's very readable, but I couldn't help but think of how it could be refactored.

Since the cases in the switch statement are essentially looking at a numerical value, I got the idea that we could retrieve our percentage values from a map:

  {
    0: '100%',
    1: '50%',
    2: // so on...
  }

And of course, an object with numbers as keys is just an array (and we can use Math.min so the indicies beyond 4 are never accessed):

const height = ['100%', '50%', '33.33%', '50%', '33.33%'][Math.min(remoteParticipantCount, 4)]

For width, there are only two values, which could just be a ternary:

const width = remoteParticipantCount < 3 ? '100%' : '50%'

With all this, a neat refactor could look like this:

              <div
                style={{
                  width: remoteParticipantCount < 3 ? '100%' : '50%',
                  height: ['100%', '50%', '33.33%', '50%', '33.33%'][Math.min(remoteParticipantCount, 4)],
                }}
                key={i}
                className={classes.participantContainer}
              >
                <Participant participant={participant} isLocalParticipant={room!.localParticipant === participant} />
              </div>

Not sure if it's more or less readable, but it's more concise. Let me know what you think!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like it! I do think that the new height property needs a comment though. Took me a second to grasp how it is working. So to save other developers a few seconds of their time, I extracted the styles into its own object with a comment.

const pages: IParticipant[][] = [[]];
pages[0].push(room!.localParticipant);

for (let i = 0; i < participants.length; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

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

participants.length is accessed a few times in this file. It also isn't exactly clear if participants is dealing with remote participants or all participants. An easy fix for readability would be to just save this value to a variable to give it a nice name:

const remoteParticipantCount = participants.length

display: 'flex',
flexWrap: 'wrap',
alignSelf: 'center',
alignContent: 'flex-start',
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if alignContent is needed. Is it doing anything?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doesn't look like it. It was at one point when I was messing around with the CSS, but looks like it is useless now 🙂

fontSize: '12px',
margin: '0',
'& video': {
objectFit: 'cover !important',
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm curious what this one looks like with real people in the room. I think this is what iOS does, but I think it's worth playing around with. It's easy enough to change 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From what I saw, it looks pretty good when there are 1-2 participants and 4 or greater participants. When there are three participants it looks a little odd due to being 100% wide and only 33% tall. It's as if you only get to see a part of the participant's video. Seeing what others think will be helpful though!

Comment on lines 30 to 36
mobileGridView: {
[theme.breakpoints.down('sm')]: {
width: '1.5em',
height: '1.5em',
},
},
},
});
})
Copy link
Contributor

Choose a reason for hiding this comment

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

So I came across this fix accidentally, but it turns out that this change here isn't needed. When box-sizing: border-box is added in MobileGridView, it gets applied to this component as well, which completely changes the size of the element. I think it's because the default style for box-sizing on a div is inherit.

Comment on lines +10 to +18
jest.mock('swiper/react/swiper-react.js', () => ({
Swiper: jest.fn(),
SwiperSlide: jest.fn(),
}));

jest.mock('swiper', () => ({
Pagination: jest.fn(),
}));

Copy link
Contributor

Choose a reason for hiding this comment

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

This is clearly needed to make the tests pass, but I can't understand why 😭 . Everything is shallow rendered. Do you have any ideas?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Jest is failing due to a syntax error: SyntaxError: Cannot use import statement outside a module. Sent you the screenshot in slack.. not entirely sure why mocking the file makes it pass though 🤔

@@ -42,6 +42,7 @@
"react-scripts": "4.0.3",
"rimraf": "3.0.2",
"strip-color": "^0.1.0",
"swiper": "^8.1.5",
Copy link
Contributor

Choose a reason for hiding this comment

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

Are there package-lock changes to commit?

@olipyskoty olipyskoty requested a review from timmydoza May 24, 2022 19:12
Copy link
Contributor

@timrozum timrozum left a comment

Choose a reason for hiding this comment

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

The demo looks great!

@olipyskoty olipyskoty merged commit 80f24e9 into feature/grid-mode May 24, 2022
@olipyskoty olipyskoty deleted the VIDEO-8473-mobile-grid-mode branch May 24, 2022 23:31
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.

3 participants