Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Fix active Jitsi calls (and other active widgets) not being visible o…
Browse files Browse the repository at this point in the history
…n screen, by showing them in PiP if they are not visible in any other container (#7435)

Co-authored-by: J. Ryan Stinnett <[email protected]>
  • Loading branch information
toger5 and jryans authored Jan 11, 2022
1 parent ac61770 commit f6effc5
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 19 deletions.
39 changes: 35 additions & 4 deletions src/components/views/elements/PersistentApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ import WidgetUtils from '../../../utils/WidgetUtils';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import { replaceableComponent } from "../../../utils/replaceableComponent";
import AppTile from "./AppTile";
import { Container, WidgetLayoutStore } from '../../../stores/widgets/WidgetLayoutStore';
import { RightPanelPhases } from '../../../stores/right-panel/RightPanelStorePhases';
import RightPanelStore from '../../../stores/right-panel/RightPanelStore';
import { UPDATE_EVENT } from '../../../stores/AsyncStore';

interface IProps {
// none
Expand All @@ -33,6 +37,7 @@ interface IProps {
interface IState {
roomId: string;
persistentWidgetId: string;
rightPanelPhase?: RightPanelPhases;
}

@replaceableComponent("views.elements.PersistentApp")
Expand All @@ -45,12 +50,14 @@ export default class PersistentApp extends React.Component<IProps, IState> {
this.state = {
roomId: RoomViewStore.getRoomId(),
persistentWidgetId: ActiveWidgetStore.instance.getPersistentWidgetId(),
rightPanelPhase: RightPanelStore.instance.currentCard.phase,
};
}

public componentDidMount(): void {
this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate);
ActiveWidgetStore.instance.on(ActiveWidgetStoreEvent.Update, this.onActiveWidgetStoreUpdate);
RightPanelStore.instance.on(UPDATE_EVENT, this.onRightPanelStoreUpdate);
MatrixClientPeg.get().on("Room.myMembership", this.onMyMembership);
}

Expand All @@ -59,6 +66,7 @@ export default class PersistentApp extends React.Component<IProps, IState> {
this.roomStoreToken.remove();
}
ActiveWidgetStore.instance.removeListener(ActiveWidgetStoreEvent.Update, this.onActiveWidgetStoreUpdate);
RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
if (MatrixClientPeg.get()) {
MatrixClientPeg.get().removeListener("Room.myMembership", this.onMyMembership);
}
Expand All @@ -71,6 +79,12 @@ export default class PersistentApp extends React.Component<IProps, IState> {
});
};

private onRightPanelStoreUpdate = () => {
this.setState({
rightPanelPhase: RightPanelStore.instance.currentCard.phase,
});
};

