diff --git a/src/Analytics.js b/src/Analytics.js
index 1bff3bdf7c..3e208ad6bd 100644
--- a/src/Analytics.js
+++ b/src/Analytics.js
@@ -84,6 +84,11 @@ const customVariables = {
expl: _td('Whether or not you\'re using the Richtext mode of the Rich Text Editor'),
example: 'off',
},
+ 'Breadcrumbs': {
+ id: 9,
+ expl: _td("Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)"),
+ example: 'disabled',
+ },
'Homeserver URL': {
id: 7,
expl: _td('Your homeserver\'s URL'),
@@ -234,6 +239,11 @@ class Analytics {
this._setVisitVariable('RTE: Uses Richtext Mode', state ? 'on' : 'off');
}
+ setBreadcrumbs(state) {
+ if (this.disabled) return;
+ this._setVisitVariable('Breadcrumbs', state ? 'enabled' : 'disabled');
+ }
+
showDetailsModal() {
let rows = [];
if (window.Piwik) {
diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js
index 95b57a0ca5..21c41125a4 100644
--- a/src/components/structures/LeftPanel.js
+++ b/src/components/structures/LeftPanel.js
@@ -27,6 +27,7 @@ import VectorConferenceHandler from '../../VectorConferenceHandler';
import TagPanelButtons from './TagPanelButtons';
import SettingsStore from '../../settings/SettingsStore';
import {_t} from "../../languageHandler";
+import Analytics from "../../Analytics";
const LeftPanel = React.createClass({
@@ -45,11 +46,23 @@ const LeftPanel = React.createClass({
getInitialState: function() {
return {
searchFilter: '',
+ breadcrumbs: false,
};
},
componentWillMount: function() {
this.focusedElement = null;
+
+ this._settingWatchRef = SettingsStore.watchSetting(
+ "feature_room_breadcrumbs", null, this._onBreadcrumbsChanged);
+
+ const useBreadcrumbs = SettingsStore.isFeatureEnabled("feature_room_breadcrumbs");
+ Analytics.setBreadcrumbs(useBreadcrumbs);
+ this.setState({breadcrumbs: useBreadcrumbs});
+ },
+
+ componentWillUnmount: function() {
+ SettingsStore.unwatchSetting(this._settingWatchRef);
},
shouldComponentUpdate: function(nextProps, nextState) {
@@ -73,6 +86,22 @@ const LeftPanel = React.createClass({
return false;
},
+ componentDidUpdate(prevProps, prevState) {
+ if (prevState.breadcrumbs !== this.state.breadcrumbs) {
+ Analytics.setBreadcrumbs(this.state.breadcrumbs);
+ }
+ },
+
+ _onBreadcrumbsChanged: function(settingName, roomId, level, valueAtLevel, value) {
+ // Features are only possible at a single level, so we can get away with using valueAtLevel.
+ // The SettingsStore runs on the same tick as the update, so `value` will be wrong.
+ this.setState({breadcrumbs: valueAtLevel});
+
+ // For some reason the setState doesn't trigger a render of the component, so force one.
+ // Probably has to do with the change happening outside of a change detector cycle.
+ this.forceUpdate();
+ },
+
_onFocus: function(ev) {
this.focusedElement = ev.target;
},
@@ -220,7 +249,7 @@ const LeftPanel = React.createClass({
collapsed={this.props.collapsed} />);
let breadcrumbs;
- if (SettingsStore.isFeatureEnabled("feature_room_breadcrumbs")) {
+ if (this.state.breadcrumbs) {
breadcrumbs = ();
}
diff --git a/src/components/views/rooms/RoomBreadcrumbs.js b/src/components/views/rooms/RoomBreadcrumbs.js
index 0a50c8d1f8..51677bf471 100644
--- a/src/components/views/rooms/RoomBreadcrumbs.js
+++ b/src/components/views/rooms/RoomBreadcrumbs.js
@@ -22,6 +22,7 @@ import AccessibleButton from '../elements/AccessibleButton';
import RoomAvatar from '../avatars/RoomAvatar';
import classNames from 'classnames';
import sdk from "../../../index";
+import Analytics from "../../../Analytics";
import * as RoomNotifs from '../../../RoomNotifs';
import * as FormattingUtils from "../../../utils/FormattingUtils";
import DMRoomMap from "../../../utils/DMRoomMap";
@@ -247,7 +248,8 @@ export default class RoomBreadcrumbs extends React.Component {
}
}
- _viewRoom(room) {
+ _viewRoom(room, index) {
+ Analytics.trackEvent("Breadcrumbs", "click_node", index);
dis.dispatch({action: "view_room", room_id: room.roomId});
}
@@ -321,7 +323,7 @@ export default class RoomBreadcrumbs extends React.Component {
}
return (
- this._viewRoom(r.room)}
+ this._viewRoom(r.room, i)}
onMouseEnter={() => this._onMouseEnter(r.room)} onMouseLeave={() => this._onMouseLeave(r.room)}>
{badge}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 7e6529e6f3..477ac1df29 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -8,6 +8,7 @@
"Your language of choice": "Your language of choice",
"Which officially provided instance you are using, if any": "Which officially provided instance you are using, if any",
"Whether or not you're using the Richtext mode of the Rich Text Editor": "Whether or not you're using the Richtext mode of the Rich Text Editor",
+ "Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)": "Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)",
"Your homeserver's URL": "Your homeserver's URL",
"Your identity server's URL": "Your identity server's URL",
"e.g. %(exampleValue)s": "e.g. %(exampleValue)s",
@@ -291,7 +292,7 @@
"Failed to join room": "Failed to join room",
"Message Pinning": "Message Pinning",
"Custom user status messages": "Custom user status messages",
- "Show recent room avatars above the room list (refresh to apply changes)": "Show recent room avatars above the room list (refresh to apply changes)",
+ "Show recent room avatars above the room list": "Show recent room avatars above the room list",
"Group & filter rooms by custom tags (refresh to apply changes)": "Group & filter rooms by custom tags (refresh to apply changes)",
"Render simple counters in room header": "Render simple counters in room header",
"Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing",
@@ -729,8 +730,8 @@
"Send a reply (unencrypted)…": "Send a reply (unencrypted)…",
"Send an encrypted message…": "Send an encrypted message…",
"Send a message (unencrypted)…": "Send a message (unencrypted)…",
- "This room has been replaced and is no longer active.": "This room has been replaced and is no longer active.",
"The conversation continues here.": "The conversation continues here.",
+ "This room has been replaced and is no longer active.": "This room has been replaced and is no longer active.",
"You do not have permission to post to this room": "You do not have permission to post to this room",
"Markdown is disabled": "Markdown is disabled",
"Hide Text Formatting Toolbar": "Hide Text Formatting Toolbar",
diff --git a/src/settings/Settings.js b/src/settings/Settings.js
index 098ef2c17b..35baa718b9 100644
--- a/src/settings/Settings.js
+++ b/src/settings/Settings.js
@@ -102,7 +102,7 @@ export const SETTINGS = {
},
"feature_room_breadcrumbs": {
isFeature: true,
- displayName: _td("Show recent room avatars above the room list (refresh to apply changes)"),
+ displayName: _td("Show recent room avatars above the room list"),
supportedLevels: LEVELS_FEATURE,
default: false,
},
diff --git a/src/settings/handlers/DeviceSettingsHandler.js b/src/settings/handlers/DeviceSettingsHandler.js
index bca7679a47..b5c4382768 100644
--- a/src/settings/handlers/DeviceSettingsHandler.js
+++ b/src/settings/handlers/DeviceSettingsHandler.js
@@ -127,6 +127,6 @@ export default class DeviceSettingsHandler extends SettingsHandler {
_writeFeature(featureName, enabled) {
localStorage.setItem("mx_labs_feature_" + featureName, enabled);
- this._watchers.notifyUpdate(featureName, null, enabled);
+ this._watchers.notifyUpdate(featureName, null, SettingLevel.DEVICE, enabled);
}
}