From bf815f4be961ba09a80fde1cac1e72a6735918b8 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 28 Oct 2017 20:21:34 -0600 Subject: [PATCH] Support labs features Signed-off-by: Travis Ralston --- src/UserSettingsStore.js | 76 ---------------------- src/components/structures/UserSettings.js | 10 +-- src/components/views/elements/Flair.js | 4 +- src/components/views/rooms/RoomHeader.js | 4 +- src/components/views/rooms/RoomSettings.js | 3 +- src/settings/DeviceSettingsHandler.js | 3 +- src/settings/SettingsStore.js | 74 +++++++++++++++------ 7 files changed, 68 insertions(+), 106 deletions(-) diff --git a/src/UserSettingsStore.js b/src/UserSettingsStore.js index ce39939bc0..2d2045d15b 100644 --- a/src/UserSettingsStore.js +++ b/src/UserSettingsStore.js @@ -25,50 +25,7 @@ import SdkConfig from './SdkConfig'; * TODO: Make things use this. This is all WIP - see UserSettings.js for usage. */ -const FEATURES = [ - { - id: 'feature_groups', - name: _td("Communities"), - }, - { - id: 'feature_pinning', - name: _td("Message Pinning"), - }, -]; - export default { - getLabsFeatures() { - const featuresConfig = SdkConfig.get()['features'] || {}; - - // The old flag: honoured for backwards compatibility - const enableLabs = SdkConfig.get()['enableLabs']; - - let labsFeatures; - if (enableLabs) { - labsFeatures = FEATURES; - } else { - labsFeatures = FEATURES.filter((f) => { - const sdkConfigValue = featuresConfig[f.id]; - if (sdkConfigValue === 'labs') { - return true; - } - }); - } - return labsFeatures.map((f) => { - return f.id; - }); - }, - - translatedNameForFeature(featureId) { - const feature = FEATURES.filter((f) => { - return f.id === featureId; - })[0]; - - if (feature === undefined) return null; - - return _t(feature.name); - }, - loadProfileInfo: function() { const cli = MatrixClientPeg.get(); return cli.getProfileInfo(cli.credentials.userId); @@ -213,37 +170,4 @@ export default { // FIXME: handle errors localStorage.setItem('mx_local_settings', JSON.stringify(settings)); }, - - isFeatureEnabled: function(featureId: string): boolean { - const featuresConfig = SdkConfig.get()['features']; - - // The old flag: honoured for backwards compatibility - const enableLabs = SdkConfig.get()['enableLabs']; - - let sdkConfigValue = enableLabs ? 'labs' : 'disable'; - if (featuresConfig && featuresConfig[featureId] !== undefined) { - sdkConfigValue = featuresConfig[featureId]; - } - - if (sdkConfigValue === 'enable') { - return true; - } else if (sdkConfigValue === 'disable') { - return false; - } else if (sdkConfigValue === 'labs') { - if (!MatrixClientPeg.get().isGuest()) { - // Make it explicit that guests get the defaults (although they shouldn't - // have been able to ever toggle the flags anyway) - const userValue = localStorage.getItem(`mx_labs_feature_${featureId}`); - return userValue === 'true'; - } - return false; - } else { - console.warn(`Unknown features config for ${featureId}: ${sdkConfigValue}`); - return false; - } - }, - - setFeatureEnabled: function(featureId: string, enabled: boolean) { - localStorage.setItem(`mx_labs_feature_${featureId}`, enabled); - }, }; diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 68ea932f93..9c28f7a869 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -15,6 +15,8 @@ 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 SettingsStore from "../../settings/SettingsStore"; + const React = require('react'); const ReactDOM = require('react-dom'); const sdk = require('../../index'); @@ -934,11 +936,11 @@ module.exports = React.createClass({ _renderLabs: function() { const features = []; - UserSettingsStore.getLabsFeatures().forEach((featureId) => { + SettingsStore.getLabsFeatures().forEach((featureId) => { // TODO: this ought to be a separate component so that we don't need // to rebind the onChange each time we render const onChange = (e) => { - UserSettingsStore.setFeatureEnabled(featureId, e.target.checked); + SettingsStore.setFeatureEnabled(featureId, e.target.checked); this.forceUpdate(); }; @@ -948,10 +950,10 @@ module.exports = React.createClass({ type="checkbox" id={featureId} name={featureId} - defaultChecked={UserSettingsStore.isFeatureEnabled(featureId)} + defaultChecked={SettingsStore.isFeatureEnabled(featureId)} onChange={onChange} /> - + ); }); diff --git a/src/components/views/elements/Flair.js b/src/components/views/elements/Flair.js index 69d9aa35b7..2e2c7f2595 100644 --- a/src/components/views/elements/Flair.js +++ b/src/components/views/elements/Flair.js @@ -19,9 +19,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import {MatrixClient} from 'matrix-js-sdk'; -import UserSettingsStore from '../../../UserSettingsStore'; import FlairStore from '../../../stores/FlairStore'; import dis from '../../../dispatcher'; +import SettingsStore from "../../../settings/SettingsStore"; class FlairAvatar extends React.Component { @@ -79,7 +79,7 @@ export default class Flair extends React.Component { componentWillMount() { this._unmounted = false; - if (UserSettingsStore.isFeatureEnabled('feature_groups') && FlairStore.groupSupport()) { + if (SettingsStore.isFeatureEnabled('feature_groups') && FlairStore.groupSupport()) { this._generateAvatars(); } this.context.matrixClient.on('RoomState.events', this.onRoomStateEvents); diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js index 4dfbdb3644..fbfe7ebe18 100644 --- a/src/components/views/rooms/RoomHeader.js +++ b/src/components/views/rooms/RoomHeader.js @@ -31,7 +31,7 @@ import linkifyMatrix from '../../../linkify-matrix'; import AccessibleButton from '../elements/AccessibleButton'; import ManageIntegsButton from '../elements/ManageIntegsButton'; import {CancelButton} from './SimpleRoomHeader'; -import UserSettingsStore from "../../../UserSettingsStore"; +import SettingsStore from "../../../settings/SettingsStore"; linkifyMatrix(linkify); @@ -304,7 +304,7 @@ module.exports = React.createClass({ ; } - if (this.props.onPinnedClick && UserSettingsStore.isFeatureEnabled('feature_pinning')) { + if (this.props.onPinnedClick && SettingsStore.isFeatureEnabled('feature_pinning')) { pinnedEventsButton = diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js index dbdcdf596a..f582cc29ef 100644 --- a/src/components/views/rooms/RoomSettings.js +++ b/src/components/views/rooms/RoomSettings.js @@ -25,6 +25,7 @@ import ObjectUtils from '../../../ObjectUtils'; import dis from '../../../dispatcher'; import UserSettingsStore from '../../../UserSettingsStore'; import AccessibleButton from '../elements/AccessibleButton'; +import SettingsStore from "../../../settings/SettingsStore"; // parse a string as an integer; if the input is undefined, or cannot be parsed @@ -671,7 +672,7 @@ module.exports = React.createClass({ const self = this; let relatedGroupsSection; - if (UserSettingsStore.isFeatureEnabled('feature_groups')) { + if (SettingsStore.isFeatureEnabled('feature_groups')) { relatedGroupsSection = SettingsStore.isFeature(s)); + + const enableLabs = SdkConfig.get()["enableLabs"]; + if (enableLabs) return possibleFeatures; + + return possibleFeatures.filter((s) => SettingsStore._getFeatureState(s) === "labs"); + } + /** * Determines if a setting is also a feature. * @param {string} settingName The setting to look up. @@ -135,6 +159,16 @@ export default class SettingsStore { return SettingsStore.getValue(settingName, roomId); } + /** + * Sets a feature as enabled or disabled on the current device. + * @param {string} settingName The name of the setting. + * @param {boolean} value True to enable the feature, false otherwise. + * @returns {Promise} Resolves when the setting has been set. + */ + static setFeatureEnabled(settingName, value) { + return SettingsStore.setValue(settingName, null, "device", value); + } + /** * Gets the value of a setting. The room ID is optional if the setting is not to * be applied to any particular room, otherwise it should be supplied. @@ -228,7 +262,7 @@ export default class SettingsStore { if (!SETTINGS[settingName]) return {}; const handlers = {}; - for (let level of SETTINGS[settingName].supportedLevels) { + for (const level of SETTINGS[settingName].supportedLevels) { if (!LEVEL_HANDLERS[level]) throw new Error("Unexpected level " + level); handlers[level] = LEVEL_HANDLERS[level]; } @@ -246,7 +280,7 @@ export default class SettingsStore { } const allowedStates = ['enable', 'disable', 'labs']; - if (!allowedStates.contains(featureState)) { + if (!allowedStates.includes(featureState)) { console.warn("Feature state '" + featureState + "' is invalid for " + settingName); featureState = "disable"; // to prevent accidental features. }