From aee467c4e55dcc9d3a892d05357b691f10a6ed3c Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 23 Nov 2021 15:04:10 +0000 Subject: [PATCH 1/3] Group Labs flags --- .../tabs/user/LabsUserSettingsTab.tsx | 49 ++++++++++++++----- src/i18n/strings/en_EN.json | 12 +++-- src/settings/Settings.tsx | 48 ++++++++++++++++-- src/settings/SettingsStore.ts | 10 +++- 4 files changed, 98 insertions(+), 21 deletions(-) diff --git a/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx b/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx index 4b8c8f8c408..7375ead8935 100644 --- a/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx @@ -15,6 +15,8 @@ limitations under the License. */ import React from 'react'; +import { sortBy } from "lodash"; + import { _t } from "../../../../../languageHandler"; import SettingsStore from "../../../../../settings/SettingsStore"; import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch"; @@ -24,6 +26,8 @@ import SdkConfig from "../../../../../SdkConfig"; import BetaCard from "../../../beta/BetaCard"; import SettingsFlag from '../../../elements/SettingsFlag'; import { MatrixClientPeg } from '../../../../../MatrixClientPeg'; +import { LabGroup, labGroupNames } from "../../../../../settings/Settings"; +import { EnhancedMap } from "../../../../../utils/maps"; interface ILabsSettingToggleProps { featureId: string; @@ -66,7 +70,7 @@ export default class LabsUserSettingsTab extends React.Component<{}, IState> { const [labs, betas] = features.reduce((arr, f) => { arr[SettingsStore.getBetaInfo(f) ? 1 : 0].push(f); return arr; - }, [[], []]); + }, [[], []] as [string[], string[]]); let betaSection; if (betas.length) { @@ -77,23 +81,44 @@ export default class LabsUserSettingsTab extends React.Component<{}, IState> { let labsSection; if (SdkConfig.get()['showLabsSettings']) { - const flags = labs.map(f => ); + const groups = new EnhancedMap(); + labs.forEach(f => { + const group = SettingsStore.getLabGroup(f); + groups.getOrCreate(group ?? LabGroup.Other, []).push( + , + ); + }); + + groups.get(LabGroup.Widgets).push( + , + ); + + groups.get(LabGroup.Experimental).push( + , + ); + + groups.getOrCreate(LabGroup.Developer, []).push( + , + , + ); + + groups.get(LabGroup.Analytics).push( + , + ); - let hiddenReadReceipts; if (this.state.showHiddenReadReceipts) { - hiddenReadReceipts = ( - + groups.get(LabGroup.Messaging).push( + , ); } labsSection =
- - { flags } - - - - - { hiddenReadReceipts } + { sortBy(Array.from(groups.entries()), "0").map(([group, flags]) => ( +
+ { _t(labGroupNames[group]) } + { flags } +
+ )) }
; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0f1f5b05477..58503c5a874 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -813,6 +813,14 @@ "%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s", "%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s", "Change notification settings": "Change notification settings", + "Messaging": "Messaging", + "Profile": "Profile", + "Spaces": "Spaces", + "Widgets": "Widgets", + "Rooms": "Rooms", + "Moderation": "Moderation", + "Experimental": "Experimental", + "Developer": "Developer", "Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators": "Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators", "Show options to enable 'Do not disturb' mode": "Show options to enable 'Do not disturb' mode", "Render LaTeX maths in messages": "Render LaTeX maths in messages", @@ -1073,7 +1081,6 @@ "Favourites": "Favourites", "People": "People", "Other rooms": "Other rooms", - "Spaces": "Spaces", "Expand space panel": "Expand space panel", "Collapse space panel": "Collapse space panel", "Click to copy": "Click to copy", @@ -1236,7 +1243,6 @@ "Failed to save your profile": "Failed to save your profile", "The operation could not be completed": "The operation could not be completed", "Upgrade to your own domain": "Upgrade to your own domain", - "Profile": "Profile", "Profile picture": "Profile picture", "Save": "Save", "Delete Backup": "Delete Backup", @@ -1700,7 +1706,6 @@ "Search": "Search", "Invites": "Invites", "Start chat": "Start chat", - "Rooms": "Rooms", "Add room": "Add room", "Create new room": "Create new room", "You do not have permissions to create new rooms in this space": "You do not have permissions to create new rooms in this space", @@ -1882,7 +1887,6 @@ "Unpin this widget to view it in this panel": "Unpin this widget to view it in this panel", "Close this widget to view it in this panel": "Close this widget to view it in this panel", "Set my room layout for everyone": "Set my room layout for everyone", - "Widgets": "Widgets", "Edit widgets, bridges & bots": "Edit widgets, bridges & bots", "Add widgets, bridges & bots": "Add widgets, bridges & bots", "Not encrypted": "Not encrypted", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index d83198fc56d..2cb2c7099cc 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -86,9 +86,36 @@ const LEVELS_UI_FEATURE = [ // in future we might have a .well-known level or something ]; +export enum LabGroup { + Messaging, + Profile, + Spaces, + Widgets, + Rooms, + Moderation, + Analytics, + Experimental, + Other, + Developer, +} + +export const labGroupNames: Record = { + [LabGroup.Messaging]: _td("Messaging"), + [LabGroup.Profile]: _td("Profile"), + [LabGroup.Spaces]: _td("Spaces"), + [LabGroup.Widgets]: _td("Widgets"), + [LabGroup.Rooms]: _td("Rooms"), + [LabGroup.Moderation]: _td("Moderation"), + [LabGroup.Analytics]: _td("Analytics"), + [LabGroup.Experimental]: _td("Experimental"), + [LabGroup.Other]: _td("Other"), + [LabGroup.Developer]: _td("Developer"), +}; + export interface ISetting { // Must be set to true for features. Default is 'false'. isFeature?: boolean; + labsGroup?: LabGroup; // Display names are strongly recommended for clarity. // Display name can also be an object for different levels. @@ -141,6 +168,7 @@ export interface ISetting { export const SETTINGS: {[setting: string]: ISetting} = { "feature_report_to_moderators": { isFeature: true, + labsGroup: LabGroup.Moderation, displayName: _td("Report to moderators prototype. " + "In rooms that support moderation, the `report` button will let you report abuse to room moderators"), supportedLevels: LEVELS_FEATURE, @@ -148,18 +176,21 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_dnd": { isFeature: true, + labsGroup: LabGroup.Profile, displayName: _td("Show options to enable 'Do not disturb' mode"), supportedLevels: LEVELS_FEATURE, default: false, }, "feature_latex_maths": { isFeature: true, + labsGroup: LabGroup.Messaging, displayName: _td("Render LaTeX maths in messages"), supportedLevels: LEVELS_FEATURE, default: false, }, "feature_communities_v2_prototypes": { isFeature: true, + labsGroup: LabGroup.Spaces, displayName: _td( "Communities v2 prototypes. Requires compatible homeserver. " + "Highly experimental - use with caution.", @@ -170,18 +201,21 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_pinning": { isFeature: true, + labsGroup: LabGroup.Messaging, displayName: _td("Message Pinning"), supportedLevels: LEVELS_FEATURE, default: false, }, "feature_maximised_widgets": { isFeature: true, + labsGroup: LabGroup.Widgets, displayName: _td("Maximised widgets"), supportedLevels: LEVELS_FEATURE, default: false, }, "feature_thread": { isFeature: true, + labsGroup: LabGroup.Messaging, // Requires a reload as we change an option flag on the `js-sdk` // And the entire sync history needs to be parsed again controller: new ReloadOnChangeController(), @@ -191,6 +225,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_custom_status": { isFeature: true, + labsGroup: LabGroup.Profile, displayName: _td("Custom user status messages"), supportedLevels: LEVELS_FEATURE, default: false, @@ -198,6 +233,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_custom_tags": { isFeature: true, + labsGroup: LabGroup.Experimental, displayName: _td("Group & filter rooms by custom tags (refresh to apply changes)"), supportedLevels: LEVELS_FEATURE, default: false, @@ -205,18 +241,21 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_state_counters": { isFeature: true, + labsGroup: LabGroup.Rooms, displayName: _td("Render simple counters in room header"), supportedLevels: LEVELS_FEATURE, default: false, }, "feature_many_integration_managers": { isFeature: true, + labsGroup: LabGroup.Experimental, displayName: _td("Multiple integration managers (requires manual setup)"), supportedLevels: LEVELS_FEATURE, default: false, }, "feature_mjolnir": { isFeature: true, + labsGroup: LabGroup.Moderation, displayName: _td("Try out new ways to ignore people (experimental)"), supportedLevels: LEVELS_FEATURE, default: false, @@ -249,6 +288,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_pseudonymous_analytics_opt_in": { isFeature: true, + labsGroup: LabGroup.Analytics, supportedLevels: LEVELS_FEATURE, displayName: _td('Send pseudonymous analytics data'), default: false, @@ -256,6 +296,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_polls": { isFeature: true, + labsGroup: LabGroup.Messaging, supportedLevels: LEVELS_FEATURE, displayName: _td("Polls (under active development)"), default: false, @@ -274,12 +315,14 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_bridge_state": { isFeature: true, + labsGroup: LabGroup.Rooms, supportedLevels: LEVELS_FEATURE, displayName: _td("Show info about bridges in room settings"), default: false, }, "feature_new_layout_switcher": { isFeature: true, + labsGroup: LabGroup.Messaging, supportedLevels: LEVELS_FEATURE, displayName: _td("New layout switcher (with message bubbles)"), default: false, @@ -287,6 +330,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_spaces_metaspaces": { isFeature: true, + labsGroup: LabGroup.Spaces, supportedLevels: LEVELS_FEATURE, displayName: _td("Meta Spaces"), default: false, @@ -301,9 +345,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_hidden_read_receipts": { supportedLevels: LEVELS_FEATURE, - displayName: _td( - "Don't send read receipts", - ), + displayName: _td("Don't send read receipts"), default: false, }, "baseFontSize": { diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts index 1222ca9231e..f28eca7756b 100644 --- a/src/settings/SettingsStore.ts +++ b/src/settings/SettingsStore.ts @@ -24,7 +24,7 @@ import RoomSettingsHandler from "./handlers/RoomSettingsHandler"; import ConfigSettingsHandler from "./handlers/ConfigSettingsHandler"; import { _t } from '../languageHandler'; import dis from '../dispatcher/dispatcher'; -import { ISetting, SETTINGS } from "./Settings"; +import { ISetting, LabGroup, SETTINGS } from "./Settings"; import LocalEchoWrapper from "./handlers/LocalEchoWrapper"; import { WatchManager, CallbackFn as WatchCallbackFn } from "./WatchManager"; import { SettingLevel } from "./SettingLevel"; @@ -273,7 +273,7 @@ export default class SettingsStore { return SETTINGS[settingName].isFeature; } - public static getBetaInfo(settingName: string) { + public static getBetaInfo(settingName: string): ISetting["betaInfo"] { // consider a beta disabled if the config is explicitly set to false, in which case treat as normal Labs flag if (SettingsStore.isFeature(settingName) && SettingsStore.getValueAt(SettingLevel.CONFIG, settingName, null, true, true) !== false @@ -282,6 +282,12 @@ export default class SettingsStore { } } + public static getLabGroup(settingName: string): LabGroup { + if (SettingsStore.isFeature(settingName)) { + return SETTINGS[settingName]?.labsGroup; + } + } + /** * Determines if a setting is enabled. * If a setting is disabled then it should be hidden from the user. From 24b6bace529fafc159fdfdbef45d6a4dbea20774 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 Nov 2021 16:07:33 +0000 Subject: [PATCH 2/3] Iterate labs groupings based on review --- .../tabs/user/LabsUserSettingsTab.tsx | 3 +- src/i18n/strings/en_EN.json | 4 ++- src/settings/Settings.tsx | 28 +++++++++++++++---- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx b/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx index 7375ead8935..ad3854c1a67 100644 --- a/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx @@ -83,8 +83,7 @@ export default class LabsUserSettingsTab extends React.Component<{}, IState> { if (SdkConfig.get()['showLabsSettings']) { const groups = new EnhancedMap(); labs.forEach(f => { - const group = SettingsStore.getLabGroup(f); - groups.getOrCreate(group ?? LabGroup.Other, []).push( + groups.getOrCreate(SettingsStore.getLabGroup(f), []).push( , ); }); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 58503c5a874..b5e7f5166ce 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -819,6 +819,9 @@ "Widgets": "Widgets", "Rooms": "Rooms", "Moderation": "Moderation", + "Message Previews": "Message Previews", + "Themes": "Themes", + "Encryption": "Encryption", "Experimental": "Experimental", "Developer": "Developer", "Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators": "Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators", @@ -1179,7 +1182,6 @@ "Sign Out": "Sign Out", "Display Name": "Display Name", "Rename": "Rename", - "Encryption": "Encryption", "Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.", "Securely cache encrypted messages locally for them to appear in search results, using %(size)s to store messages from %(rooms)s rooms.|other": "Securely cache encrypted messages locally for them to appear in search results, using %(size)s to store messages from %(rooms)s rooms.", "Securely cache encrypted messages locally for them to appear in search results, using %(size)s to store messages from %(rooms)s rooms.|one": "Securely cache encrypted messages locally for them to appear in search results, using %(size)s to store messages from %(rooms)s room.", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 2cb2c7099cc..860139e41b9 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -94,8 +94,10 @@ export enum LabGroup { Rooms, Moderation, Analytics, + MessagePreviews, + Themes, + Encryption, Experimental, - Other, Developer, } @@ -107,15 +109,16 @@ export const labGroupNames: Record = { [LabGroup.Rooms]: _td("Rooms"), [LabGroup.Moderation]: _td("Moderation"), [LabGroup.Analytics]: _td("Analytics"), + [LabGroup.MessagePreviews]: _td("Message Previews"), + [LabGroup.Themes]: _td("Themes"), + [LabGroup.Encryption]: _td("Encryption"), [LabGroup.Experimental]: _td("Experimental"), - [LabGroup.Other]: _td("Other"), [LabGroup.Developer]: _td("Developer"), }; -export interface ISetting { - // Must be set to true for features. Default is 'false'. - isFeature?: boolean; - labsGroup?: LabGroup; +interface IBaseSetting { + isFeature?: false | undefined; + labsGroup?: void; // Display names are strongly recommended for clarity. // Display name can also be an object for different levels. @@ -165,6 +168,15 @@ export interface ISetting { }; } +interface IFeature extends Omit { + // Must be set to true for features. + isFeature: true; + labsGroup: LabGroup; +} + +// Type using I-identifier for backwards compatibility from before it became a discriminated union +export type ISetting = IBaseSetting | IFeature; + export const SETTINGS: {[setting: string]: ISetting} = { "feature_report_to_moderators": { isFeature: true, @@ -262,12 +274,14 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_custom_themes": { isFeature: true, + labsGroup: LabGroup.Themes, displayName: _td("Support adding custom themes"), supportedLevels: LEVELS_FEATURE, default: false, }, "feature_roomlist_preview_reactions_dms": { isFeature: true, + labsGroup: LabGroup.MessagePreviews, displayName: _td("Show message previews for reactions in DMs"), supportedLevels: LEVELS_FEATURE, default: false, @@ -276,12 +290,14 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "feature_roomlist_preview_reactions_all": { isFeature: true, + labsGroup: LabGroup.MessagePreviews, displayName: _td("Show message previews for reactions in all rooms"), supportedLevels: LEVELS_FEATURE, default: false, }, "feature_dehydration": { isFeature: true, + labsGroup: LabGroup.Encryption, displayName: _td("Offline encrypted messaging using dehydrated devices"), supportedLevels: LEVELS_FEATURE, default: false, From 5b16823afc7488379d69a407b0f4cd9c332951de Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 Nov 2021 16:15:19 +0000 Subject: [PATCH 3/3] fix typing --- src/settings/Settings.tsx | 3 +-- src/settings/SettingsStore.ts | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 860139e41b9..395a5897117 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -118,7 +118,6 @@ export const labGroupNames: Record = { interface IBaseSetting { isFeature?: false | undefined; - labsGroup?: void; // Display names are strongly recommended for clarity. // Display name can also be an object for different levels. @@ -168,7 +167,7 @@ interface IBaseSetting { }; } -interface IFeature extends Omit { +export interface IFeature extends Omit { // Must be set to true for features. isFeature: true; labsGroup: LabGroup; diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts index f28eca7756b..9cabb27b94d 100644 --- a/src/settings/SettingsStore.ts +++ b/src/settings/SettingsStore.ts @@ -24,7 +24,7 @@ import RoomSettingsHandler from "./handlers/RoomSettingsHandler"; import ConfigSettingsHandler from "./handlers/ConfigSettingsHandler"; import { _t } from '../languageHandler'; import dis from '../dispatcher/dispatcher'; -import { ISetting, LabGroup, SETTINGS } from "./Settings"; +import { IFeature, ISetting, LabGroup, SETTINGS } from "./Settings"; import LocalEchoWrapper from "./handlers/LocalEchoWrapper"; import { WatchManager, CallbackFn as WatchCallbackFn } from "./WatchManager"; import { SettingLevel } from "./SettingLevel"; @@ -284,7 +284,7 @@ export default class SettingsStore { public static getLabGroup(settingName: string): LabGroup { if (SettingsStore.isFeature(settingName)) { - return SETTINGS[settingName]?.labsGroup; + return (SETTINGS[settingName]).labsGroup; } }