private onActiveWidgetStoreUpdate = (): void => {
this.setState({
persistentWidgetId: ActiveWidgetStore.instance.getPersistentWidgetId(),
Expand All @@ -88,17 +102,34 @@ export default class PersistentApp extends React.Component<IProps, IState> {
};

public render(): JSX.Element {
if (this.state.persistentWidgetId) {
const persistentWidgetInRoomId = ActiveWidgetStore.instance.getRoomId(this.state.persistentWidgetId);
const wId = this.state.persistentWidgetId;
if (wId) {
const persistentWidgetInRoomId = ActiveWidgetStore.instance.getRoomId(wId);

const persistentWidgetInRoom = MatrixClientPeg.get().getRoom(persistentWidgetInRoomId);

// Sanity check the room - the widget may have been destroyed between render cycles, and
// thus no room is associated anymore.
if (!persistentWidgetInRoom) return null;

const myMembership = persistentWidgetInRoom.getMyMembership();
if (this.state.roomId !== persistentWidgetInRoomId && myMembership === "join") {
const wls = WidgetLayoutStore.instance;

const userIsPartOfTheRoom = persistentWidgetInRoom.getMyMembership() == "join";
const fromAnotherRoom = this.state.roomId !== persistentWidgetInRoomId;

const notInRightPanel =
!(this.state.rightPanelPhase == RightPanelPhases.Widget &&
wId == RightPanelStore.instance.currentCard.state?.widgetId);
const notInCenterContainer =
!wls.getContainerWidgets(persistentWidgetInRoom, Container.Center).some((app) => app.id == wId);
const notInTopContainer =
!wls.getContainerWidgets(persistentWidgetInRoom, Container.Top).some(app => app.id == wId);
if (
// the widget should only be shown as a persistent app (in a floating pip container) if it is not visible on screen
// either, because we are viewing a different room OR because it is in none of the possible containers of the room view.
(fromAnotherRoom && userIsPartOfTheRoom) ||
(notInRightPanel && notInCenterContainer && notInTopContainer && userIsPartOfTheRoom)
) {
// get the widget data
const appEvent = WidgetUtils.getRoomWidgets(persistentWidgetInRoom).find((ev) => {
return ev.getStateKey() === ActiveWidgetStore.instance.getPersistentWidgetId();
Expand Down
11 changes: 8 additions & 3 deletions src/components/views/rooms/Stickerpicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
import SettingsStore from "../../../settings/SettingsStore";
import ContextMenu, { ChevronFace } from "../../structures/ContextMenu";
import { WidgetType } from "../../../widgets/WidgetType";
import { Action } from "../../../dispatcher/actions";
import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import { ActionPayload } from '../../../dispatcher/payloads';
import ScalarAuthClient from '../../../ScalarAuthClient';
import GenericElementContextMenu from "../context_menus/GenericElementContextMenu";
import { IApp } from "../../../stores/WidgetStore";
import RightPanelStore from '../../../stores/right-panel/RightPanelStore';
import { UPDATE_EVENT } from '../../../stores/AsyncStore';

// This should be below the dialog level (4000), but above the rest of the UI (1000-2000).
// We sit in a context menu, so this should be given to the context menu.
Expand Down Expand Up @@ -139,14 +140,15 @@ export default class Stickerpicker extends React.PureComponent<IProps, IState> {
// Track updates to widget state in account data
MatrixClientPeg.get().on('accountData', this.updateWidget);

RightPanelStore.instance.on(UPDATE_EVENT, this.onRightPanelStoreUpdate);
// Initialise widget state from current account data
this.updateWidget();
}

public componentWillUnmount(): void {
const client = MatrixClientPeg.get();
if (client) client.removeListener('accountData', this.updateWidget);

RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
window.removeEventListener('resize', this.onResize);
if (this.dispatcherRef) {
dis.unregister(this.dispatcherRef);
Expand Down Expand Up @@ -204,14 +206,17 @@ export default class Stickerpicker extends React.PureComponent<IProps, IState> {
case "stickerpicker_close":
this.props.setShowStickers(false);
break;
case Action.AfterRightPanelPhaseChange:
case "show_left_panel":
case "hide_left_panel":
this.props.setShowStickers(false);
break;
}
};

private onRightPanelStoreUpdate = () => {
this.props.setShowStickers(false);
};

private defaultStickerpickerContent(): JSX.Element {
return (
<AccessibleButton onClick={this.launchManageIntegrations}
Expand Down
17 changes: 10 additions & 7 deletions src/components/views/voip/CallPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,16 @@ export default class CallPreview extends React.Component<IProps, IState> {
draggable={pipMode}
onDoubleClick={this.onDoubleClick}
>
{ ({ onStartMoving, onResize }) => <CallView
onMouseDownOnHeader={onStartMoving}
call={this.state.primaryCall}
secondaryCall={this.state.secondaryCall}
pipMode={pipMode}
onResize={onResize}
/> }
{
({ onStartMoving, onResize }) =>
<CallView
onMouseDownOnHeader={onStartMoving}
call={this.state.primaryCall}
secondaryCall={this.state.secondaryCall}
pipMode={pipMode}
onResize={onResize}
/>
}
</PictureInPictureDragger>

);
Expand Down
5 changes: 0 additions & 5 deletions src/dispatcher/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,6 @@ export enum Action {
*/
ViewRoomDelta = "view_room_delta",

/**
* Trigged after the phase of the right panel is set. Should be used with AfterRightPanelPhaseChangePayload.
*/
AfterRightPanelPhaseChange = "after_right_panel_phase_change",

/**
* Opens the modal dial pad
*/
Expand Down

0 comments on commit f6effc5

Please sign in to comment.