diff --git a/.eslintignore.errorfiles b/.eslintignore.errorfiles
index 2b57d4e9e2..30cc55377c 100644
--- a/.eslintignore.errorfiles
+++ b/.eslintignore.errorfiles
@@ -48,7 +48,6 @@ src/components/views/rooms/LinkPreviewWidget.js
src/components/views/rooms/MemberDeviceInfo.js
src/components/views/rooms/MemberInfo.js
src/components/views/rooms/MemberList.js
-src/components/views/rooms/MemberTile.js
src/components/views/rooms/MessageComposer.js
src/components/views/rooms/PinnedEventTile.js
src/components/views/rooms/RoomList.js
diff --git a/res/css/structures/_ContextualMenu.scss b/res/css/structures/_ContextualMenu.scss
index fa69c6fb90..a01cd896a8 100644
--- a/res/css/structures/_ContextualMenu.scss
+++ b/res/css/structures/_ContextualMenu.scss
@@ -30,8 +30,8 @@ limitations under the License.
}
.mx_ContextualMenu {
- border-radius: 2px;
- box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.21);
+ border-radius: 4px;
+ box-shadow: 4px 4px 12px 0 rgba(118, 131, 156, 0.6);;
background-color: $menu-bg-color;
color: $primary-fg-color;
position: absolute;
diff --git a/res/css/views/avatars/_MemberStatusMessageAvatar.scss b/res/css/views/avatars/_MemberStatusMessageAvatar.scss
index 29cae9df34..c101a5d8a8 100644
--- a/res/css/views/avatars/_MemberStatusMessageAvatar.scss
+++ b/res/css/views/avatars/_MemberStatusMessageAvatar.scss
@@ -14,8 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-.mx_MemberStatusMessageAvatar_hasStatus {
- border: 2px solid $accent-color;
- border-radius: 40px;
- padding-right: 0 !important; /* Override AccessibleButton styling */
+.mx_MessageComposer_avatar .mx_BaseAvatar {
+ padding: 2px;
+ border: 1px solid transparent;
+ border-radius: 15px;
+}
+
+.mx_MessageComposer_avatar .mx_BaseAvatar_initial {
+ left: 2px;
+}
+
+.mx_MemberStatusMessageAvatar_hasStatus .mx_BaseAvatar {
+ border-color: $accent-color;
}
diff --git a/res/css/views/context_menus/_StatusMessageContextMenu.scss b/res/css/views/context_menus/_StatusMessageContextMenu.scss
index 873ad99495..8b25f3a122 100644
--- a/res/css/views/context_menus/_StatusMessageContextMenu.scss
+++ b/res/css/views/context_menus/_StatusMessageContextMenu.scss
@@ -14,42 +14,43 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-.mx_StatusMessageContextMenu_message {
- display: inline-block;
- border-radius: 3px 0 0 3px;
+.mx_StatusMessageContextMenu {
+ padding: 10px;
+}
+
+.mx_StatusMessageContextMenu_form {
+ display: flex;
+ flex-direction: column;
+}
+
+input.mx_StatusMessageContextMenu_message {
+ border-radius: 4px;
border: 1px solid $input-border-color;
- font-size: 13px;
- padding: 7px 7px 7px 9px;
- width: 135px;
- background-color: $primary-bg-color !important;
+ padding: 6.5px 11px;
+ background-color: $primary-bg-color;
+ font-weight: normal;
+ margin: 0 0 10px;
}
-.mx_StatusMessageContextMenu_submit {
- display: inline-block;
+.mx_StatusMessageContextMenu_message::placeholder {
+ color: $memberstatus-placeholder-color;
}
-.mx_StatusMessageContextMenu_submitFaded {
- opacity: 0.5;
+.mx_StatusMessageContextMenu_submit,
+.mx_StatusMessageContextMenu_clear {
+ @mixin mx_DialogButton;
+ align-self: start;
+ font-size: 12px;
+ padding: 6px 1em;
+ border: 1px solid transparent;
}
-.mx_StatusMessageContextMenu_submit img {
- vertical-align: middle;
- margin-left: 8px;
-}
-
-.mx_StatusMessageContextMenu hr {
- border: 0.5px solid $menu-border-color;
-}
-
-.mx_StatusMessageContextMenu_clearIcon {
- margin: 5px 15px 5px 5px;
- vertical-align: middle;
+.mx_StatusMessageContextMenu_submit[disabled] {
+ opacity: 0.49;
}
.mx_StatusMessageContextMenu_clear {
- padding: 2px;
-}
-
-.mx_StatusMessageContextMenu_hasStatus .mx_StatusMessageContextMenu_clear {
color: $warning-color;
+ background-color: transparent;
+ border: 1px solid $warning-color;
}
diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss
index 39640575ba..4a052482ad 100644
--- a/res/css/views/rooms/_MessageComposer.scss
+++ b/res/css/views/rooms/_MessageComposer.scss
@@ -58,17 +58,13 @@ limitations under the License.
}
.mx_MessageComposer .mx_MessageComposer_avatar {
- padding: 0 28px;
+ padding: 0 27px;
}
.mx_MessageComposer .mx_MessageComposer_avatar .mx_BaseAvatar {
display: block;
}
-.mx_MessageComposer .mx_AccessibleButton {
- padding: 0 12px 0 0;
-}
-
.mx_MessageComposer_composecontrols {
width: 100%;
}
@@ -185,7 +181,7 @@ limitations under the License.
/*display: table-cell;*/
/*vertical-align: middle;*/
/*padding-left: 10px;*/
- padding-right: 5px;
+ padding-right: 12px;
cursor: pointer;
padding-top: 4px;
}
diff --git a/res/img/icons-checkmark.svg b/res/img/icons-checkmark.svg
deleted file mode 100644
index 3c5392003d..0000000000
--- a/res/img/icons-checkmark.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
diff --git a/res/themes/dharma/css/_dharma.scss b/res/themes/dharma/css/_dharma.scss
index 732cabf494..73dc0a71e4 100644
--- a/res/themes/dharma/css/_dharma.scss
+++ b/res/themes/dharma/css/_dharma.scss
@@ -68,7 +68,7 @@ $event-selected-color: #f7f7f7;
$primary-hairline-color: #e5e5e5;
// used for the border of input text fields
-$input-border-color: #f0f0f0;
+$input-border-color: #e7e7e7;
$input-darker-bg-color: rgba(193, 201, 214, 0.29);
$input-darker-fg-color: #9fa9ba;
$input-lighter-bg-color: #f2f5f8;
@@ -192,6 +192,8 @@ $progressbar-color: #000;
$room-warning-bg-color: #fff8e3;
+$memberstatus-placeholder-color: $roomtile-name-color;
+
/*** form elements ***/
// .mx_textinput is a container for a text input
diff --git a/res/themes/light/css/_base.scss b/res/themes/light/css/_base.scss
index 10a8fcd1e5..cf539bd1f2 100644
--- a/res/themes/light/css/_base.scss
+++ b/res/themes/light/css/_base.scss
@@ -188,6 +188,8 @@ $progressbar-color: #000;
$room-warning-bg-color: #fff8e3;
+$memberstatus-placeholder-color: $roomtile-name-color;
+
// ***** Mixins! *****
@define-mixin mx_DialogButton {
diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js
index 4c7d004015..762185146c 100644
--- a/src/components/structures/RoomDirectory.js
+++ b/src/components/structures/RoomDirectory.js
@@ -34,6 +34,9 @@ import { _t } from '../../languageHandler';
import {instanceForInstanceId, protocolNameForInstanceId} from '../../utils/DirectoryUtils';
+const MAX_NAME_LENGTH = 80;
+const MAX_TOPIC_LENGTH = 160;
+
linkifyMatrix(linkify);
module.exports = React.createClass({
@@ -390,7 +393,6 @@ module.exports = React.createClass({
const self = this;
let guestRead; let guestJoin; let perms;
for (let i = 0; i < rooms.length; i++) {
- const name = rooms[i].name || get_display_alias_for_room(rooms[i]) || _t('Unnamed room');
guestRead = null;
guestJoin = null;
@@ -410,7 +412,15 @@ module.exports = React.createClass({
perms =
{guestRead}{guestJoin}
;
}
+ let name = rooms[i].name || get_display_alias_for_room(rooms[i]) || _t('Unnamed room');
+ if (name.length > MAX_NAME_LENGTH) {
+ name = `${name.substring(0, MAX_NAME_LENGTH)}...`;
+ }
+
let topic = rooms[i].topic || '';
+ if (topic.length > MAX_TOPIC_LENGTH) {
+ topic = `${topic.substring(0, MAX_TOPIC_LENGTH)}...`;
+ }
topic = linkifyString(sanitizeHtml(topic));
rows.push(
diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js
index 15b9181d21..56b23c63f2 100644
--- a/src/components/structures/UserSettings.js
+++ b/src/components/structures/UserSettings.js
@@ -82,11 +82,10 @@ const SIMPLE_SETTINGS = [
{ id: "VideoView.flipVideoHorizontally" },
{ id: "TagPanel.disableTagPanel" },
{ id: "enableWidgetScreenshots" },
- { id: "RoomSubList.showEmpty" },
{ id: "pinMentionedRooms" },
{ id: "pinUnreadRooms" },
{ id: "showDeveloperTools" },
- { id: "alwaysRetryInvites" },
+ { id: "alwaysInviteUnknownUsers" },
];
// These settings must be defined in SettingsStore
diff --git a/src/components/views/avatars/MemberStatusMessageAvatar.js b/src/components/views/avatars/MemberStatusMessageAvatar.js
index aebd1741b7..0258c4b0c8 100644
--- a/src/components/views/avatars/MemberStatusMessageAvatar.js
+++ b/src/components/views/avatars/MemberStatusMessageAvatar.js
@@ -40,38 +40,50 @@ export default class MemberStatusMessageAvatar extends React.Component {
constructor(props, context) {
super(props, context);
+
+ this.state = {
+ hasStatus: this.hasStatus,
+ };
}
componentWillMount() {
if (this.props.member.userId !== MatrixClientPeg.get().getUserId()) {
throw new Error("Cannot use MemberStatusMessageAvatar on anyone but the logged in user");
}
- }
-
- componentDidMount() {
- MatrixClientPeg.get().on("RoomState.events", this._onRoomStateEvents);
-
- if (this.props.member.user) {
- this.setState({message: this.props.member.user._unstable_statusMessage});
- } else {
- this.setState({message: ""});
+ if (!SettingsStore.isFeatureEnabled("feature_custom_status")) {
+ return;
}
- }
-
- componentWillUnmount() {
- if (MatrixClientPeg.get()) {
- MatrixClientPeg.get().removeListener("RoomState.events", this._onRoomStateEvents);
+ const { user } = this.props.member;
+ if (!user) {
+ return;
}
+ user.on("User._unstable_statusMessage", this._onStatusMessageCommitted);
}
- _onRoomStateEvents = (ev, state) => {
- if (ev.getStateKey() !== MatrixClientPeg.get().getUserId()) return;
- if (ev.getType() !== "im.vector.user_status") return;
- // TODO: We should be relying on `this.props.member.user._unstable_statusMessage`
- // We don't currently because the js-sdk doesn't emit a specific event for this
- // change, and we don't want to race it. This should be improved when we rip out
- // the im.vector.user_status stuff and replace it with a complete solution.
- this.setState({message: ev.getContent()["status"]});
+ componentWillUmount() {
+ const { user } = this.props.member;
+ if (!user) {
+ return;
+ }
+ user.removeListener(
+ "User._unstable_statusMessage",
+ this._onStatusMessageCommitted,
+ );
+ }
+
+ get hasStatus() {
+ const { user } = this.props.member;
+ if (!user) {
+ return false;
+ }
+ return !!user._unstable_statusMessage;
+ }
+
+ _onStatusMessageCommitted = () => {
+ // The `User` object has observed a status message change.
+ this.setState({
+ hasStatus: this.hasStatus,
+ });
};
_onClick = (e) => {
@@ -79,42 +91,43 @@ export default class MemberStatusMessageAvatar extends React.Component {
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
+ const x = (elementRect.left + window.pageXOffset);
+ const chevronWidth = 16; // See .mx_ContextualMenu_chevron_bottom
+ const chevronOffset = (elementRect.width - chevronWidth) / 2;
+ const chevronMargin = 1; // Add some spacing away from target
+ const y = elementRect.top + window.pageYOffset - chevronMargin;
ContextualMenu.createMenu(StatusMessageContextMenu, {
chevronOffset: chevronOffset,
chevronFace: 'bottom',
left: x,
top: y,
- menuWidth: 190,
+ menuWidth: 226,
user: this.props.member.user,
});
};
render() {
- if (!SettingsStore.isFeatureEnabled("feature_custom_status")) {
- return ;
- }
+ const avatar = ;
- const hasStatus = this.props.member.user ? !!this.props.member.user._unstable_statusMessage : false;
+ if (!SettingsStore.isFeatureEnabled("feature_custom_status")) {
+ return avatar;
+ }
const classes = classNames({
"mx_MemberStatusMessageAvatar": true,
- "mx_MemberStatusMessageAvatar_hasStatus": hasStatus,
+ "mx_MemberStatusMessageAvatar_hasStatus": this.state.hasStatus,
});
- return
-
+ return
+ {avatar}
;
}
}
diff --git a/src/components/views/context_menus/StatusMessageContextMenu.js b/src/components/views/context_menus/StatusMessageContextMenu.js
index d062fc2a3e..9916f5d347 100644
--- a/src/components/views/context_menus/StatusMessageContextMenu.js
+++ b/src/components/views/context_menus/StatusMessageContextMenu.js
@@ -19,7 +19,6 @@ import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
import MatrixClientPeg from '../../../MatrixClientPeg';
import AccessibleButton from '../elements/AccessibleButton';
-import classNames from 'classnames';
export default class StatusMessageContextMenu extends React.Component {
static propTypes = {
@@ -31,13 +30,42 @@ export default class StatusMessageContextMenu extends React.Component {
super(props, context);
this.state = {
- message: props.user ? props.user._unstable_statusMessage : "",
+ message: this.comittedStatusMessage,
};
}
+ componentWillMount() {
+ const { user } = this.props;
+ if (!user) {
+ return;
+ }
+ user.on("User._unstable_statusMessage", this._onStatusMessageCommitted);
+ }
+
+ componentWillUmount() {
+ const { user } = this.props;
+ if (!user) {
+ return;
+ }
+ user.removeListener(
+ "User._unstable_statusMessage",
+ this._onStatusMessageCommitted,
+ );
+ }
+
+ get comittedStatusMessage() {
+ return this.props.user ? this.props.user._unstable_statusMessage : "";
+ }
+
+ _onStatusMessageCommitted = () => {
+ // The `User` object has observed a status message change.
+ this.setState({
+ message: this.comittedStatusMessage,
+ });
+ };
+
_onClearClick = async (e) => {
await MatrixClientPeg.get()._unstable_setStatusMessage("");
- this.setState({message: ""});
};
_onSubmit = (e) => {
@@ -46,41 +74,49 @@ export default class StatusMessageContextMenu extends React.Component {
};
_onStatusChange = (e) => {
- this.setState({message: e.target.value});
+ // The input field's value was changed.
+ this.setState({
+ message: e.target.value,
+ });
};
render() {
- const formSubmitClasses = classNames({
- "mx_StatusMessageContextMenu_submit": true,
- "mx_StatusMessageContextMenu_submitFaded": !this.state.message, // no message == faded
- });
+ let actionButton;
+ if (this.comittedStatusMessage) {
+ if (this.state.message === this.comittedStatusMessage) {
+ actionButton =
+ {_t("Clear status")}
+ ;
+ } else {
+ actionButton =
+ {_t("Update status")}
+ ;
+ }
+ } else {
+ actionButton =
+ {_t("Set status")}
+ ;
+ }
- const form = ;
- const clearIcon = this.state.message ? "img/cancel-red.svg" : "img/cancel.svg";
- const clearButton =
-
- {_t("Clear status")}
- ;
-
- const menuClasses = classNames({
- "mx_StatusMessageContextMenu": true,
- "mx_StatusMessageContextMenu_hasStatus": this.state.message,
- });
-
- return
+ return
{ form }
-
- { clearButton }
;
}
}
diff --git a/src/components/views/dialogs/ChangelogDialog.js b/src/components/views/dialogs/ChangelogDialog.js
index 3c9414fd88..965029c069 100644
--- a/src/components/views/dialogs/ChangelogDialog.js
+++ b/src/components/views/dialogs/ChangelogDialog.js
@@ -36,7 +36,7 @@ export default class ChangelogDialog extends React.Component {
for (let i=0; i
{
if (response.statusCode < 200 || response.statusCode >= 300) {
this.setState({ [REPOS[i]]: response.statusText });
diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.js
index ba951792d0..926734a767 100644
--- a/src/components/views/rooms/MemberTile.js
+++ b/src/components/views/rooms/MemberTile.js
@@ -21,10 +21,8 @@ import SettingsStore from "../../../settings/SettingsStore";
const React = require('react');
import PropTypes from 'prop-types';
-const MatrixClientPeg = require('../../../MatrixClientPeg');
const sdk = require('../../../index');
const dis = require('../../../dispatcher');
-const Modal = require("../../../Modal");
import { _t } from '../../../languageHandler';
module.exports = React.createClass({
@@ -42,7 +40,46 @@ module.exports = React.createClass({
},
getInitialState: function() {
- return {};
+ return {
+ statusMessage: this.getStatusMessage(),
+ };
+ },
+
+ componentDidMount() {
+ if (!SettingsStore.isFeatureEnabled("feature_custom_status")) {
+ return;
+ }
+ const { user } = this.props.member;
+ if (!user) {
+ return;
+ }
+ user.on("User._unstable_statusMessage", this._onStatusMessageCommitted);
+ },
+
+ componentWillUmount() {
+ const { user } = this.props.member;
+ if (!user) {
+ return;
+ }
+ user.removeListener(
+ "User._unstable_statusMessage",
+ this._onStatusMessageCommitted,
+ );
+ },
+
+ getStatusMessage() {
+ const { user } = this.props.member;
+ if (!user) {
+ return "";
+ }
+ return user._unstable_statusMessage;
+ },
+
+ _onStatusMessageCommitted() {
+ // The `User` object has observed a status message change.
+ this.setState({
+ statusMessage: this.getStatusMessage(),
+ });
},
shouldComponentUpdate: function(nextProps, nextState) {
@@ -74,22 +111,23 @@ module.exports = React.createClass({
},
getPowerLabel: function() {
- return _t("%(userName)s (power %(powerLevelNumber)s)", {userName: this.props.member.userId, powerLevelNumber: this.props.member.powerLevel});
+ return _t("%(userName)s (power %(powerLevelNumber)s)", {
+ userName: this.props.member.userId,
+ powerLevelNumber: this.props.member.powerLevel,
+ });
},
render: function() {
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
- const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
const EntityTile = sdk.getComponent('rooms.EntityTile');
const member = this.props.member;
const name = this._getDisplayName();
- const active = -1;
const presenceState = member.user ? member.user.presence : null;
let statusMessage = null;
if (member.user && SettingsStore.isFeatureEnabled("feature_custom_status")) {
- statusMessage = member.user._unstable_statusMessage;
+ statusMessage = this.state.statusMessage;
}
const av = (
diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js
index 95073b7be8..1f9c0c1523 100644
--- a/src/components/views/rooms/RoomTile.js
+++ b/src/components/views/rooms/RoomTile.js
@@ -62,6 +62,7 @@ module.exports = React.createClass({
notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
notificationCount: this.props.room.getUnreadNotificationCount(),
selected: this.props.room.roomId === ActiveRoomObserver.getActiveRoomId(),
+ statusMessage: this._getStatusMessage(),
});
},
@@ -79,6 +80,33 @@ module.exports = React.createClass({
return Boolean(dmRooms);
},
+ _shouldShowStatusMessage() {
+ if (!SettingsStore.isFeatureEnabled("feature_custom_status")) {
+ return false;
+ }
+ const isInvite = this.props.room.getMyMembership() === "invite";
+ const isJoined = this.props.room.getMyMembership() === "join";
+ const looksLikeDm = this.props.room.getInvitedAndJoinedMemberCount() === 2;
+ return !isInvite && isJoined && looksLikeDm;
+ },
+
+ _getStatusMessageUser() {
+ const selfId = MatrixClientPeg.get().getUserId();
+ const otherMember = this.props.room.currentState.getMembersExcept([selfId])[0];
+ if (!otherMember) {
+ return null;
+ }
+ return otherMember.user;
+ },
+
+ _getStatusMessage() {
+ const statusUser = this._getStatusMessageUser();
+ if (!statusUser) {
+ return "";
+ }
+ return statusUser._unstable_statusMessage;
+ },
+
onRoomTimeline: function(ev, room) {
if (room !== this.props.room) return;
this.setState({
@@ -112,7 +140,13 @@ module.exports = React.createClass({
this.setState({
notificationCount: this.props.room.getUnreadNotificationCount(),
});
- break;
+ break;
+ // RoomTiles are one of the few components that may show custom status and
+ // also remain on screen while in Settings toggling the feature. This ensures
+ // you can clearly see the status hide and show when toggling the feature.
+ case 'feature_custom_status_changed':
+ this.forceUpdate();
+ break;
}
},
@@ -128,6 +162,16 @@ module.exports = React.createClass({
MatrixClientPeg.get().on("Room.name", this.onRoomName);
ActiveRoomObserver.addListener(this.props.room.roomId, this._onActiveRoomChange);
this.dispatcherRef = dis.register(this.onAction);
+
+ if (this._shouldShowStatusMessage()) {
+ const statusUser = this._getStatusMessageUser();
+ if (statusUser) {
+ statusUser.on(
+ "User._unstable_statusMessage",
+ this._onStatusMessageCommitted,
+ );
+ }
+ }
},
componentWillUnmount: function() {
@@ -139,6 +183,16 @@ module.exports = React.createClass({
}
ActiveRoomObserver.removeListener(this.props.room.roomId, this._onActiveRoomChange);
dis.unregister(this.dispatcherRef);
+
+ if (this._shouldShowStatusMessage()) {
+ const statusUser = this._getStatusMessageUser();
+ if (statusUser) {
+ statusUser.removeListener(
+ "User._unstable_statusMessage",
+ this._onStatusMessageCommitted,
+ );
+ }
+ }
},
componentWillReceiveProps: function(props) {
@@ -166,6 +220,13 @@ module.exports = React.createClass({
return false;
},
+ _onStatusMessageCommitted() {
+ // The status message `User` object has observed a message change.
+ this.setState({
+ statusMessage: this._getStatusMessage(),
+ });
+ },
+
onClick: function(ev) {
if (this.props.onClick) {
this.props.onClick(this.props.room.roomId, ev);
@@ -251,15 +312,9 @@ module.exports = React.createClass({
const mentionBadges = this.props.highlight && this._shouldShowMentionBadge();
const badges = notifBadges || mentionBadges;
- const isJoined = this.props.room.getMyMembership() === "join";
- const looksLikeDm = this.props.room.getInvitedAndJoinedMemberCount() === 2;
let subtext = null;
- if (!isInvite && isJoined && looksLikeDm && SettingsStore.isFeatureEnabled("feature_custom_status")) {
- const selfId = MatrixClientPeg.get().getUserId();
- const otherMember = this.props.room.currentState.getMembersExcept([selfId])[0];
- if (otherMember && otherMember.user && otherMember.user._unstable_statusMessage) {
- subtext = otherMember.user._unstable_statusMessage;
- }
+ if (this._shouldShowStatusMessage()) {
+ subtext = this.state.statusMessage;
}
const classes = classNames({
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 0086ed0378..ef0ff1ebf7 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -296,7 +296,6 @@
"Pin rooms I'm mentioned in to the top of the room list": "Pin rooms I'm mentioned in to the top of the room list",
"Pin unread rooms to the top of the room list": "Pin unread rooms to the top of the room list",
"Enable widget screenshots on supported widgets": "Enable widget screenshots on supported widgets",
- "Show empty room list headings": "Show empty room list headings",
"Always invite users which may not exist": "Always invite users which may not exist",
"Show developer tools": "Show developer tools",
"Collecting app version information": "Collecting app version information",
@@ -1088,8 +1087,10 @@
"Forget": "Forget",
"Low Priority": "Low Priority",
"Direct Chat": "Direct Chat",
- "Set a new status...": "Set a new status...",
"Clear status": "Clear status",
+ "Update status": "Update status",
+ "Set status": "Set status",
+ "Set a new status...": "Set a new status...",
"View as Grid": "View as Grid",
"View Community": "View Community",
"Sorry, your browser is not able to run Riot.": "Sorry, your browser is not able to run Riot.",
diff --git a/src/settings/Settings.js b/src/settings/Settings.js
index a04301e31e..836e906b6e 100644
--- a/src/settings/Settings.js
+++ b/src/settings/Settings.js
@@ -22,6 +22,7 @@ import {
NotificationsEnabledController,
} from "./controllers/NotificationControllers";
import LazyLoadingController from "./controllers/LazyLoadingController";
+import CustomStatusController from "./controllers/CustomStatusController";
// These are just a bunch of helper arrays to avoid copy/pasting a bunch of times
const LEVELS_ROOM_SETTINGS = ['device', 'room-device', 'room-account', 'account', 'config'];
@@ -88,6 +89,7 @@ export const SETTINGS = {
displayName: _td("Custom user status messages"),
supportedLevels: LEVELS_FEATURE,
default: false,
+ controller: new CustomStatusController(),
},
"feature_lazyloading": {
isFeature: true,
@@ -324,11 +326,6 @@ export const SETTINGS = {
supportedLevels: ['room-device'],
default: false,
},
- "RoomSubList.showEmpty": {
- supportedLevels: LEVELS_ACCOUNT_SETTINGS,
- displayName: _td('Show empty room list headings'),
- default: true,
- },
"alwaysInviteUnknownUsers": {
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
displayName: _td('Always invite users which may not exist'),
diff --git a/src/settings/controllers/CustomStatusController.js b/src/settings/controllers/CustomStatusController.js
new file mode 100644
index 0000000000..0fc6619d92
--- /dev/null
+++ b/src/settings/controllers/CustomStatusController.js
@@ -0,0 +1,28 @@
+/*
+Copyright 2019 New Vector Ltd
+
+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 SettingController from "./SettingController";
+import dis from "../../dispatcher";
+
+export default class CustomStatusController extends SettingController {
+ onChange(level, roomId, newValue) {
+ // Dispatch setting change so that some components that are still visible when the
+ // Settings page is open (such as RoomTiles) can reflect the change.
+ dis.dispatch({
+ action: "feature_custom_status_changed",
+ });
+ }
+}