diff --git a/res/css/_components.scss b/res/css/_components.scss index bb09b873a3..36648f4982 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -115,6 +115,8 @@ @import "./views/messages/_MTextBody.scss"; @import "./views/messages/_MessageActionBar.scss"; @import "./views/messages/_MessageTimestamp.scss"; +@import "./views/messages/_ReactionsRow.scss"; +@import "./views/messages/_ReactionsRowButton.scss"; @import "./views/messages/_RoomAvatarEvent.scss"; @import "./views/messages/_SenderProfile.scss"; @import "./views/messages/_TextualEvent.scss"; diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss new file mode 100644 index 0000000000..fb66ffbb8c --- /dev/null +++ b/res/css/views/messages/_ReactionsRow.scss @@ -0,0 +1,19 @@ +/* +Copyright 2019 New Vector 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_ReactionsRow { + margin: 6px 0; +} diff --git a/res/css/views/messages/_ReactionsRowButton.scss b/res/css/views/messages/_ReactionsRowButton.scss new file mode 100644 index 0000000000..9cbf839f21 --- /dev/null +++ b/res/css/views/messages/_ReactionsRowButton.scss @@ -0,0 +1,30 @@ +/* +Copyright 2019 New Vector 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_ReactionsRowButton { + display: inline-block; + height: 20px; + line-height: 21px; + margin-right: 6px; + padding: 0 6px; + border: 1px solid $reaction-row-button-border-color; + border-radius: 10px; + background-color: $reaction-row-button-bg-color; + + &:hover { + border-color: $reaction-row-button-hover-border-color; + } +} diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 7c0f8ef9ab..30066c7af4 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -151,6 +151,10 @@ $message-action-bar-fg-color: $header-panel-text-primary-color; $message-action-bar-border-color: #616b7f; $message-action-bar-hover-border-color: $header-panel-text-primary-color; +$reaction-row-button-bg-color: $header-panel-bg-color; +$reaction-row-button-border-color: #616b7f; +$reaction-row-button-hover-border-color: $header-panel-text-primary-color; + // ***** Mixins! ***** @define-mixin mx_DialogButton { diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 7451a23991..223d0fc80c 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -259,6 +259,10 @@ $message-action-bar-fg-color: $primary-fg-color; $message-action-bar-border-color: #e9edf1; $message-action-bar-hover-border-color: #b8c1d2; +$reaction-row-button-bg-color: $header-panel-bg-color; +$reaction-row-button-border-color: #e9edf1; +$reaction-row-button-hover-border-color: #bebebe; + // ***** Mixins! ***** @define-mixin mx_DialogButton { diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.js new file mode 100644 index 0000000000..a4299b9853 --- /dev/null +++ b/src/components/views/messages/ReactionsRow.js @@ -0,0 +1,65 @@ +/* +Copyright 2019 New Vector 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 React from 'react'; +import PropTypes from 'prop-types'; + +import sdk from '../../../index'; +import { isContentActionable } from '../../../utils/EventUtils'; + +// TODO: Actually load reactions from the timeline +// Since we don't yet load reactions, let's inject some dummy data for testing the UI +// only. The UI assumes these are already sorted into the order we want to present, +// presumably highest vote first. +const SAMPLE_REACTIONS = { + "👍": 4, + "👎": 2, + "🙂": 1, +}; + +export default class ReactionsRow extends React.PureComponent { + static propTypes = { + // The event we're displaying reactions for + mxEvent: PropTypes.object.isRequired, + } + + render() { + const { mxEvent } = this.props; + + if (!isContentActionable(mxEvent)) { + return null; + } + + const content = mxEvent.getContent(); + // TODO: Remove this once we load real reactions + if (!content.body || content.body !== "reactions test") { + return null; + } + + const ReactionsRowButton = sdk.getComponent('messages.ReactionsRowButton'); + const items = Object.entries(SAMPLE_REACTIONS).map(([content, count]) => { + return ; + }); + + return
+ {items} +
; + } +} diff --git a/src/components/views/messages/ReactionsRowButton.js b/src/components/views/messages/ReactionsRowButton.js new file mode 100644 index 0000000000..4afcf93fff --- /dev/null +++ b/src/components/views/messages/ReactionsRowButton.js @@ -0,0 +1,33 @@ +/* +Copyright 2019 New Vector 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 React from 'react'; +import PropTypes from 'prop-types'; + +export default class ReactionsRowButton extends React.PureComponent { + static propTypes = { + content: PropTypes.string.isRequired, + count: PropTypes.number.isRequired, + } + + render() { + const { content, count } = this.props; + + return + {content} {count} + ; + } +} diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index dd0a7aa47b..6bec3f4fff 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -622,6 +622,14 @@ module.exports = withMatrixClient(React.createClass({ : null; + let reactions; + if (SettingsStore.isFeatureEnabled("feature_reactions")) { + const ReactionsRow = sdk.getComponent('messages.ReactionsRow'); + reactions = ; + } + switch (this.props.tileShape) { case 'notif': { const EmojiText = sdk.getComponent('elements.EmojiText'); @@ -734,6 +742,7 @@ module.exports = withMatrixClient(React.createClass({ showUrlPreview={this.props.showUrlPreview} onHeightChanged={this.props.onHeightChanged} /> { keyRequestInfo } + { reactions } { actionBar } {