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

Finalize grid mode #699

Merged
merged 17 commits into from Jun 10, 2022
Merged

Finalize grid mode #699

merged 17 commits into from Jun 10, 2022

Conversation

olipyskoty
Copy link
Contributor

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 makes some final changes to the grid view behavior:

  • Removes white borders (no changes made to dominant speaker border)
  • Changes the max grid participants options to 4, 9, 16, 25
  • Makes grid view the default view
  • Updates naming from "Collaboration Mode" and "Grid Mode" to Collaboration View and Grid View to be consistent with iOS
  • Updates screenshare behavior so that users will return to whatever room view they were using prior to screenshare starting
  • Changes pagination behavior so that each page has unique participants and none carry over from a previous page

newWayPagination

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 a review from timmydoza June 8, 2022 22:23
<CollaborationViewIcon style={{ fill: '#707578', width: '0.9em' }} />
) : (
<GridViewIcon style={{ fill: '#707578', width: '0.9em' }} />
)}
</IconContainer>
<Typography variant="body1">{isGridModeActive ? 'Collaboration Mode' : 'Grid Mode'}</Typography>
<Typography variant="body1">{isGridViewActive ? 'Collaboration View' : 'Grid View'}</Typography>
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
<Typography variant="body1">{isGridViewActive ? 'Collaboration View' : 'Grid View'}</Typography>
<Typography variant="body1">{isGridViewActive ? 'Presentation View' : 'Grid View'}</Typography>


const CONTAINER_GUTTER = '50px';

