From e50478aa1d8d2d8cd7358a1c0c8d2ae323f1fe98 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 12 Oct 2017 17:03:38 +0100 Subject: [PATCH 1/4] enable/disable features in config.json As per https://docs.google.com/document/d/1Kn-mz2dDce9Cqc4oUTl5yJXGvmTlky1_KezuwUg58x0/edit# Replaces: * enableLabs setting * 'override' flag in labs * 'default' flag in labs Un-feature-flags matrix apps since this was now overidden to be enabled. --- src/UserSettingsStore.js | 91 ++++++++++--------- src/components/structures/LoggedInView.js | 2 +- src/components/structures/UserSettings.js | 28 ++---- src/components/views/rooms/AuxPanel.js | 16 ++-- src/components/views/rooms/MessageComposer.js | 23 +++-- 5 files changed, 76 insertions(+), 84 deletions(-) diff --git a/src/UserSettingsStore.js b/src/UserSettingsStore.js index 9b7554bda2..ef111c5c62 100644 --- a/src/UserSettingsStore.js +++ b/src/UserSettingsStore.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 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. @@ -17,33 +18,42 @@ limitations under the License. import Promise from 'bluebird'; import MatrixClientPeg from './MatrixClientPeg'; import Notifier from './Notifier'; -import { _t } from './languageHandler'; +import { _t, _td } from './languageHandler'; +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("Groups"), + }, +]; + export default { - LABS_FEATURES: [ - { - name: "-", - id: 'matrix_apps', - default: true, + getLabsFeatures() { + const featuresConfig = SdkConfig.get()['features'] || {}; - // XXX: Always use default, ignore localStorage and remove from labs - override: true, - }, - { - name: "-", - id: 'feature_groups', - default: false, - }, - ], + return FEATURES.filter((f) => { + const sdkConfigValue = featuresConfig[f.id]; + if (!['enable', 'disable'].includes(sdkConfigValue)) { + return true; + } + }).map((f) => { + return f.id; + }); + }, - // horrible but it works. The locality makes this somewhat more palatable. - doTranslations: function() { - this.LABS_FEATURES[0].name = _t("Matrix Apps"); - this.LABS_FEATURES[1].name = _t("Groups"); + translatedNameForFeature(featureId) { + const feature = FEATURES.filter((f) => { + return f.id === featureId; + })[0]; + + if (feature === undefined) return null; + + return _t(feature.name); }, loadProfileInfo: function() { @@ -180,33 +190,30 @@ export default { localStorage.setItem('mx_local_settings', JSON.stringify(settings)); }, - getFeatureById(feature: string) { - for (let i = 0; i < this.LABS_FEATURES.length; i++) { - const f = this.LABS_FEATURES[i]; - if (f.id === feature) { - return f; - } - } - return null; - }, - isFeatureEnabled: function(featureId: string): boolean { - // Disable labs for guests. - if (MatrixClientPeg.get().isGuest()) return false; + const featuresConfig = SdkConfig.get()['features']; - const feature = this.getFeatureById(featureId); - if (!feature) { - console.warn(`Unknown feature "${featureId}"`); + let sdkConfigValue = 'labs'; + if (featuresConfig && featuresConfig[featureId] !== undefined) { + sdkConfigValue = featuresConfig[featureId]; + } + + if (sdkConfigValue === 'enable') { + return true; + } else if (sdkConfigValue === 'enable') { + return false; + } else if (sdkConfigValue === 'labs') { + if (!MatrixClientPeg.get().isGuest()) { + const userValue = localStorage.getItem(`mx_labs_feature_${featureId}`); + if (userValue !== null) { + return userValue === 'true'; + } + } + return false; + } else { + console.warn(`Unknown features config for ${featureId}: ${sdkConfigValue}`); return false; } - // Return the default if this feature has an override to be the default value or - // if the feature has never been toggled and is therefore not in localStorage - if (Object.keys(feature).includes('override') || - localStorage.getItem(`mx_labs_feature_${featureId}`) === null - ) { - return feature.default; - } - return localStorage.getItem(`mx_labs_feature_${featureId}`) === 'true'; }, setFeatureEnabled: function(featureId: string, enabled: boolean) { diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 49522747cd..7e6fc05599 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -1,6 +1,7 @@ /* Copyright 2015, 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd +Copyright 2017 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. @@ -250,7 +251,6 @@ export default React.createClass({ page_element = ; diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 171a0dd0fd..d83434f5a8 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -1,6 +1,7 @@ /* Copyright 2015, 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd +Copyright 2017 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. @@ -212,9 +213,6 @@ module.exports = React.createClass({ // The brand string given when creating email pushers brand: React.PropTypes.string, - // True to show the 'labs' section of experimental features - enableLabs: React.PropTypes.bool, - // The base URL to use in the referral link. Defaults to window.location.origin. referralBaseUrl: React.PropTypes.string, @@ -226,7 +224,6 @@ module.exports = React.createClass({ getDefaultProps: function() { return { onClose: function() {}, - enableLabs: true, }; }, @@ -923,34 +920,25 @@ module.exports = React.createClass({ }, _renderLabs: function() { - // default to enabled if undefined - if (this.props.enableLabs === false) return null; - UserSettingsStore.doTranslations(); - const features = []; - UserSettingsStore.LABS_FEATURES.forEach((feature) => { - // This feature has an override and will be set to the default, so do not - // show it here. - if (feature.override) { - return; - } + UserSettingsStore.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(feature.id, e.target.checked); + UserSettingsStore.setFeatureEnabled(featureId, e.target.checked); this.forceUpdate(); }; features.push( -
+
- +
); }); diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js index 726ec7ff1d..271b0e48db 100644 --- a/src/components/views/rooms/AuxPanel.js +++ b/src/components/views/rooms/AuxPanel.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 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. @@ -128,15 +129,12 @@ module.exports = React.createClass({ /> ); - let appsDrawer = null; - if(UserSettingsStore.isFeatureEnabled('matrix_apps')) { - appsDrawer = ; - } + const appsDrawer = ; return (
diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 00659520c3..8e27520d89 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 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. @@ -285,18 +286,16 @@ export default class MessageComposer extends React.Component { } // Apps - if (UserSettingsStore.isFeatureEnabled('matrix_apps')) { - if (this.props.showApps) { - hideAppsButton = -
- -
; - } else { - showAppsButton = -
- -
; - } + if (this.props.showApps) { + hideAppsButton = +
+ +
; + } else { + showAppsButton = +
+ +
; } const canSendMessages = this.props.room.currentState.maySendMessage( From 20f9d71782fb237c06bea9f400c0545d26914b21 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 12 Oct 2017 17:27:09 +0100 Subject: [PATCH 2/4] oops --- src/UserSettingsStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UserSettingsStore.js b/src/UserSettingsStore.js index ef111c5c62..02b9b649b5 100644 --- a/src/UserSettingsStore.js +++ b/src/UserSettingsStore.js @@ -200,7 +200,7 @@ export default { if (sdkConfigValue === 'enable') { return true; - } else if (sdkConfigValue === 'enable') { + } else if (sdkConfigValue === 'disable') { return false; } else if (sdkConfigValue === 'labs') { if (!MatrixClientPeg.get().isGuest()) { From ef3df3e3fafe2397b2157b081f80eda8f4d8896a Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 12 Oct 2017 17:28:14 +0100 Subject: [PATCH 3/4] comment --- src/UserSettingsStore.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/UserSettingsStore.js b/src/UserSettingsStore.js index 02b9b649b5..0e9d58b270 100644 --- a/src/UserSettingsStore.js +++ b/src/UserSettingsStore.js @@ -204,6 +204,8 @@ export default { 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}`); if (userValue !== null) { return userValue === 'true'; From 65eacff3d3fbe3b30c9cba8812af5fbb7193132f Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 12 Oct 2017 17:28:53 +0100 Subject: [PATCH 4/4] redundant code is redundant --- src/UserSettingsStore.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/UserSettingsStore.js b/src/UserSettingsStore.js index 0e9d58b270..050e28e5b7 100644 --- a/src/UserSettingsStore.js +++ b/src/UserSettingsStore.js @@ -207,9 +207,7 @@ export default { // 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}`); - if (userValue !== null) { - return userValue === 'true'; - } + return userValue === 'true'; } return false; } else {