diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js
index 3f321d453d..30d67202e7 100644
--- a/src/components/structures/GroupView.js
+++ b/src/components/structures/GroupView.js
@@ -18,9 +18,154 @@ import React from 'react';
import PropTypes from 'prop-types';
import MatrixClientPeg from '../../MatrixClientPeg';
import sdk from '../../index';
+import dis from '../../dispatcher';
import { sanitizedHtmlNode } from '../../HtmlUtils';
import { _t } from '../../languageHandler';
+import AccessibleButton from '../views/elements/AccessibleButton';
+const RoomSummaryType = PropTypes.shape({
+ room_id: PropTypes.string.isRequired,
+ profile: PropTypes.shape({
+ name: PropTypes.string,
+ avatar_url: PropTypes.string,
+ canonical_alias: PropTypes.string,
+ }).isRequired,
+});
+
+const UserSummaryType = PropTypes.shape({
+ summaryInfo: PropTypes.shape({
+ user_id: PropTypes.string.isRequired,
+ }).isRequired,
+});
+
+const CategoryRoomList = React.createClass({
+ displayName: 'CategoryRoomList',
+
+ props: {
+ rooms: PropTypes.arrayOf(RoomSummaryType).isRequired,
+ category: PropTypes.shape({
+ profile: PropTypes.shape({
+ name: PropTypes.string,
+ }).isRequired,
+ }),
+ },
+
+ render: function() {
+ const roomNodes = this.props.rooms.map((r) => {
+ return ;
+ });
+ let catHeader = null;
+ if (this.props.category && this.props.category.profile) {
+ catHeader =
{this.props.category.profile.name}
;
+ }
+ return
+ {catHeader}
+ {roomNodes}
+
;
+ },
+});
+
+const FeaturedRoom = React.createClass({
+ displayName: 'FeaturedRoom',
+
+ props: {
+ summaryInfo: RoomSummaryType.isRequired,
+ },
+
+ onClick: function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+
+ dis.dispatch({
+ action: 'view_room',
+ room_alias: this.props.summaryInfo.profile.canonical_alias,
+ room_id: this.props.summaryInfo.room_id,
+ });
+ },
+
+ render: function() {
+ const RoomAvatar = sdk.getComponent("avatars.RoomAvatar");
+
+ const oobData = {
+ roomId: this.props.summaryInfo.room_id,
+ avatarUrl: this.props.summaryInfo.profile.avatar_url,
+ name: this.props.summaryInfo.profile.name,
+ };
+ let permalink = null;
+ if (this.props.summaryInfo.profile && this.props.summaryInfo.profile.canonical_alias) {
+ permalink = 'https://matrix.to/#/' + this.props.summaryInfo.profile.canonical_alias;
+ }
+ let roomNameNode = null;
+ if (permalink) {
+ roomNameNode = {this.props.summaryInfo.profile.name};
+ } else {
+ roomNameNode = {this.props.summaryInfo.profile.name};
+ }
+
+ return
+
+ {roomNameNode}
+ ;
+ },
+});
+
+const RoleUserList = React.createClass({
+ displayName: 'RoleUserList',
+
+ props: {
+ users: PropTypes.arrayOf(UserSummaryType).isRequired,
+ role: PropTypes.shape({
+ profile: PropTypes.shape({
+ name: PropTypes.string,
+ }).isRequired,
+ }),
+ },
+
+ render: function() {
+ const userNodes = this.props.users.map((u) => {
+ return ;
+ });
+ let roleHeader = null;
+ if (this.props.role && this.props.role.profile) {
+ roleHeader = {this.props.role.profile.name}
;
+ }
+ return
+ {roleHeader}
+ {userNodes}
+
;
+ },
+});
+
+const FeaturedUser = React.createClass({
+ displayName: 'FeaturedUser',
+
+ props: {
+ summaryInfo: UserSummaryType.isRequired,
+ },
+
+ onClick: function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+
+ dis.dispatch({
+ action: 'view_start_chat_or_reuse',
+ user_id: this.props.summaryInfo.user_id,
+ go_home_on_cancel: false,
+ });
+ },
+
+ render: function() {
+ // Add avatar once we get profile info inline in the summary response
+ //const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
+
+ const permalink = 'https://matrix.to/#/' + this.props.summaryInfo.user_id;
+ const userNameNode = {this.props.summaryInfo.user_id};
+
+ return
+ {userNameNode}
+ ;
+ },
+});
export default React.createClass({
displayName: 'GroupView',
@@ -33,6 +178,7 @@ export default React.createClass({
return {
summary: null,
error: null,
+ editing: false,
};
},
@@ -65,12 +211,95 @@ export default React.createClass({
});
},
+ _onSettingsClick: function() {
+ this.setState({editing: true});
+ },
+
+ _getFeaturedRoomsNode() {
+ const summary = this.state.summary;
+
+ if (summary.rooms_section.rooms.length == 0) return null;
+
+ const defaultCategoryRooms = [];
+ const categoryRooms = {};
+ summary.rooms_section.rooms.forEach((r) => {
+ if (r.category_id === null) {
+ defaultCategoryRooms.push(r);
+ } else {
+ let list = categoryRooms[r.category_id];
+ if (list === undefined) {
+ list = [];
+ categoryRooms[r.category_id] = list;
+ }
+ list.push(r);
+ }
+ });
+
+ let defaultCategoryNode = null;
+ if (defaultCategoryRooms.length > 0) {
+ defaultCategoryNode = ;
+ }
+ const categoryRoomNodes = Object.keys(categoryRooms).map((catId) => {
+ const cat = summary.rooms_section.categories[catId];
+ return ;
+ });
+
+ return
+
+ {_t('Featured Rooms:')}
+
+ {defaultCategoryNode}
+ {categoryRoomNodes}
+
;
+ },
+
+ _getFeaturedUsersNode() {
+ const summary = this.state.summary;
+
+ if (summary.users_section.users.length == 0) return null;
+
+ const noRoleUsers = [];
+ const roleUsers = {};
+ summary.users_section.users.forEach((u) => {
+ if (u.role_id === null) {
+ noRoleUsers.push(u);
+ } else {
+ let list = roleUsers[u.role_id];
+ if (list === undefined) {
+ list = [];
+ roleUsers[u.role_id] = list;
+ }
+ list.push(u);
+ }
+ });
+
+ let noRoleNode = null;
+ if (noRoleUsers.length > 0) {
+ noRoleNode = ;
+ }
+ const roleUserNodes = Object.keys(roleUsers).map((roleId) => {
+ const role = summary.users_section.roles[roleId];
+ return ;
+ });
+
+ return
+
+ {_t('Featured Users:')}
+
+ {noRoleNode}
+ {roleUserNodes}
+
;
+ },
+
render: function() {
const GroupAvatar = sdk.getComponent("avatars.GroupAvatar");
const Loader = sdk.getComponent("elements.Spinner");
+ const TintableSvg = sdk.getComponent("elements.TintableSvg");
if (this.state.summary === null && this.state.error === null) {
return ;
+ } else if (this.state.editing) {
+ return ;
} else if (this.state.summary) {
const summary = this.state.summary;
let description = null;
@@ -78,6 +307,12 @@ export default React.createClass({
description = sanitizedHtmlNode(summary.profile.long_description);
}
+ const roomBody =
+
{description}
+ {this._getFeaturedRoomsNode()}
+ {this._getFeaturedUsersNode()}
+
;
+
let nameNode;
if (summary.profile && summary.profile.name) {
nameNode =
@@ -94,6 +329,7 @@ export default React.createClass({
const groupAvatarUrl = summary.profile ? summary.profile.avatar_url : null;
+ // settings button is display: none until settings is wired up
return (
@@ -111,9 +347,12 @@ export default React.createClass({
{summary.profile.short_description}
+
+
+
- {description}
+ {roomBody}
);
} else if (this.state.error) {
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index f0337fdd8e..75a15d71ee 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -506,7 +506,7 @@ module.exports = React.createClass({
this._setMxId(payload);
break;
case 'view_start_chat_or_reuse':
- this._chatCreateOrReuse(payload.user_id);
+ this._chatCreateOrReuse(payload.user_id, payload.go_home_on_cancel);
break;
case 'view_create_chat':
this._createChat();
@@ -801,7 +801,9 @@ module.exports = React.createClass({
});
},
- _chatCreateOrReuse: function(userId) {
+ _chatCreateOrReuse: function(userId, goHomeOnCancel) {
+ if (goHomeOnCancel === undefined) goHomeOnCancel = true;
+
const ChatCreateOrReuseDialog = sdk.getComponent(
'views.dialogs.ChatCreateOrReuseDialog',
);
@@ -832,7 +834,7 @@ module.exports = React.createClass({
const close = Modal.createDialog(ChatCreateOrReuseDialog, {
userId: userId,
onFinished: (success) => {
- if (!success) {
+ if (!success && goHomeOnCancel) {
// Dialog cancelled, default to home
dis.dispatch({ action: 'view_home_page' });
}
diff --git a/src/components/views/avatars/RoomAvatar.js b/src/components/views/avatars/RoomAvatar.js
index 8041fd5cd7..a18a52b3c0 100644
--- a/src/components/views/avatars/RoomAvatar.js
+++ b/src/components/views/avatars/RoomAvatar.js
@@ -72,7 +72,7 @@ module.exports = React.createClass({
},
getRoomAvatarUrl: function(props) {
- if (!this.props.room) return null;
+ if (!props.room) return null;
return props.room.getAvatarUrl(
MatrixClientPeg.get().getHomeserverUrl(),
@@ -84,7 +84,7 @@ module.exports = React.createClass({
},
getOneToOneAvatar: function(props) {
- if (!this.props.room) return null;
+ if (!props.room) return null;
var mlist = props.room.currentState.members;
var userIds = [];
@@ -126,9 +126,16 @@ module.exports = React.createClass({
},
getFallbackAvatar: function(props) {
- if (!this.props.room) return null;
+ let roomId = null;
+ if (props.oobData && props.oobData.roomId) {
+ roomId = this.props.oobData.roomId;
+ } else if (props.room) {
+ roomId = props.room.roomId;
+ } else {
+ return null;
+ }
- return Avatar.defaultAvatarUrlForString(props.room.roomId);
+ return Avatar.defaultAvatarUrlForString(roomId);
},
render: function() {
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index d68d517302..812059ed1f 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -954,5 +954,7 @@
"Create a group to represent your community! Define a set of rooms and your own custom homepage to mark out your space in the Matrix universe.": "Create a group to represent your community! Define a set of rooms and your own custom homepage to mark out your space in the Matrix universe.",
"Join an existing group": "Join an existing group",
"To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.": "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.",
- "Error whilst fetching joined groups": "Error whilst fetching joined groups"
+ "Featured Rooms:": "Featured Rooms:",
+ "Error whilst fetching joined groups": "Error whilst fetching joined groups",
+ "Featured Users:": "Featured Users:"
}