mirror of
https://github.com/SchildiChat/element-web.git
synced 2024-10-01 01:26:12 -04:00
Merge pull request #2113 from vector-im/matthew/notif-panel
FilePanel and NotificationPanel support
This commit is contained in:
commit
f299572dc7
@ -26,9 +26,16 @@ var rate_limited_func = require('matrix-react-sdk/lib/ratelimitedfunc');
|
||||
module.exports = React.createClass({
|
||||
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 : {
|
||||
MemberList: 'MemberList',
|
||||
FileList: 'FileList',
|
||||
FilePanel: 'FilePanel',
|
||||
NotificationPanel: 'NotificationPanel',
|
||||
MemberInfo: 'MemberInfo',
|
||||
},
|
||||
|
||||
@ -61,7 +68,7 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
onMemberListButtonClick: function() {
|
||||
if (this.props.collapsed) {
|
||||
if (this.props.collapsed || this.state.phase !== this.Phase.MemberList) {
|
||||
this.setState({ phase: this.Phase.MemberList });
|
||||
dis.dispatch({
|
||||
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) {
|
||||
// redraw the badge on the membership list
|
||||
if (this.state.phase == this.Phase.MemberList && member.roomId === this.props.roomId) {
|
||||
@ -118,19 +153,25 @@ module.exports = React.createClass({
|
||||
|
||||
render: function() {
|
||||
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 buttonGroup;
|
||||
var panel;
|
||||
|
||||
var filesHighlight;
|
||||
var membersHighlight;
|
||||
var notificationsHighlight;
|
||||
if (!this.props.collapsed) {
|
||||
if (this.state.phase == this.Phase.MemberList || this.state.phase === this.Phase.MemberInfo) {
|
||||
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>;
|
||||
}
|
||||
else if (this.state.phase == this.Phase.NotificationPanel) {
|
||||
notificationsHighlight = <div className="mx_RightPanel_headerButton_highlight"></div>;
|
||||
}
|
||||
}
|
||||
|
||||
var membersBadge;
|
||||
@ -138,7 +179,7 @@ module.exports = React.createClass({
|
||||
var cli = MatrixClientPeg.get();
|
||||
var room = cli.getRoom(this.props.roomId);
|
||||
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 =
|
||||
<div className="mx_RightPanel_headerButtonGroup">
|
||||
<div className="mx_RightPanel_headerButton" title="Members" onClick={ this.onMemberListButtonClick }>
|
||||
{ membersBadge }
|
||||
<div className="mx_RightPanel_headerButton_badge">{ membersBadge ? membersBadge : <span> </span>}</div>
|
||||
<TintableSvg src="img/icons-people.svg" width="25" height="25"/>
|
||||
{ membersHighlight }
|
||||
</div>
|
||||
<div className="mx_RightPanel_headerButton mx_RightPanel_filebutton" title="Files">
|
||||
<TintableSvg src="img/files.svg" width="17" height="22"/>
|
||||
<div className="mx_RightPanel_headerButton mx_RightPanel_filebutton" title="Files" onClick={ this.onFileListButtonClick }>
|
||||
<div className="mx_RightPanel_headerButton_badge"> </div>
|
||||
<TintableSvg src="img/icons-files.svg" width="25" height="25"/>
|
||||
{ filesHighlight }
|
||||
</div>
|
||||
<div className="mx_RightPanel_headerButton mx_RightPanel_notificationbutton" title="Notifications" onClick={ this.onNotificationListButtonClick }>
|
||||
<div className="mx_RightPanel_headerButton_badge"> </div>
|
||||
<TintableSvg src="img/icons-notifications.svg" width="25" height="25"/>
|
||||
{ notificationsHighlight }
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
@ -165,6 +212,12 @@ module.exports = React.createClass({
|
||||
var MemberInfo = sdk.getComponent('rooms.MemberInfo');
|
||||
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) {
|
||||
|
@ -1,6 +0,0 @@
|
||||
.mx_RoomSettings_encrypt,
|
||||
.mx_CreateRoom_encrypt,
|
||||
.mx_RightPanel_filebutton
|
||||
{
|
||||
display: none !important;
|
||||
}
|
118
src/skins/vector/css/matrix-react-sdk/structures/FilePanel.css
Normal file
118
src/skins/vector/css/matrix-react-sdk/structures/FilePanel.css
Normal 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -30,7 +30,6 @@ limitations under the License.
|
||||
|
||||
.mx_MImageBody_download {
|
||||
color: #76cfa6;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_MImageBody_download a {
|
||||
|
@ -88,12 +88,14 @@ limitations under the License.
|
||||
height: 37px;
|
||||
border: 1px solid #979797;
|
||||
margin-right: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_RoomSettings .mx_RoomSettings_roomColor_selected {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 4px;
|
||||
cursor: default ! important;
|
||||
}
|
||||
|
||||
.mx_RoomSettings .mx_RoomSettings_roomColorPrimary {
|
||||
|
@ -63,7 +63,7 @@ limitations under the License.
|
||||
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 {
|
||||
display: block;
|
||||
position: absolute;
|
||||
@ -76,7 +76,7 @@ limitations under the License.
|
||||
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 {
|
||||
display: block;
|
||||
position: absolute;
|
||||
@ -90,11 +90,11 @@ limitations under the License.
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomTile_avatar_container:hover:before {
|
||||
.collapsed .mx_RoomTile:hover .mx_RoomTile_avatar_container:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomTile_avatar_container:hover:after {
|
||||
.collapsed .mx_RoomTile:hover .mx_RoomTile_avatar_container:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -46,15 +46,15 @@ limitations under the License.
|
||||
margin-top: 6px;
|
||||
float: left;
|
||||
background-color: #fff;
|
||||
margin-left: -4px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.mx_RightPanel_headerButton {
|
||||
cursor: pointer;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
vertical-align: top;
|
||||
padding-left: 4px;
|
||||
padding-right: 5px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
29
src/skins/vector/img/icons-files.svg
Normal file
29
src/skins/vector/img/icons-files.svg
Normal 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 |
28
src/skins/vector/img/icons-notifications.svg
Normal file
28
src/skins/vector/img/icons-notifications.svg
Normal 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 |
Loading…
Reference in New Issue
Block a user