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

Make widgets not reload (persistent) between center and top container #7575

Merged
merged 11 commits into from
Jan 24, 2022
12 changes: 6 additions & 6 deletions src/components/views/elements/AppTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export default class AppTile extends React.Component<IProps, IState> {
if (!isVisibleOnScreen && !isActiveWidget) {
ActiveWidgetStore.instance.destroyPersistentWidget(app.id);
PersistedElement.destroyElement(this.persistKey);
this.sgWidget?.stop();
this.sgWidget?.stopMessaging();
}
};

Expand All @@ -181,7 +181,7 @@ export default class AppTile extends React.Component<IProps, IState> {
if (!isActiveWidget) {
ActiveWidgetStore.instance.destroyPersistentWidget(app.id);
PersistedElement.destroyElement(this.persistKey);
this.sgWidget?.stop();
this.sgWidget?.stopMessaging();
}
};

Expand Down Expand Up @@ -217,7 +217,7 @@ export default class AppTile extends React.Component<IProps, IState> {
// Force the widget to be non-persistent (able to be deleted/forgotten)
ActiveWidgetStore.instance.destroyPersistentWidget(this.props.app.id);
PersistedElement.destroyElement(this.persistKey);
this.sgWidget?.stop();
this.sgWidget?.stopMessaging();
}

this.setState({ hasPermissionToLoad });
Expand Down Expand Up @@ -260,7 +260,7 @@ export default class AppTile extends React.Component<IProps, IState> {
}

private resetWidget(newProps: IProps): void {
this.sgWidget?.stop();
this.sgWidget?.stopMessaging();
try {
this.sgWidget = new StopGapWidget(newProps);
this.sgWidget.on("preparing", this.onWidgetPreparing);
Expand All @@ -282,7 +282,7 @@ export default class AppTile extends React.Component<IProps, IState> {
this.iframe = ref;
if (ref) {
try {
this.sgWidget?.start(ref);
this.sgWidget?.startMessaging(ref);
} catch (e) {
logger.error("Failed to start widget", e);
}
Expand Down Expand Up @@ -335,7 +335,7 @@ export default class AppTile extends React.Component<IProps, IState> {
PersistedElement.destroyElement(this.persistKey);
ActiveWidgetStore.instance.destroyPersistentWidget(this.props.app.id);

this.sgWidget?.stop({ forceDestroy: true });
this.sgWidget?.stopMessaging({ forceDestroy: true });
}

private onWidgetPreparing = (): void => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/rooms/AppsDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ export default class AppsDrawer extends React.Component<IProps, IState> {
drawer = <PersistentVResizer
room={this.props.room}
minHeight={100}
maxHeight={(this.props.maxHeight || !widgetIsMaxmised) ? this.props.maxHeight - 50 : undefined}
maxHeight={this.props.maxHeight - 50}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all changes to this file are unrelated. If you want me to I can make a different pr. It was just super convinient and simple to include them right after I found them without switching branches.

handleClass="mx_AppsContainer_resizerHandle"
handleWrapperClass="mx_AppsContainer_resizerHandleContainer"
className="mx_AppsContainer_resizer"
Expand Down
60 changes: 28 additions & 32 deletions src/stores/right-panel/RightPanelStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { EventSubscription } from 'fbemitter';
import { logger } from "matrix-js-sdk/src/logger";

import defaultDispatcher from '../../dispatcher/dispatcher';
import { pendingVerificationRequestForUser } from '../../verification';
import SettingsStore from "../../settings/SettingsStore";
import { RightPanelPhases } from "./RightPanelStorePhases";
import { ActionPayload } from "../../dispatcher/payloads";
import { Action } from '../../dispatcher/actions';
import { SettingLevel } from "../../settings/SettingLevel";
import { UPDATE_EVENT } from '../AsyncStore';
import { ReadyWatchingStore } from '../ReadyWatchingStore';
Expand All @@ -32,21 +32,14 @@ import {
IRightPanelForRoom,
} from './RightPanelStoreIPanelState';
import { MatrixClientPeg } from "../../MatrixClientPeg";
// import RoomViewStore from '../RoomViewStore';

import RoomViewStore from '../RoomViewStore';
jryans marked this conversation as resolved.
Show resolved Hide resolved
const GROUP_PHASES = [
RightPanelPhases.GroupMemberList,
RightPanelPhases.GroupRoomList,
RightPanelPhases.GroupRoomInfo,
RightPanelPhases.GroupMemberInfo,
];

const MEMBER_INFO_PHASES = [
RightPanelPhases.RoomMemberInfo,
RightPanelPhases.Room3pidMemberInfo,
RightPanelPhases.EncryptionPanel,
];

/**
* A class for tracking the state of the right panel between layouts and
* sessions. This state includes a history for each room. Each history element
Expand All @@ -68,6 +61,8 @@ export default class RightPanelStore extends ReadyWatchingStore {
[roomId: string]: IRightPanelForRoom;
} = {};

private roomStoreToken: EventSubscription;

private constructor() {
super(defaultDispatcher);
this.dispatcherRefRightPanelStore = defaultDispatcher.register(this.onDispatch);
Expand All @@ -76,8 +71,9 @@ export default class RightPanelStore extends ReadyWatchingStore {
protected async onReady(): Promise<any> {
this.isReady = true;
// TODO RightPanelStore (will be addressed when dropping groups): This should be used instead of the onDispatch callback when groups are removed.
jryans marked this conversation as resolved.
Show resolved Hide resolved
// RoomViewStore.on(UPDATE_EVENT, this.onRoomViewStoreUpdate);
this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate);
MatrixClientPeg.get().on("crypto.verification.request", this.onVerificationRequestUpdate);
this.viewedRoomId = RoomViewStore.getRoomId();
this.loadCacheFromSettings();
this.emitAndUpdateSettings();
}
Expand All @@ -91,8 +87,7 @@ export default class RightPanelStore extends ReadyWatchingStore {
protected async onNotReady(): Promise<any> {
this.isReady = false;
MatrixClientPeg.get().off("crypto.verification.request", this.onVerificationRequestUpdate);
// TODO RightPanelStore (will be addressed when dropping groups): User this instead of the dispatcher.
// RoomViewStore.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
this.roomStoreToken.remove();
}

// Getters
Expand Down Expand Up @@ -373,45 +368,46 @@ export default class RightPanelStore extends ReadyWatchingStore {
};

onRoomViewStoreUpdate = () => {
// TODO: use this function instead of the onDispatch (the whole onDispatch can get removed!) as soon groups are removed
// this.viewedRoomId = RoomViewStore.getRoomId();
// this.isViewingRoom = true; // Is viewing room will of course be removed when removing groups
// // load values from byRoomCache with the viewedRoomId.
// this.loadCacheFromSettings();
// TODO: only use this function instead of the onDispatch (the whole onDispatch can get removed!) as soon groups are removed
this.viewedRoomId = RoomViewStore.getRoomId();
this.isViewingRoom = true; // Is viewing room will of course be removed when removing groups
// load values from byRoomCache with the viewedRoomId.
this.loadCacheFromSettings();
this.emitAndUpdateSettings();
};

onDispatch = (payload: ActionPayload) => {
switch (payload.action) {
case 'view_group':
case Action.ViewRoom: {
case 'view_group': {
if (payload.room_id === this.viewedRoomId) break; // skip this transition, probably a permalink

// Put group in the same/similar view to what was open from the previously viewed room
// Is contradictory to the new "per room" philosophy but it is the legacy behavior for groups.
if ((this.isViewingRoom ? Action.ViewRoom : "view_group") != payload.action) {
if (payload.action == Action.ViewRoom && MEMBER_INFO_PHASES.includes(this.currentCard?.phase)) {
// switch from group to room
this.setRightPanelCache({ phase: RightPanelPhases.RoomMemberList, state: {} });
} else if (
payload.action == "view_group" &&
this.currentCard?.phase === RightPanelPhases.GroupMemberInfo
) {
// switch from room to group
this.setRightPanelCache({ phase: RightPanelPhases.GroupMemberList, state: {} });
}

if (
this.currentCard?.phase === RightPanelPhases.GroupMemberInfo
) {
// switch from room to group
this.setRightPanelCache({ phase: RightPanelPhases.GroupMemberList, state: {} });
}

// Update the current room here, so that all the other functions dont need to be room dependant.
// The right panel store always will return the state for the current room.
this.viewedRoomId = payload.room_id;
this.isViewingRoom = payload.action == Action.ViewRoom;
this.isViewingRoom = false;
// load values from byRoomCache with the viewedRoomId.
if (this.isReady) {
// we need the client to be ready to get the events form the ids of the settings
// the loading will be done in the onReady function (to catch up with the changes done here before it was ready)
// all the logic in this case is not necessary anymore as soon as groups are dropped and we use: onRoomViewStoreUpdate
this.loadCacheFromSettings();
this.emitAndUpdateSettings();

/*
DO NOT EMIT. Emitting breaks iframe refs by triggering a render
for the room view and calling the iframe ref changed
function
*/
jryans marked this conversation as resolved.
Show resolved Hide resolved
// this.emitAndUpdateSettings();
}
break;
}
Expand Down
16 changes: 13 additions & 3 deletions src/stores/widgets/StopGapWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,12 @@ export class StopGapWidget extends EventEmitter {
});
}
};

public start(iframe: HTMLIFrameElement) {
/**
* This starts the messaging for the widget if it is not in the state `started` yet.
* @param iframe the iframe the widget should use
* @returns
jryans marked this conversation as resolved.
Show resolved Hide resolved
*/
public startMessaging(iframe: HTMLIFrameElement): any {
if (this.started) return;
const allowedCapabilities = this.appTileProps.whitelistCapabilities || [];
const driver = new StopGapWidgetDriver(allowedCapabilities, this.mockWidget, this.kind, this.roomId);
Expand Down Expand Up @@ -407,7 +411,13 @@ export class StopGapWidget extends EventEmitter {
}
}

public stop(opts = { forceDestroy: false }) {
/**
* Stops the widget messaging for if it is started. Skips stopping if it is an active
* widget.
* @param opts
* @returns
jryans marked this conversation as resolved.
Show resolved Hide resolved
*/
public stopMessaging(opts = { forceDestroy: false }) {
if (!opts?.forceDestroy && ActiveWidgetStore.instance.getPersistentWidgetId() === this.mockWidget.id) {
logger.log("Skipping destroy - persistent widget");
return;
Expand Down