diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 462933cbc6..71910b6f31 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -65,6 +65,7 @@ module.exports = React.createClass({ collapse_rhs: false, ready: false, width: 10000, + autoPeek: true, // by default, we peek into rooms when we try to join them }; if (s.logged_in) { if (MatrixClientPeg.get().getRooms().length) { @@ -304,6 +305,9 @@ module.exports = React.createClass({ }); break; case 'view_room': + // by default we autoPeek rooms, unless we were called explicitly with + // autoPeek=false by something like RoomDirectory who has already peeked + this.setState({ autoPeek : payload.auto_peek === false ? false : true }); this._viewRoom(payload.room_id, payload.show_settings); break; case 'view_prev_room': @@ -787,6 +791,7 @@ module.exports = React.createClass({ ); diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 5604565dd7..b4986e7a33 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -57,7 +57,9 @@ if (DEBUG_SCROLL) { module.exports = React.createClass({ displayName: 'RoomView', propTypes: { - ConferenceHandler: React.PropTypes.any + ConferenceHandler: React.PropTypes.any, + roomId: React.PropTypes.string, + autoPeek: React.PropTypes.bool, // should we try to peek the room on mount, or has whoever invoked us already initiated a peek? }, /* properties in RoomView objects include: @@ -78,7 +80,9 @@ module.exports = React.createClass({ syncState: MatrixClientPeg.get().getSyncState(), hasUnsentMessages: this._hasUnsentMessages(room), callState: null, + autoPeekDone: false, // track whether our autoPeek (if any) has completed) guestsCanJoin: false, + canPeek: false, readMarkerEventId: room ? room.getEventReadUpTo(MatrixClientPeg.get().credentials.userId) : null, readMarkerGhostEventId: undefined } @@ -86,6 +90,7 @@ module.exports = React.createClass({ componentWillMount: function() { this.dispatcherRef = dis.register(this.onAction); + MatrixClientPeg.get().on("Room", this.onNewRoom); MatrixClientPeg.get().on("Room.timeline", this.onRoomTimeline); MatrixClientPeg.get().on("Room.name", this.onRoomName); MatrixClientPeg.get().on("Room.accountData", this.onRoomAccountData); @@ -110,9 +115,13 @@ module.exports = React.createClass({ // We can't try to /join because this may implicitly accept invites (!) // We can /peek though. If it fails then we present the join UI. If it // succeeds then great, show the preview (but we still may be able to /join!). - if (!this.state.room) { + if (!this.state.room && this.props.autoPeek) { console.log("Attempting to peek into room %s", this.props.roomId); MatrixClientPeg.get().peekInRoom(this.props.roomId).done(() => { + this.setState({ + autoPeekDone: true; + }); + // we don't need to do anything - JS SDK will emit Room events // which will update the UI. We *do* however need to know if we // can join the room so we can fiddle with the UI appropriately. @@ -120,15 +129,20 @@ module.exports = React.createClass({ if (!peekedRoom) { return; } + var guestAccessEvent = peekedRoom.currentState.getStateEvents("m.room.guest_access", ""); - if (!guestAccessEvent) { - return; - } - if (guestAccessEvent.getContent().guest_access === "can_join") { + if (guestAccessEvent && guestAccessEvent.getContent().guest_access === "can_join") { this.setState({ guestsCanJoin: true }); } + + var historyVisibility = peekedRoom.currentState.getStateEvents("m.room.history_visibility", ""); + if (historyVisibility && historyVisibility.getContent().history_visibility === "world_readable") { + this.setState({ + canPeek: true + }); + } }, function(err) { console.error("Failed to peek into room: %s", err); }); @@ -155,6 +169,7 @@ module.exports = React.createClass({ } dis.unregister(this.dispatcherRef); if (MatrixClientPeg.get()) { + MatrixClientPeg.get().removeListener("Room", this.onNewRoom); MatrixClientPeg.get().removeListener("Room.timeline", this.onRoomTimeline); MatrixClientPeg.get().removeListener("Room.name", this.onRoomName); MatrixClientPeg.get().removeListener("Room.accountData", this.onRoomAccountData); @@ -278,6 +293,14 @@ module.exports = React.createClass({ }); }, + onNewRoom: function(room) { + if (room.roomId == this.props.roomId) { + this.setState({ + room: room + }); + } + }, + onRoomName: function(room) { if (room.roomId == this.props.roomId) { this.setState({ @@ -929,9 +952,10 @@ module.exports = React.createClass({ ); } + var visibilityDeferred; if (old_history_visibility != newVals.history_visibility && newVals.history_visibility != undefined) { - deferreds.push( + visibilityDeferred = MatrixClientPeg.get().sendStateEvent( this.state.room.roomId, "m.room.history_visibility", { history_visibility: newVals.history_visibility, @@ -940,6 +964,27 @@ module.exports = React.createClass({ ); } + if (old_guest_read != newVals.guest_read || + old_guest_join != newVals.guest_join) + { + var guestDeferred = + MatrixClientPeg.get().setGuestAccess(this.state.room.roomId, { + allowRead: newVals.guest_read, + allowJoin: newVals.guest_join + }); + + if (visibilityDeferred) { + visibilityDeferred = visibilityDeferred.then(guestDeferred); + } + else { + visibilityDeferred = guestDeferred; + } + } + + if (visibilityDeferred) { + deferreds.push(visibilityDeferred); + } + if (newVals.power_levels) { deferreds.push( MatrixClientPeg.get().sendStateEvent( @@ -1033,17 +1078,6 @@ module.exports = React.createClass({ ); } - if (old_guest_read != newVals.guest_read || - old_guest_join != newVals.guest_join) - { - deferreds.push( - MatrixClientPeg.get().setGuestAccess(this.state.room.roomId, { - allowRead: newVals.guest_read, - allowJoin: newVals.guest_join - }) - ); - } - if (deferreds.length) { var self = this; q.allSettled(deferreds).then( @@ -1391,12 +1425,28 @@ module.exports = React.createClass({ if (!this.state.room) { if (this.props.roomId) { - return ( -
- -
- ); - } else { + if (this.props.autoPeek && !this.state.autoPeekDone) { + return ( +
+ +
+ ); + } + else { + var joinErrorText = this.state.joinError ? "Failed to join room!" : ""; + return ( +
+ +
+ +
{joinErrorText}
+
+
+ ); + } + } + else { return (
); @@ -1417,16 +1467,21 @@ module.exports = React.createClass({ var inviteEvent = myMember.events.member; var inviterName = inviteEvent.sender ? inviteEvent.sender.name : inviteEvent.getSender(); // XXX: Leaving this intentionally basic for now because invites are about to change totally + // FIXME: This comment is now outdated - what do we need to fix? ^ var joinErrorText = this.state.joinError ? "Failed to join room!" : ""; var rejectErrorText = this.state.rejectError ? "Failed to reject invite!" : ""; + + // We deliberately don't try to peek into invites, even if we have permission to peek + // as they could be a spam vector. + // XXX: in future we could give the option of a 'Preview' button which lets them view anyway. return (
-
-
{inviterName} has invited you to a room
-
- - +
+
{joinErrorText}
{rejectErrorText}
@@ -1544,6 +1599,12 @@ module.exports = React.createClass({ ); } + else if (this.state.canPeek && + (!myMember || myMember.membership !== "join")) { + aux = ( + + ); + } var conferenceCallNotification = null; if (this.state.displayConfCallNotification) { diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 2f12c4c8e2..657aa6a4d9 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -23,33 +23,57 @@ module.exports = React.createClass({ propTypes: { onJoinClick: React.PropTypes.func, - canJoin: React.PropTypes.bool + onRejectClick: React.PropTypes.func, + inviterName: React.PropTypes.string, + canJoin: React.PropTypes.bool, + canPreview: React.PropTypes.bool, }, getDefaultProps: function() { return { onJoinClick: function() {}, - canJoin: false + canJoin: false, + canPreview: true, }; }, render: function() { - var joinBlock; + var joinBlock, previewBlock; - if (this.props.canJoin) { + if (this.props.inviter) { + joinBlock = ( +
+
+ You have been invited to join this room by { this.props.inviterName } +
+
+ Would you like to accept or + decline this invitation? +
+
+ ); + + } + else if (this.props.canJoin) { joinBlock = (
- Would you like to join this room? + Would you like to join this room? +
+ ); + } + + if (this.props.canPreview) { + previewBlock = ( +
+ This is a preview of this room. Room interactions have been disabled.
); } return (
-
- This is a preview of this room. Room interactions have been disabled. -
- {joinBlock} + { previewBlock } + { joinBlock }
); } diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js index 0ff15a4f43..f41e30091b 100644 --- a/src/components/views/rooms/RoomSettings.js +++ b/src/components/views/rooms/RoomSettings.js @@ -660,12 +660,13 @@ module.exports = React.createClass({ }
+ // FIXME: disable guests_read if the user hasn't turned on shared history return (

-
-
-
+
+
+
{ tags_section }