Merge pull request #1566 from matrix-org/luke/groups-room-publicity

Add toggle to alter visibility of a room-group association
This commit is contained in:
David Baker 2017-11-02 15:38:03 +00:00 committed by GitHub
commit 7c17ad8509
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 100 additions and 19 deletions

View file

@ -21,7 +21,6 @@ import dis from '../../../dispatcher';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import sdk from '../../../index'; import sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import { GroupRoomType } from '../../../groups';
import GroupStoreCache from '../../../stores/GroupStoreCache'; import GroupStoreCache from '../../../stores/GroupStoreCache';
import GeminiScrollbar from 'react-gemini-scrollbar'; import GeminiScrollbar from 'react-gemini-scrollbar';
@ -34,13 +33,15 @@ module.exports = React.createClass({
propTypes: { propTypes: {
groupId: PropTypes.string, groupId: PropTypes.string,
groupRoom: GroupRoomType, groupRoomId: PropTypes.string,
}, },
getInitialState: function() { getInitialState: function() {
return { return {
removingRoom: false,
isUserPrivilegedInGroup: null, isUserPrivilegedInGroup: null,
groupRoom: null,
groupRoomPublicityLoading: false,
groupRoomRemoveLoading: false,
}; };
}, },
@ -55,6 +56,10 @@ module.exports = React.createClass({
} }
}, },
componentWillUnmount() {
this._unregisterGroupStore();
},
_initGroupStore(groupId) { _initGroupStore(groupId) {
this._groupStore = GroupStoreCache.getGroupStore( this._groupStore = GroupStoreCache.getGroupStore(
this.context.matrixClient, this.props.groupId, this.context.matrixClient, this.props.groupId,
@ -68,15 +73,24 @@ module.exports = React.createClass({
} }
}, },
_updateGroupRoom() {
this.setState({
groupRoom: this._groupStore.getGroupRooms().find(
(r) => r.roomId === this.props.groupRoomId,
),
});
},
onGroupStoreUpdated: function() { onGroupStoreUpdated: function() {
this.setState({ this.setState({
isUserPrivilegedInGroup: this._groupStore.isUserPrivileged(), isUserPrivilegedInGroup: this._groupStore.isUserPrivileged(),
}); });
this._updateGroupRoom();
}, },
_onRemove: function(e) { _onRemove: function(e) {
const groupId = this.props.groupId; const groupId = this.props.groupId;
const roomName = this.props.groupRoom.displayname; const roomName = this.state.groupRoom.displayname;
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
@ -86,9 +100,9 @@ module.exports = React.createClass({
button: _t("Remove"), button: _t("Remove"),
onFinished: (proceed) => { onFinished: (proceed) => {
if (!proceed) return; if (!proceed) return;
this.setState({removingRoom: true}); this.setState({groupRoomRemoveLoading: true});
const groupId = this.props.groupId; const groupId = this.props.groupId;
const roomId = this.props.groupRoom.roomId; const roomId = this.props.groupRoomId;
this._groupStore.removeRoomFromGroup(roomId).then(() => { this._groupStore.removeRoomFromGroup(roomId).then(() => {
dis.dispatch({ dis.dispatch({
action: "view_group_room_list", action: "view_group_room_list",
@ -103,7 +117,7 @@ module.exports = React.createClass({
), ),
}); });
}).finally(() => { }).finally(() => {
this.setState({removingRoom: false}); this.setState({groupRoomRemoveLoading: false});
}); });
}, },
}); });
@ -115,13 +129,41 @@ module.exports = React.createClass({
}); });
}, },
_changeGroupRoomPublicity(e) {
const isPublic = e.target.value === "public";
this.setState({
groupRoomPublicityLoading: true,
});
const groupId = this.props.groupId;
const roomId = this.props.groupRoomId;
const roomName = this.state.groupRoom.displayname;
this._groupStore.updateGroupRoomAssociation(roomId, isPublic).catch((err) => {
console.error(`Error whilst changing visibility of ${roomId} in ${groupId} to ${isPublic}`, err);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to remove room from group', '', ErrorDialog, {
title: _t("Something went wrong!"),
description: _t(
"The visibility of '%(roomName)s' in %(groupId)s could not be updated.",
{roomName, groupId},
),
});
}).finally(() => {
this.setState({
groupRoomPublicityLoading: false,
});
});
},
render: function() { render: function() {
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
const EmojiText = sdk.getComponent('elements.EmojiText'); const EmojiText = sdk.getComponent('elements.EmojiText');
const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
if (this.state.removingRoom) { const InlineSpinner = sdk.getComponent('elements.InlineSpinner');
if (this.state.groupRoomRemoveLoading || !this.state.groupRoom) {
const Spinner = sdk.getComponent("elements.Spinner"); const Spinner = sdk.getComponent("elements.Spinner");
return <Spinner />; return <div className="mx_MemberInfo">
<Spinner />
</div>;
} }
let adminTools; let adminTools;
@ -134,20 +176,50 @@ module.exports = React.createClass({
{ _t('Remove from community') } { _t('Remove from community') }
</AccessibleButton> </AccessibleButton>
</div> </div>
<h3>
{ _t('Visibility in Room List') }
{ this.state.groupRoomPublicityLoading ?
<InlineSpinner /> : <div />
}
</h3>
<div>
<label>
<input type="radio"
value="public"
checked={this.state.groupRoom.isPublic}
onClick={this._changeGroupRoomPublicity}
/>
<div className="mx_MemberInfo_label_text">
{ _t('Visible to everyone') }
</div>
</label>
</div>
<div>
<label>
<input type="radio"
value="private"
checked={!this.state.groupRoom.isPublic}
onClick={this._changeGroupRoomPublicity}
/>
<div className="mx_MemberInfo_label_text">
{ _t('Only visible to community members') }
</div>
</label>
</div>
</div>; </div>;
} }
const avatarUrl = this.context.matrixClient.mxcUrlToHttp( const avatarUrl = this.context.matrixClient.mxcUrlToHttp(
this.props.groupRoom.avatarUrl, this.state.groupRoom.avatarUrl,
36, 36, 'crop', 36, 36, 'crop',
); );
const groupRoomName = this.props.groupRoom.displayname; const groupRoomName = this.state.groupRoom.displayname;
const avatar = <BaseAvatar name={groupRoomName} width={36} height={36} url={avatarUrl} />; const avatar = <BaseAvatar name={groupRoomName} width={36} height={36} url={avatarUrl} />;
return ( return (
<div className="mx_MemberInfo"> <div className="mx_MemberInfo">
<GeminiScrollbar autoshow={true}> <GeminiScrollbar autoshow={true}>
<AccessibleButton className="mx_MemberInfo_cancel"onClick={this._onCancel}> <AccessibleButton className="mx_MemberInfo_cancel" onClick={this._onCancel}>
<img src="img/cancel.svg" width="18" height="18" className="mx_filterFlipColor" /> <img src="img/cancel.svg" width="18" height="18" className="mx_filterFlipColor" />
</AccessibleButton> </AccessibleButton>
<div className="mx_MemberInfo_avatar"> <div className="mx_MemberInfo_avatar">
@ -158,7 +230,7 @@ module.exports = React.createClass({
<div className="mx_MemberInfo_profile"> <div className="mx_MemberInfo_profile">
<div className="mx_MemberInfo_profileField"> <div className="mx_MemberInfo_profileField">
{ this.props.groupRoom.canonical_alias } { this.state.groupRoom.canonical_alias }
</div> </div>
</div> </div>

View file

@ -33,7 +33,7 @@ const GroupRoomTile = React.createClass({
dis.dispatch({ dis.dispatch({
action: 'view_group_room', action: 'view_group_room',
groupId: this.props.groupId, groupId: this.props.groupId,
groupRoom: this.props.groupRoom, groupRoomId: this.props.groupRoom.roomId,
}); });
}, },

View file

@ -50,5 +50,6 @@ export function groupRoomFromApiObject(apiObject) {
numJoinedMembers: apiObject.num_joined_members, numJoinedMembers: apiObject.num_joined_members,
worldReadable: apiObject.world_readable, worldReadable: apiObject.world_readable,
guestCanJoin: apiObject.guest_can_join, guestCanJoin: apiObject.guest_can_join,
isPublic: apiObject.is_public !== false,
}; };
} }

View file

@ -332,8 +332,6 @@
"Rooms": "Rooms", "Rooms": "Rooms",
"Low priority": "Low priority", "Low priority": "Low priority",
"Historical": "Historical", "Historical": "Historical",
"a room": "a room",
"Unnamed Room": "Unnamed Room",
"Unable to ascertain that the address this invite was sent to matches one associated with your account.": "Unable to ascertain that the address this invite was sent to matches one associated with your account.", "Unable to ascertain that the address this invite was sent to matches one associated with your account.": "Unable to ascertain that the address this invite was sent to matches one associated with your account.",
"This invitation was sent to an email address which is not associated with this account:": "This invitation was sent to an email address which is not associated with this account:", "This invitation was sent to an email address which is not associated with this account:": "This invitation was sent to an email address which is not associated with this account:",
"You may wish to login with a different account, or add this email to this account.": "You may wish to login with a different account, or add this email to this account.", "You may wish to login with a different account, or add this email to this account.": "You may wish to login with a different account, or add this email to this account.",
@ -504,6 +502,11 @@
"Remove": "Remove", "Remove": "Remove",
"Failed to remove room from community": "Failed to remove room from community", "Failed to remove room from community": "Failed to remove room from community",
"Failed to remove '%(roomName)s' from %(groupId)s": "Failed to remove '%(roomName)s' from %(groupId)s", "Failed to remove '%(roomName)s' from %(groupId)s": "Failed to remove '%(roomName)s' from %(groupId)s",
"Something went wrong!": "Something went wrong!",
"The visibility of '%(roomName)s' in %(groupId)s could not be updated.": "The visibility of '%(roomName)s' in %(groupId)s could not be updated.",
"Visibility in Room List": "Visibility in Room List",
"Visible to everyone": "Visible to everyone",
"Only visible to community members": "Only visible to community members",
"Filter community rooms": "Filter community rooms", "Filter community rooms": "Filter community rooms",
"Unknown Address": "Unknown Address", "Unknown Address": "Unknown Address",
"NOTE: Apps are not end-to-end encrypted": "NOTE: Apps are not end-to-end encrypted", "NOTE: Apps are not end-to-end encrypted": "NOTE: Apps are not end-to-end encrypted",
@ -582,7 +585,6 @@
"And %(count)s more...|other": "And %(count)s more...", "And %(count)s more...|other": "And %(count)s more...",
"ex. @bob:example.com": "ex. @bob:example.com", "ex. @bob:example.com": "ex. @bob:example.com",
"Add User": "Add User", "Add User": "Add User",
"Something went wrong!": "Something went wrong!",
"Matrix ID": "Matrix ID", "Matrix ID": "Matrix ID",
"Matrix Room ID": "Matrix Room ID", "Matrix Room ID": "Matrix Room ID",
"email address": "email address", "email address": "email address",

View file

@ -141,9 +141,15 @@ export default class GroupStore extends EventEmitter {
return this._summary.user ? this._summary.user.is_privileged : null; return this._summary.user ? this._summary.user.is_privileged : null;
} }
addRoomToGroup(roomId) { addRoomToGroup(roomId, isPublic) {
return this._matrixClient return this._matrixClient
.addRoomToGroup(this.groupId, roomId) .addRoomToGroup(this.groupId, roomId, isPublic)
.then(this._fetchRooms.bind(this));
}
updateGroupRoomAssociation(roomId, isPublic) {
return this._matrixClient
.updateGroupRoomAssociation(this.groupId, roomId, isPublic)
.then(this._fetchRooms.bind(this)); .then(this._fetchRooms.bind(this));
} }