Control currently viewied event via RoomViewStore
Fix for https://github.com/vector-im/riot-web/issues/4224 Due to the way `MatrixChat` does a state update when the `view_room` dispatch fires and a second update when `RoomViewStore` sends an update, the current event ID and room ID were becoming out of sync. The solution devised was to have the event ID managed by the `RoomViewStore` itself and do any defaulting there (for when we revisit a room that we saved scroll state for previously). This required a few changes: - The addition of `update_scroll_state` in `RoomViewStore` allows the `RoomView` to save scroll state for a room before swapping to another one. Previously the caching of scroll state was done in `RoomView`. - The `view_room` dispatch now accepts an `event_id`, which dictates which event is supposed to be scrolled to in the `MessagePanel` when a new room is viewed. It also accepts `event_offset`, but currently, this isn't passed in by a dispatch in the app, but it is clobbered when loading the default position when an `event_id` isn't specified. Finally, `highlighted` was added to distinguish whether the initial event being scrolled to is also highlighted. This flag is also used by `viewRoom` in `MatrixChat` in order to decide whether to `notifyNewScreen` with the specified `event_id`.
This commit is contained in:
parent
ea02d8841c
commit
d3cf78ff5a
5 changed files with 109 additions and 78 deletions
|
@ -27,12 +27,32 @@ const INITIAL_STATE = {
|
|||
joinError: null,
|
||||
// The room ID of the room
|
||||
roomId: null,
|
||||
// The event being viewed
|
||||
eventId: null,
|
||||
// The offset to display the event at (see scrollStateMap)
|
||||
eventPixelOffset: null,
|
||||
// Whether to highlight the event
|
||||
isEventHighlighted: false,
|
||||
// The room alias of the room (or null if not originally specified in view_room)
|
||||
roomAlias: null,
|
||||
// Whether the current room is loading
|
||||
roomLoading: false,
|
||||
// Any error that has occurred during loading
|
||||
roomLoadError: null,
|
||||
// A map from room id to scroll state.
|
||||
//
|
||||
// If there is no special scroll state (ie, we are following the live
|
||||
// timeline), the scroll state is null. Otherwise, it is an object with
|
||||
// the following properties:
|
||||
//
|
||||
// focussedEvent: the ID of the 'focussed' event. Typically this is
|
||||
// the last event fully visible in the viewport, though if we
|
||||
// have done an explicit scroll to an explicit event, it will be
|
||||
// that event.
|
||||
//
|
||||
// pixelOffset: the number of pixels the window is scrolled down
|
||||
// from the focussedEvent.
|
||||
scrollStateMap: {},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -56,8 +76,11 @@ class RoomViewStore extends Store {
|
|||
__onDispatch(payload) {
|
||||
switch (payload.action) {
|
||||
// view_room:
|
||||
// - room_alias: '#somealias:matrix.org'
|
||||
// - room_id: '!roomid123:matrix.org'
|
||||
// - room_alias: '#somealias:matrix.org'
|
||||
// - room_id: '!roomid123:matrix.org'
|
||||
// - event_id: '$213456782:matrix.org'
|
||||
// - event_offset: 100
|
||||
// - highlighted: true
|
||||
case 'view_room':
|
||||
this._viewRoom(payload);
|
||||
break;
|
||||
|
@ -88,20 +111,39 @@ class RoomViewStore extends Store {
|
|||
case 'on_logged_out':
|
||||
this.reset();
|
||||
break;
|
||||
case 'update_scroll_state':
|
||||
this._updateScrollState(payload);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_viewRoom(payload) {
|
||||
// Always set the room ID if present
|
||||
if (payload.room_id) {
|
||||
// If an event ID wasn't specified, default to the one saved for this room
|
||||
// via update_scroll_state. Also assume event_offset should be set.
|
||||
if (!payload.event_id) {
|
||||
const roomScrollState = this._state.scrollStateMap[payload.room_id];
|
||||
if (roomScrollState) {
|
||||
payload.event_id = roomScrollState.focussedEvent;
|
||||
payload.event_offset = roomScrollState.pixelOffset;
|
||||
}
|
||||
}
|
||||
|
||||
this._setState({
|
||||
roomId: payload.room_id,
|
||||
eventId: payload.event_id,
|
||||
eventPixelOffset: payload.event_offset,
|
||||
isEventHighlighted: payload.highlighted,
|
||||
roomLoading: false,
|
||||
roomLoadError: null,
|
||||
});
|
||||
} else if (payload.room_alias) {
|
||||
// Resolve the alias and then do a second dispatch with the room ID acquired
|
||||
this._setState({
|
||||
roomId: null,
|
||||
eventId: null,
|
||||
eventPixelOffset: null,
|
||||
isEventHighlighted: null,
|
||||
roomAlias: payload.room_alias,
|
||||
roomLoading: true,
|
||||
roomLoadError: null,
|
||||
|
@ -111,6 +153,8 @@ class RoomViewStore extends Store {
|
|||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: result.room_id,
|
||||
event_id: payload.event_id,
|
||||
highlighted: payload.highlighted,
|
||||
room_alias: payload.room_alias,
|
||||
});
|
||||
}, (err) => {
|
||||
|
@ -168,6 +212,15 @@ class RoomViewStore extends Store {
|
|||
});
|
||||
}
|
||||
|
||||
_updateScrollState(payload) {
|
||||
// Clobber existing scroll state for the given room ID
|
||||
const newScrollStateMap = this._state.scrollStateMap;
|
||||
newScrollStateMap[payload.room_id] = payload.scroll_state;
|
||||
this._setState({
|
||||
scrollStateMap: newScrollStateMap,
|
||||
});
|
||||
}
|
||||
|
||||
reset() {
|
||||
this._state = Object.assign({}, INITIAL_STATE);
|
||||
}
|
||||
|
@ -176,6 +229,18 @@ class RoomViewStore extends Store {
|
|||
return this._state.roomId;
|
||||
}
|
||||
|
||||
getEventId() {
|
||||
return this._state.eventId;
|
||||
}
|
||||
|
||||
getEventPixelOffset() {
|
||||
return this._state.eventPixelOffset;
|
||||
}
|
||||
|
||||
isEventHighlighted() {
|
||||
return this._state.isEventHighlighted;
|
||||
}
|
||||
|
||||
getRoomAlias() {
|
||||
return this._state.roomAlias;
|
||||
}
|
||||
|
@ -195,7 +260,6 @@ class RoomViewStore extends Store {
|
|||
getJoinError() {
|
||||
return this._state.joinError;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let singletonRoomViewStore = null;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue