Refactor PipView + fix strict errors (#9604)

This commit is contained in:
Michael Weimann 2022-11-22 07:57:38 +01:00 committed by GitHub
parent 2393510a7f
commit 3f74ac37e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 44 deletions

View File

@ -33,14 +33,21 @@ const PADDING = {
right: 8, right: 8,
}; };
/**
* The type of a callback which will create the pip content children.
*/
export type CreatePipChildren = (options: IChildrenOptions) => JSX.Element;
interface IChildrenOptions { interface IChildrenOptions {
// a callback which is called when a mouse event (most likely mouse down) occurs at start of moving the pip around
onStartMoving: (event: React.MouseEvent<Element, MouseEvent>) => void; onStartMoving: (event: React.MouseEvent<Element, MouseEvent>) => void;
// a callback which is called when the content fo the pip changes in a way that is likely to cause a resize
onResize: (event: Event) => void; onResize: (event: Event) => void;
} }
interface IProps { interface IProps {
className?: string; className?: string;
children: ({ onStartMoving, onResize }: IChildrenOptions) => React.ReactNode; children: CreatePipChildren;
draggable: boolean; draggable: boolean;
onDoubleClick?: () => void; onDoubleClick?: () => void;
onMove?: () => void; onMove?: () => void;

View File

@ -25,7 +25,7 @@ import LegacyCallView from "./LegacyCallView";
import LegacyCallHandler, { LegacyCallHandlerEvent } from '../../../LegacyCallHandler'; import LegacyCallHandler, { LegacyCallHandlerEvent } from '../../../LegacyCallHandler';
import PersistentApp from "../elements/PersistentApp"; import PersistentApp from "../elements/PersistentApp";
import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { MatrixClientPeg } from '../../../MatrixClientPeg';
import PictureInPictureDragger from './PictureInPictureDragger'; import PictureInPictureDragger, { CreatePipChildren } from './PictureInPictureDragger';
import dis from '../../../dispatcher/dispatcher'; import dis from '../../../dispatcher/dispatcher';
import { Action } from "../../../dispatcher/actions"; import { Action } from "../../../dispatcher/actions";
import { Container, WidgetLayoutStore } from '../../../stores/widgets/WidgetLayoutStore'; import { Container, WidgetLayoutStore } from '../../../stores/widgets/WidgetLayoutStore';
@ -129,7 +129,9 @@ function getPrimarySecondaryCallsForPip(roomId: Optional<string>): [MatrixCall |
*/ */
class PipView extends React.Component<IProps, IState> { class PipView extends React.Component<IProps, IState> {
private movePersistedElement = createRef<() => void>(); // The cast is not so great, but solves the typing issue for the moment.
// Proper solution: use useRef (requires the component to be refactored to a functional component).
private movePersistedElement = createRef<() => void>() as React.MutableRefObject<() => void>;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
@ -328,9 +330,37 @@ class PipView extends React.Component<IProps, IState> {
this.setState({ showWidgetInPip, persistentWidgetId, persistentRoomId }); this.setState({ showWidgetInPip, persistentWidgetId, persistentRoomId });
} }
private createVoiceBroadcastPreRecordingPipContent(
voiceBroadcastPreRecording: VoiceBroadcastPreRecording,
): CreatePipChildren {
return ({ onStartMoving }) => <div onMouseDown={onStartMoving}>
<VoiceBroadcastPreRecordingPip
voiceBroadcastPreRecording={voiceBroadcastPreRecording}
/>
</div>;
}
private createVoiceBroadcastRecordingPipContent(
voiceBroadcastRecording: VoiceBroadcastRecording,
): CreatePipChildren {
return ({ onStartMoving }) => <div onMouseDown={onStartMoving}>
<VoiceBroadcastRecordingPip
recording={voiceBroadcastRecording}
/>
</div>;
}
public render() { public render() {
const pipMode = true; const pipMode = true;
let pipContent; let pipContent: CreatePipChildren | null = null;
if (this.props.voiceBroadcastPreRecording) {
pipContent = this.createVoiceBroadcastPreRecordingPipContent(this.props.voiceBroadcastPreRecording);
}
if (this.props.voiceBroadcastRecording) {
pipContent = this.createVoiceBroadcastRecordingPipContent(this.props.voiceBroadcastRecording);
}
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
@ -359,7 +389,7 @@ class PipView extends React.Component<IProps, IState> {
pipContent = ({ onStartMoving }) => pipContent = ({ onStartMoving }) =>
<div className={pipViewClasses}> <div className={pipViewClasses}>
<LegacyCallViewHeader <LegacyCallViewHeader
onPipMouseDown={(event) => { onStartMoving(event); this.onStartMoving.bind(this)(); }} onPipMouseDown={(event) => { onStartMoving?.(event); this.onStartMoving.bind(this)(); }}
pipMode={pipMode} pipMode={pipMode}
callRooms={[roomForWidget]} callRooms={[roomForWidget]}
onExpand={!isCall && !viewingCallRoom ? this.onExpand : undefined} onExpand={!isCall && !viewingCallRoom ? this.onExpand : undefined}
@ -375,26 +405,6 @@ class PipView extends React.Component<IProps, IState> {
</div>; </div>;
} }
if (this.props.voiceBroadcastPreRecording) {
// get a ref to pre-recording inside the current scope
const preRecording = this.props.voiceBroadcastPreRecording;
pipContent = ({ onStartMoving }) => <div onMouseDown={onStartMoving}>
<VoiceBroadcastPreRecordingPip
voiceBroadcastPreRecording={preRecording}
/>
</div>;
}
if (this.props.voiceBroadcastRecording) {
// get a ref to recording inside the current scope
const recording = this.props.voiceBroadcastRecording;
pipContent = ({ onStartMoving }) => <div onMouseDown={onStartMoving}>
<VoiceBroadcastRecordingPip
recording={recording}
/>
</div>;
}
if (!!pipContent) { if (!!pipContent) {
return <PictureInPictureDragger return <PictureInPictureDragger
className="mx_LegacyCallPreview" className="mx_LegacyCallPreview"

View File

@ -146,6 +146,28 @@ describe("PipView", () => {
ActiveWidgetStore.instance.destroyPersistentWidget("1", room.roomId); ActiveWidgetStore.instance.destroyPersistentWidget("1", room.roomId);
}; };
const setUpVoiceBroadcastRecording = () => {
const voiceBroadcastInfoEvent = mkVoiceBroadcastInfoStateEvent(
room.roomId,
VoiceBroadcastInfoState.Started,
alice.userId,
client.getDeviceId() || "",
);
const voiceBroadcastRecording = new VoiceBroadcastRecording(voiceBroadcastInfoEvent, client);
voiceBroadcastRecordingsStore.setCurrent(voiceBroadcastRecording);
};
const setUpVoiceBroadcastPreRecording = () => {
const voiceBroadcastPreRecording = new VoiceBroadcastPreRecording(
room,
alice,
client,
voiceBroadcastRecordingsStore,
);
voiceBroadcastPreRecordingStore.setCurrent(voiceBroadcastPreRecording);
};
it("hides if there's no content", () => { it("hides if there's no content", () => {
renderPip(); renderPip();
expect(screen.queryByRole("complementary")).toBeNull(); expect(screen.queryByRole("complementary")).toBeNull();
@ -199,18 +221,10 @@ describe("PipView", () => {
}); });
}); });
describe("when there is a voice broadcast recording", () => { describe("when there is a voice broadcast recording and pre-recording", () => {
beforeEach(() => { beforeEach(() => {
const voiceBroadcastInfoEvent = mkVoiceBroadcastInfoStateEvent( setUpVoiceBroadcastPreRecording();
room.roomId, setUpVoiceBroadcastRecording();
VoiceBroadcastInfoState.Started,
alice.userId,
client.getDeviceId() || "",
);
const voiceBroadcastRecording = new VoiceBroadcastRecording(voiceBroadcastInfoEvent, client);
voiceBroadcastRecordingsStore.setCurrent(voiceBroadcastRecording);
renderPip(); renderPip();
}); });
@ -222,14 +236,7 @@ describe("PipView", () => {
describe("when there is a voice broadcast pre-recording", () => { describe("when there is a voice broadcast pre-recording", () => {
beforeEach(() => { beforeEach(() => {
const voiceBroadcastPreRecording = new VoiceBroadcastPreRecording( setUpVoiceBroadcastPreRecording();
room,
alice,
client,
voiceBroadcastRecordingsStore,
);
voiceBroadcastPreRecordingStore.setCurrent(voiceBroadcastPreRecording);
renderPip(); renderPip();
}); });