Add basic group view

pull/21833/head
Erik Johnston 2017-06-05 16:51:50 +01:00
parent 9e0aca534c
commit 998a55a590
5 changed files with 210 additions and 0 deletions

View File

@ -22,4 +22,5 @@ export default {
CreateRoom: "create_room",
RoomDirectory: "room_directory",
UserView: "user_view",
GroupView: "group_view",
};

View File

@ -0,0 +1,130 @@
/*
Copyright 2017 Vector Creations 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.
*/
import MatrixClientPeg from '../../MatrixClientPeg';
import sdk from '../../index';
import sanitizeHtml from "sanitize-html";
import { sanitizeHtmlParams } from '../../HtmlUtils';
module.exports = React.createClass({
displayName: 'GroupView',
propTypes: {
groupId: React.PropTypes.string.isRequired,
},
getInitialState: function() {
return {
phase: "GroupView.LOADING", // LOADING / DISPLAY / ERROR / NOT_FOUND
summary: null,
};
},
componentWillMount: function() {
this.setState({
phase: "GroupView.LOADING",
summary: null,
})
this._loadGroupFromServer(this.props.groupId)
},
componentWillReceiveProps: function(new_props) {
if (this.props.groupId != new_props.groupId) {
this.setState({
phase: "GroupView.LOADING",
summary: null,
})
this._loadGroupFromServer(new_props.groupId);
}
},
_loadGroupFromServer: function(groupId) {
const self = this;
MatrixClientPeg.get().getGroupSummary(groupId).done(function(res) {
self.setState({
phase: "GroupView.DISPLAY",
summary: res,
});
}, function(err) {
self.setState({
phase: err.errcode == 404 ? "GroupView.NOT_FOUND" :"GroupView.ERROR",
summary: null,
});
});
},
render: function() {
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
var Loader = sdk.getComponent("elements.Spinner");
if (this.state.phase == "GroupView.LOADING") {
return (
<div style={{margin: "auto"}}>
<Loader />
</div>
);
} else if (this.state.phase == "GroupView.DISPLAY") {
const summary = this.state.summary;
let avatar_url = null;
if (summary.profile.avatar_url) {
avatar_url = MatrixClientPeg.get().mxcUrlToHttp(summary.profile.avatar_url);
}
let description = null;
if (summary.profile.long_description) {
description = sanitizeHtml(summary.profile.long_description);
}
return (
<div style={{maxWidth: "960px", width: "100%", "margin": "20px auto"}}>
<div className="mx_RoomHeader">
<div className="mx_RoomHeader_wrapper">
<div className="mx_RoomHeader_avatar">
<BaseAvatar url={avatar_url} name={summary.profile.name}
width={48} height={48} />
</div>
<div className="mx_RoomHeader_info">
<div className="mx_RoomHeader_name">
<span>{summary.profile.name}</span>
<span style={{
fontWeight: "normal",
fontSize: "initial",
paddingLeft: "10px",
}}>
({this.props.groupId})
</span>
</div>
<div className="mx_RoomHeader_topic">
{summary.profile.short_description}
</div>
</div>
</div>
</div>
<div dangerouslySetInnerHTML={{ __html: description }} />
</div>
);
} else if (this.state.phase == "GroupView.NOT_FOUND") {
<div style={{margin: "auto"}}>
Group {this.props.groupId} not found
</div>
} else {
return (
<div style={{margin: "auto"}}>
Failed to load {this.props.groupId}
</div>
);
}
},
});

View File

