Skip to content

Commit

Permalink
Calling: Picture-in-picture
Browse files Browse the repository at this point in the history
  • Loading branch information
josh-signal committed Oct 12, 2020
1 parent 7b15bdd commit a581f6e
Show file tree
Hide file tree
Showing 13 changed files with 467 additions and 3 deletions.
8 changes: 8 additions & 0 deletions _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2863,6 +2863,14 @@
"message": "Settings",
"description": "Title for device selection settings"
},
"calling__pip": {
"message": "Picture-in-picture",
"description": "Title for picture-in-picture toggle"
},
"calling__hangup": {
"message": "Hang Up",
"description": "Title for hang up button"
},
"callingDeviceSelection__label--video": {
"message": "Video",
"description": "Label for video input selector"
Expand Down
1 change: 1 addition & 0 deletions images/icons/v2/collapse-24.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions images/icons/v2/expand-24.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions stylesheets/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,7 @@
font-size: large;
}
}

.call-manager-wrapper {
position: relative;
}
111 changes: 110 additions & 1 deletion stylesheets/_modules.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6133,7 +6133,7 @@ button.module-image__border-overlay:focus {
.module-ongoing-call__settings {
position: absolute;
top: 25px;
right: 25px;
right: 65px;

&--button {
@include color-svg(
Expand All @@ -6145,6 +6145,115 @@ button.module-image__border-overlay:focus {
}
}

.module-ongoing-call__pip {
position: absolute;
top: 25px;
right: 25px;

&--button {
@include color-svg('../images/icons/v2/collapse-24.svg', $color-white);
height: 22px;
width: 22px;
}
}

.module-calling-pip {
backface-visibility: hidden;
background-color: $color-gray-95;
border-radius: 4px;
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.05), 0px 8px 20px rgba(0, 0, 0, 0.3);
cursor: grab;
height: 158px;
position: absolute;
width: 120px;
z-index: 2;

&__video {
&--remote {
align-items: center;
background-color: $color-gray-95;
border-radius: 4px 4px 0 0;
display: flex;
height: 120px;
justify-content: center;
position: relative;
width: 100%;
}

&--local {
bottom: 38px;
height: 32px;
position: absolute;
right: 4px;
width: 32px;
}

&--background {
background-repeat: no-repeat;
background-size: cover;
border-radius: 4px 4px 0 0;
height: 100%;
position: absolute;
width: 100%;
}

&--blur {
backdrop-filter: blur(7px);
backface-visibility: hidden;
background-color: $color-black-alpha-40;
border-radius: 4px 4px 0 0;
height: 100%;
position: absolute;
width: 100%;
}

&--avatar img {
-webkit-user-drag: none;
-webkit-user-select: none;
}
}

&__actions {
align-items: center;
background-color: $color-gray-02;
border-radius: 0 0 4px 4px;
display: flex;
flex-direction: row;
height: 38px;
justify-content: space-around;

@include dark-theme {
background-color: $color-gray-65;
}
}

&__button {
&--hangup {
@include color-svg(
'../images/icons/v2/phone-down-28.svg',
$color-gray-75
);
height: 28px;
width: 28px;
@include dark-theme {
@include color-svg(
'../images/icons/v2/phone-down-28.svg',
$color-gray-15
);
}
}

&--pip {
@include color-svg('../images/icons/v2/expand-24.svg', $color-gray-75);
height: 24px;
width: 24px;
@include dark-theme {
@include color-svg('../images/icons/v2/expand-24.svg', $color-gray-15);
}
}
}
}

// Module: Left Pane

.module-left-pane {
Expand Down
2 changes: 2 additions & 0 deletions ts/components/CallManager.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ const defaultProps = {
hasLocalVideo: true,
hasRemoteVideo: true,
i18n,
pip: false,
renderDeviceSelection: () => <div />,
setLocalAudio: action('set-local-audio'),
setLocalPreview: action('set-local-preview'),
setLocalVideo: action('set-local-video'),
setRendererCanvas: action('set-renderer-canvas'),
settingsDialogOpen: false,
togglePip: action('toggle-pip'),
toggleSettings: action('toggle-settings'),
};

Expand Down
20 changes: 20 additions & 0 deletions ts/components/CallManager.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { CallingPip } from './CallingPip';
import { CallScreen, PropsType as CallScreenPropsType } from './CallScreen';
import {
IncomingCallBar,
Expand All @@ -10,6 +11,7 @@ import { CallDetailsType } from '../state/ducks/calling';
type CallManagerPropsType = {
callDetails?: CallDetailsType;
callState?: CallState;
pip: boolean;
renderDeviceSelection: () => JSX.Element;
settingsDialogOpen: boolean;
};
Expand All @@ -28,12 +30,14 @@ export const CallManager = ({
hasLocalVideo,
hasRemoteVideo,
i18n,
pip,
renderDeviceSelection,
setLocalAudio,
setLocalPreview,
setLocalVideo,
setRendererCanvas,
settingsDialogOpen,
togglePip,
toggleSettings,
}: PropsType): JSX.Element | null => {
if (!callDetails || !callState) {
Expand All @@ -46,6 +50,21 @@ export const CallManager = ({
const ringing = callState === CallState.Ringing;

if (outgoing || ongoing) {
if (pip) {
return (
<CallingPip
callDetails={callDetails}
hangUp={hangUp}
hasLocalVideo={hasLocalVideo}
hasRemoteVideo={hasRemoteVideo}
i18n={i18n}
setLocalPreview={setLocalPreview}
setRendererCanvas={setRendererCanvas}
togglePip={togglePip}
/>
);
}

return (
<>
<CallScreen
Expand All @@ -60,6 +79,7 @@ export const CallManager = ({
setRendererCanvas={setRendererCanvas}
setLocalAudio={setLocalAudio}
setLocalVideo={setLocalVideo}
togglePip={togglePip}
toggleSettings={toggleSettings}
/>
{settingsDialogOpen && renderDeviceSelection()}
Expand Down
1 change: 1 addition & 0 deletions ts/components/CallScreen.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const defaultProps = {
setLocalPreview: action('set-local-preview'),
setLocalVideo: action('set-local-video'),
setRendererCanvas: action('set-renderer-canvas'),
togglePip: action('toggle-pip'),
toggleSettings: action('toggle-settings'),
};

Expand Down
10 changes: 10 additions & 0 deletions ts/components/CallScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export type PropsType = {
setLocalVideo: (_: SetLocalVideoType) => void;
setLocalPreview: (_: SetLocalPreviewType) => void;
setRendererCanvas: (_: SetRendererCanvasType) => void;
togglePip: () => void;
toggleSettings: () => void;
};

Expand Down Expand Up @@ -209,6 +210,7 @@ export class CallScreen extends React.Component<PropsType, StateType> {
hasLocalVideo,
hasRemoteVideo,
i18n,
togglePip,
toggleSettings,
} = this.props;
const { showControls } = this.state;
Expand Down Expand Up @@ -256,6 +258,14 @@ export class CallScreen extends React.Component<PropsType, StateType> {
onClick={toggleSettings}
/>
</div>
<div className="module-ongoing-call__pip">
<button
type="button"
aria-label={i18n('calling__pip')}
className="module-ongoing-call__pip--button"
onClick={togglePip}
/>
</div>
</div>
{hasRemoteVideo
? this.renderRemoteVideo()
Expand Down
45 changes: 45 additions & 0 deletions ts/components/CallingPip.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as React from 'react';
import { storiesOf } from '@storybook/react';
import { boolean } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';

import { ColorType } from '../types/Colors';
import { CallingPip, PropsType } from './CallingPip';
import { setup as setupI18n } from '../../js/modules/i18n';
import enMessages from '../../_locales/en/messages.json';

const i18n = setupI18n('en', enMessages);

const callDetails = {
callId: 0,
isIncoming: true,
isVideoCall: true,

avatarPath: undefined,
color: 'ultramarine' as ColorType,
title: 'Rick Sanchez',
name: 'Rick Sanchez',
phoneNumber: '3051234567',
profileName: 'Rick Sanchez',
};

const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
callDetails,
hangUp: action('hang-up'),
hasLocalVideo: boolean('hasLocalVideo', overrideProps.hasLocalVideo || false),
hasRemoteVideo: boolean(
'hasRemoteVideo',
overrideProps.hasRemoteVideo || false
),
i18n,
setLocalPreview: action('set-local-preview'),
setRendererCanvas: action('set-renderer-canvas'),
togglePip: action('toggle-pip'),
});

const story = storiesOf('Components/CallingPip', module);

story.add('Default', () => {
const props = createProps();
return <CallingPip {...props} />;
});
Loading

0 comments on commit a581f6e

Please sign in to comment.