+ let icon;
+ if (this.state.icon !== Icon.None) {
+ icon =
;
+ }
+
+ const classes = classNames("mx_DecoratedRoomAvatar", {
+ mx_DecoratedRoomAvatar_cutout: icon,
+ });
+
+ return
-
+ {icon}
{badge}
;
}
diff --git a/src/components/views/rooms/RoomTileIcon.tsx b/src/components/views/rooms/RoomTileIcon.tsx
deleted file mode 100644
index 94833ac818..0000000000
--- a/src/components/views/rooms/RoomTileIcon.tsx
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
-Copyright 2020 The Matrix.org Foundation C.I.C.
-
-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 { Room } from "matrix-js-sdk/src/models/room";
-import { DefaultTagID, TagID } from "../../../stores/room-list/models";
-import { User } from "matrix-js-sdk/src/models/user";
-import { MatrixEvent } from "matrix-js-sdk/src/models/event";
-import DMRoomMap from "../../../utils/DMRoomMap";
-import { MatrixClientPeg } from "../../../MatrixClientPeg";
-import { isPresenceEnabled } from "../../../utils/presence";
-import { _t } from "../../../languageHandler";
-import TextWithTooltip from "../elements/TextWithTooltip";
-
-enum Icon {
- // Note: the names here are used in CSS class names
- None = "NONE", // ... except this one
- Globe = "GLOBE",
- PresenceOnline = "ONLINE",
- PresenceAway = "AWAY",
- PresenceOffline = "OFFLINE",
-}
-
-function tooltipText(variant: Icon) {
- switch (variant) {
- case Icon.Globe:
- return _t("This room is public");
- case Icon.PresenceOnline:
- return _t("Online");
- case Icon.PresenceAway:
- return _t("Away");
- case Icon.PresenceOffline:
- return _t("Offline");
- }
-}
-
-interface IProps {
- room: Room;
-}
-
-interface IState {
- icon: Icon;
-}
-
-export default class RoomTileIcon extends React.Component
{
- private _dmUser: User;
- private isUnmounted = false;
- private isWatchingTimeline = false;
-
- constructor(props: IProps) {
- super(props);
-
- this.state = {
- icon: this.calculateIcon(),
- };
- }
-
- private get isPublicRoom(): boolean {
- const joinRules = this.props.room.currentState.getStateEvents("m.room.join_rules", "");
- const joinRule = joinRules && joinRules.getContent().join_rule;
- return joinRule === 'public';
- }
-
- private get dmUser(): User {
- return this._dmUser;
- }
-
- private set dmUser(val: User) {
- const oldUser = this._dmUser;
- this._dmUser = val;
- if (oldUser && oldUser !== this._dmUser) {
- oldUser.off('User.currentlyActive', this.onPresenceUpdate);
- oldUser.off('User.presence', this.onPresenceUpdate);
- }
- if (this._dmUser && oldUser !== this._dmUser) {
- this._dmUser.on('User.currentlyActive', this.onPresenceUpdate);
- this._dmUser.on('User.presence', this.onPresenceUpdate);
- }
- }
-
- public componentWillUnmount() {
- this.isUnmounted = true;
- if (this.isWatchingTimeline) this.props.room.off('Room.timeline', this.onRoomTimeline);
- this.dmUser = null; // clear listeners, if any
- }
-
- private onRoomTimeline = (ev: MatrixEvent, room: Room) => {
- if (this.isUnmounted) return;
-
- // apparently these can happen?
- if (!room) return;
- if (this.props.room.roomId !== room.roomId) return;
-
- if (ev.getType() === 'm.room.join_rules' || ev.getType() === 'm.room.member') {
- this.setState({icon: this.calculateIcon()});
- }
- };
-
- private onPresenceUpdate = () => {
- if (this.isUnmounted) return;
-
- let newIcon = this.getPresenceIcon();
- if (newIcon !== this.state.icon) this.setState({icon: newIcon});
- };
-
- private getPresenceIcon(): Icon {
- if (!this.dmUser) return Icon.None;
-
- let icon = Icon.None;
-
- const isOnline = this.dmUser.currentlyActive || this.dmUser.presence === 'online';
- if (isOnline) {
- icon = Icon.PresenceOnline;
- } else if (this.dmUser.presence === 'offline') {
- icon = Icon.PresenceOffline;
- } else if (this.dmUser.presence === 'unavailable') {
- icon = Icon.PresenceAway;
- }
-
- return icon;
- }
-
- private calculateIcon(): Icon {
- let icon = Icon.None;
-
- // We look at the DMRoomMap and not the tag here so that we don't exclude DMs in Favourites
- const otherUserId = DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId);
- if (otherUserId && this.props.room.getJoinedMemberCount() === 2) {
- // Track presence, if available
- if (isPresenceEnabled()) {
- if (otherUserId) {
- this.dmUser = MatrixClientPeg.get().getUser(otherUserId);
- icon = this.getPresenceIcon();
- }
- }
- } else {
- // Track publicity
- icon = this.isPublicRoom ? Icon.Globe : Icon.None;
- if (!this.isWatchingTimeline) {
- this.props.room.on('Room.timeline', this.onRoomTimeline);
- this.isWatchingTimeline = true;
- }
- }
- return icon;
- }
-
- public render(): React.ReactElement {
- if (this.state.icon === Icon.None) return null;
-
- return ;
- }
-}
From d861536487d44fb2dc5594e1bc27cc6b0fe821c9 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 14 Aug 2020 10:30:54 +0100
Subject: [PATCH 08/13] Make globe transparent
---
res/css/views/avatars/_DecoratedRoomAvatar.scss | 3 ---
1 file changed, 3 deletions(-)
diff --git a/res/css/views/avatars/_DecoratedRoomAvatar.scss b/res/css/views/avatars/_DecoratedRoomAvatar.scss
index 2e4caf8e91..e0afd9de66 100644
--- a/res/css/views/avatars/_DecoratedRoomAvatar.scss
+++ b/res/css/views/avatars/_DecoratedRoomAvatar.scss
@@ -43,9 +43,6 @@ limitations under the License.
border-radius: 8px;
}
- .mx_DecoratedRoomAvatar_icon_globe {
- background-color: #fff;
- }
.mx_DecoratedRoomAvatar_icon_globe::before {
mask-position: center;
mask-size: contain;
From 228d1af6dca3dce8cdce8ee7bc482595291eec32 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 14 Aug 2020 11:01:03 +0100
Subject: [PATCH 09/13] i18n
---
src/i18n/strings/en_EN.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index b636b5470e..0f8891b5fe 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -1186,8 +1186,6 @@
"%(count)s unread messages.|other": "%(count)s unread messages.",
"%(count)s unread messages.|one": "1 unread message.",
"Unread messages.": "Unread messages.",
- "This room is public": "This room is public",
- "Away": "Away",
"Add a topic": "Add a topic",
"Upgrading this room will shut down the current instance of the room and create an upgraded room with the same name.": "Upgrading this room will shut down the current instance of the room and create an upgraded room with the same name.",
"This room has already been upgraded.": "This room has already been upgraded.",
@@ -1893,6 +1891,8 @@
"Take picture": "Take picture",
"Remove for everyone": "Remove for everyone",
"Remove for me": "Remove for me",
+ "This room is public": "This room is public",
+ "Away": "Away",
"User Status": "User Status",
"powered by Matrix": "powered by Matrix",
"This homeserver would like to make sure you are not a robot.": "This homeserver would like to make sure you are not a robot.",
From f982c7b334c5854538283f1f48bc60aefc7181e8 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 14 Aug 2020 13:22:52 +0100
Subject: [PATCH 10/13] Message Action Bar, subscribe to localEventIdReplaced
events
---
src/components/views/messages/MessageActionBar.js | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js
index 513f21b8b7..fa722a1e06 100644
--- a/src/components/views/messages/MessageActionBar.js
+++ b/src/components/views/messages/MessageActionBar.js
@@ -116,11 +116,13 @@ export default class MessageActionBar extends React.PureComponent {
componentDidMount() {
this.props.mxEvent.on("Event.decrypted", this.onDecrypted);
this.props.mxEvent.on("Event.beforeRedaction", this.onBeforeRedaction);
+ this.props.mxEvent.on("Event.localEventIdReplaced", this.onEcho);
}
componentWillUnmount() {
this.props.mxEvent.removeListener("Event.decrypted", this.onDecrypted);
this.props.mxEvent.removeListener("Event.beforeRedaction", this.onBeforeRedaction);
+ this.props.mxEvent.removeListener("Event.localEventIdReplaced", this.onEcho);
}
onDecrypted = () => {
@@ -134,6 +136,11 @@ export default class MessageActionBar extends React.PureComponent {
this.forceUpdate();
};
+ onEcho = () => {
+ // When an event is sent and echoed the possible actions change.
+ this.forceUpdate();
+ };
+
onFocusChange = (focused) => {
if (!this.props.onFocusChange) {
return;
From de9816574f0e3ef5a3bc7193264a962e7fc6ea25 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 14 Aug 2020 13:30:27 +0100
Subject: [PATCH 11/13] Make event subscriptions conditional when needed
---
src/components/views/messages/MessageActionBar.js | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js
index fa722a1e06..043fe1a985 100644
--- a/src/components/views/messages/MessageActionBar.js
+++ b/src/components/views/messages/MessageActionBar.js
@@ -114,15 +114,19 @@ export default class MessageActionBar extends React.PureComponent {
static contextType = RoomContext;
componentDidMount() {
- this.props.mxEvent.on("Event.decrypted", this.onDecrypted);
+ if (this.props.mxEvent.isBeingDecrypted()) {
+ this.props.mxEvent.once("Event.decrypted", this.onDecrypted);
+ }
this.props.mxEvent.on("Event.beforeRedaction", this.onBeforeRedaction);
- this.props.mxEvent.on("Event.localEventIdReplaced", this.onEcho);
+ if (this.props.mxEvent.getId()[0] !== "!") {
+ this.props.mxEvent.once("Event.localEventIdReplaced", this.onEcho);
+ }
}
componentWillUnmount() {
- this.props.mxEvent.removeListener("Event.decrypted", this.onDecrypted);
- this.props.mxEvent.removeListener("Event.beforeRedaction", this.onBeforeRedaction);
- this.props.mxEvent.removeListener("Event.localEventIdReplaced", this.onEcho);
+ this.props.mxEvent.off("Event.decrypted", this.onDecrypted);
+ this.props.mxEvent.off("Event.beforeRedaction", this.onBeforeRedaction);
+ this.props.mxEvent.off("Event.localEventIdReplaced", this.onEcho);
}
onDecrypted = () => {
From 591847b27426264d8052e07f484036c1bd51ea8b Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 14 Aug 2020 13:37:11 +0100
Subject: [PATCH 12/13] Watch for Event.status instead as we can do some things
in SENT
---
src/components/views/messages/MessageActionBar.js | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js
index 043fe1a985..4a6b3c39fb 100644
--- a/src/components/views/messages/MessageActionBar.js
+++ b/src/components/views/messages/MessageActionBar.js
@@ -18,6 +18,7 @@ limitations under the License.
import React, {useEffect} from 'react';
import PropTypes from 'prop-types';
+import { EventStatus } from 'matrix-js-sdk';
import { _t } from '../../../languageHandler';
import * as sdk from '../../../index';
@@ -114,19 +115,19 @@ export default class MessageActionBar extends React.PureComponent {
static contextType = RoomContext;
componentDidMount() {
+ if (this.props.mxEvent.status && this.props.mxEvent !== EventStatus.SENT) {
+ this.props.mxEvent.on("Event.status", this.onSent);
+ }
if (this.props.mxEvent.isBeingDecrypted()) {
this.props.mxEvent.once("Event.decrypted", this.onDecrypted);
}
this.props.mxEvent.on("Event.beforeRedaction", this.onBeforeRedaction);
- if (this.props.mxEvent.getId()[0] !== "!") {
- this.props.mxEvent.once("Event.localEventIdReplaced", this.onEcho);
- }
}
componentWillUnmount() {
+ this.props.mxEvent.off("Event.status", this.onSent);
this.props.mxEvent.off("Event.decrypted", this.onDecrypted);
this.props.mxEvent.off("Event.beforeRedaction", this.onBeforeRedaction);
- this.props.mxEvent.off("Event.localEventIdReplaced", this.onEcho);
}
onDecrypted = () => {
@@ -140,7 +141,7 @@ export default class MessageActionBar extends React.PureComponent {
this.forceUpdate();
};
- onEcho = () => {
+ onSent = () => {
// When an event is sent and echoed the possible actions change.
this.forceUpdate();
};
From 655cc955708d04f8c26600448c6b04b2709d4c13 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 14 Aug 2020 13:37:28 +0100
Subject: [PATCH 13/13] fix typo
---
src/components/views/messages/MessageActionBar.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js
index 4a6b3c39fb..c94f296eac 100644
--- a/src/components/views/messages/MessageActionBar.js
+++ b/src/components/views/messages/MessageActionBar.js
@@ -115,7 +115,7 @@ export default class MessageActionBar extends React.PureComponent {
static contextType = RoomContext;
componentDidMount() {
- if (this.props.mxEvent.status && this.props.mxEvent !== EventStatus.SENT) {
+ if (this.props.mxEvent.status && this.props.mxEvent.status !== EventStatus.SENT) {
this.props.mxEvent.on("Event.status", this.onSent);
}
if (this.props.mxEvent.isBeingDecrypted()) {