diff --git a/.eslintrc.js b/.eslintrc.js index 827b373949..9d68942228 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -63,6 +63,11 @@ module.exports = { "@typescript-eslint/ban-ts-comment": "off", }, }], + settings: { + react: { + version: "detect", + } + } }; function buildRestrictedPropertiesOptions(properties, message) { diff --git a/.github/workflows/layered-build.yaml b/.github/workflows/layered-build.yaml new file mode 100644 index 0000000000..c9d7e89a75 --- /dev/null +++ b/.github/workflows/layered-build.yaml @@ -0,0 +1,31 @@ +name: Layered Preview Build +on: + pull_request: + branches: [develop] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Build + run: scripts/ci/layered.sh && cd element-web && cp element.io/develop/config.json config.json && CI_PACKAGE=true yarn build + - name: Upload Artifact + uses: actions/upload-artifact@v2 + with: + name: previewbuild + path: element-web/webapp + # We'll only use this in a triggered job, then we're done with it + retention-days: 1 + - uses: actions/github-script@v3.1.0 + with: + script: | + var fs = require('fs'); + fs.writeFileSync('${{github.workspace}}/pr.json', JSON.stringify(context.payload.pull_request)); + - name: Upload PR Info + uses: actions/upload-artifact@v2 + with: + name: pr.json + path: pr.json + # We'll only use this in a triggered job, then we're done with it + retention-days: 1 + diff --git a/.github/workflows/netlify.yaml b/.github/workflows/netlify.yaml new file mode 100644 index 0000000000..a6a408bdbd --- /dev/null +++ b/.github/workflows/netlify.yaml @@ -0,0 +1,80 @@ +name: Upload Preview Build to Netlify +on: + workflow_run: + workflows: ["Layered Preview Build"] + types: + - completed +jobs: + build: + runs-on: ubuntu-latest + if: > + ${{ github.event.workflow_run.conclusion == 'success' }} + steps: + # There's a 'download artifact' action but it hasn't been updated for the + # workflow_run action (https://github.com/actions/download-artifact/issues/60) + # so instead we get this mess: + - name: 'Download artifact' + uses: actions/github-script@v3.1.0 + with: + script: | + var artifacts = await github.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{github.event.workflow_run.id }}, + }); + var matchArtifact = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "previewbuild" + })[0]; + var download = await github.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + var fs = require('fs'); + fs.writeFileSync('${{github.workspace}}/previewbuild.zip', Buffer.from(download.data)); + + var prInfoArtifact = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "pr.json" + })[0]; + var download = await github.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: prInfoArtifact.id, + archive_format: 'zip', + }); + var fs = require('fs'); + fs.writeFileSync('${{github.workspace}}/pr.json.zip', Buffer.from(download.data)); + - name: Extract Artifacts + run: unzip -d webapp previewbuild.zip && rm previewbuild.zip && unzip pr.json.zip && rm pr.json.zip + - name: 'Read PR Info' + id: readctx + uses: actions/github-script@v3.1.0 + with: + script: | + var fs = require('fs'); + var pr = JSON.parse(fs.readFileSync('${{github.workspace}}/pr.json')); + console.log(`::set-output name=prnumber::${pr.number}`); + - name: Deploy to Netlify + id: netlify + uses: nwtgck/actions-netlify@v1.2 + with: + publish-dir: webapp + deploy-message: "Deploy from GitHub Actions" + # These don't work because we're in workflow_run + enable-pull-request-comment: false + enable-commit-comment: false + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + timeout-minutes: 1 + - name: Edit PR Description + uses: velas/pr-description@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + pull-request-number: ${{ steps.readctx.outputs.prnumber }} + description-message: | + Preview: ${{ steps.netlify.outputs.deploy-url }} + ⚠️ Do you trust the author of this PR? Maybe this build will steal your keys or give you malware. Exercise caution. Use test accounts. + diff --git a/.github/workflows/preview_changelog.yaml b/.github/workflows/preview_changelog.yaml new file mode 100644 index 0000000000..d68d19361d --- /dev/null +++ b/.github/workflows/preview_changelog.yaml @@ -0,0 +1,12 @@ +name: Preview Changelog +on: + pull_request_target: + types: [ opened, edited, labeled ] +jobs: + changelog: + runs-on: ubuntu-latest + steps: + - name: Preview Changelog + uses: matrix-org/allchange@main + with: + ghToken: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d65a524d1..6f71c1414c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,76 @@ -Changes in [3.27.0](https://github.com/vector-im/element-desktop/releases/tag/v3.27.0) (2021-07-02) +Changes in [3.28.1](https://github.com/vector-im/element-desktop/releases/tag/v3.28.1) (2021-08-17) +=================================================================================================== + +## 🐛 Bug Fixes + * Fix multiple VoIP regressions ([matrix-org/matrix-js-sdk#1860](https://github.com/matrix-org/matrix-js-sdk/pull/1860)). + +Changes in [3.28.0](https://github.com/vector-im/element-desktop/releases/tag/v3.28.0) (2021-08-16) +=================================================================================================== + +## ✨ Features + * Show how long a call was on call tiles ([\#6570](https://github.com/matrix-org/matrix-react-sdk/pull/6570)). Fixes vector-im/element-web#18405. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Add regional indicators to emoji picker ([\#6490](https://github.com/matrix-org/matrix-react-sdk/pull/6490)). Fixes vector-im/element-web#14963. Contributed by [robintown](https://github.com/robintown). + * Make call control buttons accessible to screen reader users ([\#6181](https://github.com/matrix-org/matrix-react-sdk/pull/6181)). Fixes vector-im/element-web#18358. Contributed by [pvagner](https://github.com/pvagner). + * Skip sending a thumbnail if it is not a sufficient saving over the original ([\#6559](https://github.com/matrix-org/matrix-react-sdk/pull/6559)). Fixes vector-im/element-web#17906. + * Increase PiP snapping speed ([\#6539](https://github.com/matrix-org/matrix-react-sdk/pull/6539)). Fixes vector-im/element-web#18371. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Improve and move the incoming call toast ([\#6470](https://github.com/matrix-org/matrix-react-sdk/pull/6470)). Fixes vector-im/element-web#17912. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Allow all of the URL schemes that Firefox allows ([\#6457](https://github.com/matrix-org/matrix-react-sdk/pull/6457)). Contributed by [aaronraimist](https://github.com/aaronraimist). + * Improve bubble layout colors ([\#6452](https://github.com/matrix-org/matrix-react-sdk/pull/6452)). Fixes vector-im/element-web#18081. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Spaces let users switch between Home and All Rooms behaviours ([\#6497](https://github.com/matrix-org/matrix-react-sdk/pull/6497)). Fixes vector-im/element-web#18093. + * Support for MSC2285 (hidden read receipts) ([\#6390](https://github.com/matrix-org/matrix-react-sdk/pull/6390)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Group pinned message events with MELS ([\#6349](https://github.com/matrix-org/matrix-react-sdk/pull/6349)). Fixes vector-im/element-web#17938. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Make version copiable ([\#6227](https://github.com/matrix-org/matrix-react-sdk/pull/6227)). Fixes vector-im/element-web#17603 and vector-im/element-web#18329. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Improve voice messages uploading state ([\#6530](https://github.com/matrix-org/matrix-react-sdk/pull/6530)). Fixes vector-im/element-web#18226 and vector-im/element-web#18224. + * Add surround with feature ([\#5510](https://github.com/matrix-org/matrix-react-sdk/pull/5510)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Improve call event tile wording ([\#6545](https://github.com/matrix-org/matrix-react-sdk/pull/6545)). Fixes vector-im/element-web#18376. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Show an avatar/a turned off microphone icon for muted users ([\#6486](https://github.com/matrix-org/matrix-react-sdk/pull/6486)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Prompt user to leave rooms/subspaces in a space when leaving space ([\#6424](https://github.com/matrix-org/matrix-react-sdk/pull/6424)). Fixes vector-im/element-web#18071. + * Add customisation point to override widget variables ([\#6455](https://github.com/matrix-org/matrix-react-sdk/pull/6455)). Fixes vector-im/element-web#18035. + * Add support for screen sharing in 1:1 calls ([\#5992](https://github.com/matrix-org/matrix-react-sdk/pull/5992)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + +## 🐛 Bug Fixes + * [Release] Fix glare related regressions ([\#6622](https://github.com/matrix-org/matrix-react-sdk/pull/6622)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * [Release] Fix PiP of held calls ([\#6612](https://github.com/matrix-org/matrix-react-sdk/pull/6612)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * [Release] Fix toast colors ([\#6607](https://github.com/matrix-org/matrix-react-sdk/pull/6607)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix [object Object] in Widget Permissions ([\#6560](https://github.com/matrix-org/matrix-react-sdk/pull/6560)). Fixes vector-im/element-web#18384. Contributed by [Palid](https://github.com/Palid). + * Fix right margin for events on IRC layout ([\#6542](https://github.com/matrix-org/matrix-react-sdk/pull/6542)). Fixes vector-im/element-web#18354. + * Mirror only usermedia feeds ([\#6512](https://github.com/matrix-org/matrix-react-sdk/pull/6512)). Fixes vector-im/element-web#5633. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix LogoutDialog warning + TypeScript migration ([\#6533](https://github.com/matrix-org/matrix-react-sdk/pull/6533)). + * Fix the wrong font being used in the room topic field ([\#6527](https://github.com/matrix-org/matrix-react-sdk/pull/6527)). Fixes vector-im/element-web#18339. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix inconsistent styling for links on hover ([\#6513](https://github.com/matrix-org/matrix-react-sdk/pull/6513)). Contributed by [janogarcia](https://github.com/janogarcia). + * Fix incorrect height for encoded placeholder images ([\#6514](https://github.com/matrix-org/matrix-react-sdk/pull/6514)). Contributed by [Palid](https://github.com/Palid). + * Fix call events layout for message bubble ([\#6465](https://github.com/matrix-org/matrix-react-sdk/pull/6465)). Fixes vector-im/element-web#18144. + * Improve subspaces and some utilities around room/space creation ([\#6458](https://github.com/matrix-org/matrix-react-sdk/pull/6458)). Fixes vector-im/element-web#18090 vector-im/element-web#18091 and vector-im/element-web#17256. + * Restore pointer cursor for SenderProfile in message bubbles ([\#6501](https://github.com/matrix-org/matrix-react-sdk/pull/6501)). Fixes vector-im/element-web#18249. + * Fix issues with the Call View ([\#6472](https://github.com/matrix-org/matrix-react-sdk/pull/6472)). Fixes vector-im/element-web#18221. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Align event list summary read receipts when using message bubbles ([\#6500](https://github.com/matrix-org/matrix-react-sdk/pull/6500)). Fixes vector-im/element-web#18143. + * Better positioning for unbubbled events in timeline ([\#6477](https://github.com/matrix-org/matrix-react-sdk/pull/6477)). Fixes vector-im/element-web#18132. + * Realign reactions row with messages in modern layout ([\#6491](https://github.com/matrix-org/matrix-react-sdk/pull/6491)). Fixes vector-im/element-web#18118. Contributed by [robintown](https://github.com/robintown). + * Fix CreateRoomDialog exploding when making public room outside of a space ([\#6492](https://github.com/matrix-org/matrix-react-sdk/pull/6492)). Fixes vector-im/element-web#18275. + * Fix call crashing because `element` was undefined ([\#6488](https://github.com/matrix-org/matrix-react-sdk/pull/6488)). Fixes vector-im/element-web#18270. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Upscale thumbnails to the container size ([\#6589](https://github.com/matrix-org/matrix-react-sdk/pull/6589)). Fixes vector-im/element-web#18307. + * Fix create room dialog in spaces no longer adding to the space ([\#6587](https://github.com/matrix-org/matrix-react-sdk/pull/6587)). Fixes vector-im/element-web#18465. + * Don't show a modal on call reject/user hangup ([\#6580](https://github.com/matrix-org/matrix-react-sdk/pull/6580)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fade Call View Buttons after `componentDidMount` ([\#6581](https://github.com/matrix-org/matrix-react-sdk/pull/6581)). Fixes vector-im/element-web#18439. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix missing expand button on codeblocks ([\#6565](https://github.com/matrix-org/matrix-react-sdk/pull/6565)). Fixes vector-im/element-web#18388. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * allow customizing the bubble layout colors ([\#6568](https://github.com/matrix-org/matrix-react-sdk/pull/6568)). Fixes vector-im/element-web#18408. Contributed by [benneti](https://github.com/benneti). + * Don't flash "Missed call" when accepting a call ([\#6567](https://github.com/matrix-org/matrix-react-sdk/pull/6567)). Fixes vector-im/element-web#18404. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix clicking whitespaces on replies ([\#6571](https://github.com/matrix-org/matrix-react-sdk/pull/6571)). Fixes vector-im/element-web#18327. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix disabled state for voice messages + send button tooltip ([\#6562](https://github.com/matrix-org/matrix-react-sdk/pull/6562)). Fixes vector-im/element-web#18413. + * Fix voice feed being cut-off ([\#6550](https://github.com/matrix-org/matrix-react-sdk/pull/6550)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix sizing issues of the screen picker ([\#6498](https://github.com/matrix-org/matrix-react-sdk/pull/6498)). Fixes vector-im/element-web#18281. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Stop voice messages that are playing when starting a recording ([\#6563](https://github.com/matrix-org/matrix-react-sdk/pull/6563)). Fixes vector-im/element-web#18410. + * Properly set style attribute on shared usercontent iframe ([\#6561](https://github.com/matrix-org/matrix-react-sdk/pull/6561)). Fixes vector-im/element-web#18414. + * Null guard space inviter to prevent the app exploding ([\#6558](https://github.com/matrix-org/matrix-react-sdk/pull/6558)). + * Make the ringing sound mutable/disablable ([\#6534](https://github.com/matrix-org/matrix-react-sdk/pull/6534)). Fixes vector-im/element-web#15591. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix wrong cursor being used in PiP ([\#6551](https://github.com/matrix-org/matrix-react-sdk/pull/6551)). Fixes vector-im/element-web#18383. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Re-pin Jitsi if the widget already exists ([\#6226](https://github.com/matrix-org/matrix-react-sdk/pull/6226)). Fixes vector-im/element-web#17679. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix broken call notification regression ([\#6526](https://github.com/matrix-org/matrix-react-sdk/pull/6526)). Fixes vector-im/element-web#18335. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * createRoom, only send join rule event if we have a join rule to put in it ([\#6516](https://github.com/matrix-org/matrix-react-sdk/pull/6516)). Fixes vector-im/element-web#18301. + * Fix clicking pills inside replies ([\#6508](https://github.com/matrix-org/matrix-react-sdk/pull/6508)). Fixes vector-im/element-web#18283. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix grecaptcha regression ([\#6503](https://github.com/matrix-org/matrix-react-sdk/pull/6503)). Fixes vector-im/element-web#18284. Contributed by [Palid](https://github.com/Palid). + +Changes in [3.27.0](https://github.com/vector-im/element-desktop/releases/tag/v3.27.0) (2021-08-02) =================================================================================================== ## 🔒 SECURITY FIXES diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f7c8c8b1c5..f0ca3eb8a7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ Contributing code to The React SDK ================================== -matrix-react-sdk follows the same pattern as https://github.com/matrix-org/matrix-js-sdk/blob/master/CONTRIBUTING.rst +matrix-react-sdk follows the same pattern as https://github.com/matrix-org/matrix-js-sdk/blob/master/CONTRIBUTING.md diff --git a/package.json b/package.json index 2445e3c973..d6845e0981 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.27.0", + "version": "3.28.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -55,6 +55,8 @@ }, "dependencies": { "@babel/runtime": "^7.12.5", + "@sentry/browser": "^6.11.0", + "@sentry/tracing": "^6.11.0", "await-lock": "^2.1.0", "blurhash": "^1.1.3", "browser-encrypt-attachment": "^0.3.0", @@ -80,7 +82,7 @@ "katex": "^0.12.0", "linkifyjs": "^2.1.9", "lodash": "^4.17.20", - "matrix-js-sdk": "12.2.0", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-widget-api": "^0.1.0-beta.15", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", @@ -149,7 +151,7 @@ "@typescript-eslint/eslint-plugin": "^4.17.0", "@typescript-eslint/parser": "^4.17.0", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1", - "allchange": "github:matrix-org/allchange", + "allchange": "^1.0.2", "babel-jest": "^26.6.3", "chokidar": "^3.5.1", "concurrently": "^5.3.0", diff --git a/res/css/_animations.scss b/res/css/_animations.scss new file mode 100644 index 0000000000..4d3ad97141 --- /dev/null +++ b/res/css/_animations.scss @@ -0,0 +1,55 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/** + * React Transition Group animations are prefixed with 'mx_rtg--' so that we + * know they should not be used anywhere outside of React Transition Groups. +*/ + +.mx_rtg--fade-enter { + opacity: 0; +} +.mx_rtg--fade-enter-active { + opacity: 1; + transition: opacity 300ms ease; +} +.mx_rtg--fade-exit { + opacity: 1; +} +.mx_rtg--fade-exit-active { + opacity: 0; + transition: opacity 300ms ease; +} + + +@keyframes mx--anim-pulse { + 0% { opacity: 1; } + 50% { opacity: 0.7; } + 100% { opacity: 1; } +} + + +@media (prefers-reduced-motion) { + @keyframes mx--anim-pulse { + // Override all keyframes in reduced-motion + } + .mx_rtg--fade-enter-active { + transition: none; + } + .mx_rtg--fade-exit-active { + transition: none; + } +} diff --git a/res/css/_common.scss b/res/css/_common.scss index 6b4e109b3a..5fcc10add0 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -18,6 +18,7 @@ limitations under the License. @import "./_font-sizes.scss"; @import "./_font-weights.scss"; +@import "./_animations.scss"; $hover-transition: 0.08s cubic-bezier(.46, .03, .52, .96); // quadratic @@ -52,8 +53,8 @@ html { body { font-family: $font-family; font-size: $font-15px; - background-color: $primary-bg-color; - color: $primary-fg-color; + background-color: $background; + color: $primary-content; border: 0px; margin: 0px; @@ -88,7 +89,7 @@ b { } h2 { - color: $primary-fg-color; + color: $primary-content; font-weight: 400; font-size: $font-18px; margin-top: 16px; @@ -141,12 +142,12 @@ textarea::placeholder { input[type=text], input[type=password], textarea { background-color: transparent; - color: $primary-fg-color; + color: $primary-content; } /* Required by Firefox */ textarea { - color: $primary-fg-color; + color: $primary-content; } input[type=text]:focus, input[type=password]:focus, textarea:focus { @@ -167,12 +168,12 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { // it has the appearance of a text box so the controls // appear to be part of the input -.mx_Dialog, .mx_MatrixChat { +.mx_Dialog, .mx_MatrixChat_wrapper { .mx_textinput > input[type=text], .mx_textinput > input[type=search] { border: none; flex: 1; - color: $primary-fg-color; + color: $primary-content; } :not(.mx_textinput):not(.mx_Field):not(.mx_no_textinput) > input[type=text], @@ -183,7 +184,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { background-color: transparent; color: $input-darker-fg-color; border-radius: 4px; - border: 1px solid rgba($primary-fg-color, .1); + border: 1px solid rgba($primary-content, .1); // these things should probably not be defined globally margin: 9px; } @@ -208,7 +209,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { :not(.mx_textinput):not(.mx_Field):not(.mx_no_textinput) > input[type=search], .mx_textinput { color: $input-darker-fg-color; - background-color: $primary-bg-color; + background-color: $background; border: none; } } @@ -270,7 +271,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { } .mx_Dialog { - background-color: $primary-bg-color; + background-color: $background; color: $light-fg-color; z-index: 4012; font-weight: 300; @@ -378,8 +379,13 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { .mx_Dialog_content { margin: 24px 0 68px; font-size: $font-14px; - color: $primary-fg-color; + color: $primary-content; word-wrap: break-word; + + a { + color: $accent-color; + cursor: pointer; + } } .mx_Dialog_buttons { @@ -487,8 +493,8 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { border-radius: 3px; border: 1px solid $input-border-color; padding: 9px; - color: $primary-fg-color; - background-color: $primary-bg-color; + color: $primary-content; + background-color: $background; } .mx_textButton { diff --git a/res/css/_components.scss b/res/css/_components.scss index 92d2bfe7f3..566b84a7c8 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -17,6 +17,7 @@ @import "./structures/_LeftPanelWidget.scss"; @import "./structures/_MainSplit.scss"; @import "./structures/_MatrixChat.scss"; +@import "./structures/_BackdropPanel.scss"; @import "./structures/_MyGroups.scss"; @import "./structures/_NonUrgentToastContainer.scss"; @import "./structures/_NotificationPanel.scss"; @@ -27,8 +28,8 @@ @import "./structures/_RoomView.scss"; @import "./structures/_ScrollPanel.scss"; @import "./structures/_SearchBox.scss"; +@import "./structures/_SpaceHierarchy.scss"; @import "./structures/_SpacePanel.scss"; -@import "./structures/_SpaceRoomDirectory.scss"; @import "./structures/_SpaceRoomView.scss"; @import "./structures/_TabbedView.scss"; @import "./structures/_ToastContainer.scss"; @@ -75,6 +76,7 @@ @import "./views/dialogs/_CreateCommunityPrototypeDialog.scss"; @import "./views/dialogs/_CreateGroupDialog.scss"; @import "./views/dialogs/_CreateRoomDialog.scss"; +@import "./views/dialogs/_CreateSpaceFromCommunityDialog.scss"; @import "./views/dialogs/_CreateSubspaceDialog.scss"; @import "./views/dialogs/_DeactivateAccountDialog.scss"; @import "./views/dialogs/_DevtoolsDialog.scss"; @@ -240,6 +242,7 @@ @import "./views/settings/_E2eAdvancedPanel.scss"; @import "./views/settings/_EmailAddresses.scss"; @import "./views/settings/_IntegrationManager.scss"; +@import "./views/settings/_LayoutSwitcher.scss"; @import "./views/settings/_Notifications.scss"; @import "./views/settings/_PhoneNumbers.scss"; @import "./views/settings/_ProfileSettings.scss"; @@ -269,10 +272,12 @@ @import "./views/toasts/_IncomingCallToast.scss"; @import "./views/toasts/_NonUrgentEchoFailureToast.scss"; @import "./views/verification/_VerificationShowSas.scss"; +@import "./views/voip/CallView/_CallViewButtons.scss"; @import "./views/voip/_CallContainer.scss"; @import "./views/voip/_CallPreview.scss"; @import "./views/voip/_CallView.scss"; @import "./views/voip/_CallViewForRoom.scss"; +@import "./views/voip/_CallViewHeader.scss"; @import "./views/voip/_CallViewSidebar.scss"; @import "./views/voip/_DialPad.scss"; @import "./views/voip/_DialPadContextMenu.scss"; diff --git a/res/css/structures/_BackdropPanel.scss b/res/css/structures/_BackdropPanel.scss new file mode 100644 index 0000000000..482507cb15 --- /dev/null +++ b/res/css/structures/_BackdropPanel.scss @@ -0,0 +1,37 @@ +/* +Copyright 2021 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_BackdropPanel { + position: absolute; + left: 0; + top: 0; + height: 100vh; + width: 100%; + overflow: hidden; + filter: blur(var(--lp-background-blur)); + // Force a new layer for the backdropPanel so it's better hardware supported + transform: translateZ(0); +} + +.mx_BackdropPanel--image { + position: absolute; + top: 0; + left: 0; + min-height: 100%; + z-index: 0; + pointer-events: none; + overflow: hidden; +} diff --git a/res/css/structures/_ContextualMenu.scss b/res/css/structures/_ContextualMenu.scss index d7f2cb76e8..9f2b9e24b8 100644 --- a/res/css/structures/_ContextualMenu.scss +++ b/res/css/structures/_ContextualMenu.scss @@ -34,7 +34,7 @@ limitations under the License. border-radius: 8px; box-shadow: 4px 4px 12px 0 $menu-box-shadow-color; background-color: $menu-bg-color; - color: $primary-fg-color; + color: $primary-content; position: absolute; font-size: $font-14px; z-index: 5001; diff --git a/res/css/structures/_CreateRoom.scss b/res/css/structures/_CreateRoom.scss index e859beb20e..3d23ccc4b2 100644 --- a/res/css/structures/_CreateRoom.scss +++ b/res/css/structures/_CreateRoom.scss @@ -18,7 +18,7 @@ limitations under the License. width: 960px; margin-left: auto; margin-right: auto; - color: $primary-fg-color; + color: $primary-content; } .mx_CreateRoom input, diff --git a/res/css/structures/_GroupFilterPanel.scss b/res/css/structures/_GroupFilterPanel.scss index 444435dd57..cc0e760031 100644 --- a/res/css/structures/_GroupFilterPanel.scss +++ b/res/css/structures/_GroupFilterPanel.scss @@ -14,10 +14,27 @@ See the License for the specific language governing permissions and limitations under the License. */ +$groupFilterPanelWidth: 56px; // only applies in this file, used for calculations + +.mx_GroupFilterPanelContainer { + flex-grow: 0; + flex-shrink: 0; + width: $groupFilterPanelWidth; + height: 100%; + + // Create another flexbox so the GroupFilterPanel fills the container + display: flex; + flex-direction: column; + + // GroupFilterPanel handles its own CSS +} + .mx_GroupFilterPanel { - flex: 1; + z-index: 1; background-color: $groupFilterPanel-bg-color; + flex: 1; cursor: pointer; + position: relative; display: flex; flex-direction: column; @@ -75,13 +92,13 @@ limitations under the License. } .mx_GroupFilterPanel .mx_TagTile.mx_TagTile_selected_prototype { - background-color: $primary-bg-color; + background-color: $background; border-radius: 6px; } .mx_TagTile_selected_prototype { .mx_TagTile_homeIcon::before { - background-color: $primary-fg-color; // dark-on-light + background-color: $primary-content; // dark-on-light } } diff --git a/res/css/structures/_GroupView.scss b/res/css/structures/_GroupView.scss index 60f9ebdd08..5e224b1f38 100644 --- a/res/css/structures/_GroupView.scss +++ b/res/css/structures/_GroupView.scss @@ -132,7 +132,7 @@ limitations under the License. width: 100%; height: 31px; overflow: hidden; - color: $primary-fg-color; + color: $primary-content; font-weight: bold; font-size: $font-22px; padding-left: 19px; @@ -368,6 +368,65 @@ limitations under the License. padding: 40px 20px; } +.mx_GroupView_spaceUpgradePrompt { + padding: 16px 50px; + background-color: $header-panel-bg-color; + border-radius: 8px; + max-width: 632px; + font-size: $font-15px; + line-height: $font-24px; + margin-top: 24px; + position: relative; + + > h2 { + font-size: inherit; + font-weight: $font-semi-bold; + } + + > p, h2 { + margin: 0; + } + + &::before { + content: ""; + position: absolute; + height: $font-24px; + width: 20px; + left: 18px; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/room/room-summary.svg'); + background-color: $secondary-content; + } + + .mx_AccessibleButton_kind_link { + padding: 0; + } + + .mx_GroupView_spaceUpgradePrompt_close { + width: 16px; + height: 16px; + border-radius: 8px; + background-color: $input-darker-bg-color; + position: absolute; + top: 16px; + right: 16px; + + &::before { + content: ""; + position: absolute; + width: inherit; + height: inherit; + mask-repeat: no-repeat; + mask-position: center; + mask-size: 8px; + mask-image: url('$(res)/img/image-view/close.svg'); + background-color: $secondary-content; + } + } +} + .mx_GroupView .mx_MemberInfo .mx_AutoHideScrollbar > :not(.mx_MemberInfo_avatar) { padding-left: 16px; padding-right: 16px; diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index f254ca3226..5ddea244f3 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -14,31 +14,47 @@ See the License for the specific language governing permissions and limitations under the License. */ -$groupFilterPanelWidth: 56px; // only applies in this file, used for calculations $roomListCollapsedWidth: 68px; +.mx_MatrixChat--with-avatar { + .mx_LeftPanel, + .mx_LeftPanel .mx_LeftPanel_roomListContainer { + background-color: transparent; + } +} + +.mx_LeftPanel_wrapper { + display: flex; + max-width: 50%; + position: relative; + + // Contain the amount of layers rendered by constraining what actually needs re-layering via css + contain: layout paint; + + .mx_LeftPanel_wrapper--user { + background-color: $roomlist-bg-color; + display: flex; + overflow: hidden; + position: relative; + + &[data-collapsed] { + max-width: $roomListCollapsedWidth; + } + } +} + + + .mx_LeftPanel { background-color: $roomlist-bg-color; // TODO decrease this once Spaces launches as it'll no longer need to include the 56px Community Panel - min-width: 206px; - max-width: 50%; // Create a row-based flexbox for the GroupFilterPanel and the room list display: flex; contain: content; - - .mx_LeftPanel_GroupFilterPanelContainer { - flex-grow: 0; - flex-shrink: 0; - flex-basis: $groupFilterPanelWidth; - height: 100%; - - // Create another flexbox so the GroupFilterPanel fills the container - display: flex; - flex-direction: column; - - // GroupFilterPanel handles its own CSS - } + position: relative; + flex-grow: 1; + overflow: hidden; // Note: The 'room list' in this context is actually everything that isn't the tag // panel, such as the menu options, breadcrumbs, filtering, etc @@ -130,7 +146,7 @@ $roomListCollapsedWidth: 68px; mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $secondary-fg-color; + background: $secondary-content; } } @@ -153,7 +169,7 @@ $roomListCollapsedWidth: 68px; mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $secondary-fg-color; + background: $secondary-content; } &.mx_LeftPanel_exploreButton_space::before { @@ -171,6 +187,8 @@ $roomListCollapsedWidth: 68px; } .mx_LeftPanel_roomListWrapper { + // Make the y-scrollbar more responsive + padding-right: 2px; overflow: hidden; margin-top: 10px; // so we're not up against the search/filter flex: 1 0 0; // needed in Safari to properly set flex-basis @@ -192,6 +210,7 @@ $roomListCollapsedWidth: 68px; // These styles override the defaults for the minimized (66px) layout &.mx_LeftPanel_minimized { + flex-grow: 0; min-width: unset; width: unset !important; diff --git a/res/css/structures/_LeftPanelWidget.scss b/res/css/structures/_LeftPanelWidget.scss index 6e2d99bb37..93c2898395 100644 --- a/res/css/structures/_LeftPanelWidget.scss +++ b/res/css/structures/_LeftPanelWidget.scss @@ -113,7 +113,7 @@ limitations under the License. &:hover .mx_LeftPanelWidget_resizerHandle { opacity: 0.8; - background-color: $primary-fg-color; + background-color: $primary-content; } .mx_LeftPanelWidget_maximizeButton { diff --git a/res/css/structures/_MainSplit.scss b/res/css/structures/_MainSplit.scss index 8199121420..407a1c270c 100644 --- a/res/css/structures/_MainSplit.scss +++ b/res/css/structures/_MainSplit.scss @@ -38,7 +38,7 @@ limitations under the License. width: 4px !important; border-radius: 4px !important; - background-color: $primary-fg-color; + background-color: $primary-content; opacity: 0.8; } } diff --git a/res/css/structures/_MatrixChat.scss b/res/css/structures/_MatrixChat.scss index a220c5d505..fdf5cb1a03 100644 --- a/res/css/structures/_MatrixChat.scss +++ b/res/css/structures/_MatrixChat.scss @@ -29,8 +29,6 @@ limitations under the License. .mx_MatrixChat_wrapper { display: flex; - flex-direction: column; - width: 100%; height: 100%; } @@ -42,13 +40,12 @@ limitations under the License. } .mx_MatrixChat { + position: relative; width: 100%; height: 100%; display: flex; - order: 2; - flex: 1; min-height: 0; } @@ -66,8 +63,8 @@ limitations under the License. } /* not the left panel, and not the resize handle, so the roomview/groupview/... */ -.mx_MatrixChat > :not(.mx_LeftPanel):not(.mx_SpacePanel):not(.mx_ResizeHandle) { - background-color: $primary-bg-color; +.mx_MatrixChat > :not(.mx_LeftPanel):not(.mx_SpacePanel):not(.mx_ResizeHandle):not(.mx_LeftPanel_wrapper) { + background-color: $background; flex: 1 1 0; min-width: 0; @@ -94,7 +91,7 @@ limitations under the License. content: ' '; - background-color: $primary-fg-color; + background-color: $primary-content; opacity: 0.8; } } diff --git a/res/css/structures/_NotificationPanel.scss b/res/css/structures/_NotificationPanel.scss index d271cd2bcc..68e1dd6a9a 100644 --- a/res/css/structures/_NotificationPanel.scss +++ b/res/css/structures/_NotificationPanel.scss @@ -49,7 +49,7 @@ limitations under the License. bottom: 0; left: 0; right: 0; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; height: 1px; opacity: 0.4; content: ''; @@ -70,7 +70,7 @@ limitations under the License. } .mx_NotificationPanel .mx_EventTile_roomName a { - color: $primary-fg-color; + color: $primary-content; } .mx_NotificationPanel .mx_EventTile_avatar { @@ -79,7 +79,7 @@ limitations under the License. .mx_NotificationPanel .mx_EventTile .mx_SenderProfile, .mx_NotificationPanel .mx_EventTile .mx_MessageTimestamp { - color: $primary-fg-color; + color: $primary-content; font-size: $font-12px; display: inline; } @@ -118,7 +118,7 @@ limitations under the License. } .mx_NotificationPanel .mx_EventTile:hover .mx_EventTile_line { - background-color: $primary-bg-color; + background-color: $background; } .mx_NotificationPanel .mx_EventTile_content { diff --git a/res/css/structures/_RightPanel.scss b/res/css/structures/_RightPanel.scss index 3222fe936c..5316cba61d 100644 --- a/res/css/structures/_RightPanel.scss +++ b/res/css/structures/_RightPanel.scss @@ -43,7 +43,7 @@ limitations under the License. .mx_RightPanel_headerButtonGroup { height: 100%; display: flex; - background-color: $primary-bg-color; + background-color: $background; padding: 0 9px; align-items: center; } diff --git a/res/css/structures/_RoomDirectory.scss b/res/css/structures/_RoomDirectory.scss index ec07500af5..fb0f7d10e1 100644 --- a/res/css/structures/_RoomDirectory.scss +++ b/res/css/structures/_RoomDirectory.scss @@ -28,7 +28,7 @@ limitations under the License. .mx_RoomDirectory { margin-bottom: 12px; - color: $primary-fg-color; + color: $primary-content; word-break: break-word; display: flex; flex-direction: column; @@ -71,14 +71,14 @@ limitations under the License. font-weight: $font-semi-bold; font-size: $font-15px; line-height: $font-18px; - color: $primary-fg-color; + color: $primary-content; } > p { margin: 40px auto 60px; font-size: $font-14px; line-height: $font-20px; - color: $secondary-fg-color; + color: $secondary-content; max-width: 464px; // easier reading } @@ -97,7 +97,7 @@ limitations under the License. } .mx_RoomDirectory_table { - color: $primary-fg-color; + color: $primary-content; display: grid; font-size: $font-12px; grid-template-columns: max-content auto max-content max-content max-content; diff --git a/res/css/structures/_RoomSearch.scss b/res/css/structures/_RoomSearch.scss index 7fdafab5a6..bbd60a5ff3 100644 --- a/res/css/structures/_RoomSearch.scss +++ b/res/css/structures/_RoomSearch.scss @@ -33,14 +33,14 @@ limitations under the License. height: 16px; mask: url('$(res)/img/element-icons/roomlist/search.svg'); mask-repeat: no-repeat; - background-color: $secondary-fg-color; + background-color: $secondary-content; margin-left: 7px; } .mx_RoomSearch_input { border: none !important; // !important to override default app-wide styles flex: 1 !important; // !important to override default app-wide styles - color: $primary-fg-color !important; // !important to override default app-wide styles + color: $primary-content !important; // !important to override default app-wide styles padding: 0; height: 100%; width: 100%; @@ -48,12 +48,12 @@ limitations under the License. line-height: $font-16px; &:not(.mx_RoomSearch_inputExpanded)::placeholder { - color: $tertiary-fg-color !important; // !important to override default app-wide styles + color: $tertiary-content !important; // !important to override default app-wide styles } } &.mx_RoomSearch_hasQuery { - border-color: $secondary-fg-color; + border-color: $secondary-content; } &.mx_RoomSearch_focused { @@ -62,7 +62,7 @@ limitations under the License. } &.mx_RoomSearch_focused, &.mx_RoomSearch_hasQuery { - background-color: $roomlist-filter-active-bg-color; + background-color: $background; .mx_RoomSearch_clearButton { width: 16px; @@ -71,7 +71,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background-color: $secondary-fg-color; + background-color: $secondary-content; margin-right: 8px; } } diff --git a/res/css/structures/_RoomStatusBar.scss b/res/css/structures/_RoomStatusBar.scss index de9e049165..bdfbca1afa 100644 --- a/res/css/structures/_RoomStatusBar.scss +++ b/res/css/structures/_RoomStatusBar.scss @@ -27,7 +27,7 @@ limitations under the License. .mx_RoomStatusBar_typingIndicatorAvatars .mx_BaseAvatar_image { margin-right: -12px; - border: 1px solid $primary-bg-color; + border: 1px solid $background; } .mx_RoomStatusBar_typingIndicatorAvatars .mx_BaseAvatar_initial { @@ -39,7 +39,7 @@ limitations under the License. display: inline-block; color: #acacac; background-color: #ddd; - border: 1px solid $primary-bg-color; + border: 1px solid $background; border-radius: 40px; width: 24px; height: 24px; @@ -171,14 +171,14 @@ limitations under the License. } .mx_RoomStatusBar_connectionLostBar_desc { - color: $primary-fg-color; + color: $primary-content; font-size: $font-13px; opacity: 0.5; padding-bottom: 20px; } .mx_RoomStatusBar_resend_link { - color: $primary-fg-color !important; + color: $primary-content !important; text-decoration: underline !important; cursor: pointer; } @@ -187,7 +187,7 @@ limitations under the License. height: 50px; line-height: $font-50px; - color: $primary-fg-color; + color: $primary-content; opacity: 0.5; overflow-y: hidden; display: block; diff --git a/res/css/structures/_RoomView.scss b/res/css/structures/_RoomView.scss index 831f186ed4..86c2efeb4a 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -14,10 +14,22 @@ See the License for the specific language governing permissions and limitations under the License. */ +.mx_RoomView_wrapper { + display: flex; + flex-direction: column; + flex: 1; + position: relative; + justify-content: center; + // Contain the amount of layers rendered by constraining what actually needs re-layering via css + contain: strict; +} + .mx_RoomView { word-wrap: break-word; display: flex; flex-direction: column; + flex: 1; + position: relative; } @@ -40,7 +52,7 @@ limitations under the License. pointer-events: none; - background-color: $primary-bg-color; + background-color: $background; opacity: 0.95; position: absolute; @@ -87,7 +99,7 @@ limitations under the License. left: 0; right: 0; z-index: 3000; - background-color: $primary-bg-color; + background-color: $background; } .mx_RoomView_auxPanel_hiddenHighlights { @@ -153,7 +165,6 @@ limitations under the License. flex: 1; display: flex; flex-direction: column; - contain: content; } .mx_RoomView_statusArea { @@ -161,7 +172,7 @@ limitations under the License. flex: 0 0 auto; max-height: 0px; - background-color: $primary-bg-color; + background-color: $background; z-index: 1000; overflow: hidden; @@ -246,7 +257,7 @@ hr.mx_RoomView_myReadMarker { } .mx_RoomView_callStatusBar .mx_UploadBar_uploadProgressInner { - background-color: $primary-bg-color; + background-color: $background; } .mx_RoomView_callStatusBar .mx_UploadBar_uploadFilename { diff --git a/res/css/structures/_ScrollPanel.scss b/res/css/structures/_ScrollPanel.scss index 7b75c69e86..a668594bba 100644 --- a/res/css/structures/_ScrollPanel.scss +++ b/res/css/structures/_ScrollPanel.scss @@ -15,7 +15,6 @@ limitations under the License. */ .mx_ScrollPanel { - .mx_RoomView_MessageList { position: relative; display: flex; diff --git a/res/css/structures/_SpaceRoomDirectory.scss b/res/css/structures/_SpaceHierarchy.scss similarity index 80% rename from res/css/structures/_SpaceRoomDirectory.scss rename to res/css/structures/_SpaceHierarchy.scss index cb91aa3c7d..a5d589f9c2 100644 --- a/res/css/structures/_SpaceRoomDirectory.scss +++ b/res/css/structures/_SpaceHierarchy.scss @@ -14,21 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_SpaceRoomDirectory_dialogWrapper > .mx_Dialog { - max-width: 960px; - height: 100%; -} - -.mx_SpaceRoomDirectory { - height: 100%; - margin-bottom: 12px; - color: $primary-fg-color; - word-break: break-word; - display: flex; - flex-direction: column; -} - -.mx_SpaceRoomDirectory, .mx_SpaceRoomView_landing { .mx_Dialog_title { display: flex; @@ -52,7 +37,7 @@ limitations under the License. > div { font-weight: 400; - color: $secondary-fg-color; + color: $secondary-content; font-size: $font-15px; line-height: $font-24px; } @@ -68,23 +53,29 @@ limitations under the License. margin: 24px 0 16px; } - .mx_SpaceRoomDirectory_noResults { + .mx_SpaceHierarchy_noResults { text-align: center; > div { font-size: $font-15px; line-height: $font-24px; - color: $secondary-fg-color; + color: $secondary-content; } } - .mx_SpaceRoomDirectory_listHeader { + .mx_SpaceHierarchy_listHeader { display: flex; min-height: 32px; align-items: center; font-size: $font-15px; line-height: $font-24px; - color: $primary-fg-color; + color: $primary-content; + margin-bottom: 12px; + + > h4 { + font-weight: $font-semi-bold; + margin: 0; + } .mx_AccessibleButton { padding: 4px 12px; @@ -105,7 +96,7 @@ limitations under the License. } } - .mx_SpaceRoomDirectory_error { + .mx_SpaceHierarchy_error { position: relative; font-weight: $font-semi-bold; color: $notice-primary-color; @@ -124,43 +115,44 @@ limitations under the License. background-image: url("$(res)/img/element-icons/warning-badge.svg"); } } -} -.mx_SpaceRoomDirectory_list { - margin-top: 16px; - padding-bottom: 40px; + .mx_SpaceHierarchy_list { + list-style: none; + padding: 0; + margin: 0; + } - .mx_SpaceRoomDirectory_roomCount { + .mx_SpaceHierarchy_roomCount { > h3 { display: inline; font-weight: $font-semi-bold; font-size: $font-18px; line-height: $font-22px; - color: $primary-fg-color; + color: $primary-content; } > span { margin-left: 8px; font-size: $font-15px; line-height: $font-24px; - color: $secondary-fg-color; + color: $secondary-content; } } - .mx_SpaceRoomDirectory_subspace { + .mx_SpaceHierarchy_subspace { .mx_BaseAvatar_image { border-radius: 8px; } } - .mx_SpaceRoomDirectory_subspace_toggle { + .mx_SpaceHierarchy_subspace_toggle { position: absolute; left: -1px; top: 10px; height: 16px; width: 16px; border-radius: 4px; - background-color: $primary-bg-color; + background-color: $background; &::before { content: ''; @@ -171,23 +163,23 @@ limitations under the License. width: 16px; mask-repeat: no-repeat; mask-position: center; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; mask-size: 16px; transform: rotate(270deg); mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); } - &.mx_SpaceRoomDirectory_subspace_toggle_shown::before { + &.mx_SpaceHierarchy_subspace_toggle_shown::before { transform: rotate(0deg); } } - .mx_SpaceRoomDirectory_subspace_children { + .mx_SpaceHierarchy_subspace_children { position: relative; padding-left: 12px; } - .mx_SpaceRoomDirectory_roomTile { + .mx_SpaceHierarchy_roomTile { position: relative; padding: 8px 16px; border-radius: 8px; @@ -204,7 +196,7 @@ limitations under the License. grid-column: 1; } - .mx_SpaceRoomDirectory_roomTile_name { + .mx_SpaceHierarchy_roomTile_name { font-weight: $font-semi-bold; font-size: $font-15px; line-height: $font-18px; @@ -214,7 +206,7 @@ limitations under the License. .mx_InfoTooltip { display: inline; margin-left: 12px; - color: $tertiary-fg-color; + color: $tertiary-content; font-size: $font-12px; line-height: $font-15px; @@ -232,10 +224,10 @@ limitations under the License. } } - .mx_SpaceRoomDirectory_roomTile_info { + .mx_SpaceHierarchy_roomTile_info { font-size: $font-14px; line-height: $font-18px; - color: $secondary-fg-color; + color: $secondary-content; grid-row: 2; grid-column: 1/3; display: -webkit-box; @@ -244,7 +236,7 @@ limitations under the License. overflow: hidden; } - .mx_SpaceRoomDirectory_actions { + .mx_SpaceHierarchy_actions { text-align: right; margin-left: 20px; grid-column: 3; @@ -269,7 +261,7 @@ limitations under the License. } } - &:hover { + &:hover, &:focus-within { background-color: $groupFilterPanel-bg-color; .mx_AccessibleButton { @@ -278,8 +270,12 @@ limitations under the License. } } - .mx_SpaceRoomDirectory_roomTile, - .mx_SpaceRoomDirectory_subspace_children { + li.mx_SpaceHierarchy_roomTileWrapper { + list-style: none; + } + + .mx_SpaceHierarchy_roomTile, + .mx_SpaceHierarchy_subspace_children { &::before { content: ""; position: absolute; @@ -291,12 +287,12 @@ limitations under the License. } } - .mx_SpaceRoomDirectory_actions { - .mx_SpaceRoomDirectory_actionsText { + .mx_SpaceHierarchy_actions { + .mx_SpaceHierarchy_actionsText { font-weight: normal; font-size: $font-12px; line-height: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; } } @@ -307,7 +303,7 @@ limitations under the License. margin: 20px 0; } - .mx_SpaceRoomDirectory_createRoom { + .mx_SpaceHierarchy_createRoom { display: block; margin: 16px auto 0; width: max-content; diff --git a/res/css/structures/_SpacePanel.scss b/res/css/structures/_SpacePanel.scss index 1dea6332f5..702936523d 100644 --- a/res/css/structures/_SpacePanel.scss +++ b/res/css/structures/_SpacePanel.scss @@ -20,13 +20,16 @@ $gutterSize: 16px; $activeBorderTransparentGap: 1px; $activeBackgroundColor: $roomtile-selected-bg-color; -$activeBorderColor: $secondary-fg-color; +$activeBorderColor: $secondary-content; .mx_SpacePanel { - flex: 0 0 auto; background-color: $groupFilterPanel-bg-color; + flex: 0 0 auto; padding: 0; margin: 0; + position: relative; + // Fix for the blurred avatar-background + z-index: 1; // Create another flexbox so the Panel fills the container display: flex; @@ -235,7 +238,7 @@ $activeBorderColor: $secondary-fg-color; mask-size: contain; mask-repeat: no-repeat; mask-image: url('$(res)/img/element-icons/context-menu.svg'); - background: $primary-fg-color; + background: $primary-content; } } } diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 58a4b426c2..39eabe2e07 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -32,7 +32,7 @@ $SpaceRoomViewInnerWidth: 428px; } > span { - color: $secondary-fg-color; + color: $secondary-content; } &::before { @@ -45,7 +45,7 @@ $SpaceRoomViewInnerWidth: 428px; mask-position: center; mask-repeat: no-repeat; mask-size: 24px; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; } &:hover { @@ -56,12 +56,15 @@ $SpaceRoomViewInnerWidth: 428px; } > span { - color: $primary-fg-color; + color: $primary-content; } } } .mx_SpaceRoomView { + overflow-y: auto; + flex: 1; + .mx_MainSplit > div:first-child { padding: 80px 60px; flex-grow: 1; @@ -72,13 +75,13 @@ $SpaceRoomViewInnerWidth: 428px; margin: 0; font-size: $font-24px; font-weight: $font-semi-bold; - color: $primary-fg-color; + color: $primary-content; width: max-content; } .mx_SpaceRoomView_description { font-size: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; margin-top: 12px; margin-bottom: 24px; max-width: $SpaceRoomViewInnerWidth; @@ -154,7 +157,7 @@ $SpaceRoomViewInnerWidth: 428px; font-weight: $font-semi-bold; font-size: $font-14px; line-height: $font-24px; - color: $primary-fg-color; + color: $primary-content; margin-top: 24px; position: relative; padding-left: 24px; @@ -176,7 +179,19 @@ $SpaceRoomViewInnerWidth: 428px; mask-position: center; mask-size: contain; mask-image: url('$(res)/img/element-icons/room/room-summary.svg'); - background-color: $secondary-fg-color; + background-color: $secondary-content; + } + } + + .mx_SpaceRoomView_preview_migratedCommunity { + margin-bottom: 16px; + padding: 8px 12px; + border-radius: 8px; + border: 1px solid $input-border-color; + width: max-content; + + .mx_BaseAvatar { + margin-right: 4px; } } @@ -195,7 +210,7 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SpaceRoomView_preview_inviter_mxid { line-height: $font-24px; - color: $secondary-fg-color; + color: $secondary-content; } } } @@ -212,7 +227,7 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SpaceRoomView_preview_topic { font-size: $font-14px; line-height: $font-22px; - color: $secondary-fg-color; + color: $secondary-content; margin: 20px 0; max-height: 160px; overflow-y: auto; @@ -236,6 +251,7 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SpaceRoomView_landing { display: flex; flex-direction: column; + min-width: 0; > .mx_BaseAvatar_image, > .mx_BaseAvatar > .mx_BaseAvatar_image { @@ -245,7 +261,7 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SpaceRoomView_landing_name { margin: 24px 0 16px; font-size: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; > span { display: inline-block; @@ -318,7 +334,7 @@ $SpaceRoomViewInnerWidth: 428px; top: 0; height: 24px; width: 24px; - background: $tertiary-fg-color; + background: $tertiary-content; mask-position: center; mask-size: contain; mask-repeat: no-repeat; @@ -342,16 +358,11 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SpaceFeedbackPrompt { padding: 7px; // 8px - 1px border - border: 1px solid $menu-border-color; + border: 1px solid rgba($primary-content, .1); border-radius: 8px; width: max-content; margin: 0 0 -40px auto; // collapse its own height to not push other components down } - - .mx_SpaceRoomDirectory_list { - // we don't want this container to get forced into the flexbox layout - display: contents; - } } .mx_SpaceRoomView_privateScope { @@ -376,7 +387,7 @@ $SpaceRoomViewInnerWidth: 428px; width: 432px; border-radius: 8px; background-color: $info-plinth-bg-color; - color: $secondary-fg-color; + color: $secondary-content; box-sizing: border-box; > h3 { @@ -403,7 +414,7 @@ $SpaceRoomViewInnerWidth: 428px; position: absolute; top: 14px; left: 14px; - background-color: $secondary-fg-color; + background-color: $secondary-content; } } @@ -426,7 +437,7 @@ $SpaceRoomViewInnerWidth: 428px; } .mx_SpaceRoomView_inviteTeammates_buttons { - color: $secondary-fg-color; + color: $secondary-content; margin-top: 28px; .mx_AccessibleButton { @@ -442,7 +453,7 @@ $SpaceRoomViewInnerWidth: 428px; width: 24px; top: 0; left: 0; - background-color: $secondary-fg-color; + background-color: $secondary-content; mask-repeat: no-repeat; mask-position: center; mask-size: contain; @@ -461,7 +472,7 @@ $SpaceRoomViewInnerWidth: 428px; } .mx_SpaceRoomView_info { - color: $secondary-fg-color; + color: $secondary-content; font-size: $font-15px; line-height: $font-24px; margin: 20px 0; @@ -480,7 +491,7 @@ $SpaceRoomViewInnerWidth: 428px; left: -2px; mask-position: center; mask-repeat: no-repeat; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; } } diff --git a/res/css/structures/_TabbedView.scss b/res/css/structures/_TabbedView.scss index 833450a25b..e185197f25 100644 --- a/res/css/structures/_TabbedView.scss +++ b/res/css/structures/_TabbedView.scss @@ -80,7 +80,7 @@ limitations under the License. .mx_TabbedView_tabLabel_text { font-size: 15px; - color: $tertiary-fg-color; + color: $tertiary-content; } } diff --git a/res/css/structures/_ToastContainer.scss b/res/css/structures/_ToastContainer.scss index 2c3f1c705c..6024df5dc0 100644 --- a/res/css/structures/_ToastContainer.scss +++ b/res/css/structures/_ToastContainer.scss @@ -28,7 +28,7 @@ limitations under the License. margin: 0 4px; grid-row: 2 / 4; grid-column: 1; - background-color: $toast-bg-color; + background-color: $system; box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.5); border-radius: 8px; } @@ -36,8 +36,8 @@ limitations under the License. .mx_Toast_toast { grid-row: 1 / 3; grid-column: 1; - color: $primary-fg-color; - background-color: $toast-bg-color; + background-color: $system; + color: $primary-content; box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.5); border-radius: 8px; overflow: hidden; @@ -63,7 +63,7 @@ limitations under the License. &.mx_Toast_icon_verification::after { mask-image: url("$(res)/img/e2e/normal.svg"); - background-color: $primary-fg-color; + background-color: $primary-content; } &.mx_Toast_icon_verification_warning { @@ -82,7 +82,7 @@ limitations under the License. &.mx_Toast_icon_secure_backup::after { mask-image: url('$(res)/img/feather-customised/secure-backup.svg'); - background-color: $primary-fg-color; + background-color: $primary-content; } .mx_Toast_title, .mx_Toast_body { @@ -163,7 +163,7 @@ limitations under the License. } .mx_Toast_detail { - color: $secondary-fg-color; + color: $secondary-content; } .mx_Toast_deviceID { diff --git a/res/css/structures/_UserMenu.scss b/res/css/structures/_UserMenu.scss index 17e6ad75df..c10e7f60df 100644 --- a/res/css/structures/_UserMenu.scss +++ b/res/css/structures/_UserMenu.scss @@ -35,7 +35,7 @@ limitations under the License. // we cheat opacity on the theme colour with an after selector here &::after { content: ''; - border-bottom: 1px solid $primary-fg-color; // XXX: Variable abuse + border-bottom: 1px solid $primary-content; opacity: 0.2; display: block; padding-top: 8px; @@ -58,7 +58,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $tertiary-fg-color; + background: $tertiary-content; mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); } } @@ -176,7 +176,7 @@ limitations under the License. width: 85%; opacity: 0.2; border: none; - border-bottom: 1px solid $primary-fg-color; // XXX: Variable abuse + border-bottom: 1px solid $primary-content; } &.mx_IconizedContextMenu { @@ -292,7 +292,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $primary-fg-color; + background: $primary-content; } } diff --git a/res/css/structures/_ViewSource.scss b/res/css/structures/_ViewSource.scss index 248eab5d88..e3d6135ef3 100644 --- a/res/css/structures/_ViewSource.scss +++ b/res/css/structures/_ViewSource.scss @@ -24,7 +24,7 @@ limitations under the License. .mx_ViewSource_heading { font-size: $font-17px; font-weight: 400; - color: $primary-fg-color; + color: $primary-content; margin-top: 0.7em; } diff --git a/res/css/views/audio_messages/_AudioPlayer.scss b/res/css/views/audio_messages/_AudioPlayer.scss index 77dcebbb9a..3c2551e36a 100644 --- a/res/css/views/audio_messages/_AudioPlayer.scss +++ b/res/css/views/audio_messages/_AudioPlayer.scss @@ -33,7 +33,7 @@ limitations under the License. } .mx_AudioPlayer_mediaName { - color: $primary-fg-color; + color: $primary-content; font-size: $font-15px; line-height: $font-15px; text-overflow: ellipsis; diff --git a/res/css/views/audio_messages/_SeekBar.scss b/res/css/views/audio_messages/_SeekBar.scss index d13fe4ac6a..03449d009b 100644 --- a/res/css/views/audio_messages/_SeekBar.scss +++ b/res/css/views/audio_messages/_SeekBar.scss @@ -27,7 +27,7 @@ limitations under the License. width: 100%; height: 1px; - background: $quaternary-fg-color; + background: $quaternary-content; outline: none; // remove blue selection border position: relative; // for before+after pseudo elements later on @@ -42,7 +42,7 @@ limitations under the License. width: 8px; height: 8px; border-radius: 8px; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; cursor: pointer; } @@ -50,7 +50,7 @@ limitations under the License. width: 8px; height: 8px; border-radius: 8px; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; cursor: pointer; // Firefox adds a border on the thumb @@ -63,7 +63,7 @@ limitations under the License. // in firefox, so it's just wasted CPU/GPU time. &::before { // ::before to ensure it ends up under the thumb content: ''; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; // Absolute positioning to ensure it overlaps with the existing bar position: absolute; @@ -81,7 +81,7 @@ limitations under the License. // This is firefox's built-in support for the above, with 100% less hacks. &::-moz-range-progress { - background-color: $tertiary-fg-color; + background-color: $tertiary-content; height: 1px; } diff --git a/res/css/views/auth/_AuthButtons.scss b/res/css/views/auth/_AuthButtons.scss index 8deb0f80ac..3a2ad2adf8 100644 --- a/res/css/views/auth/_AuthButtons.scss +++ b/res/css/views/auth/_AuthButtons.scss @@ -39,7 +39,7 @@ limitations under the License. min-width: 80px; background-color: $accent-color; - color: $primary-bg-color; + color: $background; cursor: pointer; 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/avatars/_DecoratedRoomAvatar.scss b/res/css/views/avatars/_DecoratedRoomAvatar.scss index 257b512579..4922068462 100644 --- a/res/css/views/avatars/_DecoratedRoomAvatar.scss +++ b/res/css/views/avatars/_DecoratedRoomAvatar.scss @@ -47,7 +47,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $secondary-fg-color; + background: $secondary-content; mask-image: url('$(res)/img/globe.svg'); } diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss index 2af4e79ecd..ff6910852c 100644 --- a/res/css/views/beta/_BetaCard.scss +++ b/res/css/views/beta/_BetaCard.scss @@ -29,7 +29,7 @@ limitations under the License. font-weight: $font-semi-bold; font-size: $font-18px; line-height: $font-22px; - color: $primary-fg-color; + color: $primary-content; margin: 4px 0 14px; .mx_BetaCard_betaPill { @@ -40,7 +40,7 @@ limitations under the License. .mx_BetaCard_caption { font-size: $font-15px; line-height: $font-20px; - color: $secondary-fg-color; + color: $secondary-content; margin-bottom: 20px; } @@ -54,7 +54,7 @@ limitations under the License. .mx_BetaCard_disclaimer { font-size: $font-12px; line-height: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; margin-top: 20px; } } @@ -72,13 +72,13 @@ limitations under the License. margin: 16px 0 0; font-size: $font-15px; line-height: $font-24px; - color: $primary-fg-color; + color: $primary-content; .mx_SettingsFlag_microcopy { margin-top: 4px; font-size: $font-12px; line-height: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; } } } diff --git a/res/css/views/context_menus/_IconizedContextMenu.scss b/res/css/views/context_menus/_IconizedContextMenu.scss index ff176eef7e..ca40f18cd4 100644 --- a/res/css/views/context_menus/_IconizedContextMenu.scss +++ b/res/css/views/context_menus/_IconizedContextMenu.scss @@ -36,7 +36,7 @@ limitations under the License. // // Therefore, we just hack in a line and border the thing ourselves &::before { - border-top: 1px solid $primary-fg-color; + border-top: 1px solid $primary-content; opacity: 0.1; content: ''; @@ -63,7 +63,7 @@ limitations under the License. padding-top: 12px; padding-bottom: 12px; text-decoration: none; - color: $primary-fg-color; + color: $primary-content; font-size: $font-15px; line-height: $font-24px; @@ -119,7 +119,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $primary-fg-color; + background: $primary-content; } } diff --git a/res/css/views/context_menus/_MessageContextMenu.scss b/res/css/views/context_menus/_MessageContextMenu.scss index 338841cce4..5af748e28d 100644 --- a/res/css/views/context_menus/_MessageContextMenu.scss +++ b/res/css/views/context_menus/_MessageContextMenu.scss @@ -30,7 +30,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $primary-fg-color; + background: $primary-content; } } diff --git a/res/css/views/context_menus/_StatusMessageContextMenu.scss b/res/css/views/context_menus/_StatusMessageContextMenu.scss index fceb7fba34..1a97fb56c7 100644 --- a/res/css/views/context_menus/_StatusMessageContextMenu.scss +++ b/res/css/views/context_menus/_StatusMessageContextMenu.scss @@ -27,7 +27,7 @@ input.mx_StatusMessageContextMenu_message { border-radius: 4px; border: 1px solid $input-border-color; padding: 6.5px 11px; - background-color: $primary-bg-color; + background-color: $background; font-weight: normal; margin: 0 0 10px; } diff --git a/res/css/views/context_menus/_TagTileContextMenu.scss b/res/css/views/context_menus/_TagTileContextMenu.scss index d707f4ce7c..14f5ec817e 100644 --- a/res/css/views/context_menus/_TagTileContextMenu.scss +++ b/res/css/views/context_menus/_TagTileContextMenu.scss @@ -51,6 +51,10 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/hide.svg'); } +.mx_TagTileContextMenu_createSpace::before { + mask-image: url('$(res)/img/element-icons/message/fwd.svg'); +} + .mx_TagTileContextMenu_separator { margin-top: 0; margin-bottom: 0; diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss index 42e17c8d98..444b29c9bf 100644 --- a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss @@ -44,7 +44,7 @@ limitations under the License. > h3 { margin: 0; - color: $secondary-fg-color; + color: $secondary-content; font-size: $font-12px; font-weight: $font-semi-bold; line-height: $font-15px; @@ -66,7 +66,7 @@ limitations under the License. flex-grow: 1; font-size: $font-12px; line-height: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; .mx_ProgressBar { height: 8px; @@ -79,7 +79,7 @@ limitations under the License. margin-top: 8px; font-size: $font-15px; line-height: $font-24px; - color: $primary-fg-color; + color: $primary-content; } > * { @@ -105,7 +105,7 @@ limitations under the License. margin-top: 4px; font-size: $font-12px; line-height: $font-15px; - color: $primary-fg-color; + color: $primary-content; } } @@ -126,7 +126,7 @@ limitations under the License. &::before { content: ''; position: absolute; - background-color: $primary-fg-color; + background-color: $primary-content; mask-repeat: no-repeat; mask-position: center; mask-size: contain; @@ -145,7 +145,7 @@ limitations under the License. .mx_AddExistingToSpaceDialog { width: 480px; - color: $primary-fg-color; + color: $primary-content; display: flex; flex-direction: column; flex-wrap: nowrap; @@ -188,7 +188,7 @@ limitations under the License. padding-left: 0; flex: unset; height: unset; - color: $secondary-fg-color; + color: $secondary-content; font-size: $font-15px; line-height: $font-24px; @@ -221,7 +221,7 @@ limitations under the License. } .mx_SubspaceSelector_onlySpace { - color: $secondary-fg-color; + color: $secondary-content; font-size: $font-15px; line-height: $font-24px; } diff --git a/res/css/views/dialogs/_CommunityPrototypeInviteDialog.scss b/res/css/views/dialogs/_CommunityPrototypeInviteDialog.scss index beae03f00f..5d6c817b14 100644 --- a/res/css/views/dialogs/_CommunityPrototypeInviteDialog.scss +++ b/res/css/views/dialogs/_CommunityPrototypeInviteDialog.scss @@ -65,7 +65,7 @@ limitations under the License. .mx_CommunityPrototypeInviteDialog_personName { font-weight: 600; font-size: $font-14px; - color: $primary-fg-color; + color: $primary-content; margin-left: 7px; } diff --git a/res/css/views/dialogs/_ConfirmUserActionDialog.scss b/res/css/views/dialogs/_ConfirmUserActionDialog.scss index 284c171f4e..5ac0f07b14 100644 --- a/res/css/views/dialogs/_ConfirmUserActionDialog.scss +++ b/res/css/views/dialogs/_ConfirmUserActionDialog.scss @@ -35,8 +35,8 @@ limitations under the License. .mx_ConfirmUserActionDialog_reasonField { font-size: $font-14px; - color: $primary-fg-color; - background-color: $primary-bg-color; + color: $primary-content; + background-color: $background; border-radius: 3px; border: solid 1px $input-border-color; diff --git a/res/css/views/dialogs/_CreateGroupDialog.scss b/res/css/views/dialogs/_CreateGroupDialog.scss index f7bfc61a98..ef9c2b73d4 100644 --- a/res/css/views/dialogs/_CreateGroupDialog.scss +++ b/res/css/views/dialogs/_CreateGroupDialog.scss @@ -29,8 +29,8 @@ limitations under the License. border-radius: 3px; border: 1px solid $input-border-color; padding: 9px; - color: $primary-fg-color; - background-color: $primary-bg-color; + color: $primary-content; + background-color: $background; } .mx_CreateGroupDialog_input_hasPrefixAndSuffix { diff --git a/res/css/views/dialogs/_CreateRoomDialog.scss b/res/css/views/dialogs/_CreateRoomDialog.scss index e7cfbf6050..9cfa8ce25a 100644 --- a/res/css/views/dialogs/_CreateRoomDialog.scss +++ b/res/css/views/dialogs/_CreateRoomDialog.scss @@ -55,8 +55,8 @@ limitations under the License. border-radius: 3px; border: 1px solid $input-border-color; padding: 9px; - color: $primary-fg-color; - background-color: $primary-bg-color; + color: $primary-content; + background-color: $background; width: 100%; } diff --git a/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss b/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss new file mode 100644 index 0000000000..6ff328f6ab --- /dev/null +++ b/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss @@ -0,0 +1,187 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_CreateSpaceFromCommunityDialog_wrapper { + .mx_Dialog { + display: flex; + flex-direction: column; + } +} + +.mx_CreateSpaceFromCommunityDialog { + width: 480px; + color: $primary-content; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + min-height: 0; + + .mx_CreateSpaceFromCommunityDialog_content { + > p { + font-size: $font-15px; + line-height: $font-24px; + + &:first-of-type { + margin-top: 0; + } + + &.mx_CreateSpaceFromCommunityDialog_flairNotice { + font-size: $font-12px; + line-height: $font-15px; + } + } + + .mx_SpaceBasicSettings { + > p { + font-size: $font-12px; + line-height: $font-15px; + margin: 16px 0; + } + + .mx_Field_textarea { + margin-bottom: 0; + } + } + + .mx_JoinRuleDropdown .mx_Dropdown_menu { + width: auto !important; // override fixed width + } + + .mx_CreateSpaceFromCommunityDialog_nonPublicSpacer { + height: 63px; // balance the height of the missing room alias field to prevent modal bouncing + } + } + + .mx_CreateSpaceFromCommunityDialog_footer { + display: flex; + margin-top: 20px; + + > span { + flex-grow: 1; + font-size: $font-12px; + line-height: $font-15px; + color: $secondary-content; + + .mx_ProgressBar { + height: 8px; + width: 100%; + + @mixin ProgressBarBorderRadius 8px; + } + + .mx_CreateSpaceFromCommunityDialog_progressText { + margin-top: 8px; + font-size: $font-15px; + line-height: $font-24px; + color: $primary-content; + } + + > * { + vertical-align: middle; + } + } + + .mx_CreateSpaceFromCommunityDialog_error { + padding-left: 12px; + + > img { + align-self: center; + } + + .mx_CreateSpaceFromCommunityDialog_errorHeading { + font-weight: $font-semi-bold; + font-size: $font-15px; + line-height: $font-18px; + color: $notice-primary-color; + } + + .mx_CreateSpaceFromCommunityDialog_errorCaption { + margin-top: 4px; + font-size: $font-12px; + line-height: $font-15px; + color: $primary-content; + } + } + + .mx_AccessibleButton { + display: inline-block; + align-self: center; + } + + .mx_AccessibleButton_kind_primary { + padding: 8px 36px; + margin-left: 24px; + } + + .mx_AccessibleButton_kind_primary_outline { + margin-left: auto; + } + + .mx_CreateSpaceFromCommunityDialog_retryButton { + margin-left: 12px; + padding-left: 24px; + position: relative; + + &::before { + content: ''; + position: absolute; + background-color: $primary-content; + 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 { + padding: 0; + } + } +} + +.mx_CreateSpaceFromCommunityDialog_SuccessInfoDialog { + .mx_InfoDialog { + max-width: 500px; + } + + .mx_AccessibleButton_kind_link { + padding: 0; + } + + .mx_CreateSpaceFromCommunityDialog_SuccessInfoDialog_checkmark { + position: relative; + border-radius: 50%; + border: 3px solid $accent-color; + width: 68px; + height: 68px; + margin: 12px auto 32px; + + &::before { + width: inherit; + height: inherit; + content: ''; + position: absolute; + background-color: $accent-color; + mask-repeat: no-repeat; + mask-position: center; + mask-image: url('$(res)/img/element-icons/roomlist/checkmark.svg'); + mask-size: 48px; + } + } +} diff --git a/res/css/views/dialogs/_CreateSubspaceDialog.scss b/res/css/views/dialogs/_CreateSubspaceDialog.scss index 1ec4731ae6..1ed10df35c 100644 --- a/res/css/views/dialogs/_CreateSubspaceDialog.scss +++ b/res/css/views/dialogs/_CreateSubspaceDialog.scss @@ -23,7 +23,7 @@ limitations under the License. .mx_CreateSubspaceDialog { width: 480px; - color: $primary-fg-color; + color: $primary-content; display: flex; flex-direction: column; flex-wrap: nowrap; @@ -57,7 +57,7 @@ limitations under the License. flex-grow: 1; font-size: $font-12px; line-height: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; > * { vertical-align: middle; diff --git a/res/css/views/dialogs/_FeedbackDialog.scss b/res/css/views/dialogs/_FeedbackDialog.scss index fd225dd882..74733f7220 100644 --- a/res/css/views/dialogs/_FeedbackDialog.scss +++ b/res/css/views/dialogs/_FeedbackDialog.scss @@ -33,7 +33,7 @@ limitations under the License. padding-left: 52px; > p { - color: $tertiary-fg-color; + color: $tertiary-content; } .mx_AccessibleButton_kind_link { diff --git a/res/css/views/dialogs/_ForwardDialog.scss b/res/css/views/dialogs/_ForwardDialog.scss index e018f60172..da8ce3de5b 100644 --- a/res/css/views/dialogs/_ForwardDialog.scss +++ b/res/css/views/dialogs/_ForwardDialog.scss @@ -16,7 +16,7 @@ limitations under the License. .mx_ForwardDialog { width: 520px; - color: $primary-fg-color; + color: $primary-content; display: flex; flex-direction: column; flex-wrap: nowrap; @@ -25,7 +25,7 @@ limitations under the License. > h3 { margin: 0 0 6px; - color: $secondary-fg-color; + color: $secondary-content; font-size: $font-12px; font-weight: $font-semi-bold; line-height: $font-15px; diff --git a/res/css/views/dialogs/_GenericFeatureFeedbackDialog.scss b/res/css/views/dialogs/_GenericFeatureFeedbackDialog.scss index f83eed9c53..ab7496249d 100644 --- a/res/css/views/dialogs/_GenericFeatureFeedbackDialog.scss +++ b/res/css/views/dialogs/_GenericFeatureFeedbackDialog.scss @@ -16,7 +16,7 @@ limitations under the License. .mx_GenericFeatureFeedbackDialog { .mx_GenericFeatureFeedbackDialog_subheading { - color: $primary-fg-color; + color: $primary-content; font-size: $font-14px; line-height: $font-20px; margin-bottom: 24px; diff --git a/res/css/views/dialogs/_HostSignupDialog.scss b/res/css/views/dialogs/_HostSignupDialog.scss index ac4bc41951..d8a6652a39 100644 --- a/res/css/views/dialogs/_HostSignupDialog.scss +++ b/res/css/views/dialogs/_HostSignupDialog.scss @@ -70,11 +70,11 @@ limitations under the License. } .mx_HostSignupDialog_text_dark { - color: $primary-fg-color; + color: $primary-content; } .mx_HostSignupDialog_text_light { - color: $secondary-fg-color; + color: $secondary-content; } .mx_HostSignup_maximize_button { diff --git a/res/css/views/dialogs/_InviteDialog.scss b/res/css/views/dialogs/_InviteDialog.scss index 9fc4b7a15c..3a2918f9ec 100644 --- a/res/css/views/dialogs/_InviteDialog.scss +++ b/res/css/views/dialogs/_InviteDialog.scss @@ -56,7 +56,7 @@ limitations under the License. box-sizing: border-box; min-width: 40%; flex: 1 !important; - color: $primary-fg-color !important; + color: $primary-content !important; } } @@ -94,7 +94,7 @@ limitations under the License. } > span { - color: $primary-fg-color; + color: $primary-content; } .mx_InviteDialog_subname { @@ -110,7 +110,7 @@ limitations under the License. font-size: $font-14px; > span { - color: $primary-fg-color; + color: $primary-content; font-weight: 600; } @@ -220,7 +220,7 @@ limitations under the License. .mx_InviteDialog_roomTile_name { font-weight: 600; font-size: $font-14px; - color: $primary-fg-color; + color: $primary-content; margin-left: 7px; } @@ -352,7 +352,7 @@ limitations under the License. border-right: 0; border-radius: 0; margin-top: 0; - border-color: $quaternary-fg-color; + border-color: $quaternary-content; input { font-size: 18px; @@ -418,7 +418,7 @@ limitations under the License. > h4 { font-size: $font-15px; line-height: $font-24px; - color: $secondary-fg-color; + color: $secondary-content; font-weight: normal; } @@ -432,14 +432,14 @@ limitations under the License. font-size: $font-15px; line-height: $font-24px; font-weight: $font-semi-bold; - color: $primary-fg-color; + color: $primary-content; } .mx_InviteDialog_multiInviterError_entry_userId { margin-left: 6px; font-size: $font-12px; line-height: $font-15px; - color: $tertiary-fg-color; + color: $tertiary-content; } } diff --git a/res/css/views/dialogs/_JoinRuleDropdown.scss b/res/css/views/dialogs/_JoinRuleDropdown.scss index c48a79af3c..91691cf53b 100644 --- a/res/css/views/dialogs/_JoinRuleDropdown.scss +++ b/res/css/views/dialogs/_JoinRuleDropdown.scss @@ -19,7 +19,7 @@ limitations under the License. font-weight: normal; font-family: $font-family; font-size: $font-14px; - color: $primary-fg-color; + color: $primary-content; .mx_Dropdown_input { border: 1px solid $input-border-color; @@ -44,7 +44,7 @@ limitations under the License. top: 8px; mask-repeat: no-repeat; mask-position: center; - background-color: $secondary-fg-color; + background-color: $secondary-content; } } } diff --git a/res/css/views/dialogs/_LeaveSpaceDialog.scss b/res/css/views/dialogs/_LeaveSpaceDialog.scss index c982f50e52..0d85a87faf 100644 --- a/res/css/views/dialogs/_LeaveSpaceDialog.scss +++ b/res/css/views/dialogs/_LeaveSpaceDialog.scss @@ -63,7 +63,7 @@ limitations under the License. font-size: $font-12px; line-height: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; &::before { content: ''; @@ -72,7 +72,7 @@ limitations under the License. top: calc(50% - 8px); // vertical centering height: 16px; width: 16px; - background-color: $secondary-fg-color; + background-color: $secondary-content; mask-repeat: no-repeat; mask-size: contain; mask-image: url('$(res)/img/element-icons/room/room-summary.svg'); @@ -81,7 +81,7 @@ limitations under the License. } > p { - color: $primary-fg-color; + color: $primary-content; } } diff --git a/res/css/views/dialogs/_ManageRestrictedJoinRuleDialog.scss b/res/css/views/dialogs/_ManageRestrictedJoinRuleDialog.scss index 91df76675a..9a05e7f20a 100644 --- a/res/css/views/dialogs/_ManageRestrictedJoinRuleDialog.scss +++ b/res/css/views/dialogs/_ManageRestrictedJoinRuleDialog.scss @@ -23,7 +23,7 @@ limitations under the License. .mx_ManageRestrictedJoinRuleDialog { width: 480px; - color: $primary-fg-color; + color: $primary-content; display: flex; flex-direction: column; flex-wrap: nowrap; @@ -52,7 +52,7 @@ limitations under the License. > h3 { margin: 0; - color: $secondary-fg-color; + color: $secondary-content; font-size: $font-12px; font-weight: $font-semi-bold; line-height: $font-15px; @@ -85,7 +85,7 @@ limitations under the License. margin-top: 8px; font-size: $font-12px; line-height: $font-15px; - color: $tertiary-fg-color; + color: $tertiary-content; } .mx_Checkbox { @@ -113,7 +113,7 @@ limitations under the License. font-size: $font-12px; line-height: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; &::before { content: ''; @@ -122,7 +122,7 @@ limitations under the License. top: calc(50% - 8px); // vertical centering height: 16px; width: 16px; - background-color: $secondary-fg-color; + background-color: $secondary-content; mask-repeat: no-repeat; mask-size: contain; mask-image: url('$(res)/img/element-icons/room/room-summary.svg'); diff --git a/res/css/views/dialogs/_MessageEditHistoryDialog.scss b/res/css/views/dialogs/_MessageEditHistoryDialog.scss index e9d777effd..4574344a28 100644 --- a/res/css/views/dialogs/_MessageEditHistoryDialog.scss +++ b/res/css/views/dialogs/_MessageEditHistoryDialog.scss @@ -37,7 +37,7 @@ limitations under the License. list-style-type: none; font-size: $font-14px; padding: 0; - color: $primary-fg-color; + color: $primary-content; span.mx_EditHistoryMessage_deletion, span.mx_EditHistoryMessage_insertion { padding: 0px 2px; diff --git a/res/css/views/dialogs/_RegistrationEmailPromptDialog.scss b/res/css/views/dialogs/_RegistrationEmailPromptDialog.scss index 31fc6d7a04..02c89e2e42 100644 --- a/res/css/views/dialogs/_RegistrationEmailPromptDialog.scss +++ b/res/css/views/dialogs/_RegistrationEmailPromptDialog.scss @@ -19,7 +19,7 @@ limitations under the License. .mx_Dialog_content { margin-bottom: 24px; - color: $tertiary-fg-color; + color: $tertiary-content; } .mx_Dialog_primary { diff --git a/res/css/views/dialogs/_RoomSettingsDialogBridges.scss b/res/css/views/dialogs/_RoomSettingsDialogBridges.scss index c97a3b69b7..f18b4917cf 100644 --- a/res/css/views/dialogs/_RoomSettingsDialogBridges.scss +++ b/res/css/views/dialogs/_RoomSettingsDialogBridges.scss @@ -72,7 +72,7 @@ limitations under the License. margin-top: 0px; margin-bottom: 0px; font-size: 16pt; - color: $primary-fg-color; + color: $primary-content; } > * { @@ -81,7 +81,7 @@ limitations under the License. } .workspace-channel-details { - color: $primary-fg-color; + color: $primary-content; font-weight: 600; .channel { diff --git a/res/css/views/dialogs/_ServerOfflineDialog.scss b/res/css/views/dialogs/_ServerOfflineDialog.scss index ae4b70beb3..7a1b0bbcab 100644 --- a/res/css/views/dialogs/_ServerOfflineDialog.scss +++ b/res/css/views/dialogs/_ServerOfflineDialog.scss @@ -17,10 +17,10 @@ limitations under the License. .mx_ServerOfflineDialog { .mx_ServerOfflineDialog_content { padding-right: 85px; - color: $primary-fg-color; + color: $primary-content; hr { - border-color: $primary-fg-color; + border-color: $primary-content; opacity: 0.1; border-bottom: none; } diff --git a/res/css/views/dialogs/_ServerPickerDialog.scss b/res/css/views/dialogs/_ServerPickerDialog.scss index b01b49d7af..9a05751f91 100644 --- a/res/css/views/dialogs/_ServerPickerDialog.scss +++ b/res/css/views/dialogs/_ServerPickerDialog.scss @@ -22,7 +22,7 @@ limitations under the License. margin-bottom: 0; > p { - color: $secondary-fg-color; + color: $secondary-content; font-size: $font-14px; margin: 16px 0; @@ -38,7 +38,7 @@ limitations under the License. > h4 { font-size: $font-15px; font-weight: $font-semi-bold; - color: $secondary-fg-color; + color: $secondary-content; margin-left: 8px; } diff --git a/res/css/views/dialogs/_SetEmailDialog.scss b/res/css/views/dialogs/_SetEmailDialog.scss index 37bee7a9ff..a39d51dfce 100644 --- a/res/css/views/dialogs/_SetEmailDialog.scss +++ b/res/css/views/dialogs/_SetEmailDialog.scss @@ -19,7 +19,7 @@ limitations under the License. border: 1px solid $input-border-color; padding: 9px; color: $input-fg-color; - background-color: $primary-bg-color; + background-color: $background; font-size: $font-15px; width: 100%; max-width: 280px; diff --git a/res/css/views/dialogs/_SpaceSettingsDialog.scss b/res/css/views/dialogs/_SpaceSettingsDialog.scss index fa074fdbe8..a1fa9d52a8 100644 --- a/res/css/views/dialogs/_SpaceSettingsDialog.scss +++ b/res/css/views/dialogs/_SpaceSettingsDialog.scss @@ -15,7 +15,7 @@ limitations under the License. */ .mx_SpaceSettingsDialog { - color: $primary-fg-color; + color: $primary-content; .mx_SpaceSettings_errorText { font-weight: $font-semi-bold; @@ -50,13 +50,13 @@ limitations under the License. .mx_RadioButton_content { font-weight: $font-semi-bold; line-height: $font-18px; - color: $primary-fg-color; + color: $primary-content; } & + span { font-size: $font-15px; line-height: $font-18px; - color: $secondary-fg-color; + color: $secondary-content; margin-left: 26px; } } diff --git a/res/css/views/dialogs/security/_AccessSecretStorageDialog.scss b/res/css/views/dialogs/security/_AccessSecretStorageDialog.scss index ec3bea0ef7..98edbf8ad8 100644 --- a/res/css/views/dialogs/security/_AccessSecretStorageDialog.scss +++ b/res/css/views/dialogs/security/_AccessSecretStorageDialog.scss @@ -44,7 +44,7 @@ limitations under the License. margin-right: 8px; position: relative; top: 5px; - background-color: $primary-fg-color; + background-color: $primary-content; } .mx_AccessSecretStorageDialog_resetBadge::before { diff --git a/res/css/views/dialogs/security/_CreateSecretStorageDialog.scss b/res/css/views/dialogs/security/_CreateSecretStorageDialog.scss index d30803b1f0..b14206ff6d 100644 --- a/res/css/views/dialogs/security/_CreateSecretStorageDialog.scss +++ b/res/css/views/dialogs/security/_CreateSecretStorageDialog.scss @@ -56,7 +56,7 @@ limitations under the License. margin-right: 8px; position: relative; top: 5px; - background-color: $primary-fg-color; + background-color: $primary-content; } .mx_CreateSecretStorageDialog_secureBackupTitle::before { @@ -101,7 +101,7 @@ limitations under the License. margin-right: 8px; position: relative; top: 5px; - background-color: $primary-fg-color; + background-color: $primary-content; } .mx_CreateSecretStorageDialog_optionIcon_securePhrase { diff --git a/res/css/views/dialogs/security/_KeyBackupFailedDialog.scss b/res/css/views/dialogs/security/_KeyBackupFailedDialog.scss index 05ce158413..4a48012672 100644 --- a/res/css/views/dialogs/security/_KeyBackupFailedDialog.scss +++ b/res/css/views/dialogs/security/_KeyBackupFailedDialog.scss @@ -26,7 +26,7 @@ limitations under the License. &::before { mask: url("$(res)/img/e2e/lock-warning-filled.svg"); mask-repeat: no-repeat; - background-color: $primary-fg-color; + background-color: $primary-content; content: ""; position: absolute; top: -6px; diff --git a/res/css/views/directory/_NetworkDropdown.scss b/res/css/views/directory/_NetworkDropdown.scss index ae0927386a..93cecd8676 100644 --- a/res/css/views/directory/_NetworkDropdown.scss +++ b/res/css/views/directory/_NetworkDropdown.scss @@ -34,7 +34,7 @@ limitations under the License. box-sizing: border-box; border-radius: 4px; border: 1px solid $dialog-close-fg-color; - background-color: $primary-bg-color; + background-color: $background; max-height: calc(100vh - 20px); // allow 10px padding on both top and bottom overflow-y: auto; } @@ -153,7 +153,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-image: url('$(res)/img/feather-customised/chevron-down-thin.svg'); - background-color: $primary-fg-color; + background-color: $primary-content; } .mx_NetworkDropdown_handle_server { diff --git a/res/css/views/elements/_AddressSelector.scss b/res/css/views/elements/_AddressSelector.scss index 087504390c..a7d463353b 100644 --- a/res/css/views/elements/_AddressSelector.scss +++ b/res/css/views/elements/_AddressSelector.scss @@ -16,7 +16,7 @@ limitations under the License. .mx_AddressSelector { position: absolute; - background-color: $primary-bg-color; + background-color: $background; width: 485px; max-height: 116px; overflow-y: auto; @@ -31,8 +31,8 @@ limitations under the License. } .mx_AddressSelector_addressListElement .mx_AddressTile { - background-color: $primary-bg-color; - border: solid 1px $primary-bg-color; + background-color: $background; + border: solid 1px $background; } .mx_AddressSelector_addressListElement.mx_AddressSelector_selected { diff --git a/res/css/views/elements/_AddressTile.scss b/res/css/views/elements/_AddressTile.scss index c42f52f8f4..90c40842f7 100644 --- a/res/css/views/elements/_AddressTile.scss +++ b/res/css/views/elements/_AddressTile.scss @@ -20,7 +20,7 @@ limitations under the License. background-color: rgba(74, 73, 74, 0.1); border: solid 1px $input-border-color; line-height: $font-26px; - color: $primary-fg-color; + color: $primary-content; font-size: $font-14px; font-weight: normal; margin-right: 4px; diff --git a/res/css/views/elements/_DesktopCapturerSourcePicker.scss b/res/css/views/elements/_DesktopCapturerSourcePicker.scss index 49a0a44417..b4a2c69b86 100644 --- a/res/css/views/elements/_DesktopCapturerSourcePicker.scss +++ b/res/css/views/elements/_DesktopCapturerSourcePicker.scss @@ -24,35 +24,33 @@ limitations under the License. align-items: flex-start; height: 500px; overflow: overlay; - } - .mx_desktopCapturerSourcePicker_source { - display: flex; - flex-direction: column; - margin: 8px; - } + .mx_desktopCapturerSourcePicker_source { + width: 50%; + display: flex; + flex-direction: column; - .mx_desktopCapturerSourcePicker_source_thumbnail { - margin: 4px; - padding: 4px; - width: 312px; - border-width: 2px; - border-radius: 8px; - border-style: solid; - border-color: transparent; + .mx_desktopCapturerSourcePicker_source_thumbnail { + margin: 4px; + padding: 4px; + border-width: 2px; + border-radius: 8px; + border-style: solid; + border-color: transparent; - &.mx_desktopCapturerSourcePicker_source_thumbnail_selected, - &:hover, - &:focus { - border-color: $accent-color; + &.mx_desktopCapturerSourcePicker_source_thumbnail_selected, + &:hover, + &:focus { + border-color: $accent-color; + } + } + + .mx_desktopCapturerSourcePicker_source_name { + margin: 0 4px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } } } - - .mx_desktopCapturerSourcePicker_source_name { - margin: 0 4px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - width: 312px; - } } diff --git a/res/css/views/elements/_Dropdown.scss b/res/css/views/elements/_Dropdown.scss index 3b67e0191e..1acac70e42 100644 --- a/res/css/views/elements/_Dropdown.scss +++ b/res/css/views/elements/_Dropdown.scss @@ -16,7 +16,7 @@ limitations under the License. .mx_Dropdown { position: relative; - color: $primary-fg-color; + color: $primary-content; } .mx_Dropdown_disabled { @@ -52,7 +52,7 @@ limitations under the License. padding-right: 9px; mask: url('$(res)/img/feather-customised/dropdown-arrow.svg'); mask-repeat: no-repeat; - background: $primary-fg-color; + background: $primary-content; } .mx_Dropdown_option { @@ -111,7 +111,7 @@ input.mx_Dropdown_option:focus { padding: 0px; border-radius: 4px; border: 1px solid $input-focused-border-color; - background-color: $primary-bg-color; + background-color: $background; max-height: 200px; overflow-y: auto; } diff --git a/res/css/views/elements/_FacePile.scss b/res/css/views/elements/_FacePile.scss index c691baffb5..875e0e34d5 100644 --- a/res/css/views/elements/_FacePile.scss +++ b/res/css/views/elements/_FacePile.scss @@ -25,7 +25,7 @@ limitations under the License. } .mx_BaseAvatar_image { - border: 1px solid $primary-bg-color; + border: 1px solid $background; } .mx_BaseAvatar_initial { @@ -47,7 +47,7 @@ limitations under the License. left: 0; height: inherit; width: inherit; - background: $tertiary-fg-color; + background: $tertiary-content; mask-position: center; mask-size: 20px; mask-repeat: no-repeat; @@ -60,6 +60,6 @@ limitations under the License. margin-left: 12px; font-size: $font-14px; line-height: $font-24px; - color: $tertiary-fg-color; + color: $tertiary-content; } } diff --git a/res/css/views/elements/_Field.scss b/res/css/views/elements/_Field.scss index cae81dcc97..d74c985d4c 100644 --- a/res/css/views/elements/_Field.scss +++ b/res/css/views/elements/_Field.scss @@ -38,6 +38,7 @@ limitations under the License. .mx_Field input, .mx_Field select, .mx_Field textarea { + font-family: inherit; font-weight: normal; font-size: $font-14px; border: none; @@ -45,8 +46,8 @@ limitations under the License. // corners on the field above. border-radius: 4px; padding: 8px 9px; - color: $primary-fg-color; - background-color: $primary-bg-color; + color: $primary-content; + background-color: $background; flex: 1; min-width: 0; } @@ -66,7 +67,7 @@ limitations under the License. height: 6px; mask: url('$(res)/img/feather-customised/dropdown-arrow.svg'); mask-repeat: no-repeat; - background-color: $primary-fg-color; + background-color: $primary-content; z-index: 1; pointer-events: none; } @@ -99,7 +100,7 @@ limitations under the License. color 0.25s ease-out 0.1s, top 0.25s ease-out 0.1s, background-color 0.25s ease-out 0.1s; - color: $primary-fg-color; + color: $primary-content; background-color: transparent; font-size: $font-14px; position: absolute; diff --git a/res/css/views/elements/_InviteReason.scss b/res/css/views/elements/_InviteReason.scss index 2c2e5687e6..8024ed59a3 100644 --- a/res/css/views/elements/_InviteReason.scss +++ b/res/css/views/elements/_InviteReason.scss @@ -32,12 +32,12 @@ limitations under the License. justify-content: center; align-items: center; cursor: pointer; - color: $secondary-fg-color; + color: $secondary-content; &::before { content: ""; margin-right: 8px; - background-color: $secondary-fg-color; + background-color: $secondary-content; mask-image: url('$(res)/img/feather-customised/eye.svg'); display: inline-block; width: 18px; diff --git a/res/css/views/elements/_MiniAvatarUploader.scss b/res/css/views/elements/_MiniAvatarUploader.scss index df4676ab56..46ffd9a01c 100644 --- a/res/css/views/elements/_MiniAvatarUploader.scss +++ b/res/css/views/elements/_MiniAvatarUploader.scss @@ -37,7 +37,7 @@ limitations under the License. right: -6px; bottom: -6px; - background-color: $primary-bg-color; + background-color: $background; border-radius: 50%; z-index: 1; @@ -45,7 +45,7 @@ limitations under the License. height: 100%; width: 100%; - background-color: $secondary-fg-color; + background-color: $secondary-content; mask-position: center; mask-repeat: no-repeat; mask-image: url('$(res)/img/element-icons/camera.svg'); diff --git a/res/css/views/elements/_RichText.scss b/res/css/views/elements/_RichText.scss index d60282695c..b9d845ea7a 100644 --- a/res/css/views/elements/_RichText.scss +++ b/res/css/views/elements/_RichText.scss @@ -43,7 +43,7 @@ a.mx_Pill { /* More specific to override `.markdown-body a` color */ .mx_EventTile_content .markdown-body a.mx_UserPill, .mx_UserPill { - color: $primary-fg-color; + color: $primary-content; background-color: $other-user-pill-bg-color; } diff --git a/res/css/views/elements/_SSOButtons.scss b/res/css/views/elements/_SSOButtons.scss index e02816780f..a98e7b4024 100644 --- a/res/css/views/elements/_SSOButtons.scss +++ b/res/css/views/elements/_SSOButtons.scss @@ -35,7 +35,7 @@ limitations under the License. font-size: $font-14px; font-weight: $font-semi-bold; border: 1px solid $input-border-color; - color: $primary-fg-color; + color: $primary-content; > img { object-fit: contain; diff --git a/res/css/views/elements/_ServerPicker.scss b/res/css/views/elements/_ServerPicker.scss index 188eb5d655..d828d7cb88 100644 --- a/res/css/views/elements/_ServerPicker.scss +++ b/res/css/views/elements/_ServerPicker.scss @@ -74,7 +74,7 @@ limitations under the License. .mx_ServerPicker_desc { margin-top: -12px; - color: $tertiary-fg-color; + color: $tertiary-content; grid-column: 1 / 2; grid-row: 3; margin-bottom: 16px; diff --git a/res/css/views/elements/_Spinner.scss b/res/css/views/elements/_Spinner.scss index 93d5e2d96c..2df46687af 100644 --- a/res/css/views/elements/_Spinner.scss +++ b/res/css/views/elements/_Spinner.scss @@ -37,7 +37,7 @@ limitations under the License. } .mx_Spinner_icon { - background-color: $primary-fg-color; + background-color: $primary-content; mask: url('$(res)/img/spinner.svg'); mask-size: contain; animation: 1.1s steps(12, end) infinite spin; diff --git a/res/css/views/elements/_TagComposer.scss b/res/css/views/elements/_TagComposer.scss index 2ffd601765..f5bdb8d2d5 100644 --- a/res/css/views/elements/_TagComposer.scss +++ b/res/css/views/elements/_TagComposer.scss @@ -25,7 +25,7 @@ limitations under the License. .mx_AccessibleButton { min-width: 70px; - padding: 0; // override from button styles + padding: 0 8px; // override from button styles margin-left: 16px; // distance from } @@ -50,7 +50,7 @@ limitations under the License. &::before { content: ''; border-radius: 20px; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; opacity: 0.15; position: absolute; top: 0; diff --git a/res/css/views/elements/_Tooltip.scss b/res/css/views/elements/_Tooltip.scss index d90c818f94..6c5a7da55a 100644 --- a/res/css/views/elements/_Tooltip.scss +++ b/res/css/views/elements/_Tooltip.scss @@ -84,7 +84,7 @@ limitations under the License. // These tooltips use an older style with a chevron .mx_Field_tooltip { background-color: $menu-bg-color; - color: $primary-fg-color; + color: $primary-content; border: 1px solid $menu-border-color; text-align: unset; diff --git a/res/css/views/emojipicker/_EmojiPicker.scss b/res/css/views/emojipicker/_EmojiPicker.scss index 400e40e233..91c68158c9 100644 --- a/res/css/views/emojipicker/_EmojiPicker.scss +++ b/res/css/views/emojipicker/_EmojiPicker.scss @@ -57,7 +57,7 @@ limitations under the License. } .mx_EmojiPicker_anchor::before { - background-color: $primary-fg-color; + background-color: $primary-content; content: ''; display: inline-block; mask-size: 100%; @@ -89,7 +89,7 @@ limitations under the License. margin: 8px; border-radius: 4px; border: 1px solid $input-border-color; - background-color: $primary-bg-color; + background-color: $background; display: flex; input { @@ -126,7 +126,7 @@ limitations under the License. .mx_EmojiPicker_search_icon::after { mask: url('$(res)/img/emojipicker/search.svg') no-repeat; mask-size: 100%; - background-color: $primary-fg-color; + background-color: $primary-content; content: ''; display: inline-block; width: 100%; diff --git a/res/css/views/groups/_GroupRoomList.scss b/res/css/views/groups/_GroupRoomList.scss index fefd17849c..2f6559f7c4 100644 --- a/res/css/views/groups/_GroupRoomList.scss +++ b/res/css/views/groups/_GroupRoomList.scss @@ -16,7 +16,7 @@ limitations under the License. .mx_GroupRoomTile { position: relative; - color: $primary-fg-color; + color: $primary-content; cursor: pointer; display: flex; align-items: center; diff --git a/res/css/views/messages/_CallEvent.scss b/res/css/views/messages/_CallEvent.scss index 0c1b41ca38..7934f8f3c2 100644 --- a/res/css/views/messages/_CallEvent.scss +++ b/res/css/views/messages/_CallEvent.scss @@ -14,126 +14,23 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_CallEvent { +.mx_CallEvent_wrapper { display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; + width: 100%; - background-color: $dark-panel-bg-color; - border-radius: 8px; - margin: 10px auto; - width: 75%; - box-sizing: border-box; - height: 60px; - - &.mx_CallEvent_voice { - .mx_CallEvent_type_icon::before, - .mx_CallEvent_content_button_callBack span::before, - .mx_CallEvent_content_button_answer span::before { - mask-image: url('$(res)/img/element-icons/call/voice-call.svg'); - } - } - - &.mx_CallEvent_video { - .mx_CallEvent_type_icon::before, - .mx_CallEvent_content_button_callBack span::before, - .mx_CallEvent_content_button_answer span::before { - mask-image: url('$(res)/img/element-icons/call/video-call.svg'); - } - } - - &.mx_CallEvent_voice.mx_CallEvent_missed .mx_CallEvent_type_icon::before { - mask-image: url('$(res)/img/voip/missed-voice.svg'); - } - - &.mx_CallEvent_video.mx_CallEvent_missed .mx_CallEvent_type_icon::before { - mask-image: url('$(res)/img/voip/missed-video.svg'); - } - - .mx_CallEvent_info { + .mx_CallEvent { + position: relative; display: flex; flex-direction: row; align-items: center; - margin-left: 12px; + justify-content: space-between; - .mx_CallEvent_info_basic { - display: flex; - flex-direction: column; - margin-left: 10px; // To match mx_CallEvent - - .mx_CallEvent_sender { - font-weight: 600; - font-size: 1.5rem; - line-height: 1.8rem; - margin-bottom: 3px; - } - - .mx_CallEvent_type { - font-weight: 400; - color: $secondary-fg-color; - font-size: 1.2rem; - line-height: $font-13px; - display: flex; - align-items: center; - - .mx_CallEvent_type_icon { - height: 13px; - width: 13px; - margin-right: 5px; - - &::before { - content: ''; - position: absolute; - height: 13px; - width: 13px; - background-color: $tertiary-fg-color; - mask-repeat: no-repeat; - mask-size: contain; - } - } - } - } - } - - .mx_CallEvent_content { - display: flex; - flex-direction: row; - align-items: center; - color: $secondary-fg-color; - margin-right: 16px; - - .mx_CallEvent_content_button { - height: 24px; - padding: 0px 12px; - margin-left: 8px; - - span { - padding: 8px 0; - display: flex; - align-items: center; - - &::before { - content: ''; - display: inline-block; - background-color: $button-fg-color; - mask-position: center; - mask-repeat: no-repeat; - mask-size: 16px; - width: 16px; - height: 16px; - margin-right: 8px; - } - } - } - - .mx_CallEvent_content_button_reject span::before { - mask-image: url('$(res)/img/element-icons/call/hangup.svg'); - } - - .mx_CallEvent_content_tooltip { - margin-right: 5px; - } + background-color: $dark-panel-bg-color; + border-radius: 8px; + width: 65%; + box-sizing: border-box; + height: 60px; + margin: 4px 0; .mx_CallEvent_iconButton { display: inline-flex; @@ -144,7 +41,7 @@ limitations under the License. height: 16px; width: 16px; - background-color: $tertiary-fg-color; + background-color: $secondary-content; mask-repeat: no-repeat; mask-size: contain; mask-position: center; @@ -158,5 +55,165 @@ limitations under the License. .mx_CallEvent_unSilence::before { mask-image: url('$(res)/img/voip/un-silence.svg'); } + + &.mx_CallEvent_voice { + .mx_CallEvent_type_icon::before, + .mx_CallEvent_content_button_callBack span::before, + .mx_CallEvent_content_button_answer span::before { + mask-image: url('$(res)/img/element-icons/call/voice-call.svg'); + } + } + + &.mx_CallEvent_video { + .mx_CallEvent_type_icon::before, + .mx_CallEvent_content_button_callBack span::before, + .mx_CallEvent_content_button_answer span::before { + mask-image: url('$(res)/img/element-icons/call/video-call.svg'); + } + } + + &.mx_CallEvent_voice.mx_CallEvent_missed .mx_CallEvent_type_icon::before { + mask-image: url('$(res)/img/voip/missed-voice.svg'); + } + + &.mx_CallEvent_video.mx_CallEvent_missed .mx_CallEvent_type_icon::before { + mask-image: url('$(res)/img/voip/missed-video.svg'); + } + + &.mx_CallEvent_voice.mx_CallEvent_rejected .mx_CallEvent_type_icon::before, + &.mx_CallEvent_voice.mx_CallEvent_noAnswer .mx_CallEvent_type_icon::before { + mask-image: url('$(res)/img/voip/declined-voice.svg'); + } + + &.mx_CallEvent_video.mx_CallEvent_rejected .mx_CallEvent_type_icon::before, + &.mx_CallEvent_video.mx_CallEvent_noAnswer .mx_CallEvent_type_icon::before { + mask-image: url('$(res)/img/voip/declined-video.svg'); + } + + .mx_CallEvent_info { + display: flex; + flex-direction: row; + align-items: center; + margin-left: 12px; + min-width: 0; + + .mx_CallEvent_info_basic { + display: flex; + flex-direction: column; + margin-left: 10px; // To match mx_CallEvent + min-width: 0; + + .mx_CallEvent_sender { + font-weight: 600; + font-size: 1.5rem; + line-height: 1.8rem; + margin-bottom: 3px; + + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .mx_CallEvent_type { + font-weight: 400; + color: $secondary-content; + font-size: 1.2rem; + line-height: $font-13px; + display: flex; + align-items: center; + + .mx_CallEvent_type_icon { + height: 13px; + width: 13px; + margin-right: 5px; + + &::before { + content: ''; + position: absolute; + height: 13px; + width: 13px; + background-color: $secondary-content; + mask-repeat: no-repeat; + mask-size: contain; + } + } + } + } + } + + .mx_CallEvent_content { + display: flex; + flex-direction: row; + align-items: center; + color: $secondary-content; + margin-right: 16px; + gap: 8px; + min-width: max-content; + + .mx_CallEvent_content_button { + padding: 0px 12px; + + span { + padding: 1px 0; + display: flex; + align-items: center; + + &::before { + content: ''; + display: inline-block; + background-color: $button-fg-color; + mask-position: center; + mask-repeat: no-repeat; + mask-size: 16px; + width: 16px; + height: 16px; + margin-right: 8px; + + flex-shrink: 0; + } + } + } + + .mx_CallEvent_content_button_reject span::before { + mask-image: url('$(res)/img/element-icons/call/hangup.svg'); + } + + .mx_CallEvent_content_tooltip { + margin-right: 5px; + } + } + + &.mx_CallEvent_narrow { + height: unset; + width: 290px; + flex-direction: column; + align-items: unset; + gap: 16px; + + .mx_CallEvent_iconButton { + position: absolute; + margin-right: 0; + top: 12px; + right: 12px; + height: 16px; + width: 16px; + display: flex; + } + + .mx_CallEvent_info { + align-items: unset; + margin-top: 12px; + margin-right: 12px; + + .mx_CallEvent_sender { + margin-bottom: 8px; + } + } + + .mx_CallEvent_content { + margin-left: 54px; // mx_CallEvent margin (12px) + avatar (32px) + mx_CallEvent_info_basic margin (10px) + margin-bottom: 16px; + } + } } } diff --git a/res/css/views/messages/_MImageBody.scss b/res/css/views/messages/_MImageBody.scss index a748435cd8..920c3011f5 100644 --- a/res/css/views/messages/_MImageBody.scss +++ b/res/css/views/messages/_MImageBody.scss @@ -16,6 +16,12 @@ limitations under the License. $timelineImageBorderRadius: 4px; +.mx_MImageBody_thumbnail--blurhash { + position: absolute; + left: 0; + top: 0; +} + .mx_MImageBody_thumbnail { object-fit: contain; border-radius: $timelineImageBorderRadius; @@ -23,10 +29,17 @@ $timelineImageBorderRadius: 4px; display: flex; justify-content: center; align-items: center; + height: 100%; + width: 100%; - > div > canvas { + .mx_Blurhash > canvas { + animation: mx--anim-pulse 1.75s infinite cubic-bezier(.4, 0, .6, 1); border-radius: $timelineImageBorderRadius; } + + .mx_no-image-placeholder { + background-color: $primary-content; + } } .mx_MImageBody_thumbnail_container { @@ -87,5 +100,5 @@ $timelineImageBorderRadius: 4px; } .mx_EventTile:hover .mx_HiddenImagePlaceholder { - background-color: $primary-bg-color; + background-color: $background; } diff --git a/res/css/views/messages/_MessageActionBar.scss b/res/css/views/messages/_MessageActionBar.scss index 69f3c672b7..c6983ae631 100644 --- a/res/css/views/messages/_MessageActionBar.scss +++ b/res/css/views/messages/_MessageActionBar.scss @@ -23,7 +23,7 @@ limitations under the License. height: 32px; line-height: $font-24px; border-radius: 8px; - background: $primary-bg-color; + background: $background; border: 1px solid $input-border-color; top: -32px; right: 8px; @@ -77,11 +77,11 @@ limitations under the License. mask-size: 18px; mask-repeat: no-repeat; mask-position: center; - background-color: $secondary-fg-color; + background-color: $secondary-content; } .mx_MessageActionBar_maskButton:hover::after { - background-color: $primary-fg-color; + background-color: $primary-content; } .mx_MessageActionBar_reactButton::after { diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss index b2bca6dfb3..1b0b847932 100644 --- a/res/css/views/messages/_ReactionsRow.scss +++ b/res/css/views/messages/_ReactionsRow.scss @@ -16,7 +16,7 @@ limitations under the License. .mx_ReactionsRow { margin: 6px 0; - color: $primary-fg-color; + color: $primary-content; .mx_ReactionsRow_addReactionButton { position: relative; @@ -36,7 +36,7 @@ limitations under the License. mask-size: 16px; mask-repeat: no-repeat; mask-position: center; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; mask-image: url('$(res)/img/element-icons/room/message-bar/emoji.svg'); } @@ -46,7 +46,7 @@ limitations under the License. &:hover, &.mx_ReactionsRow_addReactionButton_active { &::before { - background-color: $primary-fg-color; + background-color: $primary-content; } } } @@ -64,10 +64,10 @@ limitations under the License. vertical-align: middle; &:link, &:visited { - color: $tertiary-fg-color; + color: $tertiary-content; } &:hover { - color: $primary-fg-color; + color: $primary-content; } } diff --git a/res/css/views/right_panel/_BaseCard.scss b/res/css/views/right_panel/_BaseCard.scss index 9a5a59bda8..8c1a55fe05 100644 --- a/res/css/views/right_panel/_BaseCard.scss +++ b/res/css/views/right_panel/_BaseCard.scss @@ -93,7 +93,7 @@ limitations under the License. } > h1 { - color: $tertiary-fg-color; + color: $tertiary-content; font-size: $font-12px; font-weight: 500; } @@ -145,7 +145,7 @@ limitations under the License. justify-content: space-around; .mx_AccessibleButton_kind_secondary { - color: $secondary-fg-color; + color: $secondary-content; background-color: rgba(141, 151, 165, 0.2); font-weight: $font-semi-bold; font-size: $font-14px; diff --git a/res/css/views/right_panel/_PinnedMessagesCard.scss b/res/css/views/right_panel/_PinnedMessagesCard.scss index 785aee09ca..f3861a3dec 100644 --- a/res/css/views/right_panel/_PinnedMessagesCard.scss +++ b/res/css/views/right_panel/_PinnedMessagesCard.scss @@ -48,7 +48,7 @@ limitations under the License. height: 32px; line-height: $font-24px; border-radius: 8px; - background: $primary-bg-color; + background: $background; border: 1px solid $input-border-color; padding: 1px; width: max-content; @@ -66,7 +66,7 @@ limitations under the License. z-index: 1; &::after { - background-color: $primary-fg-color; + background-color: $primary-content; } } } @@ -75,7 +75,7 @@ limitations under the License. font-weight: $font-semi-bold; font-size: $font-15px; line-height: $font-24px; - color: $primary-fg-color; + color: $primary-content; margin-top: 24px; margin-bottom: 20px; } @@ -83,7 +83,7 @@ limitations under the License. > span { font-size: $font-12px; line-height: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; } } } diff --git a/res/css/views/right_panel/_RoomSummaryCard.scss b/res/css/views/right_panel/_RoomSummaryCard.scss index dc7804d072..fcb83dfd7a 100644 --- a/res/css/views/right_panel/_RoomSummaryCard.scss +++ b/res/css/views/right_panel/_RoomSummaryCard.scss @@ -27,7 +27,7 @@ limitations under the License. .mx_RoomSummaryCard_alias { font-size: $font-13px; - color: $secondary-fg-color; + color: $secondary-content; } h2, .mx_RoomSummaryCard_alias { @@ -115,7 +115,7 @@ limitations under the License. // as we will be applying it in its children padding: 0; height: auto; - color: $tertiary-fg-color; + color: $tertiary-content; .mx_RoomSummaryCard_icon_app { padding: 10px 48px 10px 12px; // based on typical mx_RoomSummaryCard_Button padding @@ -128,7 +128,7 @@ limitations under the License. } span { - color: $primary-fg-color; + color: $primary-content; } } diff --git a/res/css/views/right_panel/_UserInfo.scss b/res/css/views/right_panel/_UserInfo.scss index 6632ccddf9..edc82cfdbf 100644 --- a/res/css/views/right_panel/_UserInfo.scss +++ b/res/css/views/right_panel/_UserInfo.scss @@ -55,7 +55,7 @@ limitations under the License. } .mx_UserInfo_separator { - border-bottom: 1px solid rgba($primary-fg-color, .1); + border-bottom: 1px solid rgba($primary-content, .1); } .mx_UserInfo_memberDetailsContainer { diff --git a/res/css/views/right_panel/_WidgetCard.scss b/res/css/views/right_panel/_WidgetCard.scss index a90e744a5a..824f1fcb2f 100644 --- a/res/css/views/right_panel/_WidgetCard.scss +++ b/res/css/views/right_panel/_WidgetCard.scss @@ -51,7 +51,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-image: url('$(res)/img/element-icons/room/ellipsis.svg'); - background-color: $secondary-fg-color; + background-color: $secondary-content; } } } diff --git a/res/css/views/rooms/_AppsDrawer.scss b/res/css/views/rooms/_AppsDrawer.scss index fd80836237..cfcb0c48a2 100644 --- a/res/css/views/rooms/_AppsDrawer.scss +++ b/res/css/views/rooms/_AppsDrawer.scss @@ -64,7 +64,7 @@ $MiniAppTileHeight: 200px; &:hover { .mx_AppsContainer_resizerHandle::after { opacity: 0.8; - background: $primary-fg-color; + background: $primary-content; } .mx_ResizeHandle_horizontal::before { @@ -79,7 +79,7 @@ $MiniAppTileHeight: 200px; content: ''; - background-color: $primary-fg-color; + background-color: $primary-content; opacity: 0.8; } } diff --git a/res/css/views/rooms/_Autocomplete.scss b/res/css/views/rooms/_Autocomplete.scss index f8e0a382b1..bebe0b47c9 100644 --- a/res/css/views/rooms/_Autocomplete.scss +++ b/res/css/views/rooms/_Autocomplete.scss @@ -4,27 +4,29 @@ z-index: 1001; width: 100%; border: 1px solid $primary-hairline-color; - background: $primary-bg-color; + background: $background; border-bottom: none; border-radius: 8px 8px 0 0; - max-height: 50vh; - overflow: auto; + max-height: 35vh; + overflow: clip; + display: flex; box-shadow: 0px -16px 32px $composer-shadow-color; } .mx_Autocomplete_ProviderSection { border-bottom: 1px solid $primary-hairline-color; + width: 100%; } /* a "block" completion takes up a whole line */ .mx_Autocomplete_Completion_block { - height: 34px; + min-height: 34px; display: flex; padding: 0 12px; user-select: none; cursor: pointer; align-items: center; - color: $primary-fg-color; + color: $primary-content; } .mx_Autocomplete_Completion_block * { @@ -40,7 +42,7 @@ user-select: none; cursor: pointer; align-items: center; - color: $primary-fg-color; + color: $primary-content; } .mx_Autocomplete_Completion_pill > * { @@ -59,8 +61,8 @@ .mx_Autocomplete_Completion_container_pill { margin: 12px; - display: flex; - flex-flow: wrap; + height: 100%; + overflow-y: scroll; } .mx_Autocomplete_Completion_container_truncate { @@ -68,7 +70,6 @@ .mx_Autocomplete_Completion_subtitle, .mx_Autocomplete_Completion_description { /* Ellipsis for long names/subtitles/descriptions */ - max-width: 150px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -83,7 +84,7 @@ .mx_Autocomplete_provider_name { margin: 12px; - color: $primary-fg-color; + color: $primary-content; font-weight: 400; opacity: 0.4; } diff --git a/res/css/views/rooms/_BasicMessageComposer.scss b/res/css/views/rooms/_BasicMessageComposer.scss index e1ba468204..752d3b0a54 100644 --- a/res/css/views/rooms/_BasicMessageComposer.scss +++ b/res/css/views/rooms/_BasicMessageComposer.scss @@ -31,7 +31,7 @@ limitations under the License. @keyframes visualbell { from { background-color: $visual-bell-bg-color; } - to { background-color: $primary-bg-color; } + to { background-color: $background; } } &.mx_BasicMessageComposer_input_error { @@ -65,6 +65,14 @@ limitations under the License. font-size: $font-10-4px; } } + + span.mx_UserPill { + cursor: pointer; + } + + span.mx_RoomPill { + cursor: default; + } } &.mx_BasicMessageComposer_input_disabled { diff --git a/res/css/views/rooms/_EditMessageComposer.scss b/res/css/views/rooms/_EditMessageComposer.scss index 214bfc4a1a..bf3c7c9b42 100644 --- a/res/css/views/rooms/_EditMessageComposer.scss +++ b/res/css/views/rooms/_EditMessageComposer.scss @@ -28,7 +28,7 @@ limitations under the License. .mx_BasicMessageComposer_input { border-radius: 4px; border: solid 1px $primary-hairline-color; - background-color: $primary-bg-color; + background-color: $background; max-height: 200px; padding: 3px 6px; diff --git a/res/css/views/rooms/_EntityTile.scss b/res/css/views/rooms/_EntityTile.scss index 27a4e67089..a2ebd6c11b 100644 --- a/res/css/views/rooms/_EntityTile.scss +++ b/res/css/views/rooms/_EntityTile.scss @@ -18,7 +18,7 @@ limitations under the License. .mx_EntityTile { display: flex; align-items: center; - color: $primary-fg-color; + color: $primary-content; cursor: pointer; .mx_E2EIcon { @@ -86,12 +86,12 @@ limitations under the License. .mx_EntityTile_ellipsis .mx_EntityTile_name { font-style: italic; - color: $primary-fg-color; + color: $primary-content; } .mx_EntityTile_invitePlaceholder .mx_EntityTile_name { font-style: italic; - color: $primary-fg-color; + color: $primary-content; } .mx_EntityTile_unavailable .mx_EntityTile_avatar, diff --git a/res/css/views/rooms/_EventBubbleTile.scss b/res/css/views/rooms/_EventBubbleTile.scss index 1e25deba26..8c02affbed 100644 --- a/res/css/views/rooms/_EventBubbleTile.scss +++ b/res/css/views/rooms/_EventBubbleTile.scss @@ -105,6 +105,8 @@ limitations under the License. .mx_ReplyTile .mx_SenderProfile { display: block; + top: unset; + left: unset; } .mx_ReactionsRow { @@ -188,8 +190,6 @@ limitations under the License. } .mx_ReplyThread { - margin: 0 calc(-1 * var(--gutterSize)); - .mx_EventTile_reply { max-width: 90%; padding: 0; @@ -223,11 +223,6 @@ limitations under the License. margin-left: -9px; } - .mx_ReplyThread { - border-left-width: 2px; - border-left-color: $eventbubble-reply-color; - } - /* Special layout scenario for "Unable To Decrypt (UTD)" events */ &.mx_EventTile_bad > .mx_EventTile_line { display: grid; @@ -264,6 +259,7 @@ limitations under the License. } .mx_EventTile.mx_EventTile_bubbleContainer[data-layout=bubble], +.mx_EventTile.mx_EventTile_leftAlignedBubble[data-layout=bubble], .mx_EventTile.mx_EventTile_info[data-layout=bubble], .mx_EventListSummary[data-layout=bubble][data-expanded=false] { --backgroundColor: transparent; @@ -271,7 +267,7 @@ limitations under the License. display: flex; align-items: center; - justify-content: start; + justify-content: flex-start; padding: 5px 0; .mx_EventTile_avatar { diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 6192fc4df9..64008346ca 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -55,7 +55,7 @@ $hover-select-border: 4px; } .mx_SenderProfile { - color: $primary-fg-color; + color: $primary-content; font-size: $font-14px; display: inline-block; /* anti-zalgo, with overflow hidden */ overflow: hidden; @@ -161,7 +161,7 @@ $hover-select-border: 4px; // up with the other read receipts &::before { - background-color: $tertiary-fg-color; + background-color: $tertiary-content; mask-repeat: no-repeat; mask-position: center; mask-size: 14px; @@ -480,7 +480,7 @@ $hover-select-border: 4px; } pre code > * { - display: inline-block; + display: inline; } pre { @@ -489,6 +489,10 @@ $hover-select-border: 4px; // https://github.com/vector-im/vector-web/issues/754 overflow-x: overlay; overflow-y: visible; + + &::-webkit-scrollbar-corner { + background: transparent; + } } } @@ -614,7 +618,7 @@ $hover-select-border: 4px; } .mx_EventTile_keyRequestInfo_text a { - color: $primary-fg-color; + color: $primary-content; text-decoration: underline; cursor: pointer; } diff --git a/res/css/views/rooms/_JumpToBottomButton.scss b/res/css/views/rooms/_JumpToBottomButton.scss index a8dc2ce11c..2b38b509de 100644 --- a/res/css/views/rooms/_JumpToBottomButton.scss +++ b/res/css/views/rooms/_JumpToBottomButton.scss @@ -56,7 +56,7 @@ limitations under the License. height: 38px; border-radius: 19px; box-sizing: border-box; - background: $primary-bg-color; + background: $background; border: 1.3px solid $muted-fg-color; cursor: pointer; } diff --git a/res/css/views/rooms/_MemberInfo.scss b/res/css/views/rooms/_MemberInfo.scss index 3f7f83d334..4abd9c7c30 100644 --- a/res/css/views/rooms/_MemberInfo.scss +++ b/res/css/views/rooms/_MemberInfo.scss @@ -111,7 +111,7 @@ limitations under the License. .mx_MemberInfo_field { cursor: pointer; font-size: $font-15px; - color: $primary-fg-color; + color: $primary-content; margin-left: 8px; line-height: $font-23px; } diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index 5e2eff4047..d164fac8f2 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -130,7 +130,7 @@ limitations under the License. @keyframes visualbell { from { background-color: $visual-bell-bg-color; } - to { background-color: $primary-bg-color; } + to { background-color: $background; } } .mx_MessageComposer_input_error { @@ -160,8 +160,8 @@ limitations under the License. resize: none; outline: none; box-shadow: none; - color: $primary-fg-color; - background-color: $primary-bg-color; + color: $primary-content; + background-color: $background; font-size: $font-14px; max-height: 120px; overflow: auto; diff --git a/res/css/views/rooms/_NewRoomIntro.scss b/res/css/views/rooms/_NewRoomIntro.scss index e0cccfa885..f0e471d384 100644 --- a/res/css/views/rooms/_NewRoomIntro.scss +++ b/res/css/views/rooms/_NewRoomIntro.scss @@ -67,6 +67,6 @@ limitations under the License. > p { margin: 0; font-size: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; } } diff --git a/res/css/views/rooms/_NotificationBadge.scss b/res/css/views/rooms/_NotificationBadge.scss index 64b2623238..670e057cfa 100644 --- a/res/css/views/rooms/_NotificationBadge.scss +++ b/res/css/views/rooms/_NotificationBadge.scss @@ -42,7 +42,7 @@ limitations under the License. // These are the 3 background types &.mx_NotificationBadge_dot { - background-color: $primary-fg-color; // increased visibility + background-color: $primary-content; // increased visibility width: 6px; height: 6px; diff --git a/res/css/views/rooms/_PinnedEventTile.scss b/res/css/views/rooms/_PinnedEventTile.scss index 15b3c16faa..07978a8f65 100644 --- a/res/css/views/rooms/_PinnedEventTile.scss +++ b/res/css/views/rooms/_PinnedEventTile.scss @@ -67,7 +67,7 @@ limitations under the License. //left: 0; height: inherit; width: inherit; - background: $secondary-fg-color; + background: $secondary-content; mask-position: center; mask-size: 8px; mask-repeat: no-repeat; @@ -87,7 +87,7 @@ limitations under the License. .mx_PinnedEventTile_timestamp { font-size: inherit; line-height: inherit; - color: $secondary-fg-color; + color: $secondary-content; } .mx_AccessibleButton_kind_link { diff --git a/res/css/views/rooms/_ReplyPreview.scss b/res/css/views/rooms/_ReplyPreview.scss index 60feb39d11..70a820e412 100644 --- a/res/css/views/rooms/_ReplyPreview.scss +++ b/res/css/views/rooms/_ReplyPreview.scss @@ -16,7 +16,7 @@ limitations under the License. .mx_ReplyPreview { border: 1px solid $primary-hairline-color; - background: $primary-bg-color; + background: $background; border-bottom: none; border-radius: 8px 8px 0 0; max-height: 50vh; @@ -28,7 +28,7 @@ limitations under the License. .mx_ReplyPreview_header { margin: 8px; - color: $primary-fg-color; + color: $primary-content; font-weight: 400; opacity: 0.4; } diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index fd21e5f348..3ef6491ec9 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -42,7 +42,7 @@ limitations under the License. display: flex; flex-direction: column; text-decoration: none; - color: $primary-fg-color; + color: $primary-content; } .mx_RedactedBody { diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index 4142b0a2ef..81dfa90c96 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -17,7 +17,7 @@ limitations under the License. .mx_RoomHeader { flex: 0 0 50px; border-bottom: 1px solid $primary-hairline-color; - background-color: $roomheader-bg-color; + background-color: $background; .mx_RoomHeader_e2eIcon { height: 12px; @@ -74,7 +74,7 @@ limitations under the License. .mx_RoomHeader_buttons { display: flex; - background-color: $primary-bg-color; + background-color: $background; } .mx_RoomHeader_info { diff --git a/res/css/views/rooms/_RoomList.scss b/res/css/views/rooms/_RoomList.scss index 8eda25d0c9..7d967661a6 100644 --- a/res/css/views/rooms/_RoomList.scss +++ b/res/css/views/rooms/_RoomList.scss @@ -43,11 +43,11 @@ limitations under the License. div:first-child { font-weight: $font-semi-bold; line-height: $font-18px; - color: $primary-fg-color; + color: $primary-content; } .mx_AccessibleButton { - color: $primary-fg-color; + color: $primary-content; position: relative; padding: 8px 8px 8px 32px; font-size: inherit; @@ -64,7 +64,7 @@ limitations under the License. position: absolute; top: 8px; left: 8px; - background: $secondary-fg-color; + background: $secondary-content; mask-position: center; mask-size: contain; mask-repeat: no-repeat; diff --git a/res/css/views/rooms/_RoomSublist.scss b/res/css/views/rooms/_RoomSublist.scss index 146b3edf71..3fffbfd64c 100644 --- a/res/css/views/rooms/_RoomSublist.scss +++ b/res/css/views/rooms/_RoomSublist.scss @@ -233,7 +233,7 @@ limitations under the License. &:hover, &.mx_RoomSublist_hasMenuOpen { .mx_RoomSublist_resizerHandle { opacity: 0.8; - background-color: $primary-fg-color; + background-color: $primary-content; } } } diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index b8f4aeb6e7..0c04f27115 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -124,7 +124,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $primary-fg-color; + background: $primary-content; } } diff --git a/res/css/views/rooms/_SearchBar.scss b/res/css/views/rooms/_SearchBar.scss index d9f730a8b6..e08168a122 100644 --- a/res/css/views/rooms/_SearchBar.scss +++ b/res/css/views/rooms/_SearchBar.scss @@ -47,7 +47,7 @@ limitations under the License. padding: 5px; font-size: $font-15px; cursor: pointer; - color: $primary-fg-color; + color: $primary-content; border-bottom: 2px solid $accent-color; font-weight: 600; } diff --git a/res/css/views/rooms/_TopUnreadMessagesBar.scss b/res/css/views/rooms/_TopUnreadMessagesBar.scss index 8841b042a0..7c7d96e713 100644 --- a/res/css/views/rooms/_TopUnreadMessagesBar.scss +++ b/res/css/views/rooms/_TopUnreadMessagesBar.scss @@ -41,7 +41,7 @@ limitations under the License. height: 38px; border-radius: 19px; box-sizing: border-box; - background: $primary-bg-color; + background: $background; border: 1.3px solid $muted-fg-color; cursor: pointer; } @@ -62,7 +62,7 @@ limitations under the License. display: block; width: 18px; height: 18px; - background: $primary-bg-color; + background: $background; border: 1.3px solid $muted-fg-color; border-radius: 10px; margin: 5px auto; diff --git a/res/css/views/rooms/_VoiceRecordComposerTile.scss b/res/css/views/rooms/_VoiceRecordComposerTile.scss index 5501ab343e..69fe292c0a 100644 --- a/res/css/views/rooms/_VoiceRecordComposerTile.scss +++ b/res/css/views/rooms/_VoiceRecordComposerTile.scss @@ -20,7 +20,7 @@ limitations under the License. height: 28px; border: 2px solid $voice-record-stop-border-color; border-radius: 32px; - margin-right: 16px; // between us and the send button + margin-right: 8px; // between us and the waveform component position: relative; &::after { @@ -46,9 +46,28 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/trashcan.svg'); } +.mx_VoiceRecordComposerTile_uploadingState { + margin-right: 10px; + color: $secondary-content; +} + +.mx_VoiceRecordComposerTile_failedState { + margin-right: 21px; + + .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. + // fixed height to reduce layout jumps with the play button appearing + // https://github.com/vector-im/element-web/issues/18431 + height: 32px; + margin: 6px; // force the composer area to put a gutter around us margin-right: 12px; // isolate from stop/send button @@ -68,7 +87,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: 17px; // vertically center (middle align with clock) border-radius: 10px; } } diff --git a/res/css/views/rooms/_WhoIsTypingTile.scss b/res/css/views/rooms/_WhoIsTypingTile.scss index 1c0dabbeb5..49655742bb 100644 --- a/res/css/views/rooms/_WhoIsTypingTile.scss +++ b/res/css/views/rooms/_WhoIsTypingTile.scss @@ -36,7 +36,7 @@ limitations under the License. } .mx_WhoIsTypingTile_avatars .mx_BaseAvatar { - border: 1px solid $primary-bg-color; + border: 1px solid $background; border-radius: 40px; } @@ -45,7 +45,7 @@ limitations under the License. display: inline-block; color: #acacac; background-color: #ddd; - border: 1px solid $primary-bg-color; + border: 1px solid $background; border-radius: 40px; width: 24px; height: 24px; diff --git a/res/css/views/settings/_LayoutSwitcher.scss b/res/css/views/settings/_LayoutSwitcher.scss new file mode 100644 index 0000000000..00fb8aba56 --- /dev/null +++ b/res/css/views/settings/_LayoutSwitcher.scss @@ -0,0 +1,91 @@ +/* +Copyright 2020 - 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. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_LayoutSwitcher { + .mx_LayoutSwitcher_RadioButtons { + display: flex; + flex-direction: row; + gap: 24px; + + color: $primary-content; + + > .mx_LayoutSwitcher_RadioButton { + flex-grow: 0; + flex-shrink: 1; + display: flex; + flex-direction: column; + + width: 300px; + + border: 1px solid $appearance-tab-border-color; + border-radius: 10px; + + .mx_EventTile_msgOption, + .mx_MessageActionBar { + display: none; + } + + .mx_LayoutSwitcher_RadioButton_preview { + flex-grow: 1; + display: flex; + align-items: center; + padding: 10px; + pointer-events: none; + } + + .mx_RadioButton { + flex-grow: 0; + padding: 10px; + } + + .mx_EventTile_content { + margin-right: 0; + } + + &.mx_LayoutSwitcher_RadioButton_selected { + border-color: $accent-color; + } + } + + .mx_RadioButton { + border-top: 1px solid $appearance-tab-border-color; + + > input + div { + border-color: rgba($muted-fg-color, 0.2); + } + } + + .mx_RadioButton_checked { + background-color: rgba($accent-color, 0.08); + } + + .mx_EventTile { + margin: 0; + &[data-layout=bubble] { + margin-right: 40px; + } + &[data-layout=irc] { + > a { + display: none; + } + } + .mx_EventTile_line { + max-width: 90%; + } + } + } +} diff --git a/res/css/views/settings/_Notifications.scss b/res/css/views/settings/_Notifications.scss index f93e0a53a8..a0e46c0071 100644 --- a/res/css/views/settings/_Notifications.scss +++ b/res/css/views/settings/_Notifications.scss @@ -15,7 +15,7 @@ limitations under the License. */ .mx_UserNotifSettings { - color: $primary-fg-color; // override from default settings page styles + color: $primary-content; // override from default settings page styles .mx_UserNotifSettings_pushRulesTable { width: calc(100% + 12px); // +12px to line up center of 'Noisy' column with toggle switches @@ -34,7 +34,7 @@ limitations under the License. } tr > th:nth-child(n + 2) { - color: $secondary-fg-color; + color: $secondary-content; font-size: $font-12px; vertical-align: middle; width: 66px; diff --git a/res/css/views/settings/tabs/_SettingsTab.scss b/res/css/views/settings/tabs/_SettingsTab.scss index 9f40372690..5aa9db7e86 100644 --- a/res/css/views/settings/tabs/_SettingsTab.scss +++ b/res/css/views/settings/tabs/_SettingsTab.scss @@ -25,7 +25,7 @@ limitations under the License. .mx_SettingsTab_heading { font-size: $font-20px; font-weight: 600; - color: $primary-fg-color; + color: $primary-content; margin-bottom: 10px; } @@ -37,7 +37,7 @@ limitations under the License. font-size: $font-16px; display: block; font-weight: 600; - color: $primary-fg-color; + color: $primary-content; margin-bottom: 10px; margin-top: 12px; } @@ -50,15 +50,21 @@ limitations under the License. } .mx_SettingsTab_section { + $right-gutter: 80px; + margin-bottom: 24px; .mx_SettingsFlag { - margin-right: 80px; + margin-right: $right-gutter; margin-bottom: 10px; } + > p { + margin-right: $right-gutter; + } + &.mx_SettingsTab_subsectionText .mx_SettingsFlag { - margin-right: 0px !important; + margin-right: 0 !important; } } @@ -66,7 +72,7 @@ limitations under the License. vertical-align: middle; display: inline-block; font-size: $font-14px; - color: $primary-fg-color; + color: $primary-content; max-width: calc(100% - $font-48px); // Force word wrap instead of colliding with the switch box-sizing: border-box; padding-right: 10px; @@ -76,7 +82,7 @@ limitations under the License. margin-top: 4px; font-size: $font-12px; line-height: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; } .mx_SettingsTab_section .mx_SettingsFlag .mx_ToggleSwitch { diff --git a/res/css/views/settings/tabs/room/_SecurityRoomSettingsTab.scss b/res/css/views/settings/tabs/room/_SecurityRoomSettingsTab.scss index 2aab201352..8fd0f14418 100644 --- a/res/css/views/settings/tabs/room/_SecurityRoomSettingsTab.scss +++ b/res/css/views/settings/tabs/room/_SecurityRoomSettingsTab.scss @@ -22,7 +22,7 @@ limitations under the License. .mx_SecurityRoomSettingsTab_spacesWithAccess { > h4 { - color: $secondary-fg-color; + color: $secondary-content; font-weight: $font-semi-bold; font-size: $font-12px; line-height: $font-15px; @@ -33,7 +33,7 @@ limitations under the License. font-weight: 500; font-size: $font-14px; line-height: 32px; // matches height of avatar for v-align - color: $secondary-fg-color; + color: $secondary-content; display: inline-block; img.mx_RoomAvatar_isSpaceRoom, @@ -89,7 +89,7 @@ limitations under the License. font-weight: $font-semi-bold; font-size: $font-15px; line-height: $font-24px; - color: $primary-fg-color; + color: $primary-content; display: block; } } @@ -100,7 +100,7 @@ limitations under the License. margin-bottom: 16px; font-size: $font-15px; line-height: $font-24px; - color: $secondary-fg-color; + color: $secondary-content; & + .mx_RadioButton { border-top: 1px solid $menu-border-color; diff --git a/res/css/views/settings/tabs/user/_AppearanceUserSettingsTab.scss b/res/css/views/settings/tabs/user/_AppearanceUserSettingsTab.scss index ca5a6f0a66..57c6e9b865 100644 --- a/res/css/views/settings/tabs/user/_AppearanceUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_AppearanceUserSettingsTab.scss @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020 - 2021 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ limitations under the License. } .mx_AppearanceUserSettingsTab_fontScaling { - color: $primary-fg-color; + color: $primary-content; } .mx_AppearanceUserSettingsTab_fontSlider { @@ -81,7 +81,7 @@ limitations under the License. .mx_AppearanceUserSettingsTab_themeSection { $radio-bg-color: $input-darker-bg-color; - color: $primary-fg-color; + color: $primary-content; > .mx_ThemeSelectors { display: flex; @@ -155,81 +155,8 @@ limitations under the License. margin-left: calc($font-16px + 10px); } -.mx_AppearanceUserSettingsTab_Layout_RadioButtons { - display: flex; - flex-direction: row; - gap: 24px; - - color: $primary-fg-color; - - > .mx_AppearanceUserSettingsTab_Layout_RadioButton { - flex-grow: 0; - flex-shrink: 1; - display: flex; - flex-direction: column; - - width: 300px; - - border: 1px solid $appearance-tab-border-color; - border-radius: 10px; - - .mx_EventTile_msgOption, - .mx_MessageActionBar { - display: none; - } - - .mx_AppearanceUserSettingsTab_Layout_RadioButton_preview { - flex-grow: 1; - display: flex; - align-items: center; - padding: 10px; - pointer-events: none; - } - - .mx_RadioButton { - flex-grow: 0; - padding: 10px; - } - - .mx_EventTile_content { - margin-right: 0; - } - - &.mx_AppearanceUserSettingsTab_Layout_RadioButton_selected { - border-color: $accent-color; - } - } - - .mx_RadioButton { - border-top: 1px solid $appearance-tab-border-color; - - > input + div { - border-color: rgba($muted-fg-color, 0.2); - } - } - - .mx_RadioButton_checked { - background-color: rgba($accent-color, 0.08); - } - - .mx_EventTile { - margin: 0; - &[data-layout=bubble] { - margin-right: 40px; - } - &[data-layout=irc] { - > a { - display: none; - } - } - .mx_EventTile_line { - max-width: 90%; - } - } -} - .mx_AppearanceUserSettingsTab_Advanced { - color: $primary-fg-color; + color: $primary-content; > * { margin-bottom: 16px; diff --git a/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss b/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss index 0f879d209e..3e61e80a9d 100644 --- a/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss @@ -28,28 +28,33 @@ limitations under the License. user-select: all; } -.mx_HelpUserSettingsTab_accessToken { +.mx_HelpUserSettingsTab_copy { display: flex; - justify-content: space-between; border-radius: 5px; border: solid 1px $light-fg-color; margin-bottom: 10px; margin-top: 10px; padding: 10px; -} + width: max-content; + max-width: 100%; -.mx_HelpUserSettingsTab_accessToken_copy { - flex-shrink: 0; - cursor: pointer; - margin-left: 20px; - display: inherit; -} + .mx_HelpUserSettingsTab_copyButton { + flex-shrink: 0; + width: 20px; + height: 20px; + cursor: pointer; + margin-left: 20px; + display: block; -.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; + &::before { + content: ""; + + mask-image: url($copy-button-url); + background-color: $message-action-bar-fg-color; + width: 20px; + height: 20px; + display: block; + background-repeat: no-repeat; + } + } } diff --git a/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss b/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss index be0af9123b..d1076205ad 100644 --- a/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss @@ -22,4 +22,25 @@ limitations under the License. .mx_SettingsTab_section { margin-bottom: 30px; } + + .mx_PreferencesUserSettingsTab_CommunityMigrator { + margin-right: 200px; + + > div { + font-weight: $font-semi-bold; + font-size: $font-15px; + line-height: $font-18px; + color: $primary-content; + margin: 16px 0; + + .mx_BaseAvatar { + margin-right: 12px; + vertical-align: middle; + } + + .mx_AccessibleButton { + float: right; + } + } + } } diff --git a/res/css/views/spaces/_SpaceBasicSettings.scss b/res/css/views/spaces/_SpaceBasicSettings.scss index c73e0715dd..bff574ded3 100644 --- a/res/css/views/spaces/_SpaceBasicSettings.scss +++ b/res/css/views/spaces/_SpaceBasicSettings.scss @@ -27,7 +27,7 @@ limitations under the License. position: relative; height: 80px; width: 80px; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; border-radius: 16px; } diff --git a/res/css/views/spaces/_SpaceCreateMenu.scss b/res/css/views/spaces/_SpaceCreateMenu.scss index 097b2b648e..3f526a6bba 100644 --- a/res/css/views/spaces/_SpaceCreateMenu.scss +++ b/res/css/views/spaces/_SpaceCreateMenu.scss @@ -28,7 +28,7 @@ $spacePanelWidth: 71px; padding: 24px; width: 480px; box-sizing: border-box; - background-color: $primary-bg-color; + background-color: $background; position: relative; > div { @@ -40,8 +40,7 @@ $spacePanelWidth: 71px; > p { font-size: $font-15px; - color: $secondary-fg-color; - margin: 0; + color: $secondary-content; } .mx_SpaceFeedbackPrompt { @@ -51,13 +50,6 @@ $spacePanelWidth: 71px; } } - // XXX remove this when spaces leaves Beta - .mx_BetaCard_betaPill { - position: absolute; - top: 24px; - right: 24px; - } - .mx_SpaceCreateMenuType { @mixin SpacePillButton; } @@ -84,7 +76,7 @@ $spacePanelWidth: 71px; width: 28px; top: 0; left: 0; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; transform: rotate(90deg); mask-repeat: no-repeat; mask-position: 2px 3px; @@ -100,6 +92,11 @@ $spacePanelWidth: 71px; width: min-content; } + .mx_AccessibleButton_kind_link { + padding: 0; + font-size: inherit; + } + .mx_AccessibleButton_disabled { cursor: not-allowed; } @@ -111,7 +108,7 @@ $spacePanelWidth: 71px; line-height: $font-24px; > span { - color: $secondary-fg-color; + color: $secondary-content; position: relative; font-size: inherit; line-height: inherit; diff --git a/res/css/views/toasts/_IncomingCallToast.scss b/res/css/views/toasts/_IncomingCallToast.scss index 975628f948..cb05b1a977 100644 --- a/res/css/views/toasts/_IncomingCallToast.scss +++ b/res/css/views/toasts/_IncomingCallToast.scss @@ -30,13 +30,20 @@ limitations under the License. font-size: $font-15px; line-height: $font-18px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + margin-top: 2px; + margin-right: 6px; + + max-width: 200px; } .mx_CallEvent_type { font-size: $font-12px; line-height: $font-15px; - color: $tertiary-fg-color; + color: $tertiary-content; margin-top: 4px; margin-bottom: 6px; @@ -55,7 +62,7 @@ limitations under the License. position: absolute; height: inherit; width: inherit; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; mask-repeat: no-repeat; mask-size: contain; } @@ -132,7 +139,7 @@ limitations under the License. height: inherit; width: inherit; - background-color: $tertiary-fg-color; + background-color: $tertiary-content; mask-repeat: no-repeat; mask-size: contain; mask-position: center; diff --git a/res/css/views/voip/CallView/_CallViewButtons.scss b/res/css/views/voip/CallView/_CallViewButtons.scss new file mode 100644 index 0000000000..8e343f0ff3 --- /dev/null +++ b/res/css/views/voip/CallView/_CallViewButtons.scss @@ -0,0 +1,102 @@ +/* +Copyright 2015, 2016 OpenMarket Ltd +Copyright 2020 - 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. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_CallViewButtons { + position: absolute; + display: flex; + justify-content: center; + bottom: 5px; + opacity: 1; + transition: opacity 0.5s; + z-index: 200; // To be above _all_ feeds + + &.mx_CallViewButtons_hidden { + opacity: 0.001; // opacity 0 can cause a re-layout + pointer-events: none; + } + + .mx_CallViewButtons_button { + cursor: pointer; + margin-left: 2px; + margin-right: 2px; + + + &::before { + content: ''; + display: inline-block; + + height: 48px; + width: 48px; + + background-repeat: no-repeat; + background-size: contain; + background-position: center; + } + + + &.mx_CallViewButtons_dialpad::before { + background-image: url('$(res)/img/voip/dialpad.svg'); + } + + &.mx_CallViewButtons_button_micOn::before { + background-image: url('$(res)/img/voip/mic-on.svg'); + } + + &.mx_CallViewButtons_button_micOff::before { + background-image: url('$(res)/img/voip/mic-off.svg'); + } + + &.mx_CallViewButtons_button_vidOn::before { + background-image: url('$(res)/img/voip/vid-on.svg'); + } + + &.mx_CallViewButtons_button_vidOff::before { + background-image: url('$(res)/img/voip/vid-off.svg'); + } + + &.mx_CallViewButtons_button_screensharingOn::before { + background-image: url('$(res)/img/voip/screensharing-on.svg'); + } + + &.mx_CallViewButtons_button_screensharingOff::before { + background-image: url('$(res)/img/voip/screensharing-off.svg'); + } + + &.mx_CallViewButtons_button_sidebarOn::before { + background-image: url('$(res)/img/voip/sidebar-on.svg'); + } + + &.mx_CallViewButtons_button_sidebarOff::before { + background-image: url('$(res)/img/voip/sidebar-off.svg'); + } + + &.mx_CallViewButtons_button_hangup::before { + background-image: url('$(res)/img/voip/hangup.svg'); + } + + &.mx_CallViewButtons_button_more::before { + background-image: url('$(res)/img/voip/more.svg'); + } + + &.mx_CallViewButtons_button_invisible { + visibility: hidden; + pointer-events: none; + position: absolute; + } + } +} diff --git a/res/css/views/voip/_CallContainer.scss b/res/css/views/voip/_CallContainer.scss index d11ab9bf9f..a0137b18e8 100644 --- a/res/css/views/voip/_CallContainer.scss +++ b/res/css/views/voip/_CallContainer.scss @@ -26,19 +26,6 @@ limitations under the License. // different level. pointer-events: none; - .mx_CallPreview { - pointer-events: initial; // restore pointer events so the user can leave/interact - - .mx_VideoFeed_remote.mx_VideoFeed_voice { - min-height: 150px; - } - - .mx_VideoFeed_local { - border-radius: 8px; - overflow: hidden; - } - } - .mx_AppTile_persistedWrapper div { min-width: 350px; } diff --git a/res/css/views/voip/_CallPreview.scss b/res/css/views/voip/_CallPreview.scss index 92348fb465..0fd97d4676 100644 --- a/res/css/views/voip/_CallPreview.scss +++ b/res/css/views/voip/_CallPreview.scss @@ -18,4 +18,15 @@ limitations under the License. position: fixed; left: 0; top: 0; + + pointer-events: initial; // restore pointer events so the user can leave/interact + + .mx_VideoFeed_remote.mx_VideoFeed_voice { + min-height: 150px; + } + + .mx_VideoFeed_local { + border-radius: 8px; + overflow: hidden; + } } diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index c473a1fc79..aa0aa4e2a6 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -39,19 +39,20 @@ limitations under the License. .mx_CallView_pip { width: 320px; padding-bottom: 8px; - background-color: $toast-bg-color; + background-color: $system; box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.20); border-radius: 8px; + .mx_CallView_video_hold, .mx_CallView_voice { height: 180px; } - .mx_CallView_callControls { + .mx_CallViewButtons { bottom: 0px; } - .mx_CallView_callControls_button { + .mx_CallViewButtons_button { &::before { width: 36px; height: 36px; @@ -73,11 +74,9 @@ limitations under the License. > .mx_VideoFeed { width: 100%; height: 100%; + border-width: 0 !important; // Override mx_VideoFeed_speaking &.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; align-items: center; @@ -201,134 +200,6 @@ limitations under the License. } } -.mx_CallView_header { - height: 44px; - display: flex; - flex-direction: row; - align-items: center; - justify-content: left; - flex-shrink: 0; - cursor: pointer; -} - -.mx_CallView_header_callType { - font-size: 1.2rem; - font-weight: bold; - vertical-align: middle; -} - -.mx_CallView_header_secondaryCallInfo { - &::before { - content: '·'; - margin-left: 6px; - margin-right: 6px; - } -} - -.mx_CallView_header_controls { - margin-left: auto; -} - -.mx_CallView_header_button { - display: inline-block; - vertical-align: middle; - cursor: pointer; - - &::before { - content: ''; - display: inline-block; - height: 20px; - width: 20px; - vertical-align: middle; - background-color: $secondary-fg-color; - mask-repeat: no-repeat; - mask-size: contain; - mask-position: center; - } -} - -.mx_CallView_header_button_fullscreen { - &::before { - mask-image: url('$(res)/img/element-icons/call/fullscreen.svg'); - } -} - -.mx_CallView_header_button_expand { - &::before { - mask-image: url('$(res)/img/element-icons/call/expand.svg'); - } -} - -.mx_CallView_header_callInfo { - margin-left: 12px; - margin-right: 16px; -} - -.mx_CallView_header_roomName { - font-weight: bold; - font-size: 12px; - line-height: initial; - height: 15px; -} - -.mx_CallView_secondaryCall_roomName { - margin-left: 4px; -} - -.mx_CallView_header_callTypeSmall { - font-size: 12px; - color: $secondary-fg-color; - line-height: initial; - height: 15px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - max-width: 240px; -} - -.mx_CallView_header_callTypeIcon { - display: inline-block; - margin-right: 6px; - height: 16px; - width: 16px; - vertical-align: middle; - - &::before { - content: ''; - display: inline-block; - vertical-align: top; - - height: 16px; - width: 16px; - background-color: $secondary-fg-color; - mask-repeat: no-repeat; - mask-size: contain; - mask-position: center; - } - - &.mx_CallView_header_callTypeIcon_voice::before { - mask-image: url('$(res)/img/element-icons/call/voice-call.svg'); - } - - &.mx_CallView_header_callTypeIcon_video::before { - mask-image: url('$(res)/img/element-icons/call/video-call.svg'); - } -} - -.mx_CallView_callControls { - position: absolute; - display: flex; - justify-content: center; - bottom: 5px; - opacity: 1; - transition: opacity 0.5s; - z-index: 200; // To be above _all_ feeds -} - -.mx_CallView_callControls_hidden { - opacity: 0.001; // opacity 0 can cause a re-layout - pointer-events: none; -} .mx_CallView_presenting { opacity: 1; @@ -348,94 +219,3 @@ limitations under the License. opacity: 0.001; // opacity 0 can cause a re-layout pointer-events: none; } - -.mx_CallView_callControls_button { - cursor: pointer; - margin-left: 2px; - margin-right: 2px; - - - &::before { - content: ''; - display: inline-block; - - height: 48px; - width: 48px; - - background-repeat: no-repeat; - background-size: contain; - background-position: center; - } -} - -.mx_CallView_callControls_dialpad { - &::before { - background-image: url('$(res)/img/voip/dialpad.svg'); - } -} - -.mx_CallView_callControls_button_micOn { - &::before { - background-image: url('$(res)/img/voip/mic-on.svg'); - } -} - -.mx_CallView_callControls_button_micOff { - &::before { - background-image: url('$(res)/img/voip/mic-off.svg'); - } -} - -.mx_CallView_callControls_button_vidOn { - &::before { - background-image: url('$(res)/img/voip/vid-on.svg'); - } -} - -.mx_CallView_callControls_button_vidOff { - &::before { - background-image: url('$(res)/img/voip/vid-off.svg'); - } -} - -.mx_CallView_callControls_button_screensharingOn { - &::before { - background-image: url('$(res)/img/voip/screensharing-on.svg'); - } -} - -.mx_CallView_callControls_button_screensharingOff { - &::before { - background-image: url('$(res)/img/voip/screensharing-off.svg'); - } -} - -.mx_CallView_callControls_button_sidebarOn { - &::before { - background-image: url('$(res)/img/voip/sidebar-on.svg'); - } -} - -.mx_CallView_callControls_button_sidebarOff { - &::before { - background-image: url('$(res)/img/voip/sidebar-off.svg'); - } -} - -.mx_CallView_callControls_button_hangup { - &::before { - background-image: url('$(res)/img/voip/hangup.svg'); - } -} - -.mx_CallView_callControls_button_more { - &::before { - background-image: url('$(res)/img/voip/more.svg'); - } -} - -.mx_CallView_callControls_button_invisible { - visibility: hidden; - pointer-events: none; - position: absolute; -} diff --git a/res/css/views/voip/_CallViewForRoom.scss b/res/css/views/voip/_CallViewForRoom.scss index 769e00338e..d23fcc18bc 100644 --- a/res/css/views/voip/_CallViewForRoom.scss +++ b/res/css/views/voip/_CallViewForRoom.scss @@ -39,7 +39,7 @@ limitations under the License. width: 100%; max-width: 64px; - background-color: $primary-fg-color; + background-color: $primary-content; } } } diff --git a/res/css/views/voip/_CallViewHeader.scss b/res/css/views/voip/_CallViewHeader.scss new file mode 100644 index 0000000000..0575f4f535 --- /dev/null +++ b/res/css/views/voip/_CallViewHeader.scss @@ -0,0 +1,129 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_CallViewHeader { + height: 44px; + display: flex; + flex-direction: row; + align-items: center; + justify-content: left; + flex-shrink: 0; + cursor: pointer; +} + +.mx_CallViewHeader_callType { + font-size: 1.2rem; + font-weight: bold; + vertical-align: middle; +} + +.mx_CallViewHeader_secondaryCallInfo { + &::before { + content: '·'; + margin-left: 6px; + margin-right: 6px; + } +} + +.mx_CallViewHeader_controls { + margin-left: auto; +} + +.mx_CallViewHeader_button { + display: inline-block; + vertical-align: middle; + cursor: pointer; + + &::before { + content: ''; + display: inline-block; + height: 20px; + width: 20px; + vertical-align: middle; + background-color: $secondary-content; + mask-repeat: no-repeat; + mask-size: contain; + mask-position: center; + } +} + +.mx_CallViewHeader_button_fullscreen { + &::before { + mask-image: url('$(res)/img/element-icons/call/fullscreen.svg'); + } +} + +.mx_CallViewHeader_button_expand { + &::before { + mask-image: url('$(res)/img/element-icons/call/expand.svg'); + } +} + +.mx_CallViewHeader_callInfo { + margin-left: 12px; + margin-right: 16px; +} + +.mx_CallViewHeader_roomName { + font-weight: bold; + font-size: 12px; + line-height: initial; + height: 15px; +} + +.mx_CallView_secondaryCall_roomName { + margin-left: 4px; +} + +.mx_CallViewHeader_callTypeSmall { + font-size: 12px; + color: $secondary-content; + line-height: initial; + height: 15px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + max-width: 240px; +} + +.mx_CallViewHeader_callTypeIcon { + display: inline-block; + margin-right: 6px; + height: 16px; + width: 16px; + vertical-align: middle; + + &::before { + content: ''; + display: inline-block; + vertical-align: top; + + height: 16px; + width: 16px; + background-color: $secondary-content; + mask-repeat: no-repeat; + mask-size: contain; + mask-position: center; + } + + &.mx_CallViewHeader_callTypeIcon_voice::before { + mask-image: url('$(res)/img/element-icons/call/voice-call.svg'); + } + + &.mx_CallViewHeader_callTypeIcon_video::before { + mask-image: url('$(res)/img/element-icons/call/video-call.svg'); + } +} diff --git a/res/css/views/voip/_CallViewSidebar.scss b/res/css/views/voip/_CallViewSidebar.scss index 892a137a32..fd9c76defc 100644 --- a/res/css/views/voip/_CallViewSidebar.scss +++ b/res/css/views/voip/_CallViewSidebar.scss @@ -33,15 +33,12 @@ limitations under the License. > .mx_VideoFeed { width: 100%; + border-radius: 4px; &.mx_VideoFeed_voice { - border-radius: 4px; - display: flex; align-items: center; justify-content: center; - - aspect-ratio: 16 / 9; } .mx_VideoFeed_video { diff --git a/res/css/views/voip/_DialPad.scss b/res/css/views/voip/_DialPad.scss index eefd2e9ba5..288f1f5d31 100644 --- a/res/css/views/voip/_DialPad.scss +++ b/res/css/views/voip/_DialPad.scss @@ -33,7 +33,7 @@ limitations under the License. width: 40px; height: 40px; - background-color: $dialpad-button-bg-color; + background-color: $quinary-content; border-radius: 40px; font-size: 18px; font-weight: 600; diff --git a/res/css/views/voip/_DialPadContextMenu.scss b/res/css/views/voip/_DialPadContextMenu.scss index 527d223ffc..d2014241e9 100644 --- a/res/css/views/voip/_DialPadContextMenu.scss +++ b/res/css/views/voip/_DialPadContextMenu.scss @@ -30,7 +30,7 @@ limitations under the License. margin-right: 20px; /* a separator between the input line and the dial buttons */ - border-bottom: 1px solid $quaternary-fg-color; + border-bottom: 1px solid $quaternary-content; transition: border-bottom 0.25s; } diff --git a/res/css/views/voip/_DialPadModal.scss b/res/css/views/voip/_DialPadModal.scss index b8042f77ae..f378507f90 100644 --- a/res/css/views/voip/_DialPadModal.scss +++ b/res/css/views/voip/_DialPadModal.scss @@ -30,7 +30,7 @@ limitations under the License. margin-right: 40px; /* a separator between the input line and the dial buttons */ - border-bottom: 1px solid $quaternary-fg-color; + border-bottom: 1px solid $quaternary-content; transition: border-bottom 0.25s; } diff --git a/res/css/views/voip/_VideoFeed.scss b/res/css/views/voip/_VideoFeed.scss index 3a0f62636e..1f17a54692 100644 --- a/res/css/views/voip/_VideoFeed.scss +++ b/res/css/views/voip/_VideoFeed.scss @@ -17,9 +17,21 @@ limitations under the License. .mx_VideoFeed { overflow: hidden; position: relative; + box-sizing: border-box; + border: transparent 2px solid; + display: flex; &.mx_VideoFeed_voice { background-color: $inverted-bg-color; + aspect-ratio: 16 / 9; + } + + &.mx_VideoFeed_speaking { + border: $accent-color 2px solid; + + .mx_VideoFeed_video { + border-radius: 0; + } } .mx_VideoFeed_video { diff --git a/res/img/voip/declined-video.svg b/res/img/voip/declined-video.svg new file mode 100644 index 0000000000..509ffa8fd1 --- /dev/null +++ b/res/img/voip/declined-video.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/voip/declined-voice.svg b/res/img/voip/declined-voice.svg new file mode 100644 index 0000000000..78e8d90cdf --- /dev/null +++ b/res/img/voip/declined-voice.svg @@ -0,0 +1,4 @@ + + + + diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index e4ea2bb57e..4a6db5dd55 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -1,31 +1,37 @@ -// Colors from Figma Compound https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=557%3A0 -$system-dark: #21262C; +// Colors from Figma Compound https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=559%3A741 +$accent: #0DBD8B; +$alert: #FF5B55; +$links: #0086e6; +$primary-content: #ffffff; +$secondary-content: #A9B2BC; +$tertiary-content: #8E99A4; +$quaternary-content: #6F7882; +$quinary-content: #394049; +$system: #21262C; +$background: #15191E; +$panels: rgba($system, 0.9); +$panel-base: #8D97A5; // This color is not intended for use in the app +$panel-selected: rgba($panel-base, 0.3); +$panel-hover: rgba($panel-base, 0.1); +$panel-actions: rgba($panel-base, 0.2); +$space-nav: rgba($panel-base, 0.1); + +// TODO: Move userId colors here // unified palette // try to use these colors when possible -$bg-color: #15191E; -$base-color: $bg-color; -$base-text-color: #ffffff; $header-panel-bg-color: #20252B; $header-panel-border-color: #000000; $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; // typical text (dark-on-white in light skin) -$primary-fg-color: $text-primary-color; -$primary-bg-color: $bg-color; $muted-fg-color: $header-panel-text-primary-color; -// additional text colors -$secondary-fg-color: #A9B2BC; -$tertiary-fg-color: #8E99A4; - // used for dialog box text $light-fg-color: $header-panel-text-secondary-color; @@ -44,13 +50,13 @@ $info-plinth-fg-color: #888; $preview-bar-bg-color: $header-panel-bg-color; $groupFilterPanel-bg-color: rgba(38, 39, 43, 0.82); -$inverted-bg-color: $base-color; +$inverted-bg-color: $background; // used by AddressSelector $selected-color: $room-highlight-color; // selected for hoverover & selected event tiles -$event-selected-color: $system-dark; +$event-selected-color: $system; // used for the hairline dividers in RoomView $primary-hairline-color: transparent; @@ -65,7 +71,7 @@ $input-focused-border-color: #238cf5; $input-valid-border-color: $accent-color; $input-invalid-border-color: $warning-color; -$field-focused-label-bg-color: $bg-color; +$field-focused-label-bg-color: $background; $resend-button-divider-color: #b9bec64a; // muted-text with a 4A opacity. @@ -76,15 +82,15 @@ $scrollbar-track-color: transparent; // context menus $menu-border-color: $header-panel-border-color; $menu-bg-color: $header-panel-bg-color; -$menu-box-shadow-color: $bg-color; +$menu-box-shadow-color: $background; $menu-selected-color: $room-highlight-color; $avatar-initial-color: #ffffff; -$avatar-bg-color: $bg-color; +$avatar-bg-color: $background; -$h3-color: $primary-fg-color; +$h3-color: $primary-content; -$dialog-title-fg-color: $base-text-color; +$dialog-title-fg-color: $primary-content; $dialog-backdrop-color: #000; $dialog-shadow-color: rgba(0, 0, 0, 0.48); $dialog-close-fg-color: #9fa9ba; @@ -94,45 +100,39 @@ $lightbox-background-bg-color: #000; $lightbox-background-bg-opacity: 0.85; $settings-grey-fg-color: #a2a2a2; -$settings-profile-placeholder-bg-color: $system-dark; +$settings-profile-placeholder-bg-color: $system; $settings-profile-overlay-placeholder-fg-color: #454545; $settings-profile-button-bg-color: #e7e7e7; $settings-profile-button-fg-color: $settings-profile-overlay-placeholder-fg-color; $settings-subsection-fg-color: $text-secondary-color; -$topleftmenu-color: $text-primary-color; -$roomheader-color: $text-primary-color; -$roomheader-bg-color: $bg-color; +$topleftmenu-color: $primary-content; +$roomheader-color: $primary-content; $roomheader-addroom-bg-color: rgba(92, 100, 112, 0.3); -$roomheader-addroom-fg-color: $text-primary-color; +$roomheader-addroom-fg-color: $primary-content; $groupFilterPanel-button-color: $header-panel-text-primary-color; $groupheader-button-color: $header-panel-text-primary-color; $rightpanel-button-color: $header-panel-text-primary-color; -$icon-button-color: #8E99A4; +$icon-button-color: $tertiary-content; $roomtopic-color: $text-secondary-color; $eventtile-meta-color: $roomtopic-color; $header-divider-color: $header-panel-text-primary-color; $composer-e2e-icon-color: $header-panel-text-primary-color; -$quinary-content-color: #394049; -$toast-bg-color: $quinary-content-color; - // ******************** $theme-button-bg-color: #e3e8f0; -$dialpad-button-bg-color: #394049; $roomlist-button-bg-color: rgba(141, 151, 165, 0.2); // Buttons include the filter box, explore button, and sublist buttons -$roomlist-filter-active-bg-color: $bg-color; $roomlist-bg-color: rgba(33, 38, 44, 0.90); -$roomlist-header-color: $tertiary-fg-color; -$roomsublist-divider-color: $primary-fg-color; +$roomlist-header-color: $tertiary-content; +$roomsublist-divider-color: $primary-content; $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #3e444c 0%, #3e444c00 100%); $groupFilterPanel-divider-color: $roomlist-header-color; -$roomtile-preview-color: $secondary-fg-color; +$roomtile-preview-color: $secondary-content; $roomtile-default-badge-bg-color: #61708b; $roomtile-selected-bg-color: rgba(141, 151, 165, 0.2); @@ -156,20 +156,20 @@ $event-highlight-bg-color: #25271F; $event-timestamp-color: $text-secondary-color; // Tabbed views -$tab-label-fg-color: $text-primary-color; -$tab-label-active-fg-color: $text-primary-color; +$tab-label-fg-color: $primary-content; +$tab-label-active-fg-color: $primary-content; $tab-label-bg-color: transparent; $tab-label-active-bg-color: $accent-color; -$tab-label-icon-bg-color: $text-primary-color; -$tab-label-active-icon-bg-color: $text-primary-color; +$tab-label-icon-bg-color: $primary-content; +$tab-label-active-icon-bg-color: $primary-content; // Buttons -$button-primary-fg-color: #ffffff; +$button-primary-fg-color: $primary-content; $button-primary-bg-color: $accent-color; $button-secondary-bg-color: transparent; -$button-danger-fg-color: #ffffff; +$button-danger-fg-color: $primary-content; $button-danger-bg-color: $notice-primary-color; -$button-danger-disabled-fg-color: #ffffff; +$button-danger-disabled-fg-color: $primary-content; $button-danger-disabled-bg-color: #f5b6bb; // TODO: Verify color $button-link-fg-color: $accent-color; $button-link-bg-color: transparent; @@ -178,7 +178,7 @@ $button-link-bg-color: transparent; $togglesw-off-color: $room-highlight-color; $progressbar-fg-color: $accent-color; -$progressbar-bg-color: $system-dark; +$progressbar-bg-color: $system; $visual-bell-bg-color: #800; @@ -201,32 +201,33 @@ $reaction-row-button-selected-border-color: $accent-color; $kbd-border-color: #000000; $tooltip-timeline-bg-color: $groupFilterPanel-bg-color; -$tooltip-timeline-fg-color: #ffffff; +$tooltip-timeline-fg-color: $primary-content; -$interactive-tooltip-bg-color: $base-color; -$interactive-tooltip-fg-color: #ffffff; +$interactive-tooltip-bg-color: $background; +$interactive-tooltip-fg-color: $primary-content; $breadcrumb-placeholder-bg-color: #272c35; $user-tile-hover-bg-color: $header-panel-bg-color; -$message-body-panel-fg-color: $secondary-fg-color; -$message-body-panel-bg-color: #394049; // "Dark Tile" -$message-body-panel-icon-fg-color: $secondary-fg-color; -$message-body-panel-icon-bg-color: $system-dark; // "System Dark" +$message-body-panel-fg-color: $secondary-content; +$message-body-panel-bg-color: $quinary-content; +$message-body-panel-icon-bg-color: $system; +$message-body-panel-icon-fg-color: $secondary-content; -$voice-record-stop-border-color: $quaternary-fg-color; -$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; -$voice-record-icon-color: $quaternary-fg-color; +$voice-record-stop-border-color: $quaternary-content; +$voice-record-waveform-incomplete-fg-color: $quaternary-content; +$voice-record-icon-color: $quaternary-content; $voice-playback-button-bg-color: $message-body-panel-icon-bg-color; $voice-playback-button-fg-color: $message-body-panel-icon-fg-color; // Appearance tab colors $appearance-tab-border-color: $room-highlight-color; -// blur amounts for left left panel (only for element theme, used in _mods.scss) -$roomlist-background-blur-amount: 60px; -$groupFilterPanel-background-blur-amount: 30px; +// blur amounts for left left panel (only for element theme) +:root { + --lp-background-blur: 45px; +} $composer-shadow-color: rgba(0, 0, 0, 0.28); @@ -234,7 +235,7 @@ $composer-shadow-color: rgba(0, 0, 0, 0.28); $eventbubble-self-bg: #14322E; $eventbubble-others-bg: $event-selected-color; $eventbubble-bg-hover: #1C2026; -$eventbubble-avatar-outline: $bg-color; +$eventbubble-avatar-outline: $background; $eventbubble-reply-color: #C1C6CD; // ***** Mixins! ***** diff --git a/res/themes/dark/css/dark.scss b/res/themes/dark/css/dark.scss index 600cfd528a..df83d6db88 100644 --- a/res/themes/dark/css/dark.scss +++ b/res/themes/dark/css/dark.scss @@ -2,10 +2,6 @@ @import "../../light/css/_paths.scss"; @import "../../light/css/_fonts.scss"; @import "../../light/css/_light.scss"; -// important this goes before _mods, -// as $groupFilterPanel-background-blur-amount and -// $roomlist-background-blur-amount -// are overridden in _dark.scss @import "_dark.scss"; @import "../../light/css/_mods.scss"; @import "../../../../res/css/_components.scss"; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 064b532bb0..d5bc5e6dd7 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -1,3 +1,6 @@ +// Colors from Figma Compound https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=559%3A741 +$system: #21262C; + // unified palette // try to use these colors when possible $bg-color: #181b21; @@ -21,7 +24,12 @@ $primary-bg-color: $bg-color; $muted-fg-color: $header-panel-text-primary-color; // Legacy theme backports -$quaternary-fg-color: #6F7882; +$primary-content: $primary-fg-color; +$secondary-content: $secondary-fg-color; +$tertiary-content: $tertiary-fg-color; +$quaternary-content: #6F7882; +$quinary-content: $quaternary-content; +$background: $primary-bg-color; // used for dialog box text $light-fg-color: $header-panel-text-secondary-color; @@ -111,13 +119,9 @@ $eventtile-meta-color: $roomtopic-color; $header-divider-color: $header-panel-text-primary-color; $composer-e2e-icon-color: $header-panel-text-primary-color; -$quinary-content-color: #394049; -$toast-bg-color: $quinary-content-color; - // ******************** $theme-button-bg-color: #e3e8f0; -$dialpad-button-bg-color: #6F7882; $roomlist-button-bg-color: #1A1D23; // Buttons include the filter box, explore button, and sublist buttons @@ -222,6 +226,13 @@ $appearance-tab-border-color: $room-highlight-color; $composer-shadow-color: tranparent; +// Bubble tiles +$eventbubble-self-bg: #14322E; +$eventbubble-others-bg: $event-selected-color; +$eventbubble-bg-hover: #1C2026; +$eventbubble-avatar-outline: $bg-color; +$eventbubble-reply-color: #C1C6CD; + // ***** Mixins! ***** @define-mixin mx_DialogButton { diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index 1a63c9bd07..47247e5e23 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -13,7 +13,7 @@ $font-family: 'Nunito', 'Twemoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Arial $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; +$system: #F4F6FA; // unified palette // try to use these colors when possible @@ -32,7 +32,12 @@ $primary-bg-color: #ffffff; $muted-fg-color: #61708b; // Commonly used in headings and relevant alt text // Legacy theme backports -$quaternary-fg-color: #C1C6CD; +$primary-content: $primary-fg-color; +$secondary-content: $secondary-fg-color; +$tertiary-content: $tertiary-fg-color; +$quaternary-content: #C1C6CD; +$quinary-content: #e3e8f0; +$background: $primary-bg-color; // used for dialog box text $light-fg-color: #747474; @@ -181,14 +186,11 @@ $eventtile-meta-color: $roomtopic-color; $composer-e2e-icon-color: #91a1c0; $header-divider-color: #91a1c0; -$toast-bg-color: $system-light; -$voipcall-plinth-color: $system-light; +$voipcall-plinth-color: $system; // ******************** $theme-button-bg-color: #e3e8f0; -$dialpad-button-bg-color: #e3e8f0; - $roomlist-button-bg-color: #fff; // Buttons include the filter box, explore button, and sublist buttons $roomlist-filter-active-bg-color: $roomlist-button-bg-color; @@ -334,7 +336,7 @@ $user-tile-hover-bg-color: $header-panel-bg-color; $message-body-panel-fg-color: $secondary-fg-color; $message-body-panel-bg-color: #E3E8F0; $message-body-panel-icon-fg-color: $secondary-fg-color; -$message-body-panel-icon-bg-color: $system-light; +$message-body-panel-icon-bg-color: $system; // See non-legacy _light for variable information $voice-record-stop-symbol-color: #ff4b55; @@ -352,7 +354,7 @@ $composer-shadow-color: tranparent; // Bubble tiles $eventbubble-self-bg: #F0FBF8; -$eventbubble-others-bg: $system-light; +$eventbubble-others-bg: $system; $eventbubble-bg-hover: #FAFBFD; $eventbubble-avatar-outline: #fff; $eventbubble-reply-color: #C1C6CD; diff --git a/res/themes/light-custom/css/_custom.scss b/res/themes/light-custom/css/_custom.scss index 1b9254d100..f4685fe8fa 100644 --- a/res/themes/light-custom/css/_custom.scss +++ b/res/themes/light-custom/css/_custom.scss @@ -38,7 +38,7 @@ $lightbox-border-color: var(--timeline-background-color); $menu-bg-color: var(--timeline-background-color); $avatar-bg-color: var(--timeline-background-color); $message-action-bar-bg-color: var(--timeline-background-color); -$primary-bg-color: var(--timeline-background-color); +$background: var(--timeline-background-color); $togglesw-ball-color: var(--timeline-background-color); $droptarget-bg-color: var(--timeline-background-color-50pct); //still needs alpha at .5 $authpage-modal-bg-color: var(--timeline-background-color-50pct); //still needs alpha at .59 @@ -69,7 +69,7 @@ $roomlist-bg-color: var(--roomlist-background-color); // // --timeline-text-color $message-action-bar-fg-color: var(--timeline-text-color); -$primary-fg-color: var(--timeline-text-color); +$primary-content: var(--timeline-text-color); $settings-profile-overlay-placeholder-fg-color: var(--timeline-text-color); $roomtopic-color: var(--timeline-text-color-50pct); $tab-label-fg-color: var(--timeline-text-color); @@ -139,4 +139,11 @@ $event-selected-color: var(--timeline-highlights-color); $event-highlight-bg-color: var(--timeline-highlights-color); // // redirect some variables away from their hardcoded values in the light theme -$settings-grey-fg-color: $primary-fg-color; +$settings-grey-fg-color: $primary-content; + +// --eventbubble colors +$eventbubble-self-bg: var(--eventbubble-self-bg, $eventbubble-self-bg); +$eventbubble-others-bg: var(--eventbubble-others-bg, $eventbubble-others-bg); +$eventbubble-bg-hover: var(--eventbubble-bg-hover, $eventbubble-bg-hover); +$eventbubble-avatar-outline: var(--eventbubble-avatar-outline, $eventbubble-avatar-outline); +$eventbubble-reply-color: var(--eventbubble-reply-color, $eventbubble-reply-color); diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index eff9abe5af..200d5bb12a 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -12,23 +12,34 @@ $font-family: 'Inter', 'Twemoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Arial' $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; +// Colors from Figma Compound https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=559%3A120 +$accent: #0DBD8B; +$alert: #FF5B55; +$links: #0086e6; +$primary-content: #17191C; +$secondary-content: #737D8C; +$tertiary-content: #8D97A5; +$quaternary-content: #c1c6cd; +$quinary-content: #E3E8F0; +$system: #F4F6FA; +$background: #ffffff; +$panels: rgba($system, 0.9); +$panel-selected: rgba($tertiary-content, 0.3); +$panel-hover: rgba($tertiary-content, 0.1); +$panel-actions: rgba($tertiary-content, 0.2); +$space-nav: rgba($tertiary-content, 0.15); + +// TODO: Move userId colors here // unified palette // try to use these colors when possible -$accent-color: #0DBD8B; +$accent-color: $accent; $accent-bg-color: rgba(3, 179, 129, 0.16); $notice-primary-color: #ff4b55; $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) -$primary-bg-color: #ffffff; $muted-fg-color: #61708b; // Commonly used in headings and relevant alt text // used for dialog box text @@ -38,12 +49,12 @@ $light-fg-color: #747474; $focus-bg-color: #dddddd; // button UI (white-on-green in light skin) -$accent-fg-color: #ffffff; +$accent-fg-color: $background; $accent-color-50pct: rgba($accent-color, 0.5); $accent-color-darker: #92caad; $accent-color-alt: #238CF5; -$selection-fg-color: $primary-bg-color; +$selection-fg-color: $background; $focus-brightness: 105%; @@ -82,7 +93,7 @@ $primary-hairline-color: transparent; // used for the border of input text fields $input-border-color: #e7e7e7; -$input-darker-bg-color: #e3e8f0; +$input-darker-bg-color: $quinary-content; $input-darker-fg-color: #9fa9ba; $input-lighter-bg-color: #f2f5f8; $input-lighter-fg-color: $input-darker-fg-color; @@ -90,7 +101,7 @@ $input-focused-border-color: #238cf5; $input-valid-border-color: $accent-color; $input-invalid-border-color: $warning-color; -$field-focused-label-bg-color: #ffffff; +$field-focused-label-bg-color: $background; $button-bg-color: $accent-color; $button-fg-color: white; @@ -112,8 +123,8 @@ $menu-bg-color: #fff; $menu-box-shadow-color: rgba(118, 131, 156, 0.6); $menu-selected-color: #f5f8fa; -$avatar-initial-color: #ffffff; -$avatar-bg-color: #ffffff; +$avatar-initial-color: $background; +$avatar-bg-color: $background; $h3-color: #3d3b39; @@ -141,7 +152,7 @@ $blockquote-bar-color: #ddd; $blockquote-fg-color: #777; $settings-grey-fg-color: #a2a2a2; -$settings-profile-placeholder-bg-color: $system-light; +$settings-profile-placeholder-bg-color: $system; $settings-profile-overlay-placeholder-fg-color: #2e2f32; $settings-profile-button-bg-color: #e7e7e7; $settings-profile-button-fg-color: $settings-profile-overlay-placeholder-fg-color; @@ -157,44 +168,39 @@ $rte-group-pill-color: #aaa; $topleftmenu-color: #212121; $roomheader-color: #45474a; -$roomheader-bg-color: $primary-bg-color; $roomheader-addroom-bg-color: rgba(92, 100, 112, 0.2); $roomheader-addroom-fg-color: #5c6470; $groupFilterPanel-button-color: #91A1C0; $groupheader-button-color: #91A1C0; $rightpanel-button-color: #91A1C0; -$icon-button-color: #C1C6CD; +$icon-button-color: $quaternary-content; $roomtopic-color: #9e9e9e; $eventtile-meta-color: $roomtopic-color; $composer-e2e-icon-color: #91A1C0; $header-divider-color: #91A1C0; -$toast-bg-color: $system-light; -$voipcall-plinth-color: $system-light; +$voipcall-plinth-color: $system; // ******************** -$theme-button-bg-color: #e3e8f0; -$dialpad-button-bg-color: #e3e8f0; - +$theme-button-bg-color: $quinary-content; $roomlist-button-bg-color: rgba(141, 151, 165, 0.2); // Buttons include the filter box, explore button, and sublist buttons -$roomlist-filter-active-bg-color: #ffffff; $roomlist-bg-color: rgba(245, 245, 245, 0.90); -$roomlist-header-color: $tertiary-fg-color; -$roomsublist-divider-color: $primary-fg-color; +$roomlist-header-color: $tertiary-content; +$roomsublist-divider-color: $primary-content; $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%); $groupFilterPanel-divider-color: $roomlist-header-color; -$roomtile-preview-color: $secondary-fg-color; +$roomtile-preview-color: $secondary-content; $roomtile-default-badge-bg-color: #61708b; $roomtile-selected-bg-color: #FFF; $presence-online: $accent-color; $presence-away: #d9b072; -$presence-offline: #E3E8F0; +$presence-offline: $quinary-content; // ******************** @@ -257,7 +263,7 @@ $lightbox-border-color: #ffffff; // Tabbed views $tab-label-fg-color: #45474a; -$tab-label-active-fg-color: #ffffff; +$tab-label-active-fg-color: $background; $tab-label-bg-color: transparent; $tab-label-active-bg-color: $accent-color; $tab-label-icon-bg-color: #454545; @@ -267,9 +273,9 @@ $tab-label-active-icon-bg-color: $tab-label-active-fg-color; $button-primary-fg-color: #ffffff; $button-primary-bg-color: $accent-color; $button-secondary-bg-color: $accent-fg-color; -$button-danger-fg-color: #ffffff; +$button-danger-fg-color: $background; $button-danger-bg-color: $notice-primary-color; -$button-danger-disabled-fg-color: #ffffff; +$button-danger-disabled-fg-color: $background; $button-danger-disabled-bg-color: #f5b6bb; // TODO: Verify color $button-link-fg-color: $accent-color; $button-link-bg-color: transparent; @@ -294,7 +300,7 @@ $memberstatus-placeholder-color: $muted-fg-color; $authpage-bg-color: #2e3649; $authpage-modal-bg-color: rgba(245, 245, 245, 0.90); -$authpage-body-bg-color: #ffffff; +$authpage-body-bg-color: $background; $authpage-focus-bg-color: #dddddd; $authpage-lang-color: #4e5054; $authpage-primary-color: #232f32; @@ -303,8 +309,8 @@ $authpage-secondary-color: #61708b; $dark-panel-bg-color: $secondary-accent-color; $panel-gradient: rgba(242, 245, 248, 0), rgba(242, 245, 248, 1); -$message-action-bar-bg-color: $primary-bg-color; -$message-action-bar-fg-color: $primary-fg-color; +$message-action-bar-bg-color: $background; +$message-action-bar-fg-color: $primary-content; $message-action-bar-border-color: #e9edf1; $message-action-bar-hover-border-color: $focus-bg-color; @@ -318,46 +324,46 @@ $kbd-border-color: $reaction-row-button-border-color; $inverted-bg-color: #27303a; $tooltip-timeline-bg-color: $inverted-bg-color; -$tooltip-timeline-fg-color: #ffffff; +$tooltip-timeline-fg-color: $background; $interactive-tooltip-bg-color: #27303a; -$interactive-tooltip-fg-color: #ffffff; +$interactive-tooltip-fg-color: $background; $breadcrumb-placeholder-bg-color: #e8eef5; $user-tile-hover-bg-color: $header-panel-bg-color; -$message-body-panel-fg-color: $secondary-fg-color; -$message-body-panel-bg-color: #E3E8F0; // "Separator" -$message-body-panel-icon-fg-color: $secondary-fg-color; -$message-body-panel-icon-bg-color: $system-light; +$message-body-panel-fg-color: $secondary-content; +$message-body-panel-bg-color: $quinary-content; +$message-body-panel-icon-bg-color: $system; +$message-body-panel-icon-fg-color: $secondary-content; // 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-incomplete-fg-color: $quaternary-fg-color; -$voice-record-icon-color: $tertiary-fg-color; +$voice-record-stop-border-color: $quinary-content; +$voice-record-waveform-incomplete-fg-color: $quaternary-content; +$voice-record-icon-color: $tertiary-content; $voice-playback-button-bg-color: $message-body-panel-icon-bg-color; $voice-playback-button-fg-color: $message-body-panel-icon-fg-color; // FontSlider colors $appearance-tab-border-color: $input-darker-bg-color; -// blur amounts for left left panel (only for element theme, used in _mods.scss) -$roomlist-background-blur-amount: 40px; -$groupFilterPanel-background-blur-amount: 20px; - +// blur amounts for left left panel (only for element theme) +:root { + --lp-background-blur: 30px; +} $composer-shadow-color: rgba(0, 0, 0, 0.04); // Bubble tiles $eventbubble-self-bg: #F0FBF8; -$eventbubble-others-bg: $system-light; +$eventbubble-others-bg: $system; $eventbubble-bg-hover: #FAFBFD; -$eventbubble-avatar-outline: $primary-bg-color; -$eventbubble-reply-color: #C1C6CD; +$eventbubble-avatar-outline: $background; +$eventbubble-reply-color: $quaternary-content; // ***** Mixins! ***** diff --git a/res/themes/light/css/_mods.scss b/res/themes/light/css/_mods.scss index fbca58dfb1..15f6d4b0fe 100644 --- a/res/themes/light/css/_mods.scss +++ b/res/themes/light/css/_mods.scss @@ -4,27 +4,6 @@ // set the user avatar (if any) as a background so // it can be blurred by the tag panel and room list -@supports (backdrop-filter: none) { - .mx_LeftPanel { - background-image: var(--avatar-url, unset); - background-repeat: no-repeat; - background-size: cover; - background-position: left top; - } - - .mx_GroupFilterPanel { - backdrop-filter: blur($groupFilterPanel-background-blur-amount); - } - - .mx_SpacePanel { - backdrop-filter: blur($groupFilterPanel-background-blur-amount); - } - - .mx_LeftPanel .mx_LeftPanel_roomListContainer { - backdrop-filter: blur($roomlist-background-blur-amount); - } -} - .mx_RoomSublist_showNButton { background-color: transparent !important; } diff --git a/scripts/ci/js-sdk-to-release.sh b/scripts/ci/js-sdk-to-release.sh new file mode 100755 index 0000000000..a03165bd82 --- /dev/null +++ b/scripts/ci/js-sdk-to-release.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# This changes the js-sdk into 'release mode', that is: +# * The entry point for the library is the babel-compiled lib/index.js rather than src/index.ts +# * There's a 'typings' entry referencing the types output by tsc +# We do this so we can test that each PR still builds / type checks correctly when built +# against the released js-sdk, because if you do things like `import { User } from 'matrix-js-sdk';` +# rather than `import { User } from 'matrix-js-sdk/src/models/user';` it will work fine with the +# js-sdk in development mode but then break at release time. +# We can't use the last release of the js-sdk though: it might not be up to date enough. + +cd node_modules/matrix-js-sdk +for i in main typings +do + lib_value=$(jq -r ".matrix_lib_$i" package.json) + if [ "$lib_value" != "null" ]; then + jq ".$i = .matrix_lib_$i" package.json > package.json.new && mv package.json.new package.json + fi +done +yarn run build:compile +yarn run build:types diff --git a/src/ActiveRoomObserver.ts b/src/ActiveRoomObserver.ts index 0be49a24ea..c7423fab8f 100644 --- a/src/ActiveRoomObserver.ts +++ b/src/ActiveRoomObserver.ts @@ -14,8 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import RoomViewStore from './stores/RoomViewStore'; import { EventSubscription } from 'fbemitter'; +import RoomViewStore from './stores/RoomViewStore'; type Listener = (isActive: boolean) => void; diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 77569711df..e11e828864 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -86,7 +86,7 @@ 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 { RuleId, TweakName, Tweaks } from "matrix-js-sdk/src/@types/PushRules"; import { PushProcessor } from 'matrix-js-sdk/src/pushprocessor'; import { WidgetLayoutStore, Container } from './stores/widgets/WidgetLayoutStore'; import { getIncomingCallToastKey } from './toasts/IncomingCallToast'; @@ -464,81 +464,7 @@ export default class CallHandler extends EventEmitter { this.removeCallForRoom(mappedRoomId); }); call.on(CallEvent.State, (newState: CallState, oldState: CallState) => { - if (!this.matchesCallForThisRoom(call)) return; - - this.setCallState(call, newState); - - switch (oldState) { - case CallState.Ringing: - this.pause(AudioID.Ring); - break; - case CallState.InviteSent: - this.pause(AudioID.Ringback); - break; - } - - if (newState !== CallState.Ringing) { - this.silencedCalls.delete(call.callId); - } - - switch (newState) { - 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: { - this.play(AudioID.Ringback); - break; - } - case CallState.Ended: { - const hangupReason = call.hangupReason; - Analytics.trackEvent('voip', 'callEnded', 'hangupReason', hangupReason); - this.removeCallForRoom(mappedRoomId); - if (oldState === CallState.InviteSent && call.hangupParty === CallParty.Remote) { - this.play(AudioID.Busy); - let title; - let description; - // TODO: We should either do away with these or figure out a copy for each code (expect user_hangup...) - if (call.hangupReason === CallErrorCode.UserBusy) { - title = _t("User Busy"); - description = _t("The user you called is busy."); - } else if (hangupReason && ![CallErrorCode.UserHangup, "user hangup"].includes(hangupReason)) { - title = _t("Call Failed"); - description = _t("The call could not be established"); - } - - Modal.createTrackedDialog('Call Handler', 'Call Failed', ErrorDialog, { - title, description, - }); - } else if ( - hangupReason === CallErrorCode.AnsweredElsewhere && oldState === CallState.Connecting - ) { - Modal.createTrackedDialog('Call Handler', 'Call Failed', ErrorDialog, { - title: _t("Answered Elsewhere"), - description: _t("The call was answered on another device."), - }); - } else if (oldState !== CallState.Fledgling && oldState !== CallState.Ringing) { - // don't play the end-call sound for calls that never got off the ground - this.play(AudioID.CallEnd); - } - - this.logCallStats(call, mappedRoomId); - break; - } - } + this.onCallStateChanged(newState, oldState, call); }); call.on(CallEvent.Replaced, (newCall: MatrixCall) => { if (!this.matchesCallForThisRoom(call)) return; @@ -594,6 +520,89 @@ export default class CallHandler extends EventEmitter { }); } + private onCallStateChanged = (newState: CallState, oldState: CallState, call: MatrixCall): void => { + if (!this.matchesCallForThisRoom(call)) return; + + const mappedRoomId = this.roomIdForCall(call); + this.setCallState(call, newState); + + switch (oldState) { + case CallState.Ringing: + this.pause(AudioID.Ring); + break; + case CallState.InviteSent: + this.pause(AudioID.Ringback); + break; + } + + if (newState !== CallState.Ringing) { + this.silencedCalls.delete(call.callId); + } + + switch (newState) { + case CallState.Ringing: { + const incomingCallPushRule = ( + new PushProcessor(MatrixClientPeg.get()).getPushRuleById(RuleId.IncomingCall) + ); + 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: { + this.play(AudioID.Ringback); + break; + } + case CallState.Ended: { + const hangupReason = call.hangupReason; + Analytics.trackEvent('voip', 'callEnded', 'hangupReason', hangupReason); + this.removeCallForRoom(mappedRoomId); + if (oldState === CallState.InviteSent && call.hangupParty === CallParty.Remote) { + this.play(AudioID.Busy); + + // Don't show a modal when we got rejected/the call was hung up + if (!hangupReason || [CallErrorCode.UserHangup, "user hangup"].includes(hangupReason)) break; + + let title; + let description; + // TODO: We should either do away with these or figure out a copy for each code (expect user_hangup...) + if (call.hangupReason === CallErrorCode.UserBusy) { + title = _t("User Busy"); + description = _t("The user you called is busy."); + } else { + title = _t("Call Failed"); + description = _t("The call could not be established"); + } + + Modal.createTrackedDialog('Call Handler', 'Call Failed', ErrorDialog, { + title, description, + }); + } else if ( + hangupReason === CallErrorCode.AnsweredElsewhere && oldState === CallState.Connecting + ) { + Modal.createTrackedDialog('Call Handler', 'Call Failed', ErrorDialog, { + title: _t("Answered Elsewhere"), + description: _t("The call was answered on another device."), + }); + } else if (oldState !== CallState.Fledgling && oldState !== CallState.Ringing) { + // don't play the end-call sound for calls that never got off the ground + this.play(AudioID.CallEnd); + } + + this.logCallStats(call, mappedRoomId); + break; + } + } + }; + private async logCallStats(call: MatrixCall, mappedRoomId: string) { const stats = await call.getCurrentCallStats(); logger.debug( @@ -857,6 +866,8 @@ export default class CallHandler extends EventEmitter { this.calls.set(mappedRoomId, call); this.emit(CallHandlerEvent.CallsChanged, this.calls); this.setCallListeners(call); + // Explicitly handle first state change + this.onCallStateChanged(call.state, null, call); // get ready to send encrypted events in the room, so if the user does answer // the call, we'll be ready to send. NB. This is the protocol-level room ID not diff --git a/src/ContentMessages.tsx b/src/ContentMessages.tsx index c5bcb226ff..14a0c1ed51 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,33 @@ 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) { 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; + const imageElement = await loadImageElement(imageFile); + + 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 ( + 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)) + ) { + delete imageInfo["thumbnail_info"]; return imageInfo; - }); + } + + const uploadResult = await uploadFile(matrixClient, roomId, result.thumbnail); + + imageInfo["thumbnail_url"] = uploadResult.url; + imageInfo["thumbnail_file"] = uploadResult.file; + return imageInfo; } /** diff --git a/src/DateUtils.ts b/src/DateUtils.ts index e4a1175d88..e8b81ca315 100644 --- a/src/DateUtils.ts +++ b/src/DateUtils.ts @@ -123,6 +123,19 @@ export function formatTime(date: Date, showTwelveHour = false): string { return pad(date.getHours()) + ':' + pad(date.getMinutes()); } +export function formatCallTime(delta: Date): string { + const hours = delta.getUTCHours(); + const minutes = delta.getUTCMinutes(); + const seconds = delta.getUTCSeconds(); + + let output = ""; + if (hours) output += `${hours}h `; + if (minutes || output) output += `${minutes}m `; + if (seconds || output) output += `${seconds}s`; + + return output; +} + const MILLIS_IN_DAY = 86400000; export function wantsDateSeparator(prevEventDate: Date, nextEventDate: Date): boolean { if (!nextEventDate || !prevEventDate) { diff --git a/src/KeyBindingsDefaults.ts b/src/KeyBindingsDefaults.ts index b2f70abff7..6169f431f4 100644 --- a/src/KeyBindingsDefaults.ts +++ b/src/KeyBindingsDefaults.ts @@ -161,31 +161,29 @@ const messageComposerBindings = (): KeyBinding[] => { const autocompleteBindings = (): KeyBinding[] => { return [ { - action: AutocompleteAction.CompleteOrNextSelection, + action: AutocompleteAction.ForceComplete, keyCombo: { key: Key.TAB, }, }, { - action: AutocompleteAction.CompleteOrNextSelection, + action: AutocompleteAction.ForceComplete, keyCombo: { key: Key.TAB, ctrlKey: true, }, }, { - action: AutocompleteAction.CompleteOrPrevSelection, + action: AutocompleteAction.Complete, keyCombo: { - key: Key.TAB, - shiftKey: true, + key: Key.ENTER, }, }, { - action: AutocompleteAction.CompleteOrPrevSelection, + action: AutocompleteAction.Complete, keyCombo: { - key: Key.TAB, + key: Key.ENTER, ctrlKey: true, - shiftKey: true, }, }, { diff --git a/src/KeyBindingsManager.ts b/src/KeyBindingsManager.ts index 4225d2f449..3a893e2ec8 100644 --- a/src/KeyBindingsManager.ts +++ b/src/KeyBindingsManager.ts @@ -52,13 +52,11 @@ export enum MessageComposerAction { /** Actions for text editing autocompletion */ export enum AutocompleteAction { - /** - * Select previous selection or, if the autocompletion window is not shown, open the window and select the first - * selection. - */ - CompleteOrPrevSelection = 'ApplySelection', - /** Select next selection or, if the autocompletion window is not shown, open it and select the first selection */ - CompleteOrNextSelection = 'CompleteOrNextSelection', + /** Accepts chosen autocomplete selection */ + Complete = 'Complete', + /** Accepts chosen autocomplete selection or, + * if the autocompletion window is not shown, open the window and select the first selection */ + ForceComplete = 'ForceComplete', /** Move to the previous autocomplete selection */ PrevSelection = 'PrevSelection', /** Move to the next autocomplete selection */ diff --git a/src/PasswordReset.js b/src/PasswordReset.ts similarity index 89% rename from src/PasswordReset.js rename to src/PasswordReset.ts index 88ae00d088..76f54de245 100644 --- a/src/PasswordReset.js +++ b/src/PasswordReset.ts @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { createClient } from 'matrix-js-sdk/src/matrix'; +import { createClient, IRequestTokenResponse, MatrixClient } from 'matrix-js-sdk/src/matrix'; import { _t } from './languageHandler'; /** @@ -26,12 +26,18 @@ import { _t } from './languageHandler'; * API on the homeserver in question with the new password. */ export default class PasswordReset { + private client: MatrixClient; + private clientSecret: string; + private identityServerDomain: string; + private password: string; + private sessionId: string; + /** * Configure the endpoints for password resetting. * @param {string} homeserverUrl The URL to the HS which has the account to reset. * @param {string} identityUrl The URL to the IS which has linked the email -> mxid mapping. */ - constructor(homeserverUrl, identityUrl) { + constructor(homeserverUrl: string, identityUrl: string) { this.client = createClient({ baseUrl: homeserverUrl, idBaseUrl: identityUrl, @@ -47,7 +53,7 @@ export default class PasswordReset { * @param {string} newPassword The new password for the account. * @return {Promise} Resolves when the email has been sent. Then call checkEmailLinkClicked(). */ - resetPassword(emailAddress, newPassword) { + public resetPassword(emailAddress: string, newPassword: string): Promise { this.password = newPassword; return this.client.requestPasswordEmailToken(emailAddress, this.clientSecret, 1).then((res) => { this.sessionId = res.sid; @@ -69,7 +75,7 @@ export default class PasswordReset { * with a "message" property which contains a human-readable message detailing why * the reset failed, e.g. "There is no mapped matrix user ID for the given email address". */ - async checkEmailLinkClicked() { + public async checkEmailLinkClicked(): Promise { const creds = { sid: this.sessionId, client_secret: this.clientSecret, diff --git a/src/accessibility/RovingTabIndex.tsx b/src/accessibility/RovingTabIndex.tsx index 87f525bdfc..68e10049fd 100644 --- a/src/accessibility/RovingTabIndex.tsx +++ b/src/accessibility/RovingTabIndex.tsx @@ -150,13 +150,14 @@ const reducer = (state: IState, action: IAction) => { interface IProps { handleHomeEnd?: boolean; + handleUpDown?: boolean; children(renderProps: { onKeyDownHandler(ev: React.KeyboardEvent); }); onKeyDown?(ev: React.KeyboardEvent, state: IState); } -export const RovingTabIndexProvider: React.FC = ({ children, handleHomeEnd, onKeyDown }) => { +export const RovingTabIndexProvider: React.FC = ({ children, handleHomeEnd, handleUpDown, onKeyDown }) => { const [state, dispatch] = useReducer>(reducer, { activeRef: null, refs: [], @@ -167,21 +168,50 @@ export const RovingTabIndexProvider: React.FC = ({ children, handleHomeE const onKeyDownHandler = useCallback((ev) => { let handled = false; // Don't interfere with input default keydown behaviour - if (handleHomeEnd && ev.target.tagName !== "INPUT" && ev.target.tagName !== "TEXTAREA") { + if (ev.target.tagName !== "INPUT" && ev.target.tagName !== "TEXTAREA") { // check if we actually have any items switch (ev.key) { case Key.HOME: - handled = true; - // move focus to first item - if (context.state.refs.length > 0) { - context.state.refs[0].current.focus(); + if (handleHomeEnd) { + handled = true; + // move focus to first item + if (context.state.refs.length > 0) { + context.state.refs[0].current.focus(); + } } break; + case Key.END: - handled = true; - // move focus to last item - if (context.state.refs.length > 0) { - context.state.refs[context.state.refs.length - 1].current.focus(); + if (handleHomeEnd) { + handled = true; + // move focus to last item + if (context.state.refs.length > 0) { + context.state.refs[context.state.refs.length - 1].current.focus(); + } + } + break; + + case Key.ARROW_UP: + if (handleUpDown) { + handled = true; + if (context.state.refs.length > 0) { + const idx = context.state.refs.indexOf(context.state.activeRef); + if (idx > 0) { + context.state.refs[idx - 1].current.focus(); + } + } + } + break; + + case Key.ARROW_DOWN: + if (handleUpDown) { + handled = true; + if (context.state.refs.length > 0) { + const idx = context.state.refs.indexOf(context.state.activeRef); + if (idx < context.state.refs.length - 1) { + context.state.refs[idx + 1].current.focus(); + } + } } break; } @@ -193,7 +223,7 @@ export const RovingTabIndexProvider: React.FC = ({ children, handleHomeE } else if (onKeyDown) { return onKeyDown(ev, context.state); } - }, [context.state, onKeyDown, handleHomeEnd]); + }, [context.state, onKeyDown, handleHomeEnd, handleUpDown]); return { children({ onKeyDownHandler }) } 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/autocomplete/AutocompleteProvider.tsx b/src/autocomplete/AutocompleteProvider.tsx index 51ab2e2cf7..2d82a9f591 100644 --- a/src/autocomplete/AutocompleteProvider.tsx +++ b/src/autocomplete/AutocompleteProvider.tsx @@ -27,11 +27,11 @@ export interface ICommand { }; } -export default class AutocompleteProvider { +export default abstract class AutocompleteProvider { commandRegex: RegExp; forcedCommandRegex: RegExp; - constructor(commandRegex?: RegExp, forcedCommandRegex?: RegExp) { + protected constructor(commandRegex?: RegExp, forcedCommandRegex?: RegExp) { if (commandRegex) { if (!commandRegex.global) { throw new Error('commandRegex must have global flag set'); @@ -93,23 +93,16 @@ export default class AutocompleteProvider { }; } - async getCompletions( + abstract getCompletions( query: string, selection: ISelectionRange, - force = false, - limit = -1, - ): Promise { - return []; - } + force: boolean, + limit: number, + ): Promise; - getName(): string { - return 'Default Provider'; - } + abstract getName(): string; - renderCompletions(completions: React.ReactNode[]): React.ReactNode | null { - console.error('stub; should be implemented in subclasses'); - return null; - } + abstract renderCompletions(completions: React.ReactNode[]): React.ReactNode | null; // Whether we should provide completions even if triggered forcefully, without a sigil. shouldForceComplete(): boolean { diff --git a/src/autocomplete/CommandProvider.tsx b/src/autocomplete/CommandProvider.tsx index e9a7742dee..d0fb9919f6 100644 --- a/src/autocomplete/CommandProvider.tsx +++ b/src/autocomplete/CommandProvider.tsx @@ -95,8 +95,8 @@ export default class CommandProvider extends AutocompleteProvider { renderCompletions(completions: React.ReactNode[]): React.ReactNode { return (
{ completions } diff --git a/src/autocomplete/CommunityProvider.tsx b/src/autocomplete/CommunityProvider.tsx index de99675b4b..4b42f4c64e 100644 --- a/src/autocomplete/CommunityProvider.tsx +++ b/src/autocomplete/CommunityProvider.tsx @@ -116,7 +116,7 @@ export default class CommunityProvider extends AutocompleteProvider { return (
{ completions } diff --git a/src/autocomplete/DuckDuckGoProvider.tsx b/src/autocomplete/DuckDuckGoProvider.tsx index 08750493d3..c41a91b97f 100644 --- a/src/autocomplete/DuckDuckGoProvider.tsx +++ b/src/autocomplete/DuckDuckGoProvider.tsx @@ -105,7 +105,7 @@ export default class DuckDuckGoProvider extends AutocompleteProvider { return (
{ completions } diff --git a/src/autocomplete/EmojiProvider.tsx b/src/autocomplete/EmojiProvider.tsx index d3175edbdb..326651e037 100644 --- a/src/autocomplete/EmojiProvider.tsx +++ b/src/autocomplete/EmojiProvider.tsx @@ -67,7 +67,7 @@ export default class EmojiProvider extends AutocompleteProvider { constructor() { super(EMOJI_REGEX); this.matcher = new QueryMatcher(SORTED_EMOJI, { - keys: ['emoji.emoticon'], + keys: [], funcs: [o => o.emoji.shortcodes.map(s => `:${s}:`)], // For matching against ascii equivalents shouldMatchWordsOnly: false, @@ -91,7 +91,8 @@ export default class EmojiProvider extends AutocompleteProvider { let completions = []; const { command, range } = this.getCurrentCommand(query, selection); - if (command) { + + if (command && command[0].length > 2) { const matchedString = command[0]; completions = this.matcher.match(matchedString, limit); @@ -139,7 +140,7 @@ export default class EmojiProvider extends AutocompleteProvider { return (
{ completions } diff --git a/src/autocomplete/NotifProvider.tsx b/src/autocomplete/NotifProvider.tsx index 31b834ccfe..aa4f1174dc 100644 --- a/src/autocomplete/NotifProvider.tsx +++ b/src/autocomplete/NotifProvider.tsx @@ -70,7 +70,7 @@ export default class NotifProvider extends AutocompleteProvider { return (
{ completions } diff --git a/src/autocomplete/RoomProvider.tsx b/src/autocomplete/RoomProvider.tsx index 37ddf2c387..00bfe6be5c 100644 --- a/src/autocomplete/RoomProvider.tsx +++ b/src/autocomplete/RoomProvider.tsx @@ -134,7 +134,7 @@ export default class RoomProvider extends AutocompleteProvider { return (
{ completions } diff --git a/src/autocomplete/UserProvider.tsx b/src/autocomplete/UserProvider.tsx index 182743abb3..48854657de 100644 --- a/src/autocomplete/UserProvider.tsx +++ b/src/autocomplete/UserProvider.tsx @@ -181,7 +181,7 @@ export default class UserProvider extends AutocompleteProvider { return (
{ completions } diff --git a/src/components/structures/AutoHideScrollbar.tsx b/src/components/structures/AutoHideScrollbar.tsx index 184d883dda..a60df45770 100644 --- a/src/components/structures/AutoHideScrollbar.tsx +++ b/src/components/structures/AutoHideScrollbar.tsx @@ -61,7 +61,9 @@ export default class AutoHideScrollbar extends React.Component { style={style} className={["mx_AutoHideScrollbar", className].join(" ")} onWheel={onWheel} - tabIndex={tabIndex} + // Firefox sometimes makes this element focusable due to + // overflow:scroll;, so force it out of tab order by default. + tabIndex={tabIndex ?? -1} > { children }
); diff --git a/src/components/structures/BackdropPanel.tsx b/src/components/structures/BackdropPanel.tsx new file mode 100644 index 0000000000..08f6c33738 --- /dev/null +++ b/src/components/structures/BackdropPanel.tsx @@ -0,0 +1,44 @@ +/* +Copyright 2021 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React, { CSSProperties } from "react"; + +interface IProps { + backgroundImage?: string; + blurMultiplier?: number; +} + +export const BackdropPanel: React.FC = ({ backgroundImage, blurMultiplier }) => { + if (!backgroundImage) return null; + + const styles: CSSProperties = {}; + if (blurMultiplier) { + const rootStyle = getComputedStyle(document.documentElement); + const blurValue = rootStyle.getPropertyValue('--lp-background-blur'); + const pixelsValue = blurValue.replace('px', ''); + const parsed = parseInt(pixelsValue, 10); + if (!isNaN(parsed)) { + styles.filter = `blur(${parsed * blurMultiplier}px)`; + } + } + return
+ +
; +}; +export default BackdropPanel; diff --git a/src/components/structures/CallEventGrouper.ts b/src/components/structures/CallEventGrouper.ts index ce3b530858..b48bb32efe 100644 --- a/src/components/structures/CallEventGrouper.ts +++ b/src/components/structures/CallEventGrouper.ts @@ -27,9 +27,15 @@ export enum CallEventGrouperEvent { SilencedChanged = "silenced_changed", } +const CONNECTING_STATES = [ + CallState.Connecting, + CallState.WaitLocalMedia, + CallState.CreateOffer, + CallState.CreateAnswer, +]; + const SUPPORTED_STATES = [ CallState.Connected, - CallState.Connecting, CallState.Ringing, ]; @@ -61,6 +67,10 @@ export default class CallEventGrouper extends EventEmitter { return [...this.events].find((event) => event.getType() === EventType.CallReject); } + private get selectAnswer(): MatrixEvent { + return [...this.events].find((event) => event.getType() === EventType.CallSelectAnswer); + } + public get isVoice(): boolean { const invite = this.invite; if (!invite) return; @@ -82,6 +92,11 @@ export default class CallEventGrouper extends EventEmitter { return Boolean(this.reject); } + public get duration(): Date { + if (!this.hangup || !this.selectAnswer) return; + return new Date(this.hangup.getDate().getTime() - this.selectAnswer.getDate().getTime()); + } + /** * Returns true if there are only events from the other side - we missed the call */ @@ -127,7 +142,9 @@ export default class CallEventGrouper extends EventEmitter { } private setState = () => { - if (SUPPORTED_STATES.includes(this.call?.state)) { + if (CONNECTING_STATES.includes(this.call?.state)) { + this.state = CallState.Connecting; + } else if (SUPPORTED_STATES.includes(this.call?.state)) { this.state = this.call.state; } else { if (this.callWasMissed) this.state = CustomCallState.Missed; diff --git a/src/components/structures/GroupFilterPanel.js b/src/components/structures/GroupFilterPanel.tsx similarity index 71% rename from src/components/structures/GroupFilterPanel.js rename to src/components/structures/GroupFilterPanel.tsx index 5d1be64f25..3e7c6e9b17 100644 --- a/src/components/structures/GroupFilterPanel.js +++ b/src/components/structures/GroupFilterPanel.tsx @@ -15,6 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import type { EventSubscription } from "fbemitter"; import React from 'react'; import GroupFilterOrderStore from '../../stores/GroupFilterOrderStore'; @@ -30,22 +31,43 @@ import AutoHideScrollbar from "./AutoHideScrollbar"; import SettingsStore from "../../settings/SettingsStore"; import UserTagTile from "../views/elements/UserTagTile"; import { replaceableComponent } from "../../utils/replaceableComponent"; +import UIStore from "../../stores/UIStore"; + +interface IGroupFilterPanelProps { + +} + +// FIXME: Properly type this after migrating GroupFilterOrderStore.js to Typescript +type OrderedTagsTemporaryType = Array<{}>; +// FIXME: Properly type this after migrating GroupFilterOrderStore.js to Typescript +type SelectedTagsTemporaryType = Array<{}>; + +interface IGroupFilterPanelState { + // FIXME: Properly type this after migrating GroupFilterOrderStore.js to Typescript + orderedTags: OrderedTagsTemporaryType; + // FIXME: Properly type this after migrating GroupFilterOrderStore.js to Typescript + selectedTags: SelectedTagsTemporaryType; +} @replaceableComponent("structures.GroupFilterPanel") -class GroupFilterPanel extends React.Component { - static contextType = MatrixClientContext; +class GroupFilterPanel extends React.Component { + public static contextType = MatrixClientContext; - state = { + public state = { orderedTags: [], selectedTags: [], }; - componentDidMount() { - this.unmounted = false; - this.context.on("Group.myMembership", this._onGroupMyMembership); - this.context.on("sync", this._onClientSync); + private ref = React.createRef(); + private unmounted = false; + private groupFilterOrderStoreToken?: EventSubscription; - this._groupFilterOrderStoreToken = GroupFilterOrderStore.addListener(() => { + public componentDidMount() { + this.unmounted = false; + this.context.on("Group.myMembership", this.onGroupMyMembership); + this.context.on("sync", this.onClientSync); + + this.groupFilterOrderStoreToken = GroupFilterOrderStore.addListener(() => { if (this.unmounted) { return; } @@ -56,23 +78,25 @@ class GroupFilterPanel extends React.Component { }); // This could be done by anything with a matrix client dis.dispatch(GroupActions.fetchJoinedGroups(this.context)); + UIStore.instance.trackElementDimensions("GroupPanel", this.ref.current); } - componentWillUnmount() { + public componentWillUnmount() { this.unmounted = true; - this.context.removeListener("Group.myMembership", this._onGroupMyMembership); - this.context.removeListener("sync", this._onClientSync); - if (this._groupFilterOrderStoreToken) { - this._groupFilterOrderStoreToken.remove(); + this.context.removeListener("Group.myMembership", this.onGroupMyMembership); + this.context.removeListener("sync", this.onClientSync); + if (this.groupFilterOrderStoreToken) { + this.groupFilterOrderStoreToken.remove(); } + UIStore.instance.stopTrackingElementDimensions("GroupPanel"); } - _onGroupMyMembership = () => { + private onGroupMyMembership = () => { if (this.unmounted) return; dis.dispatch(GroupActions.fetchJoinedGroups(this.context)); }; - _onClientSync = (syncState, prevState) => { + private onClientSync = (syncState, prevState) => { // Consider the client reconnected if there is no error with syncing. // This means the state could be RECONNECTING, SYNCING, PREPARED or CATCHUP. const reconnected = syncState !== "ERROR" && prevState !== syncState; @@ -82,18 +106,18 @@ class GroupFilterPanel extends React.Component { } }; - onClick = e => { + private onClick = e => { // only dispatch if its not a no-op if (this.state.selectedTags.length > 0) { dis.dispatch({ action: 'deselect_tags' }); } }; - onClearFilterClick = ev => { + private onClearFilterClick = ev => { dis.dispatch({ action: 'deselect_tags' }); }; - renderGlobalIcon() { + private renderGlobalIcon() { if (!SettingsStore.getValue("feature_communities_v2_prototypes")) return null; return ( @@ -104,7 +128,7 @@ class GroupFilterPanel extends React.Component { ); } - render() { + public render() { const DNDTagTile = sdk.getComponent('elements.DNDTagTile'); const ActionButton = sdk.getComponent('elements.ActionButton'); @@ -147,7 +171,7 @@ class GroupFilterPanel extends React.Component { ); } - return
+ return
HTML for your community's page @@ -399,6 +402,8 @@ class FeaturedUser extends React.Component { const GROUP_JOINPOLICY_OPEN = "open"; const GROUP_JOINPOLICY_INVITE = "invite"; +const UPGRADE_NOTICE_LS_KEY = "mx_hide_community_upgrade_notice"; + @replaceableComponent("structures.GroupView") export default class GroupView extends React.Component { static propTypes = { @@ -422,6 +427,7 @@ export default class GroupView extends React.Component { publicityBusy: false, inviterProfile: null, showRightPanel: RightPanelStore.getSharedInstance().isOpenForGroup, + showUpgradeNotice: !localStorage.getItem(UPGRADE_NOTICE_LS_KEY), }; componentDidMount() { @@ -807,6 +813,22 @@ export default class GroupView extends React.Component { showGroupAddRoomDialog(this.props.groupId); }; + _dismissUpgradeNotice = () => { + localStorage.setItem(UPGRADE_NOTICE_LS_KEY, "true"); + this.setState({ showUpgradeNotice: false }); + } + + _onCreateSpaceClick = () => { + createSpaceFromCommunity(this._matrixClient, this.props.groupId); + }; + + _onAdminsLinkClick = () => { + dis.dispatch({ + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.GroupMemberList, + }); + }; + _getGroupSection() { const groupSettingsSectionClasses = classnames({ "mx_GroupView_group": this.state.editing, @@ -843,10 +865,46 @@ export default class GroupView extends React.Component { }, ) }
:
; + + let communitiesUpgradeNotice; + if (this.state.showUpgradeNotice) { + let text; + if (this.state.isUserPrivileged) { + text = _t("You can create a Space from this community here.", {}, { + a: sub => + { sub } + , + }); + } else { + text = _t("Ask the admins of this community to make it into a Space " + + "and keep a look out for the invite.", {}, { + a: sub => + { sub } + , + }); + } + + communitiesUpgradeNotice =
+

{ _t("Communities can now be made into Spaces") }

+

+ { _t("Spaces are a new way to make a community, with new features coming.") } +   + { text } +   + { _t("Communities won't receive further updates.") } +

+ +
; + } + return
{ header } { hostingSignup } { changeDelayWarning } + { communitiesUpgradeNotice } { this._getJoinableNode() } { this._getLongDescriptionNode() } { this._getRoomsNode() } diff --git a/src/components/structures/InteractiveAuth.js b/src/components/structures/InteractiveAuth.js deleted file mode 100644 index 61ae1882df..0000000000 --- a/src/components/structures/InteractiveAuth.js +++ /dev/null @@ -1,300 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd. -Copyright 2019, 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import { InteractiveAuth } from "matrix-js-sdk/src/interactive-auth"; -import React, { createRef } from 'react'; -import PropTypes from 'prop-types'; - -import getEntryComponentForLoginType from '../views/auth/InteractiveAuthEntryComponents'; - -import * as sdk from '../../index'; -import { replaceableComponent } from "../../utils/replaceableComponent"; - -export const ERROR_USER_CANCELLED = new Error("User cancelled auth session"); - -@replaceableComponent("structures.InteractiveAuthComponent") -export default class InteractiveAuthComponent extends React.Component { - static propTypes = { - // matrix client to use for UI auth requests - matrixClient: PropTypes.object.isRequired, - - // response from initial request. If not supplied, will do a request on - // mount. - authData: PropTypes.shape({ - flows: PropTypes.array, - params: PropTypes.object, - session: PropTypes.string, - }), - - // callback - makeRequest: PropTypes.func.isRequired, - - // callback called when the auth process has finished, - // successfully or unsuccessfully. - // @param {bool} status True if the operation requiring - // auth was completed sucessfully, false if canceled. - // @param {object} result The result of the authenticated call - // if successful, otherwise the error object. - // @param {object} extra Additional information about the UI Auth - // process: - // * emailSid {string} If email auth was performed, the sid of - // the auth session. - // * clientSecret {string} The client secret used in auth - // sessions with the identity server. - onAuthFinished: PropTypes.func.isRequired, - - // Inputs provided by the user to the auth process - // and used by various stages. As passed to js-sdk - // interactive-auth - inputs: PropTypes.object, - - // As js-sdk interactive-auth - requestEmailToken: PropTypes.func, - sessionId: PropTypes.string, - clientSecret: PropTypes.string, - emailSid: PropTypes.string, - - // If true, poll to see if the auth flow has been completed - // out-of-band - poll: PropTypes.bool, - - // If true, components will be told that the 'Continue' button - // is managed by some other party and should not be managed by - // the component itself. - continueIsManaged: PropTypes.bool, - - // Called when the stage changes, or the stage's phase changes. First - // argument is the stage, second is the phase. Some stages do not have - // phases and will be counted as 0 (numeric). - onStagePhaseChange: PropTypes.func, - - // continueText and continueKind are passed straight through to the AuthEntryComponent. - continueText: PropTypes.string, - continueKind: PropTypes.string, - }; - - constructor(props) { - super(props); - - this.state = { - authStage: null, - busy: false, - errorText: null, - stageErrorText: null, - submitButtonEnabled: false, - }; - - this._unmounted = false; - this._authLogic = new InteractiveAuth({ - authData: this.props.authData, - doRequest: this._requestCallback, - busyChanged: this._onBusyChanged, - inputs: this.props.inputs, - stateUpdated: this._authStateUpdated, - matrixClient: this.props.matrixClient, - sessionId: this.props.sessionId, - clientSecret: this.props.clientSecret, - emailSid: this.props.emailSid, - requestEmailToken: this._requestEmailToken, - }); - - this._intervalId = null; - if (this.props.poll) { - this._intervalId = setInterval(() => { - this._authLogic.poll(); - }, 2000); - } - - this._stageComponent = createRef(); - } - - // TODO: [REACT-WARNING] Replace component with real class, use constructor for refs - UNSAFE_componentWillMount() { // eslint-disable-line camelcase - this._authLogic.attemptAuth().then((result) => { - const extra = { - emailSid: this._authLogic.getEmailSid(), - clientSecret: this._authLogic.getClientSecret(), - }; - this.props.onAuthFinished(true, result, extra); - }).catch((error) => { - this.props.onAuthFinished(false, error); - console.error("Error during user-interactive auth:", error); - if (this._unmounted) { - return; - } - - const msg = error.message || error.toString(); - this.setState({ - errorText: msg, - }); - }); - } - - componentWillUnmount() { - this._unmounted = true; - - if (this._intervalId !== null) { - clearInterval(this._intervalId); - } - } - - _requestEmailToken = async (...args) => { - this.setState({ - busy: true, - }); - try { - return await this.props.requestEmailToken(...args); - } finally { - this.setState({ - busy: false, - }); - } - }; - - tryContinue = () => { - if (this._stageComponent.current && this._stageComponent.current.tryContinue) { - this._stageComponent.current.tryContinue(); - } - }; - - _authStateUpdated = (stageType, stageState) => { - const oldStage = this.state.authStage; - this.setState({ - busy: false, - authStage: stageType, - stageState: stageState, - errorText: stageState.error, - }, () => { - if (oldStage !== stageType) { - this._setFocus(); - } else if ( - !stageState.error && this._stageComponent.current && - this._stageComponent.current.attemptFailed - ) { - this._stageComponent.current.attemptFailed(); - } - }); - }; - - _requestCallback = (auth) => { - // This wrapper just exists because the js-sdk passes a second - // 'busy' param for backwards compat. This throws the tests off - // so discard it here. - return this.props.makeRequest(auth); - }; - - _onBusyChanged = (busy) => { - // if we've started doing stuff, reset the error messages - if (busy) { - this.setState({ - busy: true, - errorText: null, - stageErrorText: null, - }); - } - // The JS SDK eagerly reports itself as "not busy" right after any - // immediate work has completed, but that's not really what we want at - // the UI layer, so we ignore this signal and show a spinner until - // there's a new screen to show the user. This is implemented by setting - // `busy: false` in `_authStateUpdated`. - // See also https://github.com/vector-im/element-web/issues/12546 - }; - - _setFocus() { - if (this._stageComponent.current && this._stageComponent.current.focus) { - this._stageComponent.current.focus(); - } - } - - _submitAuthDict = authData => { - this._authLogic.submitAuthDict(authData); - }; - - _onPhaseChange = newPhase => { - if (this.props.onStagePhaseChange) { - this.props.onStagePhaseChange(this.state.authStage, newPhase || 0); - } - }; - - _onStageCancel = () => { - this.props.onAuthFinished(false, ERROR_USER_CANCELLED); - }; - - _renderCurrentStage() { - const stage = this.state.authStage; - if (!stage) { - if (this.state.busy) { - const Loader = sdk.getComponent("elements.Spinner"); - return ; - } else { - return null; - } - } - - const StageComponent = getEntryComponentForLoginType(stage); - return ( - - ); - } - - _onAuthStageFailed = e => { - this.props.onAuthFinished(false, e); - }; - - _setEmailSid = sid => { - this._authLogic.setEmailSid(sid); - }; - - render() { - let error = null; - if (this.state.errorText) { - error = ( -
- { this.state.errorText } -
- ); - } - - return ( -
-
- { this._renderCurrentStage() } - { error } -
-
- ); - } -} diff --git a/src/components/structures/InteractiveAuth.tsx b/src/components/structures/InteractiveAuth.tsx new file mode 100644 index 0000000000..869cd29cba --- /dev/null +++ b/src/components/structures/InteractiveAuth.tsx @@ -0,0 +1,300 @@ +/* +Copyright 2017 - 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { + AuthType, + IAuthData, + IAuthDict, + IInputs, + InteractiveAuth, + IStageStatus, +} from "matrix-js-sdk/src/interactive-auth"; +import { MatrixClient } from "matrix-js-sdk/src/client"; +import React, { createRef } from 'react'; + +import getEntryComponentForLoginType, { IStageComponent } from '../views/auth/InteractiveAuthEntryComponents'; +import Spinner from "../views/elements/Spinner"; +import { replaceableComponent } from "../../utils/replaceableComponent"; + +export const ERROR_USER_CANCELLED = new Error("User cancelled auth session"); + +interface IProps { + // matrix client to use for UI auth requests + matrixClient: MatrixClient; + // response from initial request. If not supplied, will do a request on mount. + authData?: IAuthData; + // Inputs provided by the user to the auth process + // and used by various stages. As passed to js-sdk + // interactive-auth + inputs?: IInputs; + sessionId?: string; + clientSecret?: string; + emailSid?: string; + // If true, poll to see if the auth flow has been completed out-of-band + poll?: boolean; + // If true, components will be told that the 'Continue' button + // is managed by some other party and should not be managed by + // the component itself. + continueIsManaged?: boolean; + // continueText and continueKind are passed straight through to the AuthEntryComponent. + continueText?: string; + continueKind?: string; + // callback + makeRequest(auth: IAuthData): Promise; + // callback called when the auth process has finished, + // successfully or unsuccessfully. + // @param {boolean} status True if the operation requiring + // auth was completed successfully, false if canceled. + // @param {object} result The result of the authenticated call + // if successful, otherwise the error object. + // @param {object} extra Additional information about the UI Auth + // process: + // * emailSid {string} If email auth was performed, the sid of + // the auth session. + // * clientSecret {string} The client secret used in auth + // sessions with the ID server. + onAuthFinished( + status: boolean, + result: IAuthData | Error, + extra?: { emailSid?: string, clientSecret?: string }, + ): void; + // As js-sdk interactive-auth + requestEmailToken?(email: string, secret: string, attempt: number, session: string): Promise<{ sid: string }>; + // Called when the stage changes, or the stage's phase changes. First + // argument is the stage, second is the phase. Some stages do not have + // phases and will be counted as 0 (numeric). + onStagePhaseChange?(stage: string, phase: string | number): void; +} + +interface IState { + authStage?: AuthType; + stageState?: IStageStatus; + busy: boolean; + errorText?: string; + stageErrorText?: string; + submitButtonEnabled: boolean; +} + +@replaceableComponent("structures.InteractiveAuthComponent") +export default class InteractiveAuthComponent extends React.Component { + private readonly authLogic: InteractiveAuth; + private readonly intervalId: number = null; + private readonly stageComponent = createRef(); + + private unmounted = false; + + constructor(props) { + super(props); + + this.state = { + authStage: null, + busy: false, + errorText: null, + stageErrorText: null, + submitButtonEnabled: false, + }; + + this.authLogic = new InteractiveAuth({ + authData: this.props.authData, + doRequest: this.requestCallback, + busyChanged: this.onBusyChanged, + inputs: this.props.inputs, + stateUpdated: this.authStateUpdated, + matrixClient: this.props.matrixClient, + sessionId: this.props.sessionId, + clientSecret: this.props.clientSecret, + emailSid: this.props.emailSid, + requestEmailToken: this.requestEmailToken, + }); + + if (this.props.poll) { + this.intervalId = setInterval(() => { + this.authLogic.poll(); + }, 2000); + } + } + + // TODO: [REACT-WARNING] Replace component with real class, use constructor for refs + UNSAFE_componentWillMount() { // eslint-disable-line @typescript-eslint/naming-convention, camelcase + this.authLogic.attemptAuth().then((result) => { + const extra = { + emailSid: this.authLogic.getEmailSid(), + clientSecret: this.authLogic.getClientSecret(), + }; + this.props.onAuthFinished(true, result, extra); + }).catch((error) => { + this.props.onAuthFinished(false, error); + console.error("Error during user-interactive auth:", error); + if (this.unmounted) { + return; + } + + const msg = error.message || error.toString(); + this.setState({ + errorText: msg, + }); + }); + } + + componentWillUnmount() { + this.unmounted = true; + + if (this.intervalId !== null) { + clearInterval(this.intervalId); + } + } + + private requestEmailToken = async ( + email: string, + secret: string, + attempt: number, + session: string, + ): Promise<{sid: string}> => { + this.setState({ + busy: true, + }); + try { + return await this.props.requestEmailToken(email, secret, attempt, session); + } finally { + this.setState({ + busy: false, + }); + } + }; + + private tryContinue = (): void => { + this.stageComponent.current?.tryContinue?.(); + }; + + private authStateUpdated = (stageType: AuthType, stageState: IStageStatus): void => { + const oldStage = this.state.authStage; + this.setState({ + busy: false, + authStage: stageType, + stageState: stageState, + errorText: stageState.error, + }, () => { + if (oldStage !== stageType) { + this.setFocus(); + } else if (!stageState.error) { + this.stageComponent.current?.attemptFailed?.(); + } + }); + }; + + private requestCallback = (auth: IAuthData, background: boolean): Promise => { + // This wrapper just exists because the js-sdk passes a second + // 'busy' param for backwards compat. This throws the tests off + // so discard it here. + return this.props.makeRequest(auth); + }; + + private onBusyChanged = (busy: boolean): void => { + // if we've started doing stuff, reset the error messages + if (busy) { + this.setState({ + busy: true, + errorText: null, + stageErrorText: null, + }); + } + // The JS SDK eagerly reports itself as "not busy" right after any + // immediate work has completed, but that's not really what we want at + // the UI layer, so we ignore this signal and show a spinner until + // there's a new screen to show the user. This is implemented by setting + // `busy: false` in `authStateUpdated`. + // See also https://github.com/vector-im/element-web/issues/12546 + }; + + private setFocus(): void { + this.stageComponent.current?.focus?.(); + } + + private submitAuthDict = (authData: IAuthDict): void => { + this.authLogic.submitAuthDict(authData); + }; + + private onPhaseChange = (newPhase: number): void => { + this.props.onStagePhaseChange?.(this.state.authStage, newPhase || 0); + }; + + private onStageCancel = (): void => { + this.props.onAuthFinished(false, ERROR_USER_CANCELLED); + }; + + private renderCurrentStage(): JSX.Element { + const stage = this.state.authStage; + if (!stage) { + if (this.state.busy) { + return ; + } else { + return null; + } + } + + const StageComponent = getEntryComponentForLoginType(stage); + return ( + + ); + } + + private onAuthStageFailed = (e: Error): void => { + this.props.onAuthFinished(false, e); + }; + + private setEmailSid = (sid: string): void => { + this.authLogic.setEmailSid(sid); + }; + + render() { + let error = null; + if (this.state.errorText) { + error = ( +
+ { this.state.errorText } +
+ ); + } + + return ( +
+
+ { this.renderCurrentStage() } + { error } +
+
+ ); + } +} diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index 3bd2c68c6c..d955271249 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -19,8 +19,6 @@ import { createRef } from "react"; import classNames from "classnames"; import { Room } from "matrix-js-sdk/src/models/room"; -import GroupFilterPanel from "./GroupFilterPanel"; -import CustomRoomTagPanel from "./CustomRoomTagPanel"; import dis from "../../dispatcher/dispatcher"; import { _t } from "../../languageHandler"; import RoomList from "../views/rooms/RoomList"; @@ -33,15 +31,12 @@ import RoomBreadcrumbs from "../views/rooms/RoomBreadcrumbs"; import { BreadcrumbsStore } from "../../stores/BreadcrumbsStore"; import { UPDATE_EVENT } from "../../stores/AsyncStore"; import ResizeNotifier from "../../utils/ResizeNotifier"; -import SettingsStore from "../../settings/SettingsStore"; import RoomListStore, { LISTS_UPDATE_EVENT } from "../../stores/room-list/RoomListStore"; import IndicatorScrollbar from "../structures/IndicatorScrollbar"; import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; -import { OwnProfileStore } from "../../stores/OwnProfileStore"; import RoomListNumResults from "../views/rooms/RoomListNumResults"; import LeftPanelWidget from "./LeftPanelWidget"; import { replaceableComponent } from "../../utils/replaceableComponent"; -import { mediaFromMxc } from "../../customisations/Media"; import SpaceStore, { UPDATE_SELECTED_SPACE } from "../../stores/SpaceStore"; import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager"; import UIStore from "../../stores/UIStore"; @@ -53,7 +48,6 @@ interface IProps { interface IState { showBreadcrumbs: boolean; - showGroupFilterPanel: boolean; activeSpace?: Room; } @@ -70,8 +64,6 @@ const cssClasses = [ export default class LeftPanel extends React.Component { private ref: React.RefObject = createRef(); private listContainerRef: React.RefObject = createRef(); - private groupFilterPanelWatcherRef: string; - private bgImageWatcherRef: string; private focusedElement = null; private isDoingStickyHeaders = false; @@ -80,22 +72,16 @@ export default class LeftPanel extends React.Component { this.state = { showBreadcrumbs: BreadcrumbsStore.instance.visible, - showGroupFilterPanel: SettingsStore.getValue('TagPanel.enableTagPanel'), activeSpace: SpaceStore.instance.activeSpace, }; BreadcrumbsStore.instance.on(UPDATE_EVENT, this.onBreadcrumbsUpdate); RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate); - OwnProfileStore.instance.on(UPDATE_EVENT, this.onBackgroundImageUpdate); SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.updateActiveSpace); - this.bgImageWatcherRef = SettingsStore.watchSetting( - "RoomList.backgroundImage", null, this.onBackgroundImageUpdate); - this.groupFilterPanelWatcherRef = SettingsStore.watchSetting("TagPanel.enableTagPanel", null, () => { - this.setState({ showGroupFilterPanel: SettingsStore.getValue("TagPanel.enableTagPanel") }); - }); } public componentDidMount() { + UIStore.instance.trackElementDimensions("LeftPanel", this.ref.current); UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.current); UIStore.instance.on("ListContainer", this.refreshStickyHeaders); // Using the passive option to not block the main thread @@ -104,11 +90,8 @@ export default class LeftPanel extends React.Component { } public componentWillUnmount() { - SettingsStore.unwatchSetting(this.groupFilterPanelWatcherRef); - SettingsStore.unwatchSetting(this.bgImageWatcherRef); BreadcrumbsStore.instance.off(UPDATE_EVENT, this.onBreadcrumbsUpdate); RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate); - OwnProfileStore.instance.off(UPDATE_EVENT, this.onBackgroundImageUpdate); SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.updateActiveSpace); UIStore.instance.stopTrackingElementDimensions("ListContainer"); UIStore.instance.removeListener("ListContainer", this.refreshStickyHeaders); @@ -149,23 +132,6 @@ export default class LeftPanel extends React.Component { } }; - private onBackgroundImageUpdate = () => { - // Note: we do this in the LeftPanel as it uses this variable most prominently. - const avatarSize = 32; // arbitrary - let avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize); - const settingBgMxc = SettingsStore.getValue("RoomList.backgroundImage"); - if (settingBgMxc) { - avatarUrl = mediaFromMxc(settingBgMxc).getSquareThumbnailHttp(avatarSize); - } - - const avatarUrlProp = `url(${avatarUrl})`; - if (!avatarUrl) { - document.body.style.removeProperty("--avatar-url"); - } else if (document.body.style.getPropertyValue("--avatar-url") !== avatarUrlProp) { - document.body.style.setProperty("--avatar-url", avatarUrlProp); - } - }; - private handleStickyHeaders(list: HTMLDivElement) { if (this.isDoingStickyHeaders) return; this.isDoingStickyHeaders = true; @@ -392,9 +358,6 @@ export default class LeftPanel extends React.Component { @@ -443,16 +406,6 @@ export default class LeftPanel extends React.Component { } public render(): React.ReactNode { - let leftLeftPanel; - if (this.state.showGroupFilterPanel) { - leftLeftPanel = ( -
- - { SettingsStore.getValue("feature_custom_tags") ? : null } -
- ); - } - const roomList = { return (
- { leftLeftPanel }