const useStyles = makeStyles({
container: {
background: '#121C2D',
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 used in a few spots, so it would probably be good to add to the theme.

@@ -116,7 +116,7 @@ const useStyles = makeStyles((theme: Theme) =>
bottom: 0,
left: 0,
},
typeography: {
typography: {
Copy link
Contributor

Choose a reason for hiding this comment

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

🙂

margin: `${GRID_MODE_MARGIN} - borderWidth`,
},
mobileGridMode: {
gridView: {
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think about adding a border-radius of, say, 6px or 8px? Without the white border in grid view (which I think looks great), the corners feel a touch too sharp. I think we could even have presentation view use the same border-radius of 6 or 8px. Or presentation view could stay at 4px. It'll take some playing with but I think that the grid view corners could be more rounded. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, not sure why I haven't noticed this before, but I think the identity class could use padding of padding: 0.18em 0.3em 0.18em 0;. Without this, the microphone icon doesn't feel exactly centered. What do 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.

Yeah I think that all looks a lot better!

@@ -34,14 +34,38 @@ const useStyles = makeStyles((theme: Theme) => {
};
});

/**
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice comments!

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, but it should be "presentation view" here.

@@ -12,5 +12,5 @@ export const SELECTED_VIDEO_INPUT_KEY = 'TwilioVideoApp-selectedVideoInput';
// This is used to store the current background settings in localStorage
export const SELECTED_BACKGROUND_SETTINGS_KEY = 'TwilioVideoApp-selectedBackgroundSettings';

export const GRID_MODE_ASPECT_RATIO = 9 / 16; // 16:9
export const GRID_MODE_MARGIN = 3;
export const GRID_VIEW_ASPECT_RATIO = 9 / 16; // 16:9
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, we'll need to think about this one. Not sure this needs to be solved in this PR, I but changing this value here doesn't actually change the aspect ratio. I think the fix might be easy though: the container class in ParticipantInfo doesn't need to enforce an aspect ratio in grid view with padding-top. Instead it just needs height: 100%.

I realize this is out of scope for this PR, but it had never occured to me to try to change this constant before 😆

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay cool, we can look at this later!

},
mobileGridMode: {
gridView: {
background: '#121C2D',
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'm thinking that we might want a black (#000) background for the participants. This is in case we have a participant whose video is a different aspect ratio than its container (like a mobile user).

Here's an example (this isn't what a mobile user would look like but you get the idea):
image

@@ -16,16 +16,10 @@ export function usePagination(participants: Participant[]) {
}
}, [isBeyondLastPage, totalPages]);

let paginatedParticipants;
let paginatedParticipants = participants.slice(
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't make a huge difference, but I'm wondering if this hook should be moved into the GridView directory. Just so people don't think it should be used with MobileGridView pagination.

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 think that's a good idea!

@@ -72,23 +74,28 @@ const useStyles = makeStyles({
alignItems: 'center',
justifyContent: 'center',
},
lastPage: {
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.

What do you think about centered here? In some cases, flex-start makes the participants on the last page higher than all the rest, like this:

centered

I think centered participants on the last page might be ideal, but I'm curious what you think? It also has the advantage of getting rid of all the lastPage stuff.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep sounds good. I really didn't have an opinion here, and I didn't know what was best. So centering it is!

rerender({ screenShareParticipant: {} } as any);
expect(mockSetIsGridViewActive).toBeCalledWith(false);
// screenshare ends
rerender({ screenShareParticipant: {} } as any);
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
rerender({ screenShareParticipant: {} } as any);
rerender({ screenShareParticipant: undefined } as any);

Should correctly end screen share.

expect(mockSetIsGridViewActive).toBeCalledWith(true);
});

it('should not reactivate grid view when screenshare ends if grid view was active before another participant started screensharing', () => {
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
it('should not reactivate grid view when screenshare ends if grid view was active before another participant started screensharing', () => {
it('should not activate grid view when screenshare ends if presentation view was active before another participant started screensharing', () => {

Comment on lines 121 to 124
jest.spyOn(React, 'useRef').mockReturnValue({
current: false,
});

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
jest.spyOn(React, 'useRef').mockReturnValue({
current: false,
});

Same as above.

Comment on lines 97 to 100
jest.spyOn(React, 'useRef').mockReturnValue({
current: true,
});

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
jest.spyOn(React, 'useRef').mockReturnValue({
current: true,
});

I don't think this is needed. Here I think we want to test the real functionality of useRef, and not a mocked return value. But also, this code doesn't do much anyway because the mocked value is overwritten by the first useEffect in useSetPresentaionViewOnScreenShare()

Comment on lines 135 to 139
expect(mockSetIsGridViewActive).not.toBeCalled();
rerender({ screenShareParticipant: {} } as any);
expect(mockSetIsGridViewActive).toBeCalledWith(false);
// mockSetIsGridViewActive should only be called once with "false" since we're not reactivating grid mode
expect(mockSetIsGridViewActive).toBeCalledTimes(1);
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 comments from the test above. But also, I think we need to rerender the hook once more to end the screensharing:

    expect(mockSetIsGridViewActive).not.toBeCalled();
    // screenshare starts
    rerender({ screenShareParticipant: {} } as any);
    expect(mockSetIsGridViewActive).toBeCalledWith(false);

    // screenshare ends
    rerender({ screenShareParticipant: undefined } as any);

    // mockSetIsGridViewActive should only be called once with "false" since we're not reactivating grid mode
    expect(mockSetIsGridViewActive).toBeCalledTimes(1);

// mockSetIsGridViewActive should only be called once with "false" since we're not reactivating grid mode
expect(mockSetIsGridViewActive).toBeCalledTimes(1);
});

Copy link
Contributor

Choose a reason for hiding this comment

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

Once more test could be nice to test that presentation mode is not activated if the user switches to grid mode during a screenshare:

  it('should not activate presentation view when screenshare ends if presentation view was active before screensharing, but the user switched to grid view during the screenshare', () => {
    const screenShareParticipant = {};
    const room = { localParticipant: {} } as any;

    const { rerender } = renderHook(
      ({ screenShareParticipant, isGridViewActive }) =>
        useSetCollaborationViewOnScreenShare(screenShareParticipant, room, mockSetIsGridViewActive, isGridViewActive),
      { initialProps: { screenShareParticipant: undefined, isGridViewActive: false } }
    );

    expect(mockSetIsGridViewActive).not.toBeCalled();

    // start screenshare
    rerender({ screenShareParticipant, isGridViewActive: false } as any);
    expect(mockSetIsGridViewActive).toBeCalledWith(false);

    // enable grid mode
    rerender({ screenShareParticipant, isGridViewActive: true } as any);

    // stop screenshare
    rerender({ screenShareParticipant: undefined, isGridViewActive: true } as any);

    // mockSetIsGridViewActive should only be called once with "false" since we're not reactivating grid mode
    expect(mockSetIsGridViewActive).toBeCalledTimes(1);
  });

I wouldn't mind a more concise description if you can think of one 😆.

Also, note that I saved the room object and screenshare object to their own variables. This is so hook rerenders happen with the same object references as the previous render. This prevents the useEffects from running unnecessarily. This wasn't needed in the previous tests, but it's needed in this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed a couple of words but couldn't really come up with anything much shorter 😢

@olipyskoty olipyskoty requested a review from timmydoza June 9, 2022 17:54
Comment on lines 132 to 133
background: '#000000',
border: `${theme.participantBorderWidth}px solid transparent`,
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, not sure how I didn't see this before, but it looks like there's a black border around the participants:
image

I think it's really just a transparent border that's showing the black background. So I guess we just make the border the same color as the grid background color here?

Also I think background: #000000 can be removed here. Looks like there's already background: 'black' in the container class.

cy.visit('/');
cy.visit('/', {
onBeforeLoad: window => {
window.localStorage.setItem('grid-view-active-key', false);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think a quick comment here about what this does would be good.

@@ -19,6 +19,10 @@ module.exports = (on, config) => {
args,
});
const page = (participants[name] = await browser.newPage()); // keep track of this participant for future use
await page.evaluateOnNewDocument(() => {
localStorage.clear();
Copy link
Contributor

Choose a reason for hiding this comment

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

Same, comment would be good.

@olipyskoty olipyskoty merged commit b913d5e into feature/grid-mode Jun 10, 2022
@olipyskoty olipyskoty deleted the finalize-grid-mode branch June 10, 2022 17:02
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.

None yet

2 participants