Merge pull request #2113 from vector-im/matthew/notif-panel

FilePanel and NotificationPanel support
This commit is contained in:
Matthew Hodgson 2016-09-12 15:57:51 +01:00 committed by GitHub
commit f299572dc7
10 changed files with 347 additions and 22 deletions

View File

@ -26,9 +26,16 @@ var rate_limited_func = require('matrix-react-sdk/lib/ratelimitedfunc');
module.exports = React.createClass({ module.exports = React.createClass({
displayName: 'RightPanel', displayName: 'RightPanel',
propTypes: {
userId: React.PropTypes.string, // if showing an orphaned MemberInfo page, this is set
roomId: React.PropTypes.string, // if showing panels for a given room, this is set
collapsed: React.PropTypes.bool,
},
Phase : { Phase : {
MemberList: 'MemberList', MemberList: 'MemberList',
FileList: 'FileList', FilePanel: 'FilePanel',
NotificationPanel: 'NotificationPanel',
MemberInfo: 'MemberInfo', MemberInfo: 'MemberInfo',
}, },
@ -61,7 +68,7 @@ module.exports = React.createClass({
}, },
onMemberListButtonClick: function() { onMemberListButtonClick: function() {
if (this.props.collapsed) { if (this.props.collapsed || this.state.phase !== this.Phase.MemberList) {
this.setState({ phase: this.Phase.MemberList }); this.setState({ phase: this.Phase.MemberList });
dis.dispatch({ dis.dispatch({
action: 'show_right_panel', action: 'show_right_panel',
@ -74,6 +81,34 @@ module.exports = React.createClass({
} }
}, },
onFileListButtonClick: function() {
if (this.props.collapsed || this.state.phase !== this.Phase.FilePanel) {
this.setState({ phase: this.Phase.FilePanel });
dis.dispatch({
action: 'show_right_panel',
});
}
else {
dis.dispatch({
action: 'hide_right_panel',
});
}
},
onNotificationListButtonClick: function() {
if (this.props.collapsed || this.state.phase !== this.Phase.NotificationPanel) {
this.setState({ phase: this.Phase.NotificationPanel });
dis.dispatch({
action: 'show_right_panel',
});
}
else {
dis.dispatch({
action: 'hide_right_panel',
});
}
},
onRoomStateMember: function(ev, state, member) { onRoomStateMember: function(ev, state, member) {
// redraw the badge on the membership list // redraw the badge on the membership list
if (this.state.phase == this.Phase.MemberList && member.roomId === this.props.roomId) { if (this.state.phase == this.Phase.MemberList && member.roomId === this.props.roomId) {
@ -118,19 +153,25 @@ module.exports = React.createClass({
render: function() { render: function() {
var MemberList = sdk.getComponent('rooms.MemberList'); var MemberList = sdk.getComponent('rooms.MemberList');
var NotificationPanel = sdk.getComponent('structures.NotificationPanel');
var FilePanel = sdk.getComponent('structures.FilePanel');
var TintableSvg = sdk.getComponent("elements.TintableSvg"); var TintableSvg = sdk.getComponent("elements.TintableSvg");
var buttonGroup; var buttonGroup;
var panel; var panel;
var filesHighlight; var filesHighlight;
var membersHighlight; var membersHighlight;
var notificationsHighlight;
if (!this.props.collapsed) { if (!this.props.collapsed) {
if (this.state.phase == this.Phase.MemberList || this.state.phase === this.Phase.MemberInfo) { if (this.state.phase == this.Phase.MemberList || this.state.phase === this.Phase.MemberInfo) {
membersHighlight = <div className="mx_RightPanel_headerButton_highlight"></div>; membersHighlight = <div className="mx_RightPanel_headerButton_highlight"></div>;
} }
else if (this.state.phase == this.Phase.FileList) { else if (this.state.phase == this.Phase.FilePanel) {
filesHighlight = <div className="mx_RightPanel_headerButton_highlight"></div>; filesHighlight = <div className="mx_RightPanel_headerButton_highlight"></div>;
} }
else if (this.state.phase == this.Phase.NotificationPanel) {
notificationsHighlight = <div className="mx_RightPanel_headerButton_highlight"></div>;
}
} }
var membersBadge; var membersBadge;
@ -138,7 +179,7 @@ module.exports = React.createClass({
var cli = MatrixClientPeg.get(); var cli = MatrixClientPeg.get();
var room = cli.getRoom(this.props.roomId); var room = cli.getRoom(this.props.roomId);
if (room) { if (room) {
membersBadge = <div className="mx_RightPanel_headerButton_badge">{ room.getJoinedMembers().length }</div>; membersBadge = room.getJoinedMembers().length;
} }
} }
@ -146,14 +187,20 @@ module.exports = React.createClass({
buttonGroup = buttonGroup =
<div className="mx_RightPanel_headerButtonGroup"> <div className="mx_RightPanel_headerButtonGroup">
<div className="mx_RightPanel_headerButton" title="Members" onClick={ this.onMemberListButtonClick }> <div className="mx_RightPanel_headerButton" title="Members" onClick={ this.onMemberListButtonClick }>
{ membersBadge } <div className="mx_RightPanel_headerButton_badge">{ membersBadge ? membersBadge : <span>&nbsp;</span>}</div>
<TintableSvg src="img/icons-people.svg" width="25" height="25"/> <TintableSvg src="img/icons-people.svg" width="25" height="25"/>
{ membersHighlight } { membersHighlight }
</div> </div>
<div className="mx_RightPanel_headerButton mx_RightPanel_filebutton" title="Files"> <div className="mx_RightPanel_headerButton mx_RightPanel_filebutton" title="Files" onClick={ this.onFileListButtonClick }>
<TintableSvg src="img/files.svg" width="17" height="22"/> <div className="mx_RightPanel_headerButton_badge">&nbsp;</div>
<TintableSvg src="img/icons-files.svg" width="25" height="25"/>
{ filesHighlight } { filesHighlight }
</div> </div>
<div className="mx_RightPanel_headerButton mx_RightPanel_notificationbutton" title="Notifications" onClick={ this.onNotificationListButtonClick }>
<div className="mx_RightPanel_headerButton_badge">&nbsp;</div>
<TintableSvg src="img/icons-notifications.svg" width="25" height="25"/>
{ notificationsHighlight }
</div>
</div>; </div>;
} }
@ -165,6 +212,12 @@ module.exports = React.createClass({
var MemberInfo = sdk.getComponent('rooms.MemberInfo'); var MemberInfo = sdk.getComponent('rooms.MemberInfo');
panel = <MemberInfo member={this.state.member} key={this.props.roomId || this.props.userId} /> panel = <MemberInfo member={this.state.member} key={this.props.roomId || this.props.userId} />
} }
else if (this.state.phase == this.Phase.NotificationPanel) {
panel = <NotificationPanel />
}
else if (this.state.phase == this.Phase.FilePanel) {
panel = <FilePanel roomId={this.props.roomId} />
}
} }
if (!panel) { if (!panel) {

View File

@ -1,6 +0,0 @@
.mx_RoomSettings_encrypt,
.mx_CreateRoom_encrypt,
.mx_RightPanel_filebutton
{
display: none !important;
}

View File

@ -0,0 +1,118 @@
/*
Copyright 2016 OpenMarket 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.
*/
.mx_FilePanel {
-webkit-box-ordinal-group: 2;
-moz-box-ordinal-group: 2;
-ms-flex-order: 2;
-webkit-order: 2;
order: 2;
-webkit-flex: 1 1 0;
flex: 1 1 0;
width: 100%;
overflow-y: auto;
}
.mx_FilePanel .mx_RoomView_messageListWrapper {
margin-right: 20px;
}
.mx_FilePanel .mx_RoomView_MessageList h2 {
display: none;
}
/* FIXME: rather than having EventTile's default CSS be for MessagePanel,
we should make EventTile a base CSS class and customise it specifically
for usage in {Message,File,Notification}Panel. */
.mx_FilePanel .mx_EventTile_avatar {
display: none;
}
/* Overrides for the attachment body tiles */
.mx_FilePanel .mx_EventTile .mx_MImageBody {
margin-right: 0px;
}
.mx_FilePanel .mx_EventTile .mx_MImageBody_download {
display: flex;
font-size: 14px;
color: #acacac;
}
.mx_FilePanel .mx_EventTile .mx_MImageBody_downloadLink {
flex: 1 1 auto;
color: #747474;
word-break: break-all;
}
.mx_FilePanel .mx_EventTile .mx_MImageBody_size {
flex: 1 0 0;
font-size: 11px;
text-align: right;
white-space: nowrap;
}
/* Overides for the sender details line */
.mx_FilePanel .mx_EventTile_senderDetails {
display: flex;
margin-top: -2px;
}
.mx_FilePanel .mx_EventTile_senderDetailsLink {
text-decoration: none;
}
.mx_FilePanel .mx_EventTile .mx_SenderProfile {
flex: 1 1 auto;
line-height: initial;
padding: 0px;
font-size: 11px;
opacity: 1.0;
color: #acacac;
word-break: break-all;
}
.mx_FilePanel .mx_EventTile .mx_MessageTimestamp {
flex: 1 0 0;
text-align: right;
visibility: visible;
position: initial;
font-size: 11px;
opacity: 1.0;
color: #acacac;
}
/* Overrides for the wrappers around the body tile */
.mx_FilePanel .mx_EventTile_line {
margin-right: 0px;
padding-left: 0px;
}
.mx_FilePanel .mx_EventTile:hover .mx_EventTile_line {
background-color: #fff;
}
.mx_FilePanel .mx_EventTile_selected .mx_EventTile_line {
padding-left: 0px;
}

View File

@ -0,0 +1,102 @@
/*
Copyright 2015, 2016 OpenMarket 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.
*/
.mx_NotificationPanel {
-webkit-box-ordinal-group: 2;
-moz-box-ordinal-group: 2;
-ms-flex-order: 2;
-webkit-order: 2;
order: 2;
-webkit-flex: 1 1 0;
flex: 1 1 0;
width: 100%;
overflow-y: auto;
}
.mx_NotificationPanel .mx_RoomView_messageListWrapper {
margin-right: 20px;
}
.mx_NotificationPanel .mx_RoomView_MessageList h2 {
margin-left: 0px;
}
/* FIXME: rather than having EventTile's default CSS be for MessagePanel,
we should make EventTile a base CSS class and customise it specifically
for usage in {Message,File,Notification}Panel. */
.mx_NotificationPanel .mx_EventTile_roomName {
font-weight: bold;
font-size: 14px;
}
.mx_NotificationPanel .mx_EventTile_roomName a {
color: #4a4a4a;
}
.mx_NotificationPanel .mx_EventTile_avatar {
top: 8px;
left: 0px;
}
.mx_NotificationPanel .mx_EventTile .mx_SenderProfile,
.mx_NotificationPanel .mx_EventTile .mx_MessageTimestamp {
color: #000;
opacity: 0.3;
font-size: 12px;
display: inline;
padding-left: 0px;
}
.mx_NotificationPanel .mx_EventTile_senderDetails {
padding-left: 32px;
padding-top: 8px;
position: relative;
}
.mx_NotificationPanel .mx_EventTile_roomName a,
.mx_NotificationPanel .mx_EventTile_senderDetails a {
text-decoration: none ! important;
}
.mx_NotificationPanel .mx_EventTile .mx_MessageTimestamp {
visibility: visible;
position: initial;
display: inline;
}
.mx_NotificationPanel .mx_EventTile_line {
margin-right: 0px;
padding-left: 32px;
padding-top: 0px;
padding-bottom: 0px;
padding-right: 0px;
}
.mx_NotificationPanel .mx_EventTile:hover .mx_EventTile_line {
background-color: #fff;
}
.mx_NotificationPanel .mx_EventTile_selected .mx_EventTile_line {
padding-left: 0px;
}
.mx_NotificationPanel .mx_EventTile_content {
margin-right: 0px;
}

View File

@ -30,7 +30,6 @@ limitations under the License.
.mx_MImageBody_download { .mx_MImageBody_download {
color: #76cfa6; color: #76cfa6;
cursor: pointer;
} }
.mx_MImageBody_download a { .mx_MImageBody_download a {

View File

@ -88,12 +88,14 @@ limitations under the License.
height: 37px; height: 37px;
border: 1px solid #979797; border: 1px solid #979797;
margin-right: 13px; margin-right: 13px;
cursor: pointer;
} }
.mx_RoomSettings .mx_RoomSettings_roomColor_selected { .mx_RoomSettings .mx_RoomSettings_roomColor_selected {
position: absolute; position: absolute;
left: 10px; left: 10px;
top: 4px; top: 4px;
cursor: default ! important;
} }
.mx_RoomSettings .mx_RoomSettings_roomColorPrimary { .mx_RoomSettings .mx_RoomSettings_roomColorPrimary {

View File

@ -63,7 +63,7 @@ limitations under the License.
z-index: 2; z-index: 2;
} }
.mx_RoomTile_avatar_container:hover:before, .mx_RoomTile:hover .mx_RoomTile_avatar_container:before,
.mx_RoomTile_avatar_container.mx_RoomTile_avatar_roomTagMenu:before { .mx_RoomTile_avatar_container.mx_RoomTile_avatar_roomTagMenu:before {
display: block; display: block;
position: absolute; position: absolute;
@ -76,7 +76,7 @@ limitations under the License.
z-index: 4; z-index: 4;
} }
.mx_RoomTile_avatar_container:hover:after, .mx_RoomTile:hover .mx_RoomTile_avatar_container:after,
.mx_RoomTile_avatar_container.mx_RoomTile_avatar_roomTagMenu:after { .mx_RoomTile_avatar_container.mx_RoomTile_avatar_roomTagMenu:after {
display: block; display: block;
position: absolute; position: absolute;
@ -90,11 +90,11 @@ limitations under the License.
z-index: 1; z-index: 1;
} }
.collapsed .mx_RoomTile_avatar_container:hover:before { .collapsed .mx_RoomTile:hover .mx_RoomTile_avatar_container:before {
display: none; display: none;
} }
.collapsed .mx_RoomTile_avatar_container:hover:after { .collapsed .mx_RoomTile:hover .mx_RoomTile_avatar_container:after {
display: none; display: none;
} }

View File

@ -46,15 +46,15 @@ limitations under the License.
margin-top: 6px; margin-top: 6px;
float: left; float: left;
background-color: #fff; background-color: #fff;
margin-left: -4px; margin-left: 0px;
} }
.mx_RightPanel_headerButton { .mx_RightPanel_headerButton {
cursor: pointer; cursor: pointer;
display: table-cell; display: table-cell;
vertical-align: middle; vertical-align: top;
padding-left: 15px; padding-left: 4px;
padding-right: 15px; padding-right: 5px;
text-align: center; text-align: center;
position: relative; position: relative;
} }

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="25px" height="25px" viewBox="0 0 25 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: sketchtool 39.1 (31720) - http://www.bohemiancoding.com/sketch -->
<title>7C98C075-AB4D-45A3-85F9-CCD46F84DA7F</title>
<desc>Created with sketchtool.</desc>
<defs>
<path d="M0,2.00276013 C0,0.896666251 0.889186576,0 1.99983124,0 L4.84793814,0 C4.84793814,0 9.25,4.54127763 9.25,4.54127763 L9.25,10.9954009 C9.25,12.1025104 8.36307111,13 7.24288777,13 L2.00711223,13 C0.898614756,13 0,12.1064574 0,10.9972399 L0,2.00276013 Z" id="path-1"></path>
<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="9.25" height="13" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<path d="M9.28225806,5 L5.82322134,5 C4.97217082,5 4.28225806,4.31002094 4.28225806,3.45903672 L4.28225806,0" id="path-3"></path>
<mask id="mask-4" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="5" height="5" fill="white">
<use xlink:href="#path-3"></use>
</mask>
</defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Right-panel/Header" transform="translate(-66.000000, -23.000000)">
<g id="icons_files" transform="translate(66.000000, 23.000000)">
<g id="Group-5-Copy-2" fill="#76CFA6">
<path d="M12.5,25 C19.4035594,25 25,19.4035594 25,12.5 C25,5.59644063 19.4035594,0 12.5,0 C5.59644063,0 0,5.59644063 0,12.5 C0,19.4035594 5.59644063,25 12.5,25 Z" id="Oval-1-Copy-7"></path>
</g>
<g id="Rectangle-5-+-Rectangle-6-Copy-2" transform="translate(8.000000, 6.000000)" stroke="#FFFFFF" stroke-width="2">
<use id="Rectangle-5" mask="url(#mask-2)" opacity="0.8" xlink:href="#path-1"></use>
<use id="Rectangle-6" mask="url(#mask-4)" xlink:href="#path-3"></use>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="25px" height="25px" viewBox="0 0 25 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: sketchtool 39.1 (31720) - http://www.bohemiancoding.com/sketch -->
<title>5E723325-BD0B-454D-BE25-638AF09A97AC</title>
<desc>Created with sketchtool.</desc>
<defs>
<path d="M5.5,15.8888889 C6.51252204,15.8888889 7.33333333,15.0680776 7.33333333,14.0555556 C7.33333333,13.0430335 6.51252204,12.2222222 5.5,12.2222222 C4.48747796,12.2222222 3.66666667,13.0430335 3.66666667,14.0555556 C3.66666667,15.0680776 4.48747796,15.8888889 5.5,15.8888889 Z" id="path-1"></path>
<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="3.66666667" height="3.66666667" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<rect id="path-3" x="0" y="2.44444444" width="11" height="11" rx="2"></rect>
<mask id="mask-4" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="11" height="11" fill="white">
<use xlink:href="#path-3"></use>
</mask>
</defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Right-panel/Header" transform="translate(-100.000000, -23.000000)">
<g id="icons_notifications" transform="translate(100.000000, 23.000000)">
<path d="M12.5,25 C19.4035594,25 25,19.4035594 25,12.5 C25,5.59644063 19.4035594,0 12.5,0 C5.59644063,0 0,5.59644063 0,12.5 C0,19.4035594 5.59644063,25 12.5,25 Z" id="Oval-1-Copy-7" fill="#76CFA6"></path>
<g id="Group-8" opacity="0.8" transform="translate(7.000000, 4.000000)" stroke="#FFFFFF">
<use id="Oval-49" mask="url(#mask-2)" stroke-width="2" xlink:href="#path-1"></use>
<use id="Rectangle-15" mask="url(#mask-4)" stroke-width="2" fill="#76CFA6" xlink:href="#path-3"></use>
<path d="M4.27777778,1.83333333 L6.72222222,1.83333333" id="Line" stroke-linecap="round"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB