diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index 1814919b61..2b181f366e 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2019 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. @@ -61,6 +62,14 @@ limitations under the License. min-width: 0; } +.mx_RoomTile_online_dot { + border-radius: 50%; + background-color: $accent-color; + height: 5px; + width: 5px; + display: inline-block; +} + .mx_RoomTile_subtext { display: inline-block; font-size: 11px; diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 817ada9706..797aa7b87a 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -32,6 +32,7 @@ import ActiveRoomObserver from '../../../ActiveRoomObserver'; import RoomViewStore from '../../../stores/RoomViewStore'; import SettingsStore from "../../../settings/SettingsStore"; import {_t} from "../../../languageHandler"; +import RoomTileOnlineDot from "./RoomTileOnlineDot"; module.exports = createReactClass({ displayName: 'RoomTile', @@ -68,11 +69,6 @@ module.exports = createReactClass({ }); }, - _isDirectMessageRoom: function(roomId) { - const dmRooms = DMRoomMap.shared().getUserIdForRoomId(roomId); - return Boolean(dmRooms); - }, - _shouldShowStatusMessage() { if (!SettingsStore.isFeatureEnabled("feature_custom_status")) { return false; @@ -371,8 +367,11 @@ module.exports = createReactClass({ let ariaLabel = name; + const dmUserId = DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId); + let dmIndicator; - if (this._isDirectMessageRoom(this.props.room.roomId)) { + let dmOnline; + if (dmUserId) { dmIndicator = dm; + + if (this.props.room.getMember(dmUserId).membership === "join") { + const RoomTileOnlineDot = sdk.getComponent('rooms.RoomTileOnlineDot'); + dmOnline = ; + } } // The following labels are written in such a fashion to increase screen reader efficiency (speed). @@ -428,6 +432,7 @@ module.exports = createReactClass({ { label } { subtextLabel } + { dmOnline } { contextMenuButton } { badge } diff --git a/src/components/views/rooms/RoomTileOnlineDot.js b/src/components/views/rooms/RoomTileOnlineDot.js new file mode 100644 index 0000000000..a882aec613 --- /dev/null +++ b/src/components/views/rooms/RoomTileOnlineDot.js @@ -0,0 +1,48 @@ +/* +Copyright 2019 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, {useContext, useEffect, useMemo, useState, useCallback} from "react"; +import PropTypes from "prop-types"; + +import {useEventEmitter} from "../../../hooks/useEventEmitter"; +import MatrixClientContext from "../../../contexts/MatrixClientContext"; + +const RoomTileOnlineDot = ({userId}) => { + const cli = useContext(MatrixClientContext); + const user = useMemo(() => cli.getUser(userId), [cli, userId]); + + const [isOnline, setIsOnline] = useState(false); + + // Recheck if the user or client changes + useEffect(() => { + setIsOnline(user && (user.currentlyActive || user.presence === "online")); + }, [cli, user]); + // Recheck also if we receive a User.currentlyActive event + const currentlyActiveHandler = useCallback((ev) => { + const content = ev.getContent(); + setIsOnline(content.currently_active || content.presence === "online"); + }, []); + useEventEmitter(user, "User.currentlyActive", currentlyActiveHandler); + useEventEmitter(user, "User.presence", currentlyActiveHandler); + + return isOnline ? : null; +}; + +RoomTileOnlineDot.propTypes = { + userId: PropTypes.string.isRequired, +}; + +export default RoomTileOnlineDot;