From a732c55797599446c131e46ccc937859978ce5c6 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 21 Aug 2020 18:22:05 +0100 Subject: [PATCH 01/14] Add secret storage readiness checks This visits all places that were checking for cross-siging readiness and adapts them to also check for secret storage readiness if needed. Part of https://github.com/vector-im/element-web/issues/13895 --- src/DeviceListener.ts | 6 +++++- .../views/settings/CrossSigningPanel.js | 16 ++++++++++++---- src/i18n/strings/en_EN.json | 3 ++- src/rageshake/submit-rageshake.ts | 1 + 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/DeviceListener.ts b/src/DeviceListener.ts index 6b667ae54d..b05f0fcd68 100644 --- a/src/DeviceListener.ts +++ b/src/DeviceListener.ts @@ -207,9 +207,13 @@ export default class DeviceListener { // (we add a listener on sync to do once check after the initial sync is done) if (!cli.isInitialSyncComplete()) return; + // JRS: This will change again in the next PR which moves secret storage + // later in the process. const crossSigningReady = await cli.isCrossSigningReady(); + const secretStorageReady = await cli.isSecretStorageReady(); + const allSystemsReady = crossSigningReady && secretStorageReady; - if (this.dismissedThisDeviceToast || crossSigningReady) { + if (this.dismissedThisDeviceToast || allSystemsReady) { hideSetupEncryptionToast(); } else if (this.shouldShowSetupEncryptionToast()) { // make sure our keys are finished downloading diff --git a/src/components/views/settings/CrossSigningPanel.js b/src/components/views/settings/CrossSigningPanel.js index 1c6baee9af..847bcf3da3 100644 --- a/src/components/views/settings/CrossSigningPanel.js +++ b/src/components/views/settings/CrossSigningPanel.js @@ -89,6 +89,7 @@ export default class CrossSigningPanel extends React.PureComponent { const homeserverSupportsCrossSigning = await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing"); const crossSigningReady = await cli.isCrossSigningReady(); + const secretStorageReady = await cli.isSecretStorageReady(); this.setState({ crossSigningPublicKeysOnDevice, @@ -101,6 +102,7 @@ export default class CrossSigningPanel extends React.PureComponent { secretStorageKeyInAccount, homeserverSupportsCrossSigning, crossSigningReady, + secretStorageReady, }); } @@ -151,6 +153,7 @@ export default class CrossSigningPanel extends React.PureComponent { secretStorageKeyInAccount, homeserverSupportsCrossSigning, crossSigningReady, + secretStorageReady, } = this.state; let errorSection; @@ -166,14 +169,19 @@ export default class CrossSigningPanel extends React.PureComponent { summarisedStatus =

{_t( "Your homeserver does not support cross-signing.", )}

