diff --git a/res/css/structures/_RightPanel.scss b/res/css/structures/_RightPanel.scss index b4dff612ed0..554aabfcd10 100644 --- a/res/css/structures/_RightPanel.scss +++ b/res/css/structures/_RightPanel.scss @@ -55,6 +55,10 @@ limitations under the License. padding-bottom: 3px; } +.mx_RightPanel_headerButton_badgeHighlight .mx_RightPanel_headerButton_badge { + color: $warning-color; +} + .mx_RightPanel_headerButton_highlight { width: 25px; height: 5px; diff --git a/src/Notifier.js b/src/Notifier.js index 80e8be10846..8550f3bf954 100644 --- a/src/Notifier.js +++ b/src/Notifier.js @@ -289,6 +289,11 @@ const Notifier = { const room = MatrixClientPeg.get().getRoom(ev.getRoomId()); const actions = MatrixClientPeg.get().getPushActionsForEvent(ev); if (actions && actions.notify) { + dis.dispatch({ + action: "event_notification", + event: ev, + room: room, + }); if (this.isEnabled()) { this._displayPopupNotification(ev, room); } diff --git a/src/Tinter.js b/src/Tinter.js index d24a4c3e74b..9c2afd4fab5 100644 --- a/src/Tinter.js +++ b/src/Tinter.js @@ -390,7 +390,7 @@ class Tinter { // XXX: we could just move this all into TintableSvg, but as it's so similar // to the CSS fixup stuff in Tinter (just that the fixups are stored in TintableSvg) // keeping it here for now. - calcSvgFixups(svgs) { + calcSvgFixups(svgs, forceColors) { // go through manually fixing up SVG colours. // we could do this by stylesheets, but keeping the stylesheets // updated would be a PITA, so just brute-force search for the @@ -418,13 +418,21 @@ class Tinter { const tag = tags[j]; for (let k = 0; k < this.svgAttrs.length; k++) { const attr = this.svgAttrs[k]; - for (let l = 0; l < this.keyHex.length; l++) { - if (tag.getAttribute(attr) && - tag.getAttribute(attr).toUpperCase() === this.keyHex[l]) { + for (let m = 0; m < this.keyHex.length; m++) { // dev note: don't use L please. + // We use a different attribute from the one we're setting + // because we may also be using forceColors. If we were to + // check the keyHex against a forceColors value, it may not + // match and therefore not change when we need it to. + const valAttrName = "mx-val-" + attr; + let attribute = tag.getAttribute(valAttrName); + if (!attribute) attribute = tag.getAttribute(attr); // fall back to the original + if (attribute && (attribute.toUpperCase() === this.keyHex[m] || attribute.toLowerCase() === this.keyRgb[m])) { fixups.push({ node: tag, attr: attr, - index: l, + refAttr: valAttrName, + index: m, + forceColors: forceColors, }); } } @@ -440,7 +448,9 @@ class Tinter { if (DEBUG) console.log("applySvgFixups start for " + fixups); for (let i = 0; i < fixups.length; i++) { const svgFixup = fixups[i]; - svgFixup.node.setAttribute(svgFixup.attr, this.colors[svgFixup.index]); + const forcedColor = svgFixup.forceColors ? svgFixup.forceColors[svgFixup.index] : null; + svgFixup.node.setAttribute(svgFixup.attr, forcedColor ? forcedColor : this.colors[svgFixup.index]); + svgFixup.node.setAttribute(svgFixup.refAttr, this.colors[svgFixup.index]); } if (DEBUG) console.log("applySvgFixups end"); } diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index 9017447a343..0870f085a52 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -30,6 +30,7 @@ import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddres import GroupStore from '../../stores/GroupStore'; import { formatCount } from '../../utils/FormattingUtils'; +import MatrixClientPeg from "../../MatrixClientPeg"; class HeaderButton extends React.Component { constructor() { @@ -49,17 +50,26 @@ class HeaderButton extends React.Component { const TintableSvg = sdk.getComponent("elements.TintableSvg"); const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); + // XXX: We really shouldn't be hardcoding colors here, but the way TintableSvg + // works kinda prevents us from using normal CSS tactics. We use $warning-color + // here. + // Note: This array gets passed along to the Tinter's forceColors eventually. + const tintableColors = this.props.badgeHighlight ? ["#ff0064"] : null; + + const classNames = ["mx_RightPanel_headerButton"]; + if (this.props.badgeHighlight) classNames.push("mx_RightPanel_headerButton_badgeHighlight"); + return
{ this.props.badge ? this.props.badge :   }
- + { this.props.isHighlighted ?
:
} ; @@ -76,6 +86,7 @@ HeaderButton.propTypes = { // The badge to display above the icon badge: PropTypes.node, + badgeHighlight: PropTypes.bool, // The parameters to track the click event analytics: PropTypes.arrayOf(PropTypes.string).isRequired, @@ -205,7 +216,10 @@ module.exports = React.createClass({ }, 500), onAction: function(payload) { - if (payload.action === "view_user") { + if (payload.action === "event_notification") { + // Try and re-caclulate any badge counts we might have + this.forceUpdate(); + } else if (payload.action === "view_user") { dis.dispatch({ action: 'show_right_panel', }); @@ -308,6 +322,13 @@ module.exports = React.createClass({ let headerButtons = []; if (this.props.roomId) { + let notifCountBadge; + let notifCount = 0; + MatrixClientPeg.get().getRooms().forEach(r => notifCount += (r.getUnreadNotificationCount('highlight') || 0)); + if (notifCount > 0) { + notifCountBadge =
{ formatCount(notifCount) }
; + } + headerButtons = [ 0} analytics={['Right Panel', 'Notification List Button', 'click']} />, ]; diff --git a/src/components/views/elements/TintableSvg.js b/src/components/views/elements/TintableSvg.js index e04bf87793e..08628c8ca9a 100644 --- a/src/components/views/elements/TintableSvg.js +++ b/src/components/views/elements/TintableSvg.js @@ -29,6 +29,7 @@ var TintableSvg = React.createClass({ width: PropTypes.string.isRequired, height: PropTypes.string.isRequired, className: PropTypes.string, + forceColors: PropTypes.arrayOf(PropTypes.string), }, statics: { @@ -50,6 +51,12 @@ var TintableSvg = React.createClass({ delete TintableSvg.mounts[this.id]; }, + componentDidUpdate: function(prevProps, prevState) { + if (prevProps.forceColors !== this.props.forceColors) { + this.calcAndApplyFixups(this.refs.svgContainer); + } + }, + tint: function() { // TODO: only bother running this if the global tint settings have changed // since we loaded! @@ -57,8 +64,13 @@ var TintableSvg = React.createClass({ }, onLoad: function(event) { - // console.log("TintableSvg.onLoad for " + this.props.src); - this.fixups = Tinter.calcSvgFixups([event.target]); + this.calcAndApplyFixups(event.target); + }, + + calcAndApplyFixups: function(target) { + if (!target) return; + // console.log("TintableSvg.calcAndApplyFixups for " + this.props.src); + this.fixups = Tinter.calcSvgFixups([target], this.props.forceColors); Tinter.applySvgFixups(this.fixups); }, @@ -71,6 +83,7 @@ var TintableSvg = React.createClass({ height={this.props.height} onLoad={this.onLoad} tabIndex="-1" + ref="svgContainer" /> ); },