diff --git a/res/css/structures/_GroupView.scss b/res/css/structures/_GroupView.scss index 542d9d293b..398c51ba91 100644 --- a/res/css/structures/_GroupView.scss +++ b/res/css/structures/_GroupView.scss @@ -34,6 +34,8 @@ limitations under the License. .mx_GroupView_header_view { border-bottom: 1px solid $primary-hairline-color; padding-bottom: 0px; + padding-left: 8px; + padding-right: 8px; } .mx_GroupView_header_avatar, .mx_GroupView_header_info { diff --git a/res/css/structures/_MyGroups.scss b/res/css/structures/_MyGroups.scss index 6d140721c8..f9433909a5 100644 --- a/res/css/structures/_MyGroups.scss +++ b/res/css/structures/_MyGroups.scss @@ -15,10 +15,6 @@ limitations under the License. */ .mx_MyGroups { - max-width: 960px; - margin-left: auto; - margin-right: auto; - display: flex; flex-direction: column; } @@ -34,6 +30,11 @@ limitations under the License. flex-wrap: wrap; } +.mx_MyGroups > :not(.mx_RoomHeader) { + max-width: 960px; + margin: 40px; +} + .mx_MyGroups_headerCard { flex: 1 0 50%; margin-bottom: 30px; @@ -43,14 +44,31 @@ limitations under the License. } .mx_MyGroups_headerCard .mx_MyGroups_headerCard_button { + flex: 0 0 auto; margin-right: 13px; - height: 50px; + height: 40px; + width: 40px; + border-radius: 20px; + background-color: $roomheader-addroom-color; + position: relative; + + &:before { + background-color: $accent-fg-color; + mask: url('../../img/icons-create-room.svg'); + mask-repeat: no-repeat; + mask-position: center; + mask-size: 80%; + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + } } -.mx_MyGroups_headerCard_button object { - /* Otherwise the SVG object absorbs clicks and the button doesn't work */ - pointer-events: none; -} + + .mx_MyGroups_headerCard_header { font-weight: bold; diff --git a/res/css/structures/_TagPanel.scss b/res/css/structures/_TagPanel.scss index 83e7d46524..85e5c1742f 100644 --- a/res/css/structures/_TagPanel.scss +++ b/res/css/structures/_TagPanel.scss @@ -124,13 +124,28 @@ limitations under the License. padding-right: 4px; } -.mx_TagPanel_groupsButton { +.mx_TagPanel_groupsButton > .mx_AccessibleButton { + flex: auto; margin-bottom: 17px; margin-top: 18px; - height: 25px; - display: none; -} + height: 40px; + width: 40px; + border-radius: 20px; + background-color: $roomheader-addroom-color; + position: relative; + /* overwrite mx_RoleButton inline-block */ + display: block !important; -.mx_TagPanel_groupsButton object { - pointer-events: none; + &:before { + background-color: $tagpanel-bg-color; + mask: url('../../img/icons-groups-nobg.svg'); + mask-repeat: no-repeat; + mask-position: center 8px; + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + } } diff --git a/res/css/views/groups/_GroupRoomList.scss b/res/css/views/groups/_GroupRoomList.scss index fb41ebaa9e..fefd17849c 100644 --- a/res/css/views/groups/_GroupRoomList.scss +++ b/res/css/views/groups/_GroupRoomList.scss @@ -18,4 +18,10 @@ limitations under the License. position: relative; color: $primary-fg-color; cursor: pointer; + display: flex; + align-items: center; +} + +.mx_GroupRoomList_wrapper { + padding: 10px; } diff --git a/res/css/views/rooms/_MemberList.scss b/res/css/views/rooms/_MemberList.scss index e21bc22f2e..2695ebcf31 100644 --- a/res/css/views/rooms/_MemberList.scss +++ b/res/css/views/rooms/_MemberList.scss @@ -20,10 +20,21 @@ limitations under the License. flex: 1; display: flex; flex-direction: column; -} -.mx_MemberList .mx_Spinner { - flex: 1 0 auto; + .mx_Spinner { + flex: 1 0 auto; + } + + h2 { + text-transform: uppercase; + color: $h3-color; + font-weight: 600; + font-size: 13px; + padding-left: 3px; + padding-right: 12px; + margin-top: 8px; + margin-bottom: 4px; + } } .mx_MemberList_chevron { @@ -45,23 +56,15 @@ limitations under the License. flex: 1 1 0; } -.mx_MemberList h2, .mx_GroupMemberList h2 { - text-transform: uppercase; - color: $h3-color; - font-weight: 600; - font-size: 13px; - padding-left: 3px; - padding-right: 12px; - margin-top: 8px; - margin-bottom: 4px; -} + .mx_MemberList_wrapper { padding: 10px; } -.mx_MemberList_invite { +.mx_MemberList_invite, +.mx_RightPanel_invite { flex: 0 0 auto; position: relative; background-color: $button-bg-color; @@ -69,15 +72,20 @@ limitations under the License. padding: 8px; margin: 9px; display: flex; + color: $button-fg-color; + font-weight: 600; - span { - margin: 0 auto; - background-image: url('../../img/icon-invite-people.svg'); - background-repeat: no-repeat; - background-position: center left; - padding-left: 25px; - - font-weight: 600; - color: $button-fg-color; + .mx_RightPanel_icon { + padding-right: 5px; + padding-top: 2px; } } + +.mx_MemberList_invite span { + margin: 0 auto; + background-image: url('../../img/icon-invite-people.svg'); + background-repeat: no-repeat; + background-position: center left; + padding-left: 25px; + +} diff --git a/res/img/icons-groups-nobg.svg b/res/img/icons-groups-nobg.svg new file mode 100644 index 0000000000..a3d223b76d --- /dev/null +++ b/res/img/icons-groups-nobg.svg @@ -0,0 +1,60 @@ + +image/svg+xml + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/img/icons-room-nobg.svg b/res/img/icons-room-nobg.svg new file mode 100644 index 0000000000..8ca7ab272b --- /dev/null +++ b/res/img/icons-room-nobg.svg @@ -0,0 +1,28 @@ + +image/svg+xml + + + + + + + \ No newline at end of file diff --git a/src/components/structures/MainSplit.js b/src/components/structures/MainSplit.js index ea3a97e161..6fd0274f1a 100644 --- a/src/components/structures/MainSplit.js +++ b/src/components/structures/MainSplit.js @@ -19,7 +19,6 @@ import ResizeHandle from '../views/elements/ResizeHandle'; import {Resizer, FixedDistributor} from '../../resizer'; export default class MainSplit extends React.Component { - constructor(props) { super(props); this._setResizeContainerRef = this._setResizeContainerRef.bind(this); diff --git a/src/components/structures/MyGroups.js b/src/components/structures/MyGroups.js index edb50fcedb..c5bf74d561 100644 --- a/src/components/structures/MyGroups.js +++ b/src/components/structures/MyGroups.js @@ -60,7 +60,6 @@ export default withMatrixClient(React.createClass({ render: function() { const Loader = sdk.getComponent("elements.Spinner"); const SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader'); - const TintableSvg = sdk.getComponent("elements.TintableSvg"); const GroupTile = sdk.getComponent("groups.GroupTile"); const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); @@ -112,7 +111,6 @@ export default withMatrixClient(React.createClass({
-
diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index 33c09e1b16..be40957673 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -20,17 +20,14 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { _t } from '../../languageHandler'; import sdk from '../../index'; import dis from '../../dispatcher'; import { MatrixClient } from 'matrix-js-sdk'; import RateLimitedFunc from '../../ratelimitedfunc'; -import AccessibleButton from '../../components/views/elements/AccessibleButton'; import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddressPicker'; import GroupStore from '../../stores/GroupStore'; export default class RightPanel extends React.Component { - static get propTypes() { return { roomId: React.PropTypes.string, // if showing panels for a given room, this is set @@ -141,6 +138,8 @@ export default class RightPanel extends React.Component { if (payload.action === "view_right_panel_phase") { this.setState({ phase: payload.phase, + groupRoomId: payload.groupRoomId, + groupId: payload.groupId, member: payload.member, }); } @@ -157,13 +156,6 @@ export default class RightPanel extends React.Component { const GroupRoomList = sdk.getComponent('groups.GroupRoomList'); const GroupRoomInfo = sdk.getComponent('groups.GroupRoomInfo'); - const TintableSvg = sdk.getComponent("elements.TintableSvg"); - - const isPhaseGroup = [ - RightPanel.Phase.GroupMemberInfo, - RightPanel.Phase.GroupMemberList, - ].includes(this.state.phase); - let panel =
; if (this.props.roomId && this.state.phase === RightPanel.Phase.RoomMemberList) { @@ -190,26 +182,6 @@ export default class RightPanel extends React.Component { panel = ; } - // TODO: either include this in the DOM again, or move it to other component - if (this.props.groupId && this.state.isUserPrivilegedInGroup) { - // inviteGroup = - isPhaseGroup ? ( - -
- -
-
{ _t('Invite to this community') }
-
- ) : ( - -
- -
-
{ _t('Add rooms to this community') }
-
- ); - } - const classes = classNames("mx_RightPanel", "mx_fadable", { "collapsed": this.props.collapsed, "mx_fadable_faded": this.props.disabled, diff --git a/src/components/views/elements/ActionButton.js b/src/components/views/elements/ActionButton.js index e494c216de..a9d95e4a52 100644 --- a/src/components/views/elements/ActionButton.js +++ b/src/components/views/elements/ActionButton.js @@ -30,7 +30,7 @@ export default React.createClass({ action: PropTypes.string.isRequired, mouseOverAction: PropTypes.string, label: PropTypes.string.isRequired, - iconPath: PropTypes.string.isRequired, + iconPath: PropTypes.string, }, getDefaultProps: function() { @@ -72,6 +72,10 @@ export default React.createClass({ tooltip = ; } + const icon = this.props.iconPath ? + () : + undefined; + return ( - + { icon } { tooltip } ); diff --git a/src/components/views/elements/GroupsButton.js b/src/components/views/elements/GroupsButton.js index 75dfe4e9ad..854670cb3f 100644 --- a/src/components/views/elements/GroupsButton.js +++ b/src/components/views/elements/GroupsButton.js @@ -24,7 +24,6 @@ const GroupsButton = function(props) { return ( diff --git a/src/components/views/groups/GroupMemberList.js b/src/components/views/groups/GroupMemberList.js index 38c679a5b5..46653f1599 100644 --- a/src/components/views/groups/GroupMemberList.js +++ b/src/components/views/groups/GroupMemberList.js @@ -17,8 +17,13 @@ limitations under the License. import React from 'react'; import { _t } from '../../../languageHandler'; import sdk from '../../../index'; +import dis from '../../../dispatcher'; import GroupStore from '../../../stores/GroupStore'; import PropTypes from 'prop-types'; +import { showGroupInviteDialog } from '../../../GroupAddressPicker'; +import AccessibleButton from '../elements/AccessibleButton'; +import TintableSvg from '../elements/TintableSvg'; +import RightPanel from '../../structures/RightPanel'; const INITIAL_LOAD_NUM_MEMBERS = 30; @@ -135,6 +140,16 @@ export default React.createClass({ ; }, + onInviteToGroupButtonClick() { + showGroupInviteDialog(this.props.groupId).then(() => { + dis.dispatch({ + action: 'view_right_panel_phase', + phase: RightPanel.Phase.GroupMemberList, + groupId: this.props.groupId, + }); + }); + }, + render: function() { const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); if (this.state.fetching || this.state.fetchingInvitedMembers) { @@ -145,11 +160,9 @@ export default React.createClass({ } const inputBox = ( -
- -
+ ); const joined = this.state.members ?
@@ -162,13 +175,28 @@ export default React.createClass({ { this.makeGroupMemberTiles(this.state.searchQuery, this.state.invitedMembers) }
:
; + let inviteButton; + if (GroupStore.isUserPrivileged(this.props.groupId)) { + inviteButton = ( + +
+ +
+
{ _t('Invite to this community') }
+
); + } + return (
- { inputBox } + { inviteButton } { joined } { invited } + { inputBox }
); }, diff --git a/src/components/views/groups/GroupRoomList.js b/src/components/views/groups/GroupRoomList.js index cfd2b806d4..81fcfa8c8b 100644 --- a/src/components/views/groups/GroupRoomList.js +++ b/src/components/views/groups/GroupRoomList.js @@ -18,6 +18,9 @@ import { _t } from '../../../languageHandler'; import sdk from '../../../index'; import GroupStore from '../../../stores/GroupStore'; import PropTypes from 'prop-types'; +import { showGroupAddRoomDialog } from '../../../GroupAddressPicker'; +import AccessibleButton from '../elements/AccessibleButton'; +import TintableSvg from '../elements/TintableSvg'; const INITIAL_LOAD_NUM_ROOMS = 30; @@ -90,6 +93,12 @@ export default React.createClass({ this.setState({ searchQuery: ev.target.value }); }, + onAddRoomToGroupButtonClick() { + showGroupAddRoomDialog(this.props.groupId).then(() => { + this.forceUpdate(); + }); + }, + makeGroupRoomTiles: function(query) { const GroupRoomTile = sdk.getComponent("groups.GroupRoomTile"); query = (query || "").toLowerCase(); @@ -120,25 +129,38 @@ export default React.createClass({ return null; } + let inviteButton; + if (GroupStore.isUserPrivileged(this.props.groupId)) { + inviteButton = ( + +
+ +
+
{ _t('Add rooms to this community') }
+
+ ); + } const inputBox = ( -
- -
+ ); const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); const TruncatedList = sdk.getComponent("elements.TruncatedList"); return (
- { inputBox } + { inviteButton } { this.makeGroupRoomTiles(this.state.searchQuery) } + { inputBox }
); }, diff --git a/src/components/views/right_panel/GroupHeaderButtons.js b/src/components/views/right_panel/GroupHeaderButtons.js index 3cb0727928..af54787b2c 100644 --- a/src/components/views/right_panel/GroupHeaderButtons.js +++ b/src/components/views/right_panel/GroupHeaderButtons.js @@ -25,7 +25,6 @@ import HeaderButtons from './HeaderButtons'; import RightPanel from '../../structures/RightPanel'; export default class GroupHeaderButtons extends HeaderButtons { - constructor(props) { super(props, RightPanel.Phase.GroupMemberList); } @@ -45,7 +44,7 @@ export default class GroupHeaderButtons extends HeaderButtons { } else if (payload.action === "view_group") { this.setPhase(RightPanel.Phase.GroupMemberList); } else if (payload.action === "view_group_room") { - this.setPhase(RightPanel.Phase.GroupRoomInfo, {groupRoomId: payload.groupRoomId}); + this.setPhase(RightPanel.Phase.GroupRoomInfo, {groupRoomId: payload.groupRoomId, groupId: payload.groupId}); } else if (payload.action === "view_group_room_list") { this.setPhase(RightPanel.Phase.GroupRoomList); } else if (payload.action === "view_group_member_list") { @@ -71,7 +70,7 @@ export default class GroupHeaderButtons extends HeaderButtons { clickPhase={RightPanel.Phase.GroupMemberList} analytics={['Right Panel', 'Group Member List Button', 'click']} />, - { - this.resizer.forHandleWithId(id).resize(size); + const handle = this.resizer.forHandleWithId(id); + if (handle) { + handle.resize(size); + } }); this.resizer.attach(); diff --git a/src/resizer/room.js b/src/resizer/room.js index 70f8be219a..def12d49eb 100644 --- a/src/resizer/room.js +++ b/src/resizer/room.js @@ -38,6 +38,9 @@ class RoomSizer extends Sizer { class RoomDistributor extends FixedDistributor { resize(itemSize) { const scrollItem = this.item.querySelector(".mx_RoomSubList_scroll"); + if (!scrollItem) { + return; //FIXME: happens when starting the page on a community url, taking the safe way out for now + } const fixedHeight = this.item.offsetHeight - scrollItem.offsetHeight; if (itemSize > (fixedHeight + scrollItem.scrollHeight)) { super.resize("resized-all");