; - } else if (crossSigningReady) { + } else if (crossSigningReady && secretStorageReady) { summarisedStatus =

✅ {_t( - "Cross-signing and secret storage are enabled.", + "Cross-signing and secret storage are ready for use.", + )}

; + } else if (crossSigningReady && !secretStorageReady) { + summarisedStatus =

✅ {_t( + "Cross-signing is ready for use, but secret storage is " + + "currently not being used to backup your keys.", )}

; } else if (crossSigningPrivateKeysInStorage) { summarisedStatus =

{_t( - "Your account has a cross-signing identity in secret storage, but it " + - "is not yet trusted by this session.", + "Your account has a cross-signing identity in secret storage, " + + "but it is not yet trusted by this session.", )}

; } else { summarisedStatus =

{_t( diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c12b57c033..dc2669e20f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -645,7 +645,8 @@ "Confirm password": "Confirm password", "Change Password": "Change Password", "Your homeserver does not support cross-signing.": "Your homeserver does not support cross-signing.", - "Cross-signing and secret storage are enabled.": "Cross-signing and secret storage are enabled.", + "Cross-signing and secret storage are ready for use.": "Cross-signing and secret storage are ready for use.", + "Cross-signing is ready for use, but secret storage is currently not being used to backup your keys.": "Cross-signing is ready for use, but secret storage is currently not being used to backup your keys.", "Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.": "Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.", "Cross-signing and secret storage are not yet set up.": "Cross-signing and secret storage are not yet set up.", "Reset cross-signing and secret storage": "Reset cross-signing and secret storage", diff --git a/src/rageshake/submit-rageshake.ts b/src/rageshake/submit-rageshake.ts index 74292749b9..448562b68a 100644 --- a/src/rageshake/submit-rageshake.ts +++ b/src/rageshake/submit-rageshake.ts @@ -115,6 +115,7 @@ async function collectBugReport(opts: IOpts = {}, gzipLogs = true) { body.append("cross_signing_supported_by_hs", String(await client.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing"))); body.append("cross_signing_ready", String(await client.isCrossSigningReady())); + body.append("secret_storage_ready", String(await client.isSecretStorageReady())); } } From fd71bca7c0af97ab496a3d320900498256af0dc4 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 26 Aug 2020 10:33:05 -0600 Subject: [PATCH 02/14] Change menu label if in a community --- src/components/views/rooms/RoomList.tsx | 5 ++++- src/i18n/strings/en_EN.json | 1 + src/stores/TagOrderStore.js | 7 +++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index 3274e0e49f..92c5982276 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -45,6 +45,7 @@ import { arrayFastClone, arrayHasDiff } from "../../../utils/arrays"; import { objectShallowClone, objectWithOnly } from "../../../utils/objects"; import { IconizedContextMenuOption, IconizedContextMenuOptionList } from "../context_menus/IconizedContextMenu"; import AccessibleButton from "../elements/AccessibleButton"; +import TagOrderStore from "../../../stores/TagOrderStore"; interface IProps { onKeyDown: (ev: React.KeyboardEvent) => void; @@ -129,7 +130,9 @@ const TAG_AESTHETICS: { }} /> { e.preventDefault(); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index d6ba736a76..da4e298f0f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1121,6 +1121,7 @@ "Rooms": "Rooms", "Add room": "Add room", "Create new room": "Create new room", + "Explore community rooms": "Explore community rooms", "Explore public rooms": "Explore public rooms", "Low priority": "Low priority", "System Alerts": "System Alerts", diff --git a/src/stores/TagOrderStore.js b/src/stores/TagOrderStore.js index f02fce0769..2eb35e6dc2 100644 --- a/src/stores/TagOrderStore.js +++ b/src/stores/TagOrderStore.js @@ -285,6 +285,13 @@ class TagOrderStore extends Store { getSelectedTags() { return this._state.selectedTags; } + + getSelectedPrototypeTag() { + if (SettingsStore.getValue("feature_communities_v2_prototypes")) { + return this.getSelectedTags()[0]; + } + return null; // no selection as far as this function is concerned + } } if (global.singletonTagOrderStore === undefined) { From c28134eb11bb3f1fab540c83cf9a512d1209f3e0 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 26 Aug 2020 10:53:06 -0600 Subject: [PATCH 03/14] Associate created rooms with the selected community --- src/components/views/dialogs/CreateRoomDialog.js | 13 ++++++++++++- src/createRoom.ts | 6 ++++++ src/i18n/strings/en_EN.json | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/CreateRoomDialog.js b/src/components/views/dialogs/CreateRoomDialog.js index ce7ac6e59c..9726c44fac 100644 --- a/src/components/views/dialogs/CreateRoomDialog.js +++ b/src/components/views/dialogs/CreateRoomDialog.js @@ -25,6 +25,8 @@ import { _t } from '../../../languageHandler'; import {MatrixClientPeg} from '../../../MatrixClientPeg'; import {Key} from "../../../Keyboard"; import {privateShouldBeEncrypted} from "../../../createRoom"; +import TagOrderStore from "../../../stores/TagOrderStore"; +import GroupStore from "../../../stores/GroupStore"; export default createReactClass({ displayName: 'CreateRoomDialog', @@ -70,6 +72,10 @@ export default createReactClass({ opts.encryption = this.state.isEncrypted; } + if (TagOrderStore.getSelectedPrototypeTag()) { + opts.associatedWithCommunity = TagOrderStore.getSelectedPrototypeTag(); + } + return opts; }, @@ -212,7 +218,12 @@ export default createReactClass({ ; } - const title = this.state.isPublic ? _t('Create a public room') : _t('Create a private room'); + let title = this.state.isPublic ? _t('Create a public room') : _t('Create a private room'); + if (TagOrderStore.getSelectedPrototypeTag()) { + const summary = GroupStore.getSummary(TagOrderStore.getSelectedPrototypeTag()); + const name = summary?.profile?.name || TagOrderStore.getSelectedPrototypeTag(); + title = _t("Create a room in %(communityName)s", {communityName: name}); + } return ( { } else { return Promise.resolve(); } + }).then(() => { + if (opts.associatedWithCommunity) { + return GroupStore.addRoomToGroup(opts.associatedWithCommunity, roomId, false); + } }).then(function() { // NB createRoom doesn't block on the client seeing the echo that the // room has been created, so we race here with the client knowing that diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index da4e298f0f..0ec12a4d6a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1643,6 +1643,7 @@ "Enable end-to-end encryption": "Enable end-to-end encryption", "Create a public room": "Create a public room", "Create a private room": "Create a private room", + "Create a room in %(communityName)s": "Create a room in %(communityName)s", "Name": "Name", "Topic (optional)": "Topic (optional)", "Make this room public": "Make this room public", From 027f263589a767830120b18b83829d8ca8c42bab Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 26 Aug 2020 11:01:58 -0600 Subject: [PATCH 04/14] Remove prototype code from CreateGroupDialog The prototype code paths prevent users from ending up here, so we don't need custom code. --- .../views/dialogs/CreateGroupDialog.js | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/components/views/dialogs/CreateGroupDialog.js b/src/components/views/dialogs/CreateGroupDialog.js index 2b22054947..10285ccee0 100644 --- a/src/components/views/dialogs/CreateGroupDialog.js +++ b/src/components/views/dialogs/CreateGroupDialog.js @@ -83,25 +83,11 @@ export default createReactClass({ localpart: this.state.groupId, profile: profile, }).then((result) => { - if (result.room_id) { - dis.dispatch({ - action: 'view_room', - room_id: result.room_id, - }); - - // Ensure the tag gets selected now that we've created it - dis.dispatch({action: 'deselect_tags'}, true); - dis.dispatch({ - action: 'select_tag', - tag: result.group_id, - }); - } else { - dis.dispatch({ - action: 'view_group', - group_id: result.group_id, - group_is_new: true, - }); - } + dis.dispatch({ + action: 'view_group', + group_id: result.group_id, + group_is_new: true, + }); this.props.onFinished(true); }).catch((e) => { this.setState({createError: e}); From 4f29770adb8880e451067d58574b6d1f06e02de1 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 26 Aug 2020 11:02:14 -0600 Subject: [PATCH 05/14] Force the GroupStore to update after creating a prototype community --- .../views/dialogs/CreateCommunityPrototypeDialog.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx b/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx index 5f8321fd7d..58412c23d6 100644 --- a/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx +++ b/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx @@ -24,6 +24,7 @@ import { MatrixClientPeg } from "../../../MatrixClientPeg"; import InfoTooltip from "../elements/InfoTooltip"; import dis from "../../../dispatcher/dispatcher"; import {showCommunityRoomInviteDialog} from "../../../RoomInvite"; +import GroupStore from "../../../stores/GroupStore"; interface IProps extends IDialogProps { } @@ -92,6 +93,8 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent< this.props.onFinished(true); if (result.room_id) { + // Force the group store to update as it might have missed the general chat + await GroupStore.refreshGroupRooms(result.group_id); dis.dispatch({ action: 'view_room', room_id: result.room_id, From 4a807f9385fd3e755b46b897761f77cac1107e63 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 27 Aug 2020 13:41:03 +0100 Subject: [PATCH 06/14] Migrate to new, separate APIs for cross-signing and secret storage This migrates to the new JS SDK APIs, which now use separate paths for cross-signing and secret storage setup. There should be no functional change here. Part of https://github.com/vector-im/element-web/issues/13895 --- src/CrossSigningManager.js | 6 ++++-- .../dialogs/secretstorage/CreateSecretStorageDialog.js | 9 +++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js index da09a436e9..a7b494dc26 100644 --- a/src/CrossSigningManager.js +++ b/src/CrossSigningManager.js @@ -239,7 +239,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f } } else { const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog"); - await cli.bootstrapSecretStorage({ + await cli.bootstrapCrossSigning({ authUploadDeviceSigningKeys: async (makeRequest) => { const { finished } = Modal.createTrackedDialog( 'Cross-signing keys dialog', '', InteractiveAuthDialog, @@ -254,7 +254,9 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f throw new Error("Cross-signing key upload auth canceled"); } }, - getBackupPassphrase: promptForBackupPassphrase, + }); + await cli.bootstrapSecretStorage({ + getKeyBackupPassphrase: promptForBackupPassphrase, }); } diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index 47faa35df4..19c0c79448 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -282,15 +282,20 @@ export default class CreateSecretStorageDialog extends React.PureComponent { try { if (force) { console.log("Forcing secret storage reset"); // log something so we can debug this later - await cli.bootstrapSecretStorage({ + await cli.bootstrapCrossSigning({ authUploadDeviceSigningKeys: this._doBootstrapUIAuth, + setupNewCrossSigning: true, + }); + await cli.bootstrapSecretStorage({ createSecretStorageKey: async () => this._recoveryKey, setupNewKeyBackup: true, setupNewSecretStorage: true, }); } else { - await cli.bootstrapSecretStorage({ + await cli.bootstrapCrossSigning({ authUploadDeviceSigningKeys: this._doBootstrapUIAuth, + }); + await cli.bootstrapSecretStorage({ createSecretStorageKey: async () => this._recoveryKey, keyBackupInfo: this.state.backupInfo, setupNewKeyBackup: !this.state.backupInfo, From 3a98b4b4e948b9993d8f063049c5338e42fefd21 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 27 Aug 2020 13:50:50 +0100 Subject: [PATCH 07/14] Rename reset secret storage prop The bare word `force` has bothered me, so this adds a tiny amount more meaning. --- src/CrossSigningManager.js | 2 +- .../secretstorage/CreateSecretStorageDialog.js | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js index a7b494dc26..b15290b9c3 100644 --- a/src/CrossSigningManager.js +++ b/src/CrossSigningManager.js @@ -218,7 +218,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '', import("./async-components/views/dialogs/secretstorage/CreateSecretStorageDialog"), { - force: forceReset, + forceReset, }, null, /* priority = */ false, diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index 19c0c79448..00216e3765 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -56,12 +56,12 @@ export default class CreateSecretStorageDialog extends React.PureComponent { static propTypes = { hasCancel: PropTypes.bool, accountPassword: PropTypes.string, - force: PropTypes.bool, + forceReset: PropTypes.bool, }; static defaultProps = { hasCancel: true, - force: false, + forceReset: false, }; constructor(props) { @@ -118,8 +118,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent { MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo) ); - const { force } = this.props; - const phase = (backupInfo && !force) ? PHASE_MIGRATE : PHASE_CHOOSE_KEY_PASSPHRASE; + const { forceReset } = this.props; + const phase = (backupInfo && !forceReset) ? PHASE_MIGRATE : PHASE_CHOOSE_KEY_PASSPHRASE; this.setState({ phase, @@ -277,11 +277,11 @@ export default class CreateSecretStorageDialog extends React.PureComponent { const cli = MatrixClientPeg.get(); - const { force } = this.props; + const { forceReset } = this.props; try { - if (force) { - console.log("Forcing secret storage reset"); // log something so we can debug this later + if (forceReset) { + console.log("Forcing cross-signing and secret storage reset"); await cli.bootstrapCrossSigning({ authUploadDeviceSigningKeys: this._doBootstrapUIAuth, setupNewCrossSigning: true, From 13e9f7b9128b99c11970d4ca76ffd0063b085c02 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 27 Aug 2020 13:18:52 -0600 Subject: [PATCH 08/14] Update home icon --- res/css/structures/_TagPanel.scss | 13 +++++++------ res/img/element-icons/home.svg | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/res/css/structures/_TagPanel.scss b/res/css/structures/_TagPanel.scss index 2683a32dae..dc27da7102 100644 --- a/res/css/structures/_TagPanel.scss +++ b/res/css/structures/_TagPanel.scss @@ -99,11 +99,11 @@ limitations under the License. } .mx_TagTile:not(.mx_TagTile_selected_prototype) .mx_TagTile_homeIcon { - background-color: $icon-button-color; // XXX: Variable abuse + background-color: $roomheader-addroom-bg-color; border-radius: 48px; &::before { - background-color: $primary-bg-color; // light-on-grey + background-color: $roomheader-addroom-fg-color; } } @@ -116,13 +116,14 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/home.svg'); mask-position: center; mask-repeat: no-repeat; - width: 21px; - height: 21px; + mask-size: 21px; content: ''; display: inline-block; + width: 32px; + height: 32px; position: absolute; - top: calc(50% - 10.5px); - left: calc(50% - 10.5px); + top: calc(50% - 16px); + left: calc(50% - 16px); } } diff --git a/res/img/element-icons/home.svg b/res/img/element-icons/home.svg index d65812cafd..a6c15456ff 100644 --- a/res/img/element-icons/home.svg +++ b/res/img/element-icons/home.svg @@ -1,3 +1,3 @@ - + From be1de1d2952e845542b45c900d0235e2d8039114 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 27 Aug 2020 13:49:40 -0600 Subject: [PATCH 09/14] Update create room dialog copy --- .../views/dialogs/CreateRoomDialog.js | 38 ++++++++++++++++--- src/i18n/strings/en_EN.json | 8 ++-- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/components/views/dialogs/CreateRoomDialog.js b/src/components/views/dialogs/CreateRoomDialog.js index 9726c44fac..d334438d58 100644 --- a/src/components/views/dialogs/CreateRoomDialog.js +++ b/src/components/views/dialogs/CreateRoomDialog.js @@ -184,18 +184,25 @@ export default createReactClass({ const LabelledToggleSwitch = sdk.getComponent('views.elements.LabelledToggleSwitch'); const RoomAliasField = sdk.getComponent('views.elements.RoomAliasField'); - let publicPrivateLabel; let aliasField; if (this.state.isPublic) { - publicPrivateLabel = (

{_t("Set a room address to easily share your room with other people.")}

); const domain = MatrixClientPeg.get().getDomain(); aliasField = (
this._aliasFieldRef = ref} onChange={this.onAliasChange} domain={domain} value={this.state.alias} />
); - } else { - publicPrivateLabel = (

{_t("This room is private, and can only be joined by invitation.")}

); + } + + let publicPrivateLabel =

{_t( + "Private rooms can be found and joined by invitation only. Public rooms can be " + + "found and joined by anyone.", + )}

; + if (TagOrderStore.getSelectedPrototypeTag()) { + publicPrivateLabel =

{_t( + "Private rooms can be found and joined by invitation only. Public rooms can be " + + "found and joined by anyone in this community.", + )}

; } let e2eeSection; @@ -218,6 +225,19 @@ export default createReactClass({ ; } + let federateLabel = _t( + "You might enable this if the room will be only be used for collaborating with internal " + + "teams on your homeserver. This setting cannot be changed later.", + ); + if (SdkConfig.get().default_federate === false) { + // We only change the label if the default setting is different to avoid jarring text changes to the + // user. They will have read the implications of turning this off/on, so no need to rephrase for them. + federateLabel = _t( + "You might disable this if the room will be used for collaborating with external " + + "teams who have their own homeserver. This setting cannot be changed later.", + ); + } + let title = this.state.isPublic ? _t('Create a public room') : _t('Create a private room'); if (TagOrderStore.getSelectedPrototypeTag()) { const summary = GroupStore.getSummary(TagOrderStore.getSelectedPrototypeTag()); @@ -238,7 +258,15 @@ export default createReactClass({ { aliasField }
{ this.state.detailsOpen ? _t('Hide advanced') : _t('Show advanced') } - + +

{federateLabel}

diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0ec12a4d6a..b92af49fad 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1637,10 +1637,12 @@ "Community ID": "Community ID", "example": "example", "Please enter a name for the room": "Please enter a name for the room", - "Set a room address to easily share your room with other people.": "Set a room address to easily share your room with other people.", - "This room is private, and can only be joined by invitation.": "This room is private, and can only be joined by invitation.", + "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone.": "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone.", + "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone in this community.": "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone in this community.", "You can’t disable this later. Bridges & most bots won’t work yet.": "You can’t disable this later. Bridges & most bots won’t work yet.", "Enable end-to-end encryption": "Enable end-to-end encryption", + "You might enable this if the room will be only be used for collaborating with internal teams on your homeserver. This setting cannot be changed later.": "You might enable this if the room will be only be used for collaborating with internal teams on your homeserver. This setting cannot be changed later.", + "You might disable this if the room will be used for collaborating with external teams who have their own homeserver. This setting cannot be changed later.": "You might disable this if the room will be used for collaborating with external teams who have their own homeserver. This setting cannot be changed later.", "Create a public room": "Create a public room", "Create a private room": "Create a private room", "Create a room in %(communityName)s": "Create a room in %(communityName)s", @@ -1649,7 +1651,7 @@ "Make this room public": "Make this room public", "Hide advanced": "Hide advanced", "Show advanced": "Show advanced", - "Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)": "Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)", + "Block anyone not part of %(serverName)s from ever joining this room.": "Block anyone not part of %(serverName)s from ever joining this room.", "Create Room": "Create Room", "Sign out": "Sign out", "To avoid losing your chat history, you must export your room keys before logging out. You will need to go back to the newer version of %(brand)s to do this": "To avoid losing your chat history, you must export your room keys before logging out. You will need to go back to the newer version of %(brand)s to do this", From bbd343f414fec4cd1035d053c49556cf048175a3 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 27 Aug 2020 14:17:55 -0600 Subject: [PATCH 10/14] Fix clicking the background of the tag panel not clearing the filter Fixes https://github.com/vector-im/element-web/issues/12988 --- src/components/structures/TagPanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/TagPanel.js b/src/components/structures/TagPanel.js index 4acbc49d4d..40b5d04a0a 100644 --- a/src/components/structures/TagPanel.js +++ b/src/components/structures/TagPanel.js @@ -164,7 +164,7 @@ const TagPanel = createReactClass({ ); } - return
+ return
{ clearButton }
From 3c176f762ed9d20f8ffe6529ce23c5a200451308 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 27 Aug 2020 14:26:55 -0600 Subject: [PATCH 11/14] Remove disabled clear button from tag panel + dead code --- res/css/structures/_TagPanel.scss | 19 ------------------- src/components/structures/TagPanel.js | 21 --------------------- 2 files changed, 40 deletions(-) diff --git a/res/css/structures/_TagPanel.scss b/res/css/structures/_TagPanel.scss index 2683a32dae..0c8857e1ef 100644 --- a/res/css/structures/_TagPanel.scss +++ b/res/css/structures/_TagPanel.scss @@ -30,25 +30,6 @@ limitations under the License. cursor: pointer; } -.mx_TagPanel .mx_TagPanel_clearButton_container { - /* Constant height within flex mx_TagPanel */ - height: 70px; - width: 56px; - - flex: none; - - justify-content: center; - align-items: flex-start; - - display: none; -} - -.mx_TagPanel .mx_TagPanel_clearButton object { - /* Same as .mx_SearchBox padding-top */ - margin-top: 24px; - pointer-events: none; -} - .mx_TagPanel .mx_TagPanel_divider { height: 0px; width: 90%; diff --git a/src/components/structures/TagPanel.js b/src/components/structures/TagPanel.js index 40b5d04a0a..a714b126ec 100644 --- a/src/components/structures/TagPanel.js +++ b/src/components/structures/TagPanel.js @@ -95,11 +95,6 @@ const TagPanel = createReactClass({ } }, - onCreateGroupClick(ev) { - ev.stopPropagation(); - dis.dispatch({action: 'view_create_group'}); - }, - onClearFilterClick(ev) { dis.dispatch({action: 'deselect_tags'}); }, @@ -117,9 +112,7 @@ const TagPanel = createReactClass({ render() { const DNDTagTile = sdk.getComponent('elements.DNDTagTile'); - const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const ActionButton = sdk.getComponent('elements.ActionButton'); - const TintableSvg = sdk.getComponent('elements.TintableSvg'); const tags = this.state.orderedTags.map((tag, index) => { return 0; - - let clearButton; - if (itemsSelected) { - clearButton = - - ; - } - const classes = classNames('mx_TagPanel', { mx_TagPanel_items_selected: itemsSelected, }); @@ -165,9 +147,6 @@ const TagPanel = createReactClass({ } return
-
- { clearButton } -
Date: Fri, 28 Aug 2020 12:10:17 +0100 Subject: [PATCH 12/14] Add secret storage cache callback to avoid prompts This supplies a cache callback to the JS SDK so that we can be notified if a new storage key is created e.g. by resetting secret storage. This allows it to be supplied automatically in case it's needed in the same user operation, as it is when resetting both secret storage and cross-signing together. --- src/CrossSigningManager.js | 27 +++++++++++-------- .../CreateSecretStorageDialog.js | 8 +++--- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js index b15290b9c3..0353bfc5ae 100644 --- a/src/CrossSigningManager.js +++ b/src/CrossSigningManager.js @@ -69,19 +69,19 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) { if (keyInfoEntries.length > 1) { throw new Error("Multiple storage key requests not implemented"); } - const [name, info] = keyInfoEntries[0]; + const [keyId, keyInfo] = keyInfoEntries[0]; // Check the in-memory cache - if (isCachingAllowed() && secretStorageKeys[name]) { - return [name, secretStorageKeys[name]]; + if (isCachingAllowed() && secretStorageKeys[keyId]) { + return [keyId, secretStorageKeys[keyId]]; } const inputToKey = async ({ passphrase, recoveryKey }) => { if (passphrase) { return deriveKey( passphrase, - info.passphrase.salt, - info.passphrase.iterations, + keyInfo.passphrase.salt, + keyInfo.passphrase.iterations, ); } else { return decodeRecoveryKey(recoveryKey); @@ -93,10 +93,10 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) { AccessSecretStorageDialog, /* props= */ { - keyInfo: info, + keyInfo, checkPrivateKey: async (input) => { const key = await inputToKey(input); - return await MatrixClientPeg.get().checkSecretStorageKey(key, info); + return await MatrixClientPeg.get().checkSecretStorageKey(key, keyInfo); }, }, /* className= */ null, @@ -118,11 +118,15 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) { const key = await inputToKey(input); // Save to cache to avoid future prompts in the current session - if (isCachingAllowed()) { - secretStorageKeys[name] = key; - } + cacheSecretStorageKey(keyId, key); - return [name, key]; + return [keyId, key]; +} + +function cacheSecretStorageKey(keyId, key) { + if (isCachingAllowed()) { + secretStorageKeys[keyId] = key; + } } const onSecretRequested = async function({ @@ -170,6 +174,7 @@ const onSecretRequested = async function({ export const crossSigningCallbacks = { getSecretStorageKey, + cacheSecretStorageKey, onSecretRequested, }; diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index 00216e3765..0a1a0b02b3 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -282,15 +282,15 @@ export default class CreateSecretStorageDialog extends React.PureComponent { try { if (forceReset) { console.log("Forcing cross-signing and secret storage reset"); - await cli.bootstrapCrossSigning({ - authUploadDeviceSigningKeys: this._doBootstrapUIAuth, - setupNewCrossSigning: true, - }); await cli.bootstrapSecretStorage({ createSecretStorageKey: async () => this._recoveryKey, setupNewKeyBackup: true, setupNewSecretStorage: true, }); + await cli.bootstrapCrossSigning({ + authUploadDeviceSigningKeys: this._doBootstrapUIAuth, + setupNewCrossSigning: true, + }); } else { await cli.bootstrapCrossSigning({ authUploadDeviceSigningKeys: this._doBootstrapUIAuth, From f038103f97b0b9625a711e7a839420b2c7fc475c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 28 Aug 2020 09:47:36 -0600 Subject: [PATCH 13/14] Fix copy --- src/components/views/dialogs/CreateRoomDialog.js | 6 +++--- src/i18n/strings/en_EN.json | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/views/dialogs/CreateRoomDialog.js b/src/components/views/dialogs/CreateRoomDialog.js index d334438d58..4890626527 100644 --- a/src/components/views/dialogs/CreateRoomDialog.js +++ b/src/components/views/dialogs/CreateRoomDialog.js @@ -226,15 +226,15 @@ export default createReactClass({ } let federateLabel = _t( - "You might enable this if the room will be only be used for collaborating with internal " + - "teams on your homeserver. This setting cannot be changed later.", + "You might enable this if the room will only be used for collaborating with internal " + + "teams on your homeserver. This cannot be changed later.", ); if (SdkConfig.get().default_federate === false) { // We only change the label if the default setting is different to avoid jarring text changes to the // user. They will have read the implications of turning this off/on, so no need to rephrase for them. federateLabel = _t( "You might disable this if the room will be used for collaborating with external " + - "teams who have their own homeserver. This setting cannot be changed later.", + "teams who have their own homeserver. This cannot be changed later.", ); } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index b92af49fad..f65e75d2b9 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1641,8 +1641,8 @@ "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone in this community.": "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone in this community.", "You can’t disable this later. Bridges & most bots won’t work yet.": "You can’t disable this later. Bridges & most bots won’t work yet.", "Enable end-to-end encryption": "Enable end-to-end encryption", - "You might enable this if the room will be only be used for collaborating with internal teams on your homeserver. This setting cannot be changed later.": "You might enable this if the room will be only be used for collaborating with internal teams on your homeserver. This setting cannot be changed later.", - "You might disable this if the room will be used for collaborating with external teams who have their own homeserver. This setting cannot be changed later.": "You might disable this if the room will be used for collaborating with external teams who have their own homeserver. This setting cannot be changed later.", + "You might enable this if the room will only be used for collaborating with internal teams on your homeserver. This cannot be changed later.": "You might enable this if the room will only be used for collaborating with internal teams on your homeserver. This cannot be changed later.", + "You might disable this if the room will be used for collaborating with external teams who have their own homeserver. This cannot be changed later.": "You might disable this if the room will be used for collaborating with external teams who have their own homeserver. This cannot be changed later.", "Create a public room": "Create a public room", "Create a private room": "Create a private room", "Create a room in %(communityName)s": "Create a room in %(communityName)s", From b9cfa95ceb31d8333c0cb9884212821ebc797336 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 28 Aug 2020 17:06:56 +0100 Subject: [PATCH 14/14] Add display-capture to iframe allow --- src/components/views/elements/AppTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 75946f19c1..0813faee54 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -735,7 +735,7 @@ export default class AppTile extends React.Component { // Additional iframe feature pemissions // (see - https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-permissions-in-cross-origin-iframes and https://wicg.github.io/feature-policy/) - const iframeFeatures = "microphone; camera; encrypted-media; autoplay;"; + const iframeFeatures = "microphone; camera; encrypted-media; autoplay; display-capture;"; const appTileBodyClass = 'mx_AppTileBody' + (this.props.miniMode ? '_mini ' : ' ');