mirror of https://github.com/vector-im/riot-web
Merge pull request #1367 from matrix-org/dbkr/scroll_state_store
Introduce a RoomScrollStateStorepull/21833/head
commit
a012dbafce
|
@ -47,6 +47,7 @@ import KeyCode from '../../KeyCode';
|
|||
import UserProvider from '../../autocomplete/UserProvider';
|
||||
|
||||
import RoomViewStore from '../../stores/RoomViewStore';
|
||||
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
||||
|
||||
let DEBUG = false;
|
||||
let debuglog = function() {};
|
||||
|
@ -163,7 +164,6 @@ module.exports = React.createClass({
|
|||
roomLoadError: RoomViewStore.getRoomLoadError(),
|
||||
joining: RoomViewStore.isJoining(),
|
||||
initialEventId: RoomViewStore.getInitialEventId(),
|
||||
initialEventPixelOffset: RoomViewStore.getInitialEventPixelOffset(),
|
||||
isInitialEventHighlighted: RoomViewStore.isInitialEventHighlighted(),
|
||||
forwardingEvent: RoomViewStore.getForwardingEvent(),
|
||||
shouldPeek: RoomViewStore.shouldPeek(),
|
||||
|
@ -191,18 +191,26 @@ module.exports = React.createClass({
|
|||
newState.room = MatrixClientPeg.get().getRoom(newState.roomId);
|
||||
}
|
||||
|
||||
if (this.state.roomId === null && newState.roomId !== null) {
|
||||
// Get the scroll state for the new room
|
||||
|
||||
// If an event ID wasn't specified, default to the one saved for this room
|
||||
// in the scroll state store. Assume initialEventPixelOffset should be set.
|
||||
if (!newState.initialEventId) {
|
||||
const roomScrollState = RoomScrollStateStore.getScrollState(newState.roomId);
|
||||
if (roomScrollState) {
|
||||
newState.initialEventId = roomScrollState.focussedEvent;
|
||||
newState.initialEventPixelOffset = roomScrollState.pixelOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the search results when clicking a search result (which changes the
|
||||
// currently scrolled to event, this.state.initialEventId).
|
||||
if (this.state.initialEventId !== newState.initialEventId) {
|
||||
newState.searchResults = null;
|
||||
}
|
||||
|
||||
// Store the scroll state for the previous room so that we can return to this
|
||||
// position when viewing this room in future.
|
||||
if (this.state.roomId !== newState.roomId) {
|
||||
this._updateScrollMap(this.state.roomId);
|
||||
}
|
||||
|
||||
this.setState(newState, () => {
|
||||
// At this point, this.state.roomId could be null (e.g. the alias might not
|
||||
// have been resolved yet) so anything called here must handle this case.
|
||||
|
@ -340,7 +348,9 @@ module.exports = React.createClass({
|
|||
this.unmounted = true;
|
||||
|
||||
// update the scroll map before we get unmounted
|
||||
this._updateScrollMap(this.state.roomId);
|
||||
if (this.state.roomId) {
|
||||
RoomScrollStateStore.setScrollState(this.state.roomId, this._getScrollState());
|
||||
}
|
||||
|
||||
if (this.refs.roomView) {
|
||||
// disconnect the D&D event listeners from the room view. This
|
||||
|
@ -617,18 +627,6 @@ module.exports = React.createClass({
|
|||
});
|
||||
},
|
||||
|
||||
_updateScrollMap(roomId) {
|
||||
// No point updating scroll state if the room ID hasn't been resolved yet
|
||||
if (!roomId) {
|
||||
return;
|
||||
}
|
||||
dis.dispatch({
|
||||
action: 'update_scroll_state',
|
||||
room_id: roomId,
|
||||
scroll_state: this._getScrollState(),
|
||||
});
|
||||
},
|
||||
|
||||
onRoom: function(room) {
|
||||
if (!room || room.roomId !== this.state.roomId) {
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Copyright 2017 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stores where the user has scrolled to in each room
|
||||
*/
|
||||
class RoomScrollStateStore {
|
||||
constructor() {
|
||||
// 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.
|
||||
this._scrollStateMap = {};
|
||||
}
|
||||
|
||||
getScrollState(roomId) {
|
||||
return this._scrollStateMap[roomId];
|
||||
}
|
||||
|
||||
setScrollState(roomId, scrollState) {
|
||||
this._scrollStateMap[roomId] = scrollState;
|
||||
}
|
||||
}
|
||||
|
||||
if (global.mx_RoomScrollStateStore === undefined) {
|
||||
global.mx_RoomScrollStateStore = new RoomScrollStateStore();
|
||||
}
|
||||
export default global.mx_RoomScrollStateStore;
|
|
@ -30,8 +30,6 @@ const INITIAL_STATE = {
|
|||
|
||||
// The event to scroll to when the room is first viewed
|
||||
initialEventId: null,
|
||||
// The offset to display the initial event at (see scrollStateMap)
|
||||
initialEventPixelOffset: null,
|
||||
// Whether to highlight the initial event
|
||||
isInitialEventHighlighted: false,
|
||||
|
||||
|
@ -41,20 +39,6 @@ const INITIAL_STATE = {
|
|||
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: {},
|
||||
|
||||
forwardingEvent: null,
|
||||
};
|
||||
|
@ -115,9 +99,6 @@ class RoomViewStore extends Store {
|
|||
case 'on_logged_out':
|
||||
this.reset();
|
||||
break;
|
||||
case 'update_scroll_state':
|
||||
this._updateScrollState(payload);
|
||||
break;
|
||||
case 'forward_event':
|
||||
this._setState({
|
||||
forwardingEvent: payload.event,
|
||||
|
@ -132,7 +113,6 @@ class RoomViewStore extends Store {
|
|||
roomId: payload.room_id,
|
||||
roomAlias: payload.room_alias,
|
||||
initialEventId: payload.event_id,
|
||||
initialEventPixelOffset: undefined,
|
||||
isInitialEventHighlighted: payload.highlighted,
|
||||
forwardingEvent: null,
|
||||
roomLoading: false,
|
||||
|
@ -145,16 +125,6 @@ class RoomViewStore extends Store {
|
|||
newState.joining = false;
|
||||
}
|
||||
|
||||
// If an event ID wasn't specified, default to the one saved for this room
|
||||
// via update_scroll_state. Assume initialEventPixelOffset should be set.
|
||||
if (!newState.initialEventId) {
|
||||
const roomScrollState = this._state.scrollStateMap[payload.room_id];
|
||||
if (roomScrollState) {
|
||||
newState.initialEventId = roomScrollState.focussedEvent;
|
||||
newState.initialEventPixelOffset = roomScrollState.pixelOffset;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._state.forwardingEvent) {
|
||||
dis.dispatch({
|
||||
action: 'send_event',
|
||||
|
@ -241,15 +211,6 @@ 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);
|
||||
}
|
||||
|
@ -264,11 +225,6 @@ class RoomViewStore extends Store {
|
|||
return this._state.initialEventId;
|
||||
}
|
||||
|
||||
// The offset to display the initial event at (see scrollStateMap)
|
||||
getInitialEventPixelOffset() {
|
||||
return this._state.initialEventPixelOffset;
|
||||
}
|
||||
|
||||
// Whether to highlight the initial event
|
||||
isInitialEventHighlighted() {
|
||||
return this._state.isInitialEventHighlighted;
|
||||
|
|
Loading…
Reference in New Issue