diff --git a/res/css/_components.scss b/res/css/_components.scss index 20395550ab..7b8ca77739 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -173,6 +173,7 @@ @import "./views/rooms/_SendMessageComposer.scss"; @import "./views/rooms/_Stickers.scss"; @import "./views/rooms/_TopUnreadMessagesBar.scss"; +@import "./views/rooms/_UserOnlineDot.scss"; @import "./views/rooms/_WhoIsTypingTile.scss"; @import "./views/settings/_AvatarSetting.scss"; @import "./views/settings/_CrossSigningPanel.scss"; diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index 1814919b61..e5c7948216 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. diff --git a/res/css/views/rooms/_UserOnlineDot.scss b/res/css/views/rooms/_UserOnlineDot.scss new file mode 100644 index 0000000000..339e5cc48a --- /dev/null +++ b/res/css/views/rooms/_UserOnlineDot.scss @@ -0,0 +1,23 @@ +/* +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. +*/ + +.mx_UserOnlineDot { + border-radius: 50%; + background-color: $accent-color; + height: 5px; + width: 5px; + display: inline-block; +} diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 817ada9706..ecf2de394b 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -68,11 +68,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 +366,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; + + const { room } = this.props; + if (room.getMember(dmUserId).membership === "join" && room.getJoinedMemberCount() === 2) { + const UserOnlineDot = sdk.getComponent('rooms.UserOnlineDot'); + 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/UserOnlineDot.js b/src/components/views/rooms/UserOnlineDot.js new file mode 100644 index 0000000000..426dd1bf64 --- /dev/null +++ b/src/components/views/rooms/UserOnlineDot.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 UserOnlineDot = ({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; +}; + +UserOnlineDot.propTypes = { + userId: PropTypes.string.isRequired, +}; + +export default UserOnlineDot;