From 76104edeca3b8ba37d4a24903fa1e0193dad56c2 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Tue, 24 Mar 2020 21:35:17 -0500 Subject: [PATCH 001/237] Mark room as read when escape is pressed Signed-off-by: Aaron Raimist --- src/components/structures/RoomView.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 5fd5f42f78..9405a26ab2 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -560,6 +560,12 @@ export default createReactClass({ handled = true; } break; + + case Key.ESCAPE: + this._messagePanel.forgetReadMarker(); + this.jumpToLiveTimeline(); + handled = true; + break; } if (handled) { From 6095a00703cd320281a432d65b80eca9027167a9 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 8 Apr 2020 13:52:46 +0100 Subject: [PATCH 002/237] Upgrade matrix-js-sdk to 5.3.0-rc.1 --- package.json | 2 +- yarn.lock | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 616f3f541e..d610b35692 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", + "matrix-js-sdk": "5.3.0-rc.1", "minimist": "^1.2.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index 0391132786..bf43c92bde 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5689,9 +5689,10 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": - version "5.2.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/934ed37fdc90948273d7da3ec9f8728195c78a63" +matrix-js-sdk@5.3.0-rc.1: + version "5.3.0-rc.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.3.0-rc.1.tgz#9a962a0c821266e02e214591e9cbe58b102945a0" + integrity sha512-k/4xw114zk2ugAUkKDL51tN7bmddvNPYek0nttnipgnooU7HLnojRiMvTzSROkqNwic+8iRx7F2xn/hPCKGTvg== dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From 9a1ac39f495f6e3430f510bb6a98307b475435ce Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 8 Apr 2020 13:59:22 +0100 Subject: [PATCH 003/237] Prepare changelog for v2.4.0-rc.1 --- CHANGELOG.md | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6f25f1858..e9f7c0eddc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,164 @@ +Changes in [2.4.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.4.0-rc.1) (2020-04-08) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.3.1...v2.4.0-rc.1) + + * Upgrade to JS SDK to 5.3.0-rc.1 + * EventIndex: Log if we had all events in a checkpoint but are continuing. + [\#4363](https://github.com/matrix-org/matrix-react-sdk/pull/4363) + * Update from Weblate + [\#4364](https://github.com/matrix-org/matrix-react-sdk/pull/4364) + * Support deactivating your account with SSO + [\#4356](https://github.com/matrix-org/matrix-react-sdk/pull/4356) + * Add debug status for cached backup key format + [\#4359](https://github.com/matrix-org/matrix-react-sdk/pull/4359) + * Fix composer placeholder not updating + [\#4361](https://github.com/matrix-org/matrix-react-sdk/pull/4361) + * Fix sas verification buttons to match figma + [\#4358](https://github.com/matrix-org/matrix-react-sdk/pull/4358) + * Don't show fallback text for verification requests + [\#4345](https://github.com/matrix-org/matrix-react-sdk/pull/4345) + * Fix share dialog correctly + [\#4360](https://github.com/matrix-org/matrix-react-sdk/pull/4360) + * Use singular copy when only deleting one device + [\#4357](https://github.com/matrix-org/matrix-react-sdk/pull/4357) + * Deem m.sticker events as actionable for reacting + [\#4288](https://github.com/matrix-org/matrix-react-sdk/pull/4288) + * Don't show spinner over encryption setup dialogs + [\#4354](https://github.com/matrix-org/matrix-react-sdk/pull/4354) + * Support Jitsi information from client .well-known + [\#4348](https://github.com/matrix-org/matrix-react-sdk/pull/4348) + * Add new default home page fallback + [\#4350](https://github.com/matrix-org/matrix-react-sdk/pull/4350) + * Check more account data in toast listener + [\#4351](https://github.com/matrix-org/matrix-react-sdk/pull/4351) + * Don't try to send presence updates until the client is started + [\#4353](https://github.com/matrix-org/matrix-react-sdk/pull/4353) + * Fix copy button on code blocks when there is no code tag just pre + [\#4352](https://github.com/matrix-org/matrix-react-sdk/pull/4352) + * Clear sessionStorage on sign out + [\#4346](https://github.com/matrix-org/matrix-react-sdk/pull/4346) + * Re-request room keys after auth + [\#4341](https://github.com/matrix-org/matrix-react-sdk/pull/4341) + * Update emojibase for fixed emoji codepoints and Emoji 13 support + [\#4344](https://github.com/matrix-org/matrix-react-sdk/pull/4344) + * App load order tweaks for code splitting + [\#4343](https://github.com/matrix-org/matrix-react-sdk/pull/4343) + * Fix alignment of e2e icon in userinfo and expose full displayname in title + [\#4312](https://github.com/matrix-org/matrix-react-sdk/pull/4312) + * Adjust copy & UX for self-verification + [\#4342](https://github.com/matrix-org/matrix-react-sdk/pull/4342) + * QR code reciprocation + [\#4334](https://github.com/matrix-org/matrix-react-sdk/pull/4334) + * Fix Hangul typing does not work properly + [\#4339](https://github.com/matrix-org/matrix-react-sdk/pull/4339) + * Fix: dismiss setup encryption toast if cross-signing is ready + [\#4336](https://github.com/matrix-org/matrix-react-sdk/pull/4336) + * Fix read marker visibility for grouped events + [\#4340](https://github.com/matrix-org/matrix-react-sdk/pull/4340) + * Make all 'font-size's and 'line-height's rem + [\#4305](https://github.com/matrix-org/matrix-react-sdk/pull/4305) + * Fix spurious extra devices on registration + [\#4337](https://github.com/matrix-org/matrix-react-sdk/pull/4337) + * Fix the edit messager composer + [\#4333](https://github.com/matrix-org/matrix-react-sdk/pull/4333) + * Fix Room Settings Dialog Notifications tab icon + [\#4321](https://github.com/matrix-org/matrix-react-sdk/pull/4321) + * Fix various cases of React warnings by silencing them + [\#4331](https://github.com/matrix-org/matrix-react-sdk/pull/4331) + * Only apply padding to standard textual buttons (kind buttons) + [\#4332](https://github.com/matrix-org/matrix-react-sdk/pull/4332) + * Use console.log in place of console.warn for less warnings + [\#4330](https://github.com/matrix-org/matrix-react-sdk/pull/4330) + * Revert componentDidMount changes on breadcrumbs + [\#4329](https://github.com/matrix-org/matrix-react-sdk/pull/4329) + * Use new method for checking secret storage key + [\#4309](https://github.com/matrix-org/matrix-react-sdk/pull/4309) + * Label and use UNSAFE_componentWillMount to minimize warnings + [\#4315](https://github.com/matrix-org/matrix-react-sdk/pull/4315) + * Fix a number of minor code quality issues + [\#4314](https://github.com/matrix-org/matrix-react-sdk/pull/4314) + * Use componentDidMount in place of componentWillMount where possible + [\#4313](https://github.com/matrix-org/matrix-react-sdk/pull/4313) + * EventIndex: Mark the initial checkpoints for a full crawl. + [\#4325](https://github.com/matrix-org/matrix-react-sdk/pull/4325) + * Fix UserInfo e2e buttons to match Figma + [\#4320](https://github.com/matrix-org/matrix-react-sdk/pull/4320) + * Only auto-scroll to RoomTile when clicking on RoomTile or via shortcuts + [\#4316](https://github.com/matrix-org/matrix-react-sdk/pull/4316) + * Support SSO for interactive authentication + [\#4292](https://github.com/matrix-org/matrix-react-sdk/pull/4292) + * Fix /invite Slash Command + [\#4328](https://github.com/matrix-org/matrix-react-sdk/pull/4328) + * Fix jitsi popout URL + [\#4326](https://github.com/matrix-org/matrix-react-sdk/pull/4326) + * Use our own jitsi widget for the popout URL + [\#4323](https://github.com/matrix-org/matrix-react-sdk/pull/4323) + * Fix popout support for jitsi widgets + [\#4319](https://github.com/matrix-org/matrix-react-sdk/pull/4319) + * Fix: legacy verify user throwing error + [\#4318](https://github.com/matrix-org/matrix-react-sdk/pull/4318) + * Document settingDefaults + [\#3046](https://github.com/matrix-org/matrix-react-sdk/pull/3046) + * Fix Ctrl+/ for Finnish keyboard where it includes Shift + [\#4317](https://github.com/matrix-org/matrix-react-sdk/pull/4317) + * Rework SlashCommands to better expose aliases + [\#4302](https://github.com/matrix-org/matrix-react-sdk/pull/4302) + * Fix EventListSummary when RR rendering is disabled + [\#4311](https://github.com/matrix-org/matrix-react-sdk/pull/4311) + * Update link to css location. + [\#4299](https://github.com/matrix-org/matrix-react-sdk/pull/4299) + * Fix peeking keeping two timeline update mechanisms in play + [\#4310](https://github.com/matrix-org/matrix-react-sdk/pull/4310) + * Pass new secret storage key to bootstrap path + [\#4308](https://github.com/matrix-org/matrix-react-sdk/pull/4308) + * Show red shield for users that become unverified + [\#4303](https://github.com/matrix-org/matrix-react-sdk/pull/4303) + * Accessibility fixed for Event List Summary and Composer Format Bar + [\#4295](https://github.com/matrix-org/matrix-react-sdk/pull/4295) + * Support $riot: Templates for SSO/CAS urls in the welcome.html page + [\#4279](https://github.com/matrix-org/matrix-react-sdk/pull/4279) + * Added the /html command + [\#4296](https://github.com/matrix-org/matrix-react-sdk/pull/4296) + * EventIndex: Better logging on how many events are added. + [\#4301](https://github.com/matrix-org/matrix-react-sdk/pull/4301) + * Field: mark id as optional in propTypes + [\#4307](https://github.com/matrix-org/matrix-react-sdk/pull/4307) + * Fix view community link icon contrast + [\#4254](https://github.com/matrix-org/matrix-react-sdk/pull/4254) + * Remove underscore from Jitsi conference names + [\#4304](https://github.com/matrix-org/matrix-react-sdk/pull/4304) + * Refactor shield display logic; changed rules for DMs + [\#4290](https://github.com/matrix-org/matrix-react-sdk/pull/4290) + * Fix: bring back global thin scrollbars + [\#4300](https://github.com/matrix-org/matrix-react-sdk/pull/4300) + * Keyboard shortcuts: Escape cancel reply and fix Ctrl+K + [\#4297](https://github.com/matrix-org/matrix-react-sdk/pull/4297) + * Field: make id optional, generate one if not provided + [\#4298](https://github.com/matrix-org/matrix-react-sdk/pull/4298) + * Fix ugly scrollbars in TabbedView (settings), emojipicker and widgets + [\#4293](https://github.com/matrix-org/matrix-react-sdk/pull/4293) + * Rename secret storage force-reset variable to avoid confusion + [\#4274](https://github.com/matrix-org/matrix-react-sdk/pull/4274) + * Fix: can't dismiss unverified session toast when encryption hasn't been + upgraded + [\#4291](https://github.com/matrix-org/matrix-react-sdk/pull/4291) + * Blank out UserInfo avatar when changing between members + [\#4289](https://github.com/matrix-org/matrix-react-sdk/pull/4289) + * Add cancel button to verification panel + [\#4283](https://github.com/matrix-org/matrix-react-sdk/pull/4283) + * Show ongoing verification request straight away when navigating to member + [\#4284](https://github.com/matrix-org/matrix-react-sdk/pull/4284) + * Fix: allow scrolling while window is not focused & remove scrollbar hack + [\#4276](https://github.com/matrix-org/matrix-react-sdk/pull/4276) + * Show whether backup key is cached + [\#4287](https://github.com/matrix-org/matrix-react-sdk/pull/4287) + * Rename unverified session toast + [\#4285](https://github.com/matrix-org/matrix-react-sdk/pull/4285) + * Fix: pick last active DM for verification request + [\#4286](https://github.com/matrix-org/matrix-react-sdk/pull/4286) + * Fix formatBar not hidden after highlight and backspacing some text + [\#4269](https://github.com/matrix-org/matrix-react-sdk/pull/4269) + Changes in [2.3.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.3.1) (2020-04-01) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.3.0...v2.3.1) From 0d1b7b99631e8ce526fb169e02b86f805c92826b Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 8 Apr 2020 13:59:23 +0100 Subject: [PATCH 004/237] v2.4.0-rc.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d610b35692..0a9f081998 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.3.1", + "version": "2.4.0-rc.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 69382ff8e59bc01f9ce10daaedf240a02e20fc8b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Apr 2020 15:24:41 +0100 Subject: [PATCH 005/237] Fix handler to use react bubbling rather than a native global onKeyDown Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomView.js | 32 +++++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 9405a26ab2..6454136164 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -422,7 +422,7 @@ export default createReactClass({ } this.onResize(); - document.addEventListener("keydown", this.onKeyDown); + document.addEventListener("keydown", this.onNativeKeyDown); }, shouldComponentUpdate: function(nextProps, nextState) { @@ -500,7 +500,7 @@ export default createReactClass({ this.props.resizeNotifier.removeListener("middlePanelResized", this.onResize); } - document.removeEventListener("keydown", this.onKeyDown); + document.removeEventListener("keydown", this.onNativeKeyDown); // Remove RoomStore listener if (this._roomStoreToken) { @@ -542,7 +542,8 @@ export default createReactClass({ } }, - onKeyDown: function(ev) { + // we register global shortcuts here, they *must not conflict* with local shortcuts elsewhere or both will fire + onNativeKeyDown: function(ev) { let handled = false; const ctrlCmdOnly = isOnlyCtrlOrCmdKeyEvent(ev); @@ -560,11 +561,24 @@ export default createReactClass({ handled = true; } break; + } + if (handled) { + ev.stopPropagation(); + ev.preventDefault(); + } + }, + + onReactKeyDown: function(ev) { + let handled = false; + + switch (ev.key) { case Key.ESCAPE: - this._messagePanel.forgetReadMarker(); - this.jumpToLiveTimeline(); - handled = true; + if (!ev.altKey && !ev.ctrlKey && !ev.shiftKey && !ev.metaKey) { + this._messagePanel.forgetReadMarker(); + this.jumpToLiveTimeline(); + handled = true; + } break; } @@ -2030,9 +2044,13 @@ export default createReactClass({ mx_RoomView_timeline_rr_enabled: this.state.showReadReceipts, }); + const mainClasses = classNames("mx_RoomView", { + mx_RoomView_inCall: inCall, + }); + return ( -
+
Date: Wed, 15 Apr 2020 19:13:00 +0100 Subject: [PATCH 006/237] Upgrade matrix-js-sdk to 5.3.1-rc.1 --- package.json | 2 +- yarn.lock | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9acd9b4b4f..808941625e 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "5.3.0-rc.1", + "matrix-js-sdk": "5.3.1-rc.1", "minimist": "^1.2.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index c42828e461..2b55aa2ae2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5715,9 +5715,10 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": - version "5.2.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/84637c6ebd442346623bce562b441e1093d40270" +matrix-js-sdk@5.3.1-rc.1: + version "5.3.1-rc.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.3.1-rc.1.tgz#12f9434b2fc09e014371bc9a75dc2bc9bc35fe33" + integrity sha512-HP47NvGFrK4gG8ToZRurb6/pRHhJAOhixwoNT6P/FTZNZLJX4DDPY84uNR0jtmiiZXI+/wHRST0K9P6A2bgBXA== dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From e2fb96776b32cbf431f2420869e2ee89c4ebf198 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 15 Apr 2020 19:18:45 +0100 Subject: [PATCH 007/237] Prepare changelog for v2.5.0-rc.1 --- CHANGELOG.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9f7c0eddc..7586bb49eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,77 @@ +Changes in [2.5.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.1) (2020-04-15) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.4.0-rc.1...v2.5.0-rc.1) + + * Upgrade to JS SDK 5.3.1-rc.1 + * null-guard MatrixClientPeg in RoomViewStore + [\#4415](https://github.com/matrix-org/matrix-react-sdk/pull/4415) + * Fix: prevent spurious notifications from indexer + [\#4414](https://github.com/matrix-org/matrix-react-sdk/pull/4414) + * Login block on initialSync with spinners + [\#4413](https://github.com/matrix-org/matrix-react-sdk/pull/4413) + * Allow network dropdown to be scrollable and fix context menu padding calc + [\#4408](https://github.com/matrix-org/matrix-react-sdk/pull/4408) + * Remove end-to-end message info option when cross-signing is used + [\#4412](https://github.com/matrix-org/matrix-react-sdk/pull/4412) + * Minimize widgets by default + [\#4378](https://github.com/matrix-org/matrix-react-sdk/pull/4378) + * Add comments to highlight where we'll need m.widget support + [\#4380](https://github.com/matrix-org/matrix-react-sdk/pull/4380) + * Fix: dont try to enable 4S if cross-signing is disabled + [\#4407](https://github.com/matrix-org/matrix-react-sdk/pull/4407) + * Fix: don't confuse user with spinner during complete security step + [\#4406](https://github.com/matrix-org/matrix-react-sdk/pull/4406) + * Fix: avoid potential crash during certain verification paths + [\#4405](https://github.com/matrix-org/matrix-react-sdk/pull/4405) + * Add riot-desktop shortcuts for forward/back matching browsers&slack + [\#4392](https://github.com/matrix-org/matrix-react-sdk/pull/4392) + * Convert LoggedInView to an ES6 PureComponent Class & TypeScript + [\#4398](https://github.com/matrix-org/matrix-react-sdk/pull/4398) + * Fix width of MVideoBody in FilePanel + [\#4396](https://github.com/matrix-org/matrix-react-sdk/pull/4396) + * Remove unused react-addons-css-transition-group + [\#4397](https://github.com/matrix-org/matrix-react-sdk/pull/4397) + * Fix emoji tooltip flickering + [\#4395](https://github.com/matrix-org/matrix-react-sdk/pull/4395) + * Pass along key backup for bootstrap + [\#4374](https://github.com/matrix-org/matrix-react-sdk/pull/4374) + * Fix create room dialog e2ee private room setting + [\#4403](https://github.com/matrix-org/matrix-react-sdk/pull/4403) + * Sort emoji by shortcodes for autocomplete primarily for :-1 and :+1 + [\#4391](https://github.com/matrix-org/matrix-react-sdk/pull/4391) + * Fix invalid commands when figuring out whether to set isTyping + [\#4390](https://github.com/matrix-org/matrix-react-sdk/pull/4390) + * op/deop return error if trying to affect an unknown user + [\#4389](https://github.com/matrix-org/matrix-react-sdk/pull/4389) + * Composer pills respect showPillAvatar setting + [\#4384](https://github.com/matrix-org/matrix-react-sdk/pull/4384) + * Only send typing notification when composing commands which send messages + [\#4385](https://github.com/matrix-org/matrix-react-sdk/pull/4385) + * Reverse order of they match/they don't match buttons + [\#4386](https://github.com/matrix-org/matrix-react-sdk/pull/4386) + * Use singular text on 'delete sessions' button for SSO + [\#4383](https://github.com/matrix-org/matrix-react-sdk/pull/4383) + * Pass widget data through from sticker picker + [\#4377](https://github.com/matrix-org/matrix-react-sdk/pull/4377) + * Obliterate widgets when they are minimized + [\#4376](https://github.com/matrix-org/matrix-react-sdk/pull/4376) + * Fix image thumbnail width when read receipts are hidden + [\#4370](https://github.com/matrix-org/matrix-react-sdk/pull/4370) + * Add toggle for e2ee when creating private room + [\#4362](https://github.com/matrix-org/matrix-react-sdk/pull/4362) + * Fix logging for failed searches + [\#4372](https://github.com/matrix-org/matrix-react-sdk/pull/4372) + * Ensure UI is updated when cross-signing gets disabled + [\#4369](https://github.com/matrix-org/matrix-react-sdk/pull/4369) + * Retry the request for the master key from SSSS on login + [\#4371](https://github.com/matrix-org/matrix-react-sdk/pull/4371) + * Upgrade deps + [\#4365](https://github.com/matrix-org/matrix-react-sdk/pull/4365) + * App load tweaks, i18n and localStorage + [\#4367](https://github.com/matrix-org/matrix-react-sdk/pull/4367) + * Fix encoding of widget arguments + [\#4366](https://github.com/matrix-org/matrix-react-sdk/pull/4366) + Changes in [2.4.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.4.0-rc.1) (2020-04-08) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.3.1...v2.4.0-rc.1) From 6ee09cd688661be0b56310ddd43a4b5e4c9df1a3 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 15 Apr 2020 19:18:45 +0100 Subject: [PATCH 008/237] v2.5.0-rc.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 808941625e..8e1e687f4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.4.0-rc.1", + "version": "2.5.0-rc.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 6723cca48e908de4c86f5df8ef02509970bcad41 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Apr 2020 11:35:54 +0200 Subject: [PATCH 009/237] ensure twemoji font is loaded when showing SAS emojis --- src/components/views/verification/VerificationShowSas.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/components/views/verification/VerificationShowSas.js b/src/components/views/verification/VerificationShowSas.js index 0a8947f2c2..edf860c4c2 100644 --- a/src/components/views/verification/VerificationShowSas.js +++ b/src/components/views/verification/VerificationShowSas.js @@ -20,6 +20,7 @@ import { _t, _td } from '../../../languageHandler'; import {PendingActionSpinner} from "../right_panel/EncryptionInfo"; import AccessibleButton from "../elements/AccessibleButton"; import DialogButtons from "../elements/DialogButtons"; +import { fixupColorFonts } from '../../../utils/FontManager'; function capFirst(s) { return s.charAt(0).toUpperCase() + s.slice(1); @@ -44,6 +45,13 @@ export default class VerificationShowSas extends React.Component { }; } + componentWillMount() { + // As this component is also used before login (during complete security), + // also make sure we have a working emoji font to display the SAS emojis here. + // This is also done from LoggedInView. + fixupColorFonts(); + } + onMatchClick = () => { this.setState({ pending: true }); this.props.onDone(); From d17e54c1cf212edbf23c17c7ab1415161bb2fe03 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 16 Apr 2020 12:26:12 +0100 Subject: [PATCH 010/237] Use `recovery passphrase` and `recovery key` everywhere Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../keybackup/CreateKeyBackupDialog.js | 14 +++--- .../keybackup/NewRecoveryMethodDialog.js | 3 +- .../keybackup/RecoveryMethodRemovedDialog.js | 2 +- .../CreateSecretStorageDialog.js | 16 +++---- .../structures/auth/SetupEncryptionBody.js | 2 +- .../keybackup/RestoreKeyBackupDialog.js | 4 +- .../AccessSecretStorageDialog.js | 14 +++--- src/i18n/strings/en_EN.json | 47 +++++++++---------- 8 files changed, 49 insertions(+), 53 deletions(-) diff --git a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js index 3a480a2579..a07ca80918 100644 --- a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js +++ b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js @@ -272,7 +272,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { let helpText; if (this.state.zxcvbnResult) { if (this.state.zxcvbnResult.score >= PASSWORD_MIN_SCORE) { - helpText = _t("Great! This passphrase looks strong enough."); + helpText = _t("Great! This recovery passphrase looks strong enough."); } else { const suggestions = []; for (let i = 0; i < this.state.zxcvbnResult.feedback.suggestions.length; ++i) { @@ -297,7 +297,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { )}

{_t( "We'll store an encrypted copy of your keys on our server. " + - "Protect your backup with a passphrase to keep it secure.", + "Protect your backup with a recovery passphrase to keep it secure.", )}

{_t("For maximum security, this should be different from your account password.")}

@@ -307,7 +307,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { onChange={this._onPassPhraseChange} value={this.state.passPhrase} className="mx_CreateKeyBackupDialog_passPhraseInput" - placeholder={_t("Enter a passphrase...")} + placeholder={_t("Enter a recovery passphrase...")} autoFocus={true} />
@@ -364,7 +364,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return

{_t( - "Please enter your passphrase a second time to confirm.", + "Please enter your recovery passphrase a second time to confirm.", )}

@@ -373,7 +373,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { onChange={this._onPassPhraseConfirmChange} value={this.state.passPhraseConfirm} className="mx_CreateKeyBackupDialog_passPhraseInput" - placeholder={_t("Repeat your passphrase...")} + placeholder={_t("Repeat your recovery passphrase...")} autoFocus={true} />
@@ -393,7 +393,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { return

{_t( "Your recovery key is a safety net - you can use it to restore " + - "access to your encrypted messages if you forget your passphrase.", + "access to your encrypted messages if you forget your recovery passphrase.", )}

{_t( "Keep a copy of it somewhere secure, like a password manager or even a safe.", @@ -489,7 +489,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { case PHASE_PASSPHRASE: return _t('Secure your backup with a passphrase'); case PHASE_PASSPHRASE_CONFIRM: - return _t('Confirm your passphrase'); + return _t('Confirm your recovery passphrase'); case PHASE_OPTOUT_CONFIRM: return _t('Warning!'); case PHASE_SHOWKEY: diff --git a/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js b/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js index 6588ff5191..d41c8c53ef 100644 --- a/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js +++ b/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js @@ -57,8 +57,7 @@ export default class NewRecoveryMethodDialog extends React.PureComponent { ; const newMethodDetected =

{_t( - "A new recovery passphrase and key for Secure " + - "Messages have been detected.", + "A new recovery passphrase and recovery key for Secure Messages have been detected.", )}

; const hackWarning =

{_t( diff --git a/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js b/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js index c5222dafd5..95fcb96967 100644 --- a/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js +++ b/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js @@ -55,7 +55,7 @@ export default class RecoveryMethodRemovedDialog extends React.PureComponent { >

{_t( - "This session has detected that your recovery passphrase and key " + + "This session has detected that your recovery passphrase and recovery key " + "for Secure Messages have been removed.", )}

{_t( diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index d63db617d5..b83fbb0a1e 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -472,7 +472,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { let helpText; if (this.state.zxcvbnResult) { if (this.state.zxcvbnResult.score >= PASSWORD_MIN_SCORE) { - helpText = _t("Great! This passphrase looks strong enough."); + helpText = _t("Great! This recovery passphrase looks strong enough."); } else { // We take the warning from zxcvbn or failing that, the first // suggestion. In practice The first is generally the most relevant @@ -501,7 +501,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { "granting them access to encrypted messages and marking them as trusted for other users.", )}

{_t( - "Secure your encryption keys with a passphrase. For maximum security " + + "Secure your encryption keys with a recovery passphrase. For maximum security " + "this should be different to your account password:", )}

@@ -511,7 +511,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { className="mx_CreateSecretStorageDialog_passPhraseField" onChange={this._onPassPhraseChange} value={this.state.passPhrase} - label={_t("Enter a passphrase")} + label={_t("Enter a recovery passphrase")} autoFocus={true} autoComplete="new-password" /> @@ -522,7 +522,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
@@ -579,7 +579,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return

{_t( - "Enter your passphrase a second time to confirm it.", + "Enter your recovery passphrase a second time to confirm it.", )}

@@ -614,7 +614,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { return

{_t( "Your recovery key is a safety net - you can use it to restore " + - "access to your encrypted messages if you forget your passphrase.", + "access to your encrypted messages if you forget your recovery passphrase.", )}

{_t( "Keep a copy of it somewhere secure, like a password manager or even a safe.", @@ -713,7 +713,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { case PHASE_PASSPHRASE: return _t('Set up encryption'); case PHASE_PASSPHRASE_CONFIRM: - return _t('Confirm passphrase'); + return _t('Confirm recovery passphrase'); case PHASE_CONFIRM_SKIP: return _t('Are you sure?'); case PHASE_SHOWKEY: diff --git a/src/components/structures/auth/SetupEncryptionBody.js b/src/components/structures/auth/SetupEncryptionBody.js index a982957ed0..e6302a4685 100644 --- a/src/components/structures/auth/SetupEncryptionBody.js +++ b/src/components/structures/auth/SetupEncryptionBody.js @@ -116,7 +116,7 @@ export default class SetupEncryptionBody extends React.Component { "granting it access to encrypted messages.", )}

{_t( - "If you can’t access one, ", + "If you can’t access one, ", {}, { button: sub =>

{_t( - "Backup could not be decrypted with this key: " + + "Backup could not be decrypted with this recovery key: " + "please verify that you entered the correct recovery key.", )}

; @@ -291,7 +291,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { title = _t("Incorrect recovery passphrase"); content =

{_t( - "Backup could not be decrypted with this passphrase: " + + "Backup could not be decrypted with this recovery passphrase: " + "please verify that you entered the correct recovery passphrase.", )}

; diff --git a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js index e3a7d7f532..4c0c608ad6 100644 --- a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js +++ b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js @@ -119,14 +119,13 @@ export default class AccessSecretStorageDialog extends React.PureComponent { if (hasPassphrase && !this.state.forceRecoveryKey) { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); - title = _t("Enter secret storage passphrase"); + title = _t("Enter recovery passphrase"); let keyStatus; if (this.state.keyMatches === false) { keyStatus =
{"\uD83D\uDC4E "}{_t( - "Unable to access secret storage. Please verify that you " + - "entered the correct passphrase.", + "Unable to access. Please verify that you entered the correct recovery passphrase.", )}
; } else { @@ -141,7 +140,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent { )}

{_t( "Access your secure message history and your cross-signing " + - "identity for verifying other sessions by entering your passphrase.", + "identity for verifying other sessions by entering your recovery passphrase.", )}

@@ -164,7 +163,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent { /> {_t( - "If you've forgotten your passphrase you can "+ + "If you've forgotten your recovery passphrase you can "+ "use your recovery key or " + "set up new recovery options." , {}, { @@ -183,7 +182,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent { })}
; } else { - title = _t("Enter secret storage recovery key"); + title = _t("Enter recovery key"); const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); @@ -193,8 +192,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent { } else if (this.state.keyMatches === false) { keyStatus =
{"\uD83D\uDC4E "}{_t( - "Unable to access secret storage. Please verify that you " + - "entered the correct recovery key.", + "Unable to access. Please verify that you entered the correct recovery key.", )}
; } else if (this.state.recoveryKeyValid) { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 84c172ea4d..dcd24b91de 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1778,32 +1778,30 @@ "Remember my selection for this widget": "Remember my selection for this widget", "Allow": "Allow", "Deny": "Deny", - "Enter secret storage passphrase": "Enter secret storage passphrase", - "Unable to access secret storage. Please verify that you entered the correct passphrase.": "Unable to access secret storage. Please verify that you entered the correct passphrase.", + "Enter recovery passphrase": "Enter recovery passphrase", + "Unable to access. Please verify that you entered the correct recovery passphrase.": "Unable to access. Please verify that you entered the correct recovery passphrase.", "Warning: You should only access secret storage from a trusted computer.": "Warning: You should only access secret storage from a trusted computer.", - "Access your secure message history and your cross-signing identity for verifying other sessions by entering your passphrase.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your passphrase.", - "If you've forgotten your passphrase you can use your recovery key or set up new recovery options.": "If you've forgotten your passphrase you can use your recovery key or set up new recovery options.", - "Enter secret storage recovery key": "Enter secret storage recovery key", - "Unable to access secret storage. Please verify that you entered the correct recovery key.": "Unable to access secret storage. Please verify that you entered the correct recovery key.", + "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery passphrase.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery passphrase.", + "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options.": "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options.", + "Enter recovery key": "Enter recovery key", + "Unable to access. Please verify that you entered the correct recovery key.": "Unable to access. Please verify that you entered the correct recovery key.", "This looks like a valid recovery key!": "This looks like a valid recovery key!", "Not a valid recovery key": "Not a valid recovery key", "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.", "If you've forgotten your recovery key you can .": "If you've forgotten your recovery key you can .", "Unable to load backup status": "Unable to load backup status", "Recovery key mismatch": "Recovery key mismatch", - "Backup could not be decrypted with this key: please verify that you entered the correct recovery key.": "Backup could not be decrypted with this key: please verify that you entered the correct recovery key.", + "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.": "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.", "Incorrect recovery passphrase": "Incorrect recovery passphrase", - "Backup could not be decrypted with this passphrase: please verify that you entered the correct recovery passphrase.": "Backup could not be decrypted with this passphrase: please verify that you entered the correct recovery passphrase.", + "Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.": "Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.", "Unable to restore backup": "Unable to restore backup", "No backup found!": "No backup found!", "Backup restored": "Backup restored", "Failed to decrypt %(failedCount)s sessions!": "Failed to decrypt %(failedCount)s sessions!", "Restored %(sessionCount)s session keys": "Restored %(sessionCount)s session keys", - "Enter recovery passphrase": "Enter recovery passphrase", "Warning: you should only set up key backup from a trusted computer.": "Warning: you should only set up key backup from a trusted computer.", "Access your secure message history and set up secure messaging by entering your recovery passphrase.": "Access your secure message history and set up secure messaging by entering your recovery passphrase.", "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options": "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options", - "Enter recovery key": "Enter recovery key", "Warning: You should only set up key backup from a trusted computer.": "Warning: You should only set up key backup from a trusted computer.", "Access your secure message history and set up secure messaging by entering your recovery key.": "Access your secure message history and set up secure messaging by entering your recovery key.", "If you've forgotten your recovery key you can ": "If you've forgotten your recovery key you can ", @@ -2119,7 +2117,7 @@ "Registration Successful": "Registration Successful", "Create your account": "Create your account", "Use an existing session to verify this one, granting it access to encrypted messages.": "Use an existing session to verify this one, granting it access to encrypted messages.", - "If you can’t access one, ": "If you can’t access one, ", + "If you can’t access one, ": "If you can’t access one, ", "Use your other device to continue…": "Use your other device to continue…", "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.", "Your new session is now verified. Other users will see it as trusted.": "Your new session is now verified. Other users will see it as trusted.", @@ -2182,18 +2180,18 @@ "Restore": "Restore", "You'll need to authenticate with the server to confirm the upgrade.": "You'll need to authenticate with the server to confirm the upgrade.", "Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.", - "Great! This passphrase looks strong enough.": "Great! This passphrase looks strong enough.", + "Great! This recovery passphrase looks strong enough.": "Great! This recovery passphrase looks strong enough.", "Set up encryption on this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Set up encryption on this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.", - "Secure your encryption keys with a passphrase. For maximum security this should be different to your account password:": "Secure your encryption keys with a passphrase. For maximum security this should be different to your account password:", - "Enter a passphrase": "Enter a passphrase", - "Back up my encryption keys, securing them with the same passphrase": "Back up my encryption keys, securing them with the same passphrase", + "Secure your encryption keys with a recovery passphrase. For maximum security this should be different to your account password:": "Secure your encryption keys with a recovery passphrase. For maximum security this should be different to your account password:", + "Enter a recovery passphrase": "Enter a recovery passphrase", + "Back up my encryption keys, securing them with the same recovery passphrase": "Back up my encryption keys, securing them with the same recovery passphrase", "Set up with a recovery key": "Set up with a recovery key", "That matches!": "That matches!", "That doesn't match.": "That doesn't match.", "Go back to set it again.": "Go back to set it again.", - "Enter your passphrase a second time to confirm it.": "Enter your passphrase a second time to confirm it.", - "Confirm your passphrase": "Confirm your passphrase", - "Your recovery key is a safety net - you can use it to restore access to your encrypted messages if you forget your passphrase.": "Your recovery key is a safety net - you can use it to restore access to your encrypted messages if you forget your passphrase.", + "Enter your recovery passphrase a second time to confirm it.": "Enter your recovery passphrase a second time to confirm it.", + "Confirm your recovery passphrase": "Confirm your recovery passphrase", + "Your recovery key is a safety net - you can use it to restore access to your encrypted messages if you forget your recovery passphrase.": "Your recovery key is a safety net - you can use it to restore access to your encrypted messages if you forget your recovery passphrase.", "Keep a copy of it somewhere secure, like a password manager or even a safe.": "Keep a copy of it somewhere secure, like a password manager or even a safe.", "Your recovery key": "Your recovery key", "Copy": "Copy", @@ -2205,15 +2203,16 @@ "Copy it to your personal cloud storage": "Copy it to your personal cloud storage", "You can now verify your other devices, and other users to keep your chats safe.": "You can now verify your other devices, and other users to keep your chats safe.", "Upgrade your encryption": "Upgrade your encryption", + "Confirm recovery passphrase": "Confirm recovery passphrase", "Make a copy of your recovery key": "Make a copy of your recovery key", "You're done!": "You're done!", "Unable to set up secret storage": "Unable to set up secret storage", "Retry": "Retry", - "We'll store an encrypted copy of your keys on our server. Protect your backup with a passphrase to keep it secure.": "We'll store an encrypted copy of your keys on our server. Protect your backup with a passphrase to keep it secure.", + "We'll store an encrypted copy of your keys on our server. Protect your backup with a recovery passphrase to keep it secure.": "We'll store an encrypted copy of your keys on our server. Protect your backup with a recovery passphrase to keep it secure.", "For maximum security, this should be different from your account password.": "For maximum security, this should be different from your account password.", - "Enter a passphrase...": "Enter a passphrase...", - "Please enter your passphrase a second time to confirm.": "Please enter your passphrase a second time to confirm.", - "Repeat your passphrase...": "Repeat your passphrase...", + "Enter a recovery passphrase...": "Enter a recovery passphrase...", + "Please enter your recovery passphrase a second time to confirm.": "Please enter your recovery passphrase a second time to confirm.", + "Repeat your recovery passphrase...": "Repeat your recovery passphrase...", "Your keys are being backed up (the first backup could take a few minutes).": "Your keys are being backed up (the first backup could take a few minutes).", "Without setting up Secure Message Recovery, you won't be able to restore your encrypted message history if you log out or use another session.": "Without setting up Secure Message Recovery, you won't be able to restore your encrypted message history if you log out or use another session.", "Set up Secure Message Recovery": "Set up Secure Message Recovery", @@ -2227,13 +2226,13 @@ "Set up": "Set up", "Don't ask again": "Don't ask again", "New Recovery Method": "New Recovery Method", - "A new recovery passphrase and key for Secure Messages have been detected.": "A new recovery passphrase and key for Secure Messages have been detected.", + "A new recovery passphrase and recovery key for Secure Messages have been detected.": "A new recovery passphrase and recovery key for Secure Messages have been detected.", "If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.", "This session is encrypting history using the new recovery method.": "This session is encrypting history using the new recovery method.", "Go to Settings": "Go to Settings", "Set up Secure Messages": "Set up Secure Messages", "Recovery Method Removed": "Recovery Method Removed", - "This session has detected that your recovery passphrase and key for Secure Messages have been removed.": "This session has detected that your recovery passphrase and key for Secure Messages have been removed.", + "This session has detected that your recovery passphrase and recovery key for Secure Messages have been removed.": "This session has detected that your recovery passphrase and recovery key for Secure Messages have been removed.", "If you did this accidentally, you can setup Secure Messages on this session which will re-encrypt this session's message history with a new recovery method.": "If you did this accidentally, you can setup Secure Messages on this session which will re-encrypt this session's message history with a new recovery method.", "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.", "If disabled, messages from encrypted rooms won't appear in search results.": "If disabled, messages from encrypted rooms won't appear in search results.", From 498ac2e0fcad12a4f3343f3bfd4fcec065c018a6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 16 Apr 2020 12:52:35 +0100 Subject: [PATCH 011/237] Copy tweaks with Nad Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/CrossSigningManager.js | 2 +- .../views/dialogs/keybackup/CreateKeyBackupDialog.js | 2 +- .../dialogs/keybackup/NewRecoveryMethodDialog.js | 2 +- .../dialogs/keybackup/RecoveryMethodRemovedDialog.js | 2 +- .../secretstorage/AccessSecretStorageDialog.js | 6 ++---- src/i18n/strings/en_EN.json | 12 ++++++------ src/settings/Settings.js | 2 +- 7 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js index 07ec776bd1..c37d0f8bf5 100644 --- a/src/CrossSigningManager.js +++ b/src/CrossSigningManager.js @@ -51,7 +51,7 @@ async function confirmToDismiss(name) { } else if (name === "m.cross_signing.self_signing") { description = _t("If you cancel now, you won't complete verifying your other session."); } else { - description = _t("If you cancel now, you won't complete your secret storage operation."); + description = _t("If you cancel now, you won't complete your operation."); } const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); diff --git a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js index a07ca80918..e7a2c8c859 100644 --- a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js +++ b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js @@ -297,7 +297,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { )}

{_t( "We'll store an encrypted copy of your keys on our server. " + - "Protect your backup with a recovery passphrase to keep it secure.", + "Secure your backup with a recovery passphrase.", )}

{_t("For maximum security, this should be different from your account password.")}

diff --git a/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js b/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js index d41c8c53ef..9e2264a960 100644 --- a/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js +++ b/src/async-components/views/dialogs/keybackup/NewRecoveryMethodDialog.js @@ -57,7 +57,7 @@ export default class NewRecoveryMethodDialog extends React.PureComponent { ; const newMethodDetected =

{_t( - "A new recovery passphrase and recovery key for Secure Messages have been detected.", + "A new recovery passphrase and key for Secure Messages have been detected.", )}

; const hackWarning =

{_t( diff --git a/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js b/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js index 95fcb96967..c5222dafd5 100644 --- a/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js +++ b/src/async-components/views/dialogs/keybackup/RecoveryMethodRemovedDialog.js @@ -55,7 +55,7 @@ export default class RecoveryMethodRemovedDialog extends React.PureComponent { >

{_t( - "This session has detected that your recovery passphrase and recovery key " + + "This session has detected that your recovery passphrase and key " + "for Secure Messages have been removed.", )}

{_t( diff --git a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js index 4c0c608ad6..f2e7b7e704 100644 --- a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js +++ b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js @@ -134,8 +134,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent { content =

{_t( - "Warning: You should only access secret storage " + - "from a trusted computer.", {}, + "Warning: You should only do this on a trusted computer.", {}, { b: sub => {sub} }, )}

{_t( @@ -207,8 +206,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent { content =

{_t( - "Warning: You should only access secret storage " + - "from a trusted computer.", {}, + "Warning: You should only do this on a trusted computer.", {}, { b: sub => {sub} }, )}

{_t( diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index dcd24b91de..4ee910a1b6 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -70,7 +70,7 @@ "Failure to create room": "Failure to create room", "If you cancel now, you won't complete verifying the other user.": "If you cancel now, you won't complete verifying the other user.", "If you cancel now, you won't complete verifying your other session.": "If you cancel now, you won't complete verifying your other session.", - "If you cancel now, you won't complete your secret storage operation.": "If you cancel now, you won't complete your secret storage operation.", + "If you cancel now, you won't complete your operation.": "If you cancel now, you won't complete your operation.", "Cancel entering passphrase?": "Cancel entering passphrase?", "Enter passphrase": "Enter passphrase", "Cancel": "Cancel", @@ -444,7 +444,7 @@ "Send read receipts for messages (requires compatible homeserver to disable)": "Send read receipts for messages (requires compatible homeserver to disable)", "Show previews/thumbnails for images": "Show previews/thumbnails for images", "Enable message search in encrypted rooms": "Enable message search in encrypted rooms", - "Keep secret storage passphrase in memory for this session": "Keep secret storage passphrase in memory for this session", + "Keep recovery passphrase in memory for this session": "Keep recovery passphrase in memory for this session", "How fast should messages be downloaded.": "How fast should messages be downloaded.", "Manually verify all remote sessions": "Manually verify all remote sessions", "Collecting app version information": "Collecting app version information", @@ -1780,7 +1780,7 @@ "Deny": "Deny", "Enter recovery passphrase": "Enter recovery passphrase", "Unable to access. Please verify that you entered the correct recovery passphrase.": "Unable to access. Please verify that you entered the correct recovery passphrase.", - "Warning: You should only access secret storage from a trusted computer.": "Warning: You should only access secret storage from a trusted computer.", + "Warning: You should only do this on a trusted computer.": "Warning: You should only do this on a trusted computer.", "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery passphrase.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery passphrase.", "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options.": "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options.", "Enter recovery key": "Enter recovery key", @@ -2208,7 +2208,7 @@ "You're done!": "You're done!", "Unable to set up secret storage": "Unable to set up secret storage", "Retry": "Retry", - "We'll store an encrypted copy of your keys on our server. Protect your backup with a recovery passphrase to keep it secure.": "We'll store an encrypted copy of your keys on our server. Protect your backup with a recovery passphrase to keep it secure.", + "We'll store an encrypted copy of your keys on our server. Secure your backup with a recovery passphrase.": "We'll store an encrypted copy of your keys on our server. Secure your backup with a recovery passphrase.", "For maximum security, this should be different from your account password.": "For maximum security, this should be different from your account password.", "Enter a recovery passphrase...": "Enter a recovery passphrase...", "Please enter your recovery passphrase a second time to confirm.": "Please enter your recovery passphrase a second time to confirm.", @@ -2226,13 +2226,13 @@ "Set up": "Set up", "Don't ask again": "Don't ask again", "New Recovery Method": "New Recovery Method", - "A new recovery passphrase and recovery key for Secure Messages have been detected.": "A new recovery passphrase and recovery key for Secure Messages have been detected.", + "A new recovery passphrase and key for Secure Messages have been detected.": "A new recovery passphrase and key for Secure Messages have been detected.", "If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.", "This session is encrypting history using the new recovery method.": "This session is encrypting history using the new recovery method.", "Go to Settings": "Go to Settings", "Set up Secure Messages": "Set up Secure Messages", "Recovery Method Removed": "Recovery Method Removed", - "This session has detected that your recovery passphrase and recovery key for Secure Messages have been removed.": "This session has detected that your recovery passphrase and recovery key for Secure Messages have been removed.", + "This session has detected that your recovery passphrase and key for Secure Messages have been removed.": "This session has detected that your recovery passphrase and key for Secure Messages have been removed.", "If you did this accidentally, you can setup Secure Messages on this session which will re-encrypt this session's message history with a new recovery method.": "If you did this accidentally, you can setup Secure Messages on this session which will re-encrypt this session's message history with a new recovery method.", "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.", "If disabled, messages from encrypted rooms won't appear in search results.": "If disabled, messages from encrypted rooms won't appear in search results.", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 0d72017878..317508ca86 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -516,7 +516,7 @@ export const SETTINGS = { }, "keepSecretStoragePassphraseForSession": { supportedLevels: ['device', 'config'], - displayName: _td("Keep secret storage passphrase in memory for this session"), + displayName: _td("Keep recovery passphrase in memory for this session"), default: false, }, "crawlerSleepTime": { From 7236397e5fa9804a195519d45dad872b1316fd1a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 16 Apr 2020 13:23:01 +0100 Subject: [PATCH 012/237] Replace `Verify this session` and `Complete security` Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/auth/CompleteSecurity.js | 12 ++++++------ .../views/dialogs/VerificationRequestDialog.js | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/structures/auth/CompleteSecurity.js b/src/components/structures/auth/CompleteSecurity.js index 06cece0af2..3ef3140298 100644 --- a/src/components/structures/auth/CompleteSecurity.js +++ b/src/components/structures/auth/CompleteSecurity.js @@ -59,17 +59,17 @@ export default class CompleteSecurity extends React.Component { let title; if (phase === PHASE_INTRO) { - icon = ; - title = _t("Complete security"); + icon = ; + title = _t("Verify session"); } else if (phase === PHASE_DONE) { - icon = ; + icon = ; title = _t("Session verified"); } else if (phase === PHASE_CONFIRM_SKIP) { - icon = ; + icon = ; title = _t("Are you sure?"); } else if (phase === PHASE_BUSY) { - icon = ; - title = _t("Complete security"); + icon = ; + title = _t("Verify session"); } else { throw new Error(`Unknown phase ${phase}`); } diff --git a/src/components/views/dialogs/VerificationRequestDialog.js b/src/components/views/dialogs/VerificationRequestDialog.js index 7ff2cb8f50..dcb9168bda 100644 --- a/src/components/views/dialogs/VerificationRequestDialog.js +++ b/src/components/views/dialogs/VerificationRequestDialog.js @@ -48,7 +48,7 @@ export default class VerificationRequestDialog extends React.Component { const member = this.props.member || otherUserId && MatrixClientPeg.get().getUser(otherUserId); const title = request && request.isSelfVerification ? - _t("Verify this session") : _t("Verification Request"); + _t("Verify session") : _t("Verification Request"); return Date: Thu, 16 Apr 2020 13:28:12 +0100 Subject: [PATCH 013/237] further tweaks by Matthew Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/auth/CompleteSecurity.js | 4 ++-- src/components/views/dialogs/VerificationRequestDialog.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/structures/auth/CompleteSecurity.js b/src/components/structures/auth/CompleteSecurity.js index 3ef3140298..95128c0be9 100644 --- a/src/components/structures/auth/CompleteSecurity.js +++ b/src/components/structures/auth/CompleteSecurity.js @@ -60,7 +60,7 @@ export default class CompleteSecurity extends React.Component { if (phase === PHASE_INTRO) { icon = ; - title = _t("Verify session"); + title = _t("Verify this session"); } else if (phase === PHASE_DONE) { icon = ; title = _t("Session verified"); @@ -69,7 +69,7 @@ export default class CompleteSecurity extends React.Component { title = _t("Are you sure?"); } else if (phase === PHASE_BUSY) { icon = ; - title = _t("Verify session"); + title = _t("Verify this session"); } else { throw new Error(`Unknown phase ${phase}`); } diff --git a/src/components/views/dialogs/VerificationRequestDialog.js b/src/components/views/dialogs/VerificationRequestDialog.js index dcb9168bda..3a6e9a2d10 100644 --- a/src/components/views/dialogs/VerificationRequestDialog.js +++ b/src/components/views/dialogs/VerificationRequestDialog.js @@ -48,7 +48,7 @@ export default class VerificationRequestDialog extends React.Component { const member = this.props.member || otherUserId && MatrixClientPeg.get().getUser(otherUserId); const title = request && request.isSelfVerification ? - _t("Verify session") : _t("Verification Request"); + _t("Verify other session") : _t("Verification Request"); return Date: Thu, 16 Apr 2020 13:34:18 +0100 Subject: [PATCH 014/237] update Create SSSS Dialog copy Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../dialogs/secretstorage/CreateSecretStorageDialog.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index b83fbb0a1e..c8551149dc 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -497,12 +497,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent { return

{_t( - "Set up encryption on this session to allow it to verify other sessions, " + - "granting them access to encrypted messages and marking them as trusted for other users.", - )}

-

{_t( - "Secure your encryption keys with a recovery passphrase. For maximum security " + - "this should be different to your account password:", + "Set a recovery passphrase to secure encrypted information and recover it if you log out. " + + "This should be different to your account password:", )}

@@ -522,7 +518,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
From 84e8e226162fe948602f566d2c72452b0668f59f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 16 Apr 2020 13:48:52 +0100 Subject: [PATCH 015/237] i18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 4ee910a1b6..ed1fbf6831 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1772,6 +1772,7 @@ "Upload %(count)s other files|one": "Upload %(count)s other file", "Cancel All": "Cancel All", "Upload Error": "Upload Error", + "Verify other session": "Verify other session", "Verification Request": "Verification Request", "A widget would like to verify your identity": "A widget would like to verify your identity", "A widget located at %(widgetUrl)s would like to verify your identity. By allowing this, the widget will be able to verify your user ID, but not perform actions as you.": "A widget located at %(widgetUrl)s would like to verify your identity. By allowing this, the widget will be able to verify your user ID, but not perform actions as you.", @@ -2062,7 +2063,6 @@ "Uploading %(filename)s and %(count)s others|zero": "Uploading %(filename)s", "Uploading %(filename)s and %(count)s others|one": "Uploading %(filename)s and %(count)s other", "Could not load user profile": "Could not load user profile", - "Complete security": "Complete security", "Session verified": "Session verified", "Failed to send email": "Failed to send email", "The email address linked to your account must be entered.": "The email address linked to your account must be entered.", @@ -2181,10 +2181,9 @@ "You'll need to authenticate with the server to confirm the upgrade.": "You'll need to authenticate with the server to confirm the upgrade.", "Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.", "Great! This recovery passphrase looks strong enough.": "Great! This recovery passphrase looks strong enough.", - "Set up encryption on this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Set up encryption on this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.", - "Secure your encryption keys with a recovery passphrase. For maximum security this should be different to your account password:": "Secure your encryption keys with a recovery passphrase. For maximum security this should be different to your account password:", + "Set a recovery passphrase to secure encrypted information and recover it if you log out. This should be different to your account password:": "Set a recovery passphrase to secure encrypted information and recover it if you log out. This should be different to your account password:", "Enter a recovery passphrase": "Enter a recovery passphrase", - "Back up my encryption keys, securing them with the same recovery passphrase": "Back up my encryption keys, securing them with the same recovery passphrase", + "Back up encryption keys": "Back up encryption keys", "Set up with a recovery key": "Set up with a recovery key", "That matches!": "That matches!", "That doesn't match.": "That doesn't match.", From 14910c6e8077b4cfb3d5b2110e38943182532713 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 16 Apr 2020 14:02:32 +0100 Subject: [PATCH 016/237] iterate copy some more Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../views/dialogs/secretstorage/CreateSecretStorageDialog.js | 2 +- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index c8551149dc..65784c49ec 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -518,7 +518,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index ed1fbf6831..cf02e51608 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2183,7 +2183,7 @@ "Great! This recovery passphrase looks strong enough.": "Great! This recovery passphrase looks strong enough.", "Set a recovery passphrase to secure encrypted information and recover it if you log out. This should be different to your account password:": "Set a recovery passphrase to secure encrypted information and recover it if you log out. This should be different to your account password:", "Enter a recovery passphrase": "Enter a recovery passphrase", - "Back up encryption keys": "Back up encryption keys", + "Back up encrypted message keys": "Back up encrypted message keys", "Set up with a recovery key": "Set up with a recovery key", "That matches!": "That matches!", "That doesn't match.": "That doesn't match.", From d4b15da70af793224785d5bce8e8af3fc3789b34 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 16 Apr 2020 14:09:41 +0100 Subject: [PATCH 017/237] Fixxy Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../dialogs/secretstorage/AccessSecretStorageDialog.js | 6 ++++-- src/i18n/strings/en_EN.json | 4 ++-- .../views/dialogs/AccessSecretStorageDialog-test.js | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js index f2e7b7e704..7d7edffcbf 100644 --- a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js +++ b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js @@ -125,7 +125,8 @@ export default class AccessSecretStorageDialog extends React.PureComponent { if (this.state.keyMatches === false) { keyStatus =
{"\uD83D\uDC4E "}{_t( - "Unable to access. Please verify that you entered the correct recovery passphrase.", + "Unable to access secret storage. " + + "Please verify that you entered the correct recovery passphrase.", )}
; } else { @@ -191,7 +192,8 @@ export default class AccessSecretStorageDialog extends React.PureComponent { } else if (this.state.keyMatches === false) { keyStatus =
{"\uD83D\uDC4E "}{_t( - "Unable to access. Please verify that you entered the correct recovery key.", + "Unable to access secret storage. " + + "Please verify that you entered the correct recovery key.", )}
; } else if (this.state.recoveryKeyValid) { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index cf02e51608..54da81e1ff 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1780,12 +1780,12 @@ "Allow": "Allow", "Deny": "Deny", "Enter recovery passphrase": "Enter recovery passphrase", - "Unable to access. Please verify that you entered the correct recovery passphrase.": "Unable to access. Please verify that you entered the correct recovery passphrase.", + "Unable to access secret storage. Please verify that you entered the correct recovery passphrase.": "Unable to access secret storage. Please verify that you entered the correct recovery passphrase.", "Warning: You should only do this on a trusted computer.": "Warning: You should only do this on a trusted computer.", "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery passphrase.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery passphrase.", "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options.": "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options.", "Enter recovery key": "Enter recovery key", - "Unable to access. Please verify that you entered the correct recovery key.": "Unable to access. Please verify that you entered the correct recovery key.", + "Unable to access secret storage. Please verify that you entered the correct recovery key.": "Unable to access secret storage. Please verify that you entered the correct recovery key.", "This looks like a valid recovery key!": "This looks like a valid recovery key!", "Not a valid recovery key": "Not a valid recovery key", "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.", diff --git a/test/components/views/dialogs/AccessSecretStorageDialog-test.js b/test/components/views/dialogs/AccessSecretStorageDialog-test.js index 30512ca4dd..c754a4b607 100644 --- a/test/components/views/dialogs/AccessSecretStorageDialog-test.js +++ b/test/components/views/dialogs/AccessSecretStorageDialog-test.js @@ -100,7 +100,7 @@ describe("AccessSecretStorageDialog", function() { }); expect(notification.props.children).toEqual( ["\uD83D\uDC4E ", "Unable to access secret storage. Please verify that you " + - "entered the correct passphrase."]); + "entered the correct recovery passphrase."]); done(); }); }); From 7593c8273bc1e5ebf751d45071f00d7175acdc94 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 16 Apr 2020 14:55:43 +0100 Subject: [PATCH 018/237] update PHASE_PASSPHRASE copy Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../views/dialogs/keybackup/CreateKeyBackupDialog.js | 2 +- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js index e7a2c8c859..cec84e98d1 100644 --- a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js +++ b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js @@ -487,7 +487,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { _titleForPhase(phase) { switch (phase) { case PHASE_PASSPHRASE: - return _t('Secure your backup with a passphrase'); + return _t('Secure your backup with a recovery passphrase'); case PHASE_PASSPHRASE_CONFIRM: return _t('Confirm your recovery passphrase'); case PHASE_OPTOUT_CONFIRM: diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 54da81e1ff..a291065145 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2215,7 +2215,7 @@ "Your keys are being backed up (the first backup could take a few minutes).": "Your keys are being backed up (the first backup could take a few minutes).", "Without setting up Secure Message Recovery, you won't be able to restore your encrypted message history if you log out or use another session.": "Without setting up Secure Message Recovery, you won't be able to restore your encrypted message history if you log out or use another session.", "Set up Secure Message Recovery": "Set up Secure Message Recovery", - "Secure your backup with a passphrase": "Secure your backup with a passphrase", + "Secure your backup with a recovery passphrase": "Secure your backup with a recovery passphrase", "Starting backup...": "Starting backup...", "Success!": "Success!", "Create key backup": "Create key backup", From 2d395d8dd1c8b98912a7b0f0582d8e23fc01aa85 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 15 Apr 2020 13:18:42 -0600 Subject: [PATCH 019/237] Convert cross-signing feature flag to setting This is intended as a temporary measure until we're comfortable with removing the flag entirely. --- src/DeviceListener.js | 2 +- src/KeyRequestHandler.js | 4 ++-- .../views/dialogs/keybackup/CreateKeyBackupDialog.js | 2 +- src/components/structures/MatrixChat.js | 8 ++++---- src/components/structures/RightPanel.js | 4 ++-- src/components/structures/RoomView.js | 2 +- src/components/views/dialogs/CreateRoomDialog.js | 4 ++-- src/components/views/dialogs/DeviceVerifyDialog.js | 2 +- src/components/views/dialogs/InviteDialog.js | 2 +- src/components/views/messages/MessageActionBar.js | 2 +- src/components/views/right_panel/UserInfo.js | 10 +++++----- src/components/views/rooms/E2EIcon.js | 4 ++-- src/components/views/rooms/EventTile.js | 2 +- src/components/views/rooms/MemberTile.js | 2 +- src/components/views/rooms/MessageComposer.js | 2 +- src/components/views/rooms/RoomBreadcrumbs.js | 2 +- src/components/views/rooms/RoomHeader.js | 2 +- src/components/views/rooms/RoomTile.js | 6 +++--- src/components/views/settings/KeyBackupPanel.js | 2 +- .../views/settings/tabs/user/LabsUserSettingsTab.js | 1 + .../settings/tabs/user/SecurityUserSettingsTab.js | 2 +- src/createRoom.js | 2 +- src/settings/Settings.js | 4 ++-- src/verification.js | 2 +- 24 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 21c844e11c..3201e4af45 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -124,7 +124,7 @@ export default class DeviceListener { const cli = MatrixClientPeg.get(); if ( - !SettingsStore.isFeatureEnabled("feature_cross_signing") || + !SettingsStore.getValue("feature_cross_signing") || !await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing") ) return; diff --git a/src/KeyRequestHandler.js b/src/KeyRequestHandler.js index 30f3b7d50e..ceaff0c54d 100644 --- a/src/KeyRequestHandler.js +++ b/src/KeyRequestHandler.js @@ -35,7 +35,7 @@ export default class KeyRequestHandler { handleKeyRequest(keyRequest) { // Ignore own device key requests if cross-signing lab enabled - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { return; } @@ -70,7 +70,7 @@ export default class KeyRequestHandler { handleKeyRequestCancellation(cancellation) { // Ignore own device key requests if cross-signing lab enabled - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { return; } diff --git a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js index cec84e98d1..ed31176186 100644 --- a/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js +++ b/src/async-components/views/dialogs/keybackup/CreateKeyBackupDialog.js @@ -77,7 +77,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { async componentDidMount() { const cli = MatrixClientPeg.get(); const secureSecretStorage = ( - SettingsStore.isFeatureEnabled("feature_cross_signing") && + SettingsStore.getValue("feature_cross_signing") && await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing") ); this.setState({ secureSecretStorage }); diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 519b39d436..1293ccc7e9 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1506,7 +1506,7 @@ export default createReactClass({ }); cli.on("crypto.verification.request", request => { - const isFlagOn = SettingsStore.isFeatureEnabled("feature_cross_signing"); + const isFlagOn = SettingsStore.getValue("feature_cross_signing"); if (!isFlagOn && !request.channel.deviceId) { request.cancel({code: "m.invalid_message", reason: "This client has cross-signing disabled"}); @@ -1556,7 +1556,7 @@ export default createReactClass({ // changing colour. More advanced behaviour will come once // we implement more settings. cli.setGlobalErrorOnUnknownDevices( - !SettingsStore.isFeatureEnabled("feature_cross_signing"), + !SettingsStore.getValue("feature_cross_signing"), ); } }, @@ -1921,10 +1921,10 @@ export default createReactClass({ if (masterKeyInStorage) { // Auto-enable cross-signing for the new session when key found in // secret storage. - SettingsStore.setFeatureEnabled("feature_cross_signing", true); + SettingsStore.setValue("feature_cross_signing", null, SettingLevel.DEVICE, true); this.setStateForNewView({ view: VIEWS.COMPLETE_SECURITY }); } else if ( - SettingsStore.isFeatureEnabled("feature_cross_signing") && + SettingsStore.getValue("feature_cross_signing") && await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing") ) { // This will only work if the feature is set to 'enable' in the config, diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index 3c97d2f4ae..f5bdfdf40d 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -219,7 +219,7 @@ export default class RightPanel extends React.Component { break; case RIGHT_PANEL_PHASES.RoomMemberInfo: case RIGHT_PANEL_PHASES.EncryptionPanel: - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { const onClose = () => { dis.dispatch({ action: "view_user", @@ -246,7 +246,7 @@ export default class RightPanel extends React.Component { panel = ; break; case RIGHT_PANEL_PHASES.GroupMemberInfo: - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { const onClose = () => { dis.dispatch({ action: "view_user", diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 78bd34bf7f..179e0aa2e9 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -822,7 +822,7 @@ export default createReactClass({ }); return; } - if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (!SettingsStore.getValue("feature_cross_signing")) { room.hasUnverifiedDevices().then((hasUnverifiedDevices) => { this.setState({ e2eStatus: hasUnverifiedDevices ? "warning" : "verified", diff --git a/src/components/views/dialogs/CreateRoomDialog.js b/src/components/views/dialogs/CreateRoomDialog.js index f18e28b85e..fa8c7dd30e 100644 --- a/src/components/views/dialogs/CreateRoomDialog.js +++ b/src/components/views/dialogs/CreateRoomDialog.js @@ -65,7 +65,7 @@ export default createReactClass({ createOpts.creation_content = {'m.federate': false}; } - if (!this.state.isPublic && SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (!this.state.isPublic && SettingsStore.getValue("feature_cross_signing")) { opts.encryption = this.state.isEncrypted; } @@ -192,7 +192,7 @@ export default createReactClass({ } let e2eeSection; - if (!this.state.isPublic && SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (!this.state.isPublic && SettingsStore.getValue("feature_cross_signing")) { e2eeSection =

{ _t("You can’t disable this later. Bridges & most bots won’t work yet.") }

diff --git a/src/components/views/dialogs/DeviceVerifyDialog.js b/src/components/views/dialogs/DeviceVerifyDialog.js index 39e391269c..a3f9430476 100644 --- a/src/components/views/dialogs/DeviceVerifyDialog.js +++ b/src/components/views/dialogs/DeviceVerifyDialog.js @@ -131,7 +131,7 @@ export default class DeviceVerifyDialog extends React.Component { } else { this._verifier = request.verifier; } - } else if (verifyingOwnDevice && SettingsStore.isFeatureEnabled("feature_cross_signing")) { + } else if (verifyingOwnDevice && SettingsStore.getValue("feature_cross_signing")) { this._request = await client.requestVerification(this.props.userId, [ verificationMethods.SAS, SHOW_QR_CODE_METHOD, diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index f0d5443cac..a46fa0df07 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -574,7 +574,7 @@ export default class InviteDialog extends React.PureComponent { const createRoomOptions = {inlineErrors: true}; - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { // Check whether all users have uploaded device keys before. // If so, enable encryption in the new room. const client = MatrixClientPeg.get(); diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js index 5516ff2146..0cde90e417 100644 --- a/src/components/views/messages/MessageActionBar.js +++ b/src/components/views/messages/MessageActionBar.js @@ -49,7 +49,7 @@ const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFo }; let e2eInfoCallback = null; - if (mxEvent.isEncrypted() && !SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (mxEvent.isEncrypted() && !SettingsStore.getValue("feature_cross_signing")) { e2eInfoCallback = onCryptoClick; } diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index abe54b355e..862e4f7897 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -63,7 +63,7 @@ const _disambiguateDevices = (devices) => { }; export const getE2EStatus = (cli, userId, devices) => { - if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (!SettingsStore.getValue("feature_cross_signing")) { const hasUnverifiedDevice = devices.some((device) => device.isUnverified()); return hasUnverifiedDevice ? "warning" : "verified"; } @@ -111,7 +111,7 @@ async function openDMForUser(matrixClient, userId) { dmUserId: userId, }; - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { // Check whether all users have uploaded device keys before. // If so, enable encryption in the new room. const usersToDevicesMap = await matrixClient.downloadKeys([userId]); @@ -166,7 +166,7 @@ function DeviceItem({userId, device}) { // cross-signing so that other users can then safely trust you. // For other people's devices, the more general verified check that // includes locally verified devices can be used. - const isVerified = (isMe && SettingsStore.isFeatureEnabled("feature_cross_signing")) ? + const isVerified = (isMe && SettingsStore.getValue("feature_cross_signing")) ? deviceTrust.isCrossSigningVerified() : deviceTrust.isVerified(); @@ -237,7 +237,7 @@ function DevicesSection({devices, userId, loading}) { // cross-signing so that other users can then safely trust you. // For other people's devices, the more general verified check that // includes locally verified devices can be used. - const isVerified = (isMe && SettingsStore.isFeatureEnabled("feature_cross_signing")) ? + const isVerified = (isMe && SettingsStore.getValue("feature_cross_signing")) ? deviceTrust.isCrossSigningVerified() : deviceTrust.isVerified(); @@ -1298,7 +1298,7 @@ const BasicUserInfo = ({room, member, groupId, devices, isRoomEncrypted}) => { const userTrust = cli.checkUserTrust(member.userId); const userVerified = userTrust.isCrossSigningVerified(); const isMe = member.userId === cli.getUserId(); - const canVerify = SettingsStore.isFeatureEnabled("feature_cross_signing") && + const canVerify = SettingsStore.getValue("feature_cross_signing") && homeserverSupportsCrossSigning && !userVerified && !isMe; const setUpdating = (updating) => { diff --git a/src/components/views/rooms/E2EIcon.js b/src/components/views/rooms/E2EIcon.js index a2c99fad99..9189cfdf26 100644 --- a/src/components/views/rooms/E2EIcon.js +++ b/src/components/views/rooms/E2EIcon.js @@ -20,7 +20,7 @@ import PropTypes from "prop-types"; import classNames from 'classnames'; import {_t, _td} from '../../../languageHandler'; -import {useFeatureEnabled} from "../../../hooks/useSettings"; +import {useFeatureEnabled, useSettingValue} from "../../../hooks/useSettings"; import AccessibleButton from "../elements/AccessibleButton"; import Tooltip from "../elements/Tooltip"; @@ -62,7 +62,7 @@ const E2EIcon = ({isUser, status, className, size, onClick, hideTooltip}) => { }, className); let e2eTitle; - const crossSigning = useFeatureEnabled("feature_cross_signing"); + const crossSigning = useSettingValue("feature_cross_signing"); if (crossSigning && isUser) { e2eTitle = crossSigningUserTitles[status]; } else if (crossSigning && !isUser) { diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 75fbe5caa3..f67877373e 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -323,7 +323,7 @@ export default createReactClass({ // If cross-signing is off, the old behaviour is to scream at the user // as if they've done something wrong, which they haven't - if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (!SettingsStore.getValue("feature_cross_signing")) { this.setState({ verified: E2E_STATE.WARNING, }, this.props.onHeightChanged); diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.js index bf2a1bee23..d830624f8a 100644 --- a/src/components/views/rooms/MemberTile.js +++ b/src/components/views/rooms/MemberTile.js @@ -56,7 +56,7 @@ export default createReactClass({ } } - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { const { roomId } = this.props.member; if (roomId) { const isRoomEncrypted = cli.isRoomEncrypted(roomId); diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index c86bcb2ff0..4749742a7d 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -270,7 +270,7 @@ export default class MessageComposer extends React.Component { } renderPlaceholderText() { - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { if (this.state.isQuoting) { if (this.props.e2eStatus) { return _t('Send an encrypted reply…'); diff --git a/src/components/views/rooms/RoomBreadcrumbs.js b/src/components/views/rooms/RoomBreadcrumbs.js index 1d433c9a40..09228c454b 100644 --- a/src/components/views/rooms/RoomBreadcrumbs.js +++ b/src/components/views/rooms/RoomBreadcrumbs.js @@ -364,7 +364,7 @@ export default class RoomBreadcrumbs extends React.Component { } let dmIndicator; - if (this._isDmRoom(r.room) && !SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (this._isDmRoom(r.room) && !SettingsStore.getValue("feature_cross_signing")) { dmIndicator = ; } diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index d264b087a0..a34ade365b 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -155,7 +155,7 @@ export default createReactClass({ if (!cli.isRoomEncrypted(this.props.room.roomId)) { return; } - if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (!SettingsStore.getValue("feature_cross_signing")) { return; } @@ -488,7 +488,7 @@ export default createReactClass({ let dmOnline; /* Post-cross-signing we don't show DM indicators at all, instead relying on user context to let them know when that is. */ - if (dmUserId && !SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (dmUserId && !SettingsStore.getValue("feature_cross_signing")) { dmIndicator = ; } diff --git a/src/components/views/settings/KeyBackupPanel.js b/src/components/views/settings/KeyBackupPanel.js index 9d60ed1188..5548768221 100644 --- a/src/components/views/settings/KeyBackupPanel.js +++ b/src/components/views/settings/KeyBackupPanel.js @@ -326,7 +326,7 @@ export default class KeyBackupPanel extends React.PureComponent {
); - if (this.state.backupKeyStored && !SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (this.state.backupKeyStored && !SettingsStore.getValue("feature_cross_signing")) { buttonRow =

⚠️ {_t( "Backup key stored in secret storage, but this feature is not " + "enabled on this session. Please enable cross-signing in Labs to " + diff --git a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js index 3e69107159..fe160032ff 100644 --- a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js @@ -62,6 +62,7 @@ export default class LabsUserSettingsTab extends React.Component {

{flags} + diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index 3dca6e2490..1cde5d6f87 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -270,7 +270,7 @@ export default class SecurityUserSettingsTab extends React.Component { // can remove this. const CrossSigningPanel = sdk.getComponent('views.settings.CrossSigningPanel'); let crossSigning; - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { crossSigning = (
{_t("Cross-signing")} diff --git a/src/createRoom.js b/src/createRoom.js index 66d4d1908e..a39d2c2216 100644 --- a/src/createRoom.js +++ b/src/createRoom.js @@ -227,7 +227,7 @@ export async function ensureDMExists(client, userId) { roomId = existingDMRoom.roomId; } else { let encryption; - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { encryption = canEncryptToAllUsers(client, [userId]); } roomId = await createRoom({encryption, dmUserId: userId, spinner: false, andView: false}); diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 317508ca86..232c5d9f66 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -152,10 +152,10 @@ export const SETTINGS = { default: null, }, "feature_cross_signing": { - isFeature: true, + //isFeature: true, displayName: _td("Enable cross-signing to verify per-user instead of per-session (in development)"), supportedLevels: LEVELS_FEATURE, - default: false, + default: true, }, "feature_event_indexing": { isFeature: true, diff --git a/src/verification.js b/src/verification.js index e00e5e05fa..ca839940e5 100644 --- a/src/verification.js +++ b/src/verification.js @@ -27,7 +27,7 @@ import {verificationMethods} from 'matrix-js-sdk/src/crypto'; async function enable4SIfNeeded() { const cli = MatrixClientPeg.get(); - if (!cli.isCryptoEnabled() || !SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (!cli.isCryptoEnabled() || !SettingsStore.getValue("feature_cross_signing")) { return false; } const usk = cli.getCrossSigningId("user_signing"); From b5b4bdbf3d2d62316d2936964bf2516f53166196 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 16 Apr 2020 11:12:47 -0600 Subject: [PATCH 020/237] Clean up setting definition to follow surrounding practices It's not perfect, but we're at least okay with it. --- src/i18n/strings/en_EN.json | 2 +- src/settings/Settings.js | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a291065145..be8f1a7a4a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -399,7 +399,7 @@ "Try out new ways to ignore people (experimental)": "Try out new ways to ignore people (experimental)", "Show a presence dot next to DMs in the room list": "Show a presence dot next to DMs in the room list", "Support adding custom themes": "Support adding custom themes", - "Enable cross-signing to verify per-user instead of per-session (in development)": "Enable cross-signing to verify per-user instead of per-session (in development)", + "Enable cross-signing to verify per-user instead of per-session": "Enable cross-signing to verify per-user instead of per-session", "Enable local event indexing and E2EE search (requires restart)": "Enable local event indexing and E2EE search (requires restart)", "Show info about bridges in room settings": "Show info about bridges in room settings", "Show padlocks on invite only rooms": "Show padlocks on invite only rooms", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 232c5d9f66..32ff0a5f94 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -152,9 +152,10 @@ export const SETTINGS = { default: null, }, "feature_cross_signing": { - //isFeature: true, - displayName: _td("Enable cross-signing to verify per-user instead of per-session (in development)"), - supportedLevels: LEVELS_FEATURE, + // XXX: We shouldn't be using the feature prefix for non-feature settings. There is an exception + // for this case though as we're converting a feature to a setting for a temporary safety net. + displayName: _td("Enable cross-signing to verify per-user instead of per-session"), + supportedLevels: ['device', 'config'], // we shouldn't use LEVELS_FEATURE for non-features, so copy it here. default: true, }, "feature_event_indexing": { From 2ffb5be5cdfc98b281614ac7cb4baa50bd2bcd63 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 16 Apr 2020 11:15:12 -0600 Subject: [PATCH 021/237] Remove UI to change the cross-signing setting --- src/components/views/settings/tabs/user/LabsUserSettingsTab.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js index fe160032ff..3e69107159 100644 --- a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js @@ -62,7 +62,6 @@ export default class LabsUserSettingsTab extends React.Component {
{flags} - From 45b6b95d446f63a8b9159961e5f5b3810ce2f8fd Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 16 Apr 2020 11:18:54 -0600 Subject: [PATCH 022/237] Appease the linter --- src/components/views/rooms/E2EIcon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/E2EIcon.js b/src/components/views/rooms/E2EIcon.js index 9189cfdf26..5e74656920 100644 --- a/src/components/views/rooms/E2EIcon.js +++ b/src/components/views/rooms/E2EIcon.js @@ -20,7 +20,7 @@ import PropTypes from "prop-types"; import classNames from 'classnames'; import {_t, _td} from '../../../languageHandler'; -import {useFeatureEnabled, useSettingValue} from "../../../hooks/useSettings"; +import {useSettingValue} from "../../../hooks/useSettings"; import AccessibleButton from "../elements/AccessibleButton"; import Tooltip from "../elements/Tooltip"; From 2432f77b7204ed9861373df70b51a27d3a95e17a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 16 Apr 2020 11:46:29 -0600 Subject: [PATCH 023/237] Blind attempt at fixing the end to end tests --- .../CreateSecretStorageDialog.js | 6 ++++- test/end-to-end-tests/src/usecases/signup.js | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index 65784c49ec..80d0683bf9 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -624,7 +624,11 @@ export default class CreateSecretStorageDialog extends React.PureComponent { {this._recoveryKey.encodedPrivateKey}
- + {_t("Copy")} diff --git a/test/end-to-end-tests/src/usecases/signup.js b/test/end-to-end-tests/src/usecases/signup.js index ef8a259091..ffde22f929 100644 --- a/test/end-to-end-tests/src/usecases/signup.js +++ b/test/end-to-end-tests/src/usecases/signup.js @@ -79,6 +79,33 @@ module.exports = async function signup(session, username, password, homeserver) const acceptButton = await session.query('.mx_InteractiveAuthEntryComponents_termsSubmit'); await acceptButton.click(); + //plow through cross-signing setup by entering arbitrary details + //TODO: It's probably important for the tests to know the passphrase + const xsigningPassphrase = 'a7eaXcjpa9!Yl7#V^h$B^%dovHUVX'; // https://xkcd.com/221/ + let passphraseField = await session.query('.mx_CreateSecretStorageDialog_passPhraseField input'); + await session.replaceInputText(passphraseField, xsigningPassphrase); + let xsignContButton = await session.query('.mx_CreateSecretStorageDialog_passPhraseContainer .mx_Dialog_primary'); + await xsignContButton.click(); + + //repeat passphrase entry + passphraseField = await session.query('.mx_CreateSecretStorageDialog_passPhraseField input'); + await session.replaceInputText(passphraseField, xsigningPassphrase); + xsignContButton = await session.query('.mx_CreateSecretStorageDialog_passPhraseContainer .mx_Dialog_primary'); + await xsignContButton.click(); + + //ignore the recovery key + //TODO: It's probably important for the tests to know the recovery key + const copyButton = await session.query('.mx_CreateSecretStorageDialog_recoveryKeyButtons_copyBtn'); + await copyButton.click(); + + //acknowledge that we copied the recovery key to a safe place + const copyContinueButton = await session.query('.mx_CreateSecretStorageDialog .mx_Dialog_primary'); + await copyContinueButton.click(); + + //acknowledge that we're done cross-signing setup and our keys are safe + const doneOkButton = await session.query('.mx_CreateSecretStorageDialog .mx_Dialog_primary'); + await doneOkButton.click(); + //wait for registration to finish so the hash gets set //onhashchange better? From 597f97e1d8ef130870b2149b1cfae269cd135589 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 16 Apr 2020 12:04:01 -0600 Subject: [PATCH 024/237] Select the right continue button There's no buttons in the field. --- test/end-to-end-tests/src/usecases/signup.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/end-to-end-tests/src/usecases/signup.js b/test/end-to-end-tests/src/usecases/signup.js index ffde22f929..e686ebdb7d 100644 --- a/test/end-to-end-tests/src/usecases/signup.js +++ b/test/end-to-end-tests/src/usecases/signup.js @@ -84,13 +84,13 @@ module.exports = async function signup(session, username, password, homeserver) const xsigningPassphrase = 'a7eaXcjpa9!Yl7#V^h$B^%dovHUVX'; // https://xkcd.com/221/ let passphraseField = await session.query('.mx_CreateSecretStorageDialog_passPhraseField input'); await session.replaceInputText(passphraseField, xsigningPassphrase); - let xsignContButton = await session.query('.mx_CreateSecretStorageDialog_passPhraseContainer .mx_Dialog_primary'); + let xsignContButton = await session.query('.mx_CreateSecretStorageDialog .mx_Dialog_buttons .mx_Dialog_primary'); await xsignContButton.click(); //repeat passphrase entry passphraseField = await session.query('.mx_CreateSecretStorageDialog_passPhraseField input'); await session.replaceInputText(passphraseField, xsigningPassphrase); - xsignContButton = await session.query('.mx_CreateSecretStorageDialog_passPhraseContainer .mx_Dialog_primary'); + xsignContButton = await session.query('.mx_CreateSecretStorageDialog .mx_Dialog_buttons .mx_Dialog_primary'); await xsignContButton.click(); //ignore the recovery key From 2451e0b873f01db7cf3619ab26d616b9e09e4504 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 16 Apr 2020 12:13:05 -0600 Subject: [PATCH 025/237] Wait a bit before continuing with the passphrase The continue button is probably no-oping due to being disabled. --- test/end-to-end-tests/src/usecases/signup.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/end-to-end-tests/src/usecases/signup.js b/test/end-to-end-tests/src/usecases/signup.js index e686ebdb7d..aa9f6b7efa 100644 --- a/test/end-to-end-tests/src/usecases/signup.js +++ b/test/end-to-end-tests/src/usecases/signup.js @@ -84,12 +84,14 @@ module.exports = async function signup(session, username, password, homeserver) const xsigningPassphrase = 'a7eaXcjpa9!Yl7#V^h$B^%dovHUVX'; // https://xkcd.com/221/ let passphraseField = await session.query('.mx_CreateSecretStorageDialog_passPhraseField input'); await session.replaceInputText(passphraseField, xsigningPassphrase); + await session.delay(1000); // give it a second to analyze our passphrase for security let xsignContButton = await session.query('.mx_CreateSecretStorageDialog .mx_Dialog_buttons .mx_Dialog_primary'); await xsignContButton.click(); //repeat passphrase entry passphraseField = await session.query('.mx_CreateSecretStorageDialog_passPhraseField input'); await session.replaceInputText(passphraseField, xsigningPassphrase); + await session.delay(1000); // give it a second to analyze our passphrase for security xsignContButton = await session.query('.mx_CreateSecretStorageDialog .mx_Dialog_buttons .mx_Dialog_primary'); await xsignContButton.click(); From 8b5a8f163fa5df5dc096662115e52577a0e90e8e Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 16 Apr 2020 12:23:22 -0600 Subject: [PATCH 026/237] Disable e2e tests for now --- .../src/scenarios/e2e-encryption.js | 66 ++++++++++--------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/test/end-to-end-tests/src/scenarios/e2e-encryption.js b/test/end-to-end-tests/src/scenarios/e2e-encryption.js index 2f08acf417..a764b85db6 100644 --- a/test/end-to-end-tests/src/scenarios/e2e-encryption.js +++ b/test/end-to-end-tests/src/scenarios/e2e-encryption.js @@ -15,35 +15,41 @@ See the License for the specific language governing permissions and limitations under the License. */ -const sendMessage = require('../usecases/send-message'); -const acceptInvite = require('../usecases/accept-invite'); -const invite = require('../usecases/invite'); -const {receiveMessage} = require('../usecases/timeline'); -const {createRoom} = require('../usecases/create-room'); -const changeRoomSettings = require('../usecases/room-settings'); -const {startSasVerifcation, acceptSasVerification} = require('../usecases/verify'); -const assert = require('assert'); +// TODO: Update test for cross signing -module.exports = async function e2eEncryptionScenarios(alice, bob) { - console.log(" creating an e2e encrypted room and join through invite:"); - const room = "secrets"; - await createRoom(bob, room); - await changeRoomSettings(bob, {encryption: true}); - // await cancelKeyBackup(bob); - await invite(bob, "@alice:localhost"); - await acceptInvite(alice, room); - // do sas verifcation - bob.log.step(`starts SAS verification with ${alice.username}`); - const bobSasPromise = startSasVerifcation(bob, alice.username); - const aliceSasPromise = acceptSasVerification(alice, bob.username); - // wait in parallel, so they don't deadlock on each other - const [bobSas, aliceSas] = await Promise.all([bobSasPromise, aliceSasPromise]); - assert.deepEqual(bobSas, aliceSas); - bob.log.done(`done (match for ${bobSas.join(", ")})`); - const aliceMessage = "Guess what I just heard?!"; - await sendMessage(alice, aliceMessage); - await receiveMessage(bob, {sender: "alice", body: aliceMessage, encrypted: true}); - const bobMessage = "You've got to tell me!"; - await sendMessage(bob, bobMessage); - await receiveMessage(alice, {sender: "bob", body: bobMessage, encrypted: true}); +module.exports = async function() { + console.log(" this is supposed to be an e2e test, but it's broken"); }; + +// const sendMessage = require('../usecases/send-message'); +// const acceptInvite = require('../usecases/accept-invite'); +// const invite = require('../usecases/invite'); +// const {receiveMessage} = require('../usecases/timeline'); +// const {createRoom} = require('../usecases/create-room'); +// const changeRoomSettings = require('../usecases/room-settings'); +// const {startSasVerifcation, acceptSasVerification} = require('../usecases/verify'); +// const assert = require('assert'); +// +// module.exports = async function e2eEncryptionScenarios(alice, bob) { +// console.log(" creating an e2e encrypted room and join through invite:"); +// const room = "secrets"; +// await createRoom(bob, room); +// await changeRoomSettings(bob, {encryption: true}); +// // await cancelKeyBackup(bob); +// await invite(bob, "@alice:localhost"); +// await acceptInvite(alice, room); +// // do sas verifcation +// bob.log.step(`starts SAS verification with ${alice.username}`); +// const bobSasPromise = startSasVerifcation(bob, alice.username); +// const aliceSasPromise = acceptSasVerification(alice, bob.username); +// // wait in parallel, so they don't deadlock on each other +// const [bobSas, aliceSas] = await Promise.all([bobSasPromise, aliceSasPromise]); +// assert.deepEqual(bobSas, aliceSas); +// bob.log.done(`done (match for ${bobSas.join(", ")})`); +// const aliceMessage = "Guess what I just heard?!"; +// await sendMessage(alice, aliceMessage); +// await receiveMessage(bob, {sender: "alice", body: aliceMessage, encrypted: true}); +// const bobMessage = "You've got to tell me!"; +// await sendMessage(bob, bobMessage); +// await receiveMessage(alice, {sender: "bob", body: bobMessage, encrypted: true}); +// }; From 741368350c0c8712e0850fa866ede621617bdbc3 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 16 Apr 2020 12:26:08 -0600 Subject: [PATCH 027/237] Track the issue number too --- test/end-to-end-tests/src/scenarios/e2e-encryption.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/end-to-end-tests/src/scenarios/e2e-encryption.js b/test/end-to-end-tests/src/scenarios/e2e-encryption.js index a764b85db6..f30b814644 100644 --- a/test/end-to-end-tests/src/scenarios/e2e-encryption.js +++ b/test/end-to-end-tests/src/scenarios/e2e-encryption.js @@ -16,6 +16,7 @@ limitations under the License. */ // TODO: Update test for cross signing +// https://github.com/vector-im/riot-web/issues/13226 module.exports = async function() { console.log(" this is supposed to be an e2e test, but it's broken"); From c3f90ed289ba314e825555381d3ee4717b7609af Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 16 Apr 2020 12:41:48 -0600 Subject: [PATCH 028/237] Short-circuit all end to end tests --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 8e1e687f4e..fb60652f0e 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,8 @@ "lint:types": "tsc --noEmit --jsx react", "lint:style": "stylelint 'res/css/**/*.scss'", "test": "jest", - "test:e2e": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080" + "test:e2e": "echo 'The tests are broken with cross-signing. Fix them: https://github.com/vector-im/riot-web/issues/13226'", + "test:e2e_real": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080" }, "dependencies": { "@babel/runtime": "^7.8.3", From 22533d3e6a3fb17c1a124e10a6324157782fbdb6 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 16 Apr 2020 12:46:34 -0600 Subject: [PATCH 029/237] Disable scripts in CI too --- scripts/ci/end-to-end-tests.sh | 46 ++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/scripts/ci/end-to-end-tests.sh b/scripts/ci/end-to-end-tests.sh index 2f907dffa2..fa1f2b983f 100755 --- a/scripts/ci/end-to-end-tests.sh +++ b/scripts/ci/end-to-end-tests.sh @@ -13,25 +13,29 @@ handle_error() { trap 'handle_error' ERR +echo "Tests are disabled, see https://github.com/vector-im/riot-web/issues/13226" +exit 0 -echo "--- Building Riot" -scripts/ci/layered-riot-web.sh -cd ../riot-web -riot_web_dir=`pwd` -CI_PACKAGE=true yarn build -cd ../matrix-react-sdk -# run end to end tests -pushd test/end-to-end-tests -ln -s $riot_web_dir riot/riot-web -# PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true ./install.sh -# CHROME_PATH=$(which google-chrome-stable) ./run.sh -echo "--- Install synapse & other dependencies" -./install.sh -# install static webserver to server symlinked local copy of riot -./riot/install-webserver.sh -rm -r logs || true -mkdir logs -echo "+++ Running end-to-end tests" -TESTS_STARTED=1 -./run.sh --no-sandbox --log-directory logs/ -popd +#TODO: Uncomment all of this in https://github.com/vector-im/riot-web/issues/13226 + +#echo "--- Building Riot" +#scripts/ci/layered-riot-web.sh +#cd ../riot-web +#riot_web_dir=`pwd` +#CI_PACKAGE=true yarn build +#cd ../matrix-react-sdk +## run end to end tests +#pushd test/end-to-end-tests +#ln -s $riot_web_dir riot/riot-web +## PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true ./install.sh +## CHROME_PATH=$(which google-chrome-stable) ./run.sh +#echo "--- Install synapse & other dependencies" +#./install.sh +## install static webserver to server symlinked local copy of riot +#./riot/install-webserver.sh +#rm -r logs || true +#mkdir logs +#echo "+++ Running end-to-end tests" +#TESTS_STARTED=1 +#./run.sh --no-sandbox --log-directory logs/ +#popd From c6746e68b22710156cd04ad584b588246bed2925 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 16 Apr 2020 19:56:11 +0100 Subject: [PATCH 030/237] Upgrade matrix-js-sdk to 5.3.1-rc.2 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fb60652f0e..8d9f8f779c 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "5.3.1-rc.1", + "matrix-js-sdk": "5.3.1-rc.2", "minimist": "^1.2.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index 2b55aa2ae2..e78b6ed280 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5715,10 +5715,10 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -matrix-js-sdk@5.3.1-rc.1: - version "5.3.1-rc.1" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.3.1-rc.1.tgz#12f9434b2fc09e014371bc9a75dc2bc9bc35fe33" - integrity sha512-HP47NvGFrK4gG8ToZRurb6/pRHhJAOhixwoNT6P/FTZNZLJX4DDPY84uNR0jtmiiZXI+/wHRST0K9P6A2bgBXA== +matrix-js-sdk@5.3.1-rc.2: + version "5.3.1-rc.2" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.3.1-rc.2.tgz#437cb6aafa1be5d8750aa0e31baed76ef4fcb7da" + integrity sha512-VWwqjmSXaabXqwc4Lm+jHQEu3sBpHs9ni/zCW8kTf+jUDnJllCUDCRnGWY4F3QVNWT9nz9e5Nzojzq7ySiP7XA== dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From c7e908ddc0a5a0a8470a5790048a105870cd0f6c Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 16 Apr 2020 20:01:46 +0100 Subject: [PATCH 031/237] Prepare changelog for v2.5.0-rc.2 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7586bb49eb..21dfca116a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +Changes in [2.5.0-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.2) (2020-04-16) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.1...v2.5.0-rc.2) + + * Upgrade to JS SDK 5.3.1-rc.2 + * [Release] Convert cross-signing flag to a setting + [\#4429](https://github.com/matrix-org/matrix-react-sdk/pull/4429) + * Iterate cross-signing copy + [\#4426](https://github.com/matrix-org/matrix-react-sdk/pull/4426) + * Fix: ensure twemoji font is loaded when showing SAS emojis + [\#4423](https://github.com/matrix-org/matrix-react-sdk/pull/4423) + Changes in [2.5.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.1) (2020-04-15) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.4.0-rc.1...v2.5.0-rc.1) From 23f167d6813f111b59f28880215bac9fc88a8125 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 16 Apr 2020 20:01:46 +0100 Subject: [PATCH 032/237] v2.5.0-rc.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8d9f8f779c..989f0dbc96 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.5.0-rc.1", + "version": "2.5.0-rc.2", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 383915d5ccf3d875888b27650ef8ae22d2672999 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Fri, 17 Apr 2020 17:46:55 +0100 Subject: [PATCH 033/237] Upgrade matrix-js-sdk to 5.3.1-rc.3 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 989f0dbc96..adc2b61cbc 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "5.3.1-rc.2", + "matrix-js-sdk": "5.3.1-rc.3", "minimist": "^1.2.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index e78b6ed280..65f8a0e669 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5715,10 +5715,10 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -matrix-js-sdk@5.3.1-rc.2: - version "5.3.1-rc.2" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.3.1-rc.2.tgz#437cb6aafa1be5d8750aa0e31baed76ef4fcb7da" - integrity sha512-VWwqjmSXaabXqwc4Lm+jHQEu3sBpHs9ni/zCW8kTf+jUDnJllCUDCRnGWY4F3QVNWT9nz9e5Nzojzq7ySiP7XA== +matrix-js-sdk@5.3.1-rc.3: + version "5.3.1-rc.3" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.3.1-rc.3.tgz#fada68aaf9fadd2f423a297bba8193b5bd697316" + integrity sha512-YMfOdhlAFk4kHQ85S3kosVBWSr8iCJ8OaVpJr+lDFoXkvIrPgSn5zWesg+ny/bvQjWNRny7Ch7wcmozojKQqqg== dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From 12f2076e348cee91e8bec41deca4403df68cac5a Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Fri, 17 Apr 2020 17:51:49 +0100 Subject: [PATCH 034/237] Prepare changelog for v2.5.0-rc.3 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21dfca116a..c3676b5be0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Changes in [2.5.0-rc.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.3) (2020-04-17) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.2...v2.5.0-rc.3) + + * Upgrade to JS SDK 5.3.1-rc.3 + Changes in [2.5.0-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.2) (2020-04-16) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.1...v2.5.0-rc.2) From 1ee2d6f3a2d93377e410b380936a4e5112a75aac Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Fri, 17 Apr 2020 17:51:49 +0100 Subject: [PATCH 035/237] v2.5.0-rc.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index adc2b61cbc..4e20ad6acf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.5.0-rc.2", + "version": "2.5.0-rc.3", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 161203d4458bb8a8aa779614571863f1c478155e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Mon, 20 Apr 2020 10:02:40 +0200 Subject: [PATCH 036/237] EventIndex: Filter out events that don't have a propper content value. (cherry picked from commit 6084c08f345fcdebf4302091f24d7b49ccaa143e) --- src/indexing/EventIndex.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index e4e8f26031..c09fc73a58 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -275,6 +275,7 @@ export default class EventIndex extends EventEmitter { const validEventType = isUsefulType && !ev.isRedacted() && !ev.isDecryptionFailure(); let validMsgType = true; + let hasContentValue = true; if (ev.getType() === "m.room.message" && !ev.isRedacted()) { // Expand this if there are more invalid msgtypes. @@ -282,9 +283,15 @@ export default class EventIndex extends EventEmitter { if (!msgtype) validMsgType = false; else validMsgType = !msgtype.startsWith("m.key.verification"); + + if (!ev.getContent().body) hasContentValue = false + } else if (ev.getType() === "m.room.topic" && !ev.isRedacted()) { + if (!ev.getContent().topic) hasContentValue = false; + } else if (ev.getType() === "m.room.name" && !ev.isRedacted()) { + if (!ev.getContent().name) hasContentValue = false; } - return validEventType && validMsgType; + return validEventType && validMsgType && hasContentValue; } /** From 212c3ca46cb784998b18d3a12ed864e23565de63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Mon, 20 Apr 2020 10:10:16 +0200 Subject: [PATCH 037/237] EventIndex: Add a missing semicolon. (cherry picked from commit 3781bdc9758ddb54f9eacc6f56784b0d64d8ca01) --- src/indexing/EventIndex.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index c09fc73a58..a6bbbb5f96 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -284,7 +284,7 @@ export default class EventIndex extends EventEmitter { if (!msgtype) validMsgType = false; else validMsgType = !msgtype.startsWith("m.key.verification"); - if (!ev.getContent().body) hasContentValue = false + if (!ev.getContent().body) hasContentValue = false; } else if (ev.getType() === "m.room.topic" && !ev.isRedacted()) { if (!ev.getContent().topic) hasContentValue = false; } else if (ev.getType() === "m.room.name" && !ev.isRedacted()) { From 13cb49bb0d48ee0c090a708be262c64ccd4626d5 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 20 Apr 2020 14:36:15 +0100 Subject: [PATCH 038/237] Don't recheck DeviceListener until after initial sync is finished Each recheck caused a GET to account data to see if the master key exists if done before the initial sync, which is unnecessary here. This just makes it wait until the initial sync is done to recheck. Fixes https://github.com/vector-im/riot-web/issues/13279 --- src/DeviceListener.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 3201e4af45..4ec2ec0fa0 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -52,6 +52,7 @@ export default class DeviceListener { MatrixClientPeg.get().on('userTrustStatusChanged', this._onUserTrustStatusChanged); MatrixClientPeg.get().on('crossSigning.keysChanged', this._onCrossSingingKeysChanged); MatrixClientPeg.get().on('accountData', this._onAccountData); + MatrixClientPeg.get().on('sync', this._onSync); this._recheck(); } @@ -62,6 +63,7 @@ export default class DeviceListener { MatrixClientPeg.get().removeListener('userTrustStatusChanged', this._onUserTrustStatusChanged); MatrixClientPeg.get().removeListener('crossSigning.keysChanged', this._onCrossSingingKeysChanged); MatrixClientPeg.get().removeListener('accountData', this._onAccountData); + MatrixClientPeg.get().removeListener('sync', this._onSync); } this._dismissed.clear(); } @@ -109,6 +111,10 @@ export default class DeviceListener { } } + _onSync = (state, prevState) => { + if (state === 'PREPARED' && prevState === null) this._recheck(); + } + // The server doesn't tell us when key backup is set up, so we poll // & cache the result async _getKeyBackupInfo() { @@ -129,6 +135,10 @@ export default class DeviceListener { ) return; if (!cli.isCryptoEnabled()) return; + // don't recheck until the initial sync is complete: lots of account data events will fire + // while the initial sync is processing and we don't need to recheck on each one of them + // (we add a listener on sync to do once check after the initial sync is done) + if (!cli.isInitialSyncComplete()) return; const crossSigningReady = await cli.isCrossSigningReady(); From 39b36755836251b334004df4123871bf8f77a4ca Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 20 Apr 2020 18:10:23 +0100 Subject: [PATCH 039/237] Handle load error in create secret storage dialog --- .../CreateSecretStorageDialog.js | 78 +++++++++++++------ src/i18n/strings/en_EN.json | 3 +- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index 80d0683bf9..cf7f4d4126 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -26,14 +26,15 @@ import Modal from '../../../../Modal'; import { promptForBackupPassphrase } from '../../../../CrossSigningManager'; const PHASE_LOADING = 0; -const PHASE_MIGRATE = 1; -const PHASE_PASSPHRASE = 2; -const PHASE_PASSPHRASE_CONFIRM = 3; -const PHASE_SHOWKEY = 4; -const PHASE_KEEPITSAFE = 5; -const PHASE_STORING = 6; -const PHASE_DONE = 7; -const PHASE_CONFIRM_SKIP = 8; +const PHASE_LOADERROR = 1; +const PHASE_MIGRATE = 2; +const PHASE_PASSPHRASE = 3; +const PHASE_PASSPHRASE_CONFIRM = 4; +const PHASE_SHOWKEY = 5; +const PHASE_KEEPITSAFE = 6; +const PHASE_STORING = 7; +const PHASE_DONE = 8; +const PHASE_CONFIRM_SKIP = 9; const PASSWORD_MIN_SCORE = 4; // So secure, many characters, much complex, wow, etc, etc. const PASSPHRASE_FEEDBACK_DELAY = 500; // How long after keystroke to offer passphrase feedback, ms. @@ -104,25 +105,29 @@ export default class CreateSecretStorageDialog extends React.PureComponent { } async _fetchBackupInfo() { - const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion(); - const backupSigStatus = ( - // we may not have started crypto yet, in which case we definitely don't trust the backup - MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo) - ); + try { + const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion(); + const backupSigStatus = ( + // we may not have started crypto yet, in which case we definitely don't trust the backup + MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo) + ); - const { force } = this.props; - const phase = (backupInfo && !force) ? PHASE_MIGRATE : PHASE_PASSPHRASE; + const { force } = this.props; + const phase = (backupInfo && !force) ? PHASE_MIGRATE : PHASE_PASSPHRASE; - this.setState({ - phase, - backupInfo, - backupSigStatus, - }); + this.setState({ + phase, + backupInfo, + backupSigStatus, + }); - return { - backupInfo, - backupSigStatus, - }; + return { + backupInfo, + backupSigStatus, + }; + } catch (e) { + this.setState({phase: PHASE_LOADERROR}); + } } async _queryKeyUploadAuth() { @@ -133,8 +138,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent { // no keys which would be a no-op. console.log("uploadDeviceSigningKeys unexpectedly succeeded without UI auth!"); } catch (error) { - if (!error.data.flows) { + if (!error.data || !error.data.flows) { console.log("uploadDeviceSigningKeys advertised no flows!"); + return; } const canUploadKeysWithPasswordOnly = error.data.flows.some(f => { return f.stages.length === 1 && f.stages[0] === 'm.login.password'; @@ -306,6 +312,11 @@ export default class CreateSecretStorageDialog extends React.PureComponent { } } + _onLoadRetryClick = () => { + this.setState({phase: PHASE_LOADING}); + this._fetchBackupInfo(); + } + _onSkipSetupClick = () => { this.setState({phase: PHASE_CONFIRM_SKIP}); } @@ -676,6 +687,20 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
; } + _renderPhaseLoadError() { + const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); + return
+

{_t("Unable to query secret storage status")}

+
+ +
+
; + } + _renderPhaseDone() { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return
@@ -749,6 +774,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent { case PHASE_LOADING: content = this._renderBusyPhase(); break; + case PHASE_LOADERROR: + content = this._renderPhaseLoadError(); + break; case PHASE_MIGRATE: content = this._renderPhaseMigrate(); break; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index be8f1a7a4a..8ba838d313 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2200,13 +2200,14 @@ "Print it and store it somewhere safe": "Print it and store it somewhere safe", "Save it on a USB key or backup drive": "Save it on a USB key or backup drive", "Copy it to your personal cloud storage": "Copy it to your personal cloud storage", + "Unable to query secret storage status": "Unable to query secret storage status", + "Retry": "Retry", "You can now verify your other devices, and other users to keep your chats safe.": "You can now verify your other devices, and other users to keep your chats safe.", "Upgrade your encryption": "Upgrade your encryption", "Confirm recovery passphrase": "Confirm recovery passphrase", "Make a copy of your recovery key": "Make a copy of your recovery key", "You're done!": "You're done!", "Unable to set up secret storage": "Unable to set up secret storage", - "Retry": "Retry", "We'll store an encrypted copy of your keys on our server. Secure your backup with a recovery passphrase.": "We'll store an encrypted copy of your keys on our server. Secure your backup with a recovery passphrase.", "For maximum security, this should be different from your account password.": "For maximum security, this should be different from your account password.", "Enter a recovery passphrase...": "Enter a recovery passphrase...", From d842944f61bdef92f44262a13e21f4690405c5f1 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 21 Apr 2020 18:36:15 +0200 Subject: [PATCH 040/237] wait until cross-signing keys are fetched to show verify button --- src/components/views/right_panel/UserInfo.js | 38 ++++++++++++-------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index abe54b355e..65519270b5 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -142,7 +142,7 @@ function useIsEncrypted(cli, room) { function useHasCrossSigningKeys(cli, member, canVerify, setUpdating) { return useAsyncMemo(async () => { if (!canVerify) { - return false; + return undefined; } setUpdating(true); try { @@ -153,7 +153,7 @@ function useHasCrossSigningKeys(cli, member, canVerify, setUpdating) { } finally { setUpdating(false); } - }, [cli, member, canVerify], false); + }, [cli, member, canVerify], undefined); } function DeviceItem({userId, device}) { @@ -1307,18 +1307,28 @@ const BasicUserInfo = ({room, member, groupId, devices, isRoomEncrypted}) => { const hasCrossSigningKeys = useHasCrossSigningKeys(cli, member, canVerify, setUpdating ); + const showDeviceListSpinner = devices === undefined; if (canVerify) { - verifyButton = ( - { - if (hasCrossSigningKeys) { - verifyUser(member); - } else { - legacyVerifyUser(member); - } - }}> - {_t("Verify")} - - ); + if (hasCrossSigningKeys !== undefined) { + // Note: mx_UserInfo_verifyButton is for the end-to-end tests + verifyButton = ( + { + if (hasCrossSigningKeys) { + verifyUser(member); + } else { + legacyVerifyUser(member); + } + }}> + {_t("Verify")} + + ); + } else if (!showDeviceListSpinner) { + // HACK: only show a spinner if the device section spinner is not shown, + // to avoid showing a double spinner + // We should ask for a design that includes all the different loading states here + const Spinner = sdk.getComponent('elements.Spinner'); + verifyButton = ; + } } const securitySection = ( @@ -1327,7 +1337,7 @@ const BasicUserInfo = ({room, member, groupId, devices, isRoomEncrypted}) => {

{ text }

{ verifyButton }
From 89345c9e8bfdb47d49fce92aef881f7357abe0ad Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 22 Apr 2020 11:55:03 +0100 Subject: [PATCH 041/237] Convert MatrixChat to an ES6 Class Component Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.js | 367 ++++++++++++------------ 1 file changed, 179 insertions(+), 188 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 1293ccc7e9..e93b81109a 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -112,15 +112,11 @@ const ONBOARDING_FLOW_STARTERS = [ 'view_create_group', ]; -export default createReactClass({ - // we export this so that the integration tests can use it :-S - statics: { - VIEWS: VIEWS, - }, +export default class MatrixChat extends React.PureComponent { + static VIEWS = VIEWS; // we export this so that the integration tests can use it :-S + static displayName = "MatrixChat"; - displayName: 'MatrixChat', - - propTypes: { + static propTypes = { config: PropTypes.object, serverConfig: PropTypes.instanceOf(ValidatedServerConfig), ConferenceHandler: PropTypes.any, @@ -150,10 +146,19 @@ export default createReactClass({ // A function that makes a registration URL makeRegistrationUrl: PropTypes.func.isRequired, - }, + }; - getInitialState: function() { - const s = { + static defaultProps = { + realQueryParams: {}, + startingFragmentQueryParams: {}, + config: {}, + onTokenLoginCompleted: () => {}, + }; + + constructor(props, context) { + super(props, context); + + this.state = { // the master view we are showing. view: VIEWS.LOADING, @@ -194,35 +199,7 @@ export default createReactClass({ resizeNotifier: new ResizeNotifier(), showNotifierToolbar: false, }; - return s; - }, - getDefaultProps: function() { - return { - realQueryParams: {}, - startingFragmentQueryParams: {}, - config: {}, - onTokenLoginCompleted: () => {}, - }; - }, - - getFallbackHsUrl: function() { - if (this.props.serverConfig && this.props.serverConfig.isDefault) { - return this.props.config.fallback_hs_url; - } else { - return null; - } - }, - - getServerProperties() { - let props = this.state.serverConfig; - if (!props) props = this.props.serverConfig; // for unit tests - if (!props) props = SdkConfig.get()["validated_server_config"]; - return {serverConfig: props}; - }, - - // TODO: [REACT-WARNING] Move this to constructor - UNSAFE_componentWillMount: function() { SdkConfig.put(this.props.config); // Used by _viewRoom before getting state from sync @@ -325,9 +302,53 @@ export default createReactClass({ if (SettingsStore.getValue("analyticsOptIn")) { Analytics.enable(); } - }, + } - _loadSession: function() { + // TODO: [REACT-WARNING] Replace with appropriate lifecycle stage + UNSAFE_componentWillUpdate(props, state) { + if (this.shouldTrackPageChange(this.state, state)) { + this.startPageChangeTimer(); + } + } + + componentDidUpdate(prevProps, prevState) { + if (this.shouldTrackPageChange(prevState, this.state)) { + const durationMs = this.stopPageChangeTimer(); + Analytics.trackPageChange(durationMs); + } + if (this.focusComposer) { + dis.dispatch({action: 'focus_composer'}); + this.focusComposer = false; + } + } + + componentWillUnmount() { + Lifecycle.stopMatrixClient(); + dis.unregister(this.dispatcherRef); + this._themeWatcher.stop(); + window.removeEventListener("focus", this.onFocus); + window.removeEventListener('resize', this.handleResize); + this.state.resizeNotifier.removeListener("middlePanelResized", this._dispatchTimelineResize); + + if (this._accountPasswordTimer !== null) clearTimeout(this._accountPasswordTimer); + } + + getFallbackHsUrl() { + if (this.props.serverConfig && this.props.serverConfig.isDefault) { + return this.props.config.fallback_hs_url; + } else { + return null; + } + } + + getServerProperties() { + let props = this.state.serverConfig; + if (!props) props = this.props.serverConfig; // for unit tests + if (!props) props = SdkConfig.get()["validated_server_config"]; + return {serverConfig: props}; + } + + _loadSession() { // the extra Promise.resolve() ensures that synchronous exceptions hit the same codepath as // asynchronous ones. return Promise.resolve().then(() => { @@ -347,36 +368,7 @@ export default createReactClass({ // Note we don't catch errors from this: we catch everything within // loadSession as there's logic there to ask the user if they want // to try logging out. - }, - - componentWillUnmount: function() { - Lifecycle.stopMatrixClient(); - dis.unregister(this.dispatcherRef); - this._themeWatcher.stop(); - window.removeEventListener("focus", this.onFocus); - window.removeEventListener('resize', this.handleResize); - this.state.resizeNotifier.removeListener("middlePanelResized", this._dispatchTimelineResize); - - if (this._accountPasswordTimer !== null) clearTimeout(this._accountPasswordTimer); - }, - - // TODO: [REACT-WARNING] Replace with appropriate lifecycle stage - UNSAFE_componentWillUpdate: function(props, state) { - if (this.shouldTrackPageChange(this.state, state)) { - this.startPageChangeTimer(); - } - }, - - componentDidUpdate: function(prevProps, prevState) { - if (this.shouldTrackPageChange(prevState, this.state)) { - const durationMs = this.stopPageChangeTimer(); - Analytics.trackPageChange(durationMs); - } - if (this.focusComposer) { - dis.dispatch({action: 'focus_composer'}); - this.focusComposer = false; - } - }, + } startPageChangeTimer() { // Tor doesn't support performance @@ -390,7 +382,7 @@ export default createReactClass({ } this._pageChanging = true; performance.mark('riot_MatrixChat_page_change_start'); - }, + } stopPageChangeTimer() { // Tor doesn't support performance @@ -415,15 +407,15 @@ export default createReactClass({ if (!measurement) return null; return measurement.duration; - }, + } shouldTrackPageChange(prevState, state) { return prevState.currentRoomId !== state.currentRoomId || prevState.view !== state.view || prevState.page_type !== state.page_type; - }, + } - setStateForNewView: function(state) { + setStateForNewView(state) { if (state.view === undefined) { throw new Error("setStateForNewView with no view!"); } @@ -432,9 +424,9 @@ export default createReactClass({ }; Object.assign(newState, state); this.setState(newState); - }, + } - onAction: function(payload) { + onAction = (payload) => { // console.log(`MatrixClientPeg.onAction: ${payload.action}`); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); @@ -596,8 +588,8 @@ export default createReactClass({ case 'view_create_group': { const CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog"); Modal.createTrackedDialog('Create Community', '', CreateGroupDialog); + break; } - break; case 'view_room_directory': { const RoomDirectory = sdk.getComponent("structures.RoomDirectory"); Modal.createTrackedDialog('Room directory', '', RoomDirectory, {}, @@ -605,8 +597,8 @@ export default createReactClass({ // View the welcome or home page if we need something to look at this._viewSomethingBehindModal(); + break; } - break; case 'view_my_groups': this._setPage(PageTypes.MyGroups); this.notifyNewScreen('groups'); @@ -648,9 +640,8 @@ export default createReactClass({ dis.dispatch({action: 'view_my_groups'}); } break; - case 'notifier_enabled': { - this.setState({showNotifierToolbar: Notifier.shouldShowToolbar()}); - } + case 'notifier_enabled': + this.setState({showNotifierToolbar: Notifier.shouldShowToolbar()}); break; case 'hide_left_panel': this.setState({ @@ -739,15 +730,15 @@ export default createReactClass({ }); break; } - }, + }; - _setPage: function(pageType) { + _setPage(pageType) { this.setState({ page_type: pageType, }); - }, + } - _startRegistration: async function(params) { + async _startRegistration(params) { const newState = { view: VIEWS.REGISTER, }; @@ -773,10 +764,10 @@ export default createReactClass({ ThemeController.isLogin = true; this._themeWatcher.recheck(); this.notifyNewScreen('register'); - }, + } // TODO: Move to RoomViewStore - _viewNextRoom: function(roomIndexDelta) { + _viewNextRoom(roomIndexDelta) { const allRooms = RoomListSorter.mostRecentActivityFirst( MatrixClientPeg.get().getRooms(), ); @@ -802,10 +793,10 @@ export default createReactClass({ action: 'view_room', room_id: allRooms[roomIndex].roomId, }); - }, + } // TODO: Move to RoomViewStore - _viewIndexedRoom: function(roomIndex) { + _viewIndexedRoom(roomIndex) { const allRooms = RoomListSorter.mostRecentActivityFirst( MatrixClientPeg.get().getRooms(), ); @@ -815,7 +806,7 @@ export default createReactClass({ room_id: allRooms[roomIndex].roomId, }); } - }, + } // switch view to the given room // @@ -834,7 +825,7 @@ export default createReactClass({ // @param {Object=} roomInfo.oob_data Object of additional data about the room // that has been passed out-of-band (eg. // room name and avatar from an invite email) - _viewRoom: function(roomInfo) { + _viewRoom(roomInfo) { this.focusComposer = true; const newState = { @@ -895,9 +886,9 @@ export default createReactClass({ this.notifyNewScreen('room/' + presentedId); }); }); - }, + } - _viewGroup: function(payload) { + _viewGroup(payload) { const groupId = payload.group_id; this.setState({ currentGroupId: groupId, @@ -905,7 +896,7 @@ export default createReactClass({ }); this._setPage(PageTypes.GroupView); this.notifyNewScreen('group/' + groupId); - }, + } _viewSomethingBehindModal() { if (this.state.view !== VIEWS.LOGGED_IN) { @@ -915,7 +906,7 @@ export default createReactClass({ if (!this.state.currentGroupId && !this.state.currentRoomId) { this._viewHome(); } - }, + } _viewWelcome() { this.setStateForNewView({ @@ -924,9 +915,9 @@ export default createReactClass({ this.notifyNewScreen('welcome'); ThemeController.isLogin = true; this._themeWatcher.recheck(); - }, + } - _viewHome: function() { + _viewHome() { // The home page requires the "logged in" view, so we'll set that. this.setStateForNewView({ view: VIEWS.LOGGED_IN, @@ -935,9 +926,9 @@ export default createReactClass({ this.notifyNewScreen('home'); ThemeController.isLogin = false; this._themeWatcher.recheck(); - }, + } - _viewUser: function(userId, subAction) { + _viewUser(userId, subAction) { // Wait for the first sync so that `getRoom` gives us a room object if it's // in the sync response const waitForSync = this.firstSyncPromise ? @@ -951,9 +942,9 @@ export default createReactClass({ this.setState({currentUserId: userId}); this._setPage(PageTypes.UserView); }); - }, + } - _setMxId: function(payload) { + _setMxId(payload) { const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog'); const close = Modal.createTrackedDialog('Set MXID', '', SetMxIdDialog, { homeserverUrl: MatrixClientPeg.get().getHomeserverUrl(), @@ -981,9 +972,9 @@ export default createReactClass({ close(); }, }).close; - }, + } - _createRoom: async function() { + async _createRoom() { const CreateRoomDialog = sdk.getComponent('dialogs.CreateRoomDialog'); const modal = Modal.createTrackedDialog('Create Room', '', CreateRoomDialog); @@ -991,9 +982,9 @@ export default createReactClass({ if (shouldCreate) { createRoom(opts); } - }, + } - _chatCreateOrReuse: function(userId) { + _chatCreateOrReuse(userId) { // Use a deferred action to reshow the dialog once the user has registered if (MatrixClientPeg.get().isGuest()) { // No point in making 2 DMs with welcome bot. This assumes view_set_mxid will @@ -1039,9 +1030,9 @@ export default createReactClass({ user_id: userId, }); } - }, + } - _leaveRoomWarnings: function(roomId) { + _leaveRoomWarnings(roomId) { const roomToLeave = MatrixClientPeg.get().getRoom(roomId); // Show a warning if there are additional complications. const joinRules = roomToLeave.currentState.getStateEvents('m.room.join_rules', ''); @@ -1058,9 +1049,9 @@ export default createReactClass({ } } return warnings; - }, + } - _leaveRoom: function(roomId) { + _leaveRoom(roomId) { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const roomToLeave = MatrixClientPeg.get().getRoom(roomId); @@ -1071,7 +1062,7 @@ export default createReactClass({ description: ( { _t("Are you sure you want to leave the room '%(roomName)s'?", {roomName: roomToLeave.name}) } - { warnings } + { warnings } ), button: _t("Leave"), @@ -1124,7 +1115,7 @@ export default createReactClass({ } }, }); - }, + } /** * Starts a chat with the welcome user, if the user doesn't already have one @@ -1179,12 +1170,12 @@ export default createReactClass({ return roomId; } return null; - }, + } /** * Called when a new logged in session has started */ - _onLoggedIn: async function() { + async _onLoggedIn() { ThemeController.isLogin = false; this.setStateForNewView({ view: VIEWS.LOGGED_IN }); // If a specific screen is set to be shown after login, show that above @@ -1215,9 +1206,9 @@ export default createReactClass({ } StorageManager.tryPersistStorage(); - }, + } - _showScreenAfterLogin: function() { + _showScreenAfterLogin() { // If screenAfterLogin is set, use that, then null it so that a second login will // result in view_home_page, _user_settings or _room_directory if (this._screenAfterLogin && this._screenAfterLogin.screen) { @@ -1240,19 +1231,19 @@ export default createReactClass({ }); } } - }, + } - _viewLastRoom: function() { + _viewLastRoom() { dis.dispatch({ action: 'view_room', room_id: localStorage.getItem('mx_last_room_id'), }); - }, + } /** * Called when the session is logged out */ - _onLoggedOut: function() { + _onLoggedOut() { this.notifyNewScreen('login'); this.setStateForNewView({ view: VIEWS.LOGIN, @@ -1264,12 +1255,12 @@ export default createReactClass({ this._setPageSubtitle(); ThemeController.isLogin = true; this._themeWatcher.recheck(); - }, + } /** * Called when the session is softly logged out */ - _onSoftLogout: function() { + _onSoftLogout() { this.notifyNewScreen('soft_logout'); this.setStateForNewView({ view: VIEWS.SOFT_LOGOUT, @@ -1279,7 +1270,7 @@ export default createReactClass({ }); this.subTitleStatus = ''; this._setPageSubtitle(); - }, + } /** * Called just before the matrix client is started @@ -1383,10 +1374,10 @@ export default createReactClass({ title: _t('Terms and Conditions'), description:

{ _t( - 'To continue using the %(homeserverDomain)s homeserver ' + - 'you must review and agree to our terms and conditions.', - { homeserverDomain: cli.getDomain() }, - ) } + 'To continue using the %(homeserverDomain)s homeserver ' + + 'you must review and agree to our terms and conditions.', + { homeserverDomain: cli.getDomain() }, + ) }

, button: _t('Review terms and conditions'), @@ -1533,14 +1524,14 @@ export default createReactClass({ // A later sync can/will correct the tint to be the right value for the user const colorScheme = SettingsStore.getValue("roomColor"); Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color); - }, + } /** * Called shortly after the matrix client has started. Useful for * setting up anything that requires the client to be started. * @private */ - _onClientStarted: function() { + _onClientStarted() { const cli = MatrixClientPeg.get(); if (cli.isCryptoEnabled()) { @@ -1559,9 +1550,9 @@ export default createReactClass({ !SettingsStore.getValue("feature_cross_signing"), ); } - }, + } - showScreen: function(screen, params) { + showScreen(screen, params) { if (screen == 'register') { dis.dispatch({ action: 'start_registration', @@ -1706,21 +1697,21 @@ export default createReactClass({ } else { console.info("Ignoring showScreen for '%s'", screen); } - }, + } - notifyNewScreen: function(screen) { + notifyNewScreen(screen) { if (this.props.onNewScreen) { this.props.onNewScreen(screen); } this._setPageSubtitle(); - }, + } - onAliasClick: function(event, alias) { + onAliasClick(event, alias) { event.preventDefault(); dis.dispatch({action: 'view_room', room_alias: alias}); - }, + } - onUserClick: function(event, userId) { + onUserClick(event, userId) { event.preventDefault(); const member = new Matrix.RoomMember(null, userId); @@ -1729,22 +1720,22 @@ export default createReactClass({ action: 'view_user', member: member, }); - }, + } - onGroupClick: function(event, groupId) { + onGroupClick(event, groupId) { event.preventDefault(); dis.dispatch({action: 'view_group', group_id: groupId}); - }, + } - onLogoutClick: function(event) { + onLogoutClick(event) { dis.dispatch({ action: 'logout', }); event.stopPropagation(); event.preventDefault(); - }, + } - handleResize: function(e) { + handleResize = (e) => { const hideLhsThreshold = 1000; const showLhsThreshold = 1000; @@ -1757,49 +1748,49 @@ export default createReactClass({ this.state.resizeNotifier.notifyWindowResized(); this._windowWidth = window.innerWidth; - }, + }; _dispatchTimelineResize() { dis.dispatch({ action: 'timeline_resize' }); - }, + } - onRoomCreated: function(roomId) { + onRoomCreated(roomId) { dis.dispatch({ action: "view_room", room_id: roomId, }); - }, + } - onRegisterClick: function() { + onRegisterClick = () => { this.showScreen("register"); - }, + }; - onLoginClick: function() { + onLoginClick = () => { this.showScreen("login"); - }, + }; - onForgotPasswordClick: function() { + onForgotPasswordClick = () => { this.showScreen("forgot_password"); - }, + }; - onRegisterFlowComplete: function(credentials, password) { + onRegisterFlowComplete = (credentials, password) => { return this.onUserCompletedLoginFlow(credentials, password); - }, + }; // returns a promise which resolves to the new MatrixClient - onRegistered: function(credentials) { + onRegistered(credentials) { return Lifecycle.setLoggedIn(credentials); - }, + } - onFinishPostRegistration: function() { + onFinishPostRegistration = () => { // Don't confuse this with "PageType" which is the middle window to show this.setState({ view: VIEWS.LOGGED_IN, }); this.showScreen("settings"); - }, + }; - onVersion: function(current, latest, releaseNotes) { + onVersion(current, latest, releaseNotes) { this.setState({ version: current, newVersion: latest, @@ -1807,9 +1798,9 @@ export default createReactClass({ newVersionReleaseNotes: releaseNotes, checkingForUpdate: null, }); - }, + } - onSendEvent: function(roomId, event) { + onSendEvent(roomId, event) { const cli = MatrixClientPeg.get(); if (!cli) { dis.dispatch({action: 'message_send_failed'}); @@ -1821,9 +1812,9 @@ export default createReactClass({ }, (err) => { dis.dispatch({action: 'message_send_failed'}); }); - }, + } - _setPageSubtitle: function(subtitle='') { + _setPageSubtitle(subtitle='') { if (this.state.currentRoomId) { const client = MatrixClientPeg.get(); const room = client && client.getRoom(this.state.currentRoomId); @@ -1834,9 +1825,9 @@ export default createReactClass({ subtitle = `${this.subTitleStatus} ${subtitle}`; } document.title = `${SdkConfig.get().brand || 'Riot'} ${subtitle}`; - }, + } - updateStatusIndicator: function(state, prevState) { + updateStatusIndicator(state, prevState) { const notifCount = countRoomsWithNotif(MatrixClientPeg.get().getRooms()).count; if (PlatformPeg.get()) { @@ -1853,28 +1844,28 @@ export default createReactClass({ } this._setPageSubtitle(); - }, + } onCloseAllSettings() { dis.dispatch({ action: 'close_settings' }); - }, + } - onServerConfigChange(config) { + onServerConfigChange = (config) => { this.setState({serverConfig: config}); - }, + }; - _makeRegistrationUrl: function(params) { + _makeRegistrationUrl = (params) => { if (this.props.startingFragmentQueryParams.referrer) { params.referrer = this.props.startingFragmentQueryParams.referrer; } return this.props.makeRegistrationUrl(params); - }, + }; - _collectLoggedInView: function(ref) { + _collectLoggedInView = (ref) => { this._loggedInView = ref; - }, + }; - async onUserCompletedLoginFlow(credentials, password) { + onUserCompletedLoginFlow = async (credentials, password) => { this._accountPassword = password; // self-destruct the password after 5mins if (this._accountPasswordTimer !== null) clearTimeout(this._accountPasswordTimer); @@ -1937,14 +1928,14 @@ export default createReactClass({ this.setState({ pendingInitialSync: false }); return setLoggedInPromise; - }, + }; // complete security / e2e setup has finished - onCompleteSecurityE2eSetupFinished() { + onCompleteSecurityE2eSetupFinished = () => { this._onLoggedIn(); - }, + }; - render: function() { + render() { // console.log(`Rendering MatrixChat with view ${this.state.view}`); let view; @@ -1994,13 +1985,13 @@ export default createReactClass({ const LoggedInView = sdk.getComponent('structures.LoggedInView'); view = ( ); } else { @@ -2082,5 +2073,5 @@ export default createReactClass({ return {view} ; - }, -}); + } +} From d915e613dc6e9ebb59d1d6480d44e8b2d0fb40eb Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 22 Apr 2020 12:27:39 +0100 Subject: [PATCH 042/237] Convert promise utility module to tyepscript Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/utils/{promise.js => promise.ts} | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) rename src/utils/{promise.js => promise.ts} (65%) diff --git a/src/utils/promise.js b/src/utils/promise.ts similarity index 65% rename from src/utils/promise.js rename to src/utils/promise.ts index d7e8d2eae1..553e1e1959 100644 --- a/src/utils/promise.js +++ b/src/utils/promise.ts @@ -1,5 +1,5 @@ /* -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2019, 2020 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,15 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -// @flow - // Returns a promise which resolves with a given value after the given number of ms -export const sleep = (ms: number, value: any): Promise => new Promise((resolve => { setTimeout(resolve, ms, value); })); +export function sleep(ms: number, value: T): Promise { + return new Promise((resolve => { setTimeout(resolve, ms, value); })); +} // Returns a promise which resolves when the input promise resolves with its value // or when the timeout of ms is reached with the value of given timeoutValue -export async function timeout(promise: Promise, timeoutValue: any, ms: number): Promise { - const timeoutPromise = new Promise((resolve) => { +export async function timeout(promise: Promise, timeoutValue: T, ms: number): Promise { + const timeoutPromise = new Promise((resolve) => { const timeoutId = setTimeout(resolve, ms, timeoutValue); promise.then(() => { clearTimeout(timeoutId); @@ -32,12 +32,18 @@ export async function timeout(promise: Promise, timeoutValue: any, ms: number): return Promise.race([promise, timeoutPromise]); } +export interface IDeferred { + resolve: (T) => void; + reject: (any) => void; + promise: Promise; +} + // Returns a Deferred -export function defer(): {resolve: () => {}, reject: () => {}, promise: Promise} { +export function defer(): IDeferred { let resolve; let reject; - const promise = new Promise((_resolve, _reject) => { + const promise = new Promise((_resolve, _reject) => { resolve = _resolve; reject = _reject; }); @@ -46,11 +52,12 @@ export function defer(): {resolve: () => {}, reject: () => {}, promise: Promise} } // Promise.allSettled polyfill until browser support is stable in Firefox -export function allSettled(promises: Promise[]): {status: string, value?: any, reason?: any}[] { +export function allSettled(promises: Promise[]): Promise | ISettledRejected>> { if (Promise.allSettled) { - return Promise.allSettled(promises); + return Promise.allSettled(promises); } + // @ts-ignore - typescript isn't smart enough to see the disjoint here return Promise.all(promises.map((promise) => { return promise.then(value => ({ status: "fulfilled", From 01abb61e9afa513533919ed21c96d73907739192 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 22 Apr 2020 13:08:33 +0100 Subject: [PATCH 043/237] C Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/@types/global.d.ts | 13 + .../{MatrixChat.js => MatrixChat.tsx} | 518 ++++++++++-------- src/utils/promise.ts | 2 +- 3 files changed, 291 insertions(+), 242 deletions(-) rename src/components/structures/{MatrixChat.js => MatrixChat.tsx} (86%) diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 1931c0b1d0..e6e339d067 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -37,4 +37,17 @@ declare global { interface StorageEstimate { usageDetails?: {[key: string]: number}; } + + export interface ISettledFulfilled { + status: "fulfilled"; + value: T; + } + export interface ISettledRejected { + status: "rejected"; + reason: any; + } + + interface PromiseConstructor { + allSettled(promises: Promise[]): Promise | ISettledRejected>>; + } } diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.tsx similarity index 86% rename from src/components/structures/MatrixChat.js rename to src/components/structures/MatrixChat.tsx index e93b81109a..576f92408a 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.tsx @@ -17,10 +17,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; -import createReactClass from 'create-react-class'; -import PropTypes from 'prop-types'; -import * as Matrix from "matrix-js-sdk"; +import React, {createRef} from 'react'; +import {InvalidStoreError} from "matrix-js-sdk/src/errors"; +import {RoomMember} from "matrix-js-sdk/src/models/room-member"; +import {MatrixEvent} from "matrix-js-sdk/src/models/event"; import { isCryptoAvailable } from 'matrix-js-sdk/src/crypto'; // focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss @@ -63,44 +63,45 @@ import DMRoomMap from '../../utils/DMRoomMap'; import { countRoomsWithNotif } from '../../RoomNotifs'; import { ThemeWatcher } from "../../theme"; import { storeRoomAliasInCache } from '../../RoomAliasCache'; -import { defer } from "../../utils/promise"; +import {defer, IDeferred} from "../../utils/promise"; import ToastStore from "../../stores/ToastStore"; import * as StorageManager from "../../utils/StorageManager"; +import type LoggedInView from "./LoggedInView"; /** constants for MatrixChat.state.view */ -export const VIEWS = { +export enum VIEWS { // a special initial state which is only used at startup, while we are // trying to re-animate a matrix client or register as a guest. - LOADING: 0, + LOADING = 0, // we are showing the welcome view - WELCOME: 1, + WELCOME = 1, // we are showing the login view - LOGIN: 2, + LOGIN = 2, // we are showing the registration view - REGISTER: 3, + REGISTER = 3, // completing the registration flow - POST_REGISTRATION: 4, + POST_REGISTRATION = 4, // showing the 'forgot password' view - FORGOT_PASSWORD: 5, + FORGOT_PASSWORD = 5, // showing flow to trust this new device with cross-signing - COMPLETE_SECURITY: 6, + COMPLETE_SECURITY = 6, // flow to setup SSSS / cross-signing on this account - E2E_SETUP: 7, + E2E_SETUP = 7, // we are logged in with an active matrix client. - LOGGED_IN: 8, + LOGGED_IN = 8, // We are logged out (invalid token) but have our local state again. The user // should log back in to rehydrate the client. - SOFT_LOGOUT: 9, -}; + SOFT_LOGOUT = 9, +} // Actions that are redirected through the onboarding process prior to being // re-dispatched. NOTE: some actions are non-trivial and would require @@ -112,42 +113,89 @@ const ONBOARDING_FLOW_STARTERS = [ 'view_create_group', ]; -export default class MatrixChat extends React.PureComponent { +interface IScreen { + screen: string; + params?: object; +} + +interface IRoomInfo { + room_id?: string; + room_alias?: string; + event_id?: string; + + auto_join?: boolean; + highlighted?: boolean; + third_party_invite?: object; + oob_data?: object; + via_servers?: string[]; +} + +interface IProps { // TODO type things better + config: Record; + serverConfig?: ValidatedServerConfig; + ConferenceHandler?: any; + onNewScreen: (string) => void; + enableGuest?: boolean; + // the queryParams extracted from the [real] query-string of the URI + realQueryParams?: Record; + // the initial queryParams extracted from the hash-fragment of the URI + startingFragmentQueryParams?: Record; + // called when we have completed a token login + onTokenLoginCompleted?: () => void; + // Represents the screen to display as a result of parsing the initial window.location + initialScreenAfterLogin?: IScreen; + // displayname, if any, to set on the device when logging in/registering. + defaultDeviceDisplayName?: string, + // A function that makes a registration URL + makeRegistrationUrl: (object) => string, +} + +interface IState { + // the master view we are showing. + view: VIEWS; + // What the LoggedInView would be showing if visible + page_type?: PageTypes; + // The ID of the room we're viewing. This is either populated directly + // in the case where we view a room by ID or by RoomView when it resolves + // what ID an alias points at. + currentRoomId?: string; + currentGroupId?: string; + currentGroupIsNew?: boolean; + // If we're trying to just view a user ID (i.e. /user URL), this is it + currentUserId?: string; + // this is persisted as mx_lhs_size, loaded in LoggedInView + collapseLhs: boolean; + leftDisabled: boolean; + middleDisabled: boolean; + // the right panel's disabled state is tracked in its store. + version?: string; + newVersion?: string; + hasNewVersion: boolean; + newVersionReleaseNotes?: string; + checkingForUpdate?: string; // updateCheckStatusEnum + showCookieBar: boolean; + // Parameters used in the registration dance with the IS + register_client_secret?: string; + register_session_id?: string; + register_id_sid?: string; + // When showing Modal dialogs we need to set aria-hidden on the root app element + // and disable it when there are no dialogs + hideToSRUsers: boolean; + syncError?: Error; + resizeNotifier: ResizeNotifier; + showNotifierToolbar: boolean; + serverConfig?: ValidatedServerConfig; + ready: boolean; + thirdPartyInvite?: object; + roomOobData?: object; + viaServers?: string[]; + pendingInitialSync?: boolean; +} + +export default class MatrixChat extends React.PureComponent { static VIEWS = VIEWS; // we export this so that the integration tests can use it :-S static displayName = "MatrixChat"; - static propTypes = { - config: PropTypes.object, - serverConfig: PropTypes.instanceOf(ValidatedServerConfig), - ConferenceHandler: PropTypes.any, - onNewScreen: PropTypes.func, - registrationUrl: PropTypes.string, - enableGuest: PropTypes.bool, - - // the queryParams extracted from the [real] query-string of the URI - realQueryParams: PropTypes.object, - - // the initial queryParams extracted from the hash-fragment of the URI - startingFragmentQueryParams: PropTypes.object, - - // called when we have completed a token login - onTokenLoginCompleted: PropTypes.func, - - // Represents the screen to display as a result of parsing the initial - // window.location - initialScreenAfterLogin: PropTypes.shape({ - screen: PropTypes.string.isRequired, - params: PropTypes.object, - }), - - // displayname, if any, to set on the device when logging - // in/registering. - defaultDeviceDisplayName: PropTypes.string, - - // A function that makes a registration URL - makeRegistrationUrl: PropTypes.func.isRequired, - }; - static defaultProps = { realQueryParams: {}, startingFragmentQueryParams: {}, @@ -155,51 +203,46 @@ export default class MatrixChat extends React.PureComponent { onTokenLoginCompleted: () => {}, }; + firstSyncComplete: boolean; + firstSyncPromise: IDeferred; + + private screenAfterLogin?: IScreen; + private windowWidth: number; + private pageChanging: boolean; + private accountPassword?: string; + private accountPasswordTimer?: NodeJS.Timeout; + private focusComposer: boolean; + private subTitleStatus: string; + + private readonly loggedInView: React.RefObject; + private readonly dispatcherRef: any; + private readonly themeWatcher: ThemeWatcher; + constructor(props, context) { super(props, context); this.state = { - // the master view we are showing. view: VIEWS.LOADING, - - // What the LoggedInView would be showing if visible - page_type: null, - - // The ID of the room we're viewing. This is either populated directly - // in the case where we view a room by ID or by RoomView when it resolves - // what ID an alias points at. - currentRoomId: null, - - // If we're trying to just view a user ID (i.e. /user URL), this is it - viewUserId: null, - // this is persisted as mx_lhs_size, loaded in LoggedInView collapseLhs: false, leftDisabled: false, middleDisabled: false, - // the right panel's disabled state is tracked in its store. - version: null, - newVersion: null, hasNewVersion: false, newVersionReleaseNotes: null, checkingForUpdate: null, showCookieBar: false, - // Parameters used in the registration dance with the IS - register_client_secret: null, - register_session_id: null, - register_id_sid: null, - - // When showing Modal dialogs we need to set aria-hidden on the root app element - // and disable it when there are no dialogs hideToSRUsers: false, syncError: null, // If the current syncing status is ERROR, the error object, otherwise null. resizeNotifier: new ResizeNotifier(), showNotifierToolbar: false, + ready: false, }; + this.loggedInView = createRef(); + SdkConfig.put(this.props.config); // Used by _viewRoom before getting state from sync @@ -213,13 +256,13 @@ export default class MatrixChat extends React.PureComponent { // a thing to call showScreen with once login completes. this is kept // outside this.state because updating it should never trigger a // rerender. - this._screenAfterLogin = this.props.initialScreenAfterLogin; + this.screenAfterLogin = this.props.initialScreenAfterLogin; - this._windowWidth = 10000; + this.windowWidth = 10000; this.handleResize(); window.addEventListener('resize', this.handleResize); - this._pageChanging = false; + this.pageChanging = false; // check we have the right tint applied for this theme. // N.B. we don't call the whole of setTheme() here as we may be @@ -227,7 +270,7 @@ export default class MatrixChat extends React.PureComponent { Tinter.tint(); // For PersistentElement - this.state.resizeNotifier.on("middlePanelResized", this._dispatchTimelineResize); + this.state.resizeNotifier.on("middlePanelResized", this.dispatchTimelineResize); // Force users to go through the soft logout page if they're soft logged out if (Lifecycle.isSoftLogout()) { @@ -237,12 +280,12 @@ export default class MatrixChat extends React.PureComponent { Lifecycle.loadSession({}); } - this._accountPassword = null; - this._accountPasswordTimer = null; + this.accountPassword = null; + this.accountPasswordTimer = null; this.dispatcherRef = dis.register(this.onAction); - this._themeWatcher = new ThemeWatcher(); - this._themeWatcher.start(); + this.themeWatcher = new ThemeWatcher(); + this.themeWatcher.start(); this.focusComposer = false; @@ -279,17 +322,16 @@ export default class MatrixChat extends React.PureComponent { // if the user has followed a login or register link, don't reanimate // the old creds, but rather go straight to the relevant page - const firstScreen = this._screenAfterLogin ? - this._screenAfterLogin.screen : null; + const firstScreen = this.screenAfterLogin ? this.screenAfterLogin.screen : null; if (firstScreen === 'login' || firstScreen === 'register' || firstScreen === 'forgot_password') { - this._showScreenAfterLogin(); + this.showScreenAfterLogin(); return; } - return this._loadSession(); + return this.loadSession(); }); } @@ -325,12 +367,11 @@ export default class MatrixChat extends React.PureComponent { componentWillUnmount() { Lifecycle.stopMatrixClient(); dis.unregister(this.dispatcherRef); - this._themeWatcher.stop(); - window.removeEventListener("focus", this.onFocus); + this.themeWatcher.stop(); window.removeEventListener('resize', this.handleResize); - this.state.resizeNotifier.removeListener("middlePanelResized", this._dispatchTimelineResize); + this.state.resizeNotifier.removeListener("middlePanelResized", this.dispatchTimelineResize); - if (this._accountPasswordTimer !== null) clearTimeout(this._accountPasswordTimer); + if (this.accountPasswordTimer !== null) clearTimeout(this.accountPasswordTimer); } getFallbackHsUrl() { @@ -348,7 +389,7 @@ export default class MatrixChat extends React.PureComponent { return {serverConfig: props}; } - _loadSession() { + private loadSession() { // the extra Promise.resolve() ensures that synchronous exceptions hit the same codepath as // asynchronous ones. return Promise.resolve().then(() => { @@ -376,11 +417,11 @@ export default class MatrixChat extends React.PureComponent { // This shouldn't happen because UNSAFE_componentWillUpdate and componentDidUpdate // are used. - if (this._pageChanging) { + if (this.pageChanging) { console.warn('MatrixChat.startPageChangeTimer: timer already started'); return; } - this._pageChanging = true; + this.pageChanging = true; performance.mark('riot_MatrixChat_page_change_start'); } @@ -388,11 +429,11 @@ export default class MatrixChat extends React.PureComponent { // Tor doesn't support performance if (!performance || !performance.mark) return null; - if (!this._pageChanging) { + if (!this.pageChanging) { console.warn('MatrixChat.stopPageChangeTimer: timer not started'); return; } - this._pageChanging = false; + this.pageChanging = false; performance.mark('riot_MatrixChat_page_change_stop'); performance.measure( 'riot_MatrixChat_page_change_delta', @@ -409,18 +450,18 @@ export default class MatrixChat extends React.PureComponent { return measurement.duration; } - shouldTrackPageChange(prevState, state) { + shouldTrackPageChange(prevState: IState, state: IState) { return prevState.currentRoomId !== state.currentRoomId || prevState.view !== state.view || prevState.page_type !== state.page_type; } - setStateForNewView(state) { + setStateForNewView(state: Partial) { if (state.view === undefined) { throw new Error("setStateForNewView with no view!"); } const newState = { - viewUserId: null, + currentUserId: null, }; Object.assign(newState, state); this.setState(newState); @@ -479,29 +520,29 @@ export default class MatrixChat extends React.PureComponent { break; case 'start_registration': if (Lifecycle.isSoftLogout()) { - this._onSoftLogout(); + this.onSoftLogout(); break; } // This starts the full registration flow if (payload.screenAfterLogin) { - this._screenAfterLogin = payload.screenAfterLogin; + this.screenAfterLogin = payload.screenAfterLogin; } - this._startRegistration(payload.params || {}); + this.startRegistration(payload.params || {}); break; case 'start_login': if (Lifecycle.isSoftLogout()) { - this._onSoftLogout(); + this.onSoftLogout(); break; } if (payload.screenAfterLogin) { - this._screenAfterLogin = payload.screenAfterLogin; + this.screenAfterLogin = payload.screenAfterLogin; } this.setStateForNewView({ view: VIEWS.LOGIN, }); this.notifyNewScreen('login'); ThemeController.isLogin = true; - this._themeWatcher.recheck(); + this.themeWatcher.recheck(); break; case 'start_post_registration': this.setState({ @@ -520,7 +561,7 @@ export default class MatrixChat extends React.PureComponent { }); break; case 'leave_room': - this._leaveRoom(payload.room_id); + this.leaveRoom(payload.room_id); break; case 'reject_invite': Modal.createTrackedDialog('Reject invitation', '', QuestionDialog, { @@ -549,14 +590,14 @@ export default class MatrixChat extends React.PureComponent { }); break; case 'view_user_info': - this._viewUser(payload.userId, payload.subAction); + this.viewUser(payload.userId, payload.subAction); break; case 'view_room': { // Takes either a room ID or room alias: if switching to a room the client is already // known to be in (eg. user clicks on a room in the recents panel), supply the ID // If the user is clicking on a room in the context of the alias being presented // to them, supply the room alias. If both are supplied, the room ID will be ignored. - const promise = this._viewRoom(payload); + const promise = this.viewRoom(payload); if (payload.deferred_action) { promise.then(() => { dis.dispatch(payload.deferred_action); @@ -565,13 +606,13 @@ export default class MatrixChat extends React.PureComponent { break; } case 'view_prev_room': - this._viewNextRoom(-1); + this.viewNextRoom(-1); break; case 'view_next_room': - this._viewNextRoom(1); + this.viewNextRoom(1); break; case 'view_indexed_room': - this._viewIndexedRoom(payload.roomIndex); + this.viewIndexedRoom(payload.roomIndex); break; case 'view_user_settings': { const UserSettingsDialog = sdk.getComponent("dialogs.UserSettingsDialog"); @@ -579,11 +620,11 @@ export default class MatrixChat extends React.PureComponent { /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); // View the welcome or home page if we need something to look at - this._viewSomethingBehindModal(); + this.viewSomethingBehindModal(); break; } case 'view_create_room': - this._createRoom(); + this.createRoom(); break; case 'view_create_group': { const CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog"); @@ -596,27 +637,27 @@ export default class MatrixChat extends React.PureComponent { 'mx_RoomDirectory_dialogWrapper', false, true); // View the welcome or home page if we need something to look at - this._viewSomethingBehindModal(); + this.viewSomethingBehindModal(); break; } case 'view_my_groups': - this._setPage(PageTypes.MyGroups); + this.setPage(PageTypes.MyGroups); this.notifyNewScreen('groups'); break; case 'view_group': - this._viewGroup(payload); + this.viewGroup(payload); break; case 'view_welcome_page': - this._viewWelcome(); + this.viewWelcome(); break; case 'view_home_page': - this._viewHome(); + this.viewHome(); break; case 'view_set_mxid': - this._setMxId(payload); + this.setMxId(payload); break; case 'view_start_chat_or_reuse': - this._chatCreateOrReuse(payload.user_id); + this.chatCreateOrReuse(payload.user_id); break; case 'view_create_chat': showStartChatInviteDialog(); @@ -629,7 +670,7 @@ export default class MatrixChat extends React.PureComponent { // the last room we were looking at or some reasonable default/guess. We don't // have to worry about email invites or similar being re-triggered because the // function will have cleared that state and not execute that path. - this._showScreenAfterLogin(); + this.showScreenAfterLogin(); break; case 'toggle_my_groups': // We just dispatch the page change rather than have to worry about @@ -670,25 +711,25 @@ export default class MatrixChat extends React.PureComponent { this.state.view !== VIEWS.COMPLETE_SECURITY && this.state.view !== VIEWS.E2E_SETUP ) { - this._onLoggedIn(); + this.onLoggedIn(); } break; case 'on_client_not_viable': - this._onSoftLogout(); + this.onSoftLogout(); break; case 'on_logged_out': - this._onLoggedOut(); + this.onLoggedOut(); break; case 'will_start_client': this.setState({ready: false}, () => { // if the client is about to start, we are, by definition, not ready. // Set ready to false now, then it'll be set to true when the sync // listener we set below fires. - this._onWillStartClient(); + this.onWillStartClient(); }); break; case 'client_started': - this._onClientStarted(); + this.onClientStarted(); break; case 'new_version': this.onVersion( @@ -732,14 +773,14 @@ export default class MatrixChat extends React.PureComponent { } }; - _setPage(pageType) { + private setPage(pageType: string) { this.setState({ page_type: pageType, }); } - async _startRegistration(params) { - const newState = { + private async startRegistration(params: {[key: string]: string}) { + const newState: Partial = { view: VIEWS.REGISTER, }; @@ -762,12 +803,12 @@ export default class MatrixChat extends React.PureComponent { this.setStateForNewView(newState); ThemeController.isLogin = true; - this._themeWatcher.recheck(); + this.themeWatcher.recheck(); this.notifyNewScreen('register'); } // TODO: Move to RoomViewStore - _viewNextRoom(roomIndexDelta) { + private viewNextRoom(roomIndexDelta: number) { const allRooms = RoomListSorter.mostRecentActivityFirst( MatrixClientPeg.get().getRooms(), ); @@ -796,7 +837,7 @@ export default class MatrixChat extends React.PureComponent { } // TODO: Move to RoomViewStore - _viewIndexedRoom(roomIndex) { + private viewIndexedRoom(roomIndex: number) { const allRooms = RoomListSorter.mostRecentActivityFirst( MatrixClientPeg.get().getRooms(), ); @@ -825,18 +866,9 @@ export default class MatrixChat extends React.PureComponent { // @param {Object=} roomInfo.oob_data Object of additional data about the room // that has been passed out-of-band (eg. // room name and avatar from an invite email) - _viewRoom(roomInfo) { + private viewRoom(roomInfo: IRoomInfo) { this.focusComposer = true; - const newState = { - view: VIEWS.LOGGED_IN, - currentRoomId: roomInfo.room_id || null, - page_type: PageTypes.RoomView, - thirdPartyInvite: roomInfo.third_party_invite, - roomOobData: roomInfo.oob_data, - viaServers: roomInfo.via_servers, - }; - if (roomInfo.room_alias) { console.log( `Switching to room alias ${roomInfo.room_alias} at event ` + @@ -881,70 +913,77 @@ export default class MatrixChat extends React.PureComponent { if (roomInfo.event_id && roomInfo.highlighted) { presentedId += "/" + roomInfo.event_id; } - newState.ready = true; - this.setState(newState, () => { + this.setState({ + view: VIEWS.LOGGED_IN, + currentRoomId: roomInfo.room_id || null, + page_type: PageTypes.RoomView, + thirdPartyInvite: roomInfo.third_party_invite, + roomOobData: roomInfo.oob_data, + viaServers: roomInfo.via_servers, + ready: true, + }, () => { this.notifyNewScreen('room/' + presentedId); }); }); } - _viewGroup(payload) { + private viewGroup(payload) { const groupId = payload.group_id; this.setState({ currentGroupId: groupId, currentGroupIsNew: payload.group_is_new, }); - this._setPage(PageTypes.GroupView); + this.setPage(PageTypes.GroupView); this.notifyNewScreen('group/' + groupId); } - _viewSomethingBehindModal() { + private viewSomethingBehindModal() { if (this.state.view !== VIEWS.LOGGED_IN) { - this._viewWelcome(); + this.viewWelcome(); return; } if (!this.state.currentGroupId && !this.state.currentRoomId) { - this._viewHome(); + this.viewHome(); } } - _viewWelcome() { + private viewWelcome() { this.setStateForNewView({ view: VIEWS.WELCOME, }); this.notifyNewScreen('welcome'); ThemeController.isLogin = true; - this._themeWatcher.recheck(); + this.themeWatcher.recheck(); } - _viewHome() { + private viewHome() { // The home page requires the "logged in" view, so we'll set that. this.setStateForNewView({ view: VIEWS.LOGGED_IN, }); - this._setPage(PageTypes.HomePage); + this.setPage(PageTypes.HomePage); this.notifyNewScreen('home'); ThemeController.isLogin = false; - this._themeWatcher.recheck(); + this.themeWatcher.recheck(); } - _viewUser(userId, subAction) { + private viewUser(userId: string, subAction: string) { // Wait for the first sync so that `getRoom` gives us a room object if it's // in the sync response const waitForSync = this.firstSyncPromise ? this.firstSyncPromise.promise : Promise.resolve(); waitForSync.then(() => { if (subAction === 'chat') { - this._chatCreateOrReuse(userId); + this.chatCreateOrReuse(userId); return; } this.notifyNewScreen('user/' + userId); this.setState({currentUserId: userId}); - this._setPage(PageTypes.UserView); + this.setPage(PageTypes.UserView); }); } - _setMxId(payload) { + private setMxId(payload) { const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog'); const close = Modal.createTrackedDialog('Set MXID', '', SetMxIdDialog, { homeserverUrl: MatrixClientPeg.get().getHomeserverUrl(), @@ -974,7 +1013,7 @@ export default class MatrixChat extends React.PureComponent { }).close; } - async _createRoom() { + private async createRoom() { const CreateRoomDialog = sdk.getComponent('dialogs.CreateRoomDialog'); const modal = Modal.createTrackedDialog('Create Room', '', CreateRoomDialog); @@ -984,7 +1023,7 @@ export default class MatrixChat extends React.PureComponent { } } - _chatCreateOrReuse(userId) { + private chatCreateOrReuse(userId: string) { // Use a deferred action to reshow the dialog once the user has registered if (MatrixClientPeg.get().isGuest()) { // No point in making 2 DMs with welcome bot. This assumes view_set_mxid will @@ -1032,7 +1071,7 @@ export default class MatrixChat extends React.PureComponent { } } - _leaveRoomWarnings(roomId) { + private leaveRoomWarnings(roomId: string) { const roomToLeave = MatrixClientPeg.get().getRoom(roomId); // Show a warning if there are additional complications. const joinRules = roomToLeave.currentState.getStateEvents('m.room.join_rules', ''); @@ -1051,11 +1090,11 @@ export default class MatrixChat extends React.PureComponent { return warnings; } - _leaveRoom(roomId) { + private leaveRoom(roomId: string) { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const roomToLeave = MatrixClientPeg.get().getRoom(roomId); - const warnings = this._leaveRoomWarnings(roomId); + const warnings = this.leaveRoomWarnings(roomId); Modal.createTrackedDialog('Leave room', '', QuestionDialog, { title: _t("Leave room"), @@ -1121,7 +1160,7 @@ export default class MatrixChat extends React.PureComponent { * Starts a chat with the welcome user, if the user doesn't already have one * @returns {string} The room ID of the new room, or null if no room was created */ - async _startWelcomeUserChat() { + private async startWelcomeUserChat() { // We can end up with multiple tabs post-registration where the user // might then end up with a session and we don't want them all making // a chat with the welcome user: try to de-dupe. @@ -1175,22 +1214,22 @@ export default class MatrixChat extends React.PureComponent { /** * Called when a new logged in session has started */ - async _onLoggedIn() { + private async onLoggedIn() { ThemeController.isLogin = false; this.setStateForNewView({ view: VIEWS.LOGGED_IN }); // If a specific screen is set to be shown after login, show that above // all else, as it probably means the user clicked on something already. - if (this._screenAfterLogin && this._screenAfterLogin.screen) { + if (this.screenAfterLogin && this.screenAfterLogin.screen) { this.showScreen( - this._screenAfterLogin.screen, - this._screenAfterLogin.params, + this.screenAfterLogin.screen, + this.screenAfterLogin.params, ); - this._screenAfterLogin = null; + this.screenAfterLogin = null; } else if (MatrixClientPeg.currentUserIsJustRegistered()) { MatrixClientPeg.setJustRegisteredUserId(null); if (this.props.config.welcomeUserId && getCurrentLanguage().startsWith("en")) { - const welcomeUserRoom = await this._startWelcomeUserChat(); + const welcomeUserRoom = await this.startWelcomeUserChat(); if (welcomeUserRoom === null) { // We didn't redirect to the welcome user room, so show // the homepage. @@ -1202,24 +1241,24 @@ export default class MatrixChat extends React.PureComponent { dis.dispatch({action: 'view_home_page'}); } } else { - this._showScreenAfterLogin(); + this.showScreenAfterLogin(); } StorageManager.tryPersistStorage(); } - _showScreenAfterLogin() { + private showScreenAfterLogin() { // If screenAfterLogin is set, use that, then null it so that a second login will // result in view_home_page, _user_settings or _room_directory - if (this._screenAfterLogin && this._screenAfterLogin.screen) { + if (this.screenAfterLogin && this.screenAfterLogin.screen) { this.showScreen( - this._screenAfterLogin.screen, - this._screenAfterLogin.params, + this.screenAfterLogin.screen, + this.screenAfterLogin.params, ); - this._screenAfterLogin = null; + this.screenAfterLogin = null; } else if (localStorage && localStorage.getItem('mx_last_room_id')) { // Before defaulting to directory, show the last viewed room - this._viewLastRoom(); + this.viewLastRoom(); } else { if (MatrixClientPeg.get().isGuest()) { dis.dispatch({action: 'view_welcome_page'}); @@ -1233,7 +1272,7 @@ export default class MatrixChat extends React.PureComponent { } } - _viewLastRoom() { + private viewLastRoom() { dis.dispatch({ action: 'view_room', room_id: localStorage.getItem('mx_last_room_id'), @@ -1243,7 +1282,7 @@ export default class MatrixChat extends React.PureComponent { /** * Called when the session is logged out */ - _onLoggedOut() { + private onLoggedOut() { this.notifyNewScreen('login'); this.setStateForNewView({ view: VIEWS.LOGIN, @@ -1252,15 +1291,15 @@ export default class MatrixChat extends React.PureComponent { currentRoomId: null, }); this.subTitleStatus = ''; - this._setPageSubtitle(); + this.setPageSubtitle(); ThemeController.isLogin = true; - this._themeWatcher.recheck(); + this.themeWatcher.recheck(); } /** * Called when the session is softly logged out */ - _onSoftLogout() { + private onSoftLogout() { this.notifyNewScreen('soft_logout'); this.setStateForNewView({ view: VIEWS.SOFT_LOGOUT, @@ -1269,16 +1308,14 @@ export default class MatrixChat extends React.PureComponent { currentRoomId: null, }); this.subTitleStatus = ''; - this._setPageSubtitle(); + this.setPageSubtitle(); } /** * Called just before the matrix client is started * (useful for setting listeners) */ - _onWillStartClient() { - const self = this; - + private onWillStartClient() { // reset the 'have completed first sync' flag, // since we're about to start the client and therefore about // to do the first sync @@ -1292,9 +1329,9 @@ export default class MatrixChat extends React.PureComponent { // particularly noticeable when there are lots of 'limited' /sync responses // such as when laptops unsleep. // https://github.com/vector-im/riot-web/issues/3307#issuecomment-282895568 - cli.setCanResetTimelineCallback(function(roomId) { - console.log("Request to reset timeline in room ", roomId, " viewing:", self.state.currentRoomId); - if (roomId !== self.state.currentRoomId) { + cli.setCanResetTimelineCallback((roomId) => { + console.log("Request to reset timeline in room ", roomId, " viewing:", this.state.currentRoomId); + if (roomId !== this.state.currentRoomId) { // It is safe to remove events from rooms we are not viewing. return true; } @@ -1302,13 +1339,13 @@ export default class MatrixChat extends React.PureComponent { // this if we are not scrolled up in the view. To find out, delegate to // the timeline panel. If the timeline panel doesn't exist, then we assume // it is safe to reset the timeline. - if (!self._loggedInView || !self._loggedInView.child) { + if (!this.loggedInView.current || !this.loggedInView.current) { return true; } - return self._loggedInView.child.canResetTimelineInRoom(roomId); + return this.loggedInView.current.canResetTimelineInRoom(roomId); }); - cli.on('sync', function(state, prevState, data) { + cli.on('sync', (state, prevState, data) => { // LifecycleStore and others cannot directly subscribe to matrix client for // events because flux only allows store state changes during flux dispatches. // So dispatch directly from here. Ideally we'd use a SyncStateStore that @@ -1317,26 +1354,26 @@ export default class MatrixChat extends React.PureComponent { dis.dispatch({action: 'sync_state', prevState, state}); if (state === "ERROR" || state === "RECONNECTING") { - if (data.error instanceof Matrix.InvalidStoreError) { + if (data.error instanceof InvalidStoreError) { Lifecycle.handleInvalidStoreError(data.error); } - self.setState({syncError: data.error || true}); - } else if (self.state.syncError) { - self.setState({syncError: null}); + this.setState({syncError: data.error || true}); + } else if (this.state.syncError) { + this.setState({syncError: null}); } - self.updateStatusIndicator(state, prevState); + this.updateStatusIndicator(state, prevState); if (state === "SYNCING" && prevState === "SYNCING") { return; } console.info("MatrixClient sync state => %s", state); if (state !== "PREPARED") { return; } - self.firstSyncComplete = true; - self.firstSyncPromise.resolve(); + this.firstSyncComplete = true; + this.firstSyncPromise.resolve(); dis.dispatch({action: 'focus_composer'}); - self.setState({ + this.setState({ ready: true, showNotifierToolbar: Notifier.shouldShowToolbar(), }); @@ -1531,7 +1568,7 @@ export default class MatrixChat extends React.PureComponent { * setting up anything that requires the client to be started. * @private */ - _onClientStarted() { + private onClientStarted() { const cli = MatrixClientPeg.get(); if (cli.isCryptoEnabled()) { @@ -1552,7 +1589,7 @@ export default class MatrixChat extends React.PureComponent { } } - showScreen(screen, params) { + showScreen(screen: string, params?: {[key: string]: any}) { if (screen == 'register') { dis.dispatch({ action: 'start_registration', @@ -1571,7 +1608,7 @@ export default class MatrixChat extends React.PureComponent { } else if (screen === 'soft_logout') { if (MatrixClientPeg.get() && MatrixClientPeg.get().getUserId() && !Lifecycle.isSoftLogout()) { // Logged in - visit a room - this._viewLastRoom(); + this.viewLastRoom(); } else { // Ultimately triggers soft_logout if needed dis.dispatch({ @@ -1670,6 +1707,8 @@ export default class MatrixChat extends React.PureComponent { highlighted: Boolean(eventId), third_party_invite: thirdPartyInvite, oob_data: oobData, + room_alias: undefined, + room_id: undefined, }; if (roomString[0] == '#') { payload.room_alias = roomString; @@ -1699,22 +1738,22 @@ export default class MatrixChat extends React.PureComponent { } } - notifyNewScreen(screen) { + notifyNewScreen(screen: string) { if (this.props.onNewScreen) { this.props.onNewScreen(screen); } - this._setPageSubtitle(); + this.setPageSubtitle(); } - onAliasClick(event, alias) { + onAliasClick(event: MouseEvent, alias: string) { event.preventDefault(); dis.dispatch({action: 'view_room', room_alias: alias}); } - onUserClick(event, userId) { + onUserClick(event: MouseEvent, userId: string) { event.preventDefault(); - const member = new Matrix.RoomMember(null, userId); + const member = new RoomMember(null, userId); if (!member) { return; } dis.dispatch({ action: 'view_user', @@ -1722,12 +1761,12 @@ export default class MatrixChat extends React.PureComponent { }); } - onGroupClick(event, groupId) { + onGroupClick(event: MouseEvent, groupId: string) { event.preventDefault(); dis.dispatch({action: 'view_group', group_id: groupId}); } - onLogoutClick(event) { + onLogoutClick(event: React.MouseEvent) { dis.dispatch({ action: 'logout', }); @@ -1735,26 +1774,26 @@ export default class MatrixChat extends React.PureComponent { event.preventDefault(); } - handleResize = (e) => { + handleResize = () => { const hideLhsThreshold = 1000; const showLhsThreshold = 1000; - if (this._windowWidth > hideLhsThreshold && window.innerWidth <= hideLhsThreshold) { + if (this.windowWidth > hideLhsThreshold && window.innerWidth <= hideLhsThreshold) { dis.dispatch({ action: 'hide_left_panel' }); } - if (this._windowWidth <= showLhsThreshold && window.innerWidth > showLhsThreshold) { + if (this.windowWidth <= showLhsThreshold && window.innerWidth > showLhsThreshold) { dis.dispatch({ action: 'show_left_panel' }); } this.state.resizeNotifier.notifyWindowResized(); - this._windowWidth = window.innerWidth; + this.windowWidth = window.innerWidth; }; - _dispatchTimelineResize() { + private dispatchTimelineResize() { dis.dispatch({ action: 'timeline_resize' }); } - onRoomCreated(roomId) { + onRoomCreated(roomId: string) { dis.dispatch({ action: "view_room", room_id: roomId, @@ -1773,12 +1812,12 @@ export default class MatrixChat extends React.PureComponent { this.showScreen("forgot_password"); }; - onRegisterFlowComplete = (credentials, password) => { + onRegisterFlowComplete = (credentials: object, password: string) => { return this.onUserCompletedLoginFlow(credentials, password); }; // returns a promise which resolves to the new MatrixClient - onRegistered(credentials) { + onRegistered(credentials: object) { return Lifecycle.setLoggedIn(credentials); } @@ -1790,7 +1829,7 @@ export default class MatrixChat extends React.PureComponent { this.showScreen("settings"); }; - onVersion(current, latest, releaseNotes) { + onVersion(current: string, latest: string, releaseNotes?: string) { this.setState({ version: current, newVersion: latest, @@ -1800,7 +1839,7 @@ export default class MatrixChat extends React.PureComponent { }); } - onSendEvent(roomId, event) { + onSendEvent(roomId: string, event: MatrixEvent) { const cli = MatrixClientPeg.get(); if (!cli) { dis.dispatch({action: 'message_send_failed'}); @@ -1814,7 +1853,7 @@ export default class MatrixChat extends React.PureComponent { }); } - _setPageSubtitle(subtitle='') { + private setPageSubtitle(subtitle='') { if (this.state.currentRoomId) { const client = MatrixClientPeg.get(); const room = client && client.getRoom(this.state.currentRoomId); @@ -1827,7 +1866,7 @@ export default class MatrixChat extends React.PureComponent { document.title = `${SdkConfig.get().brand || 'Riot'} ${subtitle}`; } - updateStatusIndicator(state, prevState) { + updateStatusIndicator(state: string, prevState: string) { const notifCount = countRoomsWithNotif(MatrixClientPeg.get().getRooms()).count; if (PlatformPeg.get()) { @@ -1843,35 +1882,31 @@ export default class MatrixChat extends React.PureComponent { this.subTitleStatus += `[${notifCount}]`; } - this._setPageSubtitle(); + this.setPageSubtitle(); } onCloseAllSettings() { dis.dispatch({ action: 'close_settings' }); } - onServerConfigChange = (config) => { - this.setState({serverConfig: config}); + onServerConfigChange = (serverConfig: ValidatedServerConfig) => { + this.setState({serverConfig}); }; - _makeRegistrationUrl = (params) => { + private makeRegistrationUrl = (params: {[key: string]: string}) => { if (this.props.startingFragmentQueryParams.referrer) { params.referrer = this.props.startingFragmentQueryParams.referrer; } return this.props.makeRegistrationUrl(params); }; - _collectLoggedInView = (ref) => { - this._loggedInView = ref; - }; - - onUserCompletedLoginFlow = async (credentials, password) => { - this._accountPassword = password; + onUserCompletedLoginFlow = async (credentials: object, password: string) => { + this.accountPassword = password; // self-destruct the password after 5mins - if (this._accountPasswordTimer !== null) clearTimeout(this._accountPasswordTimer); - this._accountPasswordTimer = setTimeout(() => { - this._accountPassword = null; - this._accountPasswordTimer = null; + if (this.accountPasswordTimer !== null) clearTimeout(this.accountPasswordTimer); + this.accountPasswordTimer = setTimeout(() => { + this.accountPassword = null; + this.accountPasswordTimer = null; }, 60 * 5 * 1000); // Wait for the client to be logged in (but not started) @@ -1895,7 +1930,7 @@ export default class MatrixChat extends React.PureComponent { // because the client hasn't been started yet. const cryptoAvailable = isCryptoAvailable(); if (!cryptoAvailable) { - this._onLoggedIn(); + this.onLoggedIn(); } this.setState({ pendingInitialSync: true }); @@ -1923,7 +1958,7 @@ export default class MatrixChat extends React.PureComponent { // labs flag on. this.setStateForNewView({ view: VIEWS.E2E_SETUP }); } else { - this._onLoggedIn(); + this.onLoggedIn(); } this.setState({ pendingInitialSync: false }); @@ -1932,7 +1967,7 @@ export default class MatrixChat extends React.PureComponent { // complete security / e2e setup has finished onCompleteSecurityE2eSetupFinished = () => { - this._onLoggedIn(); + this.onLoggedIn(); }; render() { @@ -1959,7 +1994,7 @@ export default class MatrixChat extends React.PureComponent { view = ( ); } else if (this.state.view === VIEWS.POST_REGISTRATION) { @@ -1972,7 +2007,7 @@ export default class MatrixChat extends React.PureComponent { } else if (this.state.view === VIEWS.LOGGED_IN) { // store errors stop the client syncing and require user intervention, so we'll // be showing a dialog. Don't show anything else. - const isStoreError = this.state.syncError && this.state.syncError instanceof Matrix.InvalidStoreError; + const isStoreError = this.state.syncError && this.state.syncError instanceof InvalidStoreError; // `ready` and `view==LOGGED_IN` may be set before `page_type` (because the // latter is set via the dispatcher). If we don't yet have a `page_type`, @@ -1984,7 +2019,8 @@ export default class MatrixChat extends React.PureComponent { */ const LoggedInView = sdk.getComponent('structures.LoggedInView'); view = ( - (promise: Promise, timeoutValue: T, ms: numbe } export interface IDeferred { - resolve: (T) => void; + resolve: (value: T) => void; reject: (any) => void; promise: Promise; } From 54e976f5a8fae3447ede6d14879a2828e5850876 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 22 Apr 2020 13:22:33 +0100 Subject: [PATCH 044/237] delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 52 ++++++++++++------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 576f92408a..be2021b2ba 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -66,7 +66,7 @@ import { storeRoomAliasInCache } from '../../RoomAliasCache'; import {defer, IDeferred} from "../../utils/promise"; import ToastStore from "../../stores/ToastStore"; import * as StorageManager from "../../utils/StorageManager"; -import type LoggedInView from "./LoggedInView"; +import type LoggedInViewType from "./LoggedInView"; /** constants for MatrixChat.state.view */ export enum VIEWS { @@ -214,7 +214,7 @@ export default class MatrixChat extends React.PureComponent { private focusComposer: boolean; private subTitleStatus: string; - private readonly loggedInView: React.RefObject; + private readonly loggedInView: React.RefObject; private readonly dispatcherRef: any; private readonly themeWatcher: ThemeWatcher; @@ -823,7 +823,7 @@ export default class MatrixChat extends React.PureComponent { } let roomIndex = -1; for (let i = 0; i < allRooms.length; ++i) { - if (allRooms[i].roomId == this.state.currentRoomId) { + if (allRooms[i].roomId === this.state.currentRoomId) { roomIndex = i; break; } @@ -1194,7 +1194,7 @@ export default class MatrixChat extends React.PureComponent { // the saved sync to be loaded). const saveWelcomeUser = (ev) => { if ( - ev.getType() == 'm.direct' && + ev.getType() === 'm.direct' && ev.getContent() && ev.getContent()[this.props.config.welcomeUserId] ) { @@ -1482,12 +1482,12 @@ export default class MatrixChat extends React.PureComponent { Modal.createTrackedDialog('Crypto migrated', '', ErrorDialog, { title: _t('Old cryptography data detected'), description: _t( - "Data from an older version of Riot has been detected. "+ - "This will have caused end-to-end cryptography to malfunction "+ - "in the older version. End-to-end encrypted messages exchanged "+ - "recently whilst using the older version may not be decryptable "+ - "in this version. This may also cause messages exchanged with this "+ - "version to fail. If you experience problems, log out and back in "+ + "Data from an older version of Riot has been detected. " + + "This will have caused end-to-end cryptography to malfunction " + + "in the older version. End-to-end encrypted messages exchanged " + + "recently whilst using the older version may not be decryptable " + + "in this version. This may also cause messages exchanged with this " + + "version to fail. If you experience problems, log out and back in " + "again. To retain message history, export and re-import your keys.", ), }); @@ -1590,17 +1590,17 @@ export default class MatrixChat extends React.PureComponent { } showScreen(screen: string, params?: {[key: string]: any}) { - if (screen == 'register') { + if (screen === 'register') { dis.dispatch({ action: 'start_registration', params: params, }); - } else if (screen == 'login') { + } else if (screen === 'login') { dis.dispatch({ action: 'start_login', params: params, }); - } else if (screen == 'forgot_password') { + } else if (screen === 'forgot_password') { dis.dispatch({ action: 'start_password_recovery', params: params, @@ -1616,32 +1616,32 @@ export default class MatrixChat extends React.PureComponent { params: params, }); } - } else if (screen == 'new') { + } else if (screen === 'new') { dis.dispatch({ action: 'view_create_room', }); - } else if (screen == 'settings') { + } else if (screen === 'settings') { dis.dispatch({ action: 'view_user_settings', }); - } else if (screen == 'welcome') { + } else if (screen === 'welcome') { dis.dispatch({ action: 'view_welcome_page', }); - } else if (screen == 'home') { + } else if (screen === 'home') { dis.dispatch({ action: 'view_home_page', }); - } else if (screen == 'start') { + } else if (screen === 'start') { this.showScreen('home'); dis.dispatch({ action: 'require_registration', }); - } else if (screen == 'directory') { + } else if (screen === 'directory') { dis.dispatch({ action: 'view_room_directory', }); - } else if (screen == 'groups') { + } else if (screen === 'groups') { dis.dispatch({ action: 'view_my_groups', }); @@ -1649,11 +1649,11 @@ export default class MatrixChat extends React.PureComponent { dis.dispatch({ action: 'start_complete_security', }); - } else if (screen == 'post_registration') { + } else if (screen === 'post_registration') { dis.dispatch({ action: 'start_post_registration', }); - } else if (screen.indexOf('room/') == 0) { + } else if (screen.indexOf('room/') === 0) { // Rooms can have the following formats: // #room_alias:domain or !opaque_id:domain const room = screen.substring(5); @@ -1710,21 +1710,21 @@ export default class MatrixChat extends React.PureComponent { room_alias: undefined, room_id: undefined, }; - if (roomString[0] == '#') { + if (roomString[0] === '#') { payload.room_alias = roomString; } else { payload.room_id = roomString; } dis.dispatch(payload); - } else if (screen.indexOf('user/') == 0) { + } else if (screen.indexOf('user/') === 0) { const userId = screen.substring(5); dis.dispatch({ action: 'view_user_info', userId: userId, subAction: params.action, }); - } else if (screen.indexOf('group/') == 0) { + } else if (screen.indexOf('group/') === 0) { const groupId = screen.substring(6); // TODO: Check valid group ID @@ -1853,7 +1853,7 @@ export default class MatrixChat extends React.PureComponent { }); } - private setPageSubtitle(subtitle='') { + private setPageSubtitle(subtitle = '') { if (this.state.currentRoomId) { const client = MatrixClientPeg.get(); const room = client && client.getRoom(this.state.currentRoomId); From 8b397f807f06b20d37cea0c6f7aa1a8c55c80795 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 22 Apr 2020 14:45:50 +0100 Subject: [PATCH 045/237] Skip auth flow test for signing upload when password present If we already have an account password to use during secret storage setup, then it's highly likely that the homeserver accepts passwords for device signing key upload as well. This change then assumes password auth will work without checking to avoid a request when the server is under high load. Fixes https://github.com/vector-im/riot-web/issues/13286 --- .../dialogs/secretstorage/CreateSecretStorageDialog.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index cf7f4d4126..d64a2247a2 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -92,7 +92,15 @@ export default class CreateSecretStorageDialog extends React.PureComponent { }; this._fetchBackupInfo(); - this._queryKeyUploadAuth(); + if (this.state.accountPassword) { + // If we have an account password in memory, let's simplify and + // assume it means password auth is also supported for device + // signing key upload as well. This avoids hitting the server to + // test auth flows, which may be slow under high load. + this.state.canUploadKeysWithPasswordOnly = true; + } else { + this._queryKeyUploadAuth(); + } MatrixClientPeg.get().on('crypto.keyBackupStatus', this._onKeyBackupStatusChange); } From 475cea8b8acf7ccb1924c96a8541dc0e80f2e0b9 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 22 Apr 2020 10:58:11 -0600 Subject: [PATCH 046/237] Take encrypted message search out of labs Fixes https://github.com/vector-im/riot-web/issues/13262 This is part of the cross-signing shipping master plan. Known issues relating to this feature are: * https://github.com/vector-im/riot-web/issues/12896 * https://github.com/vector-im/riot-web/issues/12385 * https://github.com/vector-im/riot-web/issues/11831 * https://github.com/vector-im/riot-web/issues/11155 In theory, these are issues we're comfortable with shipping as we're already enabling it by default. This just makes it easier on everyone by removing the flag (making it still enabled by default). --- .../settings/tabs/user/SecurityUserSettingsTab.js | 15 ++++++--------- src/indexing/EventIndexPeg.js | 4 ---- src/settings/Settings.js | 6 ------ 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index 1cde5d6f87..907e29baa7 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -254,15 +254,12 @@ export default class SecurityUserSettingsTab extends React.Component {
); - let eventIndex; - if (SettingsStore.isFeatureEnabled("feature_event_indexing")) { - eventIndex = ( -
- {_t("Message search")} - -
- ); - } + let eventIndex = ( +
+ {_t("Message search")} + +
+ ); // XXX: There's no such panel in the current cross-signing designs, but // it's useful to have for testing the feature. If there's no interest diff --git a/src/indexing/EventIndexPeg.js b/src/indexing/EventIndexPeg.js index 9aa7e78eda..ae4c14dafd 100644 --- a/src/indexing/EventIndexPeg.js +++ b/src/indexing/EventIndexPeg.js @@ -37,10 +37,6 @@ class EventIndexPeg { * EventIndex was successfully initialized, false otherwise. */ async init() { - if (!SettingsStore.isFeatureEnabled("feature_event_indexing")) { - return false; - } - const indexManager = PlatformPeg.get().getEventIndexingManager(); if (!indexManager) { console.log("EventIndex: Platform doesn't support event indexing, not initializing."); diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 32ff0a5f94..d7374718d3 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -158,12 +158,6 @@ export const SETTINGS = { supportedLevels: ['device', 'config'], // we shouldn't use LEVELS_FEATURE for non-features, so copy it here. default: true, }, - "feature_event_indexing": { - isFeature: true, - supportedLevels: LEVELS_FEATURE, - displayName: _td("Enable local event indexing and E2EE search (requires restart)"), - default: false, - }, "feature_bridge_state": { isFeature: true, supportedLevels: LEVELS_FEATURE, From 3c722d16eac9baee185bb1e86f3166c09a1dad5a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 22 Apr 2020 11:01:07 -0600 Subject: [PATCH 047/237] i18n --- src/i18n/strings/en_EN.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8ba838d313..b444f4488e 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -400,7 +400,6 @@ "Show a presence dot next to DMs in the room list": "Show a presence dot next to DMs in the room list", "Support adding custom themes": "Support adding custom themes", "Enable cross-signing to verify per-user instead of per-session": "Enable cross-signing to verify per-user instead of per-session", - "Enable local event indexing and E2EE search (requires restart)": "Enable local event indexing and E2EE search (requires restart)", "Show info about bridges in room settings": "Show info about bridges in room settings", "Show padlocks on invite only rooms": "Show padlocks on invite only rooms", "Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing", From 50059373d29ec99442cf0af9cbfdc00d3f144956 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 22 Apr 2020 11:05:43 -0600 Subject: [PATCH 048/237] Appease the linter --- .../views/settings/tabs/user/SecurityUserSettingsTab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index 907e29baa7..a88f35da68 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -254,7 +254,7 @@ export default class SecurityUserSettingsTab extends React.Component {
); - let eventIndex = ( + const eventIndex = (
{_t("Message search")} From ab7d7becd7cd8ef32097bd5d32e56bbfa394b774 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 22 Apr 2020 11:08:46 -0600 Subject: [PATCH 049/237] Match settings paragraph style in all cases --- src/components/views/settings/EventIndexPanel.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/settings/EventIndexPanel.js b/src/components/views/settings/EventIndexPanel.js index c9c6a5ec4f..6b084c2579 100644 --- a/src/components/views/settings/EventIndexPanel.js +++ b/src/components/views/settings/EventIndexPanel.js @@ -163,7 +163,7 @@ export default class EventIndexPanel extends React.Component { ); eventIndexingSettings = ( -
+
{ _t( "Riot is missing some components required for securely " + "caching encrypted messages locally. If you'd like to " + @@ -180,7 +180,7 @@ export default class EventIndexPanel extends React.Component { ); } else { eventIndexingSettings = ( -
+
{ _t( "Riot can't securely cache encrypted messages locally " + "while running in a web browser. Use Riot Desktop " + From 63de2783c31095e08c0a7153df831848816c199d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 22 Apr 2020 21:37:52 +0100 Subject: [PATCH 050/237] Fix i18n of SSO UIA copy in Deactivate Account Dialog Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../views/dialogs/DeactivateAccountDialog.js | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/components/views/dialogs/DeactivateAccountDialog.js b/src/components/views/dialogs/DeactivateAccountDialog.js index 3889f0989a..b269ec2fdb 100644 --- a/src/components/views/dialogs/DeactivateAccountDialog.js +++ b/src/components/views/dialogs/DeactivateAccountDialog.js @@ -26,30 +26,6 @@ import { _t } from '../../../languageHandler'; import InteractiveAuth, {ERROR_USER_CANCELLED} from "../../structures/InteractiveAuth"; import {DEFAULT_PHASE, PasswordAuthEntry, SSOAuthEntry} from "../auth/InteractiveAuthEntryComponents"; -const dialogAesthetics = { - [SSOAuthEntry.PHASE_PREAUTH]: { - body: _t("Confirm your account deactivation by using Single Sign On to prove your identity."), - continueText: _t("Single Sign On"), - continueKind: "danger", - }, - [SSOAuthEntry.PHASE_POSTAUTH]: { - body: _t("Are you sure you want to deactivate your account? This is irreversible."), - continueText: _t("Confirm account deactivation"), - continueKind: "danger", - }, -}; - -// This is the same as aestheticsForStagePhases in InteractiveAuthDialog minus the `title` -const DEACTIVATE_AESTHETICS = { - [SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics, - [SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics, - [PasswordAuthEntry.LOGIN_TYPE]: { - [DEFAULT_PHASE]: { - body: _t("To continue, please enter your password:"), - }, - }, -}; - export default class DeactivateAccountDialog extends React.Component { constructor(props) { super(props); @@ -84,6 +60,30 @@ export default class DeactivateAccountDialog extends React.Component { } _onStagePhaseChange = (stage, phase) => { + const dialogAesthetics = { + [SSOAuthEntry.PHASE_PREAUTH]: { + body: _t("Confirm your account deactivation by using Single Sign On to prove your identity."), + continueText: _t("Single Sign On"), + continueKind: "danger", + }, + [SSOAuthEntry.PHASE_POSTAUTH]: { + body: _t("Are you sure you want to deactivate your account? This is irreversible."), + continueText: _t("Confirm account deactivation"), + continueKind: "danger", + }, + }; + + // This is the same as aestheticsForStagePhases in InteractiveAuthDialog minus the `title` + const DEACTIVATE_AESTHETICS = { + [SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics, + [SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics, + [PasswordAuthEntry.LOGIN_TYPE]: { + [DEFAULT_PHASE]: { + body: _t("To continue, please enter your password:"), + }, + }, + }; + const aesthetics = DEACTIVATE_AESTHETICS[stage]; let bodyText = null; let continueText = null; From f952e9ebfea4be291f7a52098c999a174f1a212b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 22 Apr 2020 21:41:30 +0100 Subject: [PATCH 051/237] i18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8ba838d313..d53c58639d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1577,12 +1577,12 @@ "You've previously used a newer version of Riot on %(host)s. To use this version again with end to end encryption, you will need to sign out and back in again. ": "You've previously used a newer version of Riot on %(host)s. To use this version again with end to end encryption, you will need to sign out and back in again. ", "Incompatible Database": "Incompatible Database", "Continue With Encryption Disabled": "Continue With Encryption Disabled", + "Server did not require any authentication": "Server did not require any authentication", + "Server did not return valid authentication information.": "Server did not return valid authentication information.", "Confirm your account deactivation by using Single Sign On to prove your identity.": "Confirm your account deactivation by using Single Sign On to prove your identity.", "Are you sure you want to deactivate your account? This is irreversible.": "Are you sure you want to deactivate your account? This is irreversible.", "Confirm account deactivation": "Confirm account deactivation", "To continue, please enter your password:": "To continue, please enter your password:", - "Server did not require any authentication": "Server did not require any authentication", - "Server did not return valid authentication information.": "Server did not return valid authentication information.", "There was a problem communicating with the server. Please try again.": "There was a problem communicating with the server. Please try again.", "This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. This action is irreversible.": "This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. This action is irreversible.", "Deactivating your account does not by default cause us to forget messages you have sent. If you would like us to forget your messages, please tick the box below.": "Deactivating your account does not by default cause us to forget messages you have sent. If you would like us to forget your messages, please tick the box below.", From 89860100aeb012cb6b8fe92a700d2062f6117062 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 22 Apr 2020 22:32:02 +0100 Subject: [PATCH 052/237] Update login security copy and design to match Figma Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/_components.scss | 1 - .../structures/auth/_CompleteSecurity.scss | 44 +++++++++++++++++++ .../views/elements/_ButtonPlaceholder.scss | 24 ---------- .../structures/auth/CompleteSecurity.js | 4 +- .../structures/auth/SetupEncryptionBody.js | 38 +++++++++------- .../views/elements/ButtonPlaceholder.js | 19 -------- src/i18n/strings/en_EN.json | 8 ++-- 7 files changed, 72 insertions(+), 66 deletions(-) delete mode 100644 res/css/views/elements/_ButtonPlaceholder.scss delete mode 100644 src/components/views/elements/ButtonPlaceholder.js diff --git a/res/css/_components.scss b/res/css/_components.scss index a5dc87a952..0ba2b609e8 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -94,7 +94,6 @@ @import "./views/elements/_AccessibleButton.scss"; @import "./views/elements/_AddressSelector.scss"; @import "./views/elements/_AddressTile.scss"; -@import "./views/elements/_ButtonPlaceholder.scss"; @import "./views/elements/_DirectorySearchBox.scss"; @import "./views/elements/_Dropdown.scss"; @import "./views/elements/_EditableItemList.scss"; diff --git a/res/css/structures/auth/_CompleteSecurity.scss b/res/css/structures/auth/_CompleteSecurity.scss index 80e7aaada0..f742be70e4 100644 --- a/res/css/structures/auth/_CompleteSecurity.scss +++ b/res/css/structures/auth/_CompleteSecurity.scss @@ -26,6 +26,50 @@ limitations under the License. position: relative; } +.mx_CompleteSecurity_clients { + width: max-content; + margin: 36px auto 0; + + .mx_CompleteSecurity_clients_desktop, .mx_CompleteSecurity_clients_mobile { + position: relative; + width: 160px; + text-align: center; + padding-top: 64px; + display: inline-block; + + &::before { + content: ''; + position: absolute; + height: 48px; + width: 48px; + left: 56px; + top: 0; + background-color: $muted-fg-color; + mask-repeat: no-repeat; + mask-size: contain; + } + } + + .mx_CompleteSecurity_clients_desktop { + margin-right: 56px; + } + + .mx_CompleteSecurity_clients_desktop::before { + mask-image: url('$(res)/img/feather-customised/monitor.svg'); + } + + .mx_CompleteSecurity_clients_mobile::before { + mask-image: url('$(res)/img/feather-customised/smartphone.svg'); + } + + p { + margin-top: 16px; + font-size: $font-12px; + color: $muted-fg-color; + text-align: center; + } +} + .mx_CompleteSecurity_heroIcon { width: 128px; height: 128px; diff --git a/res/css/views/elements/_ButtonPlaceholder.scss b/res/css/views/elements/_ButtonPlaceholder.scss deleted file mode 100644 index 858fcdecf6..0000000000 --- a/res/css/views/elements/_ButtonPlaceholder.scss +++ /dev/null @@ -1,24 +0,0 @@ -/* -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -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. -*/ - -.mx_ButtonPlaceholder { - font-size: $font-14px; - font-weight: 600; - padding: 7px 18px; - display: inline-block; - text-align: center; - color: $authpage-secondary-color; -} diff --git a/src/components/structures/auth/CompleteSecurity.js b/src/components/structures/auth/CompleteSecurity.js index 95128c0be9..c73691611d 100644 --- a/src/components/structures/auth/CompleteSecurity.js +++ b/src/components/structures/auth/CompleteSecurity.js @@ -60,7 +60,7 @@ export default class CompleteSecurity extends React.Component { if (phase === PHASE_INTRO) { icon = ; - title = _t("Verify this session"); + title = _t("Verify this login"); } else if (phase === PHASE_DONE) { icon = ; title = _t("Session verified"); @@ -69,7 +69,7 @@ export default class CompleteSecurity extends React.Component { title = _t("Are you sure?"); } else if (phase === PHASE_BUSY) { icon = ; - title = _t("Verify this session"); + title = _t("Verify this login"); } else { throw new Error(`Unknown phase ${phase}`); } diff --git a/src/components/structures/auth/SetupEncryptionBody.js b/src/components/structures/auth/SetupEncryptionBody.js index e6302a4685..13fa270a9c 100644 --- a/src/components/structures/auth/SetupEncryptionBody.js +++ b/src/components/structures/auth/SetupEncryptionBody.js @@ -108,31 +108,35 @@ export default class SetupEncryptionBody extends React.Component { member={MatrixClientPeg.get().getUser(this.state.verificationRequest.otherUserId)} />; } else if (phase === PHASE_INTRO) { - const ButtonPlaceholder = sdk.getComponent("elements.ButtonPlaceholder"); return (

{_t( - "Use an existing session to verify this one, " + + "Confirm your identity by verifying this login from one of your other sessions, " + "granting it access to encrypted messages.", )}

{_t( - "If you can’t access one, ", - {}, { - button: sub => - {sub} - , - })}

+ "This requires the latest Riot on your other devices:", + )}

+ +
+
+
Riot Web
+
Riot Desktop
+
+
+
Riot iOS
+
Riot X for Android
+
+

{_t("or another cross-signing capable Matrix client")}

+
+
- + + {_t("Use Recovery Passphrase or Key")} + + {_t("Skip")} - {_t("Use your other device to continue…")}
); @@ -150,7 +154,7 @@ export default class SetupEncryptionBody extends React.Component { } return (
-
+
{message}
{props.children}
; -} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index d53c58639d..796257262f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2063,6 +2063,7 @@ "Uploading %(filename)s and %(count)s others|zero": "Uploading %(filename)s", "Uploading %(filename)s and %(count)s others|one": "Uploading %(filename)s and %(count)s other", "Could not load user profile": "Could not load user profile", + "Verify this login": "Verify this login", "Session verified": "Session verified", "Failed to send email": "Failed to send email", "The email address linked to your account must be entered.": "The email address linked to your account must be entered.", @@ -2116,9 +2117,10 @@ "You can now close this window or log in to your new account.": "You can now close this window or log in to your new account.", "Registration Successful": "Registration Successful", "Create your account": "Create your account", - "Use an existing session to verify this one, granting it access to encrypted messages.": "Use an existing session to verify this one, granting it access to encrypted messages.", - "If you can’t access one, ": "If you can’t access one, ", - "Use your other device to continue…": "Use your other device to continue…", + "Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.": "Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.", + "This requires the latest Riot on your other devices:": "This requires the latest Riot on your other devices:", + "or another cross-signing capable Matrix client": "or another cross-signing capable Matrix client", + "Use Recovery Passphrase or Key": "Use Recovery Passphrase or Key", "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.", "Your new session is now verified. Other users will see it as trusted.": "Your new session is now verified. Other users will see it as trusted.", "Without completing security on this session, it won’t have access to encrypted messages.": "Without completing security on this session, it won’t have access to encrypted messages.", From 635472ccb16bb5cab2299c428cb1a34b55500769 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 22 Apr 2020 22:57:00 +0100 Subject: [PATCH 053/237] stage new artifacts Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/img/feather-customised/monitor.svg | 5 +++++ res/img/feather-customised/smartphone.svg | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 res/img/feather-customised/monitor.svg create mode 100644 res/img/feather-customised/smartphone.svg diff --git a/res/img/feather-customised/monitor.svg b/res/img/feather-customised/monitor.svg new file mode 100644 index 0000000000..231811d5a6 --- /dev/null +++ b/res/img/feather-customised/monitor.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/res/img/feather-customised/smartphone.svg b/res/img/feather-customised/smartphone.svg new file mode 100644 index 0000000000..fde78c82e2 --- /dev/null +++ b/res/img/feather-customised/smartphone.svg @@ -0,0 +1,4 @@ + + + + From 4cf234197b810eff25b9f052fdb171854fd05d75 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 23 Apr 2020 10:12:50 +0100 Subject: [PATCH 054/237] iterate PR Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 82 ++++++++++++------------ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index be2021b2ba..e117d8f76b 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -69,7 +69,7 @@ import * as StorageManager from "../../utils/StorageManager"; import type LoggedInViewType from "./LoggedInView"; /** constants for MatrixChat.state.view */ -export enum VIEWS { +export enum Views { // a special initial state which is only used at startup, while we are // trying to re-animate a matrix client or register as a guest. LOADING = 0, @@ -152,7 +152,7 @@ interface IProps { // TODO type things better interface IState { // the master view we are showing. - view: VIEWS; + view: Views; // What the LoggedInView would be showing if visible page_type?: PageTypes; // The ID of the room we're viewing. This is either populated directly @@ -193,7 +193,6 @@ interface IState { } export default class MatrixChat extends React.PureComponent { - static VIEWS = VIEWS; // we export this so that the integration tests can use it :-S static displayName = "MatrixChat"; static defaultProps = { @@ -222,7 +221,7 @@ export default class MatrixChat extends React.PureComponent { super(props, context); this.state = { - view: VIEWS.LOADING, + view: Views.LOADING, collapseLhs: false, leftDisabled: false, middleDisabled: false, @@ -538,7 +537,7 @@ export default class MatrixChat extends React.PureComponent { this.screenAfterLogin = payload.screenAfterLogin; } this.setStateForNewView({ - view: VIEWS.LOGIN, + view: Views.LOGIN, }); this.notifyNewScreen('login'); ThemeController.isLogin = true; @@ -546,12 +545,12 @@ export default class MatrixChat extends React.PureComponent { break; case 'start_post_registration': this.setState({ - view: VIEWS.POST_REGISTRATION, + view: Views.POST_REGISTRATION, }); break; case 'start_password_recovery': this.setStateForNewView({ - view: VIEWS.FORGOT_PASSWORD, + view: Views.FORGOT_PASSWORD, }); this.notifyNewScreen('forgot_password'); break; @@ -706,10 +705,10 @@ export default class MatrixChat extends React.PureComponent { case 'on_logged_in': if ( !Lifecycle.isSoftLogout() && - this.state.view !== VIEWS.LOGIN && - this.state.view !== VIEWS.REGISTER && - this.state.view !== VIEWS.COMPLETE_SECURITY && - this.state.view !== VIEWS.E2E_SETUP + this.state.view !== Views.LOGIN && + this.state.view !== Views.REGISTER && + this.state.view !== Views.COMPLETE_SECURITY && + this.state.view !== Views.E2E_SETUP ) { this.onLoggedIn(); } @@ -781,7 +780,7 @@ export default class MatrixChat extends React.PureComponent { private async startRegistration(params: {[key: string]: string}) { const newState: Partial = { - view: VIEWS.REGISTER, + view: Views.REGISTER, }; // Only honour params if they are all present, otherwise we reset @@ -914,7 +913,7 @@ export default class MatrixChat extends React.PureComponent { presentedId += "/" + roomInfo.event_id; } this.setState({ - view: VIEWS.LOGGED_IN, + view: Views.LOGGED_IN, currentRoomId: roomInfo.room_id || null, page_type: PageTypes.RoomView, thirdPartyInvite: roomInfo.third_party_invite, @@ -938,7 +937,7 @@ export default class MatrixChat extends React.PureComponent { } private viewSomethingBehindModal() { - if (this.state.view !== VIEWS.LOGGED_IN) { + if (this.state.view !== Views.LOGGED_IN) { this.viewWelcome(); return; } @@ -949,7 +948,7 @@ export default class MatrixChat extends React.PureComponent { private viewWelcome() { this.setStateForNewView({ - view: VIEWS.WELCOME, + view: Views.WELCOME, }); this.notifyNewScreen('welcome'); ThemeController.isLogin = true; @@ -959,7 +958,7 @@ export default class MatrixChat extends React.PureComponent { private viewHome() { // The home page requires the "logged in" view, so we'll set that. this.setStateForNewView({ - view: VIEWS.LOGGED_IN, + view: Views.LOGGED_IN, }); this.setPage(PageTypes.HomePage); this.notifyNewScreen('home'); @@ -1216,7 +1215,7 @@ export default class MatrixChat extends React.PureComponent { */ private async onLoggedIn() { ThemeController.isLogin = false; - this.setStateForNewView({ view: VIEWS.LOGGED_IN }); + this.setStateForNewView({ view: Views.LOGGED_IN }); // If a specific screen is set to be shown after login, show that above // all else, as it probably means the user clicked on something already. if (this.screenAfterLogin && this.screenAfterLogin.screen) { @@ -1285,7 +1284,7 @@ export default class MatrixChat extends React.PureComponent { private onLoggedOut() { this.notifyNewScreen('login'); this.setStateForNewView({ - view: VIEWS.LOGIN, + view: Views.LOGIN, ready: false, collapseLhs: false, currentRoomId: null, @@ -1302,7 +1301,7 @@ export default class MatrixChat extends React.PureComponent { private onSoftLogout() { this.notifyNewScreen('soft_logout'); this.setStateForNewView({ - view: VIEWS.SOFT_LOGOUT, + view: Views.SOFT_LOGOUT, ready: false, collapseLhs: false, currentRoomId: null, @@ -1824,7 +1823,7 @@ export default class MatrixChat extends React.PureComponent { onFinishPostRegistration = () => { // Don't confuse this with "PageType" which is the middle window to show this.setState({ - view: VIEWS.LOGGED_IN, + view: Views.LOGGED_IN, }); this.showScreen("settings"); }; @@ -1948,7 +1947,7 @@ export default class MatrixChat extends React.PureComponent { // Auto-enable cross-signing for the new session when key found in // secret storage. SettingsStore.setValue("feature_cross_signing", null, SettingLevel.DEVICE, true); - this.setStateForNewView({ view: VIEWS.COMPLETE_SECURITY }); + this.setStateForNewView({ view: Views.COMPLETE_SECURITY }); } else if ( SettingsStore.getValue("feature_cross_signing") && await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing") @@ -1956,7 +1955,7 @@ export default class MatrixChat extends React.PureComponent { // This will only work if the feature is set to 'enable' in the config, // since it's too early in the lifecycle for users to have turned the // labs flag on. - this.setStateForNewView({ view: VIEWS.E2E_SETUP }); + this.setStateForNewView({ view: Views.E2E_SETUP }); } else { this.onLoggedIn(); } @@ -1975,21 +1974,21 @@ export default class MatrixChat extends React.PureComponent { let view; - if (this.state.view === VIEWS.LOADING) { + if (this.state.view === Views.LOADING) { const Spinner = sdk.getComponent('elements.Spinner'); view = (
); - } else if (this.state.view === VIEWS.COMPLETE_SECURITY) { + } else if (this.state.view === Views.COMPLETE_SECURITY) { const CompleteSecurity = sdk.getComponent('structures.auth.CompleteSecurity'); view = ( ); - } else if (this.state.view === VIEWS.E2E_SETUP) { + } else if (this.state.view === Views.E2E_SETUP) { const E2eSetup = sdk.getComponent('structures.auth.E2eSetup'); view = ( { accountPassword={this.accountPassword} /> ); - } else if (this.state.view === VIEWS.POST_REGISTRATION) { + } else if (this.state.view === Views.POST_REGISTRATION) { // needs to be before normal PageTypes as you are logged in technically const PostRegistration = sdk.getComponent('structures.auth.PostRegistration'); view = ( ); - } else if (this.state.view === VIEWS.LOGGED_IN) { + } else if (this.state.view === Views.LOGGED_IN) { // store errors stop the client syncing and require user intervention, so we'll // be showing a dialog. Don't show anything else. const isStoreError = this.state.syncError && this.state.syncError instanceof InvalidStoreError; @@ -2019,15 +2018,16 @@ export default class MatrixChat extends React.PureComponent { */ const LoggedInView = sdk.getComponent('structures.LoggedInView'); view = ( - ); } else { @@ -2049,10 +2049,10 @@ export default class MatrixChat extends React.PureComponent {
); } - } else if (this.state.view === VIEWS.WELCOME) { + } else if (this.state.view === Views.WELCOME) { const Welcome = sdk.getComponent('auth.Welcome'); view = ; - } else if (this.state.view === VIEWS.REGISTER) { + } else if (this.state.view === Views.REGISTER) { const Registration = sdk.getComponent('structures.auth.Registration'); view = ( { {...this.getServerProperties()} /> ); - } else if (this.state.view === VIEWS.FORGOT_PASSWORD) { + } else if (this.state.view === Views.FORGOT_PASSWORD) { const ForgotPassword = sdk.getComponent('structures.auth.ForgotPassword'); view = ( { {...this.getServerProperties()} /> ); - } else if (this.state.view === VIEWS.LOGIN) { + } else if (this.state.view === Views.LOGIN) { const Login = sdk.getComponent('structures.auth.Login'); view = ( { {...this.getServerProperties()} /> ); - } else if (this.state.view === VIEWS.SOFT_LOGOUT) { + } else if (this.state.view === Views.SOFT_LOGOUT) { const SoftLogout = sdk.getComponent('structures.auth.SoftLogout'); view = ( Date: Thu, 23 Apr 2020 10:44:35 +0100 Subject: [PATCH 055/237] Make Screens an enum Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 326 +++++++++++++---------- 1 file changed, 179 insertions(+), 147 deletions(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index e117d8f76b..02a79f9684 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -103,6 +103,22 @@ export enum Views { SOFT_LOGOUT = 9, } +export enum Screens { + REGISTER = "register", + LOGIN = "login", + FORGOT_PASSWORD = "forgot_password", + SOFT_LOGOUT = "soft_logout", + NEW = "new", // new room + SETTINGS = "settings", + WELCOME = "welcome", + HOME = "home", + START = "start", + DIRECTORY = "directory", + GROUPS = "groups", + COMPLETE_SECURITY = "complete_security", + POST_REGISTRATION = "post_registration", +} + // Actions that are redirected through the onboarding process prior to being // re-dispatched. NOTE: some actions are non-trivial and would require // re-factoring to be included in this list in future. @@ -114,7 +130,7 @@ const ONBOARDING_FLOW_STARTERS = [ ]; interface IScreen { - screen: string; + screen: Screens | string; params?: object; } @@ -323,9 +339,9 @@ export default class MatrixChat extends React.PureComponent { // the old creds, but rather go straight to the relevant page const firstScreen = this.screenAfterLogin ? this.screenAfterLogin.screen : null; - if (firstScreen === 'login' || - firstScreen === 'register' || - firstScreen === 'forgot_password') { + if (firstScreen === Screens.LOGIN || + firstScreen === Screens.REGISTER || + firstScreen === Screens.FORGOT_PASSWORD) { this.showScreenAfterLogin(); return; } @@ -539,7 +555,7 @@ export default class MatrixChat extends React.PureComponent { this.setStateForNewView({ view: Views.LOGIN, }); - this.notifyNewScreen('login'); + this.notifyNewScreen(Screens.LOGIN); ThemeController.isLogin = true; this.themeWatcher.recheck(); break; @@ -552,7 +568,7 @@ export default class MatrixChat extends React.PureComponent { this.setStateForNewView({ view: Views.FORGOT_PASSWORD, }); - this.notifyNewScreen('forgot_password'); + this.notifyNewScreen(Screens.FORGOT_PASSWORD); break; case 'start_chat': createRoom({ @@ -803,7 +819,7 @@ export default class MatrixChat extends React.PureComponent { this.setStateForNewView(newState); ThemeController.isLogin = true; this.themeWatcher.recheck(); - this.notifyNewScreen('register'); + this.notifyNewScreen(Screens.REGISTER); } // TODO: Move to RoomViewStore @@ -1282,7 +1298,7 @@ export default class MatrixChat extends React.PureComponent { * Called when the session is logged out */ private onLoggedOut() { - this.notifyNewScreen('login'); + this.notifyNewScreen(Screens.LOGIN); this.setStateForNewView({ view: Views.LOGIN, ready: false, @@ -1299,7 +1315,7 @@ export default class MatrixChat extends React.PureComponent { * Called when the session is softly logged out */ private onSoftLogout() { - this.notifyNewScreen('soft_logout'); + this.notifyNewScreen(Screens.SOFT_LOGOUT); this.setStateForNewView({ view: Views.SOFT_LOGOUT, ready: false, @@ -1588,152 +1604,168 @@ export default class MatrixChat extends React.PureComponent { } } - showScreen(screen: string, params?: {[key: string]: any}) { - if (screen === 'register') { - dis.dispatch({ - action: 'start_registration', - params: params, - }); - } else if (screen === 'login') { - dis.dispatch({ - action: 'start_login', - params: params, - }); - } else if (screen === 'forgot_password') { - dis.dispatch({ - action: 'start_password_recovery', - params: params, - }); - } else if (screen === 'soft_logout') { - if (MatrixClientPeg.get() && MatrixClientPeg.get().getUserId() && !Lifecycle.isSoftLogout()) { - // Logged in - visit a room - this.viewLastRoom(); - } else { - // Ultimately triggers soft_logout if needed + showScreen(screen: Screens | string, params?: {[key: string]: any}) { + switch (screen) { + case Screens.REGISTER: + dis.dispatch({ + action: 'start_registration', + params: params, + }); + break; + case Screens.LOGIN: dis.dispatch({ action: 'start_login', params: params, }); - } - } else if (screen === 'new') { - dis.dispatch({ - action: 'view_create_room', - }); - } else if (screen === 'settings') { - dis.dispatch({ - action: 'view_user_settings', - }); - } else if (screen === 'welcome') { - dis.dispatch({ - action: 'view_welcome_page', - }); - } else if (screen === 'home') { - dis.dispatch({ - action: 'view_home_page', - }); - } else if (screen === 'start') { - this.showScreen('home'); - dis.dispatch({ - action: 'require_registration', - }); - } else if (screen === 'directory') { - dis.dispatch({ - action: 'view_room_directory', - }); - } else if (screen === 'groups') { - dis.dispatch({ - action: 'view_my_groups', - }); - } else if (screen === 'complete_security') { - dis.dispatch({ - action: 'start_complete_security', - }); - } else if (screen === 'post_registration') { - dis.dispatch({ - action: 'start_post_registration', - }); - } else if (screen.indexOf('room/') === 0) { - // Rooms can have the following formats: - // #room_alias:domain or !opaque_id:domain - const room = screen.substring(5); - const domainOffset = room.indexOf(':') + 1; // 0 in case room does not contain a : - let eventOffset = room.length; - // room aliases can contain slashes only look for slash after domain - if (room.substring(domainOffset).indexOf('/') > -1) { - eventOffset = domainOffset + room.substring(domainOffset).indexOf('/'); - } - const roomString = room.substring(0, eventOffset); - let eventId = room.substring(eventOffset + 1); // empty string if no event id given + break; + case Screens.FORGOT_PASSWORD: + dis.dispatch({ + action: 'start_password_recovery', + params: params, + }); + break; + case Screens.SOFT_LOGOUT: + if (MatrixClientPeg.get() && MatrixClientPeg.get().getUserId() && !Lifecycle.isSoftLogout()) { + // Logged in - visit a room + this.viewLastRoom(); + } else { + // Ultimately triggers soft_logout if needed + dis.dispatch({ + action: 'start_login', + params: params, + }); + } + break; + case Screens.NEW: + dis.dispatch({ + action: 'view_create_room', + }); + break; + case Screens.SETTINGS: + dis.dispatch({ + action: 'view_user_settings', + }); + break; + case Screens.WELCOME: + dis.dispatch({ + action: 'view_welcome_page', + }); + break; + case Screens.HOME: + dis.dispatch({ + action: 'view_home_page', + }); + break; + case Screens.START: + this.showScreen(Screens.HOME); + dis.dispatch({ + action: 'require_registration', + }); + break; + case Screens.DIRECTORY: + dis.dispatch({ + action: 'view_room_directory', + }); + break; + case Screens.GROUPS: + dis.dispatch({ + action: 'view_my_groups', + }); + break; + case Screens.COMPLETE_SECURITY: + dis.dispatch({ + action: 'start_complete_security', + }); + break; + case Screens.POST_REGISTRATION: + dis.dispatch({ + action: 'start_post_registration', + }); + break; + default: + if (screen.startsWith('room/')) { + // Rooms can have the following formats: + // #room_alias:domain or !opaque_id:domain + const room = screen.substring(5); + const domainOffset = room.indexOf(':') + 1; // 0 in case room does not contain a : + let eventOffset = room.length; + // room aliases can contain slashes only look for slash after domain + if (room.substring(domainOffset).indexOf('/') > -1) { + eventOffset = domainOffset + room.substring(domainOffset).indexOf('/'); + } + const roomString = room.substring(0, eventOffset); + let eventId = room.substring(eventOffset + 1); // empty string if no event id given - // Previously we pulled the eventID from the segments in such a way - // where if there was no eventId then we'd get undefined. However, we - // now do a splice and join to handle v3 event IDs which results in - // an empty string. To maintain our potential contract with the rest - // of the app, we coerce the eventId to be undefined where applicable. - if (!eventId) eventId = undefined; + // Previously we pulled the eventID from the segments in such a way + // where if there was no eventId then we'd get undefined. However, we + // now do a splice and join to handle v3 event IDs which results in + // an empty string. To maintain our potential contract with the rest + // of the app, we coerce the eventId to be undefined where applicable. + if (!eventId) eventId = undefined; - // TODO: Handle encoded room/event IDs: https://github.com/vector-im/riot-web/issues/9149 + // TODO: Handle encoded room/event IDs: https://github.com/vector-im/riot-web/issues/9149 - // FIXME: sort_out caseConsistency - const thirdPartyInvite = { - inviteSignUrl: params.signurl, - invitedEmail: params.email, - }; - const oobData = { - name: params.room_name, - avatarUrl: params.room_avatar_url, - inviterName: params.inviter_name, - }; + // FIXME: sort_out caseConsistency + const thirdPartyInvite = { + inviteSignUrl: params.signurl, + invitedEmail: params.email, + }; + const oobData = { + name: params.room_name, + avatarUrl: params.room_avatar_url, + inviterName: params.inviter_name, + }; - // on our URLs there might be a ?via=matrix.org or similar to help - // joins to the room succeed. We'll pass these through as an array - // to other levels. If there's just one ?via= then params.via is a - // single string. If someone does something like ?via=one.com&via=two.com - // then params.via is an array of strings. - let via = []; - if (params.via) { - if (typeof(params.via) === 'string') via = [params.via]; - else via = params.via; - } + // on our URLs there might be a ?via=matrix.org or similar to help + // joins to the room succeed. We'll pass these through as an array + // to other levels. If there's just one ?via= then params.via is a + // single string. If someone does something like ?via=one.com&via=two.com + // then params.via is an array of strings. + let via = []; + if (params.via) { + if (typeof(params.via) === 'string') via = [params.via]; + else via = params.via; + } - const payload = { - action: 'view_room', - event_id: eventId, - via_servers: via, - // If an event ID is given in the URL hash, notify RoomViewStore to mark - // it as highlighted, which will propagate to RoomView and highlight the - // associated EventTile. - highlighted: Boolean(eventId), - third_party_invite: thirdPartyInvite, - oob_data: oobData, - room_alias: undefined, - room_id: undefined, - }; - if (roomString[0] === '#') { - payload.room_alias = roomString; - } else { - payload.room_id = roomString; - } + const payload = { + action: 'view_room', + event_id: eventId, + via_servers: via, + // If an event ID is given in the URL hash, notify RoomViewStore to mark + // it as highlighted, which will propagate to RoomView and highlight the + // associated EventTile. + highlighted: Boolean(eventId), + third_party_invite: thirdPartyInvite, + oob_data: oobData, + room_alias: undefined, + room_id: undefined, + }; + if (roomString[0] === '#') { + payload.room_alias = roomString; + } else { + payload.room_id = roomString; + } - dis.dispatch(payload); - } else if (screen.indexOf('user/') === 0) { - const userId = screen.substring(5); - dis.dispatch({ - action: 'view_user_info', - userId: userId, - subAction: params.action, - }); - } else if (screen.indexOf('group/') === 0) { - const groupId = screen.substring(6); + dis.dispatch(payload); + } else if (screen.startsWith('user/')) { + const userId = screen.substring(5); + dis.dispatch({ + action: 'view_user_info', + userId: userId, + subAction: params.action, + }); + } else if (screen.startsWith('group/')) { + const groupId = screen.substring(6); - // TODO: Check valid group ID + // TODO: Check valid group ID - dis.dispatch({ - action: 'view_group', - group_id: groupId, - }); - } else { - console.info("Ignoring showScreen for '%s'", screen); + dis.dispatch({ + action: 'view_group', + group_id: groupId, + }); + } else { + console.info("Ignoring showScreen for '%s'", screen); + } } } @@ -1800,15 +1832,15 @@ export default class MatrixChat extends React.PureComponent { } onRegisterClick = () => { - this.showScreen("register"); + this.showScreen(Screens.REGISTER); }; onLoginClick = () => { - this.showScreen("login"); + this.showScreen(Screens.LOGIN); }; onForgotPasswordClick = () => { - this.showScreen("forgot_password"); + this.showScreen(Screens.FORGOT_PASSWORD); }; onRegisterFlowComplete = (credentials: object, password: string) => { @@ -1825,7 +1857,7 @@ export default class MatrixChat extends React.PureComponent { this.setState({ view: Views.LOGGED_IN, }); - this.showScreen("settings"); + this.showScreen(Screens.SETTINGS); }; onVersion(current: string, latest: string, releaseNotes?: string) { From 61b45afcd3731844482a0520d9761d841206b74a Mon Sep 17 00:00:00 2001 From: Jorik Schellekens Date: Thu, 23 Apr 2020 12:28:00 +0100 Subject: [PATCH 056/237] Slightly darker toggle off bg color --- res/themes/dark/css/_dark.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 5d6ba033c8..6224c0820f 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -147,6 +147,9 @@ $button-danger-disabled-bg-color: #f5b6bb; // TODO: Verify color $button-link-fg-color: $accent-color; $button-link-bg-color: transparent; +// Toggle switch +$togglesw-off-color: $room-highlight-color; + $visual-bell-bg-color: #800; $room-warning-bg-color: $header-panel-bg-color; From 86200812a5c6ab95645a8189682d49c7e6e632f7 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 23 Apr 2020 15:49:21 +0100 Subject: [PATCH 057/237] Upgrade matrix-js-sdk to 5.3.1-rc.4 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 4e20ad6acf..e8e834ec38 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "5.3.1-rc.3", + "matrix-js-sdk": "5.3.1-rc.4", "minimist": "^1.2.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index 65f8a0e669..150d9b126b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5715,10 +5715,10 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -matrix-js-sdk@5.3.1-rc.3: - version "5.3.1-rc.3" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.3.1-rc.3.tgz#fada68aaf9fadd2f423a297bba8193b5bd697316" - integrity sha512-YMfOdhlAFk4kHQ85S3kosVBWSr8iCJ8OaVpJr+lDFoXkvIrPgSn5zWesg+ny/bvQjWNRny7Ch7wcmozojKQqqg== +matrix-js-sdk@5.3.1-rc.4: + version "5.3.1-rc.4" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.3.1-rc.4.tgz#f0e6d512540aa04dfdc311c854fd9efb53287071" + integrity sha512-IIuUzP4ee5rw7gtuA2mT7i/jXehl0OrdBMUSAruqixl5DUvBSWjPyFbS4zclVN+DNf75j+7RWMH8Q8BLfdvLeA== dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From b3753f34076ce8764dace672490a64c38e8c74e7 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 23 Apr 2020 15:55:37 +0100 Subject: [PATCH 058/237] Prepare changelog for v2.5.0-rc.4 --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3676b5be0..541992d4c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +Changes in [2.5.0-rc.4](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.4) (2020-04-23) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.3...v2.5.0-rc.4) + + * Upgrade to JS SDK 5.3.1-rc.4 + * Take encrypted message search out of labs for release + [\#4468](https://github.com/matrix-org/matrix-react-sdk/pull/4468) + * Update login security copy and design to match Figma [to release] + [\#4474](https://github.com/matrix-org/matrix-react-sdk/pull/4474) + * Fix i18n of SSO UIA copy in Deactivate Account Dialog on release + [\#4473](https://github.com/matrix-org/matrix-react-sdk/pull/4473) + * Skip auth flow test for signing upload when password present + [\#4465](https://github.com/matrix-org/matrix-react-sdk/pull/4465) + * Fix: wait until cross-signing keys are fetched to show verify button + [\#4457](https://github.com/matrix-org/matrix-react-sdk/pull/4457) + * Handle load error in create secret storage dialog + [\#4454](https://github.com/matrix-org/matrix-react-sdk/pull/4454) + * Don't recheck DeviceListener until after initial sync is finished + [\#4450](https://github.com/matrix-org/matrix-react-sdk/pull/4450) + * EventIndex: Filter out events that don't have a propper content value. + [\#4447](https://github.com/matrix-org/matrix-react-sdk/pull/4447) + Changes in [2.5.0-rc.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.3) (2020-04-17) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.2...v2.5.0-rc.3) From 941709d19ada20e6454cfa070fe16e09084bf808 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 23 Apr 2020 15:55:37 +0100 Subject: [PATCH 059/237] v2.5.0-rc.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e8e834ec38..84bc83c2ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.5.0-rc.3", + "version": "2.5.0-rc.4", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From e3ba9c9b38779c75e57cd0e7caf93a26cdaefb4f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 23 Apr 2020 16:11:29 +0100 Subject: [PATCH 060/237] Discard unused CompatibilityPage.js in react-sdk Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/_components.scss | 1 - res/css/structures/_CompatibilityPage.scss | 19 ----- .../structures/CompatibilityPage.js | 78 ------------------- 3 files changed, 98 deletions(-) delete mode 100644 res/css/structures/_CompatibilityPage.scss delete mode 100644 src/components/structures/CompatibilityPage.js diff --git a/res/css/_components.scss b/res/css/_components.scss index 0ba2b609e8..7bf1f88ec9 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -2,7 +2,6 @@ @import "./_common.scss"; @import "./_font-sizes.scss"; @import "./structures/_AutoHideScrollbar.scss"; -@import "./structures/_CompatibilityPage.scss"; @import "./structures/_ContextualMenu.scss"; @import "./structures/_CreateRoom.scss"; @import "./structures/_CustomRoomTagPanel.scss"; diff --git a/res/css/structures/_CompatibilityPage.scss b/res/css/structures/_CompatibilityPage.scss deleted file mode 100644 index 26354ed124..0000000000 --- a/res/css/structures/_CompatibilityPage.scss +++ /dev/null @@ -1,19 +0,0 @@ -.mx_CompatibilityPage { - width: 100%; - height: 100%; - background-color: #e55; -} - -.mx_CompatibilityPage_box { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - margin: auto; - width: 500px; - height: 300px; - border: 1px solid; - padding: 10px; - background-color: #fcc; -} diff --git a/src/components/structures/CompatibilityPage.js b/src/components/structures/CompatibilityPage.js deleted file mode 100644 index 9a3fdb5f39..0000000000 --- a/src/components/structures/CompatibilityPage.js +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2015, 2016 OpenMarket Ltd -Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> -Copyright 2019 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -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 React from 'react'; -import createReactClass from 'create-react-class'; -import PropTypes from 'prop-types'; -import { _t } from '../../languageHandler'; - -export default createReactClass({ - displayName: 'CompatibilityPage', - propTypes: { - onAccept: PropTypes.func, - }, - - getDefaultProps: function() { - return { - onAccept: function() {}, // NOP - }; - }, - - onAccept: function() { - this.props.onAccept(); - }, - - render: function() { - return ( -
-
-

{ _t("Sorry, your browser is not able to run Riot.", {}, { 'b': (sub) => {sub} }) }

-

- { _t( - "Riot uses many advanced browser features, some of which are not available " + - "or experimental in your current browser.", - ) } -

-

- { _t( - 'Please install Chrome, Firefox, ' + - 'or Safari for the best experience.', - {}, - { - 'chromeLink': (sub) => {sub}, - 'firefoxLink': (sub) => {sub}, - 'safariLink': (sub) => {sub}, - }, - )} -

-

- { _t( - "With your current browser, the look and feel of the application may be " + - "completely incorrect, and some or all features may not function. " + - "If you want to try it anyway you can continue, but you are on your own in terms " + - "of any issues you may encounter!", - ) } -

- -
-
- ); - }, -}); From 531de19fa4464ea04cce372b327340339a73bb0a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 23 Apr 2020 16:11:58 +0100 Subject: [PATCH 061/237] Revert "Discard unused CompatibilityPage.js in react-sdk" This reverts commit e3ba9c9b Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/_components.scss | 1 + res/css/structures/_CompatibilityPage.scss | 19 +++++ .../structures/CompatibilityPage.js | 78 +++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 res/css/structures/_CompatibilityPage.scss create mode 100644 src/components/structures/CompatibilityPage.js diff --git a/res/css/_components.scss b/res/css/_components.scss index 7bf1f88ec9..0ba2b609e8 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -2,6 +2,7 @@ @import "./_common.scss"; @import "./_font-sizes.scss"; @import "./structures/_AutoHideScrollbar.scss"; +@import "./structures/_CompatibilityPage.scss"; @import "./structures/_ContextualMenu.scss"; @import "./structures/_CreateRoom.scss"; @import "./structures/_CustomRoomTagPanel.scss"; diff --git a/res/css/structures/_CompatibilityPage.scss b/res/css/structures/_CompatibilityPage.scss new file mode 100644 index 0000000000..26354ed124 --- /dev/null +++ b/res/css/structures/_CompatibilityPage.scss @@ -0,0 +1,19 @@ +.mx_CompatibilityPage { + width: 100%; + height: 100%; + background-color: #e55; +} + +.mx_CompatibilityPage_box { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: auto; + width: 500px; + height: 300px; + border: 1px solid; + padding: 10px; + background-color: #fcc; +} diff --git a/src/components/structures/CompatibilityPage.js b/src/components/structures/CompatibilityPage.js new file mode 100644 index 0000000000..9a3fdb5f39 --- /dev/null +++ b/src/components/structures/CompatibilityPage.js @@ -0,0 +1,78 @@ +/* +Copyright 2015, 2016 OpenMarket Ltd +Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> +Copyright 2019 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +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 React from 'react'; +import createReactClass from 'create-react-class'; +import PropTypes from 'prop-types'; +import { _t } from '../../languageHandler'; + +export default createReactClass({ + displayName: 'CompatibilityPage', + propTypes: { + onAccept: PropTypes.func, + }, + + getDefaultProps: function() { + return { + onAccept: function() {}, // NOP + }; + }, + + onAccept: function() { + this.props.onAccept(); + }, + + render: function() { + return ( +
+
+

{ _t("Sorry, your browser is not able to run Riot.", {}, { 'b': (sub) => {sub} }) }

+

+ { _t( + "Riot uses many advanced browser features, some of which are not available " + + "or experimental in your current browser.", + ) } +

+

+ { _t( + 'Please install Chrome, Firefox, ' + + 'or Safari for the best experience.', + {}, + { + 'chromeLink': (sub) => {sub}, + 'firefoxLink': (sub) => {sub}, + 'safariLink': (sub) => {sub}, + }, + )} +

+

+ { _t( + "With your current browser, the look and feel of the application may be " + + "completely incorrect, and some or all features may not function. " + + "If you want to try it anyway you can continue, but you are on your own in terms " + + "of any issues you may encounter!", + ) } +

+ +
+
+ ); + }, +}); From 949b9160916bbdfb210cdc9d1f4ba1bfaf01ee66 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 23 Apr 2020 18:14:30 +0100 Subject: [PATCH 062/237] Fix recovery link on login verification flow This fixes the recovery link to go to the right place. Fixes https://github.com/vector-im/riot-web/issues/13346 --- src/components/structures/auth/SetupEncryptionBody.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/auth/SetupEncryptionBody.js b/src/components/structures/auth/SetupEncryptionBody.js index 13fa270a9c..26534c6e02 100644 --- a/src/components/structures/auth/SetupEncryptionBody.js +++ b/src/components/structures/auth/SetupEncryptionBody.js @@ -131,7 +131,7 @@ export default class SetupEncryptionBody extends React.Component {
- + {_t("Use Recovery Passphrase or Key")} From 42a857cb5e9a2aee7cb380d54c64e26a0f544de1 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@googlemail.com> Date: Fri, 24 Apr 2020 12:25:19 +0100 Subject: [PATCH 063/237] Revert "Update emojibase for fixed emoji codepoints and Emoji 13 support" (cherry picked from commit 972f9d354d2a5a671f47b4173c3600dfc950fd96) --- package.json | 4 ++-- yarn.lock | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 84bc83c2ba..6c56dd080b 100644 --- a/package.json +++ b/package.json @@ -65,8 +65,8 @@ "create-react-class": "^15.6.0", "diff-dom": "^4.1.3", "diff-match-patch": "^1.0.4", - "emojibase-data": "^5.0.1", - "emojibase-regex": "^4.0.1", + "emojibase-data": "^4.0.2", + "emojibase-regex": "^3.0.0", "escape-html": "^1.0.3", "file-saver": "^1.3.3", "filesize": "3.5.6", diff --git a/yarn.lock b/yarn.lock index 150d9b126b..c4a792136c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3072,15 +3072,15 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emojibase-data@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/emojibase-data/-/emojibase-data-5.0.1.tgz#ce6fe36b4affd3578e0be8779211018a2fdae960" - integrity sha512-rYWlogJ2q5P78U8Xx1vhsXHcYKu1wFnr7+o6z9QHssZ1SsJLTCkJINZIPHRFWuDreAUK457TkqHpdOXElu0fzA== +emojibase-data@^4.0.2: + version "4.2.1" + resolved "https://registry.yarnpkg.com/emojibase-data/-/emojibase-data-4.2.1.tgz#3d1f0c69ddbb2ca7b7014f5e34654190802a40df" + integrity sha512-O0vxoPMgVkRq/uII/gdAjz9RwNv6ClJrd3J9QCCRC4btZRmeut/qohC/Fi+NNXUcjY08RWNTvxSnq/vij8hvrw== -emojibase-regex@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/emojibase-regex/-/emojibase-regex-4.0.1.tgz#a2cd4bbb42825422da9ec72f15e970bc2c90b46a" - integrity sha512-S42UHkFfz15i4NNz+wi9iMKFo+B6Kalc6PJLpYX0BUANViXw4vSyYZMFdBGRLduSabWHuEcTLZl9xOa2YP3eJw== +emojibase-regex@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/emojibase-regex/-/emojibase-regex-3.2.1.tgz#122935958c9a49c96bb29ac69ccbbac0b2e7022d" + integrity sha512-VAX2Rc2U/alu5q6P2cET2alzC63o1Uarm6Ea/b3ab+KOzxZT4JKmB0tCU1sTZvfNKa16KMLCK2k7hJBHJq4vWQ== emojis-list@^2.0.0: version "2.1.0" From 353810ce633cf5c00c996112f8942cf356af2793 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Apr 2020 10:01:00 -0600 Subject: [PATCH 064/237] Remove invite only padlocks feature flag Fixes https://github.com/vector-im/riot-web/issues/13366 Only known issue on this is https://github.com/vector-im/riot-web/issues/12148 This has been pre-approved by Product. --- src/components/views/rooms/InviteOnlyIcon.js | 5 ----- src/i18n/strings/en_EN.json | 1 - src/settings/Settings.js | 6 ------ 3 files changed, 12 deletions(-) diff --git a/src/components/views/rooms/InviteOnlyIcon.js b/src/components/views/rooms/InviteOnlyIcon.js index acaa12303b..b02f9843d9 100644 --- a/src/components/views/rooms/InviteOnlyIcon.js +++ b/src/components/views/rooms/InviteOnlyIcon.js @@ -17,7 +17,6 @@ limitations under the License. import React from 'react'; import { _t } from '../../../languageHandler'; import * as sdk from '../../../index'; -import SettingsStore from '../../../settings/SettingsStore'; export default class InviteOnlyIcon extends React.Component { constructor() { @@ -39,10 +38,6 @@ export default class InviteOnlyIcon extends React.Component { render() { const classes = this.props.collapsedPanel ? "mx_InviteOnlyIcon_small": "mx_InviteOnlyIcon_large"; - if (!SettingsStore.isFeatureEnabled("feature_invite_only_padlocks")) { - return null; - } - const Tooltip = sdk.getComponent("elements.Tooltip"); let tooltip; if (this.state.hover) { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c141931dd7..ce39731808 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -401,7 +401,6 @@ "Support adding custom themes": "Support adding custom themes", "Enable cross-signing to verify per-user instead of per-session": "Enable cross-signing to verify per-user instead of per-session", "Show info about bridges in room settings": "Show info about bridges in room settings", - "Show padlocks on invite only rooms": "Show padlocks on invite only rooms", "Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing", "Use compact timeline layout": "Use compact timeline layout", "Show a placeholder for removed messages": "Show a placeholder for removed messages", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index d7374718d3..b85461de55 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -164,12 +164,6 @@ export const SETTINGS = { displayName: _td("Show info about bridges in room settings"), default: false, }, - "feature_invite_only_padlocks": { - isFeature: true, - supportedLevels: LEVELS_FEATURE, - displayName: _td("Show padlocks on invite only rooms"), - default: true, - }, "MessageComposerInput.suggestEmoji": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td('Enable Emoji suggestions while typing'), From d550f6c564fa0a201d2f344b3a8fbc78fd788e75 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 24 Apr 2020 15:58:28 +0100 Subject: [PATCH 065/237] Fix incorrect toast if security setup skipped DevieListener didn't wait for the user's device list to be downloaded so it would think the user didn't have cross-signing set up. Also clear the rest of the state on stop(). Fixes https://github.com/vector-im/riot-web/issues/13372 --- src/DeviceListener.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 4ec2ec0fa0..41f249b335 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -66,6 +66,9 @@ export default class DeviceListener { MatrixClientPeg.get().removeListener('sync', this._onSync); } this._dismissed.clear(); + this._dismissedThisDeviceToast = false; + this._keyBackupInfo = null; + this._keyBackupFetchedAt = null; } dismissVerification(deviceId) { @@ -146,6 +149,8 @@ export default class DeviceListener { ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY); } else { if (!crossSigningReady) { + // make sure our keys are finished downlaoding + await cli.downloadKeys([cli.getUserId()]); // cross signing isn't enabled - nag to enable it // There are 3 different toasts for: if (cli.getStoredCrossSigningForUser(cli.getUserId())) { From c684898ba038f96afe313e7bf3accf0c813784d1 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 24 Apr 2020 15:39:54 +0100 Subject: [PATCH 066/237] Make icon change in SetupEncryptionDialog Fixes https://github.com/vector-im/riot-web/issues/13368 --- .../views/dialogs/SetupEncryptionDialog.js | 49 ++++++++++++++++--- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/components/views/dialogs/SetupEncryptionDialog.js b/src/components/views/dialogs/SetupEncryptionDialog.js index f32a289a29..71b7574551 100644 --- a/src/components/views/dialogs/SetupEncryptionDialog.js +++ b/src/components/views/dialogs/SetupEncryptionDialog.js @@ -14,16 +14,49 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; +import PropTypes from 'prop-types'; import SetupEncryptionBody from '../../structures/auth/SetupEncryptionBody'; import BaseDialog from './BaseDialog'; import { _t } from '../../../languageHandler'; +import { SetupEncryptionStore, PHASE_DONE } from '../../../stores/SetupEncryptionStore'; -export default function SetupEncryptionDialog({onFinished}) { - return - - ; +function iconFromPhase(phase) { + if (phase === PHASE_DONE) { + return require("../../../../res/img/e2e/verified.svg"); + } else { + return require("../../../../res/img/e2e/warning.svg"); + } +} + +export default class SetupEncryptionDialog extends React.Component { + static propTypes = { + onFinished: PropTypes.func.isRequired, + }; + + constructor() { + super(); + + this.store = SetupEncryptionStore.sharedInstance(); + this.store.on("update", this._onStoreUpdate); + this.state = {icon: iconFromPhase(this.store.phase)}; + } + + componentWillUnmount() { + this.store.removeListener("update", this._onStoreUpdate); + } + + _onStoreUpdate = () => { + this.setState({icon: iconFromPhase(this.store.phase)}); + }; + + render() { + return + + ; + } } From b3fac7c2cb9aa9273d3896b38c973928fccae0ec Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 24 Apr 2020 17:36:02 +0100 Subject: [PATCH 067/237] Move store subscribe to didmount --- src/components/views/dialogs/SetupEncryptionDialog.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/SetupEncryptionDialog.js b/src/components/views/dialogs/SetupEncryptionDialog.js index 71b7574551..d7723de588 100644 --- a/src/components/views/dialogs/SetupEncryptionDialog.js +++ b/src/components/views/dialogs/SetupEncryptionDialog.js @@ -38,10 +38,13 @@ export default class SetupEncryptionDialog extends React.Component { super(); this.store = SetupEncryptionStore.sharedInstance(); - this.store.on("update", this._onStoreUpdate); this.state = {icon: iconFromPhase(this.store.phase)}; } + componentDidMount() { + this.store.on("update", this._onStoreUpdate); + } + componentWillUnmount() { this.store.removeListener("update", this._onStoreUpdate); } From 5f3e3b3ec20603fa94828b64f47eb49681490c1c Mon Sep 17 00:00:00 2001 From: Agusti Bau Date: Sat, 25 Apr 2020 01:09:07 +0200 Subject: [PATCH 068/237] Extracted context menu from TagTile to DNDTagTile --- src/components/views/elements/DNDTagTile.js | 91 ++++++++++++++++----- src/components/views/elements/TagTile.js | 60 ++++++-------- 2 files changed, 92 insertions(+), 59 deletions(-) diff --git a/src/components/views/elements/DNDTagTile.js b/src/components/views/elements/DNDTagTile.js index 7aa642986b..3ef805992e 100644 --- a/src/components/views/elements/DNDTagTile.js +++ b/src/components/views/elements/DNDTagTile.js @@ -17,29 +17,76 @@ limitations under the License. import TagTile from './TagTile'; -import React from 'react'; +import React, {createRef} from 'react'; import { Draggable } from 'react-beautiful-dnd'; +import {ContextMenu, toRightOf} from "../../structures/ContextMenu"; +import * as sdk from '../../../index'; -export default function DNDTagTile(props) { - return
- - { (provided, snapshot) => ( -
-
- +export default class DNDTagTile extends React.Component { + constructor() { + super(); + this.state = { + menuDisplayed: false, + }; + + this.openMenu = this.openMenu.bind(this); + this.closeMenu = this.closeMenu.bind(this); + } + + componentDidMount() { + this._contextMenuButton = createRef(); + } + + openMenu() { + this.setState({ + menuDisplayed: true, + }); + } + + closeMenu() { + console.log("Closig menu"); + this.setState({ + menuDisplayed: false, + }); + } + + getContextMenu() { + const elementRect = this._contextMenuButton.current.getBoundingClientRect(); + const TagTileContextMenu = sdk.getComponent('context_menus.TagTileContextMenu'); + return ( + + + + ); + } + + render(props) { + return
+ + { (provided, snapshot) => ( +
+
+ +
+ { provided.placeholder }
- { provided.placeholder } -
- ) } - -
; + ) } + + {this.state.menuDisplayed && this.getContextMenu()} +
; + } } diff --git a/src/components/views/elements/TagTile.js b/src/components/views/elements/TagTile.js index 2f182c261e..023d9cca93 100644 --- a/src/components/views/elements/TagTile.js +++ b/src/components/views/elements/TagTile.js @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import createReactClass from 'create-react-class'; import classNames from 'classnames'; @@ -28,7 +28,6 @@ import * as FormattingUtils from '../../../utils/FormattingUtils'; import FlairStore from '../../../stores/FlairStore'; import GroupStore from '../../../stores/GroupStore'; import TagOrderStore from '../../../stores/TagOrderStore'; -import {ContextMenu, toRightOf} from "../../structures/ContextMenu"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; // A class for a child of TagPanel (possibly wrapped in a DNDTagTile) that represents @@ -43,6 +42,9 @@ export default createReactClass({ // A string tag such as "m.favourite" or a group ID such as "+groupid:domain.bla" // For now, only group IDs are handled. tag: PropTypes.string, + contextMenuButtonRef: PropTypes.object, + openMenu: PropTypes.func, + menuDisplayed: PropTypes.bool, }, statics: { @@ -55,14 +57,10 @@ export default createReactClass({ hover: false, // The profile data of the group if this.props.tag is a group ID profile: null, - // Whether or not the context menu is open - menuDisplayed: false, }; }, componentDidMount() { - this._contextMenuButton = createRef(); - this.unmounted = false; if (this.props.tag[0] === '+') { FlairStore.addListener('updateGroupProfile', this._onFlairStoreUpdated); @@ -124,17 +122,8 @@ export default createReactClass({ // Prevent the TagTile onClick event firing as well e.stopPropagation(); e.preventDefault(); - - this.setState({ - menuDisplayed: true, - hover: false, - }); - }, - - closeMenu: function() { - this.setState({ - menuDisplayed: false, - }); + this.setState({hover: false}); + this.props.openMenu(); }, render: function() { @@ -163,26 +152,25 @@ export default createReactClass({ } // FIXME: this ought to use AccessibleButton for a11y but that causes onMouseOut/onMouseOver to fire too much - const contextButton = this.state.hover || this.state.menuDisplayed ? -
+ const contextButton = this.state.hover || this.props.menuDisplayed ? +
{ "\u00B7\u00B7\u00B7" } -
:
; - - let contextMenu; - if (this.state.menuDisplayed) { - const elementRect = this._contextMenuButton.current.getBoundingClientRect(); - const TagTileContextMenu = sdk.getComponent('context_menus.TagTileContextMenu'); - contextMenu = ( - - - - ); - } +
:
; const AccessibleTooltipButton = sdk.getComponent("elements.AccessibleTooltipButton"); - return - -
+ + return
+ +
- - { contextMenu } - ; +
; }, }); From 98a949bed1aca4916f82bbbe615f90891d330b49 Mon Sep 17 00:00:00 2001 From: Agusti Bau Date: Sat, 25 Apr 2020 01:09:07 +0200 Subject: [PATCH 069/237] Refactored DNDTagTile to use useContextMenu Signed-off-by: Agusti Bau --- src/components/views/elements/DNDTagTile.js | 63 ++++++--------------- 1 file changed, 18 insertions(+), 45 deletions(-) diff --git a/src/components/views/elements/DNDTagTile.js b/src/components/views/elements/DNDTagTile.js index 3ef805992e..5a96f01d9f 100644 --- a/src/components/views/elements/DNDTagTile.js +++ b/src/components/views/elements/DNDTagTile.js @@ -17,55 +17,29 @@ limitations under the License. import TagTile from './TagTile'; -import React, {createRef} from 'react'; +import React from 'react'; import { Draggable } from 'react-beautiful-dnd'; -import {ContextMenu, toRightOf} from "../../structures/ContextMenu"; +import {ContextMenu, toRightOf, useContextMenu} from "../../structures/ContextMenu"; import * as sdk from '../../../index'; -export default class DNDTagTile extends React.Component { - constructor() { - super(); - this.state = { - menuDisplayed: false, - }; +export default function DNDTagTile(props) { + const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu(); - this.openMenu = this.openMenu.bind(this); - this.closeMenu = this.closeMenu.bind(this); - } - - componentDidMount() { - this._contextMenuButton = createRef(); - } - - openMenu() { - this.setState({ - menuDisplayed: true, - }); - } - - closeMenu() { - console.log("Closig menu"); - this.setState({ - menuDisplayed: false, - }); - } - - getContextMenu() { - const elementRect = this._contextMenuButton.current.getBoundingClientRect(); + let contextMenu = null; + if (menuDisplayed && handle.current) { + const elementRect = handle.current.getBoundingClientRect(); const TagTileContextMenu = sdk.getComponent('context_menus.TagTileContextMenu'); - return ( - - + contextMenu = ( + + ); } - - render(props) { return
{ (provided, snapshot) => ( @@ -76,17 +50,16 @@ export default class DNDTagTile extends React.Component { {...provided.dragHandleProps} >
{ provided.placeholder }
) } - {this.state.menuDisplayed && this.getContextMenu()} + {contextMenu}
; - } } From 606940bd7763a0e23c6cf4977dc9f0d07995a81b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 27 Apr 2020 14:07:39 +0100 Subject: [PATCH 070/237] Update Invite Dialog copy to include email addresses Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/dialogs/InviteDialog.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index a46fa0df07..c30a34cb98 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -1067,9 +1067,8 @@ export default class InviteDialog extends React.PureComponent { let buttonText; let goButtonFn; + const userId = MatrixClientPeg.get().getUserId(); if (this.props.kind === KIND_DM) { - const userId = MatrixClientPeg.get().getUserId(); - title = _t("Direct Messages"); helpText = _t( "Start a conversation with someone using their name, username (like ) or email address.", @@ -1083,12 +1082,11 @@ export default class InviteDialog extends React.PureComponent { } else { // KIND_INVITE title = _t("Invite to this room"); helpText = _t( - "If you can't find someone, ask them for their username (e.g. @user:server.com) or " + - "share this room.", {}, - { - a: (sub) => - {sub}, - }, + "Invite someone using their name, username (like ) or email address.", + {}, + {userId: () => { + return {userId}; + }}, ); buttonText = _t("Invite"); goButtonFn = this._inviteUsers; From 37374036d5cf098b7c48b30cfe98eff221947720 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 27 Apr 2020 14:09:41 +0100 Subject: [PATCH 071/237] i18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index bd4c8f58c8..3b6e077aac 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1642,7 +1642,7 @@ "Recently Direct Messaged": "Recently Direct Messaged", "Start a conversation with someone using their name, username (like ) or email address.": "Start a conversation with someone using their name, username (like ) or email address.", "Go": "Go", - "If you can't find someone, ask them for their username (e.g. @user:server.com) or share this room.": "If you can't find someone, ask them for their username (e.g. @user:server.com) or share this room.", + "Invite someone using their name, username (like ) or email address.": "Invite someone using their name, username (like ) or email address.", "You added a new session '%(displayName)s', which is requesting encryption keys.": "You added a new session '%(displayName)s', which is requesting encryption keys.", "Your unverified session '%(displayName)s' is requesting encryption keys.": "Your unverified session '%(displayName)s' is requesting encryption keys.", "Start verification": "Start verification", From a58fd6c4756c15106ad4536f4bf5bb322a9b479d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 27 Apr 2020 14:27:41 +0100 Subject: [PATCH 072/237] delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/dialogs/InviteDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index c30a34cb98..7bc9364b52 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -19,7 +19,7 @@ import PropTypes from 'prop-types'; import {_t} from "../../../languageHandler"; import * as sdk from "../../../index"; import {MatrixClientPeg} from "../../../MatrixClientPeg"; -import {makeRoomPermalink, makeUserPermalink} from "../../../utils/permalinks/Permalinks"; +import {makeUserPermalink} from "../../../utils/permalinks/Permalinks"; import DMRoomMap from "../../../utils/DMRoomMap"; import {RoomMember} from "matrix-js-sdk/src/matrix"; import SdkConfig from "../../../SdkConfig"; From ab369e70238e7504bcb52b4997342b1383352b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Mon, 27 Apr 2020 14:01:10 +0000 Subject: [PATCH 073/237] Translated using Weblate (Estonian) Currently translated at 6.7% (154 of 2294 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 5d60c1c5d9..49bfed674d 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -144,5 +144,13 @@ "Explore rooms": "Uuri jututubasid", "If you've joined lots of rooms, this might take a while": "Kui oled liitunud paljude jututubadega, siis see võib natuke aega võtta", "If disabled, messages from encrypted rooms won't appear in search results.": "Kui see seadistus pole kasutusel, siis krüptitud jututubade sõnumeid otsing ei vaata.", - "Indexed rooms:": "Indekseeritud jututoad:" + "Indexed rooms:": "Indekseeritud jututoad:", + "Remove": "Eemalda", + "You should remove your personal data from identity server before disconnecting. Unfortunately, identity server is currently offline or cannot be reached.": "Sa peaksid enne ühenduse katkestamisst eemaldama isiklikud andmed id-serverist . Kahjuks id-server ei ole hetkel võrgus või pole kättesaadav.", + "We recommend that you remove your email addresses and phone numbers from the identity server before disconnecting.": "Me soovitame, et eemaldad enne ühenduse katkestamist oma e-posti aadressi ja telefoninumbrid id-serverist.", + "Remove messages": "Kustuta sõnumid", + "Unable to remove contact information": "Kontaktiinfo eemaldamine ebaõnnestus", + "Remove %(email)s?": "Eemalda %(email)s?", + "Remove %(phone)s?": "Eemalda %(phone)s?", + "Remove recent messages by %(user)s": "Eemalda %(user)s hiljutised sõnumid" } From 0a89813de1a1fa3a83d5ae27ef14d00c7e5fcb6c Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 27 Apr 2020 14:25:47 +0100 Subject: [PATCH 074/237] Add a link from settings / devices to your user profile Temporarily until you can verify devices in settings Fixes https://github.com/vector-im/riot-web/issues/13401 --- src/components/views/dialogs/UserSettingsDialog.js | 2 +- .../settings/tabs/user/SecurityUserSettingsTab.js | 12 ++++++++++++ src/i18n/strings/en_EN.json | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/UserSettingsDialog.js b/src/components/views/dialogs/UserSettingsDialog.js index b135d5f5f6..210773c524 100644 --- a/src/components/views/dialogs/UserSettingsDialog.js +++ b/src/components/views/dialogs/UserSettingsDialog.js @@ -89,7 +89,7 @@ export default class UserSettingsDialog extends React.Component { tabs.push(new Tab( _td("Security & Privacy"), "mx_UserSettingsDialog_securityIcon", - , + , )); if (SdkConfig.get()['showLabsSettings'] || SettingsStore.getLabsFeatures().length > 0) { tabs.push(new Tab( diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index a88f35da68..a8435857ad 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -50,6 +50,10 @@ export class IgnoredUser extends React.Component { } export default class SecurityUserSettingsTab extends React.Component { + static propTypes = { + closeSettingsFn: PropTypes.func.isRequired, + }; + constructor() { super(); @@ -85,6 +89,11 @@ export default class SecurityUserSettingsTab extends React.Component { ); }; + _onGoToUserProfileClick = () => { + // close the settings dialog & let the default action run (ie. navigate to the link) + this.props.closeSettingsFn(); + } + _onUserUnignored = async (userId) => { // Don't use this.state to get the ignored user list as it might be // ever so slightly outdated. Instead, prefer to get a fresh list and @@ -283,6 +292,9 @@ export default class SecurityUserSettingsTab extends React.Component { return (
{_t("Security & Privacy")}
+ + {_t("Verify your devices in your User Profile")} +
{_t("Sessions")}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c141931dd7..94d02b30dd 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -843,6 +843,7 @@ "Message search": "Message search", "Cross-signing": "Cross-signing", "Security & Privacy": "Security & Privacy", + "Verify your devices in your User Profile": "Verify your devices in your User Profile", "Sessions": "Sessions", "A session's public name is visible to people you communicate with": "A session's public name is visible to people you communicate with", "Riot collects anonymous analytics to allow us to improve the application.": "Riot collects anonymous analytics to allow us to improve the application.", From ef1e40c83995a6495678d86a4c67d59982b0e0da Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 27 Apr 2020 14:35:32 +0100 Subject: [PATCH 075/237] Update to (almost) match design --- .../tabs/user/SecurityUserSettingsTab.js | 16 ++++++++++++---- src/i18n/strings/en_EN.json | 4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index a8435857ad..688668d0cb 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -292,11 +292,19 @@ export default class SecurityUserSettingsTab extends React.Component { return (
{_t("Security & Privacy")}
- - {_t("Verify your devices in your User Profile")} -
- {_t("Sessions")} + {_t("Where you’re logged in")} + + {_t( + "Manage the names of and sign out of your sessions below or " + + "verify them in your User Profile.", {}, + { + a: sub => {sub} + } + )} +
{_t("A session's public name is visible to people you communicate with")} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 94d02b30dd..775e04b55f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -843,8 +843,9 @@ "Message search": "Message search", "Cross-signing": "Cross-signing", "Security & Privacy": "Security & Privacy", + "Where you’re logged in": "Where you’re logged in", + "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Manage the names of and sign out of your sessions below or verify them in your User Profile.", "Verify your devices in your User Profile": "Verify your devices in your User Profile", - "Sessions": "Sessions", "A session's public name is visible to people you communicate with": "A session's public name is visible to people you communicate with", "Riot collects anonymous analytics to allow us to improve the application.": "Riot collects anonymous analytics to allow us to improve the application.", "Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.", @@ -1029,6 +1030,7 @@ "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.", "Are you sure?": "Are you sure?", "No sessions with registered encryption keys": "No sessions with registered encryption keys", + "Sessions": "Sessions", "Jump to read receipt": "Jump to read receipt", "Mention": "Mention", "Invite": "Invite", From d6f96f2f27b5329b0e0b59a08bebf11195380fd3 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 27 Apr 2020 14:38:22 +0100 Subject: [PATCH 076/237] Update i18n --- src/i18n/strings/en_EN.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 775e04b55f..2d36f756e6 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -845,7 +845,6 @@ "Security & Privacy": "Security & Privacy", "Where you’re logged in": "Where you’re logged in", "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Manage the names of and sign out of your sessions below or verify them in your User Profile.", - "Verify your devices in your User Profile": "Verify your devices in your User Profile", "A session's public name is visible to people you communicate with": "A session's public name is visible to people you communicate with", "Riot collects anonymous analytics to allow us to improve the application.": "Riot collects anonymous analytics to allow us to improve the application.", "Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.", From 63d2d128c5f12ba1549dc4955f6d6c59e806288c Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 27 Apr 2020 14:43:17 +0100 Subject: [PATCH 077/237] Lint --- .../views/settings/tabs/user/SecurityUserSettingsTab.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index 688668d0cb..0eec59806a 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -301,8 +301,8 @@ export default class SecurityUserSettingsTab extends React.Component { { a: sub => {sub} - } + >{sub}, + }, )}
From b396096cd217130841802ee65652b088c2821b6a Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 27 Apr 2020 18:35:51 +0100 Subject: [PATCH 078/237] Fix set up encryption toast to have use "set up" as action This changes the "set up encryption" toast to use "set up" as the primary action button, instead of "upgrade". Other toasts that do use text about upgrading will keep their primary action text of "upgrade" as before. Fixes https://github.com/vector-im/riot-web/issues/13231 --- src/components/views/toasts/SetupEncryptionToast.js | 1 + src/i18n/strings/en_EN.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/toasts/SetupEncryptionToast.js b/src/components/views/toasts/SetupEncryptionToast.js index 3c1f42b526..75fd55378c 100644 --- a/src/components/views/toasts/SetupEncryptionToast.js +++ b/src/components/views/toasts/SetupEncryptionToast.js @@ -90,6 +90,7 @@ export default class SetupEncryptionToast extends React.PureComponent { getSetupCaption() { switch (this.props.kind) { case 'set_up_encryption': + return _t('Set up'); case 'upgrade_encryption': case 'upgrade_ssss': return _t('Upgrade'); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index bd4c8f58c8..9c0468733e 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -561,6 +561,7 @@ "Verify yourself & others to keep your chats safe": "Verify yourself & others to keep your chats safe", "Other users may not trust it": "Other users may not trust it", "Update your secure storage": "Update your secure storage", + "Set up": "Set up", "Upgrade": "Upgrade", "Verify": "Verify", "Later": "Later", @@ -2227,7 +2228,6 @@ "Unable to create key backup": "Unable to create key backup", "Without setting up Secure Message Recovery, you'll lose your secure message history when you log out.": "Without setting up Secure Message Recovery, you'll lose your secure message history when you log out.", "If you don't want to set this up now, you can later in Settings.": "If you don't want to set this up now, you can later in Settings.", - "Set up": "Set up", "Don't ask again": "Don't ask again", "New Recovery Method": "New Recovery Method", "A new recovery passphrase and key for Secure Messages have been detected.": "A new recovery passphrase and key for Secure Messages have been detected.", From 1a99917556235784a7e98eb1975b9b511cc8c5aa Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 27 Apr 2020 17:50:50 +0100 Subject: [PATCH 079/237] only clear on continuations where the clear isn't done by SenderProfile Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/rooms/_EventTile.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index e015f30e48..89564cd130 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -110,8 +110,11 @@ limitations under the License. user-select: none; } -.mx_EventTile_line, .mx_EventTile_reply { +.mx_EventTile_continuation .mx_EventTile_line { clear: both; +} + +.mx_EventTile_line, .mx_EventTile_reply { position: relative; padding-left: 65px; /* left gutter */ padding-top: 4px; From de3226177cb6f4e6877b4fca775c73fe28742f69 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 26 Apr 2020 12:52:17 +0100 Subject: [PATCH 080/237] cap width of editable item list item to leave space for its X remove button Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/elements/_EditableItemList.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/res/css/views/elements/_EditableItemList.scss b/res/css/views/elements/_EditableItemList.scss index ef60f006cc..f089fa3dc2 100644 --- a/res/css/views/elements/_EditableItemList.scss +++ b/res/css/views/elements/_EditableItemList.scss @@ -53,6 +53,9 @@ limitations under the License. .mx_EditableItem_item { flex: auto 1 0; order: 1; + width: calc(100% - 14px); // leave space for the remove button + overflow-x: hidden; + text-overflow: ellipsis; } .mx_EditableItemList_label { From 2792988ad1a0a37ba413273128d50557e495c446 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 27 Apr 2020 23:59:07 +0100 Subject: [PATCH 081/237] Revert "Make Screens an enum" This reverts commit f6492918 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 326 ++++++++++------------- 1 file changed, 147 insertions(+), 179 deletions(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 02a79f9684..e117d8f76b 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -103,22 +103,6 @@ export enum Views { SOFT_LOGOUT = 9, } -export enum Screens { - REGISTER = "register", - LOGIN = "login", - FORGOT_PASSWORD = "forgot_password", - SOFT_LOGOUT = "soft_logout", - NEW = "new", // new room - SETTINGS = "settings", - WELCOME = "welcome", - HOME = "home", - START = "start", - DIRECTORY = "directory", - GROUPS = "groups", - COMPLETE_SECURITY = "complete_security", - POST_REGISTRATION = "post_registration", -} - // Actions that are redirected through the onboarding process prior to being // re-dispatched. NOTE: some actions are non-trivial and would require // re-factoring to be included in this list in future. @@ -130,7 +114,7 @@ const ONBOARDING_FLOW_STARTERS = [ ]; interface IScreen { - screen: Screens | string; + screen: string; params?: object; } @@ -339,9 +323,9 @@ export default class MatrixChat extends React.PureComponent { // the old creds, but rather go straight to the relevant page const firstScreen = this.screenAfterLogin ? this.screenAfterLogin.screen : null; - if (firstScreen === Screens.LOGIN || - firstScreen === Screens.REGISTER || - firstScreen === Screens.FORGOT_PASSWORD) { + if (firstScreen === 'login' || + firstScreen === 'register' || + firstScreen === 'forgot_password') { this.showScreenAfterLogin(); return; } @@ -555,7 +539,7 @@ export default class MatrixChat extends React.PureComponent { this.setStateForNewView({ view: Views.LOGIN, }); - this.notifyNewScreen(Screens.LOGIN); + this.notifyNewScreen('login'); ThemeController.isLogin = true; this.themeWatcher.recheck(); break; @@ -568,7 +552,7 @@ export default class MatrixChat extends React.PureComponent { this.setStateForNewView({ view: Views.FORGOT_PASSWORD, }); - this.notifyNewScreen(Screens.FORGOT_PASSWORD); + this.notifyNewScreen('forgot_password'); break; case 'start_chat': createRoom({ @@ -819,7 +803,7 @@ export default class MatrixChat extends React.PureComponent { this.setStateForNewView(newState); ThemeController.isLogin = true; this.themeWatcher.recheck(); - this.notifyNewScreen(Screens.REGISTER); + this.notifyNewScreen('register'); } // TODO: Move to RoomViewStore @@ -1298,7 +1282,7 @@ export default class MatrixChat extends React.PureComponent { * Called when the session is logged out */ private onLoggedOut() { - this.notifyNewScreen(Screens.LOGIN); + this.notifyNewScreen('login'); this.setStateForNewView({ view: Views.LOGIN, ready: false, @@ -1315,7 +1299,7 @@ export default class MatrixChat extends React.PureComponent { * Called when the session is softly logged out */ private onSoftLogout() { - this.notifyNewScreen(Screens.SOFT_LOGOUT); + this.notifyNewScreen('soft_logout'); this.setStateForNewView({ view: Views.SOFT_LOGOUT, ready: false, @@ -1604,168 +1588,152 @@ export default class MatrixChat extends React.PureComponent { } } - showScreen(screen: Screens | string, params?: {[key: string]: any}) { - switch (screen) { - case Screens.REGISTER: - dis.dispatch({ - action: 'start_registration', - params: params, - }); - break; - case Screens.LOGIN: + showScreen(screen: string, params?: {[key: string]: any}) { + if (screen === 'register') { + dis.dispatch({ + action: 'start_registration', + params: params, + }); + } else if (screen === 'login') { + dis.dispatch({ + action: 'start_login', + params: params, + }); + } else if (screen === 'forgot_password') { + dis.dispatch({ + action: 'start_password_recovery', + params: params, + }); + } else if (screen === 'soft_logout') { + if (MatrixClientPeg.get() && MatrixClientPeg.get().getUserId() && !Lifecycle.isSoftLogout()) { + // Logged in - visit a room + this.viewLastRoom(); + } else { + // Ultimately triggers soft_logout if needed dis.dispatch({ action: 'start_login', params: params, }); - break; - case Screens.FORGOT_PASSWORD: - dis.dispatch({ - action: 'start_password_recovery', - params: params, - }); - break; - case Screens.SOFT_LOGOUT: - if (MatrixClientPeg.get() && MatrixClientPeg.get().getUserId() && !Lifecycle.isSoftLogout()) { - // Logged in - visit a room - this.viewLastRoom(); - } else { - // Ultimately triggers soft_logout if needed - dis.dispatch({ - action: 'start_login', - params: params, - }); - } - break; - case Screens.NEW: - dis.dispatch({ - action: 'view_create_room', - }); - break; - case Screens.SETTINGS: - dis.dispatch({ - action: 'view_user_settings', - }); - break; - case Screens.WELCOME: - dis.dispatch({ - action: 'view_welcome_page', - }); - break; - case Screens.HOME: - dis.dispatch({ - action: 'view_home_page', - }); - break; - case Screens.START: - this.showScreen(Screens.HOME); - dis.dispatch({ - action: 'require_registration', - }); - break; - case Screens.DIRECTORY: - dis.dispatch({ - action: 'view_room_directory', - }); - break; - case Screens.GROUPS: - dis.dispatch({ - action: 'view_my_groups', - }); - break; - case Screens.COMPLETE_SECURITY: - dis.dispatch({ - action: 'start_complete_security', - }); - break; - case Screens.POST_REGISTRATION: - dis.dispatch({ - action: 'start_post_registration', - }); - break; - default: - if (screen.startsWith('room/')) { - // Rooms can have the following formats: - // #room_alias:domain or !opaque_id:domain - const room = screen.substring(5); - const domainOffset = room.indexOf(':') + 1; // 0 in case room does not contain a : - let eventOffset = room.length; - // room aliases can contain slashes only look for slash after domain - if (room.substring(domainOffset).indexOf('/') > -1) { - eventOffset = domainOffset + room.substring(domainOffset).indexOf('/'); - } - const roomString = room.substring(0, eventOffset); - let eventId = room.substring(eventOffset + 1); // empty string if no event id given + } + } else if (screen === 'new') { + dis.dispatch({ + action: 'view_create_room', + }); + } else if (screen === 'settings') { + dis.dispatch({ + action: 'view_user_settings', + }); + } else if (screen === 'welcome') { + dis.dispatch({ + action: 'view_welcome_page', + }); + } else if (screen === 'home') { + dis.dispatch({ + action: 'view_home_page', + }); + } else if (screen === 'start') { + this.showScreen('home'); + dis.dispatch({ + action: 'require_registration', + }); + } else if (screen === 'directory') { + dis.dispatch({ + action: 'view_room_directory', + }); + } else if (screen === 'groups') { + dis.dispatch({ + action: 'view_my_groups', + }); + } else if (screen === 'complete_security') { + dis.dispatch({ + action: 'start_complete_security', + }); + } else if (screen === 'post_registration') { + dis.dispatch({ + action: 'start_post_registration', + }); + } else if (screen.indexOf('room/') === 0) { + // Rooms can have the following formats: + // #room_alias:domain or !opaque_id:domain + const room = screen.substring(5); + const domainOffset = room.indexOf(':') + 1; // 0 in case room does not contain a : + let eventOffset = room.length; + // room aliases can contain slashes only look for slash after domain + if (room.substring(domainOffset).indexOf('/') > -1) { + eventOffset = domainOffset + room.substring(domainOffset).indexOf('/'); + } + const roomString = room.substring(0, eventOffset); + let eventId = room.substring(eventOffset + 1); // empty string if no event id given - // Previously we pulled the eventID from the segments in such a way - // where if there was no eventId then we'd get undefined. However, we - // now do a splice and join to handle v3 event IDs which results in - // an empty string. To maintain our potential contract with the rest - // of the app, we coerce the eventId to be undefined where applicable. - if (!eventId) eventId = undefined; + // Previously we pulled the eventID from the segments in such a way + // where if there was no eventId then we'd get undefined. However, we + // now do a splice and join to handle v3 event IDs which results in + // an empty string. To maintain our potential contract with the rest + // of the app, we coerce the eventId to be undefined where applicable. + if (!eventId) eventId = undefined; - // TODO: Handle encoded room/event IDs: https://github.com/vector-im/riot-web/issues/9149 + // TODO: Handle encoded room/event IDs: https://github.com/vector-im/riot-web/issues/9149 - // FIXME: sort_out caseConsistency - const thirdPartyInvite = { - inviteSignUrl: params.signurl, - invitedEmail: params.email, - }; - const oobData = { - name: params.room_name, - avatarUrl: params.room_avatar_url, - inviterName: params.inviter_name, - }; + // FIXME: sort_out caseConsistency + const thirdPartyInvite = { + inviteSignUrl: params.signurl, + invitedEmail: params.email, + }; + const oobData = { + name: params.room_name, + avatarUrl: params.room_avatar_url, + inviterName: params.inviter_name, + }; - // on our URLs there might be a ?via=matrix.org or similar to help - // joins to the room succeed. We'll pass these through as an array - // to other levels. If there's just one ?via= then params.via is a - // single string. If someone does something like ?via=one.com&via=two.com - // then params.via is an array of strings. - let via = []; - if (params.via) { - if (typeof(params.via) === 'string') via = [params.via]; - else via = params.via; - } + // on our URLs there might be a ?via=matrix.org or similar to help + // joins to the room succeed. We'll pass these through as an array + // to other levels. If there's just one ?via= then params.via is a + // single string. If someone does something like ?via=one.com&via=two.com + // then params.via is an array of strings. + let via = []; + if (params.via) { + if (typeof(params.via) === 'string') via = [params.via]; + else via = params.via; + } - const payload = { - action: 'view_room', - event_id: eventId, - via_servers: via, - // If an event ID is given in the URL hash, notify RoomViewStore to mark - // it as highlighted, which will propagate to RoomView and highlight the - // associated EventTile. - highlighted: Boolean(eventId), - third_party_invite: thirdPartyInvite, - oob_data: oobData, - room_alias: undefined, - room_id: undefined, - }; - if (roomString[0] === '#') { - payload.room_alias = roomString; - } else { - payload.room_id = roomString; - } + const payload = { + action: 'view_room', + event_id: eventId, + via_servers: via, + // If an event ID is given in the URL hash, notify RoomViewStore to mark + // it as highlighted, which will propagate to RoomView and highlight the + // associated EventTile. + highlighted: Boolean(eventId), + third_party_invite: thirdPartyInvite, + oob_data: oobData, + room_alias: undefined, + room_id: undefined, + }; + if (roomString[0] === '#') { + payload.room_alias = roomString; + } else { + payload.room_id = roomString; + } - dis.dispatch(payload); - } else if (screen.startsWith('user/')) { - const userId = screen.substring(5); - dis.dispatch({ - action: 'view_user_info', - userId: userId, - subAction: params.action, - }); - } else if (screen.startsWith('group/')) { - const groupId = screen.substring(6); + dis.dispatch(payload); + } else if (screen.indexOf('user/') === 0) { + const userId = screen.substring(5); + dis.dispatch({ + action: 'view_user_info', + userId: userId, + subAction: params.action, + }); + } else if (screen.indexOf('group/') === 0) { + const groupId = screen.substring(6); - // TODO: Check valid group ID + // TODO: Check valid group ID - dis.dispatch({ - action: 'view_group', - group_id: groupId, - }); - } else { - console.info("Ignoring showScreen for '%s'", screen); - } + dis.dispatch({ + action: 'view_group', + group_id: groupId, + }); + } else { + console.info("Ignoring showScreen for '%s'", screen); } } @@ -1832,15 +1800,15 @@ export default class MatrixChat extends React.PureComponent { } onRegisterClick = () => { - this.showScreen(Screens.REGISTER); + this.showScreen("register"); }; onLoginClick = () => { - this.showScreen(Screens.LOGIN); + this.showScreen("login"); }; onForgotPasswordClick = () => { - this.showScreen(Screens.FORGOT_PASSWORD); + this.showScreen("forgot_password"); }; onRegisterFlowComplete = (credentials: object, password: string) => { @@ -1857,7 +1825,7 @@ export default class MatrixChat extends React.PureComponent { this.setState({ view: Views.LOGGED_IN, }); - this.showScreen(Screens.SETTINGS); + this.showScreen("settings"); }; onVersion(current: string, latest: string, releaseNotes?: string) { From d61b72c0e51cd468d7102beceed267df474d29db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Mon, 27 Apr 2020 18:36:59 +0000 Subject: [PATCH 082/237] Translated using Weblate (Estonian) Currently translated at 11.1% (256 of 2296 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 111 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 49bfed674d..71fd4db711 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -47,7 +47,7 @@ "%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s", "Verify this session": "Verifitseeri see sessioon", "Which rooms would you like to add to this community?": "Milliseid jututubasid sooviksid lisada siia kogukonda?", - "Show these rooms to non-members on the community page and room list?": "Kas näitan neid jututubasid kogukonna lehel ja tubade loendis mitte-liikmetele?", + "Show these rooms to non-members on the community page and room list?": "Kas näitan neid jututubasid kogukonna lehel ja tubade loendis kogukonna mitte-liikmetele?", "Add rooms to the community": "Lisa siia kogukonda jututubasid", "Failed to add the following rooms to %(groupId)s:": "Järgnevate jututubade lisamine %(groupId)s kogukonda ebaõnnestus:", "Changes your avatar in all rooms": "Muuda oma tunnuspilti kõikides jututubades", @@ -152,5 +152,112 @@ "Unable to remove contact information": "Kontaktiinfo eemaldamine ebaõnnestus", "Remove %(email)s?": "Eemalda %(email)s?", "Remove %(phone)s?": "Eemalda %(phone)s?", - "Remove recent messages by %(user)s": "Eemalda %(user)s hiljutised sõnumid" + "Remove recent messages by %(user)s": "Eemalda %(user)s hiljutised sõnumid", + "Replying With Files": "Vasta faili(de)ga", + "Invite new community members": "Kutsu uusi liikmeid kogukonda", + "rooms.": "jututoad.", + "Notify for all other messages/rooms": "Teavita kõikidest teistest sõnumitest/jututubadest", + "Members only (since the point in time of selecting this option)": "Ainult liikmetele (alates selle seadistuse kasutuselevõtmisest)", + "Members only (since they were invited)": "Ainult liikmetele (alates nende kutsumise ajast)", + "Members only (since they joined)": "Ainult liikmetele (alates liitumisest)", + "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|other": "Oled kustutamas %(user)s %(count)s sõnumit. Seda tegevust ei saa hiljem tagasi pöörata. Kas sa kindlasti soovid jätkata?", + "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|one": "Oled kustutamas ühte %(user)s sõnumit. Seda tegevust ei saa hiljem tagasi pöörata. Kas sa kindlasti soovid jätkata?", + "Remove %(count)s messages|other": "Eemalda %(count)s sõnumit", + "Remove %(count)s messages|one": "Eemalda 1 sõnum", + "Remove recent messages": "Eemalda hiljutised sõnumid", + "Filter room members": "Filtreeri jututoa liikmeid", + "Members": "Liikmed", + "Files": "Failid", + "Remove from community": "Eemalda kogukonnast", + "Remove this user from community?": "Kas eemaldan selle kasutaja kogukonnast?", + "Failed to remove user from community": "Kasutaja eemaldamine kogukonnast ebaõnnestus", + "Failed to load group members": "Grupi liikmete laadimine ebaõnnestus", + "Filter community members": "Filtreeri kogukonna liikmeid", + "Are you sure you want to remove '%(roomName)s' from %(groupId)s?": "Kas sa soovid eemaldada %(roomName)s jututoa %(groupId)s kogukonnast?", + "Removing a room from the community will also remove it from the community page.": "Eemaldades jututoa kogukonnast eemaldad selle ka kogukonna lehelt.", + "Failed to remove room from community": "Jututoa eemaldamine kogukonnast ebaõnnestus", + "Failed to remove '%(roomName)s' from %(groupId)s": "Jututoa %(roomName)s eemaldamine %(groupId)s kogukonnast ebaõnnestus", + "Only visible to community members": "Nähtav ainult kogukonna liikmetele", + "Filter community rooms": "Filtreeri kogukonna jututubasid", + "Failed to remove widget": "Vidina eemaldamine ebaõnnestus", + "An error ocurred whilst trying to remove the widget from the room": "Vidina eemaldamisel jututoast tekkis viga", + "Are you sure you want to remove %(serverName)s": "Kas sa oled kindel et soovid eemadlada %(serverName)s", + "Remove server": "Eemalda server", + "%(networkName)s rooms": "%(networkName)s jututoad", + "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "Kas sa oled kindel et soovid eemaldada (kustutada) seda sündmust? Pane tähele, et see muutus võib tagasi pöörduda, kui muudad hiljem jututoa nime või teemanime.", + "Sign out and remove encryption keys?": "Logi välja ja eemalda krüptimisvõtmed?", + "Upload files (%(current)s of %(total)s)": "Lae failid üles (%(current)s / %(total)s)", + "Upload files": "Lae failid üles", + "These files are too large to upload. The file size limit is %(limit)s.": "Need failid on üleslaadimiseks liiga suured. Failisuuruse piir on %(limit)s.", + "Some files are too large to be uploaded. The file size limit is %(limit)s.": "Mõned failid on üleslaadimiseks liiga suured. Failisuuruse piir on %(limit)s.", + "Upload %(count)s other files|other": "Lae üles %(count)s muud faili", + "Unable to reject invite": "Ei õnnestu kutset tagasi lükata", + "Resend": "Saada uuesti", + "Resend edit": "Saada muudetud sõnum uuesti", + "Resend %(unsentCount)s reaction(s)": "Saada uuesti %(unsentCount)s reaktsioon(i)", + "Resend removal": "Saada eemaldamine uuesti", + "Cancel Sending": "Tühista saatmine", + "Forward Message": "Edasta sõnum", + "Pin Message": "Klammerda sõnum", + "View Decrypted Source": "Vaata dekrüptitud lähtekoodi", + "Unhide Preview": "Näita eelvaadet", + "Share Permalink": "Jaga püsiviidet", + "Share Message": "Jaga sõnumit", + "Source URL": "Lähteaadress", + "Collapse Reply Thread": "Ahenda vastuste jutulõnga", + "End-to-end encryption information": "Läbiva krüptimise teave", + "Notification settings": "Teavituste seadistused", + "All messages (noisy)": "Kõik sõnumid (lärmakas)", + "All messages": "Kõik sõnumid", + "Mentions only": "Ainult mainimised", + "Leave": "Lahku", + "Forget": "Unusta", + "Favourite": "Lemmik", + "Low Priority": "Madal prioriteet", + "Direct Chat": "Otsevestlus", + "Clear status": "Eemalda olek", + "Update status": "Uuenda olek", + "Set status": "Määra olek", + "Set a new status...": "Määra uus olek...", + "View Community": "Näita kogukonda", + "Hide": "Peida", + "Home": "Avaleht", + "Sign in": "Logi sisse", + "Help": "Abiteave", + "Reload": "Lae uuesti", + "Take picture": "Tee foto", + "Remove for everyone": "Eemalda kõigilt", + "Remove for me": "Eemalda minult", + "User Status": "Kasutaja olek", + "You must join the room to see its files": "Failide nägemiseks pead jututoaga liituma", + "There are no visible files in this room": "Jututoas pole nähtavaid faile", + "Failed to remove the room from the summary of %(groupId)s": "Jututoa eemaldamine %(groupId)s kogukonna ülevaatelehelt ebaõnnestus", + "Failed to remove a user from the summary of %(groupId)s": "Kasutaja eemaldamine %(groupId)s kogukonna ülevaatelehelt ebaõnnestus", + "Create a Group Chat": "Loo rühmavestlus", + "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Kas kustutame jututoa aliase %(alias)s ja eemaldame %(name)s kataloogist?", + "Remove %(name)s from the directory?": "Eemalda %(name)s kataloogist?", + "Remove from Directory": "Eemalda kataloogist", + "remove %(name)s from the directory.": "eemalda %(name)s kataloogist.", + "You seem to be uploading files, are you sure you want to quit?": "Tundub, et sa parasjagu laed faile üles, kas sa kindlasti soovid väljuda?", + "Failed to set direct chat tag": "Otsevestluse sildi lisamine ei õnnestunud", + "Failed to remove tag %(tagName)s from room": "Sildi %(tagName)s eemaldamine jututoast ebaõnnestus", + "Calls": "Kõned", + "Room List": "Jututubade loend", + "Alt": "Alt", + "Alt Gr": "Alt Gr", + "Shift": "Shift", + "Super": "Super", + "Ctrl": "Ctrl", + "Toggle Bold": "Lülita paks kiri sisse/välja", + "Toggle Italics": "Lülita kaldkiri sisse/välja", + "Toggle Quote": "Lülita tsiteerimine sisse/välja", + "New line": "Reavahetus", + "Cancel replying to a message": "Tühista sõnumile vastamine", + "Toggle microphone mute": "Lülita mikrofoni summutamine sisse/välja", + "Toggle video on/off": "Lülita video kasutamine sisse/välja", + "Jump to room search": "Suundu jututoa otsingusse", + "Navigate up/down in the room list": "Suundu jututubade loendis üles/alla", + "Select room from the room list": "Vali tubade loendist jututuba", + "Collapse room list section": "Ahenda jututubade loendi valikut", + "Expand room list section": "Laienda jututubade loendi valikut" } From 8aeeff4204467e56211d027e36d160ec16f1477f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 28 Apr 2020 06:56:41 +0000 Subject: [PATCH 083/237] Translated using Weblate (Estonian) Currently translated at 13.8% (317 of 2296 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 67 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 71fd4db711..8b0206ded9 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -110,8 +110,8 @@ "Create new room": "Loo uus jututuba", "Unblacklist": "Eemalda mustast nimekirjast", "Blacklist": "Kanna musta nimekirja", - "Unverify": "Eemalda õigeks tunnistamine", - "Verify...": "Tunnista õigeks...", + "Unverify": "Tühista verifitseerimine", + "Verify...": "Verifitseeri...", "Join": "Liitu", "No results": "Tulemusi pole", "Please create a new issue on GitHub so that we can investigate this bug.": "Selle vea uurimiseks palun loo uus veateade meie GitHub'is.", @@ -259,5 +259,66 @@ "Navigate up/down in the room list": "Suundu jututubade loendis üles/alla", "Select room from the room list": "Vali tubade loendist jututuba", "Collapse room list section": "Ahenda jututubade loendi valikut", - "Expand room list section": "Laienda jututubade loendi valikut" + "Expand room list section": "Laienda jututubade loendi valikut", + "Create Account": "Loo konto", + "Sign In": "Logi sisse", + "Send a bug report with logs": "Saada veakirjeldus koos logidega", + "Group & filter rooms by custom tags (refresh to apply changes)": "Rühmita ja filtreeri jututubasid kohandatud siltide alusel (muudatuste rakendamiseks värskenda vaade)", + "Try out new ways to ignore people (experimental)": "Proovi uusi kasutajate eiramise viise (katseline)", + "Uploading report": "Laen üles veakirjeldust", + "To report a Matrix-related security issue, please read the Matrix.org Security Disclosure Policy.": "Kui soovid teatada Matrix'iga seotud turvaveast, siis palun tutvu enne Matrix.org Turvalisuse avalikustamise juhendiga.", + "Add users and servers you want to ignore here. Use asterisks to have Riot match any characters. For example, @bot:* would ignore all users that have the name 'bot' on any server.": "Lisa siia kasutajad ja serverid keda soovid eirata. Kasuta tärne kõikide märkide tähistamiseks. Näiteks @bot:* eiraks kõiki kasutajaid kõikidest serveritest, kus nimi on \"bot\".", + "Server or user ID to ignore": "Serverid või kasutajate tunnused, mida soovid eirata", + "Ignore": "Eira", + "If this isn't what you want, please use a different tool to ignore users.": "Kui tulemus pole see mida soovisid, siis pruugi muud vahendit kasutajate eiramiseks.", + "Sessions": "Sessioonid", + "Mention": "Maini", + "Share Link to User": "Jaga viidet kasutaja kohta", + "User Options": "Kasutaja valikud", + "Direct chats": "Isiklikud sõnumid", + "Admin Tools": "Haldustoimingud", + "Online": "Võrgus", + "Reject & Ignore user": "Hülga ja eira kasutaja", + "%(count)s unread messages including mentions.|one": "1 lugemata mainimine.", + "Filter results": "Filtreeri tulemusi", + "Ignore request": "Eira taotlust", + "Report bugs & give feedback": "Teata vigadest ja anna tagasisidet", + "Report Content to Your Homeserver Administrator": "Teata sisust Sinu koduserveri haldurile", + "Send report": "Saada veateade", + "(HTTP status %(httpStatus)s)": "(HTTP staatuse kood %(httpStatus)s)", + "Please set a password!": "Palun määra salasõna!", + "This will allow you to return to your account after signing out, and sign in on other sessions.": "See võimaldab sul tagasi tulla oma kasutajakonto juurde ka peale väljalogimist ning logida sisse muudesse sessioonidesse.", + "Share Room": "Jaga jututuba", + "Link to most recent message": "Viide kõige viimasele sõnumile", + "Share User": "Jaga viidet kasutaja kohta", + "Share Community": "Jaga viidet kogukonna kohta", + "Share Room Message": "Jaga jututoa sõnumit", + "Link to selected message": "Viide valitud sõnumile", + "COPY": "KOPEERI", + "Command Help": "Abiteave käskude kohta", + "To help us prevent this in future, please send us logs.": "Tagamaks et sama ei juhtuks tulevikus, palun saada meile salvestatud logid.", + "Missing session data": "Sessiooni andmed on puudu", + "Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.": "Osa sessiooniandmetest, sealhulgas sõnumi krüptovõtmed, on puudu. Vea parandamiseks logi välja ja sisse, vajadusel taasta võtmed varundusest.", + "Your browser likely removed this data when running low on disk space.": "On võimalik et sinu brauser kustutas need andmed, sest kõvakettaruumist jäi puudu.", + "Integration Manager": "Lõiminguhaldur", + "Find others by phone or email": "Leia teisi kasutajaid telefoninumbri või e-posti aadressi alsusel", + "Be found by phone or email": "Ole leitav telefoninumbri või e-posti aadressi alsusel", + "Terms of Service": "Kasutustingimused", + "To continue you need to accept the terms of this service.": "Jätkamaks pead nõustuma kasutustingimustega.", + "Service": "Teenus", + "Summary": "Kokkuvõte", + "Document": "Dokument", + "Next": "Järgmine", + "You are currently blacklisting unverified sessions; to send messages to these sessions you must verify them.": "Sa parasjagu oled kõik verifitseerimata sessioonid kandnud musta nimekirja. Sinna sõnumite saatmiseks sa pead nad enne verifitseerima.", + "Room contains unknown sessions": "Jututoas on tundmatuid sessioone", + "\"%(RoomName)s\" contains sessions that you haven't seen before.": "\"%(RoomName)s\" sisaldab sessioone, mida sa ei ole varem näinud.", + "Unknown sessions": "Tundmatud sessioonid", + "Report Content": "Teata sisust haldurile", + "powered by Matrix": "põhineb Matrix'il", + "Custom Server Options": "Serveri kohaldatud seadistused", + "Missing captcha public key in homeserver configuration. Please report this to your homeserver administrator.": "Robotilõksu avalik võti on puudu koduserveri seadistustes. Palun teata sellest oma koduserveri haldurile.", + "Filter": "Filtreeri", + "Clear filter": "Eemalda filter", + "Copy": "Kopeeri", + "Clear room list filter field": "Tühjenda jututubade filtriväli" } From dfb2c66b6c12a5ddbd88213aaf691ae22bd1cb42 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Tue, 28 Apr 2020 02:41:30 +0000 Subject: [PATCH 084/237] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2296 of 2296 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/zh_Hant/ --- src/i18n/strings/zh_Hant.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index b2e6c35e71..164e5500b3 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -2402,5 +2402,7 @@ "Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.": "透過驗證這個從您的其他工作階段而來的登入來確認您的身份,並授予其對加密訊息的存取權限。", "This requires the latest Riot on your other devices:": "這需要在您的其他裝置上使用最新的 Riot:", "or another cross-signing capable Matrix client": "或另一個有交叉簽章功能的 Matrix 客戶端", - "Use Recovery Passphrase or Key": "使用復原通關密語或金鑰" + "Use Recovery Passphrase or Key": "使用復原通關密語或金鑰", + "Where you’re logged in": "您登入的地方", + "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "在下方管理您工作階段的名稱與登入或在您的使用者檔案中驗證它們。" } From 41ef40a0e3d9b3ef2af5289a3b82cb7f6015513c Mon Sep 17 00:00:00 2001 From: Remi Reuvekamp <20200217translateriot@remi.im> Date: Mon, 27 Apr 2020 23:00:41 +0000 Subject: [PATCH 085/237] Translated using Weblate (Dutch) Currently translated at 91.1% (2092 of 2296 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/nl/ --- src/i18n/strings/nl.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index 95a49bce8c..19f626bc0a 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -2165,5 +2165,8 @@ "To report a Matrix-related security issue, please read the Matrix.org Security Disclosure Policy.": "Bekijk eerst het beveiligingsopenbaarmakingsbeleid van Matrix.org als u een probleem met de beveiliging van Matrix wilt melden.", "Not currently indexing messages for any room.": "Er worden momenteel voor geen enkel gesprek berichten geïndexeerd.", "Currently indexing: %(currentRoom)s.": "Wordt geïndexeerd: %(currentRoom)s.", - "%(doneRooms)s out of %(totalRooms)s": "%(doneRooms)s van %(totalRooms)s" + "%(doneRooms)s out of %(totalRooms)s": "%(doneRooms)s van %(totalRooms)s", + "Unverified login. Was this you?": "Ongeverifieerde aanmelding. Was u dit?", + "Where you’re logged in": "Waar u aangemeld bent", + "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Beheer hieronder de namen van uw sessies en meld ze af. Of verifieer ze in uw gebruikersprofiel." } From 0b9423f6efb214abf66162ad1409a3259c4549a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20C?= Date: Tue, 28 Apr 2020 06:35:00 +0000 Subject: [PATCH 086/237] Translated using Weblate (French) Currently translated at 100.0% (2296 of 2296 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index a7b09ea8ac..dcec0da857 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -2403,5 +2403,7 @@ "Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.": "Confirmez votre identité en vérifiant cette connexion depuis une de vos autres sessions, cela lui permettra d’avoir accès aux messages chiffrés.", "This requires the latest Riot on your other devices:": "Ceci nécessite la dernière version de Riot sur vos autres appareils :", "or another cross-signing capable Matrix client": "ou un autre client Matrix compatible avec la signature croisée", - "Use Recovery Passphrase or Key": "Utiliser la phrase secrète ou la clé de récupération" + "Use Recovery Passphrase or Key": "Utiliser la phrase secrète ou la clé de récupération", + "Where you’re logged in": "Où vous vous êtes connecté", + "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Gérez les noms et déconnectez-vous de vos sessions ci-dessous ou vérifiez-les dans votre profil utilisateur." } From df28baf4f4eeb2ebf57cc37ba47488db78f0629d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 28 Apr 2020 09:28:54 +0000 Subject: [PATCH 087/237] Translated using Weblate (Estonian) Currently translated at 14.0% (321 of 2296 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 8b0206ded9..77b860dc2b 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -320,5 +320,9 @@ "Filter": "Filtreeri", "Clear filter": "Eemalda filter", "Copy": "Kopeeri", - "Clear room list filter field": "Tühjenda jututubade filtriväli" + "Clear room list filter field": "Tühjenda jututubade filtriväli", + "Mute": "Summuta", + "Settings": "Seadistused", + "You're not currently a member of any communities.": "Sa ei ole hetkel ainsamagi kogukonna liige.", + "Create a new community": "Loo uus kogukond" } From 9d1c73348c4b9038f8b82b3a1842cf85afcb58b0 Mon Sep 17 00:00:00 2001 From: Zoe Date: Mon, 27 Apr 2020 16:58:24 +0100 Subject: [PATCH 088/237] Show progress when loading keys --- .../keybackup/RestoreKeyBackupDialog.js | 25 ++++++++++++++++++- src/i18n/strings/en_EN.json | 3 +++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index dc82a71713..92d23f9e65 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -59,6 +59,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { forceRecoveryKey: false, passPhrase: '', restoreType: null, + progress: { stage: "prefetch" }, }; } @@ -80,6 +81,12 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { }); } + _progressCallback = (data) => { + this.setState({ + progress: data, + }); + } + _onResetRecoveryClick = () => { this.props.onFinished(false); Modal.createTrackedDialogAsync('Key Backup', 'Key Backup', @@ -110,6 +117,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { // is the right one and restoring it is currently the only way we can do this. const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithPassword( this.state.passPhrase, undefined, undefined, this.state.backupInfo, + { progressCallback: this._progressCallback }, ); if (this.props.keyCallback) { const key = await MatrixClientPeg.get().keyBackupKeyFromPassword( @@ -146,6 +154,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { try { const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithRecoveryKey( this.state.recoveryKey, undefined, undefined, this.state.backupInfo, + { progressCallback: this._progressCallback }, ); if (this.props.keyCallback) { const key = MatrixClientPeg.get().keyBackupKeyFromRecoveryKey(this.state.recoveryKey); @@ -185,6 +194,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { const recoverInfo = await accessSecretStorage(async () => { return MatrixClientPeg.get().restoreKeyBackupWithSecretStorage( this.state.backupInfo, + { progressCallback: this._progressCallback }, ); }); this.setState({ @@ -207,6 +217,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { undefined, /* targetRoomId */ undefined, /* targetSessionId */ backupInfo, + { progressCallback: this._progressCallback }, ); this.setState({ recoverInfo, @@ -273,7 +284,19 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { let title; if (this.state.loading) { title = _t("Loading..."); - content = ; + let details; + if (this.state.progress.stage === "fetch") { + details = _t("Downloading from server..."); + } else if (this.state.progress.stage === "load_keys") { + const { total, successes, failures } = this.state.progress; + details = _t("Loaded %(completed)s of %(total)s", { total, completed: successes + failures }); + } else if (this.state.progress.stage === "prefetch") { + details = _t("Requesting from server..."); + } + content =
+
{details}
+ +
; } else if (this.state.loadError) { title = _t("Error"); content = _t("Unable to load backup status"); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index bd4c8f58c8..ff9e5957d5 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1791,6 +1791,9 @@ "Not a valid recovery key": "Not a valid recovery key", "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.", "If you've forgotten your recovery key you can .": "If you've forgotten your recovery key you can .", + "Downloading from server": "Downloading from server", + "Loaded %(completed)s of %(total)s": "Loaded %(completed)s of %(total)s", + "Requesting from server...": "Requesting from server...", "Unable to load backup status": "Unable to load backup status", "Recovery key mismatch": "Recovery key mismatch", "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.": "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.", From 689d6735fc62da4278a3d5aed88b5a822be394f6 Mon Sep 17 00:00:00 2001 From: Zoe Date: Tue, 28 Apr 2020 11:36:28 +0100 Subject: [PATCH 089/237] i18n --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index ff9e5957d5..e33a389e27 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1791,7 +1791,7 @@ "Not a valid recovery key": "Not a valid recovery key", "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.", "If you've forgotten your recovery key you can .": "If you've forgotten your recovery key you can .", - "Downloading from server": "Downloading from server", + "Downloading from server...": "Downloading from server...", "Loaded %(completed)s of %(total)s": "Loaded %(completed)s of %(total)s", "Requesting from server...": "Requesting from server...", "Unable to load backup status": "Unable to load backup status", From 198edb06b93a3c750c5621e6bb7e12d4dfd73a3d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 28 Apr 2020 16:35:20 +0200 Subject: [PATCH 090/237] use normal accessible button, which is themed --- res/css/views/rooms/_RoomRecoveryReminder.scss | 5 ----- src/components/views/rooms/RoomRecoveryReminder.js | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/res/css/views/rooms/_RoomRecoveryReminder.scss b/res/css/views/rooms/_RoomRecoveryReminder.scss index 85d42ca4b4..09b28ae235 100644 --- a/res/css/views/rooms/_RoomRecoveryReminder.scss +++ b/res/css/views/rooms/_RoomRecoveryReminder.scss @@ -33,11 +33,6 @@ limitations under the License. margin-bottom: 1em; } -.mx_RoomRecoveryReminder_button { - @mixin mx_DialogButton; - margin: 0 10px; -} - .mx_RoomRecoveryReminder_secondary { font-size: 90%; margin-top: 1em; diff --git a/src/components/views/rooms/RoomRecoveryReminder.js b/src/components/views/rooms/RoomRecoveryReminder.js index b1a5aa5f5e..a29467b07f 100644 --- a/src/components/views/rooms/RoomRecoveryReminder.js +++ b/src/components/views/rooms/RoomRecoveryReminder.js @@ -150,7 +150,7 @@ export default class RoomRecoveryReminder extends React.PureComponent { )}

- {setupCaption} From 8b8b5256be5a8c2ab291288d3c9b55eebe1c4be7 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 28 Apr 2020 16:49:25 +0200 Subject: [PATCH 091/237] actually use timeline highlight color --- res/themes/light-custom/css/_custom.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/res/themes/light-custom/css/_custom.scss b/res/themes/light-custom/css/_custom.scss index 64c4cac7e3..6206496150 100644 --- a/res/themes/light-custom/css/_custom.scss +++ b/res/themes/light-custom/css/_custom.scss @@ -53,7 +53,6 @@ $tooltip-timeline-bg-color: var(--sidebar-color); $dialog-backdrop-color: var(--sidebar-color-50pct); // // --roomlist-background-color -$event-selected-color: var(--roomlist-background-color); $header-panel-bg-color: var(--roomlist-background-color); $reaction-row-button-bg-color: var(--roomlist-background-color); $panel-gradient: var(--roomlist-background-color-0pct), var(--roomlist-background-color); @@ -134,3 +133,6 @@ $username-variant5-color: var(--username-colors_5, $username-variant5-color); $username-variant6-color: var(--username-colors_6, $username-variant6-color); $username-variant7-color: var(--username-colors_7, $username-variant7-color); $username-variant8-color: var(--username-colors_8, $username-variant8-color); + +$event-selected-color: var(--timeline-highlights-color); +$event-highlight-bg-color: var(--timeline-highlights-color); From 6b28dfa50caa88addf7836f67afbc4545b6d91f7 Mon Sep 17 00:00:00 2001 From: random Date: Tue, 28 Apr 2020 13:34:01 +0000 Subject: [PATCH 092/237] Translated using Weblate (Italian) Currently translated at 100.0% (2297 of 2297 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/it/ --- src/i18n/strings/it.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index 78020c7bb8..bb2bf3c95b 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -2400,5 +2400,9 @@ "Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.": "Conferma la tua identità verificando questo accesso da una delle tue altre sessioni, dandogli l'accesso ai messaggi cifrati.", "This requires the latest Riot on your other devices:": "È richiesta l'ultima versione di Riot sui tuoi altri dispositivi:", "or another cross-signing capable Matrix client": "o un altro client Matrix che supporti la firma incrociata", - "Use Recovery Passphrase or Key": "Usa la password di ripristino o la chiave" + "Use Recovery Passphrase or Key": "Usa la password di ripristino o la chiave", + "Review where you’re logged in": "Controlla dove hai fatto l'accesso", + "Verify your other sessions": "Verifica le tue altre sessioni", + "Where you’re logged in": "Dove hai fatto l'accesso", + "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Gestisci i nomi e disconnettiti dalle tue sessioni sotto o verificale nel tuo profilo utente." } From 32c512dbfee7a8bd115539119011aa7a106d1b5a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 28 Apr 2020 17:49:10 +0100 Subject: [PATCH 093/237] Fix internal link styling in Security Settings Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../settings/tabs/user/_SecurityUserSettingsTab.scss | 8 ++++++++ .../views/settings/tabs/user/SecurityUserSettingsTab.js | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss b/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss index b5a6693006..849979f444 100644 --- a/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss @@ -55,3 +55,11 @@ limitations under the License. .mx_SecurityUserSettingsTab_ignoredUser .mx_AccessibleButton { margin-right: 10px; } + +.mx_SecurityUserSettingsTab { + .mx_SettingsTab_section { + .mx_AccessibleButton_kind_link { + padding: 0; + } + } +} diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index 1a74bbdf93..a4336a81f3 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -112,7 +112,7 @@ export default class SecurityUserSettingsTab extends React.Component { }; _onGoToUserProfileClick = () => { - // close the settings dialog & let the default action run (ie. navigate to the link) + window.location.href = "#/user/" + MatrixClientPeg.get().getUserId(); this.props.closeSettingsFn(); } @@ -327,9 +327,9 @@ export default class SecurityUserSettingsTab extends React.Component { "Manage the names of and sign out of your sessions below or " + "verify them in your User Profile.", {}, { - a: sub => {sub}, + a: sub => + {sub} + , }, )} From a63dd664a1b18f55829fbb878b0b45eb19f9b838 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 28 Apr 2020 17:57:32 +0100 Subject: [PATCH 094/237] fix font-size Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss b/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss index 849979f444..8700f8747d 100644 --- a/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss @@ -60,6 +60,7 @@ limitations under the License. .mx_SettingsTab_section { .mx_AccessibleButton_kind_link { padding: 0; + font-size: inherit; } } } From 719faed2ff50e3bb0dca2a827fa6c73e174b2d84 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 28 Apr 2020 18:35:16 +0100 Subject: [PATCH 095/237] Separate toasts for existing & new device verification Separate device verification toasts into ones for devices that were there when the app loaded and a separate toast for each device that has appeared since. Reverts part of https://github.com/matrix-org/matrix-react-sdk/pull/4506 (clicking a device from your own UserInfo now triggers the legacy verification flow again). Fixes https://github.com/vector-im/riot-web/issues/13422 Fixes https://github.com/vector-im/riot-web/issues/13418 --- src/DeviceListener.js | 104 +++++++++++++++--- src/SlashCommands.tsx | 2 +- .../views/right_panel/EncryptionPanel.js | 6 +- src/components/views/right_panel/UserInfo.js | 4 +- src/components/views/rooms/MemberInfo.js | 11 +- ...oast.js => BulkUnverifiedSessionsToast.js} | 13 ++- src/i18n/strings/en_EN.json | 7 +- src/utils/ShieldUtils.ts | 4 +- src/verification.js | 64 +++++------ test/utils/ShieldUtils-test.js | 2 +- 10 files changed, 138 insertions(+), 79 deletions(-) rename src/components/views/toasts/{UnverifiedSessionToast.js => BulkUnverifiedSessionsToast.js} (78%) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 1b451310b9..e3b833a340 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -24,6 +24,10 @@ const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000; const THIS_DEVICE_TOAST_KEY = 'setupencryption'; const OTHER_DEVICES_TOAST_KEY = 'reviewsessions'; +function toastKey(deviceId) { + return "unverified_session_" + deviceId; +} + export default class DeviceListener { static sharedInstance() { if (!global.mx_DeviceListener) global.mx_DeviceListener = new DeviceListener(); @@ -39,9 +43,18 @@ export default class DeviceListener { // cache of the key backup info this._keyBackupInfo = null; this._keyBackupFetchedAt = null; + + // We keep a list of our own device IDs so we can batch ones that were already + // there the last time the app launched into a single toast, but display new + // ones in their own toasts. + this._ourDeviceIdsAtStart = null; + + // The set of device IDs we're currently displaying toasts for + this._displayingToastsForDeviceIds = new Set(); } start() { + MatrixClientPeg.get().on('crypto.willUpdateDevices', this._onWillUpdateDevices); MatrixClientPeg.get().on('crypto.devicesUpdated', this._onDevicesUpdated); MatrixClientPeg.get().on('deviceVerificationChanged', this._onDeviceVerificationChanged); MatrixClientPeg.get().on('userTrustStatusChanged', this._onUserTrustStatusChanged); @@ -53,6 +66,7 @@ export default class DeviceListener { stop() { if (MatrixClientPeg.get()) { + MatrixClientPeg.get().removeListener('crypto.willUpdateDevices', this._onWillUpdateDevices); MatrixClientPeg.get().removeListener('crypto.devicesUpdated', this._onDevicesUpdated); MatrixClientPeg.get().removeListener('deviceVerificationChanged', this._onDeviceVerificationChanged); MatrixClientPeg.get().removeListener('userTrustStatusChanged', this._onUserTrustStatusChanged); @@ -66,10 +80,15 @@ export default class DeviceListener { this._keyBackupFetchedAt = null; } - async dismissVerifications() { - const cli = MatrixClientPeg.get(); - const devices = await cli.getStoredDevicesForUser(cli.getUserId()); - this._dismissed = new Set(devices.filter(d => d.deviceId !== cli.deviceId).map(d => d.deviceId)); + /** + * Dismiss notifications about our own unverified devices + * + * @param {String[]} deviceIds List of device IDs to dismiss notifications for + */ + async dismissUnverifiedSessions(deviceIds) { + for (const d of deviceIds) { + this._dismissed.add(d); + } this._recheck(); } @@ -79,6 +98,20 @@ export default class DeviceListener { this._recheck(); } + _ensureDeviceIdsAtStartPopulated() { + if (this._ourDeviceIdsAtStart === null) { + const cli = MatrixClientPeg.get(); + this._ourDeviceIdsAtStart = new Set( + cli.getStoredDevicesForUser(cli.getUserId()).map(d => d.deviceId), + ); + } + } + + _onWillUpdateDevices = async (users) => { + const myUserId = MatrixClientPeg.get().getUserId(); + if (users.includes(myUserId)) this._ensureDeviceIdsAtStartPopulated(); + } + _onDevicesUpdated = (users) => { if (!users.includes(MatrixClientPeg.get().getUserId())) return; this._recheck(); @@ -143,6 +176,8 @@ export default class DeviceListener { const crossSigningReady = await cli.isCrossSigningReady(); + this._ensureDeviceIdsAtStartPopulated(); + if (this._dismissedThisDeviceToast) { ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY); } else { @@ -197,32 +232,65 @@ export default class DeviceListener { } } + // Unverified devices that were there last time the app ran + // (technically could just be a boolean: we don't actually + // need to remember the device IDs, but for the sake of + // symmetry...). + const oldUnverifiedDeviceIds = new Set(); + // Unverified devices that have appeared since then + const newUnverifiedDeviceIds = new Set(); + // as long as cross-signing isn't ready, // you can't see or dismiss any device toasts if (crossSigningReady) { - let haveUnverifiedDevices = false; - - const devices = await cli.getStoredDevicesForUser(cli.getUserId()); + const devices = cli.getStoredDevicesForUser(cli.getUserId()); for (const device of devices) { if (device.deviceId == cli.deviceId) continue; const deviceTrust = await cli.checkDeviceTrust(cli.getUserId(), device.deviceId); if (!deviceTrust.isCrossSigningVerified() && !this._dismissed.has(device.deviceId)) { - haveUnverifiedDevices = true; - break; + if (this._ourDeviceIdsAtStart.has(device.deviceId)) { + oldUnverifiedDeviceIds.add(device.deviceId); + } else { + newUnverifiedDeviceIds.add(device.deviceId); + } } } + } - if (haveUnverifiedDevices) { - ToastStore.sharedInstance().addOrReplaceToast({ - key: OTHER_DEVICES_TOAST_KEY, - title: _t("Review where you’re logged in"), - icon: "verification_warning", - component: sdk.getComponent("toasts.UnverifiedSessionToast"), - }); - } else { - ToastStore.sharedInstance().dismissToast(OTHER_DEVICES_TOAST_KEY); + // Display or hide the batch toast for old unverified sessions + if (oldUnverifiedDeviceIds.size > 0) { + ToastStore.sharedInstance().addOrReplaceToast({ + key: OTHER_DEVICES_TOAST_KEY, + title: _t("Review where you’re logged in"), + icon: "verification_warning", + props: { + deviceIds: oldUnverifiedDeviceIds, + }, + component: sdk.getComponent("toasts.BulkUnverifiedSessionsToast"), + }); + } else { + ToastStore.sharedInstance().dismissToast(OTHER_DEVICES_TOAST_KEY); + } + + // Show toasts for new unverified devices if they aren't already there + for (const deviceId of newUnverifiedDeviceIds) { + ToastStore.sharedInstance().addOrReplaceToast({ + key: toastKey(deviceId), + title: _t("Unverified login. Was this you?"), + icon: "verification_warning", + props: { deviceId }, + component: sdk.getComponent("toasts.UnverifiedSessionToast"), + }); + } + + // ...and hide any we don't need any more + for (const deviceId of this._displayingToastsForDeviceIds) { + if (!newUnverifiedDeviceIds.has(deviceId)) { + ToastStore.sharedInstance().dismissToast(toastKey(deviceId)); } } + + this._displayingToastsForDeviceIds = newUnverifiedDeviceIds; } } diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index 7b9bbeface..bd7e60e2f4 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -836,7 +836,7 @@ export const Commands = [ const fingerprint = matches[3]; return success((async () => { - const device = await cli.getStoredDevice(userId, deviceId); + const device = cli.getStoredDevice(userId, deviceId); if (!device) { throw new Error(_t('Unknown (user, session) pair:') + ` (${userId}, ${deviceId})`); } diff --git a/src/components/views/right_panel/EncryptionPanel.js b/src/components/views/right_panel/EncryptionPanel.js index 476b6cace9..bc580c767b 100644 --- a/src/components/views/right_panel/EncryptionPanel.js +++ b/src/components/views/right_panel/EncryptionPanel.js @@ -22,7 +22,6 @@ import VerificationPanel from "./VerificationPanel"; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import {ensureDMExists} from "../../../createRoom"; import {useEventEmitter} from "../../../hooks/useEventEmitter"; -import {useAsyncMemo} from "../../../hooks/useAsyncMemo"; import Modal from "../../../Modal"; import {PHASE_REQUESTED, PHASE_UNSENT} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; import * as sdk from "../../../index"; @@ -47,10 +46,7 @@ const EncryptionPanel = (props) => { }, [verificationRequest]); const deviceId = request && request.channel.deviceId; - const device = useAsyncMemo(() => { - const cli = MatrixClientPeg.get(); - return cli.getStoredDevice(cli.getUserId(), deviceId); - }, [deviceId]); + const device = MatrixClientPeg.get().getStoredDevice(MatrixClientPeg.get().getUserId(), deviceId); useEffect(() => { async function awaitPromise() { diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index cafbf05a23..61f5a8161a 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -1110,7 +1110,7 @@ export const useDevices = (userId) => { async function _downloadDeviceList() { try { await cli.downloadKeys([userId], true); - const devices = await cli.getStoredDevicesForUser(userId); + const devices = cli.getStoredDevicesForUser(userId); if (cancelled) { // we got cancelled - presumably a different user now @@ -1135,7 +1135,7 @@ export const useDevices = (userId) => { useEffect(() => { let cancel = false; const updateDevices = async () => { - const newDevices = await cli.getStoredDevicesForUser(userId); + const newDevices = cli.getStoredDevicesForUser(userId); if (cancel) return; setDevices(newDevices); }; diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 9fdd2abedf..be3e8cf971 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -160,13 +160,10 @@ export default createReactClass({ // no need to re-download the whole thing; just update our copy of // the list. - // Promise.resolve to handle transition from static result to promise; can be removed - // in future - Promise.resolve(this.context.getStoredDevicesForUser(userId)).then((devices) => { - this.setState({ - devices: devices, - e2eStatus: this._getE2EStatus(devices), - }); + const devices = this.context.getStoredDevicesForUser(userId); + this.setState({ + devices: devices, + e2eStatus: this._getE2EStatus(devices), }); } }, diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/BulkUnverifiedSessionsToast.js similarity index 78% rename from src/components/views/toasts/UnverifiedSessionToast.js rename to src/components/views/toasts/BulkUnverifiedSessionsToast.js index 886e3c4c20..b16dc87f21 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/BulkUnverifiedSessionsToast.js @@ -15,6 +15,7 @@ limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import dis from "../../../dispatcher"; import { MatrixClientPeg } from '../../../MatrixClientPeg'; @@ -22,14 +23,18 @@ import DeviceListener from '../../../DeviceListener'; import FormButton from '../elements/FormButton'; import { replaceableComponent } from '../../../utils/replaceableComponent'; -@replaceableComponent("views.toasts.UnverifiedSessionToast") -export default class UnverifiedSessionToast extends React.PureComponent { +@replaceableComponent("views.toasts.BulkUnverifiedSessionsToast") +export default class BulkUnverifiedSessionsToast extends React.PureComponent { + static propTypes = { + deviceIds: PropTypes.array, + } + _onLaterClick = () => { - DeviceListener.sharedInstance().dismissVerifications(); + DeviceListener.sharedInstance().dismissUnverifiedSessions(this.props.deviceIds); }; _onReviewClick = async () => { - DeviceListener.sharedInstance().dismissVerifications(); + DeviceListener.sharedInstance().dismissUnverifiedSessions(this.props.deviceIds); dis.dispatch({ action: 'view_user_info', diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a308f91748..8ffc35fda6 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -106,6 +106,7 @@ "Encryption upgrade available": "Encryption upgrade available", "Set up encryption": "Set up encryption", "Review where you’re logged in": "Review where you’re logged in", + "Unverified login. Was this you?": "Unverified login. Was this you?", "Who would you like to add to this community?": "Who would you like to add to this community?", "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID", "Invite new community members": "Invite new community members", @@ -558,14 +559,14 @@ "Headphones": "Headphones", "Folder": "Folder", "Pin": "Pin", + "Verify your other sessions": "Verify your other sessions", + "Later": "Later", + "Review": "Review", "Verify yourself & others to keep your chats safe": "Verify yourself & others to keep your chats safe", "Other users may not trust it": "Other users may not trust it", "Update your secure storage": "Update your secure storage", "Upgrade": "Upgrade", "Verify": "Verify", - "Later": "Later", - "Verify your other sessions": "Verify your other sessions", - "Review": "Review", "From %(deviceName)s (%(deviceId)s)": "From %(deviceName)s (%(deviceId)s)", "Decline (%(counter)s)": "Decline (%(counter)s)", "Accept to continue:": "Accept to continue:", diff --git a/src/utils/ShieldUtils.ts b/src/utils/ShieldUtils.ts index 9bf6fe2327..adaa961a00 100644 --- a/src/utils/ShieldUtils.ts +++ b/src/utils/ShieldUtils.ts @@ -7,7 +7,7 @@ interface Client { isCrossSigningVerified: () => boolean wasCrossSigningVerified: () => boolean }; - getStoredDevicesForUser: (userId: string) => Promise<[{ deviceId: string }]>; + getStoredDevicesForUser: (userId: string) => [{ deviceId: string }]; checkDeviceTrust: (userId: string, deviceId: string) => { isVerified: () => boolean } @@ -45,7 +45,7 @@ export async function shieldStatusForRoom(client: Client, room: Room): Promise { return !client.checkDeviceTrust(userId, deviceId).isVerified(); }); diff --git a/src/verification.js b/src/verification.js index 630da01091..d7287552dd 100644 --- a/src/verification.js +++ b/src/verification.js @@ -23,7 +23,6 @@ import {RIGHT_PANEL_PHASES} from "./stores/RightPanelStorePhases"; import {findDMForUser} from './createRoom'; import {accessSecretStorage} from './CrossSigningManager'; import SettingsStore from './settings/SettingsStore'; -import NewSessionReviewDialog from './components/views/dialogs/NewSessionReviewDialog'; import {verificationMethods} from 'matrix-js-sdk/src/crypto'; async function enable4SIfNeeded() { @@ -70,41 +69,34 @@ export async function verifyDevice(user, device) { } } - if (user.userId === cli.getUserId()) { - Modal.createTrackedDialog('New Session Review', 'Starting dialog', NewSessionReviewDialog, { - userId: user.userId, - device, - }); - } else { - Modal.createTrackedDialog("Verification warning", "unverified session", UntrustedDeviceDialog, { - user, - device, - onFinished: async (action) => { - if (action === "sas") { - const verificationRequestPromise = cli.legacyDeviceVerification( - user.userId, - device.deviceId, - verificationMethods.SAS, - ); - dis.dispatch({ - action: "set_right_panel_phase", - phase: RIGHT_PANEL_PHASES.EncryptionPanel, - refireParams: {member: user, verificationRequestPromise}, - }); - } else if (action === "legacy") { - const ManualDeviceKeyVerificationDialog = - sdk.getComponent("dialogs.ManualDeviceKeyVerificationDialog"); - Modal.createTrackedDialog("Legacy verify session", "legacy verify session", - ManualDeviceKeyVerificationDialog, - { - userId: user.userId, - device, - }, - ); - } - }, - }); - } + Modal.createTrackedDialog("Verification warning", "unverified session", UntrustedDeviceDialog, { + user, + device, + onFinished: async (action) => { + if (action === "sas") { + const verificationRequestPromise = cli.legacyDeviceVerification( + user.userId, + device.deviceId, + verificationMethods.SAS, + ); + dis.dispatch({ + action: "set_right_panel_phase", + phase: RIGHT_PANEL_PHASES.EncryptionPanel, + refireParams: {member: user, verificationRequestPromise}, + }); + } else if (action === "legacy") { + const ManualDeviceKeyVerificationDialog = + sdk.getComponent("dialogs.ManualDeviceKeyVerificationDialog"); + Modal.createTrackedDialog("Legacy verify session", "legacy verify session", + ManualDeviceKeyVerificationDialog, + { + userId: user.userId, + device, + }, + ); + } + }, + }); } export async function legacyVerifyUser(user) { diff --git a/test/utils/ShieldUtils-test.js b/test/utils/ShieldUtils-test.js index 5f676579fa..e4c0c671e3 100644 --- a/test/utils/ShieldUtils-test.js +++ b/test/utils/ShieldUtils-test.js @@ -11,7 +11,7 @@ function mkClient(selfTrust) { checkDeviceTrust: (userId, deviceId) => ({ isVerified: () => userId === "@self:localhost" ? selfTrust : userId[2] == "T", }), - getStoredDevicesForUser: async (userId) => ["DEVICE"], + getStoredDevicesForUser: (userId) => ["DEVICE"], }; } From 3703db237648e2840757b31cb63f3fab825b2dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 28 Apr 2020 19:45:41 +0000 Subject: [PATCH 096/237] Translated using Weblate (Estonian) Currently translated at 14.1% (323 of 2297 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 77b860dc2b..7264a6080c 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -324,5 +324,7 @@ "Mute": "Summuta", "Settings": "Seadistused", "You're not currently a member of any communities.": "Sa ei ole hetkel ainsamagi kogukonna liige.", - "Create a new community": "Loo uus kogukond" + "Create a new community": "Loo uus kogukond", + "Never send encrypted messages to unverified sessions from this session": "Ära iialgi saada sellest sessioonist krüptitud sõnumeid verifitseerimata sessioonidesse", + "Never send encrypted messages to unverified sessions in this room from this session": "Ära iialgi saada sellest sessioonist krüptitud sõnumeid verifitseerimata sessioonidesse selles jututoas" } From aa0bb917334c2b625ac9ae70bababff03c0f55b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 28 Apr 2020 20:39:03 +0000 Subject: [PATCH 097/237] Translated using Weblate (Estonian) Currently translated at 18.0% (413 of 2297 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 92 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 7264a6080c..b98abc5bd3 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -326,5 +326,95 @@ "You're not currently a member of any communities.": "Sa ei ole hetkel ainsamagi kogukonna liige.", "Create a new community": "Loo uus kogukond", "Never send encrypted messages to unverified sessions from this session": "Ära iialgi saada sellest sessioonist krüptitud sõnumeid verifitseerimata sessioonidesse", - "Never send encrypted messages to unverified sessions in this room from this session": "Ära iialgi saada sellest sessioonist krüptitud sõnumeid verifitseerimata sessioonidesse selles jututoas" + "Never send encrypted messages to unverified sessions in this room from this session": "Ära iialgi saada sellest sessioonist krüptitud sõnumeid verifitseerimata sessioonidesse selles jututoas", + "Sign In or Create Account": "Logi sisse või loo uus konto", + "Use your account or create a new one to continue.": "Jätkamaks kasuta oma kontot või loo uus konto.", + "Anyone": "Kõik kasutajad", + "Encryption": "Krüptimine", + "Once enabled, encryption cannot be disabled.": "Kui krüptimine on juba kasutusele võetud, siis ei saa seda enam eemaldada.", + "Encrypted": "Krüptitud", + "Who can access this room?": "Kes pääsevad ligi siia jututuppa?", + "Who can read history?": "Kes võib lugeda ajalugu?", + "Encrypted by an unverified session": "Krüptitud verifitseerimata sessiooni poolt", + "Messages in this room are end-to-end encrypted. Learn more & verify this user in their user profile.": "Sõnumid selles jututoas on läbivalt krüptitud. Uuri lisaks ja verifitseeri see kasutaja tema kasutajaprofiilis.", + "Encryption not enabled": "Krüptimine ei ole kasutusel", + "The encryption used by this room isn't supported.": "Selles jututoas kasutatud krüptimine ei ole toetatud.", + "Error decrypting audio": "Viga helivoo dekrüptimisel", + "React": "Reageeri", + "Reply": "Vasta", + "Edit": "Muuda", + "Message Actions": "Tegevused sõnumitega", + "Attachment": "Manus", + "Error decrypting attachment": "Viga manuse dekrüptimisel", + "Decrypt %(text)s": "Dekrüpti %(text)s", + "Download %(text)s": "Lae alla %(text)s", + "Invalid file%(extra)s": "Vigane fail %(extra)s", + "Error decrypting image": "Viga pildi dekrüptimisel", + "Show image": "Näita pilti", + "You have ignored this user, so their message is hidden. Show anyways.": "Sa oled seda kasutajat eiranud ja seega tema sõnum on peidetud. Näita seda ikkagi.", + "You verified %(name)s": "Sa verifitseerisid %(name)s", + "You cancelled verifying %(name)s": "Sa tühistasid %(name)s verifitseerimise", + "%(name)s cancelled verifying": "%(name)s tühistas verifitseerimise", + "You accepted": "Sa nõustusid", + "%(name)s accepted": "%(name)s nõustus", + "You declined": "Sa keeldusid", + "You cancelled": "Sa tühistasid", + "%(name)s declined": "%(name)s keeldus", + "%(name)s cancelled": "%(name)s tühistas", + "Accepting …": "Nõustun …", + "Declining …": "Keeldun …", + "%(name)s wants to verify": "%(name)s soovib verifitseerida", + "You sent a verification request": "Sa saatsid verifitseerimispalve", + "Error decrypting video": "Viga videovoo dekrüptimisel", + "Show all": "Näita kõiki", + "Reactions": "Reageerimised", + " reacted with %(content)s": " reageeris: %(content)s", + "reacted with %(shortName)s": "reageeris(id) %(shortName)s", + "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s muutis %(roomName)s jututoa avatari", + "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s eemaldas jututoa avatari.", + "%(senderDisplayName)s changed the room avatar to ": "%(senderDisplayName)s vahetas jututoa avatariks ", + "This room is a continuation of another conversation.": "See jututuba on järg varasemale vestlusele.", + "Click here to see older messages.": "Vanemate sõnumite nägemiseks klõpsi siia.", + "Copied!": "Kopeeritud!", + "Failed to copy": "Kopeerimine ebaõnnestus", + "Edited at %(date)s. Click to view edits.": "Muudetud %(date)s. Klõpsi et näha varasemaid versioone.", + "edited": "muudetud", + "Can't load this message": "Selle sõnumi laadimine ei õnnestu", + "Submit logs": "Saada rakenduse logid", + "Removed or unknown message type": "Kustutatud või tundmatu sõnumi tüüp", + "Message removed by %(userId)s": "Kasutaja %(userId)s poolt kustutatud sõnum", + "Message removed": "Sõnum on kustutatud", + "Invite to this community": "Kutsu selle kogukonna liikmeks", + "Something went wrong!": "Midagi läks nüüd valesti!", + "The visibility of '%(roomName)s' in %(groupId)s could not be updated.": "Jututoa %(roomName)s nähtavust %(groupId)s kogukonnas ei õnnestunud värskendada.", + "Visibility in Room List": "Nähtavus jututubade loendis", + "Visible to everyone": "Nähtav kõigile", + "Something went wrong when trying to get your communities.": "Sinu kogukondade laadimisel läks midagi nüüd viltu.", + "Please help improve Riot.im by sending anonymous usage data. This will use a cookie (please see our Cookie Policy).": "Palun aita Riot'it paremaks teha saates arendajatele anonüümset kasutusteavet. See eeldab küpsise kasutamist (palun vaata meie küpsiste kasutuse reegleid).", + "Please help improve Riot.im by sending anonymous usage data. This will use a cookie.": "Palun aita Riot'it paremaks teha saates anonüümset kasutusteavet. See eeldab küpsise kasutamist.", + "Yes, I want to help!": "Jah, ma soovin aidata!", + "You are not receiving desktop notifications": "Sa hetkel ei saa oma arvuti töölauakeskkonna teavitusi", + "Enable them now": "Võta need nüüd kasutusele", + "What's New": "Meie uudised", + "Update": "Uuenda", + "What's new?": "Mida on meil uut?", + "A new version of Riot is available.": "Uus Riot'i versioon on saadaval.", + "Your server": "Sinu server", + "Matrix": "Matrix", + "Add a new server": "Lisa uus server", + "Server name": "Serveri nimi", + "Add a new server...": "Lisa uus server...", + "Matrix ID": "Matrix'i kasutajatunnus", + "Matrix Room ID": "Matrix'i jututoa tunnus", + "email address": "e-posti aadress", + "That doesn't look like a valid email address": "See ei tundu olema e-posti aadressi moodi", + "You have entered an invalid address.": "Sa oled sisestanud vigase e-posti aadressi.", + "Try using one of the following valid address types: %(validTypesList)s.": "Proovi mõnda nendest sobilikest aadressitüüpidest: %(validTypesList)s.", + "Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)": "Blokeeri teiste matrixi koduserverite kasutajate liitumine selle jututoaga (seda ei saa hiljem enam muuta!)", + "Create Room": "Loo jututuba", + "Sign out": "Logi välja", + "Incompatible Database": "Mitteühilduv andmebaas", + "Continue With Encryption Disabled": "Jätka ilma krüptimiseta", + "Your unverified session '%(displayName)s' is requesting encryption keys.": "Sinu verifitseerimata sessioon '%(displayName)s' soovib saada krüptimisvõtmeid.", + "If you can't find the room you're looking for, ask for an invite or Create a new room.": "Kui sa ei leia otsitavat jututuba, siis palu sinna kutset või loo uus jututuba." } From aaf676705a9c56d86200b9bf66079f5efe22d510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 28 Apr 2020 21:44:38 +0000 Subject: [PATCH 098/237] Translated using Weblate (Estonian) Currently translated at 19.7% (453 of 2297 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index b98abc5bd3..6771510b98 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -416,5 +416,40 @@ "Incompatible Database": "Mitteühilduv andmebaas", "Continue With Encryption Disabled": "Jätka ilma krüptimiseta", "Your unverified session '%(displayName)s' is requesting encryption keys.": "Sinu verifitseerimata sessioon '%(displayName)s' soovib saada krüptimisvõtmeid.", - "If you can't find the room you're looking for, ask for an invite or Create a new room.": "Kui sa ei leia otsitavat jututuba, siis palu sinna kutset või loo uus jututuba." + "If you can't find the room you're looking for, ask for an invite or Create a new room.": "Kui sa ei leia otsitavat jututuba, siis palu sinna kutset või loo uus jututuba.", + "device id: ": "seadme tunnus: ", + "%(duration)ss": "%(duration)s sekund(it)", + "%(duration)sm": "%(duration)s minut(it)", + "%(duration)sh": "%(duration)s tund(i)", + "%(duration)sd": "%(duration)s päev(a)", + "Online for %(duration)s": "Võrgus %(duration)s", + "Idle for %(duration)s": "Jõude %(duration)s", + "Offline for %(duration)s": "Võrgust väljas %(duration)s", + "Unknown for %(duration)s": "Teadmata olek viimased %(duration)s", + "Idle": "Jõude", + "Offline": "Võrgust väljas", + "Unknown": "Teadmata olek", + "Seen by %(userName)s at %(dateTime)s": "Nähtud %(userName)s poolt %(dateTime)s", + "Seen by %(displayName)s (%(userName)s) at %(dateTime)s": "Nähtud %(displayName)s (%(userName)s) poolt %(dateTime)s", + "Replying": "Vastan", + "Room %(name)s": "Jututuba %(name)s", + "Unnamed room": "Nimeta jututuba", + "World readable": "Kogu maailmale avali", + "Guests can join": "Külalised võivad liituda", + "(~%(count)s results)|other": "(~%(count)s tulemust)", + "(~%(count)s results)|one": "(~%(count)s tulemus)", + "Join Room": "Liitu jututoaga", + "Forget room": "Unusta jututuba", + "Search": "Otsing", + "Share room": "Jaga jututuba", + "Community Invites": "Kutsed kogukonda", + "Invites": "Kutsed", + "Favourites": "Lemmikud", + "Low priority": "Vähetähtis", + "Historical": "Ammune", + "System Alerts": "Süsteemi teated", + "This room": "See jututuba", + "Joining room …": "Liitun jututoaga …", + "Loading …": "Laen …", + "Device ID": "Seadme tunnus" } From 921d178df0659eac93e2bdc1200aeb348026d812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 28 Apr 2020 22:01:35 +0000 Subject: [PATCH 099/237] Translated using Weblate (Estonian) Currently translated at 20.2% (465 of 2297 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 6771510b98..9e7e9a326f 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -451,5 +451,17 @@ "This room": "See jututuba", "Joining room …": "Liitun jututoaga …", "Loading …": "Laen …", - "Device ID": "Seadme tunnus" + "Device ID": "Seadme tunnus", + "e.g. %(exampleValue)s": "näiteks %(exampleValue)s", + "Could not find user in room": "Jututoast ei leidnud kasutajat", + "Show timestamps in 12 hour format (e.g. 2:30pm)": "Näita ajatempleid 12-tunnises vomingus (näiteks 2:30pl)", + "New published address (e.g. #alias:server)": "Uus avaldatud aadess (näiteks #alias:server)", + "New community ID (e.g. +foo:%(localDomain)s)": "Uus kogukonna tunnus (näiteks +midagi:%(localDomain)s)", + "e.g. my-room": "näiteks minu-jututuba", + "Can't find this server or its room list": "Ei leia seda serverit ega tema jututubade loendit", + "If you can't find someone, ask them for their username (e.g. @user:server.com) or share this room.": "Kui sa ei leia kedagi, siis küsi tema kasutajanime (näiteks @kasutaja:server.ee) või jaga seda jututuba.", + "Couldn't find a matching Matrix room": "Ei leidnud vastavat Matrix'i jututuba", + "Find a room…": "Leia jututuba…", + "Find a room… (e.g. %(exampleRoom)s)": "Otsi jututuba… (näiteks %(exampleRoom)s)", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Üritasin laadida teatud hetke selle jututoa ajajoonelt, kuid ei suutnud seda leida." } From 733919253545e2daa3e79554c6b6c19b77197d05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 28 Apr 2020 22:11:52 +0000 Subject: [PATCH 100/237] Translated using Weblate (Estonian) Currently translated at 20.3% (466 of 2297 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 9e7e9a326f..9cb5dbfb4b 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -463,5 +463,6 @@ "Couldn't find a matching Matrix room": "Ei leidnud vastavat Matrix'i jututuba", "Find a room…": "Leia jututuba…", "Find a room… (e.g. %(exampleRoom)s)": "Otsi jututuba… (näiteks %(exampleRoom)s)", - "Tried to load a specific point in this room's timeline, but was unable to find it.": "Üritasin laadida teatud hetke selle jututoa ajajoonelt, kuid ei suutnud seda leida." + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Üritasin laadida teatud hetke selle jututoa ajajoonelt, kuid ei suutnud seda leida.", + "Options": "Valikud" } From 4e98b5b4b60e150f4ed594b280a3fd733803ee40 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 28 Apr 2020 17:41:10 +0200 Subject: [PATCH 101/237] dont enable e2ee when inviting a 3pid --- src/components/views/dialogs/InviteDialog.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index a46fa0df07..a2a0eddd8e 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -577,10 +577,13 @@ export default class InviteDialog extends React.PureComponent { if (SettingsStore.getValue("feature_cross_signing")) { // Check whether all users have uploaded device keys before. // If so, enable encryption in the new room. - const client = MatrixClientPeg.get(); - const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds); - if (allHaveDeviceKeys) { - createRoomOptions.encryption = true; + const containsNonMatrixUsers = targets.some(t => !(t instanceof DirectoryMember)); + if (!containsNonMatrixUsers) { + const client = MatrixClientPeg.get(); + const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds); + if (allHaveDeviceKeys) { + createRoomOptions.encryption = true; + } } } From f06a69d8ccaac280c834baf02166154777588e18 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 28 Apr 2020 18:38:54 +0200 Subject: [PATCH 102/237] targets can also contain RoomMember, so take the positive case rather --- src/components/views/dialogs/InviteDialog.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index a2a0eddd8e..759228babd 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -577,8 +577,8 @@ export default class InviteDialog extends React.PureComponent { if (SettingsStore.getValue("feature_cross_signing")) { // Check whether all users have uploaded device keys before. // If so, enable encryption in the new room. - const containsNonMatrixUsers = targets.some(t => !(t instanceof DirectoryMember)); - if (!containsNonMatrixUsers) { + const has3PidMembers = targets.some(t => t instanceof ThreepidMember); + if (has3PidMembers) { const client = MatrixClientPeg.get(); const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds); if (allHaveDeviceKeys) { From 35487c9e0233dceb150445ba509b5005fd088f6f Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Wed, 29 Apr 2020 03:14:37 +0000 Subject: [PATCH 103/237] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2297 of 2297 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/zh_Hant/ --- src/i18n/strings/zh_Hant.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 164e5500b3..06b0bed44c 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -2404,5 +2404,7 @@ "or another cross-signing capable Matrix client": "或另一個有交叉簽章功能的 Matrix 客戶端", "Use Recovery Passphrase or Key": "使用復原通關密語或金鑰", "Where you’re logged in": "您登入的地方", - "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "在下方管理您工作階段的名稱與登入或在您的使用者檔案中驗證它們。" + "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "在下方管理您工作階段的名稱與登入或在您的使用者檔案中驗證它們。", + "Review where you’re logged in": "審閱您的登入位置", + "Verify your other sessions": "驗證您其他的工作階段" } From b11c8c3da02089ed1cbcebaa95e9377104eef413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20C?= Date: Wed, 29 Apr 2020 07:22:56 +0000 Subject: [PATCH 104/237] Translated using Weblate (French) Currently translated at 100.0% (2297 of 2297 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index dcec0da857..9b373cc364 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -2405,5 +2405,7 @@ "or another cross-signing capable Matrix client": "ou un autre client Matrix compatible avec la signature croisée", "Use Recovery Passphrase or Key": "Utiliser la phrase secrète ou la clé de récupération", "Where you’re logged in": "Où vous vous êtes connecté", - "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Gérez les noms et déconnectez-vous de vos sessions ci-dessous ou vérifiez-les dans votre profil utilisateur." + "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Gérez les noms et déconnectez-vous de vos sessions ci-dessous ou vérifiez-les dans votre profil utilisateur.", + "Review where you’re logged in": "Vérifier où vous vous êtes connecté", + "Verify your other sessions": "Vérifier vos autres sessions" } From 246c70c6a19927dc092c09ec8653162c3ad8ed43 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 28 Apr 2020 17:49:10 +0100 Subject: [PATCH 105/237] Fix internal link styling in Security Settings Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../settings/tabs/user/_SecurityUserSettingsTab.scss | 8 ++++++++ .../views/settings/tabs/user/SecurityUserSettingsTab.js | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss b/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss index b5a6693006..849979f444 100644 --- a/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss @@ -55,3 +55,11 @@ limitations under the License. .mx_SecurityUserSettingsTab_ignoredUser .mx_AccessibleButton { margin-right: 10px; } + +.mx_SecurityUserSettingsTab { + .mx_SettingsTab_section { + .mx_AccessibleButton_kind_link { + padding: 0; + } + } +} diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index 0eec59806a..42fa4a5c6f 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -90,7 +90,7 @@ export default class SecurityUserSettingsTab extends React.Component { }; _onGoToUserProfileClick = () => { - // close the settings dialog & let the default action run (ie. navigate to the link) + window.location.href = "#/user/" + MatrixClientPeg.get().getUserId(); this.props.closeSettingsFn(); } @@ -299,9 +299,9 @@ export default class SecurityUserSettingsTab extends React.Component { "Manage the names of and sign out of your sessions below or " + "verify them in your User Profile.", {}, { - a: sub => {sub}, + a: sub => + {sub} + , }, )} From dc7b588e02e9fb4a8fcc482522d0bc738c58e839 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 28 Apr 2020 17:57:32 +0100 Subject: [PATCH 106/237] fix font-size Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss b/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss index 849979f444..8700f8747d 100644 --- a/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss @@ -60,6 +60,7 @@ limitations under the License. .mx_SettingsTab_section { .mx_AccessibleButton_kind_link { padding: 0; + font-size: inherit; } } } From 41dece38a4d99bfc989ca09efe40b47f76e87400 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 29 Apr 2020 10:35:35 +0100 Subject: [PATCH 107/237] iterate copy Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/dialogs/InviteDialog.js | 13 ++++++++----- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index 7bc9364b52..516ac3183f 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -19,7 +19,7 @@ import PropTypes from 'prop-types'; import {_t} from "../../../languageHandler"; import * as sdk from "../../../index"; import {MatrixClientPeg} from "../../../MatrixClientPeg"; -import {makeUserPermalink} from "../../../utils/permalinks/Permalinks"; +import {makeRoomPermalink, makeUserPermalink} from "../../../utils/permalinks/Permalinks"; import DMRoomMap from "../../../utils/DMRoomMap"; import {RoomMember} from "matrix-js-sdk/src/matrix"; import SdkConfig from "../../../SdkConfig"; @@ -1082,11 +1082,14 @@ export default class InviteDialog extends React.PureComponent { } else { // KIND_INVITE title = _t("Invite to this room"); helpText = _t( - "Invite someone using their name, username (like ) or email address.", + "Invite someone using their name, username (like ), email address or share this room.", {}, - {userId: () => { - return {userId}; - }}, + { + userId: () => + {userId}, + a: (sub) => + {sub}, + }, ); buttonText = _t("Invite"); goButtonFn = this._inviteUsers; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 3b6e077aac..2a8a614d96 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1642,7 +1642,7 @@ "Recently Direct Messaged": "Recently Direct Messaged", "Start a conversation with someone using their name, username (like ) or email address.": "Start a conversation with someone using their name, username (like ) or email address.", "Go": "Go", - "Invite someone using their name, username (like ) or email address.": "Invite someone using their name, username (like ) or email address.", + "Invite someone using their name, username (like ), email address or share this room.": "Invite someone using their name, username (like ), email address or share this room.", "You added a new session '%(displayName)s', which is requesting encryption keys.": "You added a new session '%(displayName)s', which is requesting encryption keys.", "Your unverified session '%(displayName)s' is requesting encryption keys.": "Your unverified session '%(displayName)s' is requesting encryption keys.", "Start verification": "Start verification", From bb6d13781c47585c0ca3159fc95f8c1487a2d845 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 29 Apr 2020 11:40:04 +0200 Subject: [PATCH 108/237] enable encryption when NOT inviting 3pids --- src/components/views/dialogs/InviteDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index 759228babd..e48c6866bf 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -578,7 +578,7 @@ export default class InviteDialog extends React.PureComponent { // Check whether all users have uploaded device keys before. // If so, enable encryption in the new room. const has3PidMembers = targets.some(t => t instanceof ThreepidMember); - if (has3PidMembers) { + if (!has3PidMembers) { const client = MatrixClientPeg.get(); const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds); if (allHaveDeviceKeys) { From 6f25f2eaec7c7891df4d96f65d26dfae1a048285 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 10:44:51 +0100 Subject: [PATCH 109/237] Add the other toast component --- .../views/toasts/UnverifiedSessionToast.js | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/components/views/toasts/UnverifiedSessionToast.js diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js new file mode 100644 index 0000000000..3f2f29a493 --- /dev/null +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -0,0 +1,69 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +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 React from 'react'; +import PropTypes from 'prop-types'; +import { _t } from '../../../languageHandler'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; +import Modal from '../../../Modal'; +import DeviceListener from '../../../DeviceListener'; +import NewSessionReviewDialog from '../dialogs/NewSessionReviewDialog'; +import FormButton from '../elements/FormButton'; +import { replaceableComponent } from '../../../utils/replaceableComponent'; + +@replaceableComponent("views.toasts.UnverifiedSessionToast") +export default class UnverifiedSessionToast extends React.PureComponent { + static propTypes = { + deviceId: PropTypes.object, + } + + _onLaterClick = () => { + DeviceListener.sharedInstance().dismissUnverifiedSessions([this.props.deviceId]); + }; + + _onReviewClick = async () => { + const cli = MatrixClientPeg.get(); + Modal.createTrackedDialog('New Session Review', 'Starting dialog', NewSessionReviewDialog, { + userId: cli.getUserId(), + device: cli.getStoredDevice(cli.getUserId(), this.props.deviceId), + onFinished: (r) => { + if (!r) { + /* This'll come back false if the user clicks "this wasn't me" and saw a warning dialog */ + DeviceListener.sharedInstance().dismissUnverifiedSessions([this.props.deviceId]); + } + }, + }, null, /* priority = */ false, /* static = */ true); + }; + + render() { + const cli = MatrixClientPeg.get(); + const device = cli.getStoredDevice(cli.getUserId(), this.props.deviceId); + + return (
+
+ + {device.getDisplayName()} + + ({device.deviceId}) + +
+
+ + +
+
); + } +} From be13e86b0977dc474cba9488a9bb011be7eba4df Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 28 Apr 2020 17:41:10 +0200 Subject: [PATCH 110/237] dont enable e2ee when inviting a 3pid --- src/components/views/dialogs/InviteDialog.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index a46fa0df07..a2a0eddd8e 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -577,10 +577,13 @@ export default class InviteDialog extends React.PureComponent { if (SettingsStore.getValue("feature_cross_signing")) { // Check whether all users have uploaded device keys before. // If so, enable encryption in the new room. - const client = MatrixClientPeg.get(); - const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds); - if (allHaveDeviceKeys) { - createRoomOptions.encryption = true; + const containsNonMatrixUsers = targets.some(t => !(t instanceof DirectoryMember)); + if (!containsNonMatrixUsers) { + const client = MatrixClientPeg.get(); + const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds); + if (allHaveDeviceKeys) { + createRoomOptions.encryption = true; + } } } From a8205d21f1428bc58a7915270012110c9d90c28b Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 28 Apr 2020 18:38:54 +0200 Subject: [PATCH 111/237] targets can also contain RoomMember, so take the positive case rather --- src/components/views/dialogs/InviteDialog.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index a2a0eddd8e..759228babd 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -577,8 +577,8 @@ export default class InviteDialog extends React.PureComponent { if (SettingsStore.getValue("feature_cross_signing")) { // Check whether all users have uploaded device keys before. // If so, enable encryption in the new room. - const containsNonMatrixUsers = targets.some(t => !(t instanceof DirectoryMember)); - if (!containsNonMatrixUsers) { + const has3PidMembers = targets.some(t => t instanceof ThreepidMember); + if (has3PidMembers) { const client = MatrixClientPeg.get(); const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds); if (allHaveDeviceKeys) { From c10969f520fbb8b2bbbbac9c3c8c8713e125c11f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 29 Apr 2020 11:40:04 +0200 Subject: [PATCH 112/237] enable encryption when NOT inviting 3pids --- src/components/views/dialogs/InviteDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index 759228babd..e48c6866bf 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -578,7 +578,7 @@ export default class InviteDialog extends React.PureComponent { // Check whether all users have uploaded device keys before. // If so, enable encryption in the new room. const has3PidMembers = targets.some(t => t instanceof ThreepidMember); - if (has3PidMembers) { + if (!has3PidMembers) { const client = MatrixClientPeg.get(); const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds); if (allHaveDeviceKeys) { From 75c680715fef507b2294691038cecfd6e7558b61 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 10:53:36 +0100 Subject: [PATCH 113/237] s/unverified/new/ --- src/DeviceListener.js | 2 +- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index e3b833a340..6f278904eb 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -277,7 +277,7 @@ export default class DeviceListener { for (const deviceId of newUnverifiedDeviceIds) { ToastStore.sharedInstance().addOrReplaceToast({ key: toastKey(deviceId), - title: _t("Unverified login. Was this you?"), + title: _t("New login. Was this you?"), icon: "verification_warning", props: { deviceId }, component: sdk.getComponent("toasts.UnverifiedSessionToast"), diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8ffc35fda6..a94292b220 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -106,7 +106,7 @@ "Encryption upgrade available": "Encryption upgrade available", "Set up encryption": "Set up encryption", "Review where you’re logged in": "Review where you’re logged in", - "Unverified login. Was this you?": "Unverified login. Was this you?", + "New login. Was this you?": "New login. Was this you?", "Who would you like to add to this community?": "Who would you like to add to this community?", "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID", "Invite new community members": "Invite new community members", From 89a910c7180fb0baa682b5d4932acf237e5e2a8e Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 10:55:44 +0100 Subject: [PATCH 114/237] Clarify that we don't need tyo recheck --- src/DeviceListener.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 6f278904eb..516293b324 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -110,6 +110,9 @@ export default class DeviceListener { _onWillUpdateDevices = async (users) => { const myUserId = MatrixClientPeg.get().getUserId(); if (users.includes(myUserId)) this._ensureDeviceIdsAtStartPopulated(); + + // No need to do a recheck here: we just need to get a snapshot of our devices + // before we download asny new ones. } _onDevicesUpdated = (users) => { From 2e7ccf6e7a44f9854cd914c9306389828820c5e4 Mon Sep 17 00:00:00 2001 From: Jorik Schellekens Date: Wed, 29 Apr 2020 10:57:35 +0100 Subject: [PATCH 115/237] Fix pill vertical align --- res/css/views/elements/_RichText.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/css/views/elements/_RichText.scss b/res/css/views/elements/_RichText.scss index 453cf4c7f9..d60282695c 100644 --- a/res/css/views/elements/_RichText.scss +++ b/res/css/views/elements/_RichText.scss @@ -18,13 +18,14 @@ a.mx_Pill { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; - vertical-align: text-bottom; max-width: calc(100% - 1ch); } .mx_Pill { padding: $font-1px; padding-right: 0.4em; + vertical-align: text-top; + line-height: $font-17px; } /* More specific to override `.markdown-body a` color */ From 736857ffdf060b70d18795fcf9042c59088883db Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 27 Apr 2020 18:35:51 +0100 Subject: [PATCH 116/237] Fix set up encryption toast to use "set up" as action This changes the "set up encryption" toast to use "set up" as the primary action button, instead of "upgrade". Other toasts that do use text about upgrading will keep their primary action text of "upgrade" as before. Fixes https://github.com/vector-im/riot-web/issues/13231 --- src/components/views/toasts/SetupEncryptionToast.js | 1 + src/i18n/strings/en_EN.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/toasts/SetupEncryptionToast.js b/src/components/views/toasts/SetupEncryptionToast.js index 3c1f42b526..75fd55378c 100644 --- a/src/components/views/toasts/SetupEncryptionToast.js +++ b/src/components/views/toasts/SetupEncryptionToast.js @@ -90,6 +90,7 @@ export default class SetupEncryptionToast extends React.PureComponent { getSetupCaption() { switch (this.props.kind) { case 'set_up_encryption': + return _t('Set up'); case 'upgrade_encryption': case 'upgrade_ssss': return _t('Upgrade'); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index ab4ab2189c..505c56d23a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -558,6 +558,7 @@ "Verify yourself & others to keep your chats safe": "Verify yourself & others to keep your chats safe", "Other users may not trust it": "Other users may not trust it", "Update your secure storage": "Update your secure storage", + "Set up": "Set up", "Upgrade": "Upgrade", "Verify": "Verify", "Later": "Later", @@ -2225,7 +2226,6 @@ "Unable to create key backup": "Unable to create key backup", "Without setting up Secure Message Recovery, you'll lose your secure message history when you log out.": "Without setting up Secure Message Recovery, you'll lose your secure message history when you log out.", "If you don't want to set this up now, you can later in Settings.": "If you don't want to set this up now, you can later in Settings.", - "Set up": "Set up", "Don't ask again": "Don't ask again", "New Recovery Method": "New Recovery Method", "A new recovery passphrase and key for Secure Messages have been detected.": "A new recovery passphrase and key for Secure Messages have been detected.", From 126d81912bda87d63f6da8b46951167a8c701913 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 11:02:22 +0100 Subject: [PATCH 117/237] Remove await for some more getStoredDevice() calls --- src/components/views/rooms/MemberTile.js | 2 +- src/components/views/toasts/VerificationRequestToast.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.js index d830624f8a..1c609afcaa 100644 --- a/src/components/views/rooms/MemberTile.js +++ b/src/components/views/rooms/MemberTile.js @@ -129,7 +129,7 @@ export default createReactClass({ return; } - const devices = await cli.getStoredDevicesForUser(userId); + const devices = cli.getStoredDevicesForUser(userId); const anyDeviceUnverified = devices.some(device => { const { deviceId } = device; // For your own devices, we use the stricter check of cross-signing diff --git a/src/components/views/toasts/VerificationRequestToast.js b/src/components/views/toasts/VerificationRequestToast.js index 6ca582fbc7..6447e87627 100644 --- a/src/components/views/toasts/VerificationRequestToast.js +++ b/src/components/views/toasts/VerificationRequestToast.js @@ -51,7 +51,7 @@ export default class VerificationRequestToast extends React.PureComponent { if (request.isSelfVerification) { const cli = MatrixClientPeg.get(); - this.setState({device: await cli.getStoredDevice(cli.getUserId(), request.channel.deviceId)}); + this.setState({device: cli.getStoredDevice(cli.getUserId(), request.channel.deviceId)}); } } From 0026e4a0183d4f6e7e44dbebaa0ccfb2de011f3a Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 11:25:18 +0100 Subject: [PATCH 118/237] Comment typo Co-Authored-By: J. Ryan Stinnett --- src/DeviceListener.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 516293b324..c4beb6c01e 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -112,7 +112,7 @@ export default class DeviceListener { if (users.includes(myUserId)) this._ensureDeviceIdsAtStartPopulated(); // No need to do a recheck here: we just need to get a snapshot of our devices - // before we download asny new ones. + // before we download any new ones. } _onDevicesUpdated = (users) => { From e5d06b1acbe58c476748f76474547b13001e5f07 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 27 Apr 2020 18:33:54 +0100 Subject: [PATCH 119/237] Aggregate device verification toasts into one toast 'Review' now opens the only place we can verify our own devices: our user info. --- src/DeviceListener.js | 43 ++++++++----------- .../views/toasts/UnverifiedSessionToast.js | 29 +++---------- src/i18n/strings/en_EN.json | 3 +- 3 files changed, 27 insertions(+), 48 deletions(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 41f249b335..a7b259e179 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -20,12 +20,9 @@ import * as sdk from './index'; import { _t } from './languageHandler'; import ToastStore from './stores/ToastStore'; -function toastKey(deviceId) { - return 'unverified_session_' + deviceId; -} - const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000; const THIS_DEVICE_TOAST_KEY = 'setupencryption'; +const OTHER_DEVICES_TOAST_KEY = 'reviewsessions'; export default class DeviceListener { static sharedInstance() { @@ -34,8 +31,6 @@ export default class DeviceListener { } constructor() { - // set of device IDs we're currently showing toasts for - this._activeNagToasts = new Set(); // device IDs for which the user has dismissed the verify toast ('Later') this._dismissed = new Set(); // has the user dismissed any of the various nag toasts to setup encryption on this device? @@ -71,8 +66,11 @@ export default class DeviceListener { this._keyBackupFetchedAt = null; } - dismissVerification(deviceId) { - this._dismissed.add(deviceId); + async dismissVerifications() { + const cli = MatrixClientPeg.get(); + const devices = await cli.getStoredDevicesForUser(cli.getUserId()); + this._dismissed = new Set(devices.filter(d => d.deviceId !== cli.deviceId).map(d => d.deviceId)); + this._recheck(); } @@ -202,33 +200,28 @@ export default class DeviceListener { // as long as cross-signing isn't ready, // you can't see or dismiss any device toasts if (crossSigningReady) { - const newActiveToasts = new Set(); + const unverifiedDeviceIds = new Set(); const devices = await cli.getStoredDevicesForUser(cli.getUserId()); for (const device of devices) { if (device.deviceId == cli.deviceId) continue; const deviceTrust = await cli.checkDeviceTrust(cli.getUserId(), device.deviceId); - if (deviceTrust.isCrossSigningVerified() || this._dismissed.has(device.deviceId)) { - ToastStore.sharedInstance().dismissToast(toastKey(device.deviceId)); - } else { - this._activeNagToasts.add(device.deviceId); - ToastStore.sharedInstance().addOrReplaceToast({ - key: toastKey(device.deviceId), - title: _t("Unverified login. Was this you?"), - icon: "verification_warning", - props: { device }, - component: sdk.getComponent("toasts.UnverifiedSessionToast"), - }); - newActiveToasts.add(device.deviceId); + if (!deviceTrust.isCrossSigningVerified() && !this._dismissed.has(device.deviceId)) { + unverifiedDeviceIds.add(device.deviceId); } } - // clear any other outstanding toasts (eg. logged out devices) - for (const deviceId of this._activeNagToasts) { - if (!newActiveToasts.has(deviceId)) ToastStore.sharedInstance().dismissToast(toastKey(deviceId)); + if (unverifiedDeviceIds.size > 0) { + ToastStore.sharedInstance().addOrReplaceToast({ + key: OTHER_DEVICES_TOAST_KEY, + title: _t("Review where you’re logged in"), + icon: "verification_warning", + component: sdk.getComponent("toasts.UnverifiedSessionToast"), + }); + } else { + ToastStore.sharedInstance().dismissToast(OTHER_DEVICES_TOAST_KEY); } - this._activeNagToasts = newActiveToasts; } } } diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index cb0cadcdc8..587a54164d 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -18,6 +18,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import Modal from "../../../Modal"; +import dis from "../../../dispatcher"; import { MatrixClientPeg } from '../../../MatrixClientPeg'; import DeviceListener from '../../../DeviceListener'; import NewSessionReviewDialog from '../dialogs/NewSessionReviewDialog'; @@ -26,29 +27,17 @@ import { replaceableComponent } from '../../../utils/replaceableComponent'; @replaceableComponent("views.toasts.UnverifiedSessionToast") export default class UnverifiedSessionToast extends React.PureComponent { - static propTypes = { - toastKey: PropTypes.string.isRequired, - device: PropTypes.object.isRequired, - }; - _onLaterClick = () => { - const { device } = this.props; - DeviceListener.sharedInstance().dismissVerification(device.deviceId); + DeviceListener.sharedInstance().dismissVerifications(); }; _onReviewClick = async () => { - const { device } = this.props; + DeviceListener.sharedInstance().dismissVerifications(); - Modal.createTrackedDialog('New Session Review', 'Starting dialog', NewSessionReviewDialog, { + dis.dispatch({ + action: 'view_user_info', userId: MatrixClientPeg.get().getUserId(), - device, - onFinished: (r) => { - if (!r) { - /* This'll come back false if the user clicks "this wasn't me" and saw a warning dialog */ - this._onLaterClick(); - } - }, - }, null, /* priority = */ false, /* static = */ true); + }); }; render() { @@ -56,11 +45,7 @@ export default class UnverifiedSessionToast extends React.PureComponent { return (
- - {device.getDisplayName()} - - ({device.deviceId}) - + {_t("Verify your other sessions")}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 505c56d23a..576a70f9a6 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -105,7 +105,7 @@ "Verify this session": "Verify this session", "Encryption upgrade available": "Encryption upgrade available", "Set up encryption": "Set up encryption", - "Unverified login. Was this you?": "Unverified login. Was this you?", + "Review where you’re logged in": "Review where you’re logged in", "Who would you like to add to this community?": "Who would you like to add to this community?", "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID", "Invite new community members": "Invite new community members", @@ -562,6 +562,7 @@ "Upgrade": "Upgrade", "Verify": "Verify", "Later": "Later", + "Verify your other sessions": "Verify your other sessions", "Review": "Review", "From %(deviceName)s (%(deviceId)s)": "From %(deviceName)s (%(deviceId)s)", "Decline (%(counter)s)": "Decline (%(counter)s)", From 0edb80e5416e92d99af129b90ec7872dee37e8dc Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 27 Apr 2020 18:34:48 +0100 Subject: [PATCH 120/237] Make close button work from user info view Adds more hacks so that the close button does something vagauely plausible in all situations. --- src/components/structures/RightPanel.js | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index f5bdfdf40d..d5369b8492 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -26,6 +26,7 @@ import dis from '../../dispatcher'; import RateLimitedFunc from '../../ratelimitedfunc'; import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddressPicker'; import GroupStore from '../../stores/GroupStore'; +import RoomViewStore from '../../stores/RoomViewStore'; import SettingsStore from "../../settings/SettingsStore"; import {RIGHT_PANEL_PHASES, RIGHT_PANEL_PHASES_NO_ARGS} from "../../stores/RightPanelStorePhases"; import RightPanelStore from "../../stores/RightPanelStore"; @@ -221,10 +222,26 @@ export default class RightPanel extends React.Component { case RIGHT_PANEL_PHASES.EncryptionPanel: if (SettingsStore.getValue("feature_cross_signing")) { const onClose = () => { - dis.dispatch({ - action: "view_user", - member: this.state.phase === RIGHT_PANEL_PHASES.EncryptionPanel ? this.state.member : null, - }); + // XXX: There are three different ways of 'closing' this panel depending on what state + // things are in... this knows far more than it should do about the state of the rest + // of the app and is generally a bit silly. + if (this.props.user) { + // If we have a user prop then we're displaying a user from the 'user' page type + // in LoggedInView, so need to change the page type to close the panel (we switch + // to the home page which is not obviosuly the correct thing to do, but I'm not sure + // anything else is - we could hide the close button altogether?) + dis.dispatch({ + action: "view_home_page", + }); + } else { + // Otherwise we have got our user from RoomViewStore which means we're being shown + // within a room, so go back to the member panel if we were in the encryption panel, + // or the member list if we were in the member panel... phew. + dis.dispatch({ + action: "view_user", + member: this.state.phase === RIGHT_PANEL_PHASES.EncryptionPanel ? this.state.member : null, + }); + } }; panel = Date: Mon, 27 Apr 2020 20:31:14 +0100 Subject: [PATCH 121/237] Use the New Session review dialog for verifying our own devices --- src/components/views/right_panel/UserInfo.js | 34 +++++++---- src/verification.js | 63 +++++++++++--------- 2 files changed, 59 insertions(+), 38 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index b87617c9d4..d3e8e81ebe 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -191,17 +191,29 @@ function DeviceItem({userId, device}) { device.getDisplayName(); let trustedLabel = null; if (userTrust.isVerified()) trustedLabel = isVerified ? _t("Trusted") : _t("Not trusted"); - return ( - -
-
{deviceName}
-
{trustedLabel}
- - ); + + + if (isVerified) { + return ( +
+
+
{deviceName}
+
{trustedLabel}
+
+ ); + } else { + return ( + +
+
{deviceName}
+
{trustedLabel}
+ + ); + } } function DevicesSection({devices, userId, loading}) { diff --git a/src/verification.js b/src/verification.js index ca839940e5..ed56b0e7ef 100644 --- a/src/verification.js +++ b/src/verification.js @@ -23,6 +23,7 @@ import {RIGHT_PANEL_PHASES} from "./stores/RightPanelStorePhases"; import {findDMForUser} from './createRoom'; import {accessSecretStorage} from './CrossSigningManager'; import SettingsStore from './settings/SettingsStore'; +import NewSessionReviewDialog from './components/views/dialogs/NewSessionReviewDialog'; import {verificationMethods} from 'matrix-js-sdk/src/crypto'; async function enable4SIfNeeded() { @@ -68,33 +69,41 @@ export async function verifyDevice(user, device) { return; } } - Modal.createTrackedDialog("Verification warning", "unverified session", UntrustedDeviceDialog, { - user, - device, - onFinished: async (action) => { - if (action === "sas") { - const verificationRequestPromise = cli.legacyDeviceVerification( - user.userId, - device.deviceId, - verificationMethods.SAS, - ); - dis.dispatch({ - action: "set_right_panel_phase", - phase: RIGHT_PANEL_PHASES.EncryptionPanel, - refireParams: {member: user, verificationRequestPromise}, - }); - } else if (action === "legacy") { - const ManualDeviceKeyVerificationDialog = sdk.getComponent("dialogs.ManualDeviceKeyVerificationDialog"); - Modal.createTrackedDialog("Legacy verify session", "legacy verify session", - ManualDeviceKeyVerificationDialog, - { - userId: user.userId, - device, - }, - ); - } - }, - }); + + if (user.userId === cli.getUserId()) { + Modal.createTrackedDialog('New Session Review', 'Starting dialog', NewSessionReviewDialog, { + userId: user.userId, + device, + }); + } else { + Modal.createTrackedDialog("Verification warning", "unverified session", UntrustedDeviceDialog, { + user, + device, + onFinished: async (action) => { + if (action === "sas") { + const verificationRequestPromise = cli.legacyDeviceVerification( + user.userId, + device.deviceId, + verificationMethods.SAS, + ); + dis.dispatch({ + action: "set_right_panel_phase", + phase: RIGHT_PANEL_PHASES.EncryptionPanel, + refireParams: {member: user, verificationRequestPromise}, + }); + } else if (action === "legacy") { + const ManualDeviceKeyVerificationDialog = sdk.getComponent("dialogs.ManualDeviceKeyVerificationDialog"); + Modal.createTrackedDialog("Legacy verify session", "legacy verify session", + ManualDeviceKeyVerificationDialog, + { + userId: user.userId, + device, + }, + ); + } + }, + }); + } } export async function legacyVerifyUser(user) { From 3e6a623270c1c7ccd7d0513bb97f50569fd995a3 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 27 Apr 2020 20:35:39 +0100 Subject: [PATCH 122/237] Lint --- src/components/structures/RightPanel.js | 4 ++-- src/components/views/toasts/UnverifiedSessionToast.js | 5 ----- src/verification.js | 3 ++- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index d5369b8492..3fec5aa25f 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -26,7 +26,6 @@ import dis from '../../dispatcher'; import RateLimitedFunc from '../../ratelimitedfunc'; import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddressPicker'; import GroupStore from '../../stores/GroupStore'; -import RoomViewStore from '../../stores/RoomViewStore'; import SettingsStore from "../../settings/SettingsStore"; import {RIGHT_PANEL_PHASES, RIGHT_PANEL_PHASES_NO_ARGS} from "../../stores/RightPanelStorePhases"; import RightPanelStore from "../../stores/RightPanelStore"; @@ -239,7 +238,8 @@ export default class RightPanel extends React.Component { // or the member list if we were in the member panel... phew. dis.dispatch({ action: "view_user", - member: this.state.phase === RIGHT_PANEL_PHASES.EncryptionPanel ? this.state.member : null, + member: this.state.phase === RIGHT_PANEL_PHASES.EncryptionPanel ? + this.state.member : null, }); } }; diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index 587a54164d..886e3c4c20 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -15,13 +15,10 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; -import Modal from "../../../Modal"; import dis from "../../../dispatcher"; import { MatrixClientPeg } from '../../../MatrixClientPeg'; import DeviceListener from '../../../DeviceListener'; -import NewSessionReviewDialog from '../dialogs/NewSessionReviewDialog'; import FormButton from '../elements/FormButton'; import { replaceableComponent } from '../../../utils/replaceableComponent'; @@ -41,8 +38,6 @@ export default class UnverifiedSessionToast extends React.PureComponent { }; render() { - const { device } = this.props; - return (
{_t("Verify your other sessions")} diff --git a/src/verification.js b/src/verification.js index ed56b0e7ef..630da01091 100644 --- a/src/verification.js +++ b/src/verification.js @@ -92,7 +92,8 @@ export async function verifyDevice(user, device) { refireParams: {member: user, verificationRequestPromise}, }); } else if (action === "legacy") { - const ManualDeviceKeyVerificationDialog = sdk.getComponent("dialogs.ManualDeviceKeyVerificationDialog"); + const ManualDeviceKeyVerificationDialog = + sdk.getComponent("dialogs.ManualDeviceKeyVerificationDialog"); Modal.createTrackedDialog("Legacy verify session", "legacy verify session", ManualDeviceKeyVerificationDialog, { From 7da2850a2e5e01744926df8026548a60d291dd7a Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 28 Apr 2020 09:42:39 +0100 Subject: [PATCH 123/237] No need for a set here - bool is fine --- src/DeviceListener.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index a7b259e179..ad2553ca3c 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -200,7 +200,7 @@ export default class DeviceListener { // as long as cross-signing isn't ready, // you can't see or dismiss any device toasts if (crossSigningReady) { - const unverifiedDeviceIds = new Set(); + const haveUnverifiedDevices = false; const devices = await cli.getStoredDevicesForUser(cli.getUserId()); for (const device of devices) { @@ -208,11 +208,12 @@ export default class DeviceListener { const deviceTrust = await cli.checkDeviceTrust(cli.getUserId(), device.deviceId); if (!deviceTrust.isCrossSigningVerified() && !this._dismissed.has(device.deviceId)) { - unverifiedDeviceIds.add(device.deviceId); + haveUnverifiedDevices = true; + break; } } - if (unverifiedDeviceIds.size > 0) { + if (haveUnverifiedDevices) { ToastStore.sharedInstance().addOrReplaceToast({ key: OTHER_DEVICES_TOAST_KEY, title: _t("Review where you’re logged in"), From f7c881a462e5fe3ff35a18b403f7dfe0f9039b65 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 28 Apr 2020 09:43:24 +0100 Subject: [PATCH 124/237] No need for this if statement now --- src/components/views/right_panel/UserInfo.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index d3e8e81ebe..cafbf05a23 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -181,9 +181,7 @@ function DeviceItem({userId, device}) { }); const onDeviceClick = () => { - if (!isVerified) { - verifyDevice(cli.getUser(userId), device); - } + verifyDevice(cli.getUser(userId), device); }; const deviceName = device.ambiguous ? From 81d91721d85e93f1152442d7609aa02d3bbe25f2 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 28 Apr 2020 09:49:03 +0100 Subject: [PATCH 125/237] Consts are constant --- src/DeviceListener.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index ad2553ca3c..1b451310b9 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -200,7 +200,7 @@ export default class DeviceListener { // as long as cross-signing isn't ready, // you can't see or dismiss any device toasts if (crossSigningReady) { - const haveUnverifiedDevices = false; + let haveUnverifiedDevices = false; const devices = await cli.getStoredDevicesForUser(cli.getUserId()); for (const device of devices) { From 0f9d3f555e59bf6bc90efbfc26f9c02e7d6bdee3 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 28 Apr 2020 18:35:16 +0100 Subject: [PATCH 126/237] Separate toasts for existing & new device verification Separate device verification toasts into ones for devices that were there when the app loaded and a separate toast for each device that has appeared since. Reverts part of https://github.com/matrix-org/matrix-react-sdk/pull/4506 (clicking a device from your own UserInfo now triggers the legacy verification flow again). Fixes https://github.com/vector-im/riot-web/issues/13422 Fixes https://github.com/vector-im/riot-web/issues/13418 --- src/DeviceListener.js | 104 +++++++++++++++--- src/SlashCommands.tsx | 2 +- .../views/right_panel/EncryptionPanel.js | 6 +- src/components/views/right_panel/UserInfo.js | 4 +- src/components/views/rooms/MemberInfo.js | 11 +- ...oast.js => BulkUnverifiedSessionsToast.js} | 13 ++- src/i18n/strings/en_EN.json | 7 +- src/utils/ShieldUtils.ts | 4 +- src/verification.js | 64 +++++------ test/utils/ShieldUtils-test.js | 2 +- 10 files changed, 138 insertions(+), 79 deletions(-) rename src/components/views/toasts/{UnverifiedSessionToast.js => BulkUnverifiedSessionsToast.js} (78%) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 1b451310b9..e3b833a340 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -24,6 +24,10 @@ const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000; const THIS_DEVICE_TOAST_KEY = 'setupencryption'; const OTHER_DEVICES_TOAST_KEY = 'reviewsessions'; +function toastKey(deviceId) { + return "unverified_session_" + deviceId; +} + export default class DeviceListener { static sharedInstance() { if (!global.mx_DeviceListener) global.mx_DeviceListener = new DeviceListener(); @@ -39,9 +43,18 @@ export default class DeviceListener { // cache of the key backup info this._keyBackupInfo = null; this._keyBackupFetchedAt = null; + + // We keep a list of our own device IDs so we can batch ones that were already + // there the last time the app launched into a single toast, but display new + // ones in their own toasts. + this._ourDeviceIdsAtStart = null; + + // The set of device IDs we're currently displaying toasts for + this._displayingToastsForDeviceIds = new Set(); } start() { + MatrixClientPeg.get().on('crypto.willUpdateDevices', this._onWillUpdateDevices); MatrixClientPeg.get().on('crypto.devicesUpdated', this._onDevicesUpdated); MatrixClientPeg.get().on('deviceVerificationChanged', this._onDeviceVerificationChanged); MatrixClientPeg.get().on('userTrustStatusChanged', this._onUserTrustStatusChanged); @@ -53,6 +66,7 @@ export default class DeviceListener { stop() { if (MatrixClientPeg.get()) { + MatrixClientPeg.get().removeListener('crypto.willUpdateDevices', this._onWillUpdateDevices); MatrixClientPeg.get().removeListener('crypto.devicesUpdated', this._onDevicesUpdated); MatrixClientPeg.get().removeListener('deviceVerificationChanged', this._onDeviceVerificationChanged); MatrixClientPeg.get().removeListener('userTrustStatusChanged', this._onUserTrustStatusChanged); @@ -66,10 +80,15 @@ export default class DeviceListener { this._keyBackupFetchedAt = null; } - async dismissVerifications() { - const cli = MatrixClientPeg.get(); - const devices = await cli.getStoredDevicesForUser(cli.getUserId()); - this._dismissed = new Set(devices.filter(d => d.deviceId !== cli.deviceId).map(d => d.deviceId)); + /** + * Dismiss notifications about our own unverified devices + * + * @param {String[]} deviceIds List of device IDs to dismiss notifications for + */ + async dismissUnverifiedSessions(deviceIds) { + for (const d of deviceIds) { + this._dismissed.add(d); + } this._recheck(); } @@ -79,6 +98,20 @@ export default class DeviceListener { this._recheck(); } + _ensureDeviceIdsAtStartPopulated() { + if (this._ourDeviceIdsAtStart === null) { + const cli = MatrixClientPeg.get(); + this._ourDeviceIdsAtStart = new Set( + cli.getStoredDevicesForUser(cli.getUserId()).map(d => d.deviceId), + ); + } + } + + _onWillUpdateDevices = async (users) => { + const myUserId = MatrixClientPeg.get().getUserId(); + if (users.includes(myUserId)) this._ensureDeviceIdsAtStartPopulated(); + } + _onDevicesUpdated = (users) => { if (!users.includes(MatrixClientPeg.get().getUserId())) return; this._recheck(); @@ -143,6 +176,8 @@ export default class DeviceListener { const crossSigningReady = await cli.isCrossSigningReady(); + this._ensureDeviceIdsAtStartPopulated(); + if (this._dismissedThisDeviceToast) { ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY); } else { @@ -197,32 +232,65 @@ export default class DeviceListener { } } + // Unverified devices that were there last time the app ran + // (technically could just be a boolean: we don't actually + // need to remember the device IDs, but for the sake of + // symmetry...). + const oldUnverifiedDeviceIds = new Set(); + // Unverified devices that have appeared since then + const newUnverifiedDeviceIds = new Set(); + // as long as cross-signing isn't ready, // you can't see or dismiss any device toasts if (crossSigningReady) { - let haveUnverifiedDevices = false; - - const devices = await cli.getStoredDevicesForUser(cli.getUserId()); + const devices = cli.getStoredDevicesForUser(cli.getUserId()); for (const device of devices) { if (device.deviceId == cli.deviceId) continue; const deviceTrust = await cli.checkDeviceTrust(cli.getUserId(), device.deviceId); if (!deviceTrust.isCrossSigningVerified() && !this._dismissed.has(device.deviceId)) { - haveUnverifiedDevices = true; - break; + if (this._ourDeviceIdsAtStart.has(device.deviceId)) { + oldUnverifiedDeviceIds.add(device.deviceId); + } else { + newUnverifiedDeviceIds.add(device.deviceId); + } } } + } - if (haveUnverifiedDevices) { - ToastStore.sharedInstance().addOrReplaceToast({ - key: OTHER_DEVICES_TOAST_KEY, - title: _t("Review where you’re logged in"), - icon: "verification_warning", - component: sdk.getComponent("toasts.UnverifiedSessionToast"), - }); - } else { - ToastStore.sharedInstance().dismissToast(OTHER_DEVICES_TOAST_KEY); + // Display or hide the batch toast for old unverified sessions + if (oldUnverifiedDeviceIds.size > 0) { + ToastStore.sharedInstance().addOrReplaceToast({ + key: OTHER_DEVICES_TOAST_KEY, + title: _t("Review where you’re logged in"), + icon: "verification_warning", + props: { + deviceIds: oldUnverifiedDeviceIds, + }, + component: sdk.getComponent("toasts.BulkUnverifiedSessionsToast"), + }); + } else { + ToastStore.sharedInstance().dismissToast(OTHER_DEVICES_TOAST_KEY); + } + + // Show toasts for new unverified devices if they aren't already there + for (const deviceId of newUnverifiedDeviceIds) { + ToastStore.sharedInstance().addOrReplaceToast({ + key: toastKey(deviceId), + title: _t("Unverified login. Was this you?"), + icon: "verification_warning", + props: { deviceId }, + component: sdk.getComponent("toasts.UnverifiedSessionToast"), + }); + } + + // ...and hide any we don't need any more + for (const deviceId of this._displayingToastsForDeviceIds) { + if (!newUnverifiedDeviceIds.has(deviceId)) { + ToastStore.sharedInstance().dismissToast(toastKey(deviceId)); } } + + this._displayingToastsForDeviceIds = newUnverifiedDeviceIds; } } diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index 71815dde8c..1a299db4c7 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -799,7 +799,7 @@ export const Commands = [ const fingerprint = matches[3]; return success((async () => { - const device = await cli.getStoredDevice(userId, deviceId); + const device = cli.getStoredDevice(userId, deviceId); if (!device) { throw new Error(_t('Unknown (user, session) pair:') + ` (${userId}, ${deviceId})`); } diff --git a/src/components/views/right_panel/EncryptionPanel.js b/src/components/views/right_panel/EncryptionPanel.js index 476b6cace9..bc580c767b 100644 --- a/src/components/views/right_panel/EncryptionPanel.js +++ b/src/components/views/right_panel/EncryptionPanel.js @@ -22,7 +22,6 @@ import VerificationPanel from "./VerificationPanel"; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import {ensureDMExists} from "../../../createRoom"; import {useEventEmitter} from "../../../hooks/useEventEmitter"; -import {useAsyncMemo} from "../../../hooks/useAsyncMemo"; import Modal from "../../../Modal"; import {PHASE_REQUESTED, PHASE_UNSENT} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; import * as sdk from "../../../index"; @@ -47,10 +46,7 @@ const EncryptionPanel = (props) => { }, [verificationRequest]); const deviceId = request && request.channel.deviceId; - const device = useAsyncMemo(() => { - const cli = MatrixClientPeg.get(); - return cli.getStoredDevice(cli.getUserId(), deviceId); - }, [deviceId]); + const device = MatrixClientPeg.get().getStoredDevice(MatrixClientPeg.get().getUserId(), deviceId); useEffect(() => { async function awaitPromise() { diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index cafbf05a23..61f5a8161a 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -1110,7 +1110,7 @@ export const useDevices = (userId) => { async function _downloadDeviceList() { try { await cli.downloadKeys([userId], true); - const devices = await cli.getStoredDevicesForUser(userId); + const devices = cli.getStoredDevicesForUser(userId); if (cancelled) { // we got cancelled - presumably a different user now @@ -1135,7 +1135,7 @@ export const useDevices = (userId) => { useEffect(() => { let cancel = false; const updateDevices = async () => { - const newDevices = await cli.getStoredDevicesForUser(userId); + const newDevices = cli.getStoredDevicesForUser(userId); if (cancel) return; setDevices(newDevices); }; diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 9fdd2abedf..be3e8cf971 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -160,13 +160,10 @@ export default createReactClass({ // no need to re-download the whole thing; just update our copy of // the list. - // Promise.resolve to handle transition from static result to promise; can be removed - // in future - Promise.resolve(this.context.getStoredDevicesForUser(userId)).then((devices) => { - this.setState({ - devices: devices, - e2eStatus: this._getE2EStatus(devices), - }); + const devices = this.context.getStoredDevicesForUser(userId); + this.setState({ + devices: devices, + e2eStatus: this._getE2EStatus(devices), }); } }, diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/BulkUnverifiedSessionsToast.js similarity index 78% rename from src/components/views/toasts/UnverifiedSessionToast.js rename to src/components/views/toasts/BulkUnverifiedSessionsToast.js index 886e3c4c20..b16dc87f21 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/BulkUnverifiedSessionsToast.js @@ -15,6 +15,7 @@ limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import dis from "../../../dispatcher"; import { MatrixClientPeg } from '../../../MatrixClientPeg'; @@ -22,14 +23,18 @@ import DeviceListener from '../../../DeviceListener'; import FormButton from '../elements/FormButton'; import { replaceableComponent } from '../../../utils/replaceableComponent'; -@replaceableComponent("views.toasts.UnverifiedSessionToast") -export default class UnverifiedSessionToast extends React.PureComponent { +@replaceableComponent("views.toasts.BulkUnverifiedSessionsToast") +export default class BulkUnverifiedSessionsToast extends React.PureComponent { + static propTypes = { + deviceIds: PropTypes.array, + } + _onLaterClick = () => { - DeviceListener.sharedInstance().dismissVerifications(); + DeviceListener.sharedInstance().dismissUnverifiedSessions(this.props.deviceIds); }; _onReviewClick = async () => { - DeviceListener.sharedInstance().dismissVerifications(); + DeviceListener.sharedInstance().dismissUnverifiedSessions(this.props.deviceIds); dis.dispatch({ action: 'view_user_info', diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 576a70f9a6..cde8e47569 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -106,6 +106,7 @@ "Encryption upgrade available": "Encryption upgrade available", "Set up encryption": "Set up encryption", "Review where you’re logged in": "Review where you’re logged in", + "Unverified login. Was this you?": "Unverified login. Was this you?", "Who would you like to add to this community?": "Who would you like to add to this community?", "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID", "Invite new community members": "Invite new community members", @@ -555,15 +556,15 @@ "Headphones": "Headphones", "Folder": "Folder", "Pin": "Pin", + "Verify your other sessions": "Verify your other sessions", + "Later": "Later", + "Review": "Review", "Verify yourself & others to keep your chats safe": "Verify yourself & others to keep your chats safe", "Other users may not trust it": "Other users may not trust it", "Update your secure storage": "Update your secure storage", "Set up": "Set up", "Upgrade": "Upgrade", "Verify": "Verify", - "Later": "Later", - "Verify your other sessions": "Verify your other sessions", - "Review": "Review", "From %(deviceName)s (%(deviceId)s)": "From %(deviceName)s (%(deviceId)s)", "Decline (%(counter)s)": "Decline (%(counter)s)", "Accept to continue:": "Accept to continue:", diff --git a/src/utils/ShieldUtils.ts b/src/utils/ShieldUtils.ts index 9bf6fe2327..adaa961a00 100644 --- a/src/utils/ShieldUtils.ts +++ b/src/utils/ShieldUtils.ts @@ -7,7 +7,7 @@ interface Client { isCrossSigningVerified: () => boolean wasCrossSigningVerified: () => boolean }; - getStoredDevicesForUser: (userId: string) => Promise<[{ deviceId: string }]>; + getStoredDevicesForUser: (userId: string) => [{ deviceId: string }]; checkDeviceTrust: (userId: string, deviceId: string) => { isVerified: () => boolean } @@ -45,7 +45,7 @@ export async function shieldStatusForRoom(client: Client, room: Room): Promise { return !client.checkDeviceTrust(userId, deviceId).isVerified(); }); diff --git a/src/verification.js b/src/verification.js index 630da01091..d7287552dd 100644 --- a/src/verification.js +++ b/src/verification.js @@ -23,7 +23,6 @@ import {RIGHT_PANEL_PHASES} from "./stores/RightPanelStorePhases"; import {findDMForUser} from './createRoom'; import {accessSecretStorage} from './CrossSigningManager'; import SettingsStore from './settings/SettingsStore'; -import NewSessionReviewDialog from './components/views/dialogs/NewSessionReviewDialog'; import {verificationMethods} from 'matrix-js-sdk/src/crypto'; async function enable4SIfNeeded() { @@ -70,41 +69,34 @@ export async function verifyDevice(user, device) { } } - if (user.userId === cli.getUserId()) { - Modal.createTrackedDialog('New Session Review', 'Starting dialog', NewSessionReviewDialog, { - userId: user.userId, - device, - }); - } else { - Modal.createTrackedDialog("Verification warning", "unverified session", UntrustedDeviceDialog, { - user, - device, - onFinished: async (action) => { - if (action === "sas") { - const verificationRequestPromise = cli.legacyDeviceVerification( - user.userId, - device.deviceId, - verificationMethods.SAS, - ); - dis.dispatch({ - action: "set_right_panel_phase", - phase: RIGHT_PANEL_PHASES.EncryptionPanel, - refireParams: {member: user, verificationRequestPromise}, - }); - } else if (action === "legacy") { - const ManualDeviceKeyVerificationDialog = - sdk.getComponent("dialogs.ManualDeviceKeyVerificationDialog"); - Modal.createTrackedDialog("Legacy verify session", "legacy verify session", - ManualDeviceKeyVerificationDialog, - { - userId: user.userId, - device, - }, - ); - } - }, - }); - } + Modal.createTrackedDialog("Verification warning", "unverified session", UntrustedDeviceDialog, { + user, + device, + onFinished: async (action) => { + if (action === "sas") { + const verificationRequestPromise = cli.legacyDeviceVerification( + user.userId, + device.deviceId, + verificationMethods.SAS, + ); + dis.dispatch({ + action: "set_right_panel_phase", + phase: RIGHT_PANEL_PHASES.EncryptionPanel, + refireParams: {member: user, verificationRequestPromise}, + }); + } else if (action === "legacy") { + const ManualDeviceKeyVerificationDialog = + sdk.getComponent("dialogs.ManualDeviceKeyVerificationDialog"); + Modal.createTrackedDialog("Legacy verify session", "legacy verify session", + ManualDeviceKeyVerificationDialog, + { + userId: user.userId, + device, + }, + ); + } + }, + }); } export async function legacyVerifyUser(user) { diff --git a/test/utils/ShieldUtils-test.js b/test/utils/ShieldUtils-test.js index 5f676579fa..e4c0c671e3 100644 --- a/test/utils/ShieldUtils-test.js +++ b/test/utils/ShieldUtils-test.js @@ -11,7 +11,7 @@ function mkClient(selfTrust) { checkDeviceTrust: (userId, deviceId) => ({ isVerified: () => userId === "@self:localhost" ? selfTrust : userId[2] == "T", }), - getStoredDevicesForUser: async (userId) => ["DEVICE"], + getStoredDevicesForUser: (userId) => ["DEVICE"], }; } From 9cbc40730583d6c78caabe97afc18b9a2a36eef5 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 10:44:51 +0100 Subject: [PATCH 127/237] Add the other toast component --- .../views/toasts/UnverifiedSessionToast.js | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/components/views/toasts/UnverifiedSessionToast.js diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js new file mode 100644 index 0000000000..3f2f29a493 --- /dev/null +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -0,0 +1,69 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +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 React from 'react'; +import PropTypes from 'prop-types'; +import { _t } from '../../../languageHandler'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; +import Modal from '../../../Modal'; +import DeviceListener from '../../../DeviceListener'; +import NewSessionReviewDialog from '../dialogs/NewSessionReviewDialog'; +import FormButton from '../elements/FormButton'; +import { replaceableComponent } from '../../../utils/replaceableComponent'; + +@replaceableComponent("views.toasts.UnverifiedSessionToast") +export default class UnverifiedSessionToast extends React.PureComponent { + static propTypes = { + deviceId: PropTypes.object, + } + + _onLaterClick = () => { + DeviceListener.sharedInstance().dismissUnverifiedSessions([this.props.deviceId]); + }; + + _onReviewClick = async () => { + const cli = MatrixClientPeg.get(); + Modal.createTrackedDialog('New Session Review', 'Starting dialog', NewSessionReviewDialog, { + userId: cli.getUserId(), + device: cli.getStoredDevice(cli.getUserId(), this.props.deviceId), + onFinished: (r) => { + if (!r) { + /* This'll come back false if the user clicks "this wasn't me" and saw a warning dialog */ + DeviceListener.sharedInstance().dismissUnverifiedSessions([this.props.deviceId]); + } + }, + }, null, /* priority = */ false, /* static = */ true); + }; + + render() { + const cli = MatrixClientPeg.get(); + const device = cli.getStoredDevice(cli.getUserId(), this.props.deviceId); + + return (
+
+ + {device.getDisplayName()} + + ({device.deviceId}) + +
+
+ + +
+
); + } +} From e67faa15ca241a6db8fbf9a58dab216797477e54 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 10:53:36 +0100 Subject: [PATCH 128/237] s/unverified/new/ --- src/DeviceListener.js | 2 +- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index e3b833a340..6f278904eb 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -277,7 +277,7 @@ export default class DeviceListener { for (const deviceId of newUnverifiedDeviceIds) { ToastStore.sharedInstance().addOrReplaceToast({ key: toastKey(deviceId), - title: _t("Unverified login. Was this you?"), + title: _t("New login. Was this you?"), icon: "verification_warning", props: { deviceId }, component: sdk.getComponent("toasts.UnverifiedSessionToast"), diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index cde8e47569..5129839cbd 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -106,7 +106,7 @@ "Encryption upgrade available": "Encryption upgrade available", "Set up encryption": "Set up encryption", "Review where you’re logged in": "Review where you’re logged in", - "Unverified login. Was this you?": "Unverified login. Was this you?", + "New login. Was this you?": "New login. Was this you?", "Who would you like to add to this community?": "Who would you like to add to this community?", "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID", "Invite new community members": "Invite new community members", From 8aa5d762db3db55147e3cb005fce138e109ba789 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 10:55:44 +0100 Subject: [PATCH 129/237] Clarify that we don't need tyo recheck --- src/DeviceListener.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 6f278904eb..516293b324 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -110,6 +110,9 @@ export default class DeviceListener { _onWillUpdateDevices = async (users) => { const myUserId = MatrixClientPeg.get().getUserId(); if (users.includes(myUserId)) this._ensureDeviceIdsAtStartPopulated(); + + // No need to do a recheck here: we just need to get a snapshot of our devices + // before we download asny new ones. } _onDevicesUpdated = (users) => { From 690e934b27adc4a245a7611bacfce3af91652631 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 11:02:22 +0100 Subject: [PATCH 130/237] Remove await for some more getStoredDevice() calls --- src/components/views/rooms/MemberTile.js | 2 +- src/components/views/toasts/VerificationRequestToast.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.js index d830624f8a..1c609afcaa 100644 --- a/src/components/views/rooms/MemberTile.js +++ b/src/components/views/rooms/MemberTile.js @@ -129,7 +129,7 @@ export default createReactClass({ return; } - const devices = await cli.getStoredDevicesForUser(userId); + const devices = cli.getStoredDevicesForUser(userId); const anyDeviceUnverified = devices.some(device => { const { deviceId } = device; // For your own devices, we use the stricter check of cross-signing diff --git a/src/components/views/toasts/VerificationRequestToast.js b/src/components/views/toasts/VerificationRequestToast.js index 6ca582fbc7..6447e87627 100644 --- a/src/components/views/toasts/VerificationRequestToast.js +++ b/src/components/views/toasts/VerificationRequestToast.js @@ -51,7 +51,7 @@ export default class VerificationRequestToast extends React.PureComponent { if (request.isSelfVerification) { const cli = MatrixClientPeg.get(); - this.setState({device: await cli.getStoredDevice(cli.getUserId(), request.channel.deviceId)}); + this.setState({device: cli.getStoredDevice(cli.getUserId(), request.channel.deviceId)}); } } From 5eb86c0d6a92b901c87b485c4cb0f15d7d76b274 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 11:25:18 +0100 Subject: [PATCH 131/237] Comment typo Co-Authored-By: J. Ryan Stinnett --- src/DeviceListener.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 516293b324..c4beb6c01e 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -112,7 +112,7 @@ export default class DeviceListener { if (users.includes(myUserId)) this._ensureDeviceIdsAtStartPopulated(); // No need to do a recheck here: we just need to get a snapshot of our devices - // before we download asny new ones. + // before we download any new ones. } _onDevicesUpdated = (users) => { From 62c73146dc35337cd739cff7bd14b24526a5eec2 Mon Sep 17 00:00:00 2001 From: Zoe Date: Wed, 29 Apr 2020 14:14:39 +0100 Subject: [PATCH 132/237] copy changes --- .../dialogs/keybackup/RestoreKeyBackupDialog.js | 12 ++++++------ src/i18n/strings/en_EN.json | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index 92d23f9e65..da67fb9777 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -283,15 +283,15 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { let content; let title; if (this.state.loading) { - title = _t("Loading..."); + title = _t("Restoring keys from backup"); let details; if (this.state.progress.stage === "fetch") { - details = _t("Downloading from server..."); + details = _t("Fetching keys from server..."); } else if (this.state.progress.stage === "load_keys") { const { total, successes, failures } = this.state.progress; - details = _t("Loaded %(completed)s of %(total)s", { total, completed: successes + failures }); + details = _t("%(completed)s of %(total)s keys restored", { total, completed: successes + failures }); } else if (this.state.progress.stage === "prefetch") { - details = _t("Requesting from server..."); + details = _t("Fetching keys from server..."); } content =
{details}
@@ -328,7 +328,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { content = _t("No backup found!"); } else if (this.state.recoverInfo) { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); - title = _t("Backup restored"); + title = _t("Keys restored"); let failedToDecrypt; if (this.state.recoverInfo.total > this.state.recoverInfo.imported) { failedToDecrypt =

{_t( @@ -337,7 +337,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { )}

; } content =
-

{_t("Restored %(sessionCount)s session keys", {sessionCount: this.state.recoverInfo.imported})}

+

{_t("Successfully restored %(sessionCount)s keys", {sessionCount: this.state.recoverInfo.imported})}

{failedToDecrypt} set up new recovery options.": "If you've forgotten your recovery key you can .", - "Downloading from server...": "Downloading from server...", - "Loaded %(completed)s of %(total)s": "Loaded %(completed)s of %(total)s", - "Requesting from server...": "Requesting from server...", + "Restoring keys from backup": "Restoring keys from backup", + "Fetching keys from server...": "Fetching keys from server...", + "%(completed)s of %(total)s keys restored": "%(completed)s of %(total)s keys restored", "Unable to load backup status": "Unable to load backup status", "Recovery key mismatch": "Recovery key mismatch", "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.": "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.", @@ -1801,9 +1801,9 @@ "Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.": "Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.", "Unable to restore backup": "Unable to restore backup", "No backup found!": "No backup found!", - "Backup restored": "Backup restored", + "Keys restored": "Keys restored", "Failed to decrypt %(failedCount)s sessions!": "Failed to decrypt %(failedCount)s sessions!", - "Restored %(sessionCount)s session keys": "Restored %(sessionCount)s session keys", + "Successfully restored %(sessionCount)s keys": "Successfully restored %(sessionCount)s keys", "Warning: you should only set up key backup from a trusted computer.": "Warning: you should only set up key backup from a trusted computer.", "Access your secure message history and set up secure messaging by entering your recovery passphrase.": "Access your secure message history and set up secure messaging by entering your recovery passphrase.", "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options": "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options", From 326d5674688494cf5de59a7f0264b16d4d56bd68 Mon Sep 17 00:00:00 2001 From: Zoe Date: Wed, 29 Apr 2020 14:29:36 +0100 Subject: [PATCH 133/237] Fixed the dialog height --- .../keybackup/_RestoreKeyBackupDialog.scss | 6 +++++ .../keybackup/RestoreKeyBackupDialog.js | 26 +++++++++---------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss index 9cba8e0da9..d74224c94d 100644 --- a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss +++ b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss @@ -32,3 +32,9 @@ limitations under the License. padding: 10px; } +.mx_RestoreKeyBackupDialog_content { + display: flex; + flex-direction: column; + justify-content: space-between; + min-height: 110px; /* Empirically measured */ +} diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index da67fb9777..9829f7af8e 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -293,10 +293,10 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { } else if (this.state.progress.stage === "prefetch") { details = _t("Fetching keys from server..."); } - content =
+ content = <>
{details}
-
; + ; } else if (this.state.loadError) { title = _t("Error"); content = _t("Unable to load backup status"); @@ -304,20 +304,20 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { if (this.state.restoreError.errcode === MatrixClient.RESTORE_BACKUP_ERROR_BAD_KEY) { if (this.state.restoreType === RESTORE_TYPE_RECOVERYKEY) { title = _t("Recovery key mismatch"); - content =
+ content = <>

{_t( "Backup could not be decrypted with this recovery key: " + "please verify that you entered the correct recovery key.", )}

-
; + ; } else { title = _t("Incorrect recovery passphrase"); - content =
+ content = <>

{_t( "Backup could not be decrypted with this recovery passphrase: " + "please verify that you entered the correct recovery passphrase.", )}

-
; + ; } } else { title = _t("Error"); @@ -336,7 +336,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {failedCount: this.state.recoverInfo.total - this.state.recoverInfo.imported}, )}

; } - content =
+ content = <>

{_t("Successfully restored %(sessionCount)s keys", {sessionCount: this.state.recoverInfo.imported})}

{failedToDecrypt} -
; + ; } else if (backupHasPassphrase && !this.state.forceRecoveryKey) { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); title = _t("Enter recovery passphrase"); - content =
+ content = <>

{_t( "Warning: you should only set up key backup " + "from a trusted computer.", {}, @@ -394,7 +394,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} -

; + ; } else { title = _t("Enter recovery key"); const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); @@ -413,7 +413,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
; } - content =
+ content = <>

{_t( "Warning: You should only set up key backup " + "from a trusted computer.", {}, @@ -450,7 +450,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} -

; + ; } return ( @@ -458,7 +458,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { onFinished={this.props.onFinished} title={title} > -
+
{content}
From 1291a63b98013f04c137bf53861a3d104a35a1da Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 14:49:30 +0100 Subject: [PATCH 134/237] Make new device toasts appear above review toasts ...but below incoming verification toasts, which means we now need to actually handle priority insertion correctly. Oh well. Fixes https://github.com/vector-im/riot-web/issues/13442 --- src/DeviceListener.js | 1 + src/stores/ToastStore.js | 14 ++++++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index c4beb6c01e..84c6b1d230 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -267,6 +267,7 @@ export default class DeviceListener { key: OTHER_DEVICES_TOAST_KEY, title: _t("Review where you’re logged in"), icon: "verification_warning", + priority: ToastStore.PRIORITY_LOW, props: { deviceIds: oldUnverifiedDeviceIds, }, diff --git a/src/stores/ToastStore.js b/src/stores/ToastStore.js index f17d13bf9e..ad185e42db 100644 --- a/src/stores/ToastStore.js +++ b/src/stores/ToastStore.js @@ -20,8 +20,9 @@ import EventEmitter from 'events'; * Holds the active toasts */ export default class ToastStore extends EventEmitter { - static PRIORITY_REALTIME = 1; - static PRIORITY_DEFAULT = 0; + static PRIORITY_REALTIME = 0; + static PRIORITY_DEFAULT = 1; + static PRIORITY_LOW = 2; static sharedInstance() { if (!global.mx_ToastStore) global.mx_ToastStore = new ToastStore(); @@ -43,12 +44,9 @@ export default class ToastStore extends EventEmitter { const oldIndex = this._toasts.findIndex(t => t.key === newToast.key); if (oldIndex === -1) { - // we only have two priorities so just push realtime ones onto the front - if (newToast.priority) { - this._toasts.unshift(newToast); - } else { - this._toasts.push(newToast); - } + let newIndex = this._toasts.length; + while (newIndex > 0 && this._toasts[newIndex - 1].priority > newToast.priority) --newIndex; + this._toasts.splice(newIndex, 0, newToast); } else { this._toasts[oldIndex] = newToast; } From 325e1f9c4e75cce5ce39f5db71a19bcc5f921939 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 15:10:23 +0100 Subject: [PATCH 135/237] Add jsdoc explaining ordering behaviour --- src/stores/ToastStore.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/stores/ToastStore.js b/src/stores/ToastStore.js index ad185e42db..8901736739 100644 --- a/src/stores/ToastStore.js +++ b/src/stores/ToastStore.js @@ -39,6 +39,15 @@ export default class ToastStore extends EventEmitter { this._toasts = []; } + /** + * Add or replace a toast + * If a toast with the same toastKey already exists, the given toast will replace it + * Toasts are always added underneath any toasts of the same priority, so existing + * toasts stay at the top unless a higher priority one arrives (better to not change the + * toast unless necessary). + * + * @param {boject} newToast The new toast + */ addOrReplaceToast(newToast) { if (newToast.priority === undefined) newToast.priority = ToastStore.PRIORITY_DEFAULT; From 465442c31ea0478550dfcb5d9e5877baa83616ea Mon Sep 17 00:00:00 2001 From: Zoe Date: Wed, 29 Apr 2020 15:10:23 +0100 Subject: [PATCH 136/237] fragments and i18n don't play nice together --- .../keybackup/_RestoreKeyBackupDialog.scss | 2 +- .../keybackup/RestoreKeyBackupDialog.js | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss index d74224c94d..5689d84bc5 100644 --- a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss +++ b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss @@ -32,7 +32,7 @@ limitations under the License. padding: 10px; } -.mx_RestoreKeyBackupDialog_content { +.mx_RestoreKeyBackupDialog_content > div { display: flex; flex-direction: column; justify-content: space-between; diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index 9829f7af8e..f1008dfcb0 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -293,10 +293,10 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { } else if (this.state.progress.stage === "prefetch") { details = _t("Fetching keys from server..."); } - content = <> + content =
{details}
- ; +
; } else if (this.state.loadError) { title = _t("Error"); content = _t("Unable to load backup status"); @@ -304,20 +304,20 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { if (this.state.restoreError.errcode === MatrixClient.RESTORE_BACKUP_ERROR_BAD_KEY) { if (this.state.restoreType === RESTORE_TYPE_RECOVERYKEY) { title = _t("Recovery key mismatch"); - content = <> + content =

{_t( "Backup could not be decrypted with this recovery key: " + "please verify that you entered the correct recovery key.", )}

- ; +
; } else { title = _t("Incorrect recovery passphrase"); - content = <> + content =

{_t( "Backup could not be decrypted with this recovery passphrase: " + "please verify that you entered the correct recovery passphrase.", )}

- ; +
; } } else { title = _t("Error"); @@ -336,7 +336,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {failedCount: this.state.recoverInfo.total - this.state.recoverInfo.imported}, )}

; } - content = <> + content =

{_t("Successfully restored %(sessionCount)s keys", {sessionCount: this.state.recoverInfo.imported})}

{failedToDecrypt} - ; +
; } else if (backupHasPassphrase && !this.state.forceRecoveryKey) { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); title = _t("Enter recovery passphrase"); - content = <> + content =

{_t( "Warning: you should only set up key backup " + "from a trusted computer.", {}, @@ -394,7 +394,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} - ; +

; } else { title = _t("Enter recovery key"); const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); @@ -413,7 +413,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
; } - content = <> + content =

{_t( "Warning: You should only set up key backup " + "from a trusted computer.", {}, @@ -450,7 +450,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} - ; +

; } return ( From e9214f7d1364224dc1030b48fb1b3bcaaf29c175 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 14:49:30 +0100 Subject: [PATCH 137/237] Make new device toasts appear above review toasts ...but below incoming verification toasts, which means we now need to actually handle priority insertion correctly. Oh well. Fixes https://github.com/vector-im/riot-web/issues/13442 --- src/DeviceListener.js | 1 + src/stores/ToastStore.js | 14 ++++++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index c4beb6c01e..84c6b1d230 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -267,6 +267,7 @@ export default class DeviceListener { key: OTHER_DEVICES_TOAST_KEY, title: _t("Review where you’re logged in"), icon: "verification_warning", + priority: ToastStore.PRIORITY_LOW, props: { deviceIds: oldUnverifiedDeviceIds, }, diff --git a/src/stores/ToastStore.js b/src/stores/ToastStore.js index f17d13bf9e..ad185e42db 100644 --- a/src/stores/ToastStore.js +++ b/src/stores/ToastStore.js @@ -20,8 +20,9 @@ import EventEmitter from 'events'; * Holds the active toasts */ export default class ToastStore extends EventEmitter { - static PRIORITY_REALTIME = 1; - static PRIORITY_DEFAULT = 0; + static PRIORITY_REALTIME = 0; + static PRIORITY_DEFAULT = 1; + static PRIORITY_LOW = 2; static sharedInstance() { if (!global.mx_ToastStore) global.mx_ToastStore = new ToastStore(); @@ -43,12 +44,9 @@ export default class ToastStore extends EventEmitter { const oldIndex = this._toasts.findIndex(t => t.key === newToast.key); if (oldIndex === -1) { - // we only have two priorities so just push realtime ones onto the front - if (newToast.priority) { - this._toasts.unshift(newToast); - } else { - this._toasts.push(newToast); - } + let newIndex = this._toasts.length; + while (newIndex > 0 && this._toasts[newIndex - 1].priority > newToast.priority) --newIndex; + this._toasts.splice(newIndex, 0, newToast); } else { this._toasts[oldIndex] = newToast; } From 58c0cfe315752c512835703142cd6e705b1e8f45 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 15:10:23 +0100 Subject: [PATCH 138/237] Add jsdoc explaining ordering behaviour --- src/stores/ToastStore.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/stores/ToastStore.js b/src/stores/ToastStore.js index ad185e42db..8901736739 100644 --- a/src/stores/ToastStore.js +++ b/src/stores/ToastStore.js @@ -39,6 +39,15 @@ export default class ToastStore extends EventEmitter { this._toasts = []; } + /** + * Add or replace a toast + * If a toast with the same toastKey already exists, the given toast will replace it + * Toasts are always added underneath any toasts of the same priority, so existing + * toasts stay at the top unless a higher priority one arrives (better to not change the + * toast unless necessary). + * + * @param {boject} newToast The new toast + */ addOrReplaceToast(newToast) { if (newToast.priority === undefined) newToast.priority = ToastStore.PRIORITY_DEFAULT; From 65bdaa20b02487a494aee7a85e0681550a5bc84d Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 29 Apr 2020 15:19:09 +0100 Subject: [PATCH 139/237] Allow resetting storage from the access dialog This adds a path to reset secret storage from the access dialog instead of throwing an error. Fixes https://github.com/vector-im/riot-web/issues/13436 --- .../views/dialogs/secretstorage/AccessSecretStorageDialog.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js index 7d7edffcbf..e2ceadfbb9 100644 --- a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js +++ b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js @@ -21,6 +21,7 @@ import * as sdk from '../../../../index'; import {MatrixClientPeg} from '../../../../MatrixClientPeg'; import { _t } from '../../../../languageHandler'; +import { accessSecretStorage } from '../../../../CrossSigningManager'; /* * Access Secure Secret Storage by requesting the user's passphrase. @@ -55,8 +56,9 @@ export default class AccessSecretStorageDialog extends React.PureComponent { } _onResetRecoveryClick = () => { + // Re-enter the access flow, but resetting storage this time around. this.props.onFinished(false); - throw new Error("Resetting secret storage unimplemented"); + accessSecretStorage(() => {}, /* forceReset = */ true); } _onRecoveryKeyChange = (e) => { From 5b2ff19f5929da9b93813764553e5f980b4241ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 29 Apr 2020 13:59:03 +0000 Subject: [PATCH 140/237] Translated using Weblate (Estonian) Currently translated at 20.5% (471 of 2298 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 9cb5dbfb4b..4c061b6b43 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -464,5 +464,10 @@ "Find a room…": "Leia jututuba…", "Find a room… (e.g. %(exampleRoom)s)": "Otsi jututuba… (näiteks %(exampleRoom)s)", "Tried to load a specific point in this room's timeline, but was unable to find it.": "Üritasin laadida teatud hetke selle jututoa ajajoonelt, kuid ei suutnud seda leida.", - "Options": "Valikud" + "Options": "Valikud", + "Searches DuckDuckGo for results": "Otsi DuckDuckGo abil", + "Securely cache encrypted messages locally for them to appear in search results, using ": "Turvaliselt puhverda krüptitud sõnumeid kohalikus arvutis selleks, et nad oleks otsitavad kasutades ", + "this room": "see jututuba", + "Quote": "Tsiteeri", + "This Room": "See jututuba" } From 9ac4fa92fd18c802906a401afb0862f6abf20d56 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 15:31:41 +0100 Subject: [PATCH 141/237] Update (bulk) unverified device toast copy Fixes https://github.com/vector-im/riot-web/issues/13444 --- .../views/toasts/BulkUnverifiedSessionsToast.js | 2 +- src/components/views/toasts/UnverifiedSessionToast.js | 8 ++------ src/i18n/strings/en_EN.json | 3 ++- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/components/views/toasts/BulkUnverifiedSessionsToast.js b/src/components/views/toasts/BulkUnverifiedSessionsToast.js index b16dc87f21..e0be846a2b 100644 --- a/src/components/views/toasts/BulkUnverifiedSessionsToast.js +++ b/src/components/views/toasts/BulkUnverifiedSessionsToast.js @@ -45,7 +45,7 @@ export default class BulkUnverifiedSessionsToast extends React.PureComponent { render() { return (
- {_t("Verify your other sessions")} + {_t("Unverified sessions currently have access to your account & messages")}
diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index 3f2f29a493..a4454ca6d5 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -54,15 +54,11 @@ export default class UnverifiedSessionToast extends React.PureComponent { return (
- - {device.getDisplayName()} - - ({device.deviceId}) - + {_t("Verify the identity of the new login accessing your account & messages")}
- +
); } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 7484f7f635..6ab0c886d4 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -559,7 +559,7 @@ "Headphones": "Headphones", "Folder": "Folder", "Pin": "Pin", - "Verify your other sessions": "Verify your other sessions", + "Unverified sessions currently have access to your account & messages": "Unverified sessions currently have access to your account & messages", "Later": "Later", "Review": "Review", "Verify yourself & others to keep your chats safe": "Verify yourself & others to keep your chats safe", @@ -568,6 +568,7 @@ "Set up": "Set up", "Upgrade": "Upgrade", "Verify": "Verify", + "Verify the identity of the new login accessing your account & messages": "Verify the identity of the new login accessing your account & messages", "From %(deviceName)s (%(deviceId)s)": "From %(deviceName)s (%(deviceId)s)", "Decline (%(counter)s)": "Decline (%(counter)s)", "Accept to continue:": "Accept to continue:", From 691066af947ea3a0643503acc03225b529753163 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 15:31:41 +0100 Subject: [PATCH 142/237] Update (bulk) unverified device toast copy Fixes https://github.com/vector-im/riot-web/issues/13444 --- .../views/toasts/BulkUnverifiedSessionsToast.js | 2 +- src/components/views/toasts/UnverifiedSessionToast.js | 8 ++------ src/i18n/strings/en_EN.json | 3 ++- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/components/views/toasts/BulkUnverifiedSessionsToast.js b/src/components/views/toasts/BulkUnverifiedSessionsToast.js index b16dc87f21..e0be846a2b 100644 --- a/src/components/views/toasts/BulkUnverifiedSessionsToast.js +++ b/src/components/views/toasts/BulkUnverifiedSessionsToast.js @@ -45,7 +45,7 @@ export default class BulkUnverifiedSessionsToast extends React.PureComponent { render() { return (
- {_t("Verify your other sessions")} + {_t("Unverified sessions currently have access to your account & messages")}
diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index 3f2f29a493..a4454ca6d5 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -54,15 +54,11 @@ export default class UnverifiedSessionToast extends React.PureComponent { return (
- - {device.getDisplayName()} - - ({device.deviceId}) - + {_t("Verify the identity of the new login accessing your account & messages")}
- +
); } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5129839cbd..dc83ca8964 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -556,7 +556,7 @@ "Headphones": "Headphones", "Folder": "Folder", "Pin": "Pin", - "Verify your other sessions": "Verify your other sessions", + "Unverified sessions currently have access to your account & messages": "Unverified sessions currently have access to your account & messages", "Later": "Later", "Review": "Review", "Verify yourself & others to keep your chats safe": "Verify yourself & others to keep your chats safe", @@ -565,6 +565,7 @@ "Set up": "Set up", "Upgrade": "Upgrade", "Verify": "Verify", + "Verify the identity of the new login accessing your account & messages": "Verify the identity of the new login accessing your account & messages", "From %(deviceName)s (%(deviceId)s)": "From %(deviceName)s (%(deviceId)s)", "Decline (%(counter)s)": "Decline (%(counter)s)", "Accept to continue:": "Accept to continue:", From 283a15c0b30e40f965452ce5f4c60349d2391187 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 15:54:32 +0100 Subject: [PATCH 143/237] Lint --- src/components/views/toasts/UnverifiedSessionToast.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index a4454ca6d5..032d457c3a 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -49,9 +49,6 @@ export default class UnverifiedSessionToast extends React.PureComponent { }; render() { - const cli = MatrixClientPeg.get(); - const device = cli.getStoredDevice(cli.getUserId(), this.props.deviceId); - return (
{_t("Verify the identity of the new login accessing your account & messages")} From d691386ef06f6e73d9a42f51bc461cf343c1ae3f Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 15:54:32 +0100 Subject: [PATCH 144/237] Lint --- src/components/views/toasts/UnverifiedSessionToast.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index a4454ca6d5..032d457c3a 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -49,9 +49,6 @@ export default class UnverifiedSessionToast extends React.PureComponent { }; render() { - const cli = MatrixClientPeg.get(); - const device = cli.getStoredDevice(cli.getUserId(), this.props.deviceId); - return (
{_t("Verify the identity of the new login accessing your account & messages")} From a70efea69e9c1bda8419e24770f70aa8cc057a8f Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 17:16:04 +0100 Subject: [PATCH 145/237] Treat sessions that are there when we log in as old Use the bulk 'review' toast for sessions that existed at the time of login, rather than considering them all to be new. Also cheeky unrelated proptypes fix. Fixes https://github.com/vector-im/riot-web/issues/13443 Requires https://github.com/matrix-org/matrix-js-sdk/pull/1360 --- src/DeviceListener.js | 13 ++++++++++--- .../views/toasts/UnverifiedSessionToast.js | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 84c6b1d230..c37d702fd6 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -107,7 +107,12 @@ export default class DeviceListener { } } - _onWillUpdateDevices = async (users) => { + _onWillUpdateDevices = async (users, initialFetch) => { + // We we didn't know about *any* devices before (ie. it's fresh login), + // then they are all pre-existing devices, so ignore this and set the + // devicesAtStart list to the devices that we see after the fetch. + if (initialFetch) return; + const myUserId = MatrixClientPeg.get().getUserId(); if (users.includes(myUserId)) this._ensureDeviceIdsAtStartPopulated(); @@ -179,8 +184,6 @@ export default class DeviceListener { const crossSigningReady = await cli.isCrossSigningReady(); - this._ensureDeviceIdsAtStartPopulated(); - if (this._dismissedThisDeviceToast) { ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY); } else { @@ -235,6 +238,10 @@ export default class DeviceListener { } } + // This needs to be done after awaiting on downloadKeys() above, so + // we make sure we get the devices after the fetch is done. + this._ensureDeviceIdsAtStartPopulated(); + // Unverified devices that were there last time the app ran // (technically could just be a boolean: we don't actually // need to remember the device IDs, but for the sake of diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index 032d457c3a..f3e35e247c 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -27,7 +27,7 @@ import { replaceableComponent } from '../../../utils/replaceableComponent'; @replaceableComponent("views.toasts.UnverifiedSessionToast") export default class UnverifiedSessionToast extends React.PureComponent { static propTypes = { - deviceId: PropTypes.object, + deviceId: PropTypes.string, } _onLaterClick = () => { From 13d0e26ec4f6d00d23c965ba17374b6f7233517c Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 17:28:45 +0100 Subject: [PATCH 146/237] Reduce maximum width of toasts & allow multiple lines --- res/css/structures/_ToastContainer.scss | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/res/css/structures/_ToastContainer.scss b/res/css/structures/_ToastContainer.scss index af595aaeee..64496b2cc0 100644 --- a/res/css/structures/_ToastContainer.scss +++ b/res/css/structures/_ToastContainer.scss @@ -91,10 +91,7 @@ limitations under the License. } .mx_Toast_description { - max-width: 400px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; + max-width: 272px; margin: 4px 0 11px 0; font-size: $font-12px; } From c41af152ac70c3ee97fb9e7c6911de2e1e86be9e Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 17:33:18 +0100 Subject: [PATCH 147/237] Comment typo Co-Authored-By: J. Ryan Stinnett --- src/DeviceListener.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index c37d702fd6..28f8e8b115 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -108,7 +108,7 @@ export default class DeviceListener { } _onWillUpdateDevices = async (users, initialFetch) => { - // We we didn't know about *any* devices before (ie. it's fresh login), + // If we didn't know about *any* devices before (ie. it's fresh login), // then they are all pre-existing devices, so ignore this and set the // devicesAtStart list to the devices that we see after the fetch. if (initialFetch) return; From 34d6eb591fbe2eeca527a46a23d067a13ec696f7 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 17:38:32 +0100 Subject: [PATCH 148/237] Put overflows back --- res/css/structures/_ToastContainer.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/css/structures/_ToastContainer.scss b/res/css/structures/_ToastContainer.scss index 64496b2cc0..6ec4a0d152 100644 --- a/res/css/structures/_ToastContainer.scss +++ b/res/css/structures/_ToastContainer.scss @@ -92,6 +92,8 @@ limitations under the License. .mx_Toast_description { max-width: 272px; + overflow: hidden; + text-overflow: ellipsis; margin: 4px 0 11px 0; font-size: $font-12px; } From eebcf748e18f5dc4e08cc1343a5a50f384edfdb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 29 Apr 2020 15:50:21 +0000 Subject: [PATCH 149/237] Translated using Weblate (Estonian) Currently translated at 22.2% (510 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 41 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 4c061b6b43..603354166a 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -469,5 +469,44 @@ "Securely cache encrypted messages locally for them to appear in search results, using ": "Turvaliselt puhverda krüptitud sõnumeid kohalikus arvutis selleks, et nad oleks otsitavad kasutades ", "this room": "see jututuba", "Quote": "Tsiteeri", - "This Room": "See jututuba" + "This Room": "See jututuba", + "Sun": "Pühapäev", + "Mon": "Esmaspäev", + "Tue": "Teisipäev", + "Wed": "Kolmapäev", + "Thu": "Neljapäev", + "Fri": "Reede", + "Sat": "Laupäev", + "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s, %(monthName)s %(day)s %(time)s", + "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(day)s %(monthName)s %(fullYear)s", + "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s, %(day)s %(monthName)s %(fullYear)s %(time)s", + "Encryption upgrade available": "Krüptimise uuendus on saadaval", + "Set up encryption": "Seadista krüptimine", + "Review where you’re logged in": "Vaata üle, kust sa oled Matrix'i võrku loginud", + "New login. Was this you?": "Uus sisselogimine. Kas see olid sina?", + "Who would you like to add to this community?": "Kas sa sooviksid seda lisada kogukonda?", + "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Hoiatus: kõik kogukonda lisatud kasutajad on nähtavad kõigile, kes teavad kogukonna tunnust", + "Name or Matrix ID": "Nimi või Matrix'i tunnus", + "Invite to Community": "Kutsu kogukonda", + "Room name or alias": "Jututoa nimi või alias", + "Add to community": "Lisa kogukonda", + "Failed to invite the following users to %(groupId)s:": "Järgnevate kasutajate kutsumine %(groupId)s liikmeks ebaõnnestus:", + "Failed to invite users to community": "Kasutajate kutsumine kogukonda ebaõnnestus", + "Failed to invite users to %(groupId)s": "Kasutajate kutsumine %(groupId)s kogukonna liikmeks ebaõnnestus", + "Unnamed Room": "Ilma nimeta jututuba", + "Identity server has no terms of service": "Isikutuvastusserveril puuduvad kasutustingimused", + "This action requires accessing the default identity server to validate an email address or phone number, but the server does not have any terms of service.": "E-posti aadressi või telefoninumbri kontrolliks see tegevus eeldab päringut vaikimisi isikutuvastusserverisse , aga sellel serveril puuduvad kasutustingimused.", + "Only continue if you trust the owner of the server.": "Jätka vaid siis, kui sa usaldad serveri omanikku.", + "Trust": "Usalda", + "%(name)s is requesting verification": "%(name)s soovib verifitseerimist", + "Securely cache encrypted messages locally for them to appear in search results.": "Turvaliselt puhverda krüptitud sõnumid kohalikku arvutisse ja võimalda kasutada neid otsingus.", + "Riot is missing some components required for securely caching encrypted messages locally. If you'd like to experiment with this feature, build a custom Riot Desktop with search components added.": "Riot'is on puudu need komponendid, mis võimaldavad otsida kohalikest turvaliselt puhverdatud krüptitud sõnumitest. Kui sa tahaksid sellist funktsionaalsust katsetada, siis pead kompileerima Riot'i variandi, kus need komponendid on lisatud.", + "Riot can't securely cache encrypted messages locally while running in a web browser. Use Riot Desktop for encrypted messages to appear in search results.": "Riot ei saa veebibrauserist käivitades otsida turvaliselt kohalikult puhverdatud krüptitud sõnumite hulgast. Selliste sõnumite hulgast otsimiseks kasuta Riot'i töölauaversiooni.", + "Message search": "Otsing sõnumite seast", + "Search…": "Otsi…", + "Cancel search": "Tühista otsing", + "Search failed": "Otsing ebaõnnestus", + "Server may be unavailable, overloaded, or search timed out :(": "Server kas pole leitav, on üle koormatud või otsing aegus :(", + "No more results": "Rohkem otsingutulemusi pole", + "Riot is securely caching encrypted messages locally for them to appear in search results:": "Otsingus kasutamiseks Riot puhverdab turvaliselt kohalikku arvutisse krüptitud sõnumeid:" } From 1f79f5ded687033a27ac79c99f6eb1264ef90394 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 29 Apr 2020 15:24:20 +0000 Subject: [PATCH 150/237] Translated using Weblate (French) Currently translated at 99.9% (2298 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 9b373cc364..ac41f6ec2e 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -2407,5 +2407,7 @@ "Where you’re logged in": "Où vous vous êtes connecté", "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Gérez les noms et déconnectez-vous de vos sessions ci-dessous ou vérifiez-les dans votre profil utilisateur.", "Review where you’re logged in": "Vérifier où vous vous êtes connecté", - "Verify your other sessions": "Vérifier vos autres sessions" + "Verify your other sessions": "Vérifier vos autres sessions", + "Unverified sessions currently have access to your account & messages": "Des sessions non vérifiées ont accès à votre compte et messages", + "Verify the identity of the new login accessing your account & messages": "Vérifiez l'identité de la nouvelle connexion accédant à votre compte et messages" } From e3da750de07ed66f02cb4e9a51da9fc82df4d539 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 29 Apr 2020 15:19:09 +0100 Subject: [PATCH 151/237] Allow resetting storage from the access dialog This adds a path to reset secret storage from the access dialog instead of throwing an error. Fixes https://github.com/vector-im/riot-web/issues/13436 --- .../views/dialogs/secretstorage/AccessSecretStorageDialog.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js index 7d7edffcbf..e2ceadfbb9 100644 --- a/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js +++ b/src/components/views/dialogs/secretstorage/AccessSecretStorageDialog.js @@ -21,6 +21,7 @@ import * as sdk from '../../../../index'; import {MatrixClientPeg} from '../../../../MatrixClientPeg'; import { _t } from '../../../../languageHandler'; +import { accessSecretStorage } from '../../../../CrossSigningManager'; /* * Access Secure Secret Storage by requesting the user's passphrase. @@ -55,8 +56,9 @@ export default class AccessSecretStorageDialog extends React.PureComponent { } _onResetRecoveryClick = () => { + // Re-enter the access flow, but resetting storage this time around. this.props.onFinished(false); - throw new Error("Resetting secret storage unimplemented"); + accessSecretStorage(() => {}, /* forceReset = */ true); } _onRecoveryKeyChange = (e) => { From 19170945b127f2df72cd10db79f62810d9781dda Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 17:16:04 +0100 Subject: [PATCH 152/237] Treat sessions that are there when we log in as old Use the bulk 'review' toast for sessions that existed at the time of login, rather than considering them all to be new. Also cheeky unrelated proptypes fix. Fixes https://github.com/vector-im/riot-web/issues/13443 Requires https://github.com/matrix-org/matrix-js-sdk/pull/1360 --- src/DeviceListener.js | 13 ++++++++++--- .../views/toasts/UnverifiedSessionToast.js | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 84c6b1d230..c37d702fd6 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -107,7 +107,12 @@ export default class DeviceListener { } } - _onWillUpdateDevices = async (users) => { + _onWillUpdateDevices = async (users, initialFetch) => { + // We we didn't know about *any* devices before (ie. it's fresh login), + // then they are all pre-existing devices, so ignore this and set the + // devicesAtStart list to the devices that we see after the fetch. + if (initialFetch) return; + const myUserId = MatrixClientPeg.get().getUserId(); if (users.includes(myUserId)) this._ensureDeviceIdsAtStartPopulated(); @@ -179,8 +184,6 @@ export default class DeviceListener { const crossSigningReady = await cli.isCrossSigningReady(); - this._ensureDeviceIdsAtStartPopulated(); - if (this._dismissedThisDeviceToast) { ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY); } else { @@ -235,6 +238,10 @@ export default class DeviceListener { } } + // This needs to be done after awaiting on downloadKeys() above, so + // we make sure we get the devices after the fetch is done. + this._ensureDeviceIdsAtStartPopulated(); + // Unverified devices that were there last time the app ran // (technically could just be a boolean: we don't actually // need to remember the device IDs, but for the sake of diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index 032d457c3a..f3e35e247c 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -27,7 +27,7 @@ import { replaceableComponent } from '../../../utils/replaceableComponent'; @replaceableComponent("views.toasts.UnverifiedSessionToast") export default class UnverifiedSessionToast extends React.PureComponent { static propTypes = { - deviceId: PropTypes.object, + deviceId: PropTypes.string, } _onLaterClick = () => { From 38124ba9d07f978a0645157cd871f5ad20f37d33 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 17:33:18 +0100 Subject: [PATCH 153/237] Comment typo Co-Authored-By: J. Ryan Stinnett --- src/DeviceListener.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index c37d702fd6..28f8e8b115 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -108,7 +108,7 @@ export default class DeviceListener { } _onWillUpdateDevices = async (users, initialFetch) => { - // We we didn't know about *any* devices before (ie. it's fresh login), + // If we didn't know about *any* devices before (ie. it's fresh login), // then they are all pre-existing devices, so ignore this and set the // devicesAtStart list to the devices that we see after the fetch. if (initialFetch) return; From 886b30a265191525c56463fb38dcb2509fe6c94d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 29 Apr 2020 15:07:00 +0200 Subject: [PATCH 154/237] also recheck --- src/components/structures/MatrixChat.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 1293ccc7e9..a17db57d53 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1186,6 +1186,7 @@ export default createReactClass({ */ _onLoggedIn: async function() { ThemeController.isLogin = false; + this._themeWatcher.recheck(); this.setStateForNewView({ view: VIEWS.LOGGED_IN }); // If a specific screen is set to be shown after login, show that above // all else, as it probably means the user clicked on something already. From 1cac7b778d630e502c3d53876f80578d7efd65cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 29 Apr 2020 16:56:46 +0000 Subject: [PATCH 155/237] Translated using Weblate (Estonian) Currently translated at 22.3% (513 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 603354166a..f254493f3d 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -508,5 +508,8 @@ "Search failed": "Otsing ebaõnnestus", "Server may be unavailable, overloaded, or search timed out :(": "Server kas pole leitav, on üle koormatud või otsing aegus :(", "No more results": "Rohkem otsingutulemusi pole", - "Riot is securely caching encrypted messages locally for them to appear in search results:": "Otsingus kasutamiseks Riot puhverdab turvaliselt kohalikku arvutisse krüptitud sõnumeid:" + "Riot is securely caching encrypted messages locally for them to appear in search results:": "Otsingus kasutamiseks Riot puhverdab turvaliselt kohalikku arvutisse krüptitud sõnumeid:", + "Riot does not have permission to send you notifications - please check your browser settings": "Riot'il puudub luba sulle teavituste kuvamiseks - palun kontrolli oma brauseri seadistusi", + "Riot was not given permission to send notifications - please try again": "Riot ei saanud luba teavituste kuvamiseks - palun proovi uuesti", + "Room Notification": "Jututoa teavitus" } From ba233dc37218b1aa790ff6e34e2f72e0610fc641 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 17:28:45 +0100 Subject: [PATCH 156/237] Reduce maximum width of toasts & allow multiple lines --- res/css/structures/_ToastContainer.scss | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/res/css/structures/_ToastContainer.scss b/res/css/structures/_ToastContainer.scss index af595aaeee..64496b2cc0 100644 --- a/res/css/structures/_ToastContainer.scss +++ b/res/css/structures/_ToastContainer.scss @@ -91,10 +91,7 @@ limitations under the License. } .mx_Toast_description { - max-width: 400px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; + max-width: 272px; margin: 4px 0 11px 0; font-size: $font-12px; } From 189a78d184a00bf81213e60b4e0c1d41037c209c Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 17:38:32 +0100 Subject: [PATCH 157/237] Put overflows back --- res/css/structures/_ToastContainer.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/css/structures/_ToastContainer.scss b/res/css/structures/_ToastContainer.scss index 64496b2cc0..6ec4a0d152 100644 --- a/res/css/structures/_ToastContainer.scss +++ b/res/css/structures/_ToastContainer.scss @@ -92,6 +92,8 @@ limitations under the License. .mx_Toast_description { max-width: 272px; + overflow: hidden; + text-overflow: ellipsis; margin: 4px 0 11px 0; font-size: $font-12px; } From cea8f59fb3acc77986fb305264d87a8c6996ab7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 29 Apr 2020 17:09:48 +0000 Subject: [PATCH 158/237] Translated using Weblate (Estonian) Currently translated at 23.7% (545 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index f254493f3d..528f770948 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -511,5 +511,37 @@ "Riot is securely caching encrypted messages locally for them to appear in search results:": "Otsingus kasutamiseks Riot puhverdab turvaliselt kohalikku arvutisse krüptitud sõnumeid:", "Riot does not have permission to send you notifications - please check your browser settings": "Riot'il puudub luba sulle teavituste kuvamiseks - palun kontrolli oma brauseri seadistusi", "Riot was not given permission to send notifications - please try again": "Riot ei saanud luba teavituste kuvamiseks - palun proovi uuesti", - "Room Notification": "Jututoa teavitus" + "Room Notification": "Jututoa teavitus", + "Displays information about a user": "Näitab teavet kasutaja kohta", + "This homeserver has hit its Monthly Active User limit.": "See koduserver on saavutanud igakuise aktiivsete kasutajate piiri.", + "about a minute ago": "umbes minut tagasi", + "about an hour ago": "umbes tund tagasi", + "%(num)s hours ago": "%(num)s tundi tagasi", + "about a day ago": "umbes päev tagasi", + "%(num)s days ago": "%(num)s päeva tagasi", + "about a minute from now": "umbes minuti pärast", + "about an hour from now": "umbes tunni pärast", + "%(num)s hours from now": "%(num)s tunni pärast", + "about a day from now": "umbes päeva pärast", + "%(num)s days from now": "%(num)s päeva pärast", + "Are you sure?": "Kas sa oled kindel?", + "No sessions with registered encryption keys": "Puuduvad registreeritud krüptimisvõtmetega sessioonid", + "Jump to read receipt": "Hüppa lugemisteatise juurde", + "Invite": "Kutsu", + "Unmute": "Eemalda summutamine", + "This homeserver has hit its Monthly Active User limit so some users will not be able to log in.": "See koduserver on saavutanud igakuise aktiivsete kasutajate piiri ja seega osad kasutajad ei saa sisse logida.", + "Create a public room": "Loo avalik jututuba", + "Create a private room": "Loo omavaheline jututuba", + "Name": "Nimi", + "Topic (optional)": "Teema (valikuline)", + "Make this room public": "Tee see jututuba avalikuks", + "Hide advanced": "Peida lisaseadistused", + "Show advanced": "Näita lisaseadistused", + "Server did not require any authentication": "Server ei nõudnud mitte mingisugust autentimist", + "Recent Conversations": "Hiljutised vestlused", + "Suggestions": "Soovitused", + "Start a conversation with someone using their name, username (like ) or email address.": "Alusta vestlust kasutades teise osapoole nime, kasutajanime (näiteks ) või e-posti aadressi.", + "Go": "Mine", + "Your message wasn't sent because this homeserver has hit its Monthly Active User Limit. Please contact your service administrator to continue using the service.": "Sinu sõnumit ei saadetud, kuna see koduserver on saavutanud igakuise aktiivsete kasutajate piiri. Teenuse kasutamiseks palun võta ühendust serveri haldajaga.", + "Add room": "LIsa jututuba" } From 683d6804cae5f882895473d29cb075401d43c77b Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 19:07:10 +0100 Subject: [PATCH 159/237] Update toast copy again Fixes https://github.com/vector-im/riot-web/issues/13447 --- src/components/views/toasts/BulkUnverifiedSessionsToast.js | 2 +- src/components/views/toasts/UnverifiedSessionToast.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/toasts/BulkUnverifiedSessionsToast.js b/src/components/views/toasts/BulkUnverifiedSessionsToast.js index e0be846a2b..0c40e56858 100644 --- a/src/components/views/toasts/BulkUnverifiedSessionsToast.js +++ b/src/components/views/toasts/BulkUnverifiedSessionsToast.js @@ -45,7 +45,7 @@ export default class BulkUnverifiedSessionsToast extends React.PureComponent { render() { return (
- {_t("Unverified sessions currently have access to your account & messages")} + {_t("Verify all your sessions to ensure your account & messages are safe")}
diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index f3e35e247c..afabf69178 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -51,7 +51,7 @@ export default class UnverifiedSessionToast extends React.PureComponent { render() { return (
- {_t("Verify the identity of the new login accessing your account & messages")} + {_t("Verify the new login accessing your account & messages")}
From c97eab24c7e0c2d6c2a5b45b2d988baa29f56ede Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 29 Apr 2020 19:07:10 +0100 Subject: [PATCH 160/237] Update toast copy again Fixes https://github.com/vector-im/riot-web/issues/13447 --- src/components/views/toasts/BulkUnverifiedSessionsToast.js | 2 +- src/components/views/toasts/UnverifiedSessionToast.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/toasts/BulkUnverifiedSessionsToast.js b/src/components/views/toasts/BulkUnverifiedSessionsToast.js index e0be846a2b..0c40e56858 100644 --- a/src/components/views/toasts/BulkUnverifiedSessionsToast.js +++ b/src/components/views/toasts/BulkUnverifiedSessionsToast.js @@ -45,7 +45,7 @@ export default class BulkUnverifiedSessionsToast extends React.PureComponent { render() { return (
- {_t("Unverified sessions currently have access to your account & messages")} + {_t("Verify all your sessions to ensure your account & messages are safe")}
diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index f3e35e247c..afabf69178 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -51,7 +51,7 @@ export default class UnverifiedSessionToast extends React.PureComponent { render() { return (
- {_t("Verify the identity of the new login accessing your account & messages")} + {_t("Verify the new login accessing your account & messages")}
From 9d699c66d0514a87a2884e1a18d7399a08a1afb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 29 Apr 2020 19:19:22 +0000 Subject: [PATCH 161/237] Translated using Weblate (Estonian) Currently translated at 24.1% (553 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 528f770948..7f9dcb3113 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -543,5 +543,13 @@ "Start a conversation with someone using their name, username (like ) or email address.": "Alusta vestlust kasutades teise osapoole nime, kasutajanime (näiteks ) või e-posti aadressi.", "Go": "Mine", "Your message wasn't sent because this homeserver has hit its Monthly Active User Limit. Please contact your service administrator to continue using the service.": "Sinu sõnumit ei saadetud, kuna see koduserver on saavutanud igakuise aktiivsete kasutajate piiri. Teenuse kasutamiseks palun võta ühendust serveri haldajaga.", - "Add room": "LIsa jututuba" + "Add room": "LIsa jututuba", + "%(senderName)s invited %(targetName)s.": "%(senderName)s kutsus vestlema kasutajat %(targetName)s.", + "%(targetName)s joined the room.": "%(targetName)s liitus jututoaga.", + "%(senderName)s answered the call.": "%(senderName)s vastas kõnele.", + "%(senderName)s ended the call.": "%(senderName)s lõpetas kõne.", + "%(senderName)s placed a voice call.": "%(senderName)s alustas häälkõnet.", + "%(senderName)s placed a voice call. (not supported by this browser)": "%(senderName)s alustas häälkõnet. (sellel brauseril puudub niisuguste kõnede tugi)", + "%(senderName)s placed a video call.": "%(senderName)s alustas videokõnet.", + "%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s alustas videokõnet. (sellel brauseril puudub niisuguste kõnede tugi)" } From dab4ca64fce6ab176058e60c6b022c513776a50a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 29 Apr 2020 19:43:59 +0000 Subject: [PATCH 162/237] Translated using Weblate (Estonian) Currently translated at 26.8% (617 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 66 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 7f9dcb3113..74885e0aad 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -551,5 +551,69 @@ "%(senderName)s placed a voice call.": "%(senderName)s alustas häälkõnet.", "%(senderName)s placed a voice call. (not supported by this browser)": "%(senderName)s alustas häälkõnet. (sellel brauseril puudub niisuguste kõnede tugi)", "%(senderName)s placed a video call.": "%(senderName)s alustas videokõnet.", - "%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s alustas videokõnet. (sellel brauseril puudub niisuguste kõnede tugi)" + "%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s alustas videokõnet. (sellel brauseril puudub niisuguste kõnede tugi)", + "%(senderDisplayName)s made the room invite only.": "%(senderDisplayName)s määras et jututuppa pääseb vaid kutsega.", + "%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s muutis liitumisreeglid järgnevaks - %(rule)s", + "%(senderDisplayName)s has allowed guests to join the room.": "%(senderDisplayName)s on lubanud külalistel jututoaga liituda.", + "%(senderDisplayName)s has prevented guests from joining the room.": "%(senderDisplayName)s on määranud et külalised ei saa jututoaga liituda.", + "%(senderDisplayName)s changed guest access to %(rule)s": "%(senderDisplayName)s muutis külaliste ligipääsureeglid alljärgnevaks - %(rule)s", + "%(senderDisplayName)s sent an image.": "%(senderDisplayName)s saatis pildi.", + "%(senderName)s set the main address for this room to %(address)s.": "%(senderName)s muutis selle jututoa põhiaadressiks %(address)s.", + "%(senderName)s removed the main address for this room.": "%(senderName)s eemaldas põhiaadressi sellest jututoast.", + "%(senderName)s added the alternative addresses %(addresses)s for this room.|other": "%(senderName)s lisas sellele jututoale täiendava aadressi %(addresses)s.", + "%(senderName)s added the alternative addresses %(addresses)s for this room.|one": "%(senderName)s lisas sellele jututoale täiendava aadressi %(addresses)s.", + "%(senderName)s removed the alternative addresses %(addresses)s for this room.|other": "%(senderName)s eemaldas täiendavad aadressid %(addresses)s sellelt jututoalt.", + "%(senderName)s removed the alternative addresses %(addresses)s for this room.|one": "%(senderName)s eemaldas täiendava aadressi %(addresses)s sellelt jututoalt.", + "%(senderName)s changed the alternative addresses for this room.": "%(senderName)s muutis selle jututoa täiendavat aadressi.", + "%(senderName)s changed the main and alternative addresses for this room.": "%(senderName)s muutis selle jututoa põhiaadressi ja täiendavat aadressi.", + "%(senderName)s changed the addresses for this room.": "%(senderName)s muutis selle jututoa aadressid.", + "Someone": "Keegi", + "(not supported by this browser)": "(ei ole toetatud selles brauseris)", + "(could not connect media)": "(ühendus teise osapoolega ei õnnestunud)", + "(no answer)": "(ei ole vastust)", + "(unknown failure: %(reason)s)": "(teadmata viga: %(reason)s)", + "%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s võttis %(targetDisplayName)s'lt tagasi jututoaga liitumise kutse.", + "%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s saatis %(targetDisplayName)s'le kutse jututoaga liitumiseks.", + "%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s määras, et jututoa tulevane ajalugu on nähtav kõikidele selle liikmetele nende kutsumise hetkest.", + "%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s määras, et jututoa tulevane ajalugu on nähtav kõikidele selle liikmetele nende liitumise hetkest.", + "%(senderName)s made future room history visible to all room members.": "%(senderName)s määras, et jututoa tulevane ajalugu on nähtav kõikidele selle liikmetele.", + "%(senderName)s made future room history visible to anyone.": "%(senderName)s seadistas, et jututoa tulevane ajalugu on kõigile nähtav.", + "%(senderName)s made future room history visible to unknown (%(visibility)s).": "%(senderName)s seadistas, et jututoa tulevase ajaloo nähtavuse olek on (%(visibility)s).", + "%(widgetName)s widget modified by %(senderName)s": "%(senderName)s muutis vidinat %(widgetName)s", + "%(widgetName)s widget added by %(senderName)s": "%(senderName)s lisas vidina %(widgetName)s", + "%(widgetName)s widget removed by %(senderName)s": "%(senderName)s eemaldas vidina %(widgetName)s", + "Muted Users": "Summutatud kasutajad", + "This room is end-to-end encrypted": "See jututuba on läbivalt krüptitud", + "Everyone in this room is verified": "Kõik kasutajad siin nututoas on verifitseeritud", + "Some sessions for this user are not trusted": "Mõned selle kasutaja sessioonid ei ole usaldusväärsed", + "All sessions for this user are trusted": "Kõik selle kasutaja sessioonid on usaldusväärsed", + "Some sessions in this encrypted room are not trusted": "Mõned sessioonid selles krüptitud jututoas ei ole usaldusväärsed", + "All sessions in this encrypted room are trusted": "Kõik sessioonid selles krüptitud jututoas on usaldusväärsed", + "Edit message": "Muuda sõnumit", + "%(senderName)s sent an image": "%(senderName)s saatis pildi", + "%(senderName)s sent a video": "%(senderName)s saatis video", + "%(senderName)s uploaded a file": "%(senderName)s laadis üles faili", + "Your key share request has been sent - please check your other sessions for key share requests.": "Sinu krüptovõtme jagamise päring on saadetud - palun oma teisi sessioone krüptovõtme jagamise päringu osas.", + "This message cannot be decrypted": "Seda sõnumit ei sa dekrüptida", + "Unencrypted": "Krüptimata", + "Encrypted by a deleted session": "Krüptitud kustutatud sessiooni poolt", + "Please select the destination room for this message": "Palun vali jututuba, kuhu soovid seda sõnumit saata", + "Invite only": "Ainult kutse", + "Scroll to most recent messages": "Mine viimaste sõnumite juurde", + "Close preview": "Sulge eelvaade", + "Disinvite": "Eemalda kutse", + "Kick": "Müksa välja", + "Disinvite this user?": "Kas võtad selle kasutaja kutse tagasi?", + "Kick this user?": "Kas müksad selle kasutaja jututoast välja?", + "Failed to kick": "Jututoast väljamüksamine ei õnnestunud", + "No recent messages by %(user)s found": "Kasutajalt %(user)s ei leitud hiljutisi sõnumeid", + "Try scrolling up in the timeline to see if there are any earlier ones.": "Vaata kas ajajoonel ülespool leidub varasemaid sõnumeid.", + "For a large amount of messages, this might take some time. Please don't refresh your client in the meantime.": "Kui sõnumeid on väga palju, siis võib nüüd aega kuluda. Oodates palun ära tee ühtegi päringut ega andmevärskendust.", + "Failed to mute user": "Kasutaja summutamine ebaõnnestus", + "%(creator)s created and configured the room.": "%(creator)s lõi ja seadistas jututoa.", + "Click to unmute video": "Klõpsi video heli taastamiseks", + "Click to mute video": "Klõpsi video heli summutamiseks", + "Click to unmute audio": "Klõpsi heli taastamiseks", + "Click to mute audio": "Klõpsi heli summutamiseks", + "Your profile": "Sinu profiil" } From 49ac4963c523b58efa341aa9b09e2fd29bf1bc08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 29 Apr 2020 20:55:43 +0000 Subject: [PATCH 163/237] Translated using Weblate (Estonian) Currently translated at 28.1% (647 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 74885e0aad..42e1030a89 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -615,5 +615,35 @@ "Click to mute video": "Klõpsi video heli summutamiseks", "Click to unmute audio": "Klõpsi heli taastamiseks", "Click to mute audio": "Klõpsi heli summutamiseks", - "Your profile": "Sinu profiil" + "Your profile": "Sinu profiil", + "How fast should messages be downloaded.": "Kui kiiresti peaksime sõnumeid alla laadima.", + "Error downloading theme information.": "Viga teema teabefaili allalaadimisel.", + "Close": "Sulge", + "Add a widget": "Lisa vidin", + "Drop File Here": "Lohista fail siia", + "Drop file here to upload": "Faili üleslaadimiseks lohista ta siia", + " (unsupported)": " (ei ole toetatud)", + "This user has not verified all of their sessions.": "See kasutaja ei ole verifitseerinud kõiki nende sessioone.", + "You have not verified this user.": "Sa ei ole seda kasutajat verifitseerinud.", + "You have verified this user. This user has verified all of their sessions.": "Sa oled selle kasutaja verifitseerinud. See kasutaja on verifitseerinud kõik nende sessioonid.", + "Someone is using an unknown session": "Keegi kasutab tundmatut sessiooni", + "This event could not be displayed": "Seda sündmust ei õnnestunud kuvada", + "Downloading update...": "Laen alla uuendust...", + "Download this file": "Lae see fail alla", + "You can now close this window or log in to your new account.": "Sa võid nüüd sulgeda selle akna või logida sisse oma uuele kontole.", + "Download": "Lae alla", + "Your recovery key is in your Downloads folder.": "Sinu taastevõti on sinu Allalaadimised kasutas.", + "Disable": "Lülita välja", + "Not currently indexing messages for any room.": "Mitte ainsamagi jututoa sõnumeid hetkel ei indekseerita.", + "Currently indexing: %(currentRoom)s": "Parasjagu indekseerin: %(currentRoom)s", + "Space used:": "Kasutatud andmeruum:", + "Indexed messages:": "Indekseeritud sõnumid:", + "Failed to add tag %(tagName)s to room": "Sildi %(tagName)s lisamine jututoale ebaõnnestus", + "Close dialog or context menu": "Sulge dialoogiaken või kontekstimenüü", + "Page Up": "Page Up", + "Page Down": "Page Down", + "Esc": "Esc", + "Enter": "Enter", + "Space": "Tühikuklahv", + "End": "End" } From 8be07abf6cf330ef18c96804e1d29d17bb7603a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 29 Apr 2020 21:27:33 +0000 Subject: [PATCH 164/237] Translated using Weblate (Estonian) Currently translated at 28.6% (657 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 42e1030a89..7fa5208f4b 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -645,5 +645,15 @@ "Esc": "Esc", "Enter": "Enter", "Space": "Tühikuklahv", - "End": "End" + "End": "End", + "Unable to add email address": "E-posti aadressi lisamine ebaõnnestus", + "Add": "Lisa", + "We've sent you an email to verify your address. Please follow the instructions there and then click the button below.": "Sinu aadressi kontrollimiseks saatsime sulle e-kirja. Palun järgi kirjas näidatud juhendit ja siis klõpsi alljärgnevat nuppu.", + "Email Address": "E-posti aadress", + "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains.": "Saatsime tekstisõnumi numbrile +%(msisdn)s. Palun sisesta seal kuvatud kontrollkood.", + "Phone Number": "Telefoni number", + "Cannot add any more widgets": "Rohkem vidinaid ei õnnestu lisada", + "The maximum permitted number of widgets have already been added to this room.": "Suurim lubatud vidinate arv on siia jututuppa juba lisatud.", + "Join as voice or video.": "Liitu kas häälkõnega või videokõnega.", + "Ongoing conference call%(supportedText)s.": "Toimuv rühmavestlus %(supportedText)s." } From 4d66e251ae2a9012caf47bcf989792e90f08358f Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Thu, 30 Apr 2020 06:17:03 +0000 Subject: [PATCH 165/237] Translated using Weblate (Bulgarian) Currently translated at 86.3% (1984 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/bg/ --- src/i18n/strings/bg.json | 84 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/bg.json b/src/i18n/strings/bg.json index b31498ef0b..7a5edcc381 100644 --- a/src/i18n/strings/bg.json +++ b/src/i18n/strings/bg.json @@ -1961,5 +1961,87 @@ "Enable message search in encrypted rooms": "Включи търсенето на съобщения в шифровани стаи", "Keep secret storage passphrase in memory for this session": "Съхрани паролата за секретното складиране в паметта за тази сесия", "How fast should messages be downloaded.": "Колко бързо да се изтеглят съобщенията.", - "Manually verify all remote sessions": "Ръчно потвърждаване на всички отдалечени сесии" + "Manually verify all remote sessions": "Ръчно потвърждаване на всички отдалечени сесии", + "If you cancel now, you won't complete your operation.": "Ако се откажете сега, няма да завършите операцията.", + "Review where you’re logged in": "Прегледайте откъде сте влезли в профила си", + "New login. Was this you?": "Нов вход. Вие ли бяхте това?", + "%(name)s is requesting verification": "%(name)s изпрати запитване за верификация", + "Failed to set topic": "Неуспешно задаване на тема", + "Command failed": "Командата не се изпълни", + "Could not find user in room": "Неуспешно намиране на потребител в стаята", + "Please supply a widget URL or embed code": "Укажете URL адрес на приспособление или код за вграждане", + "Send a bug report with logs": "Изпратете доклад за грешка с логове", + "Enable cross-signing to verify per-user instead of per-session": "Включи кръстосано-подписване за верифициране на ниво потребител, вместо на ниво сесия", + "Keep recovery passphrase in memory for this session": "Запази паролата за възстановяване в паметта за тази сесия", + "Verify this session by completing one of the following:": "Верифицирайте тази сесия чрез едно от следните действия:", + "Scan this unique code": "Сканирайте този уникален код", + "or": "или", + "Compare unique emoji": "Сравнете уникални емоджи", + "Compare a unique set of emoji if you don't have a camera on either device": "Сравнете уникални емоджи, ако нямате камера на някое от устройствата", + "Start": "Започни", + "Confirm the emoji below are displayed on both sessions, in the same order:": "Потвърдете, че емоджитата по-долу са показани и на двете сесии в един и същи ред:", + "Verify this session by confirming the following number appears on its screen.": "Потвърдете тази сесия, като потвърдите, че следното число се появява на екрана й.", + "Waiting for your other session, %(deviceName)s (%(deviceId)s), to verify…": "Изчакване на другата сесия, %(deviceName)s (%(deviceId)s) да потвърди…", + "Waiting for %(displayName)s to verify…": "Изчакване на %(displayName)s да потвърди…", + "Cancelling…": "Отказване…", + "They match": "Съвпадат", + "They don't match": "Не съвпадат", + "To be secure, do this in person or use a trusted way to communicate.": "За да е по-сигурно, направете го на живо или използвайте доверен начин за комуникация.", + "Lock": "Заключи", + "Unverified sessions currently have access to your account & messages": "Непотвърдени сесии в момента имат достъп до профила и съобщенията ви", + "Later": "По-късно", + "Review": "Прегледай", + "Verify yourself & others to keep your chats safe": "Потвърдете себе си и останалите за да запазите чатовете си сигурни", + "Other users may not trust it": "Други потребители може да не се доверят", + "Update your secure storage": "Обновете защитеното складиране", + "Verify the identity of the new login accessing your account & messages": "Потвърдете самоличността на новия вход достъпващ профила и съобщенията ви", + "From %(deviceName)s (%(deviceId)s)": "От %(deviceName)s (%(deviceId)s)", + "This bridge was provisioned by .": "Мостът е настроен от .", + "Workspace: %(networkName)s": "Работна област: %(networkName)s", + "Channel: %(channelName)s": "Канал: %(channelName)s", + "Show less": "Покажи по-малко", + "Changing password will currently reset any end-to-end encryption keys on all sessions, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Промяната на паролата в момента би нулирало всички ключове за шифроване-от-край-до-край, правейки историята на чата нечетима, освен ако първо не експортирате ключовете, а след промяната на паролата ги импортирате. В бъдеще, това ще бъде подобрено.", + "Your homeserver does not support cross-signing.": "Сървърът ви не поддържа кръстосано-подписване.", + "Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.": "Профилът ви има самоличност за кръстосано подписване в секретно складиране, но все още не е доверено от тази сесия.", + "Reset cross-signing and secret storage": "Нулирай кръстосаното-подписване и секретното складиране", + "well formed": "коректен", + "unexpected type": "непознат тип", + "in memory": "в паметта", + "Self signing private key:": "Частен ключ за самоподписване:", + "cached locally": "кеширан локално", + "not found locally": "ненамерен локално", + "User signing private key:": "Частен ключ за подписване на потребители:", + "Session backup key:": "Ключ за резервно копие на сесията:", + "Homeserver feature support:": "Поддържани функции от сървъра:", + "exists": "съществува", + "Secret Storage key format:": "Формат на ключа за секретно складиране:", + "outdated": "остарял", + "up to date": "обновен", + "Your homeserver does not support session management.": "Сървърът ви не поддържа управление на сесии.", + "Unable to load session list": "Неуспешно зареждане на списъка със сесии", + "Confirm deleting these sessions by using Single Sign On to prove your identity.|other": "Потвърдете изтриването на тези сесии използвайки Single Sign On, за да докажете самоличността си.", + "Confirm deleting these sessions by using Single Sign On to prove your identity.|one": "Потвърдете изтриването на тази сесия използвайки Single Sign On, за да докажете самоличността си.", + "Confirm deleting these sessions": "Потвърдете изтриването на тези сесии", + "Click the button below to confirm deleting these sessions.|other": "Кликнете бутона по-долу за да потвърдите изтриването на тези сесии.", + "Click the button below to confirm deleting these sessions.|one": "Кликнете бутона по-долу за да потвърдите изтриването на тази сесия.", + "Delete sessions|other": "Изтрий сесиите", + "Delete sessions|one": "Изтрий сесията", + "Delete %(count)s sessions|other": "Изтрий %(count)s сесии", + "Delete %(count)s sessions|one": "Изтрий %(count)s сесия", + "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 ": "Кеширай шифровани съобщения по сигурен начин, за да могат да се появяват в резултати от търсения, използвайки ", + " to store messages from ": " за складиране на съобщения от ", + "rooms.": "стаи.", + "Manage": "Управление", + "Securely cache encrypted messages locally for them to appear in search results.": "Кеширай шифровани съобщения локално по сигурен начин за да се появяват в резултати от търсения.", + "Enable": "Включи", + "Riot is missing some components required for securely caching encrypted messages locally. If you'd like to experiment with this feature, build a custom Riot Desktop with search components added.": "Липсват задължителни компоненти в Riot, за да могат да бъдат складирани локално и по сигурен начин шифровани съобщения. Ако искате да експериментирате с тази функция, \"компилирайте\" версия на Riot Desktop с добавени компоненти за търсене.", + "Riot can't securely cache encrypted messages locally while running in a web browser. Use Riot Desktop for encrypted messages to appear in search results.": "Riot работещ в браузър не може да складира шифровани съобщения локално по сигурен начин. Използвайте Riot Desktop за да може шифровани съобщения да се появяват в резултати от търсения.", + "This session is backing up your keys. ": "Тази сесия прави резервни копия на ключовете ви. ", + "This session is not backing up your keys, but you do have an existing backup you can restore from and add to going forward.": "Тази сесия не прави резервни копия на ключовете, но имате съществуващо резервно копие, което да възстановите и към което да добавяте от тук нататък.", + "Connect this session to key backup before signing out to avoid losing any keys that may only be on this session.": "Свържете тази сесия с резервно копие на ключове преди да се отпишете от нея, за да не загубите ключове, които може би съществуват единствено в тази сесия.", + "Connect this session to Key Backup": "Свържи тази сесия с резервно копие на ключовете", + "Backup has a signature from unknown session with ID %(deviceId)s": "Резервното копие има подпис от непозната сесия с идентификатор %(deviceId)s", + "Backup has a valid signature from this session": "Резервното копие има валиден подпис от тази сесия", + "Backup has an invalid signature from this session": "Резервното копие има невалиден подпис от тази сесия" } From feee969edc011bf497960cdca38b477ba39914e8 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Thu, 30 Apr 2020 02:41:06 +0000 Subject: [PATCH 166/237] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2299 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/zh_Hant/ --- src/i18n/strings/zh_Hant.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 06b0bed44c..9b0f4ccc5f 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -2406,5 +2406,8 @@ "Where you’re logged in": "您登入的地方", "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "在下方管理您工作階段的名稱與登入或在您的使用者檔案中驗證它們。", "Review where you’re logged in": "審閱您的登入位置", - "Verify your other sessions": "驗證您其他的工作階段" + "Verify your other sessions": "驗證您其他的工作階段", + "New login. Was this you?": "新登入。這是您嗎?", + "Unverified sessions currently have access to your account & messages": "未驗證的工作階段目前正在存取您的帳號與訊息", + "Verify the identity of the new login accessing your account & messages": "驗證存取您帳號與訊息的新登入身份" } From 87cd39109f91065c100158935aa7522df306cb1f Mon Sep 17 00:00:00 2001 From: yuuki-san Date: Wed, 29 Apr 2020 18:20:53 +0000 Subject: [PATCH 167/237] Translated using Weblate (Czech) Currently translated at 93.6% (2151 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/cs/ --- src/i18n/strings/cs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 52c90cc3d7..4de5084106 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -2107,7 +2107,7 @@ "Whether you're using Riot on a device where touch is the primary input mechanism": "Zda používáte Riot na dotykovém zařízení", "Whether you're using Riot as an installed Progressive Web App": "Zda používáte Riot jako nainstalovanou Progresivní Webovou Aplikaci", "Your user agent": "Identifikace vašeho prohlížeče", - "The information being sent to us to help make Riot better includes:": "Abychom mohli Riot zlepšovat, posíláme si následující informace:", + "The information being sent to us to help make Riot better includes:": "Abychom mohli Riot zlepšovat, posíláte nám následující informace:", "Verify this session by completing one of the following:": "Ověřte tuto relaci dokončením jednoho z následujících:", "Scan this unique code": "Naskenujte tento jedinečný kód", "or": "nebo", From 2a4c6f3da9b9bedcad0d3ecf78fd7465639b358b Mon Sep 17 00:00:00 2001 From: axel simon Date: Wed, 29 Apr 2020 17:33:30 +0000 Subject: [PATCH 168/237] Translated using Weblate (French) Currently translated at 99.9% (2298 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index ac41f6ec2e..ab3acb07b8 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -88,7 +88,7 @@ "An error has occurred.": "Une erreur est survenue.", "Email": "E-mail", "Failed to unban": "Échec de la révocation du bannissement", - "Failed to verify email address: make sure you clicked the link in the email": "Échec de la vérification de l’adresse e-mail : vérifiez que vous avez bien cliqué sur le lien dans l’e-mail", + "Failed to verify email address: make sure you clicked the link in the email": "La vérification de l’adresse e-mail a échoué : vérifiez que vous avez bien cliqué sur le lien dans l’e-mail", "Failure to create room": "Échec de la création du salon", "Favourites": "Favoris", "Fill screen": "Plein écran", @@ -234,7 +234,7 @@ "Voice call": "Appel vocal", "VoIP conference finished.": "Téléconférence VoIP terminée.", "VoIP conference started.": "Téléconférence VoIP démarrée.", - "VoIP is unsupported": "VoIP (Appels par Internet) n'est pas supportée", + "VoIP is unsupported": "Voix sur IP non gérée", "Warning!": "Attention !", "Who can access this room?": "Qui peut accéder au salon ?", "Who can read history?": "Qui peut lire l'historique ?", @@ -661,10 +661,10 @@ "Display your community flair in rooms configured to show it.": "Sélectionnez les badges dans les paramètres de chaque salon pour les afficher.", "expand": "développer", "collapse": "réduire", - "Call Failed": "Échec de l'appel", + "Call Failed": "L'appel a échoué", "Review Devices": "Passer en revue les appareils", - "Call Anyway": "Appeler quand même", - "Answer Anyway": "Répondre quand même", + "Call Anyway": "Appeler malgré tout", + "Answer Anyway": "Répondre malgré tout", "Call": "Appel", "Answer": "Répondre", "Send": "Envoyer", @@ -688,8 +688,8 @@ "The platform you're on": "La plateforme que vous utilisez", "The version of Riot.im": "La version de Riot.im", "Your language of choice": "La langue que vous avez choisie", - "Which officially provided instance you are using, if any": "Quelle instance officielle vous utilisez, si c'est le cas", - "Whether or not you're using the Richtext mode of the Rich Text Editor": "Si vous utilisez le mode de texte enrichi de l'éditeur de texte enrichi", + "Which officially provided instance you are using, if any": "L'instance officielle que vous utilisez, si vous en utilisez une", + "Whether or not you're using the Richtext mode of the Rich Text Editor": "Si vous utilisez le mode « texte enrichi » de l'éditeur de texte enrichi", "Your homeserver's URL": "L'URL de votre serveur d'accueil", "Your identity server's URL": "L'URL de votre serveur d'identité", "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s %(day)s %(monthName)s %(fullYear)s", @@ -1553,9 +1553,9 @@ "You are not currently using an identity server. To discover and be discoverable by existing contacts you know, add one below.": "Vous n’utilisez actuellement aucun serveur d’identité. Pour découvrir et être découvert par les contacts existants que vous connaissez, ajoutez-en un ci-dessous.", "Disconnecting from your identity server will mean you won't be discoverable by other users and you won't be able to invite others by email or phone.": "La déconnexion de votre serveur d’identité signifie que vous ne serez plus découvrable par d’autres utilisateurs et que vous ne pourrez plus faire d’invitation par e-mail ou téléphone.", "Integration Manager": "Gestionnaire d’intégration", - "Call failed due to misconfigured server": "Échec de l’appel à cause d’un serveur mal configuré", + "Call failed due to misconfigured server": "L’appel a échoué à cause d’un serveur mal configuré", "Please ask the administrator of your homeserver (%(homeserverDomain)s) to configure a TURN server in order for calls to work reliably.": "Demandez à l’administrateur de votre serveur d’accueil (%(homeserverDomain)s) de configurer un serveur TURN afin que les appels fonctionnent de manière fiable.", - "Alternatively, you can try to use the public server at turn.matrix.org, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Sinon, vous pouvez essayer d’utiliser le serveur public à turn.matrix.org, mais ça ne sera pas aussi fiable et ça partagera votre adresse IP avec ce serveur. Vous pouvez aussi gérer cela dans les paramètres.", + "Alternatively, you can try to use the public server at turn.matrix.org, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Vous pouvez sinon essayer d’utiliser le serveur public turn.matrix.org, mais ça ne sera pas aussi fiable et votre adresse IP sera partagée avec ce serveur. Vous pouvez aussi gérer ce réglage dans les paramètres.", "Try using turn.matrix.org": "Essayer d’utiliser turn.matrix.org", "Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Autoriser le repli sur le serveur d’assistance d’appel turn.matrix.org quand votre serveur n’en fournit pas (votre adresse IP serait partagée lors d’un appel)", "Only continue if you trust the owner of the server.": "Continuez seulement si vous faites confiance au propriétaire du serveur.", From e33a4a24523577689869c1b8666a0d778516c244 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 29 Apr 2020 17:36:00 +0000 Subject: [PATCH 169/237] Translated using Weblate (French) Currently translated at 99.9% (2298 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index ab3acb07b8..2e9e0d971a 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -39,7 +39,7 @@ "Banned users": "Utilisateurs bannis", "Bans user with given id": "Bannit l'utilisateur à partir de son identifiant", "Blacklisted": "Sur liste noire", - "Call Timeout": "Délai d’appel expiré", + "Call Timeout": "L’appel a dépassé le délai d'attente maximal", "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Impossible de se connecter au serveur d'accueil en HTTP si l'URL dans la barre de votre explorateur est en HTTPS. Utilisez HTTPS ou activez le support des scripts non-vérifiés.", "Change Password": "Changer le mot de passe", "%(senderName)s changed their profile picture.": "%(senderName)s a changé son image de profil.", From fec4429d7d04e626f97e1569fb156cfeafd2c46e Mon Sep 17 00:00:00 2001 From: grrgui Date: Wed, 29 Apr 2020 17:37:20 +0000 Subject: [PATCH 170/237] Translated using Weblate (French) Currently translated at 99.9% (2298 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 2e9e0d971a..1fc3ab8d88 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -215,7 +215,7 @@ "Unable to verify email address.": "Impossible de vérifier l’adresse e-mail.", "Unban": "Révoquer le bannissement", "%(senderName)s unbanned %(targetName)s.": "%(senderName)s a révoqué le bannissement de %(targetName)s.", - "Unable to capture screen": "Impossible de capturer l'écran", + "Unable to capture screen": "Impossible de faire une capture d'écran", "Unable to enable Notifications": "Impossible d'activer les notifications", "unencrypted": "non chiffré", "unknown device": "appareil inconnu", From 9a2a57fe99d3809893332c6d8b2cf257318d0de4 Mon Sep 17 00:00:00 2001 From: yuuki-san Date: Wed, 29 Apr 2020 18:06:39 +0000 Subject: [PATCH 171/237] Translated using Weblate (Slovak) Currently translated at 62.5% (1438 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/sk/ --- src/i18n/strings/sk.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/sk.json b/src/i18n/strings/sk.json index f6f0cd3a74..fbecaa4845 100644 --- a/src/i18n/strings/sk.json +++ b/src/i18n/strings/sk.json @@ -1506,5 +1506,18 @@ "Something went wrong. Please try again or view your console for hints.": "Niečo sa nepodarilo. Prosím, skúste znovu neskôr alebo si prečítajte ďalšie usmernenia zobrazením konzoly.", "Error subscribing to list": "Chyba pri prihlasovaní sa do zoznamu", "Please verify the room ID or alias and try again.": "Prosím, overte platnosť ID miestnosti alebo alias a skúste znovu.\nPlease verify the room ID or alias and try again.", - "Error removing ignored user/server": "Chyba pri odstraňovaní ignorovaného používateľa / servera" + "Error removing ignored user/server": "Chyba pri odstraňovaní ignorovaného používateľa / servera", + "Use Single Sign On to continue": "Pokračovať pomocou Jednotného prihlásenia", + "Confirm adding this email address by using Single Sign On to prove your identity.": "Potvrďte pridanie tejto adresy pomocou Jednotného prihlásenia.", + "Single Sign On": "Jednotné prihlásenie", + "Confirm adding email": "Potvrdiť pridanie emailu", + "Click the button below to confirm adding this email address.": "Kliknutím na tlačítko potvrdíte pridanie emailovej adresy.", + "Confirm adding this phone number by using Single Sign On to prove your identity.": "Potvrďte pridanie telefónneho čísla pomocou Jednotného prihlásenia.", + "Confirm adding phone number": "Potvrdiť pridanie telefónneho čísla", + "Click the button below to confirm adding this phone number.": "Kliknutím na tlačítko potvrdíte pridanie telefónneho čísla.", + "The version of Riot": "Verzia Riotu", + "Whether you're using Riot on a device where touch is the primary input mechanism": "Či používate Riot na zariadení, ktorého hlavným vstupným mechanizmom je dotyk (mobil, tablet,...)", + "Whether you're using Riot as an installed Progressive Web App": "Či používate Riot ako nainštalovanú Progresívnu Webovú Aplikáciu", + "Your user agent": "Identifikátor vášho prehliadača", + "The information being sent to us to help make Riot better includes:": "Informácie, ktoré nám posielate, aby sme zlepšili Riot, zahŕňajú:" } From 5ecd874e820fba16f36b61ceaf9c823088a99408 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 30 Apr 2020 09:44:15 +0100 Subject: [PATCH 172/237] yarn i18n --- src/i18n/strings/en_EN.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 6ab0c886d4..b1ec616d67 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -559,7 +559,7 @@ "Headphones": "Headphones", "Folder": "Folder", "Pin": "Pin", - "Unverified sessions currently have access to your account & messages": "Unverified sessions currently have access to your account & messages", + "Verify all your sessions to ensure your account & messages are safe": "Verify all your sessions to ensure your account & messages are safe", "Later": "Later", "Review": "Review", "Verify yourself & others to keep your chats safe": "Verify yourself & others to keep your chats safe", @@ -568,7 +568,7 @@ "Set up": "Set up", "Upgrade": "Upgrade", "Verify": "Verify", - "Verify the identity of the new login accessing your account & messages": "Verify the identity of the new login accessing your account & messages", + "Verify the new login accessing your account & messages": "Verify the new login accessing your account & messages", "From %(deviceName)s (%(deviceId)s)": "From %(deviceName)s (%(deviceId)s)", "Decline (%(counter)s)": "Decline (%(counter)s)", "Accept to continue:": "Accept to continue:", From aa9da54bed1f92baca01b4fa32f9c513ed4ca627 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 30 Apr 2020 09:44:15 +0100 Subject: [PATCH 173/237] yarn i18n --- src/i18n/strings/en_EN.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index dc83ca8964..861dc24707 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -556,7 +556,7 @@ "Headphones": "Headphones", "Folder": "Folder", "Pin": "Pin", - "Unverified sessions currently have access to your account & messages": "Unverified sessions currently have access to your account & messages", + "Verify all your sessions to ensure your account & messages are safe": "Verify all your sessions to ensure your account & messages are safe", "Later": "Later", "Review": "Review", "Verify yourself & others to keep your chats safe": "Verify yourself & others to keep your chats safe", @@ -565,7 +565,7 @@ "Set up": "Set up", "Upgrade": "Upgrade", "Verify": "Verify", - "Verify the identity of the new login accessing your account & messages": "Verify the identity of the new login accessing your account & messages", + "Verify the new login accessing your account & messages": "Verify the new login accessing your account & messages", "From %(deviceName)s (%(deviceId)s)": "From %(deviceName)s (%(deviceId)s)", "Decline (%(counter)s)": "Decline (%(counter)s)", "Accept to continue:": "Accept to continue:", From e845409167098097fcde34872ad121877b825dba Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 30 Apr 2020 11:00:35 +0100 Subject: [PATCH 174/237] Fix device verification toasts not disappearing recheck in DeviceListener returned early if cross-signing wasn't ready, but this was unnecessary and prevented it from hiding the device verification toasts (which also appeared above the toast to verify yourself). --- src/DeviceListener.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 28f8e8b115..d948911d7c 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -223,7 +223,6 @@ export default class DeviceListener { }); } } - return; } else if (await cli.secretStorageKeyNeedsUpgrade()) { ToastStore.sharedInstance().addOrReplaceToast({ key: THIS_DEVICE_TOAST_KEY, From 4f95c89ffcef2a6329cb00675b4e6953567a1769 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 30 Apr 2020 11:00:35 +0100 Subject: [PATCH 175/237] Fix device verification toasts not disappearing recheck in DeviceListener returned early if cross-signing wasn't ready, but this was unnecessary and prevented it from hiding the device verification toasts (which also appeared above the toast to verify yourself). --- src/DeviceListener.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 28f8e8b115..d948911d7c 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -223,7 +223,6 @@ export default class DeviceListener { }); } } - return; } else if (await cli.secretStorageKeyNeedsUpgrade()) { ToastStore.sharedInstance().addOrReplaceToast({ key: THIS_DEVICE_TOAST_KEY, From 6f844977f527483910c97975c062b000a1d4332b Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 30 Apr 2020 09:36:39 +0000 Subject: [PATCH 176/237] Translated using Weblate (French) Currently translated at 99.9% (2298 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 1fc3ab8d88..aa873c386d 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -2409,5 +2409,7 @@ "Review where you’re logged in": "Vérifier où vous vous êtes connecté", "Verify your other sessions": "Vérifier vos autres sessions", "Unverified sessions currently have access to your account & messages": "Des sessions non vérifiées ont accès à votre compte et messages", - "Verify the identity of the new login accessing your account & messages": "Vérifiez l'identité de la nouvelle connexion accédant à votre compte et messages" + "Verify the identity of the new login accessing your account & messages": "Vérifiez l'identité de la nouvelle connexion accédant à votre compte et messages", + "New login. Was this you?": "Nouvelle connexion. Était-ce vous ?", + "Verify all your sessions to ensure your account & messages are safe": "Vérifiez toutes vos sessions pour vous assurer que votre compte et messages sont sécurisés" } From 5a29bf569dedb998227074c45483c80e7dfca176 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 30 Apr 2020 11:21:33 +0100 Subject: [PATCH 177/237] Upgrade matrix-js-sdk to 6.0.0-rc.1 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 6c56dd080b..bb23fb6e80 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "5.3.1-rc.4", + "matrix-js-sdk": "6.0.0-rc.1", "minimist": "^1.2.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index c4a792136c..60ab9c225b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5715,10 +5715,10 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -matrix-js-sdk@5.3.1-rc.4: - version "5.3.1-rc.4" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.3.1-rc.4.tgz#f0e6d512540aa04dfdc311c854fd9efb53287071" - integrity sha512-IIuUzP4ee5rw7gtuA2mT7i/jXehl0OrdBMUSAruqixl5DUvBSWjPyFbS4zclVN+DNf75j+7RWMH8Q8BLfdvLeA== +matrix-js-sdk@6.0.0-rc.1: + version "6.0.0-rc.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-6.0.0-rc.1.tgz#afdee9d49fe0a1040d56fc1b5014e628cc15b5a4" + integrity sha512-m3xkRFmf6VLXxDVeHPrIWFp9tvc8lGIZSlJ/ObY+mdn4gIGFjV77A+3gcuMynj0yb6DJtkexPlqP2G9wmMyQuQ== dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From b7f2c7b813c3b41dd0f7ea03f0ec2433998a9404 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 30 Apr 2020 11:30:13 +0100 Subject: [PATCH 178/237] Prepare changelog for v2.5.0-rc.5 --- CHANGELOG.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 541992d4c4..b06db93b43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,49 @@ +Changes in [2.5.0-rc.5](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.5) (2020-04-30) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.4...v2.5.0-rc.5) + + * Upgrade to JS SDK 6.0.0-rc.1 + * Fix device verification toasts not disappearing + [\#4533](https://github.com/matrix-org/matrix-react-sdk/pull/4533) + * Allow resetting storage from the access dialog + [\#4526](https://github.com/matrix-org/matrix-react-sdk/pull/4526) + * Update toast copy again + [\#4530](https://github.com/matrix-org/matrix-react-sdk/pull/4530) + * Reduce maximum width of toasts & allow multiple lines + [\#4528](https://github.com/matrix-org/matrix-react-sdk/pull/4528) + * Treat sessions that are there when we log in as old + [\#4527](https://github.com/matrix-org/matrix-react-sdk/pull/4527) + * Update (bulk) unverified device toast copy + [\#4523](https://github.com/matrix-org/matrix-react-sdk/pull/4523) + * Make new device toasts appear above review toasts + [\#4520](https://github.com/matrix-org/matrix-react-sdk/pull/4520) + * Separate toasts for existing & new device verification + [\#4517](https://github.com/matrix-org/matrix-react-sdk/pull/4517) + * Aggregate device verify toasts + [\#4516](https://github.com/matrix-org/matrix-react-sdk/pull/4516) + * Fix set up encryption toast to use "set up" as action + [\#4515](https://github.com/matrix-org/matrix-react-sdk/pull/4515) + * Fix internal link styling in Security Settings + [\#4512](https://github.com/matrix-org/matrix-react-sdk/pull/4512) + * Don't enable e2ee when inviting a 3pid + [\#4513](https://github.com/matrix-org/matrix-react-sdk/pull/4513) + * only clear on continuations where the clear isn't done by SenderProfile + [\#4505](https://github.com/matrix-org/matrix-react-sdk/pull/4505) + * cap width of editable item list item to leave space for its X button + [\#4504](https://github.com/matrix-org/matrix-react-sdk/pull/4504) + * Add a link from settings / devices to your user profile + [\#4499](https://github.com/matrix-org/matrix-react-sdk/pull/4499) + * Make icon change in SetupEncryptionDialog + [\#4490](https://github.com/matrix-org/matrix-react-sdk/pull/4490) + * Remove invite only padlocks feature flag for release + [\#4488](https://github.com/matrix-org/matrix-react-sdk/pull/4488) + * Fix incorrect toast if security setup skipped + [\#4489](https://github.com/matrix-org/matrix-react-sdk/pull/4489) + * Revert "Update emojibase for fixed emoji codepoints and Emoji 13 support" + [\#4483](https://github.com/matrix-org/matrix-react-sdk/pull/4483) + * Fix recovery link on login verification flow + [\#4480](https://github.com/matrix-org/matrix-react-sdk/pull/4480) + Changes in [2.5.0-rc.4](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.4) (2020-04-23) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.3...v2.5.0-rc.4) From 619fbd6adc484d6b3487a0765706be884920696d Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 30 Apr 2020 11:30:14 +0100 Subject: [PATCH 179/237] v2.5.0-rc.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bb23fb6e80..d0ab225fa2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.5.0-rc.4", + "version": "2.5.0-rc.5", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 126b71dd30668158ab4a6274584ec06322f0cc2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Thu, 30 Apr 2020 10:51:56 +0000 Subject: [PATCH 180/237] Translated using Weblate (Estonian) Currently translated at 30.1% (692 of 2299 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 7fa5208f4b..bfa03e0dec 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -536,7 +536,7 @@ "Topic (optional)": "Teema (valikuline)", "Make this room public": "Tee see jututuba avalikuks", "Hide advanced": "Peida lisaseadistused", - "Show advanced": "Näita lisaseadistused", + "Show advanced": "Näita lisaseadistusi", "Server did not require any authentication": "Server ei nõudnud mitte mingisugust autentimist", "Recent Conversations": "Hiljutised vestlused", "Suggestions": "Soovitused", @@ -655,5 +655,40 @@ "Cannot add any more widgets": "Rohkem vidinaid ei õnnestu lisada", "The maximum permitted number of widgets have already been added to this room.": "Suurim lubatud vidinate arv on siia jututuppa juba lisatud.", "Join as voice or video.": "Liitu kas häälkõnega või videokõnega.", - "Ongoing conference call%(supportedText)s.": "Toimuv rühmavestlus %(supportedText)s." + "Ongoing conference call%(supportedText)s.": "Toimuv rühmavestlus %(supportedText)s.", + "Advanced": "Teave arendajatele", + "Gets or sets the room topic": "Otsib või määrab jututoa teema", + "Sets the room name": "Määrab jututoa nime", + "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s eemaldas jututoa nime.", + "%(senderDisplayName)s changed the room name from %(oldRoomName)s to %(newRoomName)s.": "%(senderDisplayName)s muutis jututoa vana nime %(oldRoomName)s uueks nimeks %(newRoomName)s.", + "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s muutis jututoa nimeks %(roomName)s.", + "Show info about bridges in room settings": "Näita jututoa seadistustes teavet võrgusildade kohta", + "Upload": "Lae üles", + "Save": "Salvesta", + "General": "Üldist", + "Notifications": "Teavitused", + "Security & Privacy": "Turvalisus ja privaatsus", + "No Audio Outputs detected": "Ei leidnud ühtegi heliväljundit", + "No Microphones detected": "Ei leidnud ühtegi mikrofoni", + "No Webcams detected": "Ei leidnud ühtegi veebikaamerat", + "Default Device": "Vaikimisi seade", + "Audio Output": "Heliväljund", + "Microphone": "Mikrofon", + "Camera": "Kaamera", + "Voice & Video": "Heli ja video", + "This room is not accessible by remote Matrix servers": "See jututuba ei ole leitav teiste Matrix'i serverite jaoks", + "Upgrade this room to the recommended room version": "Uuenda see jututoa versioon soovitatud versioonini", + "View older messages in %(roomName)s.": "Näita vanemat tüüpi sõnumeid jututoas %(roomName)s.", + "Room information": "Info jututoa kohta", + "Internal room ID:": "Jututoa sisemine tunnus:", + "Room version": "Jututoa versioon", + "Room version:": "Jututoa versioon:", + "Developer options": "Valikud arendajale", + "Open Devtools": "Ava arendusvahendid", + "Change room name": "Muuda jututoa nimi", + "Roles & Permissions": "Rollid ja õigused", + "Room Name": "Jututoa nimi", + "Room Topic": "Jututoa teema", + "Room Settings - %(roomName)s": "Jututoa seadistused - %(roomName)s", + "General failure": "Üldine viga" } From d3ce4072d481cf935025fbc4f58ba53edbdcaf44 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 30 Apr 2020 15:41:49 +0100 Subject: [PATCH 181/237] Only show key backup reminder when confirmed by server to be missing The key backup reminder was being shown too eagerly in cases when we hadn't actually checked with the homeserver on key backup status. This changes to only show the reminder when we're sure a backup doesn't exist. Fixes https://github.com/vector-im/riot-web/issues/13404 --- src/components/structures/RoomView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 179e0aa2e9..4f9c0a7c91 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -1768,7 +1768,7 @@ export default createReactClass({ const showRoomRecoveryReminder = ( SettingsStore.getValue("showRoomRecoveryReminder") && this.context.isRoomEncrypted(this.state.room.roomId) && - !this.context.getKeyBackupEnabled() + this.context.getKeyBackupEnabled() === false ); const hiddenHighlightCount = this._getHiddenHighlightCount(); From 3240b3bd60513e8c6faa517f981f11b07b622a84 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 30 Apr 2020 16:09:38 +0100 Subject: [PATCH 182/237] Add device name to unverified session toast --- src/components/views/toasts/UnverifiedSessionToast.js | 6 +++++- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index afabf69178..38cd9f20df 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -49,9 +49,13 @@ export default class UnverifiedSessionToast extends React.PureComponent { }; render() { + const cli = MatrixClientPeg.get(); + const device = cli.getStoredDevice(cli.getUserId(), this.props.deviceId); + return (
- {_t("Verify the new login accessing your account & messages")} + {_t( + "Verify the new login accessing your account: %(name)s", { name: device.getDisplayName()})}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 4be143c523..3b432c410d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -568,7 +568,7 @@ "Set up": "Set up", "Upgrade": "Upgrade", "Verify": "Verify", - "Verify the new login accessing your account & messages": "Verify the new login accessing your account & messages", + "Verify the new login accessing your account: %(name)s": "Verify the new login accessing your account: %(name)s", "From %(deviceName)s (%(deviceId)s)": "From %(deviceName)s (%(deviceId)s)", "Decline (%(counter)s)": "Decline (%(counter)s)", "Accept to continue:": "Accept to continue:", From 6ef5b788065ebe6a8b4b09ffb69275a3eafb50d0 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 30 Apr 2020 16:09:38 +0100 Subject: [PATCH 183/237] Add device name to unverified session toast --- src/components/views/toasts/UnverifiedSessionToast.js | 6 +++++- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/views/toasts/UnverifiedSessionToast.js b/src/components/views/toasts/UnverifiedSessionToast.js index afabf69178..38cd9f20df 100644 --- a/src/components/views/toasts/UnverifiedSessionToast.js +++ b/src/components/views/toasts/UnverifiedSessionToast.js @@ -49,9 +49,13 @@ export default class UnverifiedSessionToast extends React.PureComponent { }; render() { + const cli = MatrixClientPeg.get(); + const device = cli.getStoredDevice(cli.getUserId(), this.props.deviceId); + return (
- {_t("Verify the new login accessing your account & messages")} + {_t( + "Verify the new login accessing your account: %(name)s", { name: device.getDisplayName()})}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 861dc24707..5544e3a8b1 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -565,7 +565,7 @@ "Set up": "Set up", "Upgrade": "Upgrade", "Verify": "Verify", - "Verify the new login accessing your account & messages": "Verify the new login accessing your account & messages", + "Verify the new login accessing your account: %(name)s": "Verify the new login accessing your account: %(name)s", "From %(deviceName)s (%(deviceId)s)": "From %(deviceName)s (%(deviceId)s)", "Decline (%(counter)s)": "Decline (%(counter)s)", "Accept to continue:": "Accept to continue:", From fb2b37f0fe06044bc88ad9df1ef7914d859ac877 Mon Sep 17 00:00:00 2001 From: SophieKrueger Date: Thu, 30 Apr 2020 14:59:47 +0000 Subject: [PATCH 184/237] Translated using Weblate (German) Currently translated at 77.8% (1791 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index e928282fa8..f89958376b 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -1855,5 +1855,8 @@ "Enter your recovery passphrase a second time to confirm it.": "Gib deine Wiederherstellungspassphrase zur Bestätigung erneut ein.", "Confirm your recovery passphrase": "Bestätige deine Wiederherstellungspassphrase", "Confirm recovery passphrase": "Bestätige die Wiederherstellungspassphrase", - "Please enter your recovery passphrase a second time to confirm.": "Bitte gib deine Wiederherstellungspassphrase ein zweites Mal ein um sie zu bestätigen." + "Please enter your recovery passphrase a second time to confirm.": "Bitte gib deine Wiederherstellungspassphrase ein zweites Mal ein um sie zu bestätigen.", + "Review where you’re logged in": "Überprüfe, wo du eingeloggt bist", + "New login. Was this you?": "Neue Anmeldung. Warst du das?", + "Please supply a widget URL or embed code": "Bitte gib eine Widget-URL oder einen Einbettungscode an" } From fced07682ea0d5c632bcfc6126116d3c32b76590 Mon Sep 17 00:00:00 2001 From: "@a2sc:matrix.org" Date: Thu, 30 Apr 2020 15:04:31 +0000 Subject: [PATCH 185/237] Translated using Weblate (German) Currently translated at 77.8% (1791 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index f89958376b..25f498b4e9 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -1858,5 +1858,8 @@ "Please enter your recovery passphrase a second time to confirm.": "Bitte gib deine Wiederherstellungspassphrase ein zweites Mal ein um sie zu bestätigen.", "Review where you’re logged in": "Überprüfe, wo du eingeloggt bist", "New login. Was this you?": "Neue Anmeldung. Warst du das?", - "Please supply a widget URL or embed code": "Bitte gib eine Widget-URL oder einen Einbettungscode an" + "Please supply a widget URL or embed code": "Bitte gib eine Widget-URL oder einen Einbettungscode an", + "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains.": "Gibt den per SMS an +%(msisdn)s gesendeten Bestätigungscode ein.", + "Someone is using an unknown session": "Jemand verwendet eine unbekannte Sitzung", + "This room is end-to-end encrypted": "Dieser Raum ist Ende-zu-Ende verschlüsselt" } From 834be6f796e4052289b3950f9d8c3a2c4793b92c Mon Sep 17 00:00:00 2001 From: "@a2sc:matrix.org" Date: Thu, 30 Apr 2020 16:02:42 +0000 Subject: [PATCH 186/237] Translated using Weblate (German) Currently translated at 77.8% (1792 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 25f498b4e9..083ca396fc 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -1861,5 +1861,6 @@ "Please supply a widget URL or embed code": "Bitte gib eine Widget-URL oder einen Einbettungscode an", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains.": "Gibt den per SMS an +%(msisdn)s gesendeten Bestätigungscode ein.", "Someone is using an unknown session": "Jemand verwendet eine unbekannte Sitzung", - "This room is end-to-end encrypted": "Dieser Raum ist Ende-zu-Ende verschlüsselt" + "This room is end-to-end encrypted": "Dieser Raum ist Ende-zu-Ende verschlüsselt", + "You are not subscribed to any lists": "Du hast keine Listen abonniert" } From 124740a63c509a61351be0bb216de69111b653ad Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 30 Apr 2020 22:08:00 +0100 Subject: [PATCH 187/237] Wait for user to be verified in e2e setup Wait for our user to become verified and cross-signing to be ready before declaring that we're finsihed, otherwise we could end up prompting the user to verify again if we just wait for the verification itself to complete. Fixes part of https://github.com/vector-im/riot-web/issues/13464 --- src/stores/SetupEncryptionStore.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/stores/SetupEncryptionStore.js b/src/stores/SetupEncryptionStore.js index cbbbefb129..031c28ddb1 100644 --- a/src/stores/SetupEncryptionStore.js +++ b/src/stores/SetupEncryptionStore.js @@ -17,6 +17,7 @@ limitations under the License. import EventEmitter from 'events'; import { MatrixClientPeg } from '../MatrixClientPeg'; import { accessSecretStorage, AccessCancelledError } from '../CrossSigningManager'; +import { PHASE_DONE as VERIF_PHASE_DONE } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; export const PHASE_INTRO = 0; export const PHASE_BUSY = 1; @@ -39,6 +40,7 @@ export class SetupEncryptionStore extends EventEmitter { this.verificationRequest = null; this.backupInfo = null; MatrixClientPeg.get().on("crypto.verification.request", this.onVerificationRequest); + MatrixClientPeg.get().on('userTrustStatusChanged', this._onUserTrustStatusChanged); } stop() { @@ -51,6 +53,7 @@ export class SetupEncryptionStore extends EventEmitter { } if (MatrixClientPeg.get()) { MatrixClientPeg.get().removeListener("crypto.verification.request", this.onVerificationRequest); + MatrixClientPeg.get().removeListener('userTrustStatusChanged', this._onUserTrustStatusChanged); } } @@ -102,6 +105,15 @@ export class SetupEncryptionStore extends EventEmitter { } } + _onUserTrustStatusChanged = async (userId) => { + if (userId !== MatrixClientPeg.get().getUserId()) return; + const crossSigningReady = await MatrixClientPeg.get().isCrossSigningReady(); + if (crossSigningReady) { + this.phase = PHASE_DONE; + this.emit("update"); + } + } + onVerificationRequest = async (request) => { if (request.otherUserId !== MatrixClientPeg.get().getUserId()) return; @@ -119,6 +131,14 @@ export class SetupEncryptionStore extends EventEmitter { this.verificationRequest.off("change", this.onVerificationRequestChange); this.verificationRequest = null; this.emit("update"); + } else if (this.verificationRequest.phase === VERIF_PHASE_DONE) { + this.verificationRequest.off("change", this.onVerificationRequestChange); + this.verificationRequest = null; + // At this point, the verification has finished, we just need to wait for + // cross signing to be ready to use, so wait for the user trust status to + // change. + this.phase = PHASE_BUSY; + this.emit("update"); } } From d241ceea56737c1acac70ddada986eff7fb8bc98 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 30 Apr 2020 22:21:48 +0100 Subject: [PATCH 188/237] Clear more state in DeviceListener Especially the devices at start, otherwise they'll just be wrong if you log in after logging out. --- src/DeviceListener.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index d948911d7c..d2ba8219db 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -78,6 +78,8 @@ export default class DeviceListener { this._dismissedThisDeviceToast = false; this._keyBackupInfo = null; this._keyBackupFetchedAt = null; + this._ourDeviceIdsAtStart = null; + this._displayingToastsForDeviceIds = new Set(); } /** From 6ca9630a3a51486340e9cb5504d8da06b2eb88d3 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Fri, 1 May 2020 02:10:28 +0000 Subject: [PATCH 189/237] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2302 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/zh_Hant/ --- src/i18n/strings/zh_Hant.json | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 9b0f4ccc5f..5ea7e7a413 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -722,7 +722,7 @@ "Everyone": "每個人", "Fetching third party location failed": "抓取第三方位置失敗", "A new version of Riot is available.": "Riot 釋出了新版本。", - "I understand the risks and wish to continue": "我了解這些風險並願意繼續", + "I understand the risks and wish to continue": "我了解風險並希望繼續", "Send Account Data": "傳送帳號資料", "Advanced notification settings": "進階通知設定", "Uploading report": "上傳報告", @@ -1351,7 +1351,7 @@ "Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. Learn more about encryption.": "一旦啟用,聊天室的加密就不能停用了。在已加密的聊天室裡傳送的訊息無法被伺服器看見,僅能被聊天室的參與者看到。啟用加密可能會讓許多機器人與橋接運作不正常。取得更多關於加密的資訊。", "Power level": "權力等級", "Want more than a community? Get your own server": "想要的不只是社群?架設您自己的伺服器", - "Please install Chrome, Firefox, or Safari for the best experience.": "請安裝 ChromeFirefoxSafari 以獲得最佳體驗。", + "Please install Chrome, Firefox, or Safari for the best experience.": "請安裝 ChromeFirefoxSafari 以取得最佳體驗。", "Warning: Upgrading a room will not automatically migrate room members to the new version of the room. We'll post a link to the new room in the old version of the room - room members will have to click this link to join the new room.": "警告:升級聊天室不會自動將聊天室成員遷移到新版的聊天室。我們會在舊版聊天室中貼出到新聊天室的連結,聊天室成員必須點選此連結以加入新聊天室。", "Adds a custom widget by URL to the room": "透過 URL 新增自訂小工具到聊天室", "Please supply a https:// or http:// widget URL": "請提供 https:// 或 http:// 小工具 URL", @@ -2409,5 +2409,12 @@ "Verify your other sessions": "驗證您其他的工作階段", "New login. Was this you?": "新登入。這是您嗎?", "Unverified sessions currently have access to your account & messages": "未驗證的工作階段目前正在存取您的帳號與訊息", - "Verify the identity of the new login accessing your account & messages": "驗證存取您帳號與訊息的新登入身份" + "Verify the identity of the new login accessing your account & messages": "驗證存取您帳號與訊息的新登入身份", + "Verify all your sessions to ensure your account & messages are safe": "驗證您所有的工作階段以確保您的帳號與訊息是安全的", + "Verify the new login accessing your account: %(name)s": "驗證正在存取您帳號的新登入:%(name)s", + "Restoring keys from backup": "從備份還原金鑰", + "Fetching keys from server...": "正在從伺服器擷取金鑰……", + "%(completed)s of %(total)s keys restored": "%(total)s 中的 %(completed)s 金鑰已復原", + "Keys restored": "金鑰已復原", + "Successfully restored %(sessionCount)s keys": "成功復原 %(sessionCount)s 金鑰" } From 36cf07c975950ee4a59a7d08f1bf61cb50907ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20C?= Date: Fri, 1 May 2020 06:45:20 +0000 Subject: [PATCH 190/237] Translated using Weblate (French) Currently translated at 100.0% (2302 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index aa873c386d..d3c671a898 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -2411,5 +2411,11 @@ "Unverified sessions currently have access to your account & messages": "Des sessions non vérifiées ont accès à votre compte et messages", "Verify the identity of the new login accessing your account & messages": "Vérifiez l'identité de la nouvelle connexion accédant à votre compte et messages", "New login. Was this you?": "Nouvelle connexion. Était-ce vous ?", - "Verify all your sessions to ensure your account & messages are safe": "Vérifiez toutes vos sessions pour vous assurer que votre compte et messages sont sécurisés" + "Verify all your sessions to ensure your account & messages are safe": "Vérifiez toutes vos sessions pour vous assurer que votre compte et messages sont sécurisés", + "Verify the new login accessing your account: %(name)s": "Vérifiez la nouvelle connexion accédant à votre compte : %(name)s", + "Restoring keys from backup": "Restauration des clés depuis la sauvegarde", + "Fetching keys from server...": "Récupération des clés depuis le serveur…", + "%(completed)s of %(total)s keys restored": "%(completed)s clés sur %(total)s restaurées", + "Keys restored": "Clés restaurées", + "Successfully restored %(sessionCount)s keys": "%(sessionCount)s clés ont été restaurées avec succès" } From a291f6c2c5b293a164cd2bb2785cee760a0a8903 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 30 Apr 2020 22:08:00 +0100 Subject: [PATCH 191/237] Wait for user to be verified in e2e setup Wait for our user to become verified and cross-signing to be ready before declaring that we're finsihed, otherwise we could end up prompting the user to verify again if we just wait for the verification itself to complete. Fixes part of https://github.com/vector-im/riot-web/issues/13464 --- src/stores/SetupEncryptionStore.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/stores/SetupEncryptionStore.js b/src/stores/SetupEncryptionStore.js index cbbbefb129..031c28ddb1 100644 --- a/src/stores/SetupEncryptionStore.js +++ b/src/stores/SetupEncryptionStore.js @@ -17,6 +17,7 @@ limitations under the License. import EventEmitter from 'events'; import { MatrixClientPeg } from '../MatrixClientPeg'; import { accessSecretStorage, AccessCancelledError } from '../CrossSigningManager'; +import { PHASE_DONE as VERIF_PHASE_DONE } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; export const PHASE_INTRO = 0; export const PHASE_BUSY = 1; @@ -39,6 +40,7 @@ export class SetupEncryptionStore extends EventEmitter { this.verificationRequest = null; this.backupInfo = null; MatrixClientPeg.get().on("crypto.verification.request", this.onVerificationRequest); + MatrixClientPeg.get().on('userTrustStatusChanged', this._onUserTrustStatusChanged); } stop() { @@ -51,6 +53,7 @@ export class SetupEncryptionStore extends EventEmitter { } if (MatrixClientPeg.get()) { MatrixClientPeg.get().removeListener("crypto.verification.request", this.onVerificationRequest); + MatrixClientPeg.get().removeListener('userTrustStatusChanged', this._onUserTrustStatusChanged); } } @@ -102,6 +105,15 @@ export class SetupEncryptionStore extends EventEmitter { } } + _onUserTrustStatusChanged = async (userId) => { + if (userId !== MatrixClientPeg.get().getUserId()) return; + const crossSigningReady = await MatrixClientPeg.get().isCrossSigningReady(); + if (crossSigningReady) { + this.phase = PHASE_DONE; + this.emit("update"); + } + } + onVerificationRequest = async (request) => { if (request.otherUserId !== MatrixClientPeg.get().getUserId()) return; @@ -119,6 +131,14 @@ export class SetupEncryptionStore extends EventEmitter { this.verificationRequest.off("change", this.onVerificationRequestChange); this.verificationRequest = null; this.emit("update"); + } else if (this.verificationRequest.phase === VERIF_PHASE_DONE) { + this.verificationRequest.off("change", this.onVerificationRequestChange); + this.verificationRequest = null; + // At this point, the verification has finished, we just need to wait for + // cross signing to be ready to use, so wait for the user trust status to + // change. + this.phase = PHASE_BUSY; + this.emit("update"); } } From 4377e4161f5aa8ed98b9f2ebfbe9192d77797767 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 30 Apr 2020 22:21:48 +0100 Subject: [PATCH 192/237] Clear more state in DeviceListener Especially the devices at start, otherwise they'll just be wrong if you log in after logging out. --- src/DeviceListener.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/DeviceListener.js b/src/DeviceListener.js index d948911d7c..d2ba8219db 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -78,6 +78,8 @@ export default class DeviceListener { this._dismissedThisDeviceToast = false; this._keyBackupInfo = null; this._keyBackupFetchedAt = null; + this._ourDeviceIdsAtStart = null; + this._displayingToastsForDeviceIds = new Set(); } /** From bc6aeef8241a5d7e2ace44a7ddaa82230b1b83db Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 1 May 2020 10:58:00 +0100 Subject: [PATCH 193/237] Guard against race when waiting for cross-signing to be ready Check to see if cross-signing is already set up after a verification is done to make sure it doesn't race and we end up waiting forever. --- src/stores/SetupEncryptionStore.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/stores/SetupEncryptionStore.js b/src/stores/SetupEncryptionStore.js index 031c28ddb1..ae1f998b02 100644 --- a/src/stores/SetupEncryptionStore.js +++ b/src/stores/SetupEncryptionStore.js @@ -126,7 +126,7 @@ export class SetupEncryptionStore extends EventEmitter { this.emit("update"); } - onVerificationRequestChange = () => { + onVerificationRequestChange = async () => { if (this.verificationRequest.cancelled) { this.verificationRequest.off("change", this.onVerificationRequestChange); this.verificationRequest = null; @@ -136,8 +136,9 @@ export class SetupEncryptionStore extends EventEmitter { this.verificationRequest = null; // At this point, the verification has finished, we just need to wait for // cross signing to be ready to use, so wait for the user trust status to - // change. - this.phase = PHASE_BUSY; + // change (or change to DONE if it's already ready). + const crossSigningReady = await MatrixClientPeg.get().isCrossSigningReady(); + this.phase = crossSigningReady ? PHASE_DONE : PHASE_BUSY; this.emit("update"); } } From 8a02e064bd98569cdadfd52b9cca15fbf39e62cb Mon Sep 17 00:00:00 2001 From: Zoe Date: Fri, 1 May 2020 11:03:48 +0100 Subject: [PATCH 194/237] Don't erase password confirm on registration error Fixes: https://github.com/vector-im/riot-web/issues/11395 Problem here was that the form gets re-mounted but there wasn't a facility to preserve the password confirmation field. Since the form validates that the passwords are equal, if we mount with a password supplied we just copy it over. --- src/components/views/auth/RegistrationForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/auth/RegistrationForm.js b/src/components/views/auth/RegistrationForm.js index f1624bc9e5..2a79bb8588 100644 --- a/src/components/views/auth/RegistrationForm.js +++ b/src/components/views/auth/RegistrationForm.js @@ -76,7 +76,7 @@ export default createReactClass({ email: this.props.defaultEmail || "", phoneNumber: this.props.defaultPhoneNumber || "", password: this.props.defaultPassword || "", - passwordConfirm: "", + passwordConfirm: this.props.defaultPassword || "", passwordComplexity: null, passwordSafe: false, }; From a04564d1e37c2f1b265154ff6c678ef0e25781fc Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 1 May 2020 10:58:00 +0100 Subject: [PATCH 195/237] Guard against race when waiting for cross-signing to be ready Check to see if cross-signing is already set up after a verification is done to make sure it doesn't race and we end up waiting forever. --- src/stores/SetupEncryptionStore.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/stores/SetupEncryptionStore.js b/src/stores/SetupEncryptionStore.js index 031c28ddb1..ae1f998b02 100644 --- a/src/stores/SetupEncryptionStore.js +++ b/src/stores/SetupEncryptionStore.js @@ -126,7 +126,7 @@ export class SetupEncryptionStore extends EventEmitter { this.emit("update"); } - onVerificationRequestChange = () => { + onVerificationRequestChange = async () => { if (this.verificationRequest.cancelled) { this.verificationRequest.off("change", this.onVerificationRequestChange); this.verificationRequest = null; @@ -136,8 +136,9 @@ export class SetupEncryptionStore extends EventEmitter { this.verificationRequest = null; // At this point, the verification has finished, we just need to wait for // cross signing to be ready to use, so wait for the user trust status to - // change. - this.phase = PHASE_BUSY; + // change (or change to DONE if it's already ready). + const crossSigningReady = await MatrixClientPeg.get().isCrossSigningReady(); + this.phase = crossSigningReady ? PHASE_DONE : PHASE_BUSY; this.emit("update"); } } From d4005b6238f85cfa11d570338dcd63018b7673b5 Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Fri, 1 May 2020 10:34:30 +0000 Subject: [PATCH 196/237] Translated using Weblate (Bulgarian) Currently translated at 86.3% (1987 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/bg/ --- src/i18n/strings/bg.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/bg.json b/src/i18n/strings/bg.json index 7a5edcc381..46a4d811e5 100644 --- a/src/i18n/strings/bg.json +++ b/src/i18n/strings/bg.json @@ -2043,5 +2043,11 @@ "Connect this session to Key Backup": "Свържи тази сесия с резервно копие на ключовете", "Backup has a signature from unknown session with ID %(deviceId)s": "Резервното копие има подпис от непозната сесия с идентификатор %(deviceId)s", "Backup has a valid signature from this session": "Резервното копие има валиден подпис от тази сесия", - "Backup has an invalid signature from this session": "Резервното копие има невалиден подпис от тази сесия" + "Backup has an invalid signature from this session": "Резервното копие има невалиден подпис от тази сесия", + "Verify all your sessions to ensure your account & messages are safe": "Верифицирайте всички свой сесии за да подсигурите, че профила и съобщенията ви са защитени", + "Verify the new login accessing your account: %(name)s": "Верифицирайте новия вход достъпващ профила ви: %(name)s", + "Backup has a valid signature from verified session ": "Резервното копие има валиден подпис от потвърдена сесия ", + "Backup has a valid signature from unverified session ": "Резервното копие има валиден подпис от непотвърдена сесия ", + "Backup has an invalid signature from verified session ": "Резервното копие има невалиден подпис от потвърдена сесия ", + "Backup has an invalid signature from unverified session ": "Резервното копие има невалиден подпис от непотвърдена сесия " } From a89d3f986d57fe9327b97858210ab828a9cd8a04 Mon Sep 17 00:00:00 2001 From: random Date: Fri, 1 May 2020 09:45:15 +0000 Subject: [PATCH 197/237] Translated using Weblate (Italian) Currently translated at 100.0% (2302 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/it/ --- src/i18n/strings/it.json | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index bb2bf3c95b..78abb0e53e 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -780,7 +780,7 @@ "Explore Account Data": "Esplora dati account", "All messages (noisy)": "Tutti i messaggi (rumoroso)", "Saturday": "Sabato", - "I understand the risks and wish to continue": "Sono consapevole dei rischi e vorrei continuare", + "I understand the risks and wish to continue": "Capisco i rischi e desidero continuare", "Direct Chat": "Chat Diretta", "The server may be unavailable or overloaded": "Il server potrebbe essere non disponibile o sovraccarico", "Reject": "Rifiuta", @@ -1321,7 +1321,7 @@ "Premium hosting for organisations Learn more": "Hosting premium per organizzazioni Maggior informazioni", "Other": "Altro", "Find other public servers or use a custom server": "Trova altri server pubblici o usane uno personale", - "Please install Chrome, Firefox, or Safari for the best experience.": "Ti suggeriamo di installare Chrome, Firefox o Safari per la migliore esperienza.", + "Please install Chrome, Firefox, or Safari for the best experience.": "Installa Chrome, Firefox, o Safari per una migliore esperienza.", "Couldn't load page": "Caricamento pagina fallito", "Want more than a community? Get your own server": "Vuoi più di una comunità? Ottieni il tuo server personale", "This homeserver does not support communities": "Questo homeserver non supporta le comunità", @@ -2404,5 +2404,13 @@ "Review where you’re logged in": "Controlla dove hai fatto l'accesso", "Verify your other sessions": "Verifica le tue altre sessioni", "Where you’re logged in": "Dove hai fatto l'accesso", - "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Gestisci i nomi e disconnettiti dalle tue sessioni sotto o verificale nel tuo profilo utente." + "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Gestisci i nomi e disconnettiti dalle tue sessioni sotto o verificale nel tuo profilo utente.", + "New login. Was this you?": "Nuovo accesso. Eri tu?", + "Verify all your sessions to ensure your account & messages are safe": "Verifica tutte le tue sessioni per assicurarti che il tuo account e i messaggi siano protetti", + "Verify the new login accessing your account: %(name)s": "Verifica il nuovo accesso entrando nel tuo account: %(name)s", + "Restoring keys from backup": "Ripristino delle chiavi dal backup", + "Fetching keys from server...": "Ricezione delle chiavi dal server...", + "%(completed)s of %(total)s keys restored": "%(completed)s di %(total)s chiavi ripristinate", + "Keys restored": "Chiavi ripristinate", + "Successfully restored %(sessionCount)s keys": "Ripristinate %(sessionCount)s chiavi correttamente" } From b5cb912cfd98f9d3ba6bf261acf2f87007425b6d Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Fri, 1 May 2020 16:24:59 +0100 Subject: [PATCH 198/237] Upgrade matrix-js-sdk to 6.0.0-rc.2 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d0ab225fa2..4ed79c0c86 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "6.0.0-rc.1", + "matrix-js-sdk": "6.0.0-rc.2", "minimist": "^1.2.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index 60ab9c225b..ae0a218e0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5715,10 +5715,10 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -matrix-js-sdk@6.0.0-rc.1: - version "6.0.0-rc.1" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-6.0.0-rc.1.tgz#afdee9d49fe0a1040d56fc1b5014e628cc15b5a4" - integrity sha512-m3xkRFmf6VLXxDVeHPrIWFp9tvc8lGIZSlJ/ObY+mdn4gIGFjV77A+3gcuMynj0yb6DJtkexPlqP2G9wmMyQuQ== +matrix-js-sdk@6.0.0-rc.2: + version "6.0.0-rc.2" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-6.0.0-rc.2.tgz#56eb438458cb59cf18bbd6126d72029dc728659f" + integrity sha512-osW5GIOAcCpY/wCxct9RMxRZhodkVBdEDVZuQm2nstKDLGafl5oxAit2LAz9g0ymv+16LBp8XbThM2GWa2lj2Q== dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From 340dd4415d2c67ad71d9c37e8488730c170fb0a8 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Fri, 1 May 2020 16:30:10 +0100 Subject: [PATCH 199/237] Prepare changelog for v2.5.0-rc.6 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b06db93b43..df4a934a07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +Changes in [2.5.0-rc.6](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.6) (2020-05-01) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.5...v2.5.0-rc.6) + + * Upgrade to JS SDK 6.0.0-rc.2 + * Wait for user to be verified in e2e setup + [\#4538](https://github.com/matrix-org/matrix-react-sdk/pull/4538) + * Add device name to unverified session toast + [\#4536](https://github.com/matrix-org/matrix-react-sdk/pull/4536) + Changes in [2.5.0-rc.5](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.5) (2020-04-30) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.4...v2.5.0-rc.5) From ccb6d91988afe4bb4cf28a3b607e473fe043e734 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Fri, 1 May 2020 16:30:10 +0100 Subject: [PATCH 200/237] v2.5.0-rc.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4ed79c0c86..19fa03b3d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.5.0-rc.5", + "version": "2.5.0-rc.6", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 0b4a3d36cd1d20d8cb86eaadc28879ff438c6160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Fri, 1 May 2020 21:04:13 +0000 Subject: [PATCH 201/237] Translated using Weblate (Estonian) Currently translated at 30.6% (704 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index bfa03e0dec..764854fb53 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -690,5 +690,17 @@ "Room Name": "Jututoa nimi", "Room Topic": "Jututoa teema", "Room Settings - %(roomName)s": "Jututoa seadistused - %(roomName)s", - "General failure": "Üldine viga" + "General failure": "Üldine viga", + "Where you’re logged in": "Kus sa oled võrku loginud", + "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Halda alljärgnevas oma sessioonide nimesid, logi neist välja või verifitseeri neid oma kasutajaprofiilis.", + "A session's public name is visible to people you communicate with": "Sessiooni avalik nimi on nähtav neile, kellega sa suhtled", + "Riot collects anonymous analytics to allow us to improve the application.": "Võimaldamaks meil rakendust parandada kogub Riot anonüümset analüütikat.", + "Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "Privaatsus on meile oluline ning seega me ei kogu ei isiklikke ega isikustatavaid andmeid.", + "Learn more about how we use analytics.": "Loe lisaks kuidas me kasutama analüütikat.", + "No media permissions": "Meediaõigused puuduvad", + "You may need to manually permit Riot to access your microphone/webcam": "Sa võib-olla pead andma Riot'ile loa mikrofoni ja veebikaamera kasutamiseks", + "Missing media permissions, click the button below to request.": "Meediaga seotud õigused puuduvad. Nende nõutamiseks klõpsi järgnevat nuppu.", + "Request media permissions": "Nõuta meediaõigusi", + "Frequently Used": "Enamkasutatud", + "Smileys & People": "Vigurnäod ja inimesed" } From f6185c29f1addbf2de0029c9ea2abe31c18ef38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Fri, 1 May 2020 21:47:30 +0000 Subject: [PATCH 202/237] Translated using Weblate (Estonian) Currently translated at 31.3% (721 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 764854fb53..334a20f104 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -702,5 +702,22 @@ "Missing media permissions, click the button below to request.": "Meediaga seotud õigused puuduvad. Nende nõutamiseks klõpsi järgnevat nuppu.", "Request media permissions": "Nõuta meediaõigusi", "Frequently Used": "Enamkasutatud", - "Smileys & People": "Vigurnäod ja inimesed" + "Smileys & People": "Vigurnäod ja inimesed", + "Animals & Nature": "Loomad ja loodus", + "Food & Drink": "Toit ja jook", + "Activities": "Tegevused", + "Travel & Places": "Reisimine ja kohad", + "Objects": "Esemed", + "Symbols": "Sümbolid", + "Flags": "Lipud", + "Quick Reactions": "Reageeri lennult", + "Unknown Address": "Teadmata aadress", + "Any of the following data may be shared:": "Järgnevaid andmeid võib jagada:", + "Your display name": "Sinu kuvatav nimi", + "Your avatar URL": "Sinu avatari aadress", + "Your user ID": "Sinu kasutajatunnus", + "Your theme": "Sinu teema", + "Riot URL": "Riot'i aadress", + "Room ID": "Jututoa tunnus", + "Widget ID": "Vidina tunnus" } From 01131a403657e0025b8506d3a3e14b819d01bd51 Mon Sep 17 00:00:00 2001 From: Agusti Bau Date: Sat, 2 May 2020 12:55:56 +0200 Subject: [PATCH 203/237] removed unnecessary divs --- src/components/views/elements/DNDTagTile.js | 4 +--- src/components/views/elements/TagTile.js | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/components/views/elements/DNDTagTile.js b/src/components/views/elements/DNDTagTile.js index 5a96f01d9f..2a6664d271 100644 --- a/src/components/views/elements/DNDTagTile.js +++ b/src/components/views/elements/DNDTagTile.js @@ -43,7 +43,6 @@ export default function DNDTagTile(props) { type="draggable-TagTile" > { (provided, snapshot) => ( -
-
{ provided.placeholder } -
+
) } {contextMenu} diff --git a/src/components/views/elements/TagTile.js b/src/components/views/elements/TagTile.js index 023d9cca93..848dc797a2 100644 --- a/src/components/views/elements/TagTile.js +++ b/src/components/views/elements/TagTile.js @@ -159,8 +159,7 @@ export default createReactClass({ const AccessibleTooltipButton = sdk.getComponent("elements.AccessibleTooltipButton"); - return
- - -
; + ; }, }); From fc5a5c411f41c004fae10241f3dc4d4c013e307a Mon Sep 17 00:00:00 2001 From: Agusti Bau Date: Sat, 2 May 2020 13:09:04 +0200 Subject: [PATCH 204/237] provided.placeholder has no effect --- src/components/views/elements/DNDTagTile.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/elements/DNDTagTile.js b/src/components/views/elements/DNDTagTile.js index 2a6664d271..b017704e70 100644 --- a/src/components/views/elements/DNDTagTile.js +++ b/src/components/views/elements/DNDTagTile.js @@ -54,7 +54,6 @@ export default function DNDTagTile(props) { menuDisplayed={menuDisplayed} openMenu={openMenu} /> - { provided.placeholder }
) } From a84a3c4780bece5778d9e4fabcb5856ec284928b Mon Sep 17 00:00:00 2001 From: Agusti Bau Date: Sat, 2 May 2020 13:12:31 +0200 Subject: [PATCH 205/237] hide badge when context menu is open --- src/components/views/elements/TagTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/TagTile.js b/src/components/views/elements/TagTile.js index 848dc797a2..0f98971198 100644 --- a/src/components/views/elements/TagTile.js +++ b/src/components/views/elements/TagTile.js @@ -143,7 +143,7 @@ export default createReactClass({ const badge = TagOrderStore.getGroupBadge(this.props.tag); let badgeElement; - if (badge && !this.state.hover) { + if (badge && !this.state.hover && !this.props.menuDisplayed) { const badgeClasses = classNames({ "mx_TagTile_badge": true, "mx_TagTile_badgeHighlight": badge.highlight, From baa9cd8078ef277f84714beda7a4afd4336a1a3c Mon Sep 17 00:00:00 2001 From: Agusti Bau Date: Sat, 2 May 2020 13:25:18 +0200 Subject: [PATCH 206/237] formatted files --- src/components/views/elements/DNDTagTile.js | 50 ++++++++++----------- src/components/views/elements/TagTile.js | 50 ++++++++++----------- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/components/views/elements/DNDTagTile.js b/src/components/views/elements/DNDTagTile.js index b017704e70..67572d4508 100644 --- a/src/components/views/elements/DNDTagTile.js +++ b/src/components/views/elements/DNDTagTile.js @@ -19,7 +19,7 @@ import TagTile from './TagTile'; import React from 'react'; import { Draggable } from 'react-beautiful-dnd'; -import {ContextMenu, toRightOf, useContextMenu} from "../../structures/ContextMenu"; +import { ContextMenu, toRightOf, useContextMenu } from "../../structures/ContextMenu"; import * as sdk from '../../../index'; export default function DNDTagTile(props) { @@ -35,28 +35,28 @@ export default function DNDTagTile(props) { ); } - return
- - { (provided, snapshot) => ( -
- -
- ) } -
- {contextMenu} -
; + return
+ + {(provided, snapshot) => ( +
+ +
+ )} +
+ {contextMenu} +
; } diff --git a/src/components/views/elements/TagTile.js b/src/components/views/elements/TagTile.js index 0f98971198..d8983ac2ea 100644 --- a/src/components/views/elements/TagTile.js +++ b/src/components/views/elements/TagTile.js @@ -84,7 +84,7 @@ export default createReactClass({ this.props.tag, ).then((profile) => { if (this.unmounted) return; - this.setState({profile}); + this.setState({ profile }); }).catch((err) => { console.warn('Could not fetch group profile for ' + this.props.tag, err); }); @@ -111,18 +111,18 @@ export default createReactClass({ }, onMouseOver: function() { - this.setState({hover: true}); + this.setState({ hover: true }); }, onMouseOut: function() { - this.setState({hover: false}); + this.setState({ hover: false }); }, openMenu: function(e) { // Prevent the TagTile onClick event firing as well e.stopPropagation(); e.preventDefault(); - this.setState({hover: false}); + this.setState({ hover: false }); this.props.openMenu(); }, @@ -154,32 +154,32 @@ export default createReactClass({ // FIXME: this ought to use AccessibleButton for a11y but that causes onMouseOut/onMouseOver to fire too much const contextButton = this.state.hover || this.props.menuDisplayed ?
- { "\u00B7\u00B7\u00B7" } + {"\u00B7\u00B7\u00B7"}
:
; const AccessibleTooltipButton = sdk.getComponent("elements.AccessibleTooltipButton"); return +
-
- - { contextButton } - { badgeElement } -
- ; + + {contextButton} + {badgeElement} +
+
; }, }); From 0b99e2522234604bbf1a7b3efecde23bde758f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Sat, 2 May 2020 05:07:00 +0000 Subject: [PATCH 207/237] Translated using Weblate (Estonian) Currently translated at 33.9% (781 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 62 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 334a20f104..b6fb63b73d 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -719,5 +719,65 @@ "Your theme": "Sinu teema", "Riot URL": "Riot'i aadress", "Room ID": "Jututoa tunnus", - "Widget ID": "Vidina tunnus" + "Widget ID": "Vidina tunnus", + "%(oldDisplayName)s changed their display name to %(displayName)s.": "%(oldDisplayName)s muutis oma kuvatava nime %(displayName)s-ks.", + "%(senderName)s set their display name to %(displayName)s.": "%(senderName)s määras oma kuvatava nime %(displayName)s-ks.", + "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s eemaldas oma kuvatava nime (%(oldDisplayName)s).", + "%(senderName)s removed their profile picture.": "%(senderName)s eemaldas om profiilipildi.", + "%(senderName)s changed their profile picture.": "%(senderName)s muutis oma profiilipilti.", + "%(senderName)s set a profile picture.": "%(senderName)s määras oma profiilipildi.", + "Light theme": "Hele teema", + "Dark theme": "Tume teema", + "%(name)s (%(userId)s)": "%(name)s (%(userId)s)", + "Your browser does not support the required cryptography extensions": "Sinu brauser ei toeta vajalikke krüptoteeke", + "Not a valid Riot keyfile": "See ei ole sobilik võtmefail Riot'i jaoks", + "Authentication check failed: incorrect password?": "Autentimine ebaõnnestus: kas salasõna pole õige?", + "Unrecognised address": "Tundmatu aadress", + "You do not have permission to invite people to this room.": "Sul pole õigusi siia jututuppa osalejate kutsumiseks.", + "User %(userId)s is already in the room": "Kasutaja %(userId)s on juba jututoas", + "User %(user_id)s does not exist": "Kasutajat %(user_id)s pole olemas", + "User %(user_id)s may or may not exist": "Kasutaja %(user_id)s võib olla olemas, aga võib ka mitte olla olemas", + "The user's homeserver does not support the version of the room.": "Kasutaja koduserver ei toeta selle jututoa versiooni.", + "Unknown server error": "Tundmatu serveriviga", + "This is a top-10 common password": "See on kümne levinuima salasõna seas", + "This is a top-100 common password": "See on saja levinuima salasõna seas", + "This is a very common password": "See on väga levinud salasõna", + "This is similar to a commonly used password": "See on sarnane tavaliselt kasutatavatele salasõnadele", + "Support adding custom themes": "Toeta kohandatud teemade lisamist", + "Show display name changes": "Näita kuvatava nime muutusi", + "Match system theme": "Kasuta süsteemset teemat", + "Messages containing my display name": "Sõnumid, mis sisaldavad minu kuvatavat nime", + "Failed to upload profile picture!": "Profiilipildi üleslaadimine ebaõnnestus!", + "No display name": "Kuvatav nimi puudub", + "New passwords don't match": "Uued salasõnad ei klapi", + "Passwords can't be empty": "Salasõna ei saa olla tühi", + "Current password": "Praegune salasõna", + "Password": "Salasõna", + "New Password": "Uus salasõna", + "Confirm password": "Korda uut salasõna", + "Change Password": "Muuda salasõna", + "Failed to set display name": "Kuvatava nime määramine ebaõnnestus", + "Display Name": "Kuvatav nimi", + "Profile picture": "Profiilipilt", + "Failed to change password. Is your password correct?": "Salasõna muutmine ebaõnnestus. Kas sinu salasõna on ikka õige?", + "Invalid theme schema.": "Vigane teemafail.", + "Theme added!": "Teema sai lisatud!", + "Profile": "Profiil", + "Email addresses": "E-posti aadressid", + "Phone numbers": "Telefoninumbrid", + "Set a new account password...": "Määra kontole uus salasõna...", + "Account": "Kasutajakonto", + "Language and region": "Keel ja piirkond", + "Custom theme URL": "Kohandatud teema URL", + "Add theme": "Lisa teema", + "Theme": "Teema", + "Start verification again from their profile.": "Alusta verifitseerimist uuesti nende profiilist.", + "To return to your account in future you need to set a password": "Selleks et hiljemgi oma kontot kasutada, sa pead määrama salasõna", + "Set Password": "Määra salasõna", + "Unable to find profiles for the Matrix IDs listed below - would you like to invite them anyway?": "Allpool loetletud Matrix'i kasutajatunnustele ei leidunud profiile. Kas sa ikkagi tahaksid neile kutse saata?", + "To continue, please enter your password:": "Jätkamiseks palun sisesta oma salasõna:", + "Your password": "Sinu salasõna", + "We recommend you change your password and recovery key in Settings immediately": "Me soovitame et vaheta koheselt Seadistuste lehelt oma salasõna ja taastevõti", + "Could not load user profile": "Kasutajaprofiili laadimine ei õnnestunud", + "Set a display name:": "Määra kuvatav nimi:" } From c00b0702698d46a251cc1870ad2c6fce88aa5302 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 3 May 2020 13:28:16 +0100 Subject: [PATCH 208/237] Fix reply RR spacing getting doubled Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/rooms/_EventTile.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 99377ee5be..752cf982f6 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -126,7 +126,7 @@ limitations under the License. .mx_RoomView_timeline_rr_enabled, // on ELS we need the margin to allow interaction with the expand/collapse button which is normally in the RR gutter .mx_EventListSummary { - .mx_EventTile_line, .mx_EventTile_reply { + .mx_EventTile_line { /* ideally should be 100px, but 95px gives us a max thumbnail size of 800x600, which is nice */ margin-right: 110px; } From 677475ed060763568fe7c15ec6f4555a38ef3a5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Sun, 3 May 2020 21:47:23 +0000 Subject: [PATCH 209/237] Translated using Weblate (Estonian) Currently translated at 34.8% (800 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index b6fb63b73d..cacefc44ee 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -779,5 +779,24 @@ "Your password": "Sinu salasõna", "We recommend you change your password and recovery key in Settings immediately": "Me soovitame et vaheta koheselt Seadistuste lehelt oma salasõna ja taastevõti", "Could not load user profile": "Kasutajaprofiili laadimine ei õnnestunud", - "Set a display name:": "Määra kuvatav nimi:" + "Set a display name:": "Määra kuvatav nimi:", + "Send typing notifications": "Anna märku teisele osapoolele, kui mina sõnumit kirjutan", + "Show typing notifications": "Anna märku, kui teine osapool sõnumit kirjutab", + "Automatically replace plain text Emoji": "Automaatelt asenda vormindamata tekst emotikoniga", + "Mirror local video feed": "Peegelda kohalikku videovoogu", + "Enable Community Filter Panel": "Kasuta kogukondade filtreerimispaneeli", + "Allow Peer-to-Peer for 1:1 calls": "Luba võrdõigusvõrgu loogikat kasutavad omavahelised kõned", + "Send analytics data": "Saada arendajatele analüütikat", + "Enable inline URL previews by default": "Luba URL'ide vaikimisi eelvaated", + "Enable URL previews for this room (only affects you)": "Luba URL'ide eelvaated selle jututoa jaoks (mõjutab vaid sind)", + "Enable URL previews by default for participants in this room": "Luba URL'ide vaikimisi eelvaated selles jututoas osalejate jaoks", + "Room Colour": "Jututoa värv", + "Enable widget screenshots on supported widgets": "Kui vidin seda toetab, siis luba tal teha ekraanitõmmiseid", + "Prompt before sending invites to potentially invalid matrix IDs": "Hoiata enne kutse saatmist võimalikule vigasele Matrix'i kasutajatunnusele", + "Show developer tools": "Näita arendaja tööriistu", + "Show hidden events in timeline": "Näita ajajoonel peidetud sündmusi", + "Low bandwidth mode": "Vähese ribalaiusega režiim", + "Composer": "Sõnumite kirjutamine", + "Jump to start/end of the composer": "Hüppa sõnumite kirjutamise algusesse või lõppu", + "Navigate composer history": "Vaata sõnumite kirjutamise ajalugu" } From dd6a938d5376e88b9e91a52d8a909313a490f912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Sun, 3 May 2020 22:49:51 +0000 Subject: [PATCH 210/237] Translated using Weblate (Estonian) Currently translated at 35.3% (812 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index cacefc44ee..d640121c0b 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -794,9 +794,21 @@ "Enable widget screenshots on supported widgets": "Kui vidin seda toetab, siis luba tal teha ekraanitõmmiseid", "Prompt before sending invites to potentially invalid matrix IDs": "Hoiata enne kutse saatmist võimalikule vigasele Matrix'i kasutajatunnusele", "Show developer tools": "Näita arendaja tööriistu", - "Show hidden events in timeline": "Näita ajajoonel peidetud sündmusi", + "Show hidden events in timeline": "Näita peidetud sündmusi ajajoonel", "Low bandwidth mode": "Vähese ribalaiusega režiim", "Composer": "Sõnumite kirjutamine", "Jump to start/end of the composer": "Hüppa sõnumite kirjutamise algusesse või lõppu", - "Navigate composer history": "Vaata sõnumite kirjutamise ajalugu" + "Navigate composer history": "Vaata sõnumite kirjutamise ajalugu", + "Show previews/thumbnails for images": "Näita piltide eelvaateid või väikepilte", + "Collecting logs": "Kogun logisid", + "Waiting for response from server": "Ootan serverilt vastust", + "Messages containing my username": "Sõnumid, mis sisaldavad minu kasutajatunnust", + "Messages containing @room": "Sõnumid, mis sisaldavad sõna @room", + "Messages in one-to-one chats": "Kahepoolsete vestluste sõnumid", + "Encrypted messages in one-to-one chats": "Kahepoolsete vestluste krüptitud sõnumid", + "Messages in group chats": "Rühmavestluste sõnumid", + "Encrypted messages in group chats": "Rühmavestluste krüptitud sõnumid", + "When I'm invited to a room": "Kui mind kutsutakse jututuppa", + "Call invitation": "Kõnekutse", + "Messages sent by bot": "Robotite saadetud sõnumid" } From b9ce10af19d1335fd97ecf1e7032ecaa43c200f2 Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Fri, 1 May 2020 10:38:14 +0000 Subject: [PATCH 211/237] Translated using Weblate (Bulgarian) Currently translated at 91.9% (2115 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/bg/ --- src/i18n/strings/bg.json | 130 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/bg.json b/src/i18n/strings/bg.json index 46a4d811e5..87e5d928ac 100644 --- a/src/i18n/strings/bg.json +++ b/src/i18n/strings/bg.json @@ -2049,5 +2049,133 @@ "Backup has a valid signature from verified session ": "Резервното копие има валиден подпис от потвърдена сесия ", "Backup has a valid signature from unverified session ": "Резервното копие има валиден подпис от непотвърдена сесия ", "Backup has an invalid signature from verified session ": "Резервното копие има невалиден подпис от потвърдена сесия ", - "Backup has an invalid signature from unverified session ": "Резервното копие има невалиден подпис от непотвърдена сесия " + "Backup has an invalid signature from unverified session ": "Резервното копие има невалиден подпис от непотвърдена сесия ", + "Backup is not signed by any of your sessions": "Резервното копие не е подписано от нито една ваша сесия", + "This backup is trusted because it has been restored on this session": "Това резервно копие е доверено, защото е било възстановено в текущата сесия", + "Backup key stored in secret storage, but this feature is not enabled on this session. Please enable cross-signing in Labs to modify key backup state.": "Резервно копие на ключа е съхранено в секретно складиране, но тази функция не е включена в сегашната сесия. Включете кръстосано-подписване в Labs за да модифицирате състоянието на резервното копие на ключа.", + "Your keys are not being backed up from this session.": "На ключовете ви не се прави резервно копие от тази сесия.", + "Enable desktop notifications for this session": "Включи уведомления на работния плот за тази сесия", + "Enable audible notifications for this session": "Включи звукови уведомления за тази сесия", + "Your password was successfully changed. You will not receive push notifications on other sessions until you log back in to them": "Паролата ви беше променена. Няма да получавате push уведомления на другите ви сесии докато не влезете отново в тях", + "Invalid theme schema.": "Невалиден формат на темата.", + "Error downloading theme information.": "Неуспешно изтегляне на информацията за темата.", + "Theme added!": "Темата беше добавена!", + "Custom theme URL": "Собствен URL адрес на тема", + "Add theme": "Добави тема", + "To report a Matrix-related security issue, please read the Matrix.org Security Disclosure Policy.": "За да съобщените за проблем със сигурността свързан с Matrix, прочетете Политиката за споделяне на проблеми със сигурността на Matrix.org.", + "Keyboard Shortcuts": "Клавишни комбинации", + "Session ID:": "Сесиен идентификатор:", + "Session key:": "Сесиен ключ:", + "Message search": "Търсене на съобщения", + "Where you’re logged in": "Когато сте вписани", + "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Управлявайте имената или входа в сесиите си по-долу или ги верифицирайте от профила си.", + "A session's public name is visible to people you communicate with": "Публичното име на сесията е видимо за хората, с които комуникирате", + "This room is bridging messages to the following platforms. Learn more.": "Тази стая препредава съобщения със следните платформи. Научи повече.", + "This room isn’t bridging messages to any platforms. Learn more.": "Тази стая не препредава съобщения с други платформи. Научи повече.", + "Bridges": "Мостове", + "This user has not verified all of their sessions.": "Този потребител не е верифицирал всичките си сесии.", + "You have not verified this user.": "Не сте верифицирали този потребител.", + "You have verified this user. This user has verified all of their sessions.": "Верифицирали сте този потребител. Този потребител е верифицирал всичките си сесии.", + "Someone is using an unknown session": "Някой използва непозната сесия", + "This room is end-to-end encrypted": "Тази стая е шифрована от-край-до-край", + "Everyone in this room is verified": "Всички в тази стая са верифицирани", + "Some sessions for this user are not trusted": "Някои сесии на този потребител не са доверени", + "All sessions for this user are trusted": "Всички сесии на този потребител са доверени", + "Some sessions in this encrypted room are not trusted": "Някои сесии в тази шифрована стая не са доверени", + "All sessions in this encrypted room are trusted": "Всички сесии в тази шифрована стая са доверени", + "Mod": "Модератор", + "Your key share request has been sent - please check your other sessions for key share requests.": "Заявката ви за споделяне на ключ е изпратена - проверете останалите си сесии за заявки за споделяне на ключове.", + "Key share requests are sent to your other sessions automatically. If you rejected or dismissed the key share request on your other sessions, click here to request the keys for this session again.": "Заявките за споделяне на ключове се изпращат до другите ви сесии автоматично. Ако сте отказали заявката от другите ви сесии, кликнете тук за да изпратите заявка за тази сесия отново.", + "If your other sessions do not have the key for this message you will not be able to decrypt them.": "Ако другите ви сесии нямат ключа за това съобщения, няма да можете да ги дешифровате.", + "Re-request encryption keys from your other sessions.": "Поискай отново ключове за шифроване от другите сесии.", + "Encrypted by an unverified session": "Шифровано от неверифицирана сесия", + "Encrypted by a deleted session": "Шифровано от изтрита сесия", + "Invite only": "Само с покани", + "Scroll to most recent messages": "Отиди до най-скорошните съобщения", + "No sessions with registered encryption keys": "Няма сесии с регистрирани ключове за шифроване", + "Sessions": "Сесии", + "Send a reply…": "Изпрати отговор…", + "Send a message…": "Изпрати съобщение…", + "Reject & Ignore user": "Откажи и игнорирай потребителя", + "Unknown Command": "Непозната команда", + "Unrecognised command: %(commandText)s": "Неразпозната команда: %(commandText)s", + "You can use /help to list available commands. Did you mean to send this as a message?": "Може да използвате /help за да видите наличните команди. Или пък искахте да изпратите това като съобщение?", + "Hint: Begin your message with // to start it with a slash.": "Съвет: Започнете съобщението си с // за да изпратите съобщение започващо с наклонена черта.", + "Send as message": "Изпрати като съобщение", + "Mark all as read": "Маркирай всичко като прочетено", + "There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.": "Възникна грешка при обновяване на алтернативните адреси на стаята. Или не е позволено от сървъра или се е случила временна грешка.", + "You don't have permission to delete the alias.": "Нямате привилегия да изтриете този алтернативен адрес.", + "Local address": "Локален адрес", + "Published Addresses": "Публикувани адреси", + "Published addresses can be used by anyone on any server to join your room. To publish an address, it needs to be set as a local address first.": "Публикуваните адреси могат да бъдат използвани от всеки човек, на кой да е сървър, за присъединяване към стаята. За да публикувате адрес, първо трябва да е настроен като локален адрес.", + "Other published addresses:": "Други публикувани адреси:", + "No other published addresses yet, add one below": "Все още няма други публикувани адреси, добавете такъв по-долу", + "New published address (e.g. #alias:server)": "Нов публикуван адрес (напр. #alias:server)", + "Local Addresses": "Локални адреси", + "Set addresses for this room so users can find this room through your homeserver (%(localDomain)s)": "Настройте адреси за тази стая, така че потребителите да могат да намерят стаята през вашия сървър (%(localDomain)s)", + "Waiting for you to accept on your other session…": "Изчаква се да приемете от другата ви сесия…", + "Waiting for %(displayName)s to accept…": "Изчаква се %(displayName)s да приеме…", + "Accepting…": "Приемане…", + "Start Verification": "Започни верификация", + "Your messages are secured and only you and the recipient have the unique keys to unlock them.": "Съобщенията ви са защитени и само вие и получателят имате уникалните ключове за да ги отключите.", + "In encrypted rooms, your messages are secured and only you and the recipient have the unique keys to unlock them.": "В шифровани стаи, съобщенията ви са защитени и само вие и получателят имате уникалните ключове за да ги отключите.", + "Verify User": "Потвърди потребителя", + "For extra security, verify this user by checking a one-time code on both of your devices.": "За допълнителна сигурност, потвърдете този потребител като проверите еднократен код на устройствата ви.", + "Your messages are not secure": "Съобщенията ви не са защитени", + "One of the following may be compromised:": "Едно от следните неща може да е било компрометирано:", + "Your homeserver": "Сървърът ви", + "The homeserver the user you’re verifying is connected to": "Сървърът на потребителя, който верифицирате", + "Yours, or the other users’ internet connection": "Интернет връзката ви или тази на другите потребители", + "Yours, or the other users’ session": "Сесията ви или тази на другите потребители", + "%(count)s sessions|other": "%(count)s сесии", + "%(count)s sessions|one": "%(count)s сесия", + "Hide sessions": "Скрий сесиите", + "The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what Riot supports. Try with a different client.": "Сесията, която се опитвате да верифицирате не поддържа сканиране на QR код или емоджи верификация (нещата които Riot поддържа). Пробвайте с друг клиент.", + "Verify by scanning": "Верифицирай чрез сканиране", + "Ask %(displayName)s to scan your code:": "Попитайте %(displayName)s да сканира вашия код:", + "If you can't scan the code above, verify by comparing unique emoji.": "Ако не можете да сканирате кода по-горе, верифицирайте сравнявайки уникални емоджита.", + "Verify by comparing unique emoji.": "Верифицирай чрез сравняване на уникални емоджита.", + "Verify by emoji": "Верифицирай чрез емоджи", + "Almost there! Is your other session showing the same shield?": "Почти е готово! Другата ви сесия показва ли същия щит?", + "Almost there! Is %(displayName)s showing the same shield?": "Почти е готово! Сесията %(displayName)s показва ли същия щит?", + "Verify all users in a room to ensure it's secure.": "Верифицирай всички потребители в стаята за да подсигурите безопасността.", + "In encrypted rooms, verify all users to ensure it’s secure.": "В шифровани стаи, верифицирайте всички потребители за да подсигурите безопасността.", + "You've successfully verified %(deviceName)s (%(deviceId)s)!": "Успешно верифицирахте %(deviceName)s (%(deviceId)s)!", + "You've successfully verified %(displayName)s!": "Успешно верифицирахте %(displayName)s!", + "Verified": "Потвърдено", + "Got it": "Разбрах", + "Start verification again from the notification.": "Започнете верифициране отново от уведомлението.", + "Start verification again from their profile.": "Започнете верифициране отново от профила им.", + "Verification timed out.": "Изтече времето за верификация.", + "You cancelled verification on your other session.": "Отказахте верификацията от другата сесия.", + "%(displayName)s cancelled verification.": "%(displayName)s отказа верификацията.", + "You cancelled verification.": "Отказахте верификацията.", + "Verification cancelled": "Верификацията беше отказана", + "Compare emoji": "Сравни емоджи", + "Encryption enabled": "Шифроването е включено", + "Messages in this room are end-to-end encrypted. Learn more & verify this user in their user profile.": "Съобщенията в тази стая са ширфовани от-край-до-край. Научете повече и верифицирайте този потребител от профила им.", + "Encryption not enabled": "Шифроването не е включено", + "The encryption used by this room isn't supported.": "Шифроването използвано от тази стая не се поддържа.", + "You declined": "Отказахте", + "%(name)s declined": "%(name)s отказа", + "Accepting …": "Приемане…", + "Declining …": "Отказване…", + "Can't load this message": "Съобщението не може да се зареди", + "Submit logs": "Изпрати логове", + "Enter a server name": "Въведете име на сървър", + "Looks good": "Изглежда добре", + "Can't find this server or its room list": "Сървърът или списъка със стаи не може да бъде намерен", + "All rooms": "Всички стаи", + "Your server": "Вашият сървър", + "Are you sure you want to remove %(serverName)s": "Сигурни ли сте, че искате да премахнете %(serverName)s", + "Remove server": "Премахни сървъра", + "Matrix": "Matrix", + "Add a new server": "Добави нов сървър", + "Enter the name of a new server you want to explore.": "Въведете името на новия сървър, който искате да прегледате.", + "Server name": "Име на сървър", + "Add a new server...": "Добави нов сървър...", + "%(networkName)s rooms": "%(networkName)s стаи", + "Matrix rooms": "Matrix стаи", + "Reminder: Your browser is unsupported, so your experience may be unpredictable.": "Напомняне: браузърът ви не се поддържа, така че не всичко може да работи правилно.", + "Destroy cross-signing keys?": "Унищожаване на ключовете за кръстосано-подписване?" } From 8a794fafc6520a6b3ce00ca489e06514b0b47f45 Mon Sep 17 00:00:00 2001 From: Szimszon Date: Sun, 3 May 2020 15:16:05 +0000 Subject: [PATCH 212/237] Translated using Weblate (Hungarian) Currently translated at 100.0% (2302 of 2302 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/hu/ --- src/i18n/strings/hu.json | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index b1db06fa4b..8bf5e28f7f 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -1351,7 +1351,7 @@ "Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. Learn more about encryption.": "Ha egyszer engedélyezve lett, a szoba titkosítását nem lehet kikapcsolni. A titkosított szobákban küldött üzenetek a szerver számára nem, csak a szoba tagjai számára láthatók. A titkosítás bekapcsolása megakadályoz sok botot és hidat a megfelelő működésben. Tudj meg többet a titkosításról.", "Power level": "Hozzáférési szint", "Want more than a community? Get your own server": "Többet szeretnél, mint egy közösség? Szerezz saját szervert", - "Please install Chrome, Firefox, or Safari for the best experience.": "Kérlek telepíts Chromeot, Firefoxot vagy Safarit a jegjobb élményhez.", + "Please install Chrome, Firefox, or Safari for the best experience.": "A legjobb élmény eléréséhez kérlek telepíts Chrome-ot, Firefoxot vagy Safarit.", "Warning: Upgrading a room will not automatically migrate room members to the new version of the room. We'll post a link to the new room in the old version of the room - room members will have to click this link to join the new room.": "Figyelmeztetés: A szoba frissítése nem fogja automatikusan átvinni a szoba résztvevőit az új verziójú szobába. A régi szobába bekerül egy link az új szobához - a tagoknak rá kell kattintani a linkre az új szobába való belépéshez.", "Adds a custom widget by URL to the room": "Egyedi kisalkalmazás hozzáadása a szobához URL-lel", "Please supply a https:// or http:// widget URL": "Kérlek add meg a https:// vagy http:// kisalkalmazás URL-t", @@ -2395,5 +2395,16 @@ "This requires the latest Riot on your other devices:": "A Riot legújabb kliensére van ehhez szükséged a többi eszközödön:", "or another cross-signing capable Matrix client": "vagy másik eszközök közötti hitelesítésre alkalmas Matrix kliensre", "Use Recovery Passphrase or Key": "Használd a Visszaállítási Jelmondatot vagy Kulcsot", - "Unable to query secret storage status": "A biztonsági tároló állapotát nem lehet lekérdezni" + "Unable to query secret storage status": "A biztonsági tároló állapotát nem lehet lekérdezni", + "Review where you’re logged in": "Tekintsd át hol vagy bejelentkezve", + "New login. Was this you?": "Új bejelentkezés. Te voltál?", + "Verify all your sessions to ensure your account & messages are safe": "Ellenőrizd minden munkamenetedet, hogy a fiókod és az üzeneteid biztonságban legyenek", + "Verify the new login accessing your account: %(name)s": "Ellenőrizd ezt az új bejelentkezést ami hozzáfér a fiókodhoz: %(name)s", + "Where you’re logged in": "Ahol be vagy jelentkezve", + "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Állítsd be a munkameneteid neveit, jelentkezz ki vagy ellenőrizd őket a Felhasználói Beállításokban.", + "Restoring keys from backup": "Kulcsok visszaállítása mentésből", + "Fetching keys from server...": "Kulcsok lekérdezése a szerverről…", + "%(completed)s of %(total)s keys restored": "%(completed)s/%(total)s kulcs visszaállítva", + "Keys restored": "Kulcsok visszaállítva", + "Successfully restored %(sessionCount)s keys": "Kulcsok (%(sessionCount)s) sikeresen visszaállítva" } From d9639c5412f869b8a1e4c362d6d844297fe5dc2c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 4 May 2020 13:40:52 +0200 Subject: [PATCH 213/237] increare rage shake size limit to 5mb --- src/rageshake/rageshake.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rageshake/rageshake.js b/src/rageshake/rageshake.js index a9d17e77c9..59ed5fa8b7 100644 --- a/src/rageshake/rageshake.js +++ b/src/rageshake/rageshake.js @@ -41,7 +41,7 @@ limitations under the License. const FLUSH_RATE_MS = 30 * 1000; // the length of log data we keep in indexeddb (and include in the reports) -const MAX_LOG_SIZE = 1024 * 1024 * 1; // 1 MB +const MAX_LOG_SIZE = 1024 * 1024 * 5; // 5 MB // A class which monkey-patches the global console and stores log lines. class ConsoleLogger { From aa87e84652e9f2377a24eeaea7b9f5c75a35b98a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 4 May 2020 13:40:52 +0200 Subject: [PATCH 214/237] increare rage shake size limit to 5mb --- src/rageshake/rageshake.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rageshake/rageshake.js b/src/rageshake/rageshake.js index a9d17e77c9..59ed5fa8b7 100644 --- a/src/rageshake/rageshake.js +++ b/src/rageshake/rageshake.js @@ -41,7 +41,7 @@ limitations under the License. const FLUSH_RATE_MS = 30 * 1000; // the length of log data we keep in indexeddb (and include in the reports) -const MAX_LOG_SIZE = 1024 * 1024 * 1; // 1 MB +const MAX_LOG_SIZE = 1024 * 1024 * 5; // 5 MB // A class which monkey-patches the global console and stores log lines. class ConsoleLogger { From a11812a4029472127c4380a03b526eb7d8d689e2 Mon Sep 17 00:00:00 2001 From: Jorik Schellekens Date: Mon, 4 May 2020 15:07:41 +0100 Subject: [PATCH 215/237] Fix slider toggle regression. --- res/css/views/elements/_ToggleSwitch.scss | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/res/css/views/elements/_ToggleSwitch.scss b/res/css/views/elements/_ToggleSwitch.scss index 7c65fbc90d..62669889ee 100644 --- a/res/css/views/elements/_ToggleSwitch.scss +++ b/res/css/views/elements/_ToggleSwitch.scss @@ -24,11 +24,6 @@ limitations under the License. background-color: $togglesw-off-color; opacity: 0.5; - - display: flex; - flex-direction: row; - flex: 0 0 auto; - align-items: center; } .mx_ToggleSwitch_enabled { @@ -38,16 +33,18 @@ limitations under the License. .mx_ToggleSwitch.mx_ToggleSwitch_on { background-color: $togglesw-on-color; + + > .mx_ToggleSwitch_ball { + left: calc(100% - $font-20px); + } } .mx_ToggleSwitch_ball { - transition: left 0.15s ease-out 0.1s; + position: relative; width: $font-20px; height: $font-20px; border-radius: $font-20px; background-color: $togglesw-ball-color; -} - -.mx_ToggleSwitch_on { - flex-direction: row-reverse; + transition: left 0.15s ease-out 0.1s; + left: 0; } From 7ef3b446f4fcb587ef071f6de8ad8aba14ad3d05 Mon Sep 17 00:00:00 2001 From: Zoe Date: Mon, 27 Apr 2020 16:58:24 +0100 Subject: [PATCH 216/237] Show progress when loading keys --- .../keybackup/RestoreKeyBackupDialog.js | 25 ++++++++++++++++++- src/i18n/strings/en_EN.json | 3 +++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index dc82a71713..92d23f9e65 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -59,6 +59,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { forceRecoveryKey: false, passPhrase: '', restoreType: null, + progress: { stage: "prefetch" }, }; } @@ -80,6 +81,12 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { }); } + _progressCallback = (data) => { + this.setState({ + progress: data, + }); + } + _onResetRecoveryClick = () => { this.props.onFinished(false); Modal.createTrackedDialogAsync('Key Backup', 'Key Backup', @@ -110,6 +117,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { // is the right one and restoring it is currently the only way we can do this. const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithPassword( this.state.passPhrase, undefined, undefined, this.state.backupInfo, + { progressCallback: this._progressCallback }, ); if (this.props.keyCallback) { const key = await MatrixClientPeg.get().keyBackupKeyFromPassword( @@ -146,6 +154,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { try { const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithRecoveryKey( this.state.recoveryKey, undefined, undefined, this.state.backupInfo, + { progressCallback: this._progressCallback }, ); if (this.props.keyCallback) { const key = MatrixClientPeg.get().keyBackupKeyFromRecoveryKey(this.state.recoveryKey); @@ -185,6 +194,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { const recoverInfo = await accessSecretStorage(async () => { return MatrixClientPeg.get().restoreKeyBackupWithSecretStorage( this.state.backupInfo, + { progressCallback: this._progressCallback }, ); }); this.setState({ @@ -207,6 +217,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { undefined, /* targetRoomId */ undefined, /* targetSessionId */ backupInfo, + { progressCallback: this._progressCallback }, ); this.setState({ recoverInfo, @@ -273,7 +284,19 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { let title; if (this.state.loading) { title = _t("Loading..."); - content = ; + let details; + if (this.state.progress.stage === "fetch") { + details = _t("Downloading from server..."); + } else if (this.state.progress.stage === "load_keys") { + const { total, successes, failures } = this.state.progress; + details = _t("Loaded %(completed)s of %(total)s", { total, completed: successes + failures }); + } else if (this.state.progress.stage === "prefetch") { + details = _t("Requesting from server..."); + } + content =
+
{details}
+ +
; } else if (this.state.loadError) { title = _t("Error"); content = _t("Unable to load backup status"); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5544e3a8b1..992ace1e92 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1794,6 +1794,9 @@ "Not a valid recovery key": "Not a valid recovery key", "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.", "If you've forgotten your recovery key you can .": "If you've forgotten your recovery key you can .", + "Downloading from server": "Downloading from server", + "Loaded %(completed)s of %(total)s": "Loaded %(completed)s of %(total)s", + "Requesting from server...": "Requesting from server...", "Unable to load backup status": "Unable to load backup status", "Recovery key mismatch": "Recovery key mismatch", "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.": "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.", From b7bcf25cfab8539c172f36b6ee331eaa06488426 Mon Sep 17 00:00:00 2001 From: Zoe Date: Tue, 28 Apr 2020 11:36:28 +0100 Subject: [PATCH 217/237] i18n --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 992ace1e92..3fd9951cfe 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1794,7 +1794,7 @@ "Not a valid recovery key": "Not a valid recovery key", "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.", "If you've forgotten your recovery key you can .": "If you've forgotten your recovery key you can .", - "Downloading from server": "Downloading from server", + "Downloading from server...": "Downloading from server...", "Loaded %(completed)s of %(total)s": "Loaded %(completed)s of %(total)s", "Requesting from server...": "Requesting from server...", "Unable to load backup status": "Unable to load backup status", From 3dbcc9fe9957289eb7f0d78ff75545885078f9a2 Mon Sep 17 00:00:00 2001 From: Zoe Date: Wed, 29 Apr 2020 14:14:39 +0100 Subject: [PATCH 218/237] copy changes --- .../dialogs/keybackup/RestoreKeyBackupDialog.js | 12 ++++++------ src/i18n/strings/en_EN.json | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index 92d23f9e65..da67fb9777 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -283,15 +283,15 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { let content; let title; if (this.state.loading) { - title = _t("Loading..."); + title = _t("Restoring keys from backup"); let details; if (this.state.progress.stage === "fetch") { - details = _t("Downloading from server..."); + details = _t("Fetching keys from server..."); } else if (this.state.progress.stage === "load_keys") { const { total, successes, failures } = this.state.progress; - details = _t("Loaded %(completed)s of %(total)s", { total, completed: successes + failures }); + details = _t("%(completed)s of %(total)s keys restored", { total, completed: successes + failures }); } else if (this.state.progress.stage === "prefetch") { - details = _t("Requesting from server..."); + details = _t("Fetching keys from server..."); } content =
{details}
@@ -328,7 +328,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { content = _t("No backup found!"); } else if (this.state.recoverInfo) { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); - title = _t("Backup restored"); + title = _t("Keys restored"); let failedToDecrypt; if (this.state.recoverInfo.total > this.state.recoverInfo.imported) { failedToDecrypt =

{_t( @@ -337,7 +337,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { )}

; } content =
-

{_t("Restored %(sessionCount)s session keys", {sessionCount: this.state.recoverInfo.imported})}

+

{_t("Successfully restored %(sessionCount)s keys", {sessionCount: this.state.recoverInfo.imported})}

{failedToDecrypt} set up new recovery options.": "If you've forgotten your recovery key you can .", - "Downloading from server...": "Downloading from server...", - "Loaded %(completed)s of %(total)s": "Loaded %(completed)s of %(total)s", - "Requesting from server...": "Requesting from server...", + "Restoring keys from backup": "Restoring keys from backup", + "Fetching keys from server...": "Fetching keys from server...", + "%(completed)s of %(total)s keys restored": "%(completed)s of %(total)s keys restored", "Unable to load backup status": "Unable to load backup status", "Recovery key mismatch": "Recovery key mismatch", "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.": "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.", @@ -1804,9 +1804,9 @@ "Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.": "Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.", "Unable to restore backup": "Unable to restore backup", "No backup found!": "No backup found!", - "Backup restored": "Backup restored", + "Keys restored": "Keys restored", "Failed to decrypt %(failedCount)s sessions!": "Failed to decrypt %(failedCount)s sessions!", - "Restored %(sessionCount)s session keys": "Restored %(sessionCount)s session keys", + "Successfully restored %(sessionCount)s keys": "Successfully restored %(sessionCount)s keys", "Warning: you should only set up key backup from a trusted computer.": "Warning: you should only set up key backup from a trusted computer.", "Access your secure message history and set up secure messaging by entering your recovery passphrase.": "Access your secure message history and set up secure messaging by entering your recovery passphrase.", "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options": "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options", From 1afb09d2574dfced61baa3aeafe7881329b712ea Mon Sep 17 00:00:00 2001 From: Zoe Date: Wed, 29 Apr 2020 14:29:36 +0100 Subject: [PATCH 219/237] Fixed the dialog height --- .../keybackup/_RestoreKeyBackupDialog.scss | 6 +++++ .../keybackup/RestoreKeyBackupDialog.js | 26 +++++++++---------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss index 9cba8e0da9..d74224c94d 100644 --- a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss +++ b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss @@ -32,3 +32,9 @@ limitations under the License. padding: 10px; } +.mx_RestoreKeyBackupDialog_content { + display: flex; + flex-direction: column; + justify-content: space-between; + min-height: 110px; /* Empirically measured */ +} diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index da67fb9777..9829f7af8e 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -293,10 +293,10 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { } else if (this.state.progress.stage === "prefetch") { details = _t("Fetching keys from server..."); } - content =
+ content = <>
{details}
-
; + ; } else if (this.state.loadError) { title = _t("Error"); content = _t("Unable to load backup status"); @@ -304,20 +304,20 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { if (this.state.restoreError.errcode === MatrixClient.RESTORE_BACKUP_ERROR_BAD_KEY) { if (this.state.restoreType === RESTORE_TYPE_RECOVERYKEY) { title = _t("Recovery key mismatch"); - content =
+ content = <>

{_t( "Backup could not be decrypted with this recovery key: " + "please verify that you entered the correct recovery key.", )}

-
; + ; } else { title = _t("Incorrect recovery passphrase"); - content =
+ content = <>

{_t( "Backup could not be decrypted with this recovery passphrase: " + "please verify that you entered the correct recovery passphrase.", )}

-
; + ; } } else { title = _t("Error"); @@ -336,7 +336,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {failedCount: this.state.recoverInfo.total - this.state.recoverInfo.imported}, )}

; } - content =
+ content = <>

{_t("Successfully restored %(sessionCount)s keys", {sessionCount: this.state.recoverInfo.imported})}

{failedToDecrypt} -
; + ; } else if (backupHasPassphrase && !this.state.forceRecoveryKey) { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); title = _t("Enter recovery passphrase"); - content =
+ content = <>

{_t( "Warning: you should only set up key backup " + "from a trusted computer.", {}, @@ -394,7 +394,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} -

; + ; } else { title = _t("Enter recovery key"); const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); @@ -413,7 +413,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
; } - content =
+ content = <>

{_t( "Warning: You should only set up key backup " + "from a trusted computer.", {}, @@ -450,7 +450,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} -

; + ; } return ( @@ -458,7 +458,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { onFinished={this.props.onFinished} title={title} > -
+
{content}
From 64c70b2de09ca3cb3c7124f44a1c94f812243418 Mon Sep 17 00:00:00 2001 From: Zoe Date: Wed, 29 Apr 2020 15:10:23 +0100 Subject: [PATCH 220/237] fragments and i18n don't play nice together --- .../keybackup/_RestoreKeyBackupDialog.scss | 2 +- .../keybackup/RestoreKeyBackupDialog.js | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss index d74224c94d..5689d84bc5 100644 --- a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss +++ b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss @@ -32,7 +32,7 @@ limitations under the License. padding: 10px; } -.mx_RestoreKeyBackupDialog_content { +.mx_RestoreKeyBackupDialog_content > div { display: flex; flex-direction: column; justify-content: space-between; diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index 9829f7af8e..f1008dfcb0 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -293,10 +293,10 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { } else if (this.state.progress.stage === "prefetch") { details = _t("Fetching keys from server..."); } - content = <> + content =
{details}
- ; +
; } else if (this.state.loadError) { title = _t("Error"); content = _t("Unable to load backup status"); @@ -304,20 +304,20 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { if (this.state.restoreError.errcode === MatrixClient.RESTORE_BACKUP_ERROR_BAD_KEY) { if (this.state.restoreType === RESTORE_TYPE_RECOVERYKEY) { title = _t("Recovery key mismatch"); - content = <> + content =

{_t( "Backup could not be decrypted with this recovery key: " + "please verify that you entered the correct recovery key.", )}

- ; +
; } else { title = _t("Incorrect recovery passphrase"); - content = <> + content =

{_t( "Backup could not be decrypted with this recovery passphrase: " + "please verify that you entered the correct recovery passphrase.", )}

- ; +
; } } else { title = _t("Error"); @@ -336,7 +336,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {failedCount: this.state.recoverInfo.total - this.state.recoverInfo.imported}, )}

; } - content = <> + content =

{_t("Successfully restored %(sessionCount)s keys", {sessionCount: this.state.recoverInfo.imported})}

{failedToDecrypt} - ; +
; } else if (backupHasPassphrase && !this.state.forceRecoveryKey) { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); title = _t("Enter recovery passphrase"); - content = <> + content =

{_t( "Warning: you should only set up key backup " + "from a trusted computer.", {}, @@ -394,7 +394,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} - ; +

; } else { title = _t("Enter recovery key"); const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); @@ -413,7 +413,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
; } - content = <> + content =

{_t( "Warning: You should only set up key backup " + "from a trusted computer.", {}, @@ -450,7 +450,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} - ; +

; } return ( From 83bd96a091a3d6d3a6f90160bc03f0655f6d3685 Mon Sep 17 00:00:00 2001 From: Jorik Schellekens Date: Mon, 4 May 2020 17:15:09 +0100 Subject: [PATCH 221/237] Css rounds weirdly sometimes. Heigher precision fixes it. --- res/css/_font-sizes.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/_font-sizes.scss b/res/css/_font-sizes.scss index 5cd19ce620..76a9b16425 100644 --- a/res/css/_font-sizes.scss +++ b/res/css/_font-sizes.scss @@ -34,7 +34,7 @@ $font-16px: 1.067rem; $font-17px: 1.133rem; $font-18px: 1.200rem; $font-19px: 1.267rem; -$font-20px: 1.333rem; +$font-20px: 1.3333333rem; $font-21px: 1.400rem; $font-22px: 1.467rem; $font-23px: 1.533rem; From 9a14417a037933204a6676fa858524bf9f93cb22 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 4 May 2020 15:41:26 -0600 Subject: [PATCH 222/237] Don't try to reload profile information when closing the user panel Fixes https://github.com/vector-im/riot-web/issues/13479 This looks to have been caused by something to do with the app load order, though where is a mystery. The view change seems to fire for the same page type despite a dispatch that says to change the view type. Instead of debugging it too much further, we'll just patch around it. This commit also makes the settings link use a more safe approach to viewing the user info - not going through the dispatcher means we are at the mercy of browser behaviour when we already have a loop which deals with this. --- src/components/structures/RightPanel.js | 2 +- src/components/structures/UserView.js | 5 ++++- .../views/settings/tabs/user/SecurityUserSettingsTab.js | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index 3fec5aa25f..34652098b3 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -227,7 +227,7 @@ export default class RightPanel extends React.Component { if (this.props.user) { // If we have a user prop then we're displaying a user from the 'user' page type // in LoggedInView, so need to change the page type to close the panel (we switch - // to the home page which is not obviosuly the correct thing to do, but I'm not sure + // to the home page which is not obviously the correct thing to do, but I'm not sure // anything else is - we could hide the close button altogether?) dis.dispatch({ action: "view_home_page", diff --git a/src/components/structures/UserView.js b/src/components/structures/UserView.js index c4fba137cc..493cc136d1 100644 --- a/src/components/structures/UserView.js +++ b/src/components/structures/UserView.js @@ -42,7 +42,10 @@ export default class UserView extends React.Component { } componentDidUpdate(prevProps) { - if (prevProps.userId !== this.props.userId) { + // XXX: We shouldn't need to null check the userId here, but we declare + // it as optional and MatrixChat sometimes fires in a way which results + // in an NPE when we try to update the profile info. + if (prevProps.userId !== this.props.userId && this.props.userId) { this._loadProfileInfo(); } } diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index a4336a81f3..5dd6475e6e 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -112,7 +112,10 @@ export default class SecurityUserSettingsTab extends React.Component { }; _onGoToUserProfileClick = () => { - window.location.href = "#/user/" + MatrixClientPeg.get().getUserId(); + dis.dispatch({ + action: 'view_user_info', + userId: MatrixClientPeg.get().getUserId(), + }); this.props.closeSettingsFn(); } From f2df698e3bfa856acecddc1fade398763795dc2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 5 May 2020 10:10:21 +0200 Subject: [PATCH 223/237] EventIndex: Reduce the logging the event index is producing. --- src/indexing/EventIndex.js | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index a6bbbb5f96..eed9837a7a 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -102,9 +102,6 @@ export default class EventIndex extends EventEmitter { const timeline = room.getLiveTimeline(); const token = timeline.getPaginationToken("b"); - console.log("EventIndex: Got token for indexer", - room.roomId, token); - const backCheckpoint = { roomId: room.roomId, token: token, @@ -161,7 +158,6 @@ export default class EventIndex extends EventEmitter { if (prevState === "SYNCING" && state === "SYNCING") { // A sync was done, presumably we queued up some live events, // commit them now. - console.log("EventIndex: Committing events"); await indexManager.commitLiveEvents(); return; } @@ -336,8 +332,6 @@ export default class EventIndex extends EventEmitter { async crawlerFunc() { let cancelled = false; - console.log("EventIndex: Started crawler function"); - const client = MatrixClientPeg.get(); const indexManager = PlatformPeg.get().getEventIndexingManager(); @@ -366,8 +360,6 @@ export default class EventIndex extends EventEmitter { await sleep(sleepTime); - console.log("EventIndex: Running the crawler loop."); - if (cancelled) { break; } @@ -386,8 +378,6 @@ export default class EventIndex extends EventEmitter { idle = false; - console.log("EventIndex: crawling using checkpoint", checkpoint); - // We have a checkpoint, let us fetch some messages, again, very // conservatively to not bother our homeserver too much. const eventMapper = client.getEventMapper({preventReEmit: true}); @@ -511,15 +501,6 @@ export default class EventIndex extends EventEmitter { direction: checkpoint.direction, }; - console.log( - "EventIndex: Crawled room", - client.getRoom(checkpoint.roomId).name, - "and fetched total", matrixEvents.length, "events of which", - events.length, "are being added,", redactionEvents.length, - "are redacted,", matrixEvents.length - events.length, - "are being skipped, undecryptable", undecryptableEvents.length, - ); - try { for (let i = 0; i < redactionEvents.length; i++) { const ev = redactionEvents[i]; @@ -552,8 +533,6 @@ export default class EventIndex extends EventEmitter { } this._crawler = null; - - console.log("EventIndex: Stopping crawler function"); } /** From c9ac726629c44d20c2ce02b4846f57d3be563c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 5 May 2020 10:21:18 +0200 Subject: [PATCH 224/237] EventIndex: Remove an unused variable. --- src/indexing/EventIndex.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index eed9837a7a..02151f8474 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -467,9 +467,6 @@ export default class EventIndex extends EventEmitter { // decryption keys, do we want to retry this checkpoint at a later // stage? const filteredEvents = matrixEvents.filter(this.isValidEvent); - const undecryptableEvents = matrixEvents.filter((ev) => { - return ev.isDecryptionFailure(); - }); // Collect the redaction events so we can delete the redacted events // from the index. From b04bb423f8dc3b1fb84ac2a7d058c3eed4656d3a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 5 May 2020 10:23:39 +0200 Subject: [PATCH 225/237] differentiate copy for own untrusted device dialog --- src/i18n/strings/en_EN.json | 4 +++- src/verification.js | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 3b432c410d..b5b87054dc 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -310,9 +310,11 @@ "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s", "Light theme": "Light theme", "Dark theme": "Dark theme", - "Not Trusted": "Not Trusted", + "You signed in to a new session without verifying it:": "You signed in to a new session without verifying it:", + "Verify your other session using one of the options below.": "Verify your other session using one of the options below.", "%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) signed in to a new session without verifying it:", "Ask this user to verify their session, or manually verify it below.": "Ask this user to verify their session, or manually verify it below.", + "Not Trusted": "Not Trusted", "Manually Verify by Text": "Manually Verify by Text", "Interactively verify by Emoji": "Interactively verify by Emoji", "Done": "Done", diff --git a/src/verification.js b/src/verification.js index d7287552dd..f488b2ebeb 100644 --- a/src/verification.js +++ b/src/verification.js @@ -43,14 +43,26 @@ function UntrustedDeviceDialog(props) { const {device, user, onFinished} = props; const BaseDialog = sdk.getComponent("dialogs.BaseDialog"); const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); + let askToVerifyText; + let newSessionText; + + if (MatrixClientPeg.get().getUserId() === user.userId) { + newSessionText = _t("You signed in to a new session without verifying it:"); + askToVerifyText = _t("Verify your other session using one of the options below."); + } else { + newSessionText = _t("%(name)s (%(userId)s) signed in to a new session without verifying it:", + {name: user.displayName, userId: user.userId}); + askToVerifyText = _t("Ask this user to verify their session, or manually verify it below."); + } + return
-

{_t("%(name)s (%(userId)s) signed in to a new session without verifying it:", {name: user.displayName, userId: user.userId})}

+

{newSessionText}

{device.getDisplayName()} ({device.deviceId})

-

{_t("Ask this user to verify their session, or manually verify it below.")}

+

{askToVerifyText}

onFinished("legacy")}>{_t("Manually Verify by Text")} From ab82bf80484e69abff75ff2fcebd8f795f062852 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 5 May 2020 10:23:39 +0200 Subject: [PATCH 226/237] differentiate copy for own untrusted device dialog --- src/i18n/strings/en_EN.json | 4 +++- src/verification.js | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5544e3a8b1..8d2aa14419 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -306,9 +306,11 @@ "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s", "Light theme": "Light theme", "Dark theme": "Dark theme", - "Not Trusted": "Not Trusted", + "You signed in to a new session without verifying it:": "You signed in to a new session without verifying it:", + "Verify your other session using one of the options below.": "Verify your other session using one of the options below.", "%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) signed in to a new session without verifying it:", "Ask this user to verify their session, or manually verify it below.": "Ask this user to verify their session, or manually verify it below.", + "Not Trusted": "Not Trusted", "Manually Verify by Text": "Manually Verify by Text", "Interactively verify by Emoji": "Interactively verify by Emoji", "Done": "Done", diff --git a/src/verification.js b/src/verification.js index d7287552dd..f488b2ebeb 100644 --- a/src/verification.js +++ b/src/verification.js @@ -43,14 +43,26 @@ function UntrustedDeviceDialog(props) { const {device, user, onFinished} = props; const BaseDialog = sdk.getComponent("dialogs.BaseDialog"); const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); + let askToVerifyText; + let newSessionText; + + if (MatrixClientPeg.get().getUserId() === user.userId) { + newSessionText = _t("You signed in to a new session without verifying it:"); + askToVerifyText = _t("Verify your other session using one of the options below."); + } else { + newSessionText = _t("%(name)s (%(userId)s) signed in to a new session without verifying it:", + {name: user.displayName, userId: user.userId}); + askToVerifyText = _t("Ask this user to verify their session, or manually verify it below."); + } + return
-

{_t("%(name)s (%(userId)s) signed in to a new session without verifying it:", {name: user.displayName, userId: user.userId})}

+

{newSessionText}

{device.getDisplayName()} ({device.deviceId})

-

{_t("Ask this user to verify their session, or manually verify it below.")}

+

{askToVerifyText}

onFinished("legacy")}>{_t("Manually Verify by Text")} From 5aa645caf9401b4e53d006604dd7a223d4a368e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 5 May 2020 10:10:21 +0200 Subject: [PATCH 227/237] EventIndex: Reduce the logging the event index is producing. --- src/indexing/EventIndex.js | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index a6bbbb5f96..eed9837a7a 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -102,9 +102,6 @@ export default class EventIndex extends EventEmitter { const timeline = room.getLiveTimeline(); const token = timeline.getPaginationToken("b"); - console.log("EventIndex: Got token for indexer", - room.roomId, token); - const backCheckpoint = { roomId: room.roomId, token: token, @@ -161,7 +158,6 @@ export default class EventIndex extends EventEmitter { if (prevState === "SYNCING" && state === "SYNCING") { // A sync was done, presumably we queued up some live events, // commit them now. - console.log("EventIndex: Committing events"); await indexManager.commitLiveEvents(); return; } @@ -336,8 +332,6 @@ export default class EventIndex extends EventEmitter { async crawlerFunc() { let cancelled = false; - console.log("EventIndex: Started crawler function"); - const client = MatrixClientPeg.get(); const indexManager = PlatformPeg.get().getEventIndexingManager(); @@ -366,8 +360,6 @@ export default class EventIndex extends EventEmitter { await sleep(sleepTime); - console.log("EventIndex: Running the crawler loop."); - if (cancelled) { break; } @@ -386,8 +378,6 @@ export default class EventIndex extends EventEmitter { idle = false; - console.log("EventIndex: crawling using checkpoint", checkpoint); - // We have a checkpoint, let us fetch some messages, again, very // conservatively to not bother our homeserver too much. const eventMapper = client.getEventMapper({preventReEmit: true}); @@ -511,15 +501,6 @@ export default class EventIndex extends EventEmitter { direction: checkpoint.direction, }; - console.log( - "EventIndex: Crawled room", - client.getRoom(checkpoint.roomId).name, - "and fetched total", matrixEvents.length, "events of which", - events.length, "are being added,", redactionEvents.length, - "are redacted,", matrixEvents.length - events.length, - "are being skipped, undecryptable", undecryptableEvents.length, - ); - try { for (let i = 0; i < redactionEvents.length; i++) { const ev = redactionEvents[i]; @@ -552,8 +533,6 @@ export default class EventIndex extends EventEmitter { } this._crawler = null; - - console.log("EventIndex: Stopping crawler function"); } /** From 51a79a43e3186838d02349ee3106d748ac8e71fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 5 May 2020 10:21:18 +0200 Subject: [PATCH 228/237] EventIndex: Remove an unused variable. --- src/indexing/EventIndex.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index eed9837a7a..02151f8474 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -467,9 +467,6 @@ export default class EventIndex extends EventEmitter { // decryption keys, do we want to retry this checkpoint at a later // stage? const filteredEvents = matrixEvents.filter(this.isValidEvent); - const undecryptableEvents = matrixEvents.filter((ev) => { - return ev.isDecryptionFailure(); - }); // Collect the redaction events so we can delete the redacted events // from the index. From 1423c2e4bcd9be4d6d37b320b5962478d932921d Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 5 May 2020 11:04:24 +0100 Subject: [PATCH 229/237] Upgrade matrix-js-sdk to 6.0.0 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 19fa03b3d8..42db16f37f 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "6.0.0-rc.2", + "matrix-js-sdk": "6.0.0", "minimist": "^1.2.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index ae0a218e0e..1066e95e36 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5715,10 +5715,10 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -matrix-js-sdk@6.0.0-rc.2: - version "6.0.0-rc.2" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-6.0.0-rc.2.tgz#56eb438458cb59cf18bbd6126d72029dc728659f" - integrity sha512-osW5GIOAcCpY/wCxct9RMxRZhodkVBdEDVZuQm2nstKDLGafl5oxAit2LAz9g0ymv+16LBp8XbThM2GWa2lj2Q== +matrix-js-sdk@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-6.0.0.tgz#2374a583878073871a0202dc237691ef15540575" + integrity sha512-NBHb5JIKetCVhOdfETyhUL9lYs2M+v8W/uczTzW6IX9XFOtNaha8X82waXlRt6RJpZRm5aJveODkybvo9VOLtg== dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From e6c485c7e83d351e554ecbfcceaa7540b202fa14 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 5 May 2020 11:10:36 +0100 Subject: [PATCH 230/237] Prepare changelog for v2.5.0 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index df4a934a07..0706e20085 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +Changes in [2.5.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0) (2020-05-05) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.6...v2.5.0) + + * Upgrade to JS SDK 6.0.0 + * EventIndex: Reduce the logging the event index is producing. + [\#4551](https://github.com/matrix-org/matrix-react-sdk/pull/4551) + * Differentiate copy for own untrusted device dialog + [\#4550](https://github.com/matrix-org/matrix-react-sdk/pull/4550) + * More detailed progress for key backup progress + [\#4545](https://github.com/matrix-org/matrix-react-sdk/pull/4545) + * Increase rageshake size limit to 5mb + [\#4544](https://github.com/matrix-org/matrix-react-sdk/pull/4544) + Changes in [2.5.0-rc.6](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.6) (2020-05-01) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.5...v2.5.0-rc.6) From 854855a5aa568eb2ecbc08a806934fd42f394c45 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 5 May 2020 11:10:36 +0100 Subject: [PATCH 231/237] v2.5.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 42db16f37f..15d1267d0c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.5.0-rc.6", + "version": "2.5.0", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From aa0c6f1f71a6122579c74f3cba3a7925f35131ac Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 5 May 2020 11:40:37 +0100 Subject: [PATCH 232/237] Reset matrix-js-sdk back to develop branch --- package.json | 2 +- yarn.lock | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 0e538be35f..92d228a812 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "6.0.0", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "minimist": "^1.2.0", "pako": "^1.0.5", "parse5": "^5.1.1", diff --git a/yarn.lock b/yarn.lock index 8ca39b0d96..520e976b17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5720,10 +5720,9 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -matrix-js-sdk@6.0.0: +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": version "6.0.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-6.0.0.tgz#2374a583878073871a0202dc237691ef15540575" - integrity sha512-NBHb5JIKetCVhOdfETyhUL9lYs2M+v8W/uczTzW6IX9XFOtNaha8X82waXlRt6RJpZRm5aJveODkybvo9VOLtg== + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/f120533fadb309ac5dc8b2bcb6882e784ba93f18" dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From 781cbea74450e7acb982c41bfa54dbf43957f15f Mon Sep 17 00:00:00 2001 From: Zoe Date: Tue, 5 May 2020 15:39:37 +0100 Subject: [PATCH 233/237] Fix a crash where a name could unexpectedly be an empty list --- src/components/structures/RoomSubList.js | 40 ++++++++++++++++++++++-- src/components/views/rooms/RoomTile.js | 3 +- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index 1e3e15b4ec..4e8e51c3cc 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -37,6 +37,42 @@ import toRem from "../../utils/rem"; // turn this on for drop & drag console debugging galore const debug = false; +class RoomTileErrorBoundary extends React.PureComponent { + constructor(props) { + super(props); + + this.state = { + error: null, + }; + } + + static getDerivedStateFromError(error) { + // Side effects are not permitted here, so we only update the state so + // that the next render shows an error message. + return { error }; + } + + componentDidCatch(error, { componentStack }) { + // Browser consoles are better at formatting output when native errors are passed + // in their own `console.error` invocation. + console.error(error); + console.error( + "The above error occured while React was rendering the following components:", + componentStack, + ); + } + + render() { + if (this.state.error) { + return (
+ {this.props.roomId} +
); + } else { + return this.props.children; + } + } +} + export default class RoomSubList extends React.PureComponent { static displayName = 'RoomSubList'; static debug = debug; @@ -208,7 +244,7 @@ export default class RoomSubList extends React.PureComponent { }; makeRoomTile = (room) => { - return ; + />; }; _onNotifBadgeClick = (e) => { diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index f157ee0df7..6a23fe309b 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -432,10 +432,9 @@ export default createReactClass({ }); let name = this.state.roomName; - if (name == undefined || name == null) name = ''; + if (typeof name !== 'string') name = ''; name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon - let badge; if (badges) { const limitedCount = FormattingUtils.formatCount(notificationCount); From 0c5c2501e6df4e2805a6c37ec0383fc26fd62bd7 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 6 May 2020 12:23:03 +0200 Subject: [PATCH 234/237] remove prefixes as we're using data urls now --- src/editor/parts.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/editor/parts.js b/src/editor/parts.js index acd27ac219..0adc5573ea 100644 --- a/src/editor/parts.js +++ b/src/editor/parts.js @@ -259,7 +259,7 @@ class RoomPillPart extends PillPart { "crop"); if (!avatarUrl) { initialLetter = Avatar.getInitialLetter(this._room ? this._room.name : this.resourceId); - avatarUrl = `../../${Avatar.defaultAvatarUrlForString(this._room ? this._room.roomId : this.resourceId)}`; + avatarUrl = Avatar.defaultAvatarUrlForString(this._room ? this._room.roomId : this.resourceId); } this._setAvatarVars(node, avatarUrl, initialLetter); } @@ -291,18 +291,13 @@ class UserPillPart extends PillPart { } const name = this._member.name || this._member.userId; const defaultAvatarUrl = Avatar.defaultAvatarUrlForString(this._member.userId); - let avatarUrl = Avatar.avatarUrlForMember( + const avatarUrl = Avatar.avatarUrlForMember( this._member, 16 * window.devicePixelRatio, 16 * window.devicePixelRatio, "crop"); let initialLetter = ""; if (avatarUrl === defaultAvatarUrl) { - // the url from defaultAvatarUrlForString is meant to go in an img element, - // which has the base of the document. we're using it in css, - // which has the base of the theme css file, two levels deeper than the document, - // so go up to the level of the document. - avatarUrl = `../../${avatarUrl}`; initialLetter = Avatar.getInitialLetter(name); } this._setAvatarVars(node, avatarUrl, initialLetter); From 1767a611a6cb456cb504c97a3e1be04c710bc844 Mon Sep 17 00:00:00 2001 From: Dan Jenkins Date: Wed, 6 May 2020 16:23:06 +0100 Subject: [PATCH 235/237] set the meta tag for theme-color to the same theme css background --- src/theme.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/theme.js b/src/theme.js index ab5974f207..2ccce81a8d 100644 --- a/src/theme.js +++ b/src/theme.js @@ -242,6 +242,10 @@ export async function setTheme(theme) { if (a == styleElements[stylesheetName]) return; a.disabled = true; }); + const bodyStyles = global.getComputedStyle(document.getElementsByTagName("body")[0]); + if (bodyStyles.backgroundColor) { + document.querySelector('meta[name="theme-color"]').content = bodyStyles.backgroundColor; + } Tinter.setTheme(theme); resolve(); }; From 9ae812c346333f4c4b294add6438464c2591904f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 6 May 2020 15:17:55 -0600 Subject: [PATCH 236/237] Add a loading state for email addresses/phone numbers in settings Fixes https://github.com/vector-im/riot-web/issues/13432 --- .../tabs/user/_GeneralUserSettingsTab.scss | 6 +++ .../tabs/user/GeneralUserSettingsTab.js | 39 ++++++++++++------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss b/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss index 62d230e752..95a46b51ee 100644 --- a/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss @@ -23,6 +23,12 @@ limitations under the License. margin-top: 0; } +.mx_GeneralUserSettingsTab_accountSection .mx_Spinner, +.mx_GeneralUserSettingsTab_discovery .mx_Spinner { + // Move the spinner to the left side of the container (default center) + justify-content: left; +} + .mx_GeneralUserSettingsTab_accountSection .mx_EmailAddresses, .mx_GeneralUserSettingsTab_accountSection .mx_PhoneNumbers, .mx_GeneralUserSettingsTab_discovery .mx_ExistingEmailAddress, diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 801062bff4..867982ad2b 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -38,6 +38,7 @@ import {SERVICE_TYPES} from "matrix-js-sdk"; import IdentityAuthClient from "../../../../../IdentityAuthClient"; import {abbreviateUrl} from "../../../../../utils/UrlUtils"; import { getThreepidsWithBindStatus } from '../../../../../boundThreepids'; +import Spinner from "../../../elements/Spinner"; export default class GeneralUserSettingsTab extends React.Component { static propTypes = { @@ -60,6 +61,7 @@ export default class GeneralUserSettingsTab extends React.Component { }, emails: [], msisdns: [], + loading3pids: true, // whether or not the emails and msisdns have been loaded ...this._calculateThemeState(), customThemeUrl: "", customThemeMessage: {isError: false, text: ""}, @@ -158,8 +160,11 @@ export default class GeneralUserSettingsTab extends React.Component { ); console.warn(e); } - this.setState({ emails: threepids.filter((a) => a.medium === 'email') }); - this.setState({ msisdns: threepids.filter((a) => a.medium === 'msisdn') }); + this.setState({ + emails: threepids.filter((a) => a.medium === 'email'), + msisdns: threepids.filter((a) => a.medium === 'msisdn'), + loading3pids: false, + }); } async _checkTerms() { @@ -325,7 +330,6 @@ export default class GeneralUserSettingsTab extends React.Component { const ChangePassword = sdk.getComponent("views.settings.ChangePassword"); const EmailAddresses = sdk.getComponent("views.settings.account.EmailAddresses"); const PhoneNumbers = sdk.getComponent("views.settings.account.PhoneNumbers"); - const Spinner = sdk.getComponent("views.elements.Spinner"); let passwordChangeForm = ( - {_t("Email addresses")} - + : - - {_t("Phone numbers")} - ; + const msisdns = this.state.loading3pids + ? + : + />; + threepidSection =
+ {_t("Email addresses")} + {emails} + + {_t("Phone numbers")} + {msisdns}
; } else if (this.state.serverSupportsSeparateAddAndBind === null) { threepidSection = ; @@ -491,12 +501,15 @@ export default class GeneralUserSettingsTab extends React.Component { const EmailAddresses = sdk.getComponent("views.settings.discovery.EmailAddresses"); const PhoneNumbers = sdk.getComponent("views.settings.discovery.PhoneNumbers"); + const emails = this.state.loading3pids ? : ; + const msisdns = this.state.loading3pids ? : ; + const threepidSection = this.state.haveIdServer ?
{_t("Email addresses")} - + {emails} {_t("Phone numbers")} - + {msisdns}
: null; return ( From 0b5691c0032d5145c57925dc40fa6d090eb02da6 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 7 May 2020 09:43:14 +0100 Subject: [PATCH 237/237] Fix right panel hiding when viewing room member If you clicked on the header button whilst the right panel was showing a room member, it would NPE because there was no refireParams.member. It fires the same phase with no refireParams to toggle the panel visibility (apparently), so detect that case. Fixes https://github.com/vector-im/riot-web/issues/13571 --- src/stores/RightPanelStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/RightPanelStore.js b/src/stores/RightPanelStore.js index 8869d0be42..3a5605ba3f 100644 --- a/src/stores/RightPanelStore.js +++ b/src/stores/RightPanelStore.js @@ -139,7 +139,7 @@ export default class RightPanelStore extends Store { let targetPhase = payload.phase; let refireParams = payload.refireParams; // redirect to EncryptionPanel if there is an ongoing verification request - if (targetPhase === RIGHT_PANEL_PHASES.RoomMemberInfo) { + if (targetPhase === RIGHT_PANEL_PHASES.RoomMemberInfo && payload.refireParams) { const {member} = payload.refireParams; const pendingRequest = pendingVerificationRequestForUser(member); if (pendingRequest) {