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

Commit f6effc5

Browse files
toger5jryans
andauthored
Fix active Jitsi calls (and other active widgets) not being visible on screen, by showing them in PiP if they are not visible in any other container (#7435)
Co-authored-by: J. Ryan Stinnett <[email protected]>
1 parent ac61770 commit f6effc5

File tree

4 files changed

+53
-19
lines changed

4 files changed

+53
-19
lines changed

src/components/views/elements/PersistentApp.tsx

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ import WidgetUtils from '../../../utils/WidgetUtils';
2525
import { MatrixClientPeg } from '../../../MatrixClientPeg';
2626
import { replaceableComponent } from "../../../utils/replaceableComponent";
2727
import AppTile from "./AppTile";
28+
import { Container, WidgetLayoutStore } from '../../../stores/widgets/WidgetLayoutStore';
29+
import { RightPanelPhases } from '../../../stores/right-panel/RightPanelStorePhases';
30+
import RightPanelStore from '../../../stores/right-panel/RightPanelStore';
31+
import { UPDATE_EVENT } from '../../../stores/AsyncStore';
2832

2933
interface IProps {
3034
// none
@@ -33,6 +37,7 @@ interface IProps {
3337
interface IState {
3438
roomId: string;
3539
persistentWidgetId: string;
40+
rightPanelPhase?: RightPanelPhases;
3641
}
3742

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

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

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

82+
private onRightPanelStoreUpdate = () => {
83+
this.setState({
84+
rightPanelPhase: RightPanelStore.instance.currentCard.phase,
85+
});
86+
};
87+
7488
private onActiveWidgetStoreUpdate = (): void => {
7589
this.setState({
7690
persistentWidgetId: ActiveWidgetStore.instance.getPersistentWidgetId(),
@@ -88,17 +102,34 @@ export default class PersistentApp extends React.Component<IProps, IState> {
88102
};
89103

90104
public render(): JSX.Element {
91-
if (this.state.persistentWidgetId) {
92-
const persistentWidgetInRoomId = ActiveWidgetStore.instance.getRoomId(this.state.persistentWidgetId);
105+
const wId = this.state.persistentWidgetId;
106+
if (wId) {
107+
const persistentWidgetInRoomId = ActiveWidgetStore.instance.getRoomId(wId);
93108

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

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

100-
const myMembership = persistentWidgetInRoom.getMyMembership();
101-
if (this.state.roomId !== persistentWidgetInRoomId && myMembership === "join") {
115+
const wls = WidgetLayoutStore.instance;
116+
117+
const userIsPartOfTheRoom = persistentWidgetInRoom.getMyMembership() == "join";
118+
const fromAnotherRoom = this.state.roomId !== persistentWidgetInRoomId;
119+
120+
const notInRightPanel =
121+
!(this.state.rightPanelPhase == RightPanelPhases.Widget &&
122+
wId == RightPanelStore.instance.currentCard.state?.widgetId);
123+
const notInCenterContainer =
124+
!wls.getContainerWidgets(persistentWidgetInRoom, Container.Center).some((app) => app.id == wId);
125+
const notInTopContainer =
126+
!wls.getContainerWidgets(persistentWidgetInRoom, Container.Top).some(app => app.id == wId);
127+
if (
128+
// the widget should only be shown as a persistent app (in a floating pip container) if it is not visible on screen
129+
// either, because we are viewing a different room OR because it is in none of the possible containers of the room view.
130+
(fromAnotherRoom && userIsPartOfTheRoom) ||
131+
(notInRightPanel && notInCenterContainer && notInTopContainer && userIsPartOfTheRoom)
132+
) {
102133
// get the widget data
103134
const appEvent = WidgetUtils.getRoomWidgets(persistentWidgetInRoom).find((ev) => {
104135
return ev.getStateKey() === ActiveWidgetStore.instance.getPersistentWidgetId();

src/components/views/rooms/Stickerpicker.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@ import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
2929
import SettingsStore from "../../../settings/SettingsStore";
3030
import ContextMenu, { ChevronFace } from "../../structures/ContextMenu";
3131
import { WidgetType } from "../../../widgets/WidgetType";
32-
import { Action } from "../../../dispatcher/actions";
3332
import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore";
3433
import { replaceableComponent } from "../../../utils/replaceableComponent";
3534
import { ActionPayload } from '../../../dispatcher/payloads';
3635
import ScalarAuthClient from '../../../ScalarAuthClient';
3736
import GenericElementContextMenu from "../context_menus/GenericElementContextMenu";
3837
import { IApp } from "../../../stores/WidgetStore";
38+
import RightPanelStore from '../../../stores/right-panel/RightPanelStore';
39+
import { UPDATE_EVENT } from '../../../stores/AsyncStore';
3940

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

143+
RightPanelStore.instance.on(UPDATE_EVENT, this.onRightPanelStoreUpdate);
142144
// Initialise widget state from current account data
143145
this.updateWidget();
144146
}
145147

146148
public componentWillUnmount(): void {
147149
const client = MatrixClientPeg.get();
148150
if (client) client.removeListener('accountData', this.updateWidget);
149-
151+
RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
150152
window.removeEventListener('resize', this.onResize);
151153
if (this.dispatcherRef) {
152154
dis.unregister(this.dispatcherRef);
@@ -204,14 +206,17 @@ export default class Stickerpicker extends React.PureComponent<IProps, IState> {
204206
case "stickerpicker_close":
205207
this.props.setShowStickers(false);
206208
break;
207-
case Action.AfterRightPanelPhaseChange:
208209
case "show_left_panel":
209210
case "hide_left_panel":
210211
this.props.setShowStickers(false);
211212
break;
212213
}
213214
};
214215

216+
private onRightPanelStoreUpdate = () => {
217+
this.props.setShowStickers(false);
218+
};
219+
215220
private defaultStickerpickerContent(): JSX.Element {
216221
return (
217222
<AccessibleButton onClick={this.launchManageIntegrations}

src/components/views/voip/CallPreview.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,16 @@ export default class CallPreview extends React.Component<IProps, IState> {
197197
draggable={pipMode}
198198
onDoubleClick={this.onDoubleClick}
199199
>
200-
{ ({ onStartMoving, onResize }) => <CallView
201-
onMouseDownOnHeader={onStartMoving}
202-
call={this.state.primaryCall}
203-
secondaryCall={this.state.secondaryCall}
204-
pipMode={pipMode}
205-
onResize={onResize}
206-
/> }
200+
{
201+
({ onStartMoving, onResize }) =>
202+
<CallView
203+
onMouseDownOnHeader={onStartMoving}
204+
call={this.state.primaryCall}
205+
secondaryCall={this.state.secondaryCall}
206+
pipMode={pipMode}
207+
onResize={onResize}
208+
/>
209+
}
207210
</PictureInPictureDragger>
208211

209212
);

src/dispatcher/actions.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,6 @@ export enum Action {
102102
*/
103103
ViewRoomDelta = "view_room_delta",
104104

105-
/**
106-
* Trigged after the phase of the right panel is set. Should be used with AfterRightPanelPhaseChangePayload.
107-
*/
108-
AfterRightPanelPhaseChange = "after_right_panel_phase_change",
109-
110105
/**
111106
* Opens the modal dial pad
112107
*/

0 commit comments

Comments
 (0)