Fix message edition and reply when multiple rooms at displayed the same moment (#31280)

* feat: implement `ExtrasApi#setRoomIdsForSpace`

* fix: message reply with multiple room views

* fix: message edition when multiple rooms are displayed

* test: check that the view room action is not dispatch when replying

* test: check that the view room action is not dispatch when editing

* refactor: use `ExtraApis#getVisibleRoomBySpaceKey` instead of  `ExtraApis#setRoomIdsForSpace`

* test: update tests to use `getVisibleRoomBySpaceKey`
This commit is contained in:
Florian Duros
2025-11-21 15:51:23 +01:00
committed by GitHub
parent a79f6e7aa5
commit fbb43d5e61
5 changed files with 120 additions and 2 deletions

View File

@@ -1207,7 +1207,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
case Action.EditEvent: {
// Quit early if we're trying to edit events in wrong rendering context
if (payload.timelineRenderingType !== this.state.timelineRenderingType) return;
if (payload.event && payload.event.getRoomId() !== this.state.roomId) {
const roomId: string | undefined = payload.event?.getRoomId();
if (payload.event && roomId !== this.state.roomId) {
// if the room is displayed in a module, we don't want to change the room view
if (roomId && this.roomViewStore.isRoomDisplayedInModule(roomId)) return;
// If the event is in a different room (e.g. because the event to be edited is being displayed
// in the results of an all-rooms search), we need to view that room first.
defaultDispatcher.dispatch<ViewRoomPayload>({

View File

@@ -25,11 +25,16 @@ interface EmittedEvents {
export class ElementWebExtrasApi extends TypedEventEmitter<keyof EmittedEvents, EmittedEvents> implements ExtrasApi {
public spacePanelItems = new Map<string, SpacePanelItemProps>();
public visibleRoomBySpaceKey = new Map<string, () => string[]>();
public setSpacePanelItem(spacekey: string, item: SpacePanelItemProps): void {
this.spacePanelItems.set(spacekey, item);
this.emit(ExtrasApiEvent.SpacePanelItemsChanged);
}
public getVisibleRoomBySpaceKey(spaceKey: string, cb: () => string[]): void {
this.visibleRoomBySpaceKey.set(spaceKey, cb);
}
}
export function useModuleSpacePanelItems(api: ElementWebExtrasApi): ModuleSpacePanelItem[] {

View File

@@ -52,6 +52,7 @@ import { ModuleRunner } from "../modules/ModuleRunner";
import { setMarkedUnreadState } from "../utils/notifications";
import { ConnectionState, ElementCall } from "../models/Call";
import { isVideoRoom } from "../utils/video-rooms";
import { ModuleApi } from "../modules/Api";
const NUM_JOIN_RETRY = 5;
@@ -292,10 +293,15 @@ export class RoomViewStore extends EventEmitter {
case "reply_to_event":
// Thread timeline view handles its own reply-to-state
if (TimelineRenderingType.Thread !== payload.context) {
const roomId: string | undefined = payload.event?.getRoomId();
// If currently viewed room does not match the room in which we wish to reply then change rooms this
// can happen when performing a search across all rooms. Persist the data from this event for both
// room and search timeline rendering types, search will get auto-closed by RoomView at this time.
if (payload.event && payload.event.getRoomId() !== this.state.roomId) {
if (payload.event && roomId !== this.state.roomId) {
// if the room is displayed in a module, we don't want to change the room view
if (roomId && this.isRoomDisplayedInModule(roomId)) return;
this.dis?.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
room_id: payload.event.getRoomId(),
@@ -802,4 +808,16 @@ export class RoomViewStore extends EventEmitter {
ModuleRunner.instance.invoke(RoomViewLifecycle.ViewRoom, viewRoomOpts, this.getRoomId());
this.setState({ viewRoomOpts });
}
/**
* Checks if a room is already displayed in the current active space module.
* @param roomId
*/
public isRoomDisplayedInModule(roomId: string): boolean {
const currentSpace = this.stores.spaceStore.activeSpace;
const cb = ModuleApi.instance.extras.visibleRoomBySpaceKey.get(currentSpace);
if (!cb) return false;
return cb().includes(roomId);
}
}