From c6a058fb6fa0af190c117c2f3b5bc01a6eab17e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 19 Dec 2020 19:32:58 +0100 Subject: [PATCH 01/60] Added surround with MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../views/rooms/BasicMessageComposer.tsx | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index 2ececdeaed..cd34e25926 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -418,6 +418,10 @@ export default class BasicMessageEditor extends React.Component }; private onKeyDown = (event: React.KeyboardEvent) => { + const selectionRange = getRangeForSelection(this.editorRef.current, this.props.model, document.getSelection()); + // trim the range as we want it to exclude leading/trailing spaces + selectionRange.trim(); + const model = this.props.model; const modKey = IS_MAC ? event.metaKey : event.ctrlKey; let handled = false; @@ -471,6 +475,43 @@ export default class BasicMessageEditor extends React.Component }); handled = true; // autocomplete or enter to send below shouldn't have any modifier keys pressed. + } else if (document.getSelection().type != "Caret") { + if (event.key === '(') { + this.historyManager.ensureLastChangesPushed(this.props.model); + this.modifiedFlag = true; + toggleInlineFormat(selectionRange, "(", ")"); + handled = true; + } else if (event.key === '[') { + this.historyManager.ensureLastChangesPushed(this.props.model); + this.modifiedFlag = true; + toggleInlineFormat(selectionRange, "[", "]"); + handled = true; + } else if (event.key === '{') { + this.historyManager.ensureLastChangesPushed(this.props.model); + this.modifiedFlag = true; + toggleInlineFormat(selectionRange, "{", "}"); + handled = true; + } else if (event.key === '<') { + this.historyManager.ensureLastChangesPushed(this.props.model); + this.modifiedFlag = true; + toggleInlineFormat(selectionRange, "<", ">"); + handled = true; + } else if (event.key === '"') { + this.historyManager.ensureLastChangesPushed(this.props.model); + this.modifiedFlag = true; + toggleInlineFormat(selectionRange, "\""); + handled = true; + } else if (event.key === '`') { + this.historyManager.ensureLastChangesPushed(this.props.model); + this.modifiedFlag = true; + toggleInlineFormat(selectionRange, "`"); + handled = true; + } else if (event.key === '\'') { + this.historyManager.ensureLastChangesPushed(this.props.model); + this.modifiedFlag = true; + toggleInlineFormat(selectionRange, "'"); + handled = true; + } } else { const metaOrAltPressed = event.metaKey || event.altKey; const modifierPressed = metaOrAltPressed || event.shiftKey; From e90f5ddf5b6ac14648d7fc36ecf414a04d668c4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 19 Dec 2020 19:36:56 +0100 Subject: [PATCH 02/60] Added a comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/BasicMessageComposer.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index cd34e25926..587f13e8c2 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -512,6 +512,7 @@ export default class BasicMessageEditor extends React.Component toggleInlineFormat(selectionRange, "'"); handled = true; } + // Surround selected text with a character } else { const metaOrAltPressed = event.metaKey || event.altKey; const modifierPressed = metaOrAltPressed || event.shiftKey; From b330dd55a0cd61fe9b014d47c6dcfb085e835b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 07:53:09 +0100 Subject: [PATCH 03/60] Hide surround with behind a setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/BasicMessageComposer.tsx | 3 ++- .../views/settings/tabs/user/PreferencesUserSettingsTab.js | 1 + src/settings/Settings.ts | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index 587f13e8c2..a91e92123b 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -418,6 +418,7 @@ export default class BasicMessageEditor extends React.Component }; private onKeyDown = (event: React.KeyboardEvent) => { + const surroundWith = SettingsStore.getValue("MessageComposerInput.surroundWith"); const selectionRange = getRangeForSelection(this.editorRef.current, this.props.model, document.getSelection()); // trim the range as we want it to exclude leading/trailing spaces selectionRange.trim(); @@ -475,7 +476,7 @@ export default class BasicMessageEditor extends React.Component }); handled = true; // autocomplete or enter to send below shouldn't have any modifier keys pressed. - } else if (document.getSelection().type != "Caret") { + } else if (surroundWith && document.getSelection().type != "Caret") { if (event.key === '(') { this.historyManager.ensureLastChangesPushed(this.props.model); this.modifiedFlag = true; diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js index 4d8493401e..2544c03a22 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js @@ -34,6 +34,7 @@ export default class PreferencesUserSettingsTab extends React.Component { 'MessageComposerInput.suggestEmoji', 'sendTypingNotifications', 'MessageComposerInput.ctrlEnterToSend', + 'MessageComposerInput.surroundWith', ]; static TIMELINE_SETTINGS = [ diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index b239b809fe..ed9b37d632 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -336,6 +336,11 @@ export const SETTINGS: {[setting: string]: ISetting} = { displayName: isMac ? _td("Use Command + Enter to send a message") : _td("Use Ctrl + Enter to send a message"), default: false, }, + "MessageComposerInput.surroundWith": { + supportedLevels: LEVELS_ACCOUNT_SETTINGS, + displayName: _td("Use surround with"), + default: false, + }, "MessageComposerInput.autoReplaceEmoji": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td('Automatically replace plain text Emoji'), From 3f0d7673725f12b99e48b0f2e94c9c0f78f9c5d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 07:57:15 +0100 Subject: [PATCH 04/60] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/i18n/strings/en_EN.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a9d31bb9f2..3af2a62c94 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -816,6 +816,7 @@ "Use Ctrl + F to search": "Use Ctrl + F to search", "Use Command + Enter to send a message": "Use Command + Enter to send a message", "Use Ctrl + Enter to send a message": "Use Ctrl + Enter to send a message", + "Use surround with": "Use surround with", "Automatically replace plain text Emoji": "Automatically replace plain text Emoji", "Mirror local video feed": "Mirror local video feed", "Enable Community Filter Panel": "Enable Community Filter Panel", From cf25e15eb6d3071dccb92c07e1f96bd726d56755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20V=C3=A1gner?= Date: Sat, 12 Jun 2021 12:49:15 +0200 Subject: [PATCH 05/60] Make call control buttons accessible to screen reader users MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Vágner --- src/components/views/voip/CallView.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index c084dacaa8..178df246d1 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -441,6 +441,7 @@ export default class CallView extends React.Component { const vidMuteButton = this.props.call.type === CallType.Video ? : null; // The dial pad & 'more' button actions are only relevant in a connected call @@ -450,6 +451,7 @@ export default class CallView extends React.Component { inputRef={this.dialpadButton} onClick={this.onDialpadClick} isExpanded={this.state.showDialpad} + aria-label={_t("Dialpad")} /> :
; const contextMenuButton = this.state.callState === CallState.Connected ? { onClick={this.onMoreClick} inputRef={this.contextMenuButton} isExpanded={this.state.showMoreMenu} + aria-label={_t("More")} /> :
; // in the near future, the dial pad button will go on the left. For now, it's the nothing button @@ -466,6 +469,7 @@ export default class CallView extends React.Component { Date: Sat, 12 Jun 2021 13:53:44 +0200 Subject: [PATCH 06/60] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Vágner --- src/i18n/strings/en_EN.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 874dc11bd2..7df22432de 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -889,6 +889,12 @@ "sends snowfall": "sends snowfall", "Sends the given message with a space themed effect": "Sends the given message with a space themed effect", "sends space invaders": "sends space invaders", + "Start the camera": "Start the camera", + "Stop the camera": "Stop the camera", + "Dialpad": "Dialpad", + "More": "More", + "Unmute the microphone": "Unmute the microphone", + "Mute the microphone": "Mute the microphone", "unknown person": "unknown person", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Consulting with %(transferTarget)s. Transfer to %(transferee)s", "You held the call Switch": "You held the call Switch", From a94d11235ed5352b8da0ae87964abf2a00eddb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20V=C3=A1gner?= Date: Sat, 12 Jun 2021 14:17:10 +0200 Subject: [PATCH 07/60] Changed the buttons to TooltipButtons and added the tooltip for the hangup button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Vágner --- src/components/views/voip/CallView.tsx | 21 ++++++++++++--------- src/i18n/strings/en_EN.json | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 178df246d1..66b3f6b2d4 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -25,6 +25,8 @@ import RoomAvatar from "../avatars/RoomAvatar"; import { CallState, CallType, MatrixCall, CallEvent } from 'matrix-js-sdk/src/webrtc/call'; import classNames from 'classnames'; import AccessibleButton from '../elements/AccessibleButton'; +import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; +import { ContextMenuTooltipButton } from "../../../accessibility/context_menu/ContextMenuTooltipButton"; import {isOnlyCtrlOrCmdKeyEvent, Key} from '../../../Keyboard'; import {alwaysAboveLeftOf, alwaysAboveRightOf, ChevronFace, ContextMenuButton} from '../../structures/ContextMenu'; import CallContextMenu from '../context_menus/CallContextMenu'; @@ -438,40 +440,40 @@ export default class CallView extends React.Component { mx_CallView_callControls_hidden: !this.state.controlsVisible, }); - const vidMuteButton = this.props.call.type === CallType.Video ? : null; // The dial pad & 'more' button actions are only relevant in a connected call // When not connected, we have to put something there to make the flexbox alignment correct - const dialpadButton = this.state.callState === CallState.Connected ? :
; - const contextMenuButton = this.state.callState === CallState.Connected ? :
; // in the near future, the dial pad button will go on the left. For now, it's the nothing button // because something needs to have margin-right: auto to make the alignment correct. const callControls =
{dialpadButton} - - { dis.dispatch({ @@ -479,6 +481,7 @@ export default class CallView extends React.Component { room_id: callRoomId, }); }} + title={_t("Hangup")} /> {vidMuteButton}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 7df22432de..d50348954a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -895,6 +895,7 @@ "More": "More", "Unmute the microphone": "Unmute the microphone", "Mute the microphone": "Mute the microphone", + "Hangup": "Hangup", "unknown person": "unknown person", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Consulting with %(transferTarget)s. Transfer to %(transferee)s", "You held the call Switch": "You held the call Switch", From fd7eaddb2d4c170084fbfc6ca3ca4c26f40a57b9 Mon Sep 17 00:00:00 2001 From: pvagner Date: Wed, 16 Jun 2021 10:18:35 +0200 Subject: [PATCH 08/60] Update src/components/views/voip/CallView.tsx Co-authored-by: Michael Telatynski <7t3chguy@googlemail.com> --- src/components/views/voip/CallView.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 66b3f6b2d4..f7f82d4300 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -26,9 +26,13 @@ import { CallState, CallType, MatrixCall, CallEvent } from 'matrix-js-sdk/src/we import classNames from 'classnames'; import AccessibleButton from '../elements/AccessibleButton'; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; -import { ContextMenuTooltipButton } from "../../../accessibility/context_menu/ContextMenuTooltipButton"; import {isOnlyCtrlOrCmdKeyEvent, Key} from '../../../Keyboard'; -import {alwaysAboveLeftOf, alwaysAboveRightOf, ChevronFace, ContextMenuButton} from '../../structures/ContextMenu'; +import { + alwaysAboveLeftOf, + alwaysAboveRightOf, + ChevronFace, + ContextMenuTooltipButton, +} from '../../structures/ContextMenu'; import CallContextMenu from '../context_menus/CallContextMenu'; import { avatarUrlForMember } from '../../../Avatar'; import DialpadContextMenu from '../context_menus/DialpadContextMenu'; From 38c0cd27163effd85b5c12cd499f6291e1a06c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 20 Jun 2021 08:21:33 +0200 Subject: [PATCH 09/60] Cache surroundWith setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../views/rooms/BasicMessageComposer.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index f5fddff45b..de72f8a348 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -107,6 +107,7 @@ interface IState { showVisualBell?: boolean; autoComplete?: AutocompleteWrapperModel; completionIndex?: number; + surroundWith: boolean, } @replaceableComponent("views.rooms.BasicMessageEditor") @@ -125,12 +126,14 @@ export default class BasicMessageEditor extends React.Component private readonly emoticonSettingHandle: string; private readonly shouldShowPillAvatarSettingHandle: string; + private readonly surroundWithHandle: string; private readonly historyManager = new HistoryManager(); constructor(props) { super(props); this.state = { showPillAvatar: SettingsStore.getValue("Pill.shouldShowPillAvatar"), + surroundWith: SettingsStore.getValue("MessageComposerInput.surroundWith"), }; this.emoticonSettingHandle = SettingsStore.watchSetting('MessageComposerInput.autoReplaceEmoji', null, @@ -138,6 +141,8 @@ export default class BasicMessageEditor extends React.Component this.configureEmoticonAutoReplace(); this.shouldShowPillAvatarSettingHandle = SettingsStore.watchSetting("Pill.shouldShowPillAvatar", null, this.configureShouldShowPillAvatar); + this.surroundWithHandle = SettingsStore.watchSetting("MessageComposerInput.surroundWith", null, + this.surroundWithSettingChanged); } public componentDidUpdate(prevProps: IProps) { @@ -428,7 +433,6 @@ export default class BasicMessageEditor extends React.Component }; private onKeyDown = (event: React.KeyboardEvent) => { - const surroundWith = SettingsStore.getValue("MessageComposerInput.surroundWith"); const selectionRange = getRangeForSelection(this.editorRef.current, this.props.model, document.getSelection()); // trim the range as we want it to exclude leading/trailing spaces selectionRange.trim(); @@ -436,7 +440,7 @@ export default class BasicMessageEditor extends React.Component const model = this.props.model; let handled = false; - if (surroundWith && document.getSelection().type != "Caret") { + if (this.state.surroundWith && document.getSelection().type != "Caret") { // Surround selected text with a character if (event.key === '(') { this.historyManager.ensureLastChangesPushed(this.props.model); @@ -628,6 +632,11 @@ export default class BasicMessageEditor extends React.Component this.setState({ showPillAvatar }); }; + private surroundWithSettingChanged = () => { + const surroundWith = SettingsStore.getValue("MessageComposerInput.surroundWith"); + this.setState({ surroundWith }); + }; + componentWillUnmount() { document.removeEventListener("selectionchange", this.onSelectionChange); this.editorRef.current.removeEventListener("input", this.onInput, true); @@ -635,6 +644,7 @@ export default class BasicMessageEditor extends React.Component this.editorRef.current.removeEventListener("compositionend", this.onCompositionEnd, true); SettingsStore.unwatchSetting(this.emoticonSettingHandle); SettingsStore.unwatchSetting(this.shouldShowPillAvatarSettingHandle); + SettingsStore.unwatchSetting(this.surroundWithHandle); } componentDidMount() { From a772460f63681b85fbc1ad9d972d329d871cbd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 20 Jun 2021 08:38:01 +0200 Subject: [PATCH 10/60] Simplifie surround with and make it more extensible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../views/rooms/BasicMessageComposer.tsx | 45 +++++++------------ 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index de72f8a348..239624f5d8 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -55,6 +55,14 @@ const REGEX_EMOTICON_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.sourc const IS_MAC = navigator.platform.indexOf("Mac") !== -1; +const SURROUND_WITH_CHARACTERS = ["\"", "_", "`", "'", "*", "~", "$"]; +const SURROUND_WITH_DOUBLE_CHARACTERS = new Map([ + ["(", ")"], + ["[", "]"], + ["{", "}"], + ["<", ">"], +]); + function ctrlShortcutLabel(key) { return (IS_MAC ? "⌘" : "Ctrl") + "+" + key; } @@ -441,41 +449,18 @@ export default class BasicMessageEditor extends React.Component let handled = false; if (this.state.surroundWith && document.getSelection().type != "Caret") { - // Surround selected text with a character - if (event.key === '(') { + // This surrounds the selected text with a character. This is + // intentionally left out of the keybinding manager as the keybinds + // here shouldn't be changeable + if (SURROUND_WITH_CHARACTERS.includes(event.key)) { this.historyManager.ensureLastChangesPushed(this.props.model); this.modifiedFlag = true; - toggleInlineFormat(selectionRange, "(", ")"); + toggleInlineFormat(selectionRange, event.key); handled = true; - } else if (event.key === '[') { + } else if ([...SURROUND_WITH_DOUBLE_CHARACTERS.keys()].includes(event.key)) { this.historyManager.ensureLastChangesPushed(this.props.model); this.modifiedFlag = true; - toggleInlineFormat(selectionRange, "[", "]"); - handled = true; - } else if (event.key === '{') { - this.historyManager.ensureLastChangesPushed(this.props.model); - this.modifiedFlag = true; - toggleInlineFormat(selectionRange, "{", "}"); - handled = true; - } else if (event.key === '<') { - this.historyManager.ensureLastChangesPushed(this.props.model); - this.modifiedFlag = true; - toggleInlineFormat(selectionRange, "<", ">"); - handled = true; - } else if (event.key === '"') { - this.historyManager.ensureLastChangesPushed(this.props.model); - this.modifiedFlag = true; - toggleInlineFormat(selectionRange, "\""); - handled = true; - } else if (event.key === '`') { - this.historyManager.ensureLastChangesPushed(this.props.model); - this.modifiedFlag = true; - toggleInlineFormat(selectionRange, "`"); - handled = true; - } else if (event.key === '\'') { - this.historyManager.ensureLastChangesPushed(this.props.model); - this.modifiedFlag = true; - toggleInlineFormat(selectionRange, "'"); + toggleInlineFormat(selectionRange, event.key, SURROUND_WITH_DOUBLE_CHARACTERS.get(event.key)); handled = true; } } From 3e97847e7de3830e4a63d2d884a374a9091b03eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 20 Jun 2021 08:47:21 +0200 Subject: [PATCH 11/60] Get selection range only if necessary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/BasicMessageComposer.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index 239624f5d8..d8a872f1c6 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -441,10 +441,6 @@ export default class BasicMessageEditor extends React.Component }; private onKeyDown = (event: React.KeyboardEvent) => { - const selectionRange = getRangeForSelection(this.editorRef.current, this.props.model, document.getSelection()); - // trim the range as we want it to exclude leading/trailing spaces - selectionRange.trim(); - const model = this.props.model; let handled = false; @@ -452,6 +448,15 @@ export default class BasicMessageEditor extends React.Component // This surrounds the selected text with a character. This is // intentionally left out of the keybinding manager as the keybinds // here shouldn't be changeable + + const selectionRange = getRangeForSelection( + this.editorRef.current, + this.props.model, + document.getSelection(), + ); + // trim the range as we want it to exclude leading/trailing spaces + selectionRange.trim(); + if (SURROUND_WITH_CHARACTERS.includes(event.key)) { this.historyManager.ensureLastChangesPushed(this.props.model); this.modifiedFlag = true; From 314ab7a94d7868c6375d3efca8d46d6c4f97ffa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 21 Jun 2021 11:20:20 +0200 Subject: [PATCH 12/60] If there already is a Jitsi widget pin it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/CallHandler.tsx | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 448b1cb780..5138d526dd 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -61,7 +61,6 @@ import Modal from './Modal'; import { _t } from './languageHandler'; import dis from './dispatcher/dispatcher'; import WidgetUtils from './utils/WidgetUtils'; -import WidgetEchoStore from './stores/WidgetEchoStore'; import SettingsStore from './settings/SettingsStore'; import {Jitsi} from "./widgets/Jitsi"; import {WidgetType} from "./widgets/WidgetType"; @@ -88,6 +87,7 @@ import { randomUppercaseString, randomLowercaseString } from "matrix-js-sdk/src/ import EventEmitter from 'events'; import SdkConfig from './SdkConfig'; import { ensureDMExists, findDMForUser } from './createRoom'; +import { WidgetLayoutStore, Container } from './stores/widgets/WidgetLayoutStore'; export const PROTOCOL_PSTN = 'm.protocol.pstn'; export const PROTOCOL_PSTN_PREFIXED = 'im.vector.protocol.pstn'; @@ -940,14 +940,10 @@ export default class CallHandler extends EventEmitter { // prevent double clicking the call button const room = MatrixClientPeg.get().getRoom(roomId); - const currentJitsiWidgets = WidgetUtils.getRoomWidgetsOfType(room, WidgetType.JITSI); - const hasJitsi = currentJitsiWidgets.length > 0 - || WidgetEchoStore.roomHasPendingWidgetsOfType(roomId, currentJitsiWidgets, WidgetType.JITSI); - if (hasJitsi) { - Modal.createTrackedDialog('Call already in progress', '', ErrorDialog, { - title: _t('Call in Progress'), - description: _t('A call is currently being placed!'), - }); + const jitsiWidget = WidgetStore.instance.getApps(roomId).find((app) => WidgetType.JITSI.matches(app.type)); + if (jitsiWidget) { + // If there already is a Jitsi widget pin it + WidgetLayoutStore.instance.moveToContainer(room, jitsiWidget, Container.Top); return; } From ce47662b55e4296ad73cd395109934c4fe689ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 21 Jun 2021 11:23:49 +0200 Subject: [PATCH 13/60] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/i18n/strings/en_EN.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index b88dc79da5..1401fca4ba 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -65,8 +65,6 @@ "You cannot place a call with yourself.": "You cannot place a call with yourself.", "Unable to look up phone number": "Unable to look up phone number", "There was an error looking up the phone number": "There was an error looking up the phone number", - "Call in Progress": "Call in Progress", - "A call is currently being placed!": "A call is currently being placed!", "Permission Required": "Permission Required", "You do not have permission to start a conference call in this room": "You do not have permission to start a conference call in this room", "End conference": "End conference", From d7b10e2ff4704afc17ed22983f086fa44b22d270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 21 Jun 2021 17:26:06 +0200 Subject: [PATCH 14/60] Simplifie code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/BasicMessageComposer.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index d8a872f1c6..06759d0bf5 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -457,12 +457,7 @@ export default class BasicMessageEditor extends React.Component // trim the range as we want it to exclude leading/trailing spaces selectionRange.trim(); - if (SURROUND_WITH_CHARACTERS.includes(event.key)) { - this.historyManager.ensureLastChangesPushed(this.props.model); - this.modifiedFlag = true; - toggleInlineFormat(selectionRange, event.key); - handled = true; - } else if ([...SURROUND_WITH_DOUBLE_CHARACTERS.keys()].includes(event.key)) { + if ([...SURROUND_WITH_DOUBLE_CHARACTERS.keys(), ...SURROUND_WITH_CHARACTERS].includes(event.key)) { this.historyManager.ensureLastChangesPushed(this.props.model); this.modifiedFlag = true; toggleInlineFormat(selectionRange, event.key, SURROUND_WITH_DOUBLE_CHARACTERS.get(event.key)); From b2292268bc9a551a1b9ecfe535eafd3b823789d4 Mon Sep 17 00:00:00 2001 From: pvagner Date: Wed, 30 Jun 2021 07:06:10 +0200 Subject: [PATCH 15/60] Update src/components/views/voip/CallView.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Šimon Brandner --- src/components/views/voip/CallView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 6cb245f7b1..3f959622e7 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -26,7 +26,7 @@ import { CallState, CallType, MatrixCall, CallEvent } from 'matrix-js-sdk/src/we import classNames from 'classnames'; import AccessibleButton from '../elements/AccessibleButton'; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; -import { isOnlyCtrlOrCmdKeyEvent, Key} from '../../../Keyboard'; +import { isOnlyCtrlOrCmdKeyEvent, Key } from '../../../Keyboard'; import { alwaysAboveLeftOf, alwaysAboveRightOf, From caefefc2c22704fc4f678a680592d885880193d0 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Tue, 27 Jul 2021 17:22:49 -0400 Subject: [PATCH 16/60] Add regional indicators to emoji picker Signed-off-by: Robin Townsend --- src/emoji.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/emoji.ts b/src/emoji.ts index 321eae63f6..1445f737d6 100644 --- a/src/emoji.ts +++ b/src/emoji.ts @@ -35,6 +35,9 @@ export const EMOTICON_TO_EMOJI = new Map(); export const getEmojiFromUnicode = unicode => UNICODE_TO_EMOJI.get(stripVariation(unicode)); +const isRegionalIndicator = (x: string) => + Array.from(x).length === 1 && x >= '\u{1f1e6}' && x <= '\u{1f1ff}'; + const EMOJIBASE_GROUP_ID_TO_CATEGORY = [ "people", // smileys "people", // actually people @@ -72,7 +75,11 @@ export const EMOJI: IEmoji[] = EMOJIBASE.map((emojiData: Omit Date: Tue, 27 Jul 2021 17:35:34 -0400 Subject: [PATCH 17/60] Add more types Signed-off-by: Robin Townsend --- src/emoji.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emoji.ts b/src/emoji.ts index 1445f737d6..e871e0bb58 100644 --- a/src/emoji.ts +++ b/src/emoji.ts @@ -35,7 +35,7 @@ export const EMOTICON_TO_EMOJI = new Map(); export const getEmojiFromUnicode = unicode => UNICODE_TO_EMOJI.get(stripVariation(unicode)); -const isRegionalIndicator = (x: string) => +const isRegionalIndicator = (x: string): boolean => Array.from(x).length === 1 && x >= '\u{1f1e6}' && x <= '\u{1f1ff}'; const EMOJIBASE_GROUP_ID_TO_CATEGORY = [ From f16b1d46b72430715a75bac495b6ac19e94efe44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 28 Jul 2021 20:58:24 +0200 Subject: [PATCH 18/60] Fix sizing issue of the screen picker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/elements/_DesktopCapturerSourcePicker.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/res/css/views/elements/_DesktopCapturerSourcePicker.scss b/res/css/views/elements/_DesktopCapturerSourcePicker.scss index 49a0a44417..bd81aafef3 100644 --- a/res/css/views/elements/_DesktopCapturerSourcePicker.scss +++ b/res/css/views/elements/_DesktopCapturerSourcePicker.scss @@ -35,7 +35,6 @@ limitations under the License. .mx_desktopCapturerSourcePicker_source_thumbnail { margin: 4px; padding: 4px; - width: 312px; border-width: 2px; border-radius: 8px; border-style: solid; @@ -53,6 +52,5 @@ limitations under the License. white-space: nowrap; text-overflow: ellipsis; overflow: hidden; - width: 312px; } } From 7fd14c9ccc5c1cbee3d27d7880a7de285509971a Mon Sep 17 00:00:00 2001 From: Dariusz Niemczyk Date: Sun, 1 Aug 2021 16:18:06 +0200 Subject: [PATCH 19/60] Add data-mx-theme to theme css for hot-reload --- src/theme.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/theme.js b/src/theme.js index 2caf48b65a..cd14d2d9db 100644 --- a/src/theme.js +++ b/src/theme.js @@ -171,15 +171,10 @@ export async function setTheme(theme) { // look for the stylesheet elements. // styleElements is a map from style name to HTMLLinkElement. const styleElements = Object.create(null); - let a; - for (let i = 0; (a = document.getElementsByTagName("link")[i]); i++) { - const href = a.getAttribute("href"); - // shouldn't we be using the 'title' tag rather than the href? - const match = href && href.match(/^bundles\/.*\/theme-(.*)\.css$/); - if (match) { - styleElements[match[1]] = a; - } - } + const themes = Array.from(document.querySelectorAll('[data-mx-theme]')); + themes.forEach(theme => { + styleElements[theme.attributes['data-mx-theme'].value.toLowerCase()] = theme; + }); if (!(stylesheetName in styleElements)) { throw new Error("Unknown theme " + stylesheetName); From c5d11a9f17b9e523ecffe28c31102b0a3b4d63e9 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 2 Aug 2021 23:29:46 -0600 Subject: [PATCH 20/60] Improve voice messages uploading state Fixes https://github.com/vector-im/element-web/issues/18226 Fixes https://github.com/vector-im/element-web/issues/18224 --- .../views/rooms/_VoiceRecordComposerTile.scss | 11 ++++ .../views/rooms/VoiceRecordComposerTile.tsx | 54 ++++++++++++++----- src/i18n/strings/en_EN.json | 3 +- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/res/css/views/rooms/_VoiceRecordComposerTile.scss b/res/css/views/rooms/_VoiceRecordComposerTile.scss index 5501ab343e..3d8d0e5ecc 100644 --- a/res/css/views/rooms/_VoiceRecordComposerTile.scss +++ b/res/css/views/rooms/_VoiceRecordComposerTile.scss @@ -46,6 +46,17 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/trashcan.svg'); } +.mx_VoiceRecordComposerTile_uploadState { + margin-right: 21px; + color: $secondary-fg-color; + + .mx_VoiceRecordComposerTile_uploadState_badge { + display: inline-block; + margin-right: 4px; + vertical-align: middle; + } +} + .mx_MessageComposer_row .mx_VoiceMessagePrimaryContainer { // Note: remaining class properties are in the PlayerContainer CSS. diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index 8323320520..490d6b2231 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -17,10 +17,7 @@ limitations under the License. import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import { _t } from "../../../languageHandler"; import React, { ReactNode } from "react"; -import { - RecordingState, - VoiceRecording, -} from "../../../audio/VoiceRecording"; +import { IUpload, RecordingState, VoiceRecording } from "../../../audio/VoiceRecording"; import { Room } from "matrix-js-sdk/src/models/room"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import classNames from "classnames"; @@ -34,6 +31,10 @@ import { MsgType } from "matrix-js-sdk/src/@types/event"; import Modal from "../../../Modal"; import ErrorDialog from "../dialogs/ErrorDialog"; import MediaDeviceHandler, { MediaDeviceKindEnum } from "../../../MediaDeviceHandler"; +import NotificationBadge from "./NotificationBadge"; +import { StaticNotificationState } from "../../../stores/notifications/StaticNotificationState"; +import { NotificationColor } from "../../../stores/notifications/NotificationColor"; +import InlineSpinner from "../elements/InlineSpinner"; interface IProps { room: Room; @@ -42,6 +43,7 @@ interface IProps { interface IState { recorder?: VoiceRecording; recordingPhase?: RecordingState; + didUploadFail?: boolean; } /** @@ -69,9 +71,19 @@ export default class VoiceRecordComposerTile extends React.PureComponent { @@ -234,7 +245,26 @@ export default class VoiceRecordComposerTile extends React.PureComponent; } + let uploadIndicator; + if (this.state.recordingPhase === RecordingState.Uploading) { + uploadIndicator = + + { _t("Uploading...") } + ; + } else if (this.state.didUploadFail && this.state.recordingPhase === RecordingState.Ended) { + uploadIndicator = + + { /* Need to stick the badge in a span to ensure it doesn't create a block component */ } + + + { _t("Failed to upload voice message") } + ; + } + return (<> + { uploadIndicator } { deleteButton } { this.renderWaveformArea() } { recordingInfo } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 87cd9afb5b..c929bd683b 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1701,7 +1701,6 @@ "Invited by %(sender)s": "Invited by %(sender)s", "Jump to first unread message.": "Jump to first unread message.", "Mark all as read": "Mark all as read", - "The voice message failed to upload.": "The voice message failed to upload.", "Unable to access your microphone": "Unable to access your microphone", "We were unable to access your microphone. Please check your browser settings and try again.": "We were unable to access your microphone. Please check your browser settings and try again.", "No microphone found": "No microphone found", @@ -1709,6 +1708,8 @@ "Record a voice message": "Record a voice message", "Stop the recording": "Stop the recording", "Delete recording": "Delete recording", + "Uploading...": "Uploading...", + "Failed to upload voice message": "Failed to upload voice message", "Error updating main address": "Error updating main address", "There was an error updating the room's main address. It may not be allowed by the server or a temporary failure occurred.": "There was an error updating the room's main address. It may not be allowed by the server or a temporary failure occurred.", "There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.": "There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.", From 37f51c7536d878ad93767155037d6f9264bac50f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 3 Aug 2021 14:48:39 +0200 Subject: [PATCH 21/60] Don't ring if it's disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/CallHandler.tsx | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index e7c1dda54f..d4a29a11b9 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -1,7 +1,8 @@ /* Copyright 2015, 2016 OpenMarket Ltd Copyright 2017, 2018 New Vector Ltd -Copyright 2019, 2020 The Matrix.org Foundation C.I.C. +Copyright 2019 - 2021 The Matrix.org Foundation C.I.C. +Copyright 2021 Šimon Brandner Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -86,6 +87,8 @@ import { randomUppercaseString, randomLowercaseString } from "matrix-js-sdk/src/ import EventEmitter from 'events'; import SdkConfig from './SdkConfig'; import { ensureDMExists, findDMForUser } from './createRoom'; +import { IPushRule, RuleId, TweakName, Tweaks } from "matrix-js-sdk/src/@types/PushRules"; +import { PushProcessor } from 'matrix-js-sdk/src/pushprocessor'; export const PROTOCOL_PSTN = 'm.protocol.pstn'; export const PROTOCOL_PSTN_PREFIXED = 'im.vector.protocol.pstn'; @@ -475,9 +478,22 @@ export default class CallHandler extends EventEmitter { this.silencedCalls.delete(call.callId); } + const incomingCallPushRule = ( + new PushProcessor(MatrixClientPeg.get()).getPushRuleById(RuleId.IncomingCall) as IPushRule + ); switch (newState) { case CallState.Ringing: - this.play(AudioID.Ring); + if ( + incomingCallPushRule?.enabled && + incomingCallPushRule.actions.some((a: Tweaks) => ( + a.set_tweak === TweakName.Sound && + a.value === "ring" + )) + ) { + this.play(AudioID.Ring); + } else { + this.silenceCall(call.callId); + } break; case CallState.InviteSent: this.play(AudioID.Ringback); From e787d14cde2783e3e83613a40355a0afba477191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 3 Aug 2021 14:58:50 +0200 Subject: [PATCH 22/60] Set silenced state as soon as we get the call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/IncomingCallBox.tsx | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/components/views/voip/IncomingCallBox.tsx b/src/components/views/voip/IncomingCallBox.tsx index 95e97f1080..66fc2847f7 100644 --- a/src/components/views/voip/IncomingCallBox.tsx +++ b/src/components/views/voip/IncomingCallBox.tsx @@ -63,16 +63,12 @@ export default class IncomingCallBox extends React.Component { private onAction = (payload: ActionPayload) => { switch (payload.action) { case 'call_state': { - const call = CallHandler.sharedInstance().getCallForRoom(payload.room_id); - if (call && call.state === CallState.Ringing) { - this.setState({ - incomingCall: call, - silenced: false, // Reset silenced state for new call - }); + const incomingCall = CallHandler.sharedInstance().getCallForRoom(payload.room_id); + const silenced = CallHandler.sharedInstance().isCallSilenced(incomingCall.callId); + if (incomingCall && incomingCall.state === CallState.Ringing) { + this.setState({ incomingCall, silenced }); } else { - this.setState({ - incomingCall: null, - }); + this.setState({ incomingCall: null }); } } } From 75948587e43cf539dbef39c1f09a37ff7ed1d155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 3 Aug 2021 15:13:40 +0200 Subject: [PATCH 23/60] Avoid calling with undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/IncomingCallBox.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/views/voip/IncomingCallBox.tsx b/src/components/views/voip/IncomingCallBox.tsx index 66fc2847f7..4479c02e30 100644 --- a/src/components/views/voip/IncomingCallBox.tsx +++ b/src/components/views/voip/IncomingCallBox.tsx @@ -64,9 +64,11 @@ export default class IncomingCallBox extends React.Component { switch (payload.action) { case 'call_state': { const incomingCall = CallHandler.sharedInstance().getCallForRoom(payload.room_id); - const silenced = CallHandler.sharedInstance().isCallSilenced(incomingCall.callId); if (incomingCall && incomingCall.state === CallState.Ringing) { - this.setState({ incomingCall, silenced }); + this.setState({ + incomingCall, + silenced: CallHandler.sharedInstance().isCallSilenced(incomingCall.callId), + }); } else { this.setState({ incomingCall: null }); } From 2a378f30b7f3b71deddcba306078c78332c647a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 3 Aug 2021 15:38:12 +0200 Subject: [PATCH 24/60] Attempt to fix tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- test/test-utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test-utils.js b/test/test-utils.js index 5e29fd242e..6d0d930d93 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -48,6 +48,7 @@ export function createTestClient() { getDomain: jest.fn().mockReturnValue("matrix.rog"), getUserId: jest.fn().mockReturnValue("@userId:matrix.rog"), + getPushRuleById: jest.fn().mockReturnValue(null), getPushActionsForEvent: jest.fn(), getRoom: jest.fn().mockImplementation(mkStubRoom), getRooms: jest.fn().mockReturnValue([]), From a18f41ceed92de96a2df3d21ac23799660142a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 3 Aug 2021 15:43:56 +0200 Subject: [PATCH 25/60] Fix tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- test/test-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-utils.js b/test/test-utils.js index 6d0d930d93..fb2d866962 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -48,7 +48,6 @@ export function createTestClient() { getDomain: jest.fn().mockReturnValue("matrix.rog"), getUserId: jest.fn().mockReturnValue("@userId:matrix.rog"), - getPushRuleById: jest.fn().mockReturnValue(null), getPushActionsForEvent: jest.fn(), getRoom: jest.fn().mockImplementation(mkStubRoom), getRooms: jest.fn().mockReturnValue([]), @@ -96,6 +95,7 @@ export function createTestClient() { getItem: jest.fn(), }, }, + pushRules: {}, decryptEventIfNeeded: () => Promise.resolve(), isUserIgnored: jest.fn().mockReturnValue(false), getCapabilities: jest.fn().mockResolvedValue({}), From 7b565db02dacc067ae0d3b9adc7fbf3a277f8ee3 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Aug 2021 12:52:21 -0600 Subject: [PATCH 26/60] Update uploading state designs --- res/css/views/rooms/_VoiceRecordComposerTile.scss | 8 ++++++-- src/components/views/rooms/VoiceRecordComposerTile.tsx | 9 ++++----- src/i18n/strings/en_EN.json | 2 -- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/res/css/views/rooms/_VoiceRecordComposerTile.scss b/res/css/views/rooms/_VoiceRecordComposerTile.scss index 3d8d0e5ecc..7acec5a133 100644 --- a/res/css/views/rooms/_VoiceRecordComposerTile.scss +++ b/res/css/views/rooms/_VoiceRecordComposerTile.scss @@ -46,9 +46,13 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/trashcan.svg'); } -.mx_VoiceRecordComposerTile_uploadState { - margin-right: 21px; +.mx_VoiceRecordComposerTile_uploadingState { + margin-right: 10px; color: $secondary-fg-color; +} + +.mx_VoiceRecordComposerTile_failedState { + margin-right: 21px; .mx_VoiceRecordComposerTile_uploadState_badge { display: inline-block; diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index 490d6b2231..1f481d7531 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -246,20 +246,19 @@ export default class VoiceRecordComposerTile extends React.PureComponent + if (this.state.recordingPhase === RecordingState.Uploading || true) { + uploadIndicator = - { _t("Uploading...") } ; } else if (this.state.didUploadFail && this.state.recordingPhase === RecordingState.Ended) { - uploadIndicator = + uploadIndicator = { /* Need to stick the badge in a span to ensure it doesn't create a block component */ } - { _t("Failed to upload voice message") } + { _t("Failed to send") } ; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c929bd683b..9a717e31a4 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1708,8 +1708,6 @@ "Record a voice message": "Record a voice message", "Stop the recording": "Stop the recording", "Delete recording": "Delete recording", - "Uploading...": "Uploading...", - "Failed to upload voice message": "Failed to upload voice message", "Error updating main address": "Error updating main address", "There was an error updating the room's main address. It may not be allowed by the server or a temporary failure occurred.": "There was an error updating the room's main address. It may not be allowed by the server or a temporary failure occurred.", "There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.": "There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.", From c4e6cc797302fd12af7c33c05a7b91cf11226524 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Aug 2021 12:57:16 -0600 Subject: [PATCH 27/60] Remove debugging --- src/components/views/rooms/VoiceRecordComposerTile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index 1f481d7531..b980b9295b 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -246,7 +246,7 @@ export default class VoiceRecordComposerTile extends React.PureComponent ; From 32442068cf53144f101523d56b3dcd7ab80a82ce Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Aug 2021 13:26:27 -0600 Subject: [PATCH 28/60] Use a default waveform when recording to ease component pop-in Fixes https://github.com/vector-im/element-web/issues/18225 --- src/components/views/audio_messages/LiveRecordingWaveform.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/audio_messages/LiveRecordingWaveform.tsx b/src/components/views/audio_messages/LiveRecordingWaveform.tsx index 9c33889884..9f981e8ca2 100644 --- a/src/components/views/audio_messages/LiveRecordingWaveform.tsx +++ b/src/components/views/audio_messages/LiveRecordingWaveform.tsx @@ -17,7 +17,7 @@ limitations under the License. import React from "react"; import { IRecordingUpdate, RECORDING_PLAYBACK_SAMPLES, VoiceRecording } from "../../../audio/VoiceRecording"; import { replaceableComponent } from "../../../utils/replaceableComponent"; -import { arrayFastResample } from "../../../utils/arrays"; +import { arrayFastResample, arraySeed } from "../../../utils/arrays"; import { percentageOf } from "../../../utils/numbers"; import Waveform from "./Waveform"; import { MarkedExecution } from "../../../utils/MarkedExecution"; @@ -48,7 +48,7 @@ export default class LiveRecordingWaveform extends React.PureComponent Date: Tue, 3 Aug 2021 13:33:42 -0600 Subject: [PATCH 29/60] Improve hover states (tooltips) for voice message interactions Fixes https://github.com/vector-im/element-web/issues/18375 --- src/components/views/rooms/VoiceRecordComposerTile.tsx | 6 +++--- src/i18n/strings/en_EN.json | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index 8323320520..7949f41784 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -209,9 +209,9 @@ export default class VoiceRecordComposerTile extends React.PureComponent; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 3ad8daa85c..cf06112b14 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1705,9 +1705,8 @@ "We were unable to access your microphone. Please check your browser settings and try again.": "We were unable to access your microphone. Please check your browser settings and try again.", "No microphone found": "No microphone found", "We didn't find a microphone on your device. Please check your settings and try again.": "We didn't find a microphone on your device. Please check your settings and try again.", - "Record a voice message": "Record a voice message", - "Stop the recording": "Stop the recording", - "Delete recording": "Delete recording", + "Send voice message": "Send voice message", + "Stop recording": "Stop recording", "Error updating main address": "Error updating main address", "There was an error updating the room's main address. It may not be allowed by the server or a temporary failure occurred.": "There was an error updating the room's main address. It may not be allowed by the server or a temporary failure occurred.", "There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.": "There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.", From 24da0291a05a4ddfc4c008415b3ea6688836a73a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Aug 2021 13:33:58 -0600 Subject: [PATCH 30/60] Re-center recording LED Fixes https://github.com/vector-im/element-web/issues/18375 --- res/css/views/rooms/_VoiceRecordComposerTile.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/rooms/_VoiceRecordComposerTile.scss b/res/css/views/rooms/_VoiceRecordComposerTile.scss index 5501ab343e..8c13018c51 100644 --- a/res/css/views/rooms/_VoiceRecordComposerTile.scss +++ b/res/css/views/rooms/_VoiceRecordComposerTile.scss @@ -68,7 +68,7 @@ limitations under the License. height: 10px; position: absolute; left: 12px; // 12px from the left edge for container padding - top: 18px; // vertically center (middle align with clock) + top: 16px; // vertically center (middle align with clock) border-radius: 10px; } } From 1b9fe46733f8ae587ee592786a80a8b5b42a3ac7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Aug 2021 13:51:11 -0600 Subject: [PATCH 31/60] Remove unnecessary rescaling of voice waveforms Fixes https://github.com/vector-im/element-web/issues/18364 --- src/audio/Playback.ts | 14 +++----------- .../views/audio_messages/LiveRecordingWaveform.tsx | 9 ++------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/audio/Playback.ts b/src/audio/Playback.ts index 33d346629a..9dad828a79 100644 --- a/src/audio/Playback.ts +++ b/src/audio/Playback.ts @@ -38,17 +38,9 @@ function makePlaybackWaveform(input: number[]): number[] { // First, convert negative amplitudes to positive so we don't detect zero as "noisy". const noiseWaveform = input.map(v => Math.abs(v)); - // Next, we'll resample the waveform using a smoothing approach so we can keep the same rough shape. - // We also rescale the waveform to be 0-1 for the remaining function logic. - const resampled = arrayRescale(arraySmoothingResample(noiseWaveform, PLAYBACK_WAVEFORM_SAMPLES), 0, 1); - - // Then, we'll do a high and low pass filter to isolate actual speaking volumes within the rescaled - // waveform. Most speech happens below the 0.5 mark. - const filtered = resampled.map(v => clamp(v, 0.1, 0.5)); - - // Finally, we'll rescale the filtered waveform (0.1-0.5 becomes 0-1 again) so the user sees something - // sensible. This is what we return to keep our contract of "values between zero and one". - return arrayRescale(filtered, 0, 1); + // Then, we'll resample the waveform using a smoothing approach so we can keep the same rough shape. + // We also rescale the waveform to be 0-1 so we end up with a clamped waveform to rely upon. + return arrayRescale(arraySmoothingResample(noiseWaveform, PLAYBACK_WAVEFORM_SAMPLES), 0, 1); } export class Playback extends EventEmitter implements IDestroyable { diff --git a/src/components/views/audio_messages/LiveRecordingWaveform.tsx b/src/components/views/audio_messages/LiveRecordingWaveform.tsx index 9f981e8ca2..73e18626fe 100644 --- a/src/components/views/audio_messages/LiveRecordingWaveform.tsx +++ b/src/components/views/audio_messages/LiveRecordingWaveform.tsx @@ -18,7 +18,6 @@ import React from "react"; import { IRecordingUpdate, RECORDING_PLAYBACK_SAMPLES, VoiceRecording } from "../../../audio/VoiceRecording"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import { arrayFastResample, arraySeed } from "../../../utils/arrays"; -import { percentageOf } from "../../../utils/numbers"; import Waveform from "./Waveform"; import { MarkedExecution } from "../../../utils/MarkedExecution"; @@ -54,12 +53,8 @@ export default class LiveRecordingWaveform extends React.PureComponent { - const bars = arrayFastResample(Array.from(update.waveform), RECORDING_PLAYBACK_SAMPLES); - // The incoming data is between zero and one, but typically even screaming into a - // microphone won't send you over 0.6, so we artificially adjust the gain for the - // waveform. This results in a slightly more cinematic/animated waveform for the - // user. - this.waveform = bars.map(b => percentageOf(b, 0, 0.50)); + // The incoming data is between zero and one, so we don't need to clamp/rescale it. + this.waveform = arrayFastResample(Array.from(update.waveform), RECORDING_PLAYBACK_SAMPLES); this.scheduledUpdate.mark(); }); } From 372cbbfe8ef3a4dd0396c2de49f7e71be2311511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 08:11:05 +0200 Subject: [PATCH 32/60] Increase snapping speed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 6261b9965f..46ff8ca838 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -36,7 +36,7 @@ const PIP_VIEW_WIDTH = 336; const PIP_VIEW_HEIGHT = 232; const MOVING_AMT = 0.2; -const SNAPPING_AMT = 0.05; +const SNAPPING_AMT = 0.1; const PADDING = { top: 58, From b4b788e8d5b223fe4ec0b5ff29d9b993a890f3f7 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Wed, 4 Aug 2021 11:21:52 +0200 Subject: [PATCH 33/60] Fix right margin for events on IRC layout Fixes vector-im/element-web#18354 --- res/css/views/rooms/_EventTile.scss | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 6e207d674b..1c9d8e87d9 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -310,14 +310,12 @@ $hover-select-border: 4px; } .mx_RoomView_timeline_rr_enabled { - - .mx_EventTile:not([data-layout=bubble]) { + .mx_EventTile[data-layout=group] { .mx_EventTile_line { /* ideally should be 100px, but 95px gives us a max thumbnail size of 800x600, which is nice */ margin-right: 110px; } } - // on ELS we need the margin to allow interaction with the expand/collapse button which is normally in the RR gutter } From 4a1789be53212266073de2b9f021b344d9f7b479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 13:04:23 +0200 Subject: [PATCH 34/60] Update copy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/CallEvent.tsx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/components/views/messages/CallEvent.tsx b/src/components/views/messages/CallEvent.tsx index 2de66f897a..12e7f22173 100644 --- a/src/components/views/messages/CallEvent.tsx +++ b/src/components/views/messages/CallEvent.tsx @@ -117,14 +117,12 @@ export default class CallEvent extends React.Component { if (state === CallState.Ended) { const hangupReason = this.props.callEventGrouper.hangupReason; const gotRejected = this.props.callEventGrouper.gotRejected; - const rejectParty = this.props.callEventGrouper.rejectParty; if (gotRejected) { - const weDeclinedCall = MatrixClientPeg.get().getUserId() === rejectParty; return (
- { weDeclinedCall ? _t("You declined this call") : _t("They declined this call") } - { this.renderCallBackButton(weDeclinedCall ? _t("Call back") : _t("Call again")) } + { _t("Call declined") } + { this.renderCallBackButton(_t("Call back")) }
); } else if (([CallErrorCode.UserHangup, "user hangup"].includes(hangupReason) || !hangupReason)) { @@ -136,14 +134,14 @@ export default class CallEvent extends React.Component { // Also, if we don't have a reason return (
- { _t("This call has ended") } + { _t("Call ended") }
); } else if (hangupReason === CallErrorCode.InviteTimeout) { return (
- { _t("They didn't pick up") } - { this.renderCallBackButton(_t("Call again")) } + { _t("Missed call") } + { this.renderCallBackButton(_t("Call back")) }
); } @@ -176,7 +174,8 @@ export default class CallEvent extends React.Component { className="mx_CallEvent_content_tooltip" kind={InfoTooltipKind.Warning} /> - { _t("This call has failed") } + { _t("Connection failed") } + { this.renderCallBackButton(_t("Retry")) }
); } @@ -190,7 +189,7 @@ export default class CallEvent extends React.Component { if (state === CustomCallState.Missed) { return (
- { _t("You missed this call") } + { _t("Missed call") } { this.renderCallBackButton(_t("Call back")) }
); From d05be441134fd9d1b66cf6269a1e669e3faf2035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 13:07:54 +0200 Subject: [PATCH 35/60] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/i18n/strings/en_EN.json | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 6867f28b74..aa736bb1e8 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1865,19 +1865,15 @@ "Verification cancelled": "Verification cancelled", "Compare emoji": "Compare emoji", "Connected": "Connected", - "You declined this call": "You declined this call", - "They declined this call": "They declined this call", + "Call declined": "Call declined", "Call back": "Call back", - "Call again": "Call again", - "This call has ended": "This call has ended", - "They didn't pick up": "They didn't pick up", + "Missed call": "Missed call", "Could not connect media": "Could not connect media", "Connection failed": "Connection failed", "Their device couldn't start the camera or microphone": "Their device couldn't start the camera or microphone", "An unknown error occurred": "An unknown error occurred", "Unknown failure: %(reason)s)": "Unknown failure: %(reason)s)", - "This call has failed": "This call has failed", - "You missed this call": "You missed this call", + "Retry": "Retry", "The call is in an unknown state!": "The call is in an unknown state!", "Sunday": "Sunday", "Monday": "Monday", @@ -1900,7 +1896,6 @@ "Error processing audio message": "Error processing audio message", "React": "React", "Edit": "Edit", - "Retry": "Retry", "Reply": "Reply", "Message Actions": "Message Actions", "Download %(text)s": "Download %(text)s", From f97f410d0939f7c59e8efed819d60967ce528218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 13:16:01 +0200 Subject: [PATCH 36/60] Unused import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/CallEvent.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/messages/CallEvent.tsx b/src/components/views/messages/CallEvent.tsx index 12e7f22173..a204907caa 100644 --- a/src/components/views/messages/CallEvent.tsx +++ b/src/components/views/messages/CallEvent.tsx @@ -25,7 +25,6 @@ import { CallErrorCode, CallState } from 'matrix-js-sdk/src/webrtc/call'; import InfoTooltip, { InfoTooltipKind } from '../elements/InfoTooltip'; import classNames from 'classnames'; import AccessibleTooltipButton from '../elements/AccessibleTooltipButton'; -import { MatrixClientPeg } from '../../../MatrixClientPeg'; interface IProps { mxEvent: MatrixEvent; From d0b295f1a737808e4602999a7dfaf901c65008ee Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 4 Aug 2021 13:28:31 +0100 Subject: [PATCH 37/60] Add CODEOWNERS --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..2c068fff33 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @matrix-org/element-web From 5877e936c06c383ecde92db4eea1a58c2c8a309f Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 4 Aug 2021 09:24:18 -0400 Subject: [PATCH 38/60] Fix fallback fonts Signed-off-by: Robin Townsend --- res/themes/legacy-light/css/_legacy-light.scss | 4 ++-- res/themes/light/css/_light.scss | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index e945efb219..1a63c9bd07 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -8,9 +8,9 @@ /* Noto Color Emoji contains digits, in fixed-width, therefore causing digits in flowed text to stand out. TODO: Consider putting all emoji fonts to the end rather than the front. */ -$font-family: 'Nunito', 'Twemoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Arial', 'Helvetica', 'Sans-Serif', 'Noto Color Emoji'; +$font-family: 'Nunito', 'Twemoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Arial', 'Helvetica', sans-serif, 'Noto Color Emoji'; -$monospace-font-family: 'Inconsolata', 'Twemoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Courier', 'monospace', 'Noto Color Emoji'; +$monospace-font-family: 'Inconsolata', 'Twemoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Courier', monospace, 'Noto Color Emoji'; // Colors from Figma Compound https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=557%3A0 $system-light: #F4F6FA; diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index aa17dddc56..eff9abe5af 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -8,9 +8,9 @@ /* Noto Color Emoji contains digits, in fixed-width, therefore causing digits in flowed text to stand out. TODO: Consider putting all emoji fonts to the end rather than the front. */ -$font-family: 'Inter', 'Twemoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Arial', 'Helvetica', 'Sans-Serif', 'Noto Color Emoji'; +$font-family: 'Inter', 'Twemoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Arial', 'Helvetica', sans-serif, 'Noto Color Emoji'; -$monospace-font-family: 'Inconsolata', 'Twemoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Courier', 'monospace', 'Noto Color Emoji'; +$monospace-font-family: 'Inconsolata', 'Twemoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Courier', monospace, 'Noto Color Emoji'; // Colors from Figma Compound https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=557%3A0 $system-light: #F4F6FA; From 79e4a95b13bded8accd3a6a4b7e6002ed246fde9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 16:25:44 +0200 Subject: [PATCH 39/60] Move stuff out of if statement for better readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/CallHandler.tsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index d4a29a11b9..8d862498d2 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -481,15 +481,14 @@ export default class CallHandler extends EventEmitter { const incomingCallPushRule = ( new PushProcessor(MatrixClientPeg.get()).getPushRuleById(RuleId.IncomingCall) as IPushRule ); + const pushRuleEnabled = incomingCallPushRule?.enabled; + const tweakSetToRing = incomingCallPushRule.actions.some((action: Tweaks) => ( + action.set_tweak === TweakName.Sound && + action.value === "ring" + )); switch (newState) { case CallState.Ringing: - if ( - incomingCallPushRule?.enabled && - incomingCallPushRule.actions.some((a: Tweaks) => ( - a.set_tweak === TweakName.Sound && - a.value === "ring" - )) - ) { + if (pushRuleEnabled && tweakSetToRing) { this.play(AudioID.Ring); } else { this.silenceCall(call.callId); From 023d8749499605da27d949308e91d58e25cb7183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 16:34:59 +0200 Subject: [PATCH 40/60] Add missing ? MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/CallHandler.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 0de6723d33..0cb916578e 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -485,7 +485,7 @@ export default class CallHandler extends EventEmitter { new PushProcessor(MatrixClientPeg.get()).getPushRuleById(RuleId.IncomingCall) as IPushRule ); const pushRuleEnabled = incomingCallPushRule?.enabled; - const tweakSetToRing = incomingCallPushRule.actions.some((action: Tweaks) => ( + const tweakSetToRing = incomingCallPushRule?.actions.some((action: Tweaks) => ( action.set_tweak === TweakName.Sound && action.value === "ring" )); From 74e1342fa8266c97e6d4dcae664b9a1d4447f0b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 16:35:46 +0200 Subject: [PATCH 41/60] Wrap cases in {} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/CallHandler.tsx | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 0cb916578e..77569711df 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -481,27 +481,29 @@ export default class CallHandler extends EventEmitter { this.silencedCalls.delete(call.callId); } - const incomingCallPushRule = ( - new PushProcessor(MatrixClientPeg.get()).getPushRuleById(RuleId.IncomingCall) as IPushRule - ); - const pushRuleEnabled = incomingCallPushRule?.enabled; - const tweakSetToRing = incomingCallPushRule?.actions.some((action: Tweaks) => ( - action.set_tweak === TweakName.Sound && - action.value === "ring" - )); switch (newState) { - case CallState.Ringing: + case CallState.Ringing: { + const incomingCallPushRule = ( + new PushProcessor(MatrixClientPeg.get()).getPushRuleById(RuleId.IncomingCall) as IPushRule + ); + const pushRuleEnabled = incomingCallPushRule?.enabled; + const tweakSetToRing = incomingCallPushRule?.actions.some((action: Tweaks) => ( + action.set_tweak === TweakName.Sound && + action.value === "ring" + )); + if (pushRuleEnabled && tweakSetToRing) { this.play(AudioID.Ring); } else { this.silenceCall(call.callId); } break; - case CallState.InviteSent: + } + case CallState.InviteSent: { this.play(AudioID.Ringback); break; - case CallState.Ended: - { + } + case CallState.Ended: { const hangupReason = call.hangupReason; Analytics.trackEvent('voip', 'callEnded', 'hangupReason', hangupReason); this.removeCallForRoom(mappedRoomId); From fe643b2401d38457deb891af17bd6543ec5526c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 17:09:48 +0200 Subject: [PATCH 42/60] Use flex-start as it has more universal support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/auth/_InteractiveAuthEntryComponents.scss | 2 +- res/css/views/rooms/_EventBubbleTile.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/res/css/views/auth/_InteractiveAuthEntryComponents.scss b/res/css/views/auth/_InteractiveAuthEntryComponents.scss index ffaad3cd7a..ec07b765fd 100644 --- a/res/css/views/auth/_InteractiveAuthEntryComponents.scss +++ b/res/css/views/auth/_InteractiveAuthEntryComponents.scss @@ -85,7 +85,7 @@ limitations under the License. .mx_InteractiveAuthEntryComponents_termsPolicy { display: flex; flex-direction: row; - justify-content: start; + justify-content: flex-start; align-items: center; } diff --git a/res/css/views/rooms/_EventBubbleTile.scss b/res/css/views/rooms/_EventBubbleTile.scss index 1e25deba26..c6170bf7c0 100644 --- a/res/css/views/rooms/_EventBubbleTile.scss +++ b/res/css/views/rooms/_EventBubbleTile.scss @@ -271,7 +271,7 @@ limitations under the License. display: flex; align-items: center; - justify-content: start; + justify-content: flex-start; padding: 5px 0; .mx_EventTile_avatar { From e2bc76a1294158a9f149b3e6048b0586bbfedd41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 17:17:21 +0200 Subject: [PATCH 43/60] Fix voice feed cut-off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/voip/_CallView.scss | 2 -- res/css/views/voip/_CallViewSidebar.scss | 2 -- res/css/views/voip/_VideoFeed.scss | 1 + 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index 60b7aa69ea..fb18c6a5ee 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -75,8 +75,6 @@ limitations under the License. height: 100%; &.mx_VideoFeed_voice { - // We don't want to collide with the call controls that have 52px of height - margin-bottom: 52px; background-color: $inverted-bg-color; display: flex; justify-content: center; diff --git a/res/css/views/voip/_CallViewSidebar.scss b/res/css/views/voip/_CallViewSidebar.scss index 892a137a32..dbadc22028 100644 --- a/res/css/views/voip/_CallViewSidebar.scss +++ b/res/css/views/voip/_CallViewSidebar.scss @@ -40,8 +40,6 @@ limitations under the License. display: flex; align-items: center; justify-content: center; - - aspect-ratio: 16 / 9; } .mx_VideoFeed_video { diff --git a/res/css/views/voip/_VideoFeed.scss b/res/css/views/voip/_VideoFeed.scss index 3a0f62636e..7a8d39dfe3 100644 --- a/res/css/views/voip/_VideoFeed.scss +++ b/res/css/views/voip/_VideoFeed.scss @@ -20,6 +20,7 @@ limitations under the License. &.mx_VideoFeed_voice { background-color: $inverted-bg-color; + aspect-ratio: 16 / 9; } .mx_VideoFeed_video { From 91b4b50969719db75d9c75d2af9d1647add38112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 17:25:12 +0200 Subject: [PATCH 44/60] Fix wrong cursor being used in PiP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/voip/_CallContainer.scss | 1 - res/css/views/voip/_CallView.scss | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/voip/_CallContainer.scss b/res/css/views/voip/_CallContainer.scss index 181a5ee0a3..d11ab9bf9f 100644 --- a/res/css/views/voip/_CallContainer.scss +++ b/res/css/views/voip/_CallContainer.scss @@ -28,7 +28,6 @@ limitations under the License. .mx_CallPreview { pointer-events: initial; // restore pointer events so the user can leave/interact - cursor: pointer; .mx_VideoFeed_remote.mx_VideoFeed_voice { min-height: 150px; diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index 60b7aa69ea..c473a1fc79 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -208,6 +208,7 @@ limitations under the License. align-items: center; justify-content: left; flex-shrink: 0; + cursor: pointer; } .mx_CallView_header_callType { From ee500ad68403fd79730bfbec0b01f6c44c368a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 18:14:32 +0200 Subject: [PATCH 45/60] Update copy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/settings/Settings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 8c30a55f8d..f196f1cda9 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -473,7 +473,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "MessageComposerInput.surroundWith": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, - displayName: _td("Use surround with"), + displayName: _td("Surround selected text when typing special characters"), default: false, }, "MessageComposerInput.autoReplaceEmoji": { From b9b98c6a817b33f1cb23b76b4cf1adbea4d325fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 4 Aug 2021 18:15:11 +0200 Subject: [PATCH 46/60] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- 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 3eedb9510c..70bb1e436b 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -847,7 +847,7 @@ "Use Ctrl + F to search timeline": "Use Ctrl + F to search timeline", "Use Command + Enter to send a message": "Use Command + Enter to send a message", "Use Ctrl + Enter to send a message": "Use Ctrl + Enter to send a message", - "Use surround with": "Use surround with", + "Surround selected text when typing special characters": "Surround selected text when typing special characters", "Automatically replace plain text Emoji": "Automatically replace plain text Emoji", "Mirror local video feed": "Mirror local video feed", "Enable Community Filter Panel": "Enable Community Filter Panel", From 4d5bdf70b70aa57d6e4394eacfe0baef9e4d189c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Aug 2021 15:08:22 -0600 Subject: [PATCH 47/60] Fix worklet reference for new webpack pipeline --- src/audio/VoiceRecording.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/audio/VoiceRecording.ts b/src/audio/VoiceRecording.ts index efd616e5ae..67b2acda0c 100644 --- a/src/audio/VoiceRecording.ts +++ b/src/audio/VoiceRecording.ts @@ -30,6 +30,7 @@ import { IEncryptedFile } from "matrix-js-sdk/src/@types/event"; import { uploadFile } from "../ContentMessages"; import { FixedRollingArray } from "../utils/FixedRollingArray"; import { clamp } from "../utils/numbers"; +import mxRecorderWorkletPath from "./RecorderWorklet"; const CHANNELS = 1; // stereo isn't important export const SAMPLE_RATE = 48000; // 48khz is what WebRTC uses. 12khz is where we lose quality. @@ -113,16 +114,10 @@ export class VoiceRecording extends EventEmitter implements IDestroyable { }); this.recorderSource = this.recorderContext.createMediaStreamSource(this.recorderStream); - // Set up our worklet. We use this for timing information and waveform analysis: the - // web audio API prefers this be done async to avoid holding the main thread with math. - const mxRecorderWorkletPath = document.body.dataset.vectorRecorderWorkletScript; - if (!mxRecorderWorkletPath) { - // noinspection ExceptionCaughtLocallyJS - throw new Error("Unable to create recorder: no worklet script registered"); - } - // Connect our inputs and outputs if (this.recorderContext.audioWorklet) { + // Set up our worklet. We use this for timing information and waveform analysis: the + // web audio API prefers this be done async to avoid holding the main thread with math. await this.recorderContext.audioWorklet.addModule(mxRecorderWorkletPath); this.recorderWorklet = new AudioWorkletNode(this.recorderContext, WORKLET_NAME); this.recorderSource.connect(this.recorderWorklet); From 9b32a1c60923fa9dc22ffb8c7be60fa65ae5fd52 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Aug 2021 15:23:35 -0600 Subject: [PATCH 48/60] Appease Jest --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index cccb92d5d9..2445e3c973 100644 --- a/package.json +++ b/package.json @@ -193,7 +193,8 @@ "decoderWorker\\.min\\.js": "/__mocks__/empty.js", "decoderWorker\\.min\\.wasm": "/__mocks__/empty.js", "waveWorker\\.min\\.js": "/__mocks__/empty.js", - "workers/(.+)\\.worker\\.ts": "/__mocks__/workerMock.js" + "workers/(.+)\\.worker\\.ts": "/__mocks__/workerMock.js", + "RecorderWorklet": "/__mocks__/empty.js" }, "transformIgnorePatterns": [ "/node_modules/(?!matrix-js-sdk).+$" From 5e3b79eecafb1d70a3cf076b5048d50d5c4ec3e5 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 4 Aug 2021 18:42:47 -0400 Subject: [PATCH 49/60] Remove seams from pin icon Signed-off-by: Robin Townsend --- res/img/element-icons/room/pin.svg | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/res/img/element-icons/room/pin.svg b/res/img/element-icons/room/pin.svg index 2448fc61c5..f090f60be8 100644 --- a/res/img/element-icons/room/pin.svg +++ b/res/img/element-icons/room/pin.svg @@ -1,7 +1,3 @@ - - - - - + From a9d7d010141052f6b1d85c2aefab7de5c6b1a314 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 5 Aug 2021 12:30:22 +0100 Subject: [PATCH 50/60] Null guard space inviter to prevent the app exploding --- src/components/structures/SpaceRoomView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 4064b2f48e..6f63ea090c 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -192,11 +192,11 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => if (inviteSender) { inviterSection =
- +
{ _t(" invites you", {}, { - inviter: () => { inviter.name || inviteSender }, + inviter: () => { inviter?.name || inviteSender }, }) }
{ inviter ?
From 99adbfd1ea896e6fbaf6417d6ecf8aab50d58a8b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 5 Aug 2021 13:04:20 +0100 Subject: [PATCH 51/60] Skip sending a thumbnail if it is not a sufficient saving over the original --- src/ContentMessages.tsx | 49 +++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/src/ContentMessages.tsx b/src/ContentMessages.tsx index c5bcb226ff..8973219b49 100644 --- a/src/ContentMessages.tsx +++ b/src/ContentMessages.tsx @@ -209,6 +209,14 @@ async function loadImageElement(imageFile: File) { return { width, height, img }; } +// Minimum size for image files before we generate a thumbnail for them. +const IMAGE_SIZE_THRESHOLD_THUMBNAIL = 1 << 15; // 32KB +// Minimum size improvement for image thumbnails, if both are not met then don't bother uploading thumbnail. +const IMAGE_THUMBNAIL_MIN_REDUCTION_SIZE = 1 << 16; // 1MB +const IMAGE_THUMBNAIL_MIN_REDUCTION_PERCENT = 0.1; // 10% +// We don't apply these thresholds to video thumbnails as a poster image is always useful +// and videos tend to be much larger. + /** * Read the metadata for an image file and create and upload a thumbnail of the image. * @@ -217,23 +225,40 @@ async function loadImageElement(imageFile: File) { * @param {File} imageFile The image to read and thumbnail. * @return {Promise} A promise that resolves with the attachment info. */ -function infoForImageFile(matrixClient, roomId, imageFile) { +async function infoForImageFile(matrixClient: MatrixClient, roomId: string, imageFile: File) { + if (imageFile.size <= IMAGE_SIZE_THRESHOLD_THUMBNAIL) { + // don't bother generating a thumbnail, image is small enough already + return {}; + } + let thumbnailType = "image/png"; if (imageFile.type === "image/jpeg") { thumbnailType = "image/jpeg"; } - let imageInfo; - return loadImageElement(imageFile).then((r) => { - return createThumbnail(r.img, r.width, r.height, thumbnailType); - }).then((result) => { - imageInfo = result.info; - return uploadFile(matrixClient, roomId, result.thumbnail); - }).then((result) => { - imageInfo.thumbnail_url = result.url; - imageInfo.thumbnail_file = result.file; - return imageInfo; - }); + const imageElement = await loadImageElement(imageFile); + + if (imageElement.width < MAX_WIDTH && imageElement.height < MAX_HEIGHT) { + // don't bother uploading thumbnail as it'd be the same resolution as the original. + return {}; + } + + const result = await createThumbnail(imageElement.img, imageElement.width, imageElement.height, thumbnailType); + const imageInfo = result.info; + + const sizeDifference = imageFile.size - imageInfo.thumbnail_info.size; + if (sizeDifference <= IMAGE_THUMBNAIL_MIN_REDUCTION_SIZE && + sizeDifference <= (imageFile.size * IMAGE_THUMBNAIL_MIN_REDUCTION_PERCENT) + ) { + // don't bother uploading thumbnail as it not sufficiently smaller than the original. + return {}; + } + + const uploadResult = await uploadFile(matrixClient, roomId, result.thumbnail); + + imageInfo["thumbnail_url"] = uploadResult.url; + imageInfo["thumbnail_file"] = uploadResult.file; + return imageInfo; } /** From 980b284642cbbdbcb88920b8dd1e89bf312cc820 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 5 Aug 2021 13:12:01 +0100 Subject: [PATCH 52/60] Fix image & blurhash info when skipping thumbnail due to thresholds --- src/ContentMessages.tsx | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/ContentMessages.tsx b/src/ContentMessages.tsx index 8973219b49..14a0c1ed51 100644 --- a/src/ContentMessages.tsx +++ b/src/ContentMessages.tsx @@ -226,11 +226,6 @@ const IMAGE_THUMBNAIL_MIN_REDUCTION_PERCENT = 0.1; // 10% * @return {Promise} A promise that resolves with the attachment info. */ async function infoForImageFile(matrixClient: MatrixClient, roomId: string, imageFile: File) { - if (imageFile.size <= IMAGE_SIZE_THRESHOLD_THUMBNAIL) { - // don't bother generating a thumbnail, image is small enough already - return {}; - } - let thumbnailType = "image/png"; if (imageFile.type === "image/jpeg") { thumbnailType = "image/jpeg"; @@ -238,20 +233,18 @@ async function infoForImageFile(matrixClient: MatrixClient, roomId: string, imag const imageElement = await loadImageElement(imageFile); - if (imageElement.width < MAX_WIDTH && imageElement.height < MAX_HEIGHT) { - // don't bother uploading thumbnail as it'd be the same resolution as the original. - return {}; - } - const result = await createThumbnail(imageElement.img, imageElement.width, imageElement.height, thumbnailType); const imageInfo = result.info; + // we do all sizing checks here because we still rely on thumbnail generation for making a blurhash from. const sizeDifference = imageFile.size - imageInfo.thumbnail_info.size; - if (sizeDifference <= IMAGE_THUMBNAIL_MIN_REDUCTION_SIZE && - sizeDifference <= (imageFile.size * IMAGE_THUMBNAIL_MIN_REDUCTION_PERCENT) + if ( + imageFile.size <= IMAGE_SIZE_THRESHOLD_THUMBNAIL || // image is small enough already + (sizeDifference <= IMAGE_THUMBNAIL_MIN_REDUCTION_SIZE && // thumbnail is not sufficiently smaller than original + sizeDifference <= (imageFile.size * IMAGE_THUMBNAIL_MIN_REDUCTION_PERCENT)) ) { - // don't bother uploading thumbnail as it not sufficiently smaller than the original. - return {}; + delete imageInfo["thumbnail_info"]; + return imageInfo; } const uploadResult = await uploadFile(matrixClient, roomId, result.thumbnail); From a8b050a385f8831904c083f7ef555a083e26eeff Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 5 Aug 2021 13:37:23 +0100 Subject: [PATCH 53/60] Post-merge conflict resolution and improve alignment of tooltips --- src/components/views/voip/CallView.tsx | 50 ++++++++++++++++++++------ 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 356e642d65..3178566e68 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -23,11 +23,16 @@ import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { _t, _td } from '../../../languageHandler'; import VideoFeed from './VideoFeed'; import RoomAvatar from "../avatars/RoomAvatar"; -import { CallState, CallType, MatrixCall, CallEvent } from 'matrix-js-sdk/src/webrtc/call'; +import { CallEvent, CallState, CallType, MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import classNames from 'classnames'; import AccessibleButton from '../elements/AccessibleButton'; import { isOnlyCtrlOrCmdKeyEvent, Key } from '../../../Keyboard'; -import { alwaysAboveLeftOf, alwaysAboveRightOf, ChevronFace, ContextMenuButton } from '../../structures/ContextMenu'; +import { + alwaysAboveLeftOf, + alwaysAboveRightOf, + ChevronFace, + ContextMenuTooltipButton, +} from '../../structures/ContextMenu'; import CallContextMenu from '../context_menus/CallContextMenu'; import { avatarUrlForMember } from '../../../Avatar'; import DialpadContextMenu from '../context_menus/DialpadContextMenu'; @@ -37,6 +42,8 @@ import DesktopCapturerSourcePicker from "../elements/DesktopCapturerSourcePicker import Modal from '../../../Modal'; import { SDPStreamMetadataPurpose } from 'matrix-js-sdk/src/webrtc/callEventTypes'; import CallViewSidebar from './CallViewSidebar'; +import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; +import { Alignment } from "../elements/Tooltip"; interface IProps { // The call for us to display @@ -115,7 +122,6 @@ export default class CallView extends React.Component { private controlsHideTimer: number = null; private dialpadButton = createRef(); private contextMenuButton = createRef(); - private contextMenu = createRef(); constructor(props: IProps) { super(props); @@ -479,9 +485,12 @@ export default class CallView extends React.Component { let vidMuteButton; if (this.props.call.type === CallType.Video) { vidMuteButton = ( - ); } @@ -496,9 +505,15 @@ export default class CallView extends React.Component { this.props.call.state === CallState.Connected ) { screensharingButton = ( - ); } @@ -518,6 +533,7 @@ export default class CallView extends React.Component { ); } @@ -526,22 +542,28 @@ export default class CallView extends React.Component { let contextMenuButton; if (this.state.callState === CallState.Connected) { contextMenuButton = ( - ); } let dialpadButton; if (this.state.callState === CallState.Connected && this.props.call.opponentSupportsDTMF()) { dialpadButton = ( - ); } @@ -583,9 +605,12 @@ export default class CallView extends React.Component { { dialPad } { contextMenu } { dialpadButton } - { vidMuteButton }
@@ -593,9 +618,12 @@ export default class CallView extends React.Component { { screensharingButton } { sidebarButton } { contextMenuButton } -
); @@ -820,7 +848,7 @@ export default class CallView extends React.Component { let fullScreenButton; if (!this.props.pipMode) { fullScreenButton = ( -
{ let expandButton; if (this.props.pipMode) { - expandButton =
Date: Thu, 5 Aug 2021 13:50:50 +0100 Subject: [PATCH 54/60] i18n --- src/i18n/strings/en_EN.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 9664b2ca14..41ef0cc04f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -906,8 +906,12 @@ "sends space invaders": "sends space invaders", "Start the camera": "Start the camera", "Stop the camera": "Stop the camera", - "Dialpad": "Dialpad", + "Stop sharing your screen": "Stop sharing your screen", + "Start sharing your screen": "Start sharing your screen", + "Hide sidebar": "Hide sidebar", + "Show sidebar": "Show sidebar", "More": "More", + "Dialpad": "Dialpad", "Unmute the microphone": "Unmute the microphone", "Mute the microphone": "Mute the microphone", "Hangup": "Hangup", From e1b62ae38b15b503468f212f247dd9470e18c47a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 5 Aug 2021 14:20:31 +0100 Subject: [PATCH 55/60] Increase yOffset by 4px away --- src/components/views/voip/CallView.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 3178566e68..945cc55ed3 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -490,7 +490,7 @@ export default class CallView extends React.Component { onClick={this.onVidMuteClick} title={this.state.vidMuted ? _t("Start the camera") : _t("Stop the camera")} alignment={Alignment.Top} - yOffset={-20} + yOffset={-24} /> ); } @@ -513,7 +513,7 @@ export default class CallView extends React.Component { : _t("Start sharing your screen") } alignment={Alignment.Top} - yOffset={-20} + yOffset={-24} /> ); } @@ -549,7 +549,7 @@ export default class CallView extends React.Component { isExpanded={this.state.showMoreMenu} title={_t("More")} alignment={Alignment.Top} - yOffset={-20} + yOffset={-24} /> ); } @@ -563,7 +563,7 @@ export default class CallView extends React.Component { isExpanded={this.state.showDialpad} title={_t("Dialpad")} alignment={Alignment.Top} - yOffset={-20} + yOffset={-24} /> ); } @@ -610,7 +610,7 @@ export default class CallView extends React.Component { onClick={this.onMicMuteClick} title={this.state.micMuted ? _t("Unmute the microphone") : _t("Mute the microphone")} alignment={Alignment.Top} - yOffset={-20} + yOffset={-24} /> { vidMuteButton }
@@ -623,7 +623,7 @@ export default class CallView extends React.Component { onClick={this.onHangupClick} title={_t("Hangup")} alignment={Alignment.Top} - yOffset={-20} + yOffset={-24} />
); From b860acca8043ea9c8c937380650339566439f775 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 5 Aug 2021 14:43:44 +0100 Subject: [PATCH 56/60] Extract tooltipYOffset to a const --- src/components/views/voip/CallView.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 945cc55ed3..d301a1e43b 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -82,6 +82,8 @@ interface IState { sidebarShown: boolean; } +const tooltipYOffset = -24; + function getFullScreenElement() { return ( document.fullscreenElement || @@ -490,7 +492,7 @@ export default class CallView extends React.Component { onClick={this.onVidMuteClick} title={this.state.vidMuted ? _t("Start the camera") : _t("Stop the camera")} alignment={Alignment.Top} - yOffset={-24} + yOffset={tooltipYOffset} /> ); } @@ -513,7 +515,7 @@ export default class CallView extends React.Component { : _t("Start sharing your screen") } alignment={Alignment.Top} - yOffset={-24} + yOffset={tooltipYOffset} /> ); } @@ -549,7 +551,7 @@ export default class CallView extends React.Component { isExpanded={this.state.showMoreMenu} title={_t("More")} alignment={Alignment.Top} - yOffset={-24} + yOffset={tooltipYOffset} /> ); } @@ -563,7 +565,7 @@ export default class CallView extends React.Component { isExpanded={this.state.showDialpad} title={_t("Dialpad")} alignment={Alignment.Top} - yOffset={-24} + yOffset={tooltipYOffset} /> ); } @@ -610,7 +612,7 @@ export default class CallView extends React.Component { onClick={this.onMicMuteClick} title={this.state.micMuted ? _t("Unmute the microphone") : _t("Mute the microphone")} alignment={Alignment.Top} - yOffset={-24} + yOffset={tooltipYOffset} /> { vidMuteButton }
@@ -623,7 +625,7 @@ export default class CallView extends React.Component { onClick={this.onHangupClick} title={_t("Hangup")} alignment={Alignment.Top} - yOffset={-24} + yOffset={tooltipYOffset} />
); From df888a1886aeb9783091caf506d7b4216495a533 Mon Sep 17 00:00:00 2001 From: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> Date: Thu, 5 Aug 2021 16:33:22 +0100 Subject: [PATCH 57/60] Fix in-call context menus when in PiP mode (#6552) Mounting them as children when in PiP mode doesn't work. Condition mounting the context menus as children of the current component based on whether PiP mode is active. --- src/components/views/voip/CallView.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 356e642d65..d5ec2e71d3 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -554,7 +554,11 @@ export default class CallView extends React.Component { ChevronFace.None, CONTEXT_MENU_VPADDING, )} - mountAsChild={true} + // We mount the context menus as a as a child typically in order to include the + // context menus when fullscreening the call content. + // However, this does not work as well when the call is embedded in a + // picture-in-picture frame. Thus, only mount as child when we are *not* in PiP. + mountAsChild={!this.props.pipMode} onFinished={this.closeDialpad} call={this.props.call} />; @@ -568,7 +572,7 @@ export default class CallView extends React.Component { ChevronFace.None, CONTEXT_MENU_VPADDING, )} - mountAsChild={true} + mountAsChild={!this.props.pipMode} onFinished={this.closeContextMenu} call={this.props.call} />; From 81ddaf2efaf0eda2c296b0e2fb43834b7aae5575 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 5 Aug 2021 11:21:22 -0600 Subject: [PATCH 58/60] Properly set style attribute on shared usercontent iframe Fixes https://github.com/vector-im/element-web/issues/18414 --- src/utils/FileDownloader.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utils/FileDownloader.ts b/src/utils/FileDownloader.ts index a22ff506de..5ec91d71cc 100644 --- a/src/utils/FileDownloader.ts +++ b/src/utils/FileDownloader.ts @@ -43,9 +43,8 @@ function getManagedIframe(): { iframe: HTMLIFrameElement, onLoadPromise: Promise // Dev note: the reassignment warnings are entirely incorrect here. - // @ts-ignore - // noinspection JSConstantReassignment - managedIframe.style = { display: "none" }; + managedIframe.style.display = "none"; + // @ts-ignore // noinspection JSConstantReassignment managedIframe.sandbox = "allow-scripts allow-downloads allow-downloads-without-user-activation"; From 17a3dc5e6dc79ccd9e926c49a9c24f0caae0e0f5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 5 Aug 2021 12:44:12 -0600 Subject: [PATCH 59/60] Stop voice messages that are playing when starting a recording Fixes https://github.com/vector-im/element-web/issues/18410 --- src/components/views/rooms/VoiceRecordComposerTile.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index 019e39d415..1b583444a3 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -35,6 +35,7 @@ import NotificationBadge from "./NotificationBadge"; import { StaticNotificationState } from "../../../stores/notifications/StaticNotificationState"; import { NotificationColor } from "../../../stores/notifications/NotificationColor"; import InlineSpinner from "../elements/InlineSpinner"; +import { PlaybackManager } from "../../../audio/PlaybackManager"; interface IProps { room: Room; @@ -177,6 +178,9 @@ export default class VoiceRecordComposerTile extends React.PureComponent Date: Thu, 5 Aug 2021 17:56:16 -0400 Subject: [PATCH 60/60] Add comments to isRegionalIndicator Signed-off-by: Robin Townsend --- src/emoji.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/emoji.ts b/src/emoji.ts index e871e0bb58..ee84583fc9 100644 --- a/src/emoji.ts +++ b/src/emoji.ts @@ -35,8 +35,15 @@ export const EMOTICON_TO_EMOJI = new Map(); export const getEmojiFromUnicode = unicode => UNICODE_TO_EMOJI.get(stripVariation(unicode)); -const isRegionalIndicator = (x: string): boolean => - Array.from(x).length === 1 && x >= '\u{1f1e6}' && x <= '\u{1f1ff}'; +const isRegionalIndicator = (x: string): boolean => { + // First verify that the string is a single character. We use Array.from + // to make sure we count by characters, not UTF-8 code units. + return Array.from(x).length === 1 && + // Next verify that the character is within the code point range for + // regional indicators. + // http://unicode.org/charts/PDF/Unicode-6.0/U60-1F100.pdf + x >= '\u{1f1e6}' && x <= '\u{1f1ff}'; +}; const EMOJIBASE_GROUP_ID_TO_CATEGORY = [ "people", // smileys