diff --git a/src/components/structures/BottomLeftMenu.js b/src/components/structures/BottomLeftMenu.js index f357bede96..9e7442cd90 100644 --- a/src/components/structures/BottomLeftMenu.js +++ b/src/components/structures/BottomLeftMenu.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +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. @@ -14,13 +15,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -'use strict'; +import React from 'react'; +import ReactDOM from 'react-dom'; +import sdk from 'matrix-react-sdk'; +import dis from 'matrix-react-sdk/lib/dispatcher'; +import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton'; +import Velocity from 'velocity-vector'; +import 'velocity-vector/velocity.ui'; -var React = require('react'); -var ReactDOM = require('react-dom'); -var sdk = require('matrix-react-sdk') -var dis = require('matrix-react-sdk/lib/dispatcher'); -var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton'); +const CALLOUT_ANIM_DURATION = 1000; module.exports = React.createClass({ displayName: 'BottomLeftMenu', @@ -39,6 +42,18 @@ module.exports = React.createClass({ }); }, + componentWillMount: function() { + this._dispatcherRef = dis.register(this.onAction); + this._peopleButton = null; + this._directoryButton = null; + this._createRoomButton = null; + this._lastCallouts = {}; + }, + + componentWillUnmount: function() { + dis.unregister(this._dispatcherRef); + }, + // Room events onDirectoryClick: function() { dis.dispatch({ action: 'view_room_directory' }); @@ -103,6 +118,30 @@ module.exports = React.createClass({ this.setState({ settingsHover: false }); }, + onAction: function(payload) { + let calloutElement; + switch (payload.action) { + // Incoming instruction: dance! + case 'callout_start_chat': + calloutElement = this._peopleButton; + break; + case 'callout_room_directory': + calloutElement = this._directoryButton; + break; + case 'callout_create_room': + calloutElement = this._createRoomButton; + break; + } + if (calloutElement) { + const lastCallout = this._lastCallouts[payload.action]; + const now = Date.now(); + if (lastCallout == undefined || lastCallout < now - CALLOUT_ANIM_DURATION) { + this._lastCallouts[payload.action] = now; + Velocity(ReactDOM.findDOMNode(calloutElement), "callout.bounce", CALLOUT_ANIM_DURATION); + } + } + }, + // Get the label/tooltip to show getLabel: function(label, show) { if (show) { @@ -111,31 +150,46 @@ module.exports = React.createClass({ } }, + _collectPeopleButton: function(e) { + this._peopleButton = e; + }, + + _collectDirectoryButton: function(e) { + this._directoryButton = e; + }, + + _collectCreateRoomButton: function(e) { + this._createRoomButton = e; + }, + render: function() { - var TintableSvg = sdk.getComponent('elements.TintableSvg'); + const HomeButton = sdk.getComponent('elements.HomeButton'); + const StartChatButton = sdk.getComponent('elements.StartChatButton'); + const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton'); + const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton'); + const SettingsButton = sdk.getComponent('elements.SettingsButton'); + + var homeButton; + if (this.props.teamToken) { + homeButton = ; + } + return (
- - - { this.getLabel("Welcome page", this.state.homeHover) } - - - - { this.getLabel("Start chat", this.state.peopleHover) } - - - - { this.getLabel("Room directory", this.state.directoryHover) } - - - - { this.getLabel("Create new room", this.state.roomsHover) } - - - - { this.getLabel("Settings", this.state.settingsHover) } - + { homeButton } +
+ +
+
+ +
+
+ +
+ + +
); diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index 6490e4564c..afd7b8b211 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -1,4 +1,5 @@ /* +Copyright 2017 Vector Creations Ltd Copyright 2015, 2016 OpenMarket Ltd Licensed under the Apache License, Version 2.0 (the "License"); @@ -83,6 +84,8 @@ var RoomSubList = React.createClass({ incomingCall: React.PropTypes.object, onShowMoreRooms: React.PropTypes.func, searchFilter: React.PropTypes.string, + emptyContent: React.PropTypes.node, // content shown if the list is empty + headerItems: React.PropTypes.node, // content shown in the sublist header }, getInitialState: function() { @@ -521,16 +524,15 @@ var RoomSubList = React.createClass({ render: function() { var connectDropTarget = this.props.connectDropTarget; - var RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget'); var TruncatedList = sdk.getComponent('elements.TruncatedList'); var label = this.props.collapsed ? null : this.props.label; - //console.log("render: " + JSON.stringify(this.state.sortedList)); - - var target; - if (this.state.sortedList.length == 0 && this.props.editable) { - target = ; + let content; + if (this.state.sortedList.length == 0) { + content = this.props.emptyContent; + } else { + content = this.makeRoomTiles(); } if (this.state.sortedList.length > 0 || this.props.editable) { @@ -540,8 +542,7 @@ var RoomSubList = React.createClass({ if (!this.state.hidden) { subList = - { target } - { this.makeRoomTiles() } + { content } ; } else { diff --git a/src/skins/vector/css/_components.scss b/src/skins/vector/css/_components.scss index 225fd35712..b1964dca04 100644 --- a/src/skins/vector/css/_components.scss +++ b/src/skins/vector/css/_components.scss @@ -27,6 +27,7 @@ @import "./matrix-react-sdk/views/elements/_MemberEventListSummary.scss"; @import "./matrix-react-sdk/views/elements/_ProgressBar.scss"; @import "./matrix-react-sdk/views/elements/_RichText.scss"; +@import "./matrix-react-sdk/views/elements/_RoleButton.scss"; @import "./matrix-react-sdk/views/login/_InteractiveAuthEntryComponents.scss"; @import "./matrix-react-sdk/views/login/_ServerConfig.scss"; @import "./matrix-react-sdk/views/messages/_MEmoteBody.scss"; diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss b/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss new file mode 100644 index 0000000000..094e0b9b1b --- /dev/null +++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss @@ -0,0 +1,33 @@ +/* +Copyright 2107 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. +*/ + +.mx_RoleButton { + margin-left: 4px; + margin-right: 4px; + cursor: pointer; + display: inline-block; +} + +.mx_RoleButton object { + pointer-events: none; +} + +.mx_RoleButton_tooltip { + display: inline-block; + position: relative; + top: -25px; + left: 6px; +} diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss index 110dcd5b6b..35787ca0c4 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2107 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. @@ -37,3 +38,25 @@ limitations under the License. .mx_RoomList_scrollbar .gm-scrollbar.-vertical { z-index: 6; } + +.mx_RoomList_emptySubListTip { + font-size: 13px; + margin-left: 18px; + margin-right: 18px; + margin-top: 8px; + margin-bottom: 7px; + padding: 5px; + border: 1px dashed $accent-color; + color: $primary-fg-color; + background-color: $droptarget-bg-color; + border-radius: 4px; +} + +.mx_RoomList_emptySubListTip .mx_RoleButton { + vertical-align: -3px; +} + +.mx_RoomList_headerButtons { + position: absolute; + right: 60px; +} diff --git a/src/skins/vector/css/vector-web/structures/_LeftPanel.scss b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss index d3bbce1b19..dbe745f799 100644 --- a/src/skins/vector/css/vector-web/structures/_LeftPanel.scss +++ b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss @@ -64,43 +64,29 @@ limitations under the License. pointer-events: none; } -.mx_LeftPanel .mx_BottomLeftMenu_homePage, -.mx_LeftPanel .mx_BottomLeftMenu_directory, -.mx_LeftPanel .mx_BottomLeftMenu_createRoom, -.mx_LeftPanel .mx_BottomLeftMenu_people, -.mx_LeftPanel .mx_BottomLeftMenu_settings { - display: inline-block; - cursor: pointer; -} - -.collapsed .mx_BottomLeftMenu_homePage, -.collapsed .mx_BottomLeftMenu_directory, -.collapsed .mx_BottomLeftMenu_createRoom, -.collapsed .mx_BottomLeftMenu_people, -.collapsed .mx_BottomLeftMenu_settings { +.collapsed .mx_RoleButton { margin-right: 0px ! important; padding-top: 3px ! important; padding-bottom: 3px ! important; } -.mx_LeftPanel .mx_BottomLeftMenu_homePage, -.mx_LeftPanel .mx_BottomLeftMenu_directory, -.mx_LeftPanel .mx_BottomLeftMenu_createRoom, -.mx_LeftPanel .mx_BottomLeftMenu_people { +.mx_BottomLeftMenu_options > div { + display: inline-block; +} + +.mx_BottomLeftMenu_options .mx_RoleButton { + margin-left: 0px; margin-right: 10px; } -.mx_LeftPanel .mx_BottomLeftMenu_settings { +.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings { float: right; } +.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings .mx_RoleButton { + margin-right: 0px; +} + .mx_LeftPanel.collapsed .mx_BottomLeftMenu_settings { float: none; } - -.mx_LeftPanel .mx_BottomLeftMenu_tooltip { - display: inline-block; - position: relative; - top: -25px; - left: 6px; -}