From 48224bb41088fd54be816877e65bee1d3b776da3 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Dec 2021 17:39:19 +0100 Subject: [PATCH 1/4] Always show jitsi (and other sticky widgets) in pip mode if they are not shown in any of the other widget containers. --- .../views/elements/PersistentApp.tsx | 50 +++++++++++++++++-- src/components/views/voip/CallPreview.tsx | 15 +++--- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/components/views/elements/PersistentApp.tsx b/src/components/views/elements/PersistentApp.tsx index 80e57b537b5..861f632d735 100644 --- a/src/components/views/elements/PersistentApp.tsx +++ b/src/components/views/elements/PersistentApp.tsx @@ -25,6 +25,12 @@ 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 RightPanelStore from '../../../stores/RightPanelStore'; +import { RightPanelPhases } from '../../../stores/RightPanelStorePhases'; +import dis from '../../../dispatcher/dispatcher'; +import { ActionPayload } from '../../../dispatcher/payloads'; +import { Action } from '../../../dispatcher/actions'; interface IProps { // none @@ -33,22 +39,25 @@ interface IProps { interface IState { roomId: string; persistentWidgetId: string; + rightPanelPhase?: RightPanelPhases; } @replaceableComponent("views.elements.PersistentApp") export default class PersistentApp extends React.Component { private roomStoreToken: EventSubscription; - + private dispatcherRef: string; constructor(props: IProps) { super(props); this.state = { roomId: RoomViewStore.getRoomId(), persistentWidgetId: ActiveWidgetStore.instance.getPersistentWidgetId(), + rightPanelPhase: RightPanelStore.getSharedInstance().roomPanelPhase, }; } public componentDidMount(): void { + this.dispatcherRef = dis.register(this.onWidgetAction); this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); ActiveWidgetStore.instance.on(ActiveWidgetStoreEvent.Update, this.onActiveWidgetStoreUpdate); MatrixClientPeg.get().on("Room.myMembership", this.onMyMembership); @@ -58,6 +67,9 @@ export default class PersistentApp extends React.Component { if (this.roomStoreToken) { this.roomStoreToken.remove(); } + if (this.dispatcherRef) { + dis.unregister(this.dispatcherRef); + } ActiveWidgetStore.instance.removeListener(ActiveWidgetStoreEvent.Update, this.onActiveWidgetStoreUpdate); if (MatrixClientPeg.get()) { MatrixClientPeg.get().removeListener("Room.myMembership", this.onMyMembership); @@ -71,6 +83,17 @@ export default class PersistentApp extends React.Component { }); }; + private onWidgetAction = (payload: ActionPayload): void => { + switch (payload.action) { + case Action.AfterRightPanelPhaseChange: + this.setState({ + rightPanelPhase: RightPanelStore.getSharedInstance().roomPanelPhase, + }); + break; + default: break; + } + }; + private onActiveWidgetStoreUpdate = (): void => { this.setState({ persistentWidgetId: ActiveWidgetStore.instance.getPersistentWidgetId(), @@ -88,8 +111,9 @@ export default class PersistentApp extends React.Component { }; 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); @@ -97,8 +121,24 @@ export default class PersistentApp extends React.Component { // 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.getSharedInstance().roomPanelPhaseParams?.widgetId); + const notInCenterContainer = + !wls.getContainerWidgets(persistentWidgetInRoom, Container.Center) + .find((app)=>app.id == wId); + const notInTopContainer = + !wls.getContainerWidgets(persistentWidgetInRoom, Container.Top).find(app=>app.id == wId); + if ( + //Show the persistent widget in two cases. The booleans have to be read like this: the widget is-`fromAnotherRoom`: + (fromAnotherRoom && userIsPartOfTheRoom) || + (notInRightPanel && notInCenterContainer && notInTopContainer && userIsPartOfTheRoom) + ) { // get the widget data const appEvent = WidgetUtils.getRoomWidgets(persistentWidgetInRoom).find((ev) => { return ev.getStateKey() === ActiveWidgetStore.instance.getPersistentWidgetId(); diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index a14506d9fb7..16aa5f26965 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -197,13 +197,14 @@ export default class CallPreview extends React.Component { draggable={pipMode} onDoubleClick={this.onDoubleClick} > - { ({ onStartMoving, onResize }) => } + { ({ onStartMoving, onResize }) => + } ); From b9afcacce67eeb5b0c926b8c9af6c63095c851a9 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 29 Dec 2021 11:38:32 +0100 Subject: [PATCH 2/4] review fixes --- .../views/elements/PersistentApp.tsx | 9 +++++---- src/components/views/voip/CallPreview.tsx | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/components/views/elements/PersistentApp.tsx b/src/components/views/elements/PersistentApp.tsx index 861f632d735..cd1b6b232cc 100644 --- a/src/components/views/elements/PersistentApp.tsx +++ b/src/components/views/elements/PersistentApp.tsx @@ -46,6 +46,7 @@ interface IState { export default class PersistentApp extends React.Component { private roomStoreToken: EventSubscription; private dispatcherRef: string; + constructor(props: IProps) { super(props); @@ -130,12 +131,12 @@ export default class PersistentApp extends React.Component { !(this.state.rightPanelPhase == RightPanelPhases.Widget && wId == RightPanelStore.getSharedInstance().roomPanelPhaseParams?.widgetId); const notInCenterContainer = - !wls.getContainerWidgets(persistentWidgetInRoom, Container.Center) - .find((app)=>app.id == wId); + !wls.getContainerWidgets(persistentWidgetInRoom, Container.Center).some((app) => app.id == wId); const notInTopContainer = - !wls.getContainerWidgets(persistentWidgetInRoom, Container.Top).find(app=>app.id == wId); + !wls.getContainerWidgets(persistentWidgetInRoom, Container.Top).some(app => app.id == wId); if ( - //Show the persistent widget in two cases. The booleans have to be read like this: the widget is-`fromAnotherRoom`: + // 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) ) { diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 16aa5f26965..dec63711a1b 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -197,14 +197,16 @@ export default class CallPreview extends React.Component { draggable={pipMode} onDoubleClick={this.onDoubleClick} > - { ({ onStartMoving, onResize }) => - } + { + ({ onStartMoving, onResize }) => + + } ); From b62c86873b3f0a9ebe09fca4c99afd1647f7bfd4 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 5 Jan 2022 18:00:07 +0100 Subject: [PATCH 3/4] refactor for new right panel remove old artifact: AfterRightPanelPhaseChangePayload --- .../views/elements/PersistentApp.tsx | 33 +++++++------------ src/components/views/rooms/Stickerpicker.tsx | 11 +++++-- src/dispatcher/actions.ts | 5 --- 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/components/views/elements/PersistentApp.tsx b/src/components/views/elements/PersistentApp.tsx index cd1b6b232cc..fdc871dc0c4 100644 --- a/src/components/views/elements/PersistentApp.tsx +++ b/src/components/views/elements/PersistentApp.tsx @@ -26,12 +26,9 @@ import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { replaceableComponent } from "../../../utils/replaceableComponent"; import AppTile from "./AppTile"; import { Container, WidgetLayoutStore } from '../../../stores/widgets/WidgetLayoutStore'; -import RightPanelStore from '../../../stores/RightPanelStore'; -import { RightPanelPhases } from '../../../stores/RightPanelStorePhases'; -import dis from '../../../dispatcher/dispatcher'; -import { ActionPayload } from '../../../dispatcher/payloads'; -import { Action } from '../../../dispatcher/actions'; - +import { RightPanelPhases } from '../../../stores/right-panel/RightPanelStorePhases'; +import RightPanelStore from '../../../stores/right-panel/RightPanelStore'; +import { UPDATE_EVENT } from '../../../stores/AsyncStore'; interface IProps { // none } @@ -45,7 +42,6 @@ interface IState { @replaceableComponent("views.elements.PersistentApp") export default class PersistentApp extends React.Component { private roomStoreToken: EventSubscription; - private dispatcherRef: string; constructor(props: IProps) { super(props); @@ -53,14 +49,14 @@ export default class PersistentApp extends React.Component { this.state = { roomId: RoomViewStore.getRoomId(), persistentWidgetId: ActiveWidgetStore.instance.getPersistentWidgetId(), - rightPanelPhase: RightPanelStore.getSharedInstance().roomPanelPhase, + rightPanelPhase: RightPanelStore.instance.currentCard.phase, }; } public componentDidMount(): void { - this.dispatcherRef = dis.register(this.onWidgetAction); 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); } @@ -68,10 +64,8 @@ export default class PersistentApp extends React.Component { if (this.roomStoreToken) { this.roomStoreToken.remove(); } - if (this.dispatcherRef) { - dis.unregister(this.dispatcherRef); - } ActiveWidgetStore.instance.removeListener(ActiveWidgetStoreEvent.Update, this.onActiveWidgetStoreUpdate); + RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate); if (MatrixClientPeg.get()) { MatrixClientPeg.get().removeListener("Room.myMembership", this.onMyMembership); } @@ -84,15 +78,10 @@ export default class PersistentApp extends React.Component { }); }; - private onWidgetAction = (payload: ActionPayload): void => { - switch (payload.action) { - case Action.AfterRightPanelPhaseChange: - this.setState({ - rightPanelPhase: RightPanelStore.getSharedInstance().roomPanelPhase, - }); - break; - default: break; - } + private onRightPanelStoreUpdate = () => { + this.setState({ + rightPanelPhase: RightPanelStore.instance.currentCard.phase, + }); }; private onActiveWidgetStoreUpdate = (): void => { @@ -129,7 +118,7 @@ export default class PersistentApp extends React.Component { const notInRightPanel = !(this.state.rightPanelPhase == RightPanelPhases.Widget && - wId == RightPanelStore.getSharedInstance().roomPanelPhaseParams?.widgetId); + wId == RightPanelStore.instance.currentCard.state?.widgetId); const notInCenterContainer = !wls.getContainerWidgets(persistentWidgetInRoom, Container.Center).some((app) => app.id == wId); const notInTopContainer = diff --git a/src/components/views/rooms/Stickerpicker.tsx b/src/components/views/rooms/Stickerpicker.tsx index 507f5493116..9fc16ff95f3 100644 --- a/src/components/views/rooms/Stickerpicker.tsx +++ b/src/components/views/rooms/Stickerpicker.tsx @@ -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. @@ -139,6 +140,7 @@ export default class Stickerpicker extends React.PureComponent { // 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(); } @@ -146,7 +148,7 @@ export default class Stickerpicker extends React.PureComponent { 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); @@ -204,7 +206,6 @@ export default class Stickerpicker extends React.PureComponent { case "stickerpicker_close": this.props.setShowStickers(false); break; - case Action.AfterRightPanelPhaseChange: case "show_left_panel": case "hide_left_panel": this.props.setShowStickers(false); @@ -212,6 +213,10 @@ export default class Stickerpicker extends React.PureComponent { } }; + private onRightPanelStoreUpdate = () => { + this.props.setShowStickers(false); + }; + private defaultStickerpickerContent(): JSX.Element { return ( Date: Tue, 11 Jan 2022 10:30:36 +0100 Subject: [PATCH 4/4] Update src/components/views/elements/PersistentApp.tsx Co-authored-by: J. Ryan Stinnett --- src/components/views/elements/PersistentApp.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/elements/PersistentApp.tsx b/src/components/views/elements/PersistentApp.tsx index fdc871dc0c4..aba42236bb5 100644 --- a/src/components/views/elements/PersistentApp.tsx +++ b/src/components/views/elements/PersistentApp.tsx @@ -29,6 +29,7 @@ import { Container, WidgetLayoutStore } from '../../../stores/widgets/WidgetLayo import { RightPanelPhases } from '../../../stores/right-panel/RightPanelStorePhases'; import RightPanelStore from '../../../stores/right-panel/RightPanelStore'; import { UPDATE_EVENT } from '../../../stores/AsyncStore'; + interface IProps { // none }