diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index 99841c986e..9d86a62de4 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -98,7 +98,6 @@ class MatrixClientPeg { const opts = utils.deepCopy(this.opts); // the react sdk doesn't work without this, so don't allow opts.pendingEventOrdering = "detached"; - opts.disablePresence = true; // we do this manually try { const promise = this.matrixClient.store.startup(); diff --git a/src/Presence.js b/src/Presence.js index fd9bcf516d..9367fe35cd 100644 --- a/src/Presence.js +++ b/src/Presence.js @@ -57,27 +57,13 @@ class Presence { return this.state; } - /** - * Get the current status message. - * @returns {String} the status message, may be null - */ - getStatusMessage() { - return this.statusMessage; - } - /** * Set the presence state. * If the state has changed, the Home Server will be notified. * @param {string} newState the new presence state (see PRESENCE enum) - * @param {String} statusMessage an optional status message for the presence - * @param {boolean} maintain true to have this status maintained by this tracker */ - setState(newState, statusMessage=null, maintain=false) { - if (this.maintain) { - // Don't update presence if we're maintaining a particular status - return; - } - if (newState === this.state && statusMessage === this.statusMessage) { + setState(newState) { + if (newState === this.state) { return; } if (PRESENCE_STATES.indexOf(newState) === -1) { @@ -87,37 +73,21 @@ class Presence { return; } const old_state = this.state; - const old_message = this.statusMessage; this.state = newState; - this.statusMessage = statusMessage; - this.maintain = maintain; if (MatrixClientPeg.get().isGuest()) { return; // don't try to set presence when a guest; it won't work. } - const updateContent = { - presence: this.state, - status_msg: this.statusMessage ? this.statusMessage : '', - }; - const self = this; - MatrixClientPeg.get().setPresence(updateContent).done(function() { + MatrixClientPeg.get().setPresence(this.state).done(function() { console.log("Presence: %s", newState); - - // We have to dispatch because the js-sdk is unreliable at telling us about our own presence - dis.dispatch({action: "self_presence_updated", statusInfo: updateContent}); }, function(err) { console.error("Failed to set presence: %s", err); self.state = old_state; - self.statusMessage = old_message; }); } - stopMaintainingStatus() { - this.maintain = false; - } - /** * Callback called when the user made no action on the page for UNAVAILABLE_TIME ms. * @private diff --git a/src/components/views/avatars/MemberPresenceAvatar.js b/src/components/views/avatars/MemberPresenceAvatar.js deleted file mode 100644 index aa6def00ae..0000000000 --- a/src/components/views/avatars/MemberPresenceAvatar.js +++ /dev/null @@ -1,169 +0,0 @@ -/* - Copyright 2017 Travis Ralston - - 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. - */ - -'use strict'; - -import React from "react"; -import PropTypes from 'prop-types'; -import * as sdk from "../../../index"; -import MatrixClientPeg from "../../../MatrixClientPeg"; -import AccessibleButton from '../elements/AccessibleButton'; -import Presence from "../../../Presence"; -import dispatcher from "../../../dispatcher"; -import * as ContextualMenu from "../../structures/ContextualMenu"; -import SettingsStore from "../../../settings/SettingsStore"; - -// This is an avatar with presence information and controls on it. -module.exports = React.createClass({ - displayName: 'MemberPresenceAvatar', - - propTypes: { - member: PropTypes.object.isRequired, - width: PropTypes.number, - height: PropTypes.number, - resizeMethod: PropTypes.string, - }, - - getDefaultProps: function() { - return { - width: 40, - height: 40, - resizeMethod: 'crop', - }; - }, - - getInitialState: function() { - let presenceState = null; - let presenceMessage = null; - - // RoomMembers do not necessarily have a user. - if (this.props.member.user) { - presenceState = this.props.member.user.presence; - presenceMessage = this.props.member.user.presenceStatusMsg; - } - - return { - status: presenceState, - message: presenceMessage, - }; - }, - - componentWillMount: function() { - MatrixClientPeg.get().on("User.presence", this.onUserPresence); - this.dispatcherRef = dispatcher.register(this.onAction); - }, - - componentWillUnmount: function() { - if (MatrixClientPeg.get()) { - MatrixClientPeg.get().removeListener("User.presence", this.onUserPresence); - } - dispatcher.unregister(this.dispatcherRef); - }, - - onAction: function(payload) { - if (payload.action !== "self_presence_updated") return; - if (this.props.member.userId !== MatrixClientPeg.get().getUserId()) return; - this.setState({ - status: payload.statusInfo.presence, - message: payload.statusInfo.status_msg, - }); - }, - - onUserPresence: function(event, user) { - if (user.userId !== MatrixClientPeg.get().getUserId()) return; - this.setState({ - status: user.presence, - message: user.presenceStatusMsg, - }); - }, - - onStatusChange: function(newStatus) { - Presence.stopMaintainingStatus(); - if (newStatus === "online") { - Presence.setState(newStatus); - } else Presence.setState(newStatus, null, true); - }, - - onClick: function(e) { - const PresenceContextMenu = sdk.getComponent('context_menus.PresenceContextMenu'); - const elementRect = e.target.getBoundingClientRect(); - - // The window X and Y offsets are to adjust position when zoomed in to page - const x = (elementRect.left + window.pageXOffset) - (elementRect.width / 2) + 3; - const chevronOffset = 12; - let y = elementRect.top + (elementRect.height / 2) + window.pageYOffset; - y = y - (chevronOffset + 4); // where 4 is 1/4 the height of the chevron - - ContextualMenu.createMenu(PresenceContextMenu, { - chevronOffset: chevronOffset, - chevronFace: 'bottom', - left: x, - top: y, - menuWidth: 125, - currentStatus: this.state.status, - onChange: this.onStatusChange, - }); - - e.stopPropagation(); - - // XXX NB the following assumes that user is non-null, which is not valid - // const presenceState = this.props.member.user.presence; - // const presenceLastActiveAgo = this.props.member.user.lastActiveAgo; - // const presenceLastTs = this.props.member.user.lastPresenceTs; - // const presenceCurrentlyActive = this.props.member.user.currentlyActive; - // const presenceMessage = this.props.member.user.presenceStatusMsg; - }, - - render: function() { - const MemberAvatar = sdk.getComponent("avatars.MemberAvatar"); - - let onClickFn = null; - if (this.props.member.userId === MatrixClientPeg.get().getUserId()) { - onClickFn = this.onClick; - } - - const avatarNode = ( - - ); - let statusNode = ( - - ); - - // LABS: Disable presence management functions for now - // Also disable the presence information if there's no status information - if (!SettingsStore.isFeatureEnabled("feature_presence_management") || !this.state.status) { - statusNode = null; - onClickFn = null; - } - - let avatar = ( -
- { avatarNode } - { statusNode } -
- ); - if (onClickFn) { - avatar = ( - - { avatarNode } - { statusNode } - - ); - } - return avatar; - }, -}); diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index ff46f7423e..6b5da2553e 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -235,7 +235,7 @@ export default class MessageComposer extends React.Component { render() { const me = this.props.room.getMember(MatrixClientPeg.get().credentials.userId); const uploadInputStyle = {display: 'none'}; - const MemberPresenceAvatar = sdk.getComponent('avatars.MemberPresenceAvatar'); + const MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); const TintableSvg = sdk.getComponent("elements.TintableSvg"); const MessageComposerInput = sdk.getComponent("rooms.MessageComposerInput"); @@ -243,7 +243,7 @@ export default class MessageComposer extends React.Component { controls.push(
- +
, ); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5deefc546b..725ddbaa2f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -170,6 +170,7 @@ "%(widgetName)s widget modified by %(senderName)s": "%(widgetName)s widget modified by %(senderName)s", "%(widgetName)s widget added by %(senderName)s": "%(widgetName)s widget added by %(senderName)s", "%(widgetName)s widget removed by %(senderName)s": "%(widgetName)s widget removed by %(senderName)s", + "Message Pinning": "Message Pinning", "%(displayName)s is typing": "%(displayName)s is typing", "%(names)s and %(count)s others are typing|other": "%(names)s and %(count)s others are typing", "%(names)s and %(count)s others are typing|one": "%(names)s and one other is typing", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 7acaa8009f..8e94be3be1 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -88,12 +88,6 @@ export const SETTINGS = { supportedLevels: LEVELS_FEATURE, default: false, }, - "feature_presence_management": { - isFeature: true, - displayName: _td("Presence Management"), - supportedLevels: LEVELS_FEATURE, - default: false, - }, "feature_tag_panel": { isFeature: true, displayName: _td("Tag Panel"),