Allow call and broadcast PiP at the same time (#9829)

pull/28788/head^2
Michael Weimann 2022-12-28 14:43:44 +01:00 committed by GitHub
parent d2763c329d
commit c257e137aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 79 additions and 33 deletions

View File

@ -15,8 +15,12 @@ limitations under the License.
*/ */
.mx_LegacyCallPreview { .mx_LegacyCallPreview {
position: fixed; align-items: flex-end;
display: flex;
flex-direction: column;
gap: $spacing-16;
left: 0; left: 0;
position: fixed;
top: 0; top: 0;
pointer-events: initial; /* restore pointer events so the user can leave/interact */ pointer-events: initial; /* restore pointer events so the user can leave/interact */

View File

@ -47,7 +47,7 @@ interface IChildrenOptions {
interface IProps { interface IProps {
className?: string; className?: string;
children: CreatePipChildren; children: Array<CreatePipChildren>;
draggable: boolean; draggable: boolean;
onDoubleClick?: () => void; onDoubleClick?: () => void;
onMove?: () => void; onMove?: () => void;
@ -208,6 +208,13 @@ export default class PictureInPictureDragger extends React.Component<IProps> {
transform: `translateX(${this.translationX}px) translateY(${this.translationY}px)`, transform: `translateX(${this.translationX}px) translateY(${this.translationY}px)`,
}; };
const children = this.props.children.map((create: CreatePipChildren) => {
return create({
onStartMoving: this.onStartMoving,
onResize: this.onResize,
});
});
return ( return (
<aside <aside
className={this.props.className} className={this.props.className}
@ -215,10 +222,7 @@ export default class PictureInPictureDragger extends React.Component<IProps> {
ref={this.callViewWrapper} ref={this.callViewWrapper}
onDoubleClick={this.props.onDoubleClick} onDoubleClick={this.props.onDoubleClick}
> >
{this.props.children({ {children}
onStartMoving: this.onStartMoving,
onResize: this.onResize,
})}
</aside> </aside>
); );
} }

View File

@ -373,24 +373,20 @@ class PipView extends React.Component<IProps, IState> {
public render() { public render() {
const pipMode = true; const pipMode = true;
let pipContent: CreatePipChildren | null = null; let pipContent: Array<CreatePipChildren> = [];
if (this.props.voiceBroadcastPlayback) {
pipContent = this.createVoiceBroadcastPlaybackPipContent(this.props.voiceBroadcastPlayback);
}
if (this.props.voiceBroadcastPreRecording) {
pipContent = this.createVoiceBroadcastPreRecordingPipContent(this.props.voiceBroadcastPreRecording);
}
if (this.props.voiceBroadcastRecording) { if (this.props.voiceBroadcastRecording) {
pipContent = this.createVoiceBroadcastRecordingPipContent(this.props.voiceBroadcastRecording); pipContent = [this.createVoiceBroadcastRecordingPipContent(this.props.voiceBroadcastRecording)];
} else if (this.props.voiceBroadcastPreRecording) {
pipContent = [this.createVoiceBroadcastPreRecordingPipContent(this.props.voiceBroadcastPreRecording)];
} else if (this.props.voiceBroadcastPlayback) {
pipContent = [this.createVoiceBroadcastPlaybackPipContent(this.props.voiceBroadcastPlayback)];
} }
if (this.state.primaryCall) { if (this.state.primaryCall) {
// get a ref to call inside the current scope // get a ref to call inside the current scope
const call = this.state.primaryCall; const call = this.state.primaryCall;
pipContent = ({ onStartMoving, onResize }) => ( pipContent.push(({ onStartMoving, onResize }) => (
<LegacyCallView <LegacyCallView
onMouseDownOnHeader={onStartMoving} onMouseDownOnHeader={onStartMoving}
call={call} call={call}
@ -398,7 +394,7 @@ class PipView extends React.Component<IProps, IState> {
pipMode={pipMode} pipMode={pipMode}
onResize={onResize} onResize={onResize}
/> />
); ));
} }
if (this.state.showWidgetInPip) { if (this.state.showWidgetInPip) {
@ -412,7 +408,7 @@ class PipView extends React.Component<IProps, IState> {
const viewingCallRoom = this.state.viewedRoomId === roomId; const viewingCallRoom = this.state.viewedRoomId === roomId;
const isCall = CallStore.instance.getActiveCall(roomId) !== null; const isCall = CallStore.instance.getActiveCall(roomId) !== null;
pipContent = ({ onStartMoving }) => ( pipContent.push(({ onStartMoving }) => (
<div className={pipViewClasses}> <div className={pipViewClasses}>
<LegacyCallViewHeader <LegacyCallViewHeader
onPipMouseDown={(event) => { onPipMouseDown={(event) => {
@ -432,10 +428,10 @@ class PipView extends React.Component<IProps, IState> {
movePersistedElement={this.movePersistedElement} movePersistedElement={this.movePersistedElement}
/> />
</div> </div>
); ));
} }
if (!!pipContent) { if (pipContent.length) {
return ( return (
<PictureInPictureDragger <PictureInPictureDragger
className="mx_LegacyCallPreview" className="mx_LegacyCallPreview"

View File

@ -24,18 +24,22 @@ import PictureInPictureDragger, {
describe("PictureInPictureDragger", () => { describe("PictureInPictureDragger", () => {
let renderResult: RenderResult; let renderResult: RenderResult;
const mkContent1: CreatePipChildren = () => { const mkContent1: Array<CreatePipChildren> = [
return <div>content 1</div>; () => {
}; return <div>content 1</div>;
},
];
const mkContent2: CreatePipChildren = () => { const mkContent2: Array<CreatePipChildren> = [
return ( () => {
<div> return (
content 2<br /> <div>
content 2.2 content 2<br />
</div> content 2.2
); </div>
}; );
},
];
describe("when rendering the dragger with PiP content 1", () => { describe("when rendering the dragger with PiP content 1", () => {
beforeEach(() => { beforeEach(() => {
@ -66,4 +70,16 @@ describe("PictureInPictureDragger", () => {
}); });
}); });
}); });
describe("when rendering the dragger with PiP content 1 and 2", () => {
beforeEach(() => {
renderResult = render(
<PictureInPictureDragger draggable={true}>{[...mkContent1, ...mkContent2]}</PictureInPictureDragger>,
);
});
it("should render both contents", () => {
expect(renderResult.container).toMatchSnapshot();
});
});
}); });

View File

@ -279,9 +279,18 @@ describe("PipView", () => {
}); });
it("should render the voice broadcast recording PiP", () => { it("should render the voice broadcast recording PiP", () => {
// check for the „Live“ badge // check for the „Live“ badge to be present
expect(screen.queryByText("Live")).toBeInTheDocument(); expect(screen.queryByText("Live")).toBeInTheDocument();
}); });
it("and a call it should show both, the call and the recording", async () => {
await withCall(async () => {
// Broadcast: Check for the „Live“ badge to be present
expect(screen.queryByText("Live")).toBeInTheDocument();
// Call: Check for the „Fill screen“ button to be present
expect(screen.queryByLabelText("Fill screen")).toBeInTheDocument();
});
});
}); });
describe("when there is a voice broadcast playback and pre-recording", () => { describe("when there is a voice broadcast playback and pre-recording", () => {

View File

@ -1,5 +1,22 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PictureInPictureDragger when rendering the dragger with PiP content 1 and 2 should render both contents 1`] = `
<div>
<aside
style="transform: translateX(680px) translateY(478px);"
>
<div>
content 1
</div>
<div>
content 2
<br />
content 2.2
</div>
</aside>
</div>
`;
exports[`PictureInPictureDragger when rendering the dragger with PiP content 1 and rendering PiP content 2 should update the PiP content 1`] = ` exports[`PictureInPictureDragger when rendering the dragger with PiP content 1 and rendering PiP content 2 should update the PiP content 1`] = `
<div> <div>
<aside <aside