@ -179,6 +179,7 @@ export default React.createClass({
const CreateRoom = sdk.getComponent('structures.CreateRoom');
const RoomDirectory = sdk.getComponent('structures.RoomDirectory');
const HomePage = sdk.getComponent('structures.HomePage');
const GroupView = sdk.getComponent('structures.GroupView');
const MatrixToolbar = sdk.getComponent('globals.MatrixToolbar');
const GuestWarningBar = sdk.getComponent('globals.GuestWarningBar');
const NewVersionBar = sdk.getComponent('globals.NewVersionBar');
@ -247,6 +248,12 @@ export default React.createClass({
page_element = null; // deliberately null for now
right_panel = <RightPanel userId={this.props.viewUserId} opacity={this.props.rightOpacity} />;
break;
case PageTypes.GroupView:
// TODO
page_element = <GroupView
groupId={this.props.currentGroupId}
/>
break;
}
var topBar;

View File

@ -261,6 +261,9 @@ module.exports = React.createClass({
if (this.onUserClick) {
linkifyMatrix.onUserClick = this.onUserClick;
}
if (this.onGroupClick) {
linkifyMatrix.onGroupClick = this.onGroupClick;
}
window.addEventListener('resize', this.handleResize);
this.handleResize();
@ -458,6 +461,12 @@ module.exports = React.createClass({
this._setPage(PageTypes.RoomDirectory);
this.notifyNewScreen('directory');
break;
case 'view_group':
const groupId = payload.group_id;
this.setState({currentGroupId: groupId});
this._setPage(PageTypes.GroupView);
this.notifyNewScreen('group/' + groupId);
break;
case 'view_home_page':
if (!this._teamToken) {
dis.dispatch({action: 'view_room_directory'});
@ -1001,6 +1010,15 @@ module.exports = React.createClass({
member: member,
});
}
} else if (screen.indexOf('group/') == 0) {
const groupId = screen.substring(6);
// TODO: Check valid group ID
dis.dispatch({
action: 'view_group',
group_id: groupId,
});
} else {
console.info("Ignoring showScreen for '%s'", screen);
}
@ -1029,6 +1047,11 @@ module.exports = React.createClass({
});
},
onGroupClick: function(event, groupId) {
event.preventDefault();
dis.dispatch({action: 'view_group', group_id: groupId});
},
onLogoutClick: function(event) {
dis.dispatch({
action: 'logout',

View File

@ -108,11 +108,53 @@ function matrixLinkify(linkify) {
S_AT_NAME_COLON_DOMAIN.on(TT.DOT, S_AT_NAME_COLON_DOMAIN_DOT);
S_AT_NAME_COLON_DOMAIN_DOT.on(TT.DOMAIN, S_AT_NAME_COLON_DOMAIN);
S_AT_NAME_COLON_DOMAIN_DOT.on(TT.TLD, S_USERID);
var GROUPID = function(value) {
MultiToken.call(this, value);
this.type = 'groupid';
this.isLink = true;
};
GROUPID.prototype = new MultiToken();
var S_PLUS = new linkify.parser.State();
var S_PLUS_NAME = new linkify.parser.State();
var S_PLUS_NAME_COLON = new linkify.parser.State();
var S_PLUS_NAME_COLON_DOMAIN = new linkify.parser.State();
var S_PLUS_NAME_COLON_DOMAIN_DOT = new linkify.parser.State();
var S_GROUPID = new linkify.parser.State(GROUPID);
var groupid_tokens = [
TT.DOT,
TT.UNDERSCORE,
TT.PLUS,
TT.NUM,
TT.DOMAIN,
TT.TLD,
// as in roomname_tokens
TT.LOCALHOST,
];
S_START.on(TT.PLUS, S_PLUS);
S_PLUS.on(groupid_tokens, S_PLUS_NAME);
S_PLUS_NAME.on(groupid_tokens, S_PLUS_NAME);
S_PLUS_NAME.on(TT.DOMAIN, S_PLUS_NAME);
S_PLUS_NAME.on(TT.COLON, S_PLUS_NAME_COLON);
S_PLUS_NAME_COLON.on(TT.DOMAIN, S_PLUS_NAME_COLON_DOMAIN);
S_PLUS_NAME_COLON.on(TT.LOCALHOST, S_GROUPID); // accept +foo:localhost
S_PLUS_NAME_COLON_DOMAIN.on(TT.DOT, S_PLUS_NAME_COLON_DOMAIN_DOT);
S_PLUS_NAME_COLON_DOMAIN_DOT.on(TT.DOMAIN, S_PLUS_NAME_COLON_DOMAIN);
S_PLUS_NAME_COLON_DOMAIN_DOT.on(TT.TLD, S_GROUPID);
}
// stubs, overwritten in MatrixChat's componentDidMount
matrixLinkify.onUserClick = function(e, userId) { e.preventDefault(); };
matrixLinkify.onAliasClick = function(e, roomAlias) { e.preventDefault(); };
matrixLinkify.onGroupClick = function(e, groupId) { e.preventDefault(); };
var escapeRegExp = function(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@ -143,6 +185,12 @@ matrixLinkify.options = {
matrixLinkify.onAliasClick(e, href);
}
};
case "groupid":
return {
click: function(e) {
matrixLinkify.onGroupClick(e, href);
}
};
}
},
@ -150,6 +198,7 @@ matrixLinkify.options = {
switch (type) {
case 'roomalias':
case 'userid':
case "groupid":
return matrixLinkify.MATRIXTO_BASE_URL + '/#/' + href;
default:
var m;