diff --git a/README.md b/README.md index 73afe34df0..b3e96ef001 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Platform Targets: * WebRTC features (VoIP and Video calling) are only available in Chrome & Firefox. * Mobile Web is not currently a target platform - instead please use the native iOS (https://github.com/matrix-org/matrix-ios-kit) and Android - (https://github.com/matrix-org/matrix-android-sdk) SDKs. + (https://github.com/matrix-org/matrix-android-sdk2) SDKs. All code lands on the `develop` branch - `master` is only used for stable releases. **Please file PRs against `develop`!!** diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss index 84f965e6bd..524f107165 100644 --- a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss @@ -101,7 +101,7 @@ limitations under the License. .mx_BaseAvatar { display: inline-flex; - margin: 5px 16px 5px 5px; + margin: auto 16px auto 5px; vertical-align: middle; } @@ -160,31 +160,32 @@ limitations under the License. } } - .mx_AddExistingToSpaceDialog_errorText { - font-weight: $font-semi-bold; - font-size: $font-12px; - line-height: $font-15px; - color: $notice-primary-color; - margin-bottom: 28px; - } - .mx_AddExistingToSpace { display: contents; } .mx_AddExistingToSpaceDialog_footer { display: flex; - margin-top: 32px; + margin-top: 20px; > span { flex-grow: 1; - font-size: $font-14px; + font-size: $font-12px; line-height: $font-15px; - font-weight: $font-semi-bold; + color: $secondary-fg-color; - .mx_AccessibleButton { - font-size: inherit; - display: inline-block; + .mx_ProgressBar { + height: 8px; + width: 100%; + + @mixin ProgressBarBorderRadius 8px; + } + + .mx_AddExistingToSpaceDialog_progressText { + margin-top: 8px; + font-size: $font-15px; + line-height: $font-24px; + color: $primary-fg-color; } > * { @@ -192,8 +193,54 @@ limitations under the License. } } + .mx_AddExistingToSpaceDialog_error { + padding-left: 12px; + + > img { + align-self: center; + } + + .mx_AddExistingToSpaceDialog_errorHeading { + font-weight: $font-semi-bold; + font-size: $font-15px; + line-height: $font-18px; + color: $notice-primary-color; + } + + .mx_AddExistingToSpaceDialog_errorCaption { + margin-top: 4px; + font-size: $font-12px; + line-height: $font-15px; + color: $primary-fg-color; + } + } + .mx_AccessibleButton { display: inline-block; + align-self: center; + } + + .mx_AccessibleButton_kind_primary { + padding: 8px 36px; + } + + .mx_AddExistingToSpaceDialog_retryButton { + margin-left: 12px; + padding-left: 24px; + position: relative; + + &::before { + content: ''; + position: absolute; + background-color: $primary-fg-color; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/retry.svg'); + width: 18px; + height: 18px; + left: 0; + } } .mx_AccessibleButton_kind_link { diff --git a/res/css/views/elements/_ProgressBar.scss b/res/css/views/elements/_ProgressBar.scss index 770978e921..c075ac74ff 100644 --- a/res/css/views/elements/_ProgressBar.scss +++ b/res/css/views/elements/_ProgressBar.scss @@ -21,7 +21,7 @@ progress.mx_ProgressBar { appearance: none; border: none; - @mixin ProgressBarBorderRadius "6px"; + @mixin ProgressBarBorderRadius 6px; @mixin ProgressBarColour $progressbar-fg-color; @mixin ProgressBarBgColour $progressbar-bg-color; ::-webkit-progress-value { diff --git a/res/css/views/rooms/_VoiceRecordComposerTile.scss b/res/css/views/rooms/_VoiceRecordComposerTile.scss index 15daf81672..b87211a847 100644 --- a/res/css/views/rooms/_VoiceRecordComposerTile.scss +++ b/res/css/views/rooms/_VoiceRecordComposerTile.scss @@ -39,14 +39,14 @@ limitations under the License. width: 14px; // w&h are size of icon height: 18px; vertical-align: middle; - margin-right: 7px; // distance from left edge of waveform container (container has some margin too) + margin-right: 11px; // distance from left edge of waveform container (container has some margin too) background-color: $voice-record-icon-color; mask-repeat: no-repeat; mask-size: contain; mask-image: url('$(res)/img/element-icons/trashcan.svg'); } -.mx_VoiceMessagePrimaryContainer { +.mx_VoiceRecordComposerTile_recording.mx_VoiceMessagePrimaryContainer { // Note: remaining class properties are in the PlayerContainer CSS. margin: 6px; // force the composer area to put a gutter around us @@ -55,7 +55,9 @@ limitations under the License. position: relative; // important for the live circle &.mx_VoiceRecordComposerTile_recording { - padding-left: 16px; // +10px for the live circle, +6px for regular padding + // We are putting the circle in this padding, so we need +10px from the regular + // padding on the left side. + padding-left: 22px; &::before { animation: recording-pulse 2s infinite; @@ -65,8 +67,8 @@ limitations under the License. width: 10px; height: 10px; position: absolute; - left: 8px; - top: 16px; // vertically center + left: 12px; // 12px from the left edge for container padding + top: 18px; // vertically center (middle align with clock) border-radius: 10px; } } diff --git a/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss b/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss index 109edfff81..0f879d209e 100644 --- a/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss @@ -22,3 +22,34 @@ limitations under the License. .mx_HelpUserSettingsTab span.mx_AccessibleButton { word-break: break-word; } + +.mx_HelpUserSettingsTab code { + word-break: break-all; + user-select: all; +} + +.mx_HelpUserSettingsTab_accessToken { + display: flex; + justify-content: space-between; + border-radius: 5px; + border: solid 1px $light-fg-color; + margin-bottom: 10px; + margin-top: 10px; + padding: 10px; +} + +.mx_HelpUserSettingsTab_accessToken_copy { + flex-shrink: 0; + cursor: pointer; + margin-left: 20px; + display: inherit; +} + +.mx_HelpUserSettingsTab_accessToken_copy > div { + mask-image: url($copy-button-url); + background-color: $message-action-bar-fg-color; + margin-left: 5px; + width: 20px; + height: 20px; + background-repeat: no-repeat; +} diff --git a/res/css/views/voice_messages/_PlaybackContainer.scss b/res/css/views/voice_messages/_PlaybackContainer.scss index 49bd81ef81..64e8f445e1 100644 --- a/res/css/views/voice_messages/_PlaybackContainer.scss +++ b/res/css/views/voice_messages/_PlaybackContainer.scss @@ -19,8 +19,9 @@ limitations under the License. // Container for live recording and playback controls .mx_VoiceMessagePrimaryContainer { - padding: 6px; // makes us 4px taller than the send/stop button - padding-right: 5px; // there's 1px from the waveform itself, so account for that + // 7px top and bottom for visual design. 12px left & right, but the waveform (right) + // has a 1px padding on it that we want to account for. + padding: 7px 12px 7px 11px; background-color: $voice-record-waveform-bg-color; border-radius: 12px; @@ -30,11 +31,9 @@ limitations under the License. color: $voice-record-waveform-fg-color; font-size: $font-14px; + line-height: $font-24px; .mx_Waveform { - // We want the bars to be 2px shorter than the play/pause button in the waveform control - height: 28px; // default is 30px, so we're subtracting the 2px border off the bars - .mx_Waveform_bar { background-color: $voice-record-waveform-incomplete-fg-color; @@ -47,8 +46,8 @@ limitations under the License. } .mx_Clock { - padding-right: 4px; // isolate from waveform - padding-left: 8px; // isolate from live circle - width: 40px; // we're not using a monospace font, so fake it + width: 42px; // we're not using a monospace font, so fake it + padding-right: 6px; // with the fixed width this ends up as a visual 8px most of the time, as intended. + padding-left: 8px; // isolate from recording circle / play control } } diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index 7292e325df..0be75be28c 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -65,14 +65,17 @@ limitations under the License. } } -.mx_CallView_voice { +.mx_CallView_content { position: relative; display: flex; - flex-direction: column; + border-radius: 8px; +} + +.mx_CallView_voice { align-items: center; justify-content: center; + flex-direction: column; background-color: $inverted-bg-color; - border-radius: 8px; } .mx_CallView_voice_avatarsContainer { @@ -109,9 +112,7 @@ limitations under the License. .mx_CallView_video { width: 100%; height: 100%; - position: relative; z-index: 30; - border-radius: 8px; overflow: hidden; } diff --git a/res/css/views/voip/_VideoFeed.scss b/res/css/views/voip/_VideoFeed.scss index 8ead8bba3e..7d85ac264e 100644 --- a/res/css/views/voip/_VideoFeed.scss +++ b/res/css/views/voip/_VideoFeed.scss @@ -14,21 +14,37 @@ See the License for the specific language governing permissions and limitations under the License. */ +.mx_VideoFeed_voice { + // We don't want to collide with the call controls that have 52px of height + padding-bottom: 52px; + background-color: $inverted-bg-color; +} + + .mx_VideoFeed_remote { width: 100%; height: 100%; - background-color: #000; - z-index: 50; + display: flex; + justify-content: center; + align-items: center; + + &.mx_VideoFeed_video { + background-color: #000; + } } .mx_VideoFeed_local { - width: 25%; - height: 25%; + max-width: 25%; + max-height: 25%; position: absolute; right: 10px; top: 10px; z-index: 100; border-radius: 4px; + + &.mx_VideoFeed_video { + background-color: transparent; + } } .mx_VideoFeed_mirror { diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index cfdda41619..d31b67d4ab 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -9,6 +9,7 @@ $header-panel-text-primary-color: #B9BEC6; $header-panel-text-secondary-color: #c8c8cd; $text-primary-color: #ffffff; $text-secondary-color: #B9BEC6; +$quaternary-fg-color: #6F7882; $search-bg-color: #181b21; $search-placeholder-color: #61708b; $room-highlight-color: #343a46; @@ -42,13 +43,13 @@ $preview-bar-bg-color: $header-panel-bg-color; $groupFilterPanel-bg-color: rgba(38, 39, 43, 0.82); $inverted-bg-color: $base-color; -$voice-record-stop-border-color: #6F7882; // "Quarterly" +$voice-record-stop-border-color: $quaternary-fg-color; $voice-record-waveform-bg-color: #394049; // "Dark Tile" -$voice-record-waveform-fg-color: $tertiary-fg-color; -$voice-record-waveform-incomplete-fg-color: #5b646d; -$voice-record-icon-color: $tertiary-fg-color; +$voice-record-waveform-fg-color: $secondary-fg-color; +$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; +$voice-record-icon-color: $quaternary-fg-color; $voice-playback-button-bg-color: $tertiary-fg-color; -$voice-playback-button-fg-color: $bg-color; +$voice-playback-button-fg-color: #21262C; // "Separator" // used by AddressSelector $selected-color: $room-highlight-color; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 6413a99ce0..6a162bbda7 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -127,11 +127,11 @@ $groupFilterPanel-divider-color: $roomlist-header-color; // See non-legacy dark for variable information $voice-record-stop-border-color: #6F7882; $voice-record-waveform-bg-color: #394049; -$voice-record-waveform-fg-color: $tertiary-fg-color; -$voice-record-waveform-incomplete-fg-color: #5b646d; -$voice-record-icon-color: $tertiary-fg-color; +$voice-record-waveform-fg-color: $secondary-fg-color; +$voice-record-waveform-incomplete-fg-color: #6F7882; +$voice-record-icon-color: #6F7882; $voice-playback-button-bg-color: $tertiary-fg-color; -$voice-playback-button-fg-color: $bg-color; +$voice-playback-button-fg-color: #21262C; $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index 2151724071..cc0f54853e 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -192,15 +192,15 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%) $groupFilterPanel-divider-color: $roomlist-header-color; // See non-legacy _light for variable information -$voice-record-stop-border-color: #E3E8F0; $voice-record-stop-symbol-color: #ff4b55; -$voice-record-waveform-bg-color: #E3E8F0; -$voice-record-waveform-fg-color: $muted-fg-color; -$voice-record-waveform-incomplete-fg-color: #C1C6CD; $voice-record-live-circle-color: #ff4b55; -$voice-record-icon-color: $muted-fg-color; +$voice-record-stop-border-color: #E3E8F0; +$voice-record-waveform-bg-color: #E3E8F0; +$voice-record-waveform-fg-color: $secondary-fg-color; +$voice-record-waveform-incomplete-fg-color: #C1C6CD; +$voice-record-icon-color: $tertiary-fg-color; $voice-playback-button-bg-color: $primary-bg-color; -$voice-playback-button-fg-color: $muted-fg-color; +$voice-playback-button-fg-color: $secondary-fg-color; $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 1763fcdd48..240e78b1e2 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -21,6 +21,7 @@ $notice-primary-bg-color: rgba(255, 75, 85, 0.16); $primary-fg-color: #2e2f32; $secondary-fg-color: #737D8C; $tertiary-fg-color: #8D99A5; +$quaternary-fg-color: #C1C6CD; $header-panel-bg-color: #f3f8fd; // typical text (dark-on-white in light skin) @@ -182,15 +183,18 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%) $groupFilterPanel-divider-color: $roomlist-header-color; -$voice-record-stop-border-color: #E3E8F0; -$voice-record-stop-symbol-color: #ff4b55; // $warning-color, but without letting people change it in themes -$voice-record-waveform-bg-color: #E3E8F0; -$voice-record-waveform-fg-color: $muted-fg-color; -$voice-record-waveform-incomplete-fg-color: #C1C6CD; -$voice-record-live-circle-color: #ff4b55; // $warning-color, but without letting people change it in themes -$voice-record-icon-color: $muted-fg-color; +// These two don't change between themes. They are the $warning-color, but we don't +// want custom themes to affect them by accident. +$voice-record-stop-symbol-color: #ff4b55; +$voice-record-live-circle-color: #ff4b55; + +$voice-record-stop-border-color: #E3E8F0; // "Separator" +$voice-record-waveform-bg-color: #E3E8F0; // "Separator" +$voice-record-waveform-fg-color: $secondary-fg-color; +$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; +$voice-record-icon-color: $tertiary-fg-color; $voice-playback-button-bg-color: $primary-bg-color; -$voice-playback-button-fg-color: $muted-fg-color; +$voice-playback-button-fg-color: $secondary-fg-color; $roomtile-preview-color: $secondary-fg-color; $roomtile-default-badge-bg-color: #61708b; diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 0ab26ef943..e8f2f1bc08 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -118,6 +118,16 @@ declare global { interface HTMLAudioElement { type?: string; + // sinkId & setSinkId are experimental and typescript doesn't know about them + sinkId: string; + setSinkId(outputId: string); + } + + interface HTMLVideoElement { + type?: string; + // sinkId & setSinkId are experimental and typescript doesn't know about them + sinkId: string; + setSinkId(outputId: string); } interface Element { diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 91fd7e4c7d..0268ebfe46 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -85,6 +85,7 @@ import { Action } from './dispatcher/actions'; import VoipUserMapper from './VoipUserMapper'; import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from './widgets/ManagedHybrid'; import { randomUppercaseString, randomLowercaseString } from "matrix-js-sdk/src/randomstring"; +import EventEmitter from 'events'; import SdkConfig from './SdkConfig'; import { ensureDMExists, findDMForUser } from './createRoom'; @@ -138,22 +139,12 @@ export enum PlaceCallType { ScreenSharing = 'screensharing', } -function getRemoteAudioElement(): HTMLAudioElement { - // this needs to be somewhere at the top of the DOM which - // always exists to avoid audio interruptions. - // Might as well just use DOM. - const remoteAudioElement = document.getElementById("remoteAudio") as HTMLAudioElement; - if (!remoteAudioElement) { - console.error( - "Failed to find remoteAudio element - cannot play audio!" + - "You need to add an