Skip to content
This repository was archived by the owner on May 18, 2025. It is now read-only.

Commit 96300b4

Browse files
authored
Merge pull request matrix-org#2336 from matrix-org/travis/notif-button
Show the number of unread notifications above the bell on the right
2 parents bc9c08b + 95d15b7 commit 96300b4

File tree

5 files changed

+65
-11
lines changed

5 files changed

+65
-11
lines changed

res/css/structures/_RightPanel.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ limitations under the License.
5555
padding-bottom: 3px;
5656
}
5757

58+
.mx_RightPanel_headerButton_badgeHighlight .mx_RightPanel_headerButton_badge {
59+
color: $warning-color;
60+
}
61+
5862
.mx_RightPanel_headerButton_highlight {
5963
width: 25px;
6064
height: 5px;

src/Notifier.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,11 @@ const Notifier = {
289289
const room = MatrixClientPeg.get().getRoom(ev.getRoomId());
290290
const actions = MatrixClientPeg.get().getPushActionsForEvent(ev);
291291
if (actions && actions.notify) {
292+
dis.dispatch({
293+
action: "event_notification",
294+
event: ev,
295+
room: room,
296+
});
292297
if (this.isEnabled()) {
293298
this._displayPopupNotification(ev, room);
294299
}

src/Tinter.js

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ class Tinter {
390390
// XXX: we could just move this all into TintableSvg, but as it's so similar
391391
// to the CSS fixup stuff in Tinter (just that the fixups are stored in TintableSvg)
392392
// keeping it here for now.
393-
calcSvgFixups(svgs) {
393+
calcSvgFixups(svgs, forceColors) {
394394
// go through manually fixing up SVG colours.
395395
// we could do this by stylesheets, but keeping the stylesheets
396396
// updated would be a PITA, so just brute-force search for the
@@ -418,13 +418,21 @@ class Tinter {
418418
const tag = tags[j];
419419
for (let k = 0; k < this.svgAttrs.length; k++) {
420420
const attr = this.svgAttrs[k];
421-
for (let l = 0; l < this.keyHex.length; l++) {
422-
if (tag.getAttribute(attr) &&
423-
tag.getAttribute(attr).toUpperCase() === this.keyHex[l]) {
421+
for (let m = 0; m < this.keyHex.length; m++) { // dev note: don't use L please.
422+
// We use a different attribute from the one we're setting
423+
// because we may also be using forceColors. If we were to
424+
// check the keyHex against a forceColors value, it may not
425+
// match and therefore not change when we need it to.
426+
const valAttrName = "mx-val-" + attr;
427+
let attribute = tag.getAttribute(valAttrName);
428+
if (!attribute) attribute = tag.getAttribute(attr); // fall back to the original
429+
if (attribute && (attribute.toUpperCase() === this.keyHex[m] || attribute.toLowerCase() === this.keyRgb[m])) {
424430
fixups.push({
425431
node: tag,
426432
attr: attr,
427-
index: l,
433+
refAttr: valAttrName,
434+
index: m,
435+
forceColors: forceColors,
428436
});
429437
}
430438
}
@@ -440,7 +448,9 @@ class Tinter {
440448
if (DEBUG) console.log("applySvgFixups start for " + fixups);
441449
for (let i = 0; i < fixups.length; i++) {
442450
const svgFixup = fixups[i];
443-
svgFixup.node.setAttribute(svgFixup.attr, this.colors[svgFixup.index]);
451+
const forcedColor = svgFixup.forceColors ? svgFixup.forceColors[svgFixup.index] : null;
452+
svgFixup.node.setAttribute(svgFixup.attr, forcedColor ? forcedColor : this.colors[svgFixup.index]);
453+
svgFixup.node.setAttribute(svgFixup.refAttr, this.colors[svgFixup.index]);
444454
}
445455
if (DEBUG) console.log("applySvgFixups end");
446456
}

src/components/structures/RightPanel.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddres
3030
import GroupStore from '../../stores/GroupStore';
3131

3232
import { formatCount } from '../../utils/FormattingUtils';
33+
import MatrixClientPeg from "../../MatrixClientPeg";
3334

3435
class HeaderButton extends React.Component {
3536
constructor() {
@@ -49,17 +50,26 @@ class HeaderButton extends React.Component {
4950
const TintableSvg = sdk.getComponent("elements.TintableSvg");
5051
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
5152

53+
// XXX: We really shouldn't be hardcoding colors here, but the way TintableSvg
54+
// works kinda prevents us from using normal CSS tactics. We use $warning-color
55+
// here.
56+
// Note: This array gets passed along to the Tinter's forceColors eventually.
57+
const tintableColors = this.props.badgeHighlight ? ["#ff0064"] : null;
58+
59+
const classNames = ["mx_RightPanel_headerButton"];
60+
if (this.props.badgeHighlight) classNames.push("mx_RightPanel_headerButton_badgeHighlight");
61+
5262
return <AccessibleButton
5363
aria-label={this.props.title}
5464
aria-expanded={this.props.isHighlighted}
5565
title={this.props.title}
56-
className="mx_RightPanel_headerButton"
66+
className={classNames.join(" ")}
5767
onClick={this.onClick} >
5868

5969
<div className="mx_RightPanel_headerButton_badge">
6070
{ this.props.badge ? this.props.badge : <span>&nbsp;</span> }
6171
</div>
62-
<TintableSvg src={this.props.iconSrc} width="25" height="25" />
72+
<TintableSvg src={this.props.iconSrc} width="25" height="25" forceColors={tintableColors} />
6373
{ this.props.isHighlighted ? <div className="mx_RightPanel_headerButton_highlight" /> : <div /> }
6474

6575
</AccessibleButton>;
@@ -76,6 +86,7 @@ HeaderButton.propTypes = {
7686

7787
// The badge to display above the icon
7888
badge: PropTypes.node,
89+
badgeHighlight: PropTypes.bool,
7990
// The parameters to track the click event
8091
analytics: PropTypes.arrayOf(PropTypes.string).isRequired,
8192

@@ -205,7 +216,10 @@ module.exports = React.createClass({
205216
}, 500),
206217

207218
onAction: function(payload) {
208-
if (payload.action === "view_user") {
219+
if (payload.action === "event_notification") {
220+
// Try and re-caclulate any badge counts we might have
221+
this.forceUpdate();
222+
} else if (payload.action === "view_user") {
209223
dis.dispatch({
210224
action: 'show_right_panel',
211225
});
@@ -308,6 +322,13 @@ module.exports = React.createClass({
308322

309323
let headerButtons = [];
310324
if (this.props.roomId) {
325+
let notifCountBadge;
326+
let notifCount = 0;
327+
MatrixClientPeg.get().getRooms().forEach(r => notifCount += (r.getUnreadNotificationCount('highlight') || 0));
328+
if (notifCount > 0) {
329+
notifCountBadge = <div title={_t("%counts Notifications")}>{ formatCount(notifCount) }</div>;
330+
}
331+
311332
headerButtons = [
312333
<HeaderButton key="_membersButton" title={membersTitle} iconSrc="img/icons-people.svg"
313334
isHighlighted={[this.Phase.RoomMemberList, this.Phase.RoomMemberInfo].includes(this.state.phase)}
@@ -323,6 +344,7 @@ module.exports = React.createClass({
323344
<HeaderButton key="_notifsButton" title={_t('Notifications')} iconSrc="img/icons-notifications.svg"
324345
isHighlighted={this.state.phase === this.Phase.NotificationPanel}
325346
clickPhase={this.Phase.NotificationPanel}
347+
badge={notifCountBadge} badgeHighlight={notifCount > 0}
326348
analytics={['Right Panel', 'Notification List Button', 'click']}
327349
/>,
328350
];

src/components/views/elements/TintableSvg.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ var TintableSvg = React.createClass({
2929
width: PropTypes.string.isRequired,
3030
height: PropTypes.string.isRequired,
3131
className: PropTypes.string,
32+
forceColors: PropTypes.arrayOf(PropTypes.string),
3233
},
3334

3435
statics: {
@@ -50,15 +51,26 @@ var TintableSvg = React.createClass({
5051
delete TintableSvg.mounts[this.id];
5152
},
5253

54+
componentDidUpdate: function(prevProps, prevState) {
55+
if (prevProps.forceColors !== this.props.forceColors) {
56+
this.calcAndApplyFixups(this.refs.svgContainer);
57+
}
58+
},
59+
5360
tint: function() {
5461
// TODO: only bother running this if the global tint settings have changed
5562
// since we loaded!
5663
Tinter.applySvgFixups(this.fixups);
5764
},
5865

5966
onLoad: function(event) {
60-
// console.log("TintableSvg.onLoad for " + this.props.src);
61-
this.fixups = Tinter.calcSvgFixups([event.target]);
67+
this.calcAndApplyFixups(event.target);
68+
},
69+
70+
calcAndApplyFixups: function(target) {
71+
if (!target) return;
72+
// console.log("TintableSvg.calcAndApplyFixups for " + this.props.src);
73+
this.fixups = Tinter.calcSvgFixups([target], this.props.forceColors);
6274
Tinter.applySvgFixups(this.fixups);
6375
},
6476

@@ -71,6 +83,7 @@ var TintableSvg = React.createClass({
7183
height={this.props.height}
7284
onLoad={this.onLoad}
7385
tabIndex="-1"
86+
ref="svgContainer"
7487
/>
7588
);
7689
},

0 commit comments

Comments
 (0)