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

Control currently viewed event via RoomViewStore #1058

Merged
merged 19 commits into from
Jun 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/components/structures/LoggedInView.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,8 @@ export default React.createClass({
ref='roomView'
autoJoin={this.props.autoJoin}
onRegistered={this.props.onRegistered}
eventId={this.props.initialEventId}
thirdPartyInvite={this.props.thirdPartyInvite}
oobData={this.props.roomOobData}
highlightedEventId={this.props.highlightedEventId}
eventPixelOffset={this.props.initialEventPixelOffset}
key={this.props.currentRoomId || 'roomview'}
opacity={this.props.middleOpacity}
Expand Down
32 changes: 9 additions & 23 deletions src/components/structures/MatrixChat.js
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,8 @@ module.exports = React.createClass({
// @param {boolean=} roomInfo.show_settings Makes RoomView show the room settings dialog.
// @param {string=} roomInfo.event_id ID of the event in this room to show: this will cause a switch to the
// context of that particular event.
// @param {boolean=} roomInfo.highlighted If true, add event_id to the hash of the URL
Copy link
Member

Choose a reason for hiding this comment

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

surely it means way more than that? like, the event will also be highlighted in the view.

Bear in mind this is documenting the parameters on the view_room more than the parameters to the function - the docs just got left behind when view_room started going to more places :/

Copy link
Contributor Author

@lukebarnard1 lukebarnard1 Jun 8, 2017

Choose a reason for hiding this comment

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

I don't think we should document things that happen elsewhere. If someone wants to know what the view_room dispatch does, they should look for all the things that receive it (namely, RoomViewStore).

Copy link
Member

Choose a reason for hiding this comment

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

I'm not convinced by that. The view_room dispatch is an API, like any other. You don't refuse to document your methods and say "look at these other methods which I call". I want to know: what does it mean, conceptually, to set the 'highlighted' param in a view_room dispatch. I don't think at its heart it means 'add the event_id' to the location bar.

There's a (very strong) argument that this is not the place for that documentation, but we have nowhere else right now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, but I feel that someone is going to get confused when the documentation for this function doesn't match what the function does.

// and alter the EventTile to appear highlighted.
// @param {Object=} roomInfo.third_party_invite Object containing data about the third party
// we received to join the room, if any.
// @param {string=} roomInfo.third_party_invite.inviteSignUrl 3pid invite sign URL
Expand All @@ -618,40 +620,20 @@ module.exports = React.createClass({
this.focusComposer = true;

const newState = {
initialEventId: roomInfo.event_id,
highlightedEventId: roomInfo.event_id,
initialEventPixelOffset: undefined,
page_type: PageTypes.RoomView,
thirdPartyInvite: roomInfo.third_party_invite,
roomOobData: roomInfo.oob_data,
currentRoomAlias: roomInfo.room_alias,
autoJoin: roomInfo.auto_join,
};

if (!roomInfo.room_alias) {
newState.currentRoomId = roomInfo.room_id;
}

// if we aren't given an explicit event id, look for one in the
// scrollStateMap.
//
// TODO: do this in RoomView rather than here
if (!roomInfo.event_id && this.refs.loggedInView) {
const scrollState = this.refs.loggedInView.getScrollStateForRoom(roomInfo.room_id);
if (scrollState) {
newState.initialEventId = scrollState.focussedEvent;
newState.initialEventPixelOffset = scrollState.pixelOffset;
}
}

if (roomInfo.room_alias) {
console.log(
`Switching to room alias ${roomInfo.room_alias} at event ` +
newState.initialEventId,
roomInfo.event_id,
);
} else {
console.log(`Switching to room id ${roomInfo.room_id} at event ` +
newState.initialEventId,
roomInfo.event_id,
);
}

Expand Down Expand Up @@ -680,7 +662,7 @@ module.exports = React.createClass({
}
}

if (roomInfo.event_id) {
if (roomInfo.event_id && roomInfo.highlighted) {
Copy link
Member

Choose a reason for hiding this comment

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

can you add this to the jsdoc please

presentedId += "/" + roomInfo.event_id;
}
this.notifyNewScreen('room/' + presentedId);
Expand Down Expand Up @@ -1137,6 +1119,10 @@ module.exports = React.createClass({
const payload = {
action: 'view_room',
event_id: eventId,
// If an event ID is given in the URL hash, notify RoomViewStore to mark
// it as highlighted, which will propagate to RoomView and highlight the
// associated EventTile.
highlighted: Boolean(eventId),
third_party_invite: thirdPartyInvite,
oob_data: oobData,
};
Expand Down
108 changes: 52 additions & 56 deletions src/components/structures/RoomView.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,36 +83,8 @@ module.exports = React.createClass({
// * invited us tovthe room
oobData: React.PropTypes.object,

// id of an event to jump to. If not given, will go to the end of the
// live timeline.
eventId: React.PropTypes.string,

// where to position the event given by eventId, in pixels from the
// bottom of the viewport. If not given, will try to put the event
// 1/3 of the way down the viewport.
eventPixelOffset: React.PropTypes.number,

// ID of an event to highlight. If undefined, no event will be highlighted.
// Typically this will either be the same as 'eventId', or undefined.
highlightedEventId: React.PropTypes.string,

// is the RightPanel collapsed?
collapsedRhs: React.PropTypes.bool,

// a map from room id to scroll state, which will be updated on unmount.
//
// 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: React.PropTypes.object,
},

getInitialState: function() {
Expand All @@ -122,6 +94,13 @@ module.exports = React.createClass({
roomLoading: true,
peekLoading: false,

// The event to be scrolled to initially
initialEventId: null,
// The offset in pixels from the event with which to scroll vertically
initialEventPixelOffset: null,
// Whether to highlight the event scrolled to
isInitialEventHighlighted: null,

forwardingEvent: null,
editingRoomSettings: false,
uploadingRoomSettings: false,
Expand Down Expand Up @@ -180,13 +159,32 @@ module.exports = React.createClass({
if (this.unmounted) {
return;
}
this.setState({
const newState = {
roomId: RoomViewStore.getRoomId(),
roomAlias: RoomViewStore.getRoomAlias(),
roomLoading: RoomViewStore.isRoomLoading(),
roomLoadError: RoomViewStore.getRoomLoadError(),
joining: RoomViewStore.isJoining(),
}, () => {
initialEventId: RoomViewStore.getInitialEventId(),
initialEventPixelOffset: RoomViewStore.getInitialEventPixelOffset(),
isInitialEventHighlighted: RoomViewStore.isInitialEventHighlighted(),
};

// 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.
this._onHaveRoom();
this.onRoom(MatrixClientPeg.get().getRoom(this.state.roomId));
});
Expand Down Expand Up @@ -287,13 +285,6 @@ module.exports = React.createClass({
}
},

componentWillReceiveProps: function(newProps) {
if (newProps.eventId != this.props.eventId) {
// when we change focussed event id, hide the search results.
this.setState({searchResults: null});
}
},

shouldComponentUpdate: function(nextProps, nextState) {
return (!ObjectUtils.shallowEqual(this.props, nextProps) ||
!ObjectUtils.shallowEqual(this.state, nextState));
Expand All @@ -319,7 +310,7 @@ module.exports = React.createClass({
this.unmounted = true;

// update the scroll map before we get unmounted
this._updateScrollMap();
this._updateScrollMap(this.state.roomId);

if (this.refs.roomView) {
// disconnect the D&D event listeners from the room view. This
Expand Down Expand Up @@ -598,6 +589,18 @@ 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;
Expand Down Expand Up @@ -1240,21 +1243,6 @@ module.exports = React.createClass({
}
},

// update scrollStateMap on unmount
_updateScrollMap: function() {
if (!this.state.room) {
// we were instantiated on a room alias and haven't yet joined the room.
return;
}
if (!this.props.scrollStateMap) return;

var roomId = this.state.room.roomId;

var state = this._getScrollState();
this.props.scrollStateMap[roomId] = state;
},


// get the current scroll position of the room, so that it can be
// restored when we switch back to it.
//
Expand Down Expand Up @@ -1677,16 +1665,24 @@ module.exports = React.createClass({
hideMessagePanel = true;
}

const shouldHighlight = this.state.isInitialEventHighlighted;
let highlightedEventId = null;
if (this.state.forwardingEvent) {
highlightedEventId = this.state.forwardingEvent.getId();
} else if (shouldHighlight) {
highlightedEventId = this.state.initialEventId;
}

// console.log("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview);
var messagePanel = (
<TimelinePanel ref={this._gatherTimelinePanelRef}
timelineSet={this.state.room.getUnfilteredTimelineSet()}
manageReadReceipts={!UserSettingsStore.getSyncedSetting('hideReadReceipts', false)}
manageReadMarkers={true}
hidden={hideMessagePanel}
highlightedEventId={this.state.forwardingEvent ? this.state.forwardingEvent.getId() : this.props.highlightedEventId}
eventId={this.props.eventId}
eventPixelOffset={this.props.eventPixelOffset}
highlightedEventId={highlightedEventId}
eventId={this.state.initialEventId}
eventPixelOffset={this.state.initialEventPixelOffset}
onScroll={ this.onMessageListScroll }
onReadMarkerUpdated={ this._updateTopUnreadMessagesBar }
showUrlPreview = { this.state.showUrlPreview }
Expand Down
1 change: 1 addition & 0 deletions src/components/views/rooms/EventTile.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ module.exports = WithMatrixClient(React.createClass({
dis.dispatch({
action: 'view_room',
event_id: this.props.mxEvent.getId(),
highlighted: true,
room_id: this.props.mxEvent.getRoomId(),
});
},
Expand Down
Loading