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/develop.yml b/.github/workflows/develop.yml index 0ae59da09a..4f9826391a 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -10,6 +10,8 @@ on: jobs: end-to-end: runs-on: ubuntu-latest + env: + PR_NUMBER: ${{github.event.number}} container: vectorim/element-web-ci-e2etests-env:latest steps: - name: Checkout code diff --git a/.github/workflows/layered-build.yaml b/.github/workflows/layered-build.yaml index c9d7e89a75..c8717667d7 100644 --- a/.github/workflows/layered-build.yaml +++ b/.github/workflows/layered-build.yaml @@ -5,6 +5,8 @@ on: jobs: build: runs-on: ubuntu-latest + env: + PR_NUMBER: ${{github.event.number}} steps: - uses: actions/checkout@v2 - name: Build diff --git a/.github/workflows/typecheck.yaml b/.github/workflows/typecheck.yaml new file mode 100644 index 0000000000..f6ab643958 --- /dev/null +++ b/.github/workflows/typecheck.yaml @@ -0,0 +1,26 @@ +name: Type Check +on: + pull_request: + branches: [develop] +jobs: + build: + runs-on: ubuntu-latest + env: + PR_NUMBER: ${{github.event.number}} + steps: + - uses: actions/checkout@v2 + - uses: c-hive/gha-yarn-cache@v2 + - name: Install Deps + run: "./scripts/ci/install-deps.sh --ignore-scripts" + - name: Typecheck + run: "yarn run lint:types" + - name: Switch js-sdk to release mode + run: | + scripts/ci/js-sdk-to-release.js + cd node_modules/matrix-js-sdk + yarn install + yarn run build:compile + yarn run build:types + - name: Typecheck (release mode) + run: "yarn run lint:types" + diff --git a/.stylelintrc.js b/.stylelintrc.js index 0e6de7000f..c044b19a63 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -17,6 +17,7 @@ module.exports = { "selector-list-comma-newline-after": null, "at-rule-no-unknown": null, "no-descending-specificity": null, + "no-empty-first-line": true, "scss/at-rule-no-unknown": [true, { // https://github.com/vector-im/element-web/issues/10544 "ignoreAtRules": ["define-mixin"], diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f71c1414c..9a445a4041 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,114 @@ +Changes in [3.30.0](https://github.com/vector-im/element-desktop/releases/tag/v3.30.0) (2021-09-14) +=================================================================================================== + +## ✨ Features + * Add bubble highlight styling ([\#6582](https://github.com/matrix-org/matrix-react-sdk/pull/6582)). Fixes vector-im/element-web#18295 and vector-im/element-web#18295. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * [Release] Add config option to turn on in-room event sending timing metrics ([\#6773](https://github.com/matrix-org/matrix-react-sdk/pull/6773)). + * Create narrow mode for Composer ([\#6682](https://github.com/matrix-org/matrix-react-sdk/pull/6682)). Fixes vector-im/element-web#18533 and vector-im/element-web#18533. + * Prefer matrix.to alias links over room id in spaces & share ([\#6745](https://github.com/matrix-org/matrix-react-sdk/pull/6745)). Fixes vector-im/element-web#18796 and vector-im/element-web#18796. + * Stop automatic playback of voice messages if a non-voice message is encountered ([\#6728](https://github.com/matrix-org/matrix-react-sdk/pull/6728)). Fixes vector-im/element-web#18850 and vector-im/element-web#18850. + * Show call length during a call ([\#6700](https://github.com/matrix-org/matrix-react-sdk/pull/6700)). Fixes vector-im/element-web#18566 and vector-im/element-web#18566. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Serialize and retry mass-leave when leaving space ([\#6737](https://github.com/matrix-org/matrix-react-sdk/pull/6737)). Fixes vector-im/element-web#18789 and vector-im/element-web#18789. + * Improve form handling in and around space creation ([\#6739](https://github.com/matrix-org/matrix-react-sdk/pull/6739)). Fixes vector-im/element-web#18775 and vector-im/element-web#18775. + * Split autoplay GIFs and videos into different settings ([\#6726](https://github.com/matrix-org/matrix-react-sdk/pull/6726)). Fixes vector-im/element-web#5771 and vector-im/element-web#5771. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Add autoplay for voice messages ([\#6710](https://github.com/matrix-org/matrix-react-sdk/pull/6710)). Fixes vector-im/element-web#18804, vector-im/element-web#18715, vector-im/element-web#18714 vector-im/element-web#17961 and vector-im/element-web#18804. + * Allow to use basic html to format invite messages ([\#6703](https://github.com/matrix-org/matrix-react-sdk/pull/6703)). Fixes vector-im/element-web#15738 and vector-im/element-web#15738. Contributed by [skolmer](https://github.com/skolmer). + * Allow widgets, when eligible, to interact with more rooms as per MSC2762 ([\#6684](https://github.com/matrix-org/matrix-react-sdk/pull/6684)). + * Remove arbitrary limits from send/receive events for widgets ([\#6719](https://github.com/matrix-org/matrix-react-sdk/pull/6719)). Fixes vector-im/element-web#17994 and vector-im/element-web#17994. + * Reload suggested rooms if we see the state change down /sync ([\#6715](https://github.com/matrix-org/matrix-react-sdk/pull/6715)). Fixes vector-im/element-web#18761 and vector-im/element-web#18761. + * When creating private spaces, make the initial rooms restricted if supported ([\#6721](https://github.com/matrix-org/matrix-react-sdk/pull/6721)). Fixes vector-im/element-web#18722 and vector-im/element-web#18722. + * Threading exploration work ([\#6658](https://github.com/matrix-org/matrix-react-sdk/pull/6658)). Fixes vector-im/element-web#18532 and vector-im/element-web#18532. + * Default to `Don't leave any` when leaving a space ([\#6697](https://github.com/matrix-org/matrix-react-sdk/pull/6697)). Fixes vector-im/element-web#18592 and vector-im/element-web#18592. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Special case redaction event sending from widgets per MSC2762 ([\#6686](https://github.com/matrix-org/matrix-react-sdk/pull/6686)). Fixes vector-im/element-web#18573 and vector-im/element-web#18573. + * Add active speaker indicators ([\#6639](https://github.com/matrix-org/matrix-react-sdk/pull/6639)). Fixes vector-im/element-web#17627 and vector-im/element-web#17627. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Increase general app performance by optimizing layers ([\#6644](https://github.com/matrix-org/matrix-react-sdk/pull/6644)). Fixes vector-im/element-web#18730 and vector-im/element-web#18730. Contributed by [Palid](https://github.com/Palid). + +## 🐛 Bug Fixes + * Fix autocomplete not having y-scroll ([\#6802](https://github.com/matrix-org/matrix-react-sdk/pull/6802)). + * Fix emoji picker and stickerpicker not appearing correctly when opened ([\#6801](https://github.com/matrix-org/matrix-react-sdk/pull/6801)). + * Debounce read marker update on scroll ([\#6774](https://github.com/matrix-org/matrix-react-sdk/pull/6774)). + * Fix Space creation wizard go to my first room button behaviour ([\#6748](https://github.com/matrix-org/matrix-react-sdk/pull/6748)). Fixes vector-im/element-web#18764 and vector-im/element-web#18764. + * Fix scroll being stuck at bottom ([\#6751](https://github.com/matrix-org/matrix-react-sdk/pull/6751)). Fixes vector-im/element-web#18903 and vector-im/element-web#18903. + * Fix widgets not remembering identity verification when asked to. ([\#6742](https://github.com/matrix-org/matrix-react-sdk/pull/6742)). Fixes vector-im/element-web#15631 and vector-im/element-web#15631. + * Add missing pluralisation i18n strings for Spaces ([\#6738](https://github.com/matrix-org/matrix-react-sdk/pull/6738)). Fixes vector-im/element-web#18780 and vector-im/element-web#18780. + * Make ForgotPassword UX slightly more user friendly ([\#6636](https://github.com/matrix-org/matrix-react-sdk/pull/6636)). Fixes vector-im/element-web#11531 and vector-im/element-web#11531. Contributed by [Palid](https://github.com/Palid). + * Don't context switch room on SpaceStore ready as it can break permalinks ([\#6730](https://github.com/matrix-org/matrix-react-sdk/pull/6730)). Fixes vector-im/element-web#17974 and vector-im/element-web#17974. + * Fix explore rooms button not working during space creation wizard ([\#6729](https://github.com/matrix-org/matrix-react-sdk/pull/6729)). Fixes vector-im/element-web#18762 and vector-im/element-web#18762. + * Fix bug where one party's media would sometimes not be shown ([\#6731](https://github.com/matrix-org/matrix-react-sdk/pull/6731)). + * Only make the initial space rooms suggested by default ([\#6714](https://github.com/matrix-org/matrix-react-sdk/pull/6714)). Fixes vector-im/element-web#18760 and vector-im/element-web#18760. + * Replace fake username in EventTilePreview with a proper loading state ([\#6702](https://github.com/matrix-org/matrix-react-sdk/pull/6702)). Fixes vector-im/element-web#15897 and vector-im/element-web#15897. Contributed by [skolmer](https://github.com/skolmer). + * Don't send prehistorical events to widgets during decryption at startup ([\#6695](https://github.com/matrix-org/matrix-react-sdk/pull/6695)). Fixes vector-im/element-web#18060 and vector-im/element-web#18060. + * When creating subspaces properly set restricted join rule ([\#6725](https://github.com/matrix-org/matrix-react-sdk/pull/6725)). Fixes vector-im/element-web#18797 and vector-im/element-web#18797. + * Fix the Image View not openning for some pinned messages ([\#6723](https://github.com/matrix-org/matrix-react-sdk/pull/6723)). Fixes vector-im/element-web#18422 and vector-im/element-web#18422. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Show autocomplete sections vertically ([\#6722](https://github.com/matrix-org/matrix-react-sdk/pull/6722)). Fixes vector-im/element-web#18860 and vector-im/element-web#18860. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix EmojiPicker filtering to lower case emojibase data strings ([\#6717](https://github.com/matrix-org/matrix-react-sdk/pull/6717)). Fixes vector-im/element-web#18686 and vector-im/element-web#18686. + * Clear currentRoomId when viewing home page, fixing document title ([\#6716](https://github.com/matrix-org/matrix-react-sdk/pull/6716)). Fixes vector-im/element-web#18668 and vector-im/element-web#18668. + * Fix membership updates to Spaces not applying in real-time ([\#6713](https://github.com/matrix-org/matrix-react-sdk/pull/6713)). Fixes vector-im/element-web#18737 and vector-im/element-web#18737. + * Don't show a double stacked invite modals when inviting to Spaces ([\#6698](https://github.com/matrix-org/matrix-react-sdk/pull/6698)). Fixes vector-im/element-web#18745 and vector-im/element-web#18745. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Remove non-functional DuckDuckGo Autocomplete Provider ([\#6712](https://github.com/matrix-org/matrix-react-sdk/pull/6712)). Fixes vector-im/element-web#18778 and vector-im/element-web#18778. + * Filter members on `MemberList` load ([\#6708](https://github.com/matrix-org/matrix-react-sdk/pull/6708)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix improper voice messages being produced in Firefox and sometimes other browsers. ([\#6696](https://github.com/matrix-org/matrix-react-sdk/pull/6696)). Fixes vector-im/element-web#18587 and vector-im/element-web#18587. + * Fix client forgetting which capabilities a widget was approved for ([\#6685](https://github.com/matrix-org/matrix-react-sdk/pull/6685)). Fixes vector-im/element-web#18786 and vector-im/element-web#18786. + * Fix left panel widgets not remembering collapsed state ([\#6687](https://github.com/matrix-org/matrix-react-sdk/pull/6687)). Fixes vector-im/element-web#17803 and vector-im/element-web#17803. + * Fix changelog link colour back to blue ([\#6692](https://github.com/matrix-org/matrix-react-sdk/pull/6692)). Fixes vector-im/element-web#18726 and vector-im/element-web#18726. + * Soften codeblock border color ([\#6564](https://github.com/matrix-org/matrix-react-sdk/pull/6564)). Fixes vector-im/element-web#18367 and vector-im/element-web#18367. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Pause ringing more aggressively ([\#6691](https://github.com/matrix-org/matrix-react-sdk/pull/6691)). Fixes vector-im/element-web#18588 and vector-im/element-web#18588. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix command autocomplete ([\#6680](https://github.com/matrix-org/matrix-react-sdk/pull/6680)). Fixes vector-im/element-web#18670 and vector-im/element-web#18670. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Don't re-sort the room-list based on profile/status changes ([\#6595](https://github.com/matrix-org/matrix-react-sdk/pull/6595)). Fixes vector-im/element-web#110 and vector-im/element-web#110. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix codeblock formatting with syntax highlighting on ([\#6681](https://github.com/matrix-org/matrix-react-sdk/pull/6681)). Fixes vector-im/element-web#18739 vector-im/element-web#18365 and vector-im/element-web#18739. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Add padding to the Add button in the notification settings ([\#6665](https://github.com/matrix-org/matrix-react-sdk/pull/6665)). Fixes vector-im/element-web#18706 and vector-im/element-web#18706. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + +Changes in [3.29.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.29.1) (2021-09-13) +=================================================================================================== + +## 🔒 SECURITY FIXES + * Fix a security issue with message key sharing. See https://matrix.org/blog/2021/09/13/vulnerability-disclosure-key-sharing + for details. + +Changes in [3.29.0](https://github.com/vector-im/element-desktop/releases/tag/v3.29.0) (2021-08-31) +=================================================================================================== + +## ✨ Features + * [Release]Increase general app performance by optimizing layers ([\#6672](https://github.com/matrix-org/matrix-react-sdk/pull/6672)). Fixes vector-im/element-web#18730 and vector-im/element-web#18730. Contributed by [Palid](https://github.com/Palid). + * Add a warning on E2EE rooms if you try to make them public ([\#5698](https://github.com/matrix-org/matrix-react-sdk/pull/5698)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Allow pagination of the space hierarchy and use new APIs ([\#6507](https://github.com/matrix-org/matrix-react-sdk/pull/6507)). Fixes vector-im/element-web#18089 and vector-im/element-web#18427. + * Improve emoji in composer ([\#6650](https://github.com/matrix-org/matrix-react-sdk/pull/6650)). Fixes vector-im/element-web#18593 and vector-im/element-web#18593. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Allow playback of replied-to voice message ([\#6629](https://github.com/matrix-org/matrix-react-sdk/pull/6629)). Fixes vector-im/element-web#18599 and vector-im/element-web#18599. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Format autocomplete suggestions vertically ([\#6620](https://github.com/matrix-org/matrix-react-sdk/pull/6620)). Fixes vector-im/element-web#17574 and vector-im/element-web#17574. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Remember last `MemberList` search query per-room ([\#6640](https://github.com/matrix-org/matrix-react-sdk/pull/6640)). Fixes vector-im/element-web#18613 and vector-im/element-web#18613. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Sentry rageshakes ([\#6597](https://github.com/matrix-org/matrix-react-sdk/pull/6597)). Fixes vector-im/element-web#11111 and vector-im/element-web#11111. Contributed by [novocaine](https://github.com/novocaine). + * Autocomplete has been updated to match modern accessibility standards. Navigate via up/down arrows rather than Tab. Enter or Tab to confirm a suggestion. This should be familiar to Slack & Discord users. You can now use Tab to navigate around the application and do more without touching your mouse. No more accidentally sending half of people's names because the completion didn't fire on Enter! ([\#5659](https://github.com/matrix-org/matrix-react-sdk/pull/5659)). Fixes vector-im/element-web#4872, vector-im/element-web#11071, vector-im/element-web#17171, vector-im/element-web#15646 vector-im/element-web#4872 and vector-im/element-web#4872. + * Add new call tile states ([\#6610](https://github.com/matrix-org/matrix-react-sdk/pull/6610)). Fixes vector-im/element-web#18521 and vector-im/element-web#18521. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Left align call tiles ([\#6609](https://github.com/matrix-org/matrix-react-sdk/pull/6609)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Make loading encrypted images look snappier ([\#6590](https://github.com/matrix-org/matrix-react-sdk/pull/6590)). Fixes vector-im/element-web#17878 and vector-im/element-web#17862. Contributed by [Palid](https://github.com/Palid). + * Offer a way to create a space based on existing community ([\#6543](https://github.com/matrix-org/matrix-react-sdk/pull/6543)). Fixes vector-im/element-web#18092. + * Accessibility improvements in and around Spaces ([\#6569](https://github.com/matrix-org/matrix-react-sdk/pull/6569)). Fixes vector-im/element-web#18094 and vector-im/element-web#18094. + +## 🐛 Bug Fixes + * [Release] Fix commit edit history ([\#6690](https://github.com/matrix-org/matrix-react-sdk/pull/6690)). Fixes vector-im/element-web#18742 and vector-im/element-web#18742. Contributed by [Palid](https://github.com/Palid). + * Fix images not rendering when sent from other clients. ([\#6661](https://github.com/matrix-org/matrix-react-sdk/pull/6661)). Fixes vector-im/element-web#18702 and vector-im/element-web#18702. + * Fix autocomplete scrollbar and make the autocomplete a little smaller ([\#6655](https://github.com/matrix-org/matrix-react-sdk/pull/6655)). Fixes vector-im/element-web#18682 and vector-im/element-web#18682. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix replies on the bubble layout ([\#6451](https://github.com/matrix-org/matrix-react-sdk/pull/6451)). Fixes vector-im/element-web#18184. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Show "Enable encryption in settings" only when the user can do that ([\#6646](https://github.com/matrix-org/matrix-react-sdk/pull/6646)). Fixes vector-im/element-web#18646 and vector-im/element-web#18646. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix cross signing setup from settings screen ([\#6633](https://github.com/matrix-org/matrix-react-sdk/pull/6633)). Fixes vector-im/element-web#17761 and vector-im/element-web#17761. + * Fix call tiles on the bubble layout ([\#6647](https://github.com/matrix-org/matrix-react-sdk/pull/6647)). Fixes vector-im/element-web#18648 and vector-im/element-web#18648. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix error on accessing encrypted media without encryption keys ([\#6625](https://github.com/matrix-org/matrix-react-sdk/pull/6625)). Contributed by [Palid](https://github.com/Palid). + * Fix jitsi widget sometimes being permanently stuck in the bottom-right corner ([\#6632](https://github.com/matrix-org/matrix-react-sdk/pull/6632)). Fixes vector-im/element-web#17226 and vector-im/element-web#17226. Contributed by [Palid](https://github.com/Palid). + * Fix FilePanel pagination in E2EE rooms ([\#6630](https://github.com/matrix-org/matrix-react-sdk/pull/6630)). Fixes vector-im/element-web#18415 and vector-im/element-web#18415. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix call tile buttons ([\#6624](https://github.com/matrix-org/matrix-react-sdk/pull/6624)). Fixes vector-im/element-web#18565 and vector-im/element-web#18565. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix vertical call tile spacing issues ([\#6621](https://github.com/matrix-org/matrix-react-sdk/pull/6621)). Fixes vector-im/element-web#18558 and vector-im/element-web#18558. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix long display names in call tiles ([\#6618](https://github.com/matrix-org/matrix-react-sdk/pull/6618)). Fixes vector-im/element-web#18562 and vector-im/element-web#18562. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Avoid access token overflow ([\#6616](https://github.com/matrix-org/matrix-react-sdk/pull/6616)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Properly handle media errors ([\#6615](https://github.com/matrix-org/matrix-react-sdk/pull/6615)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix glare related regressions ([\#6614](https://github.com/matrix-org/matrix-react-sdk/pull/6614)). Fixes vector-im/element-web#18538 and vector-im/element-web#18538. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix long display names in call toasts ([\#6617](https://github.com/matrix-org/matrix-react-sdk/pull/6617)). Fixes vector-im/element-web#18557 and vector-im/element-web#18557. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix PiP of held calls ([\#6611](https://github.com/matrix-org/matrix-react-sdk/pull/6611)). Fixes vector-im/element-web#18539 and vector-im/element-web#18539. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix call tile behaviour on narrow layouts ([\#6556](https://github.com/matrix-org/matrix-react-sdk/pull/6556)). Fixes vector-im/element-web#18398. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Fix video call persisting when widget removed ([\#6608](https://github.com/matrix-org/matrix-react-sdk/pull/6608)). Fixes vector-im/element-web#15703 and vector-im/element-web#15703. + * Fix toast colors ([\#6606](https://github.com/matrix-org/matrix-react-sdk/pull/6606)). Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Remove tiny scrollbar dot from code blocks ([\#6596](https://github.com/matrix-org/matrix-react-sdk/pull/6596)). Fixes vector-im/element-web#18474. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * Improve handling of pills in the composer ([\#6353](https://github.com/matrix-org/matrix-react-sdk/pull/6353)). Fixes vector-im/element-web#10134 vector-im/element-web#10896 and vector-im/element-web#15037. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + Changes in [3.28.1](https://github.com/vector-im/element-desktop/releases/tag/v3.28.1) (2021-08-17) =================================================================================================== diff --git a/package.json b/package.json index 2650081cab..8dcaaf36f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.28.1", + "version": "3.30.0", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -64,7 +64,6 @@ "cheerio": "^1.0.0-rc.9", "classnames": "^2.2.6", "commonmark": "^0.29.3", - "context-filter-polyfill": "^0.2.4", "counterpart": "^0.18.6", "diff-dom": "^4.2.2", "diff-match-patch": "^1.0.5", @@ -85,7 +84,7 @@ "linkifyjs": "^2.1.9", "lodash": "^4.17.20", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", - "matrix-widget-api": "^0.1.0-beta.15", + "matrix-widget-api": "^0.1.0-beta.16", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", "pako": "^2.0.3", @@ -95,10 +94,10 @@ "prop-types": "^15.7.2", "qrcode": "^1.4.4", "re-resizable": "^6.9.0", - "react": "^17.0.2", + "react": "17.0.2", "react-beautiful-dnd": "^13.1.0", "react-blurhash": "^0.1.3", - "react-dom": "^17.0.2", + "react-dom": "17.0.2", "react-focus-lock": "^2.5.0", "react-transition-group": "^4.4.1", "resize-observer-polyfill": "^1.5.1", @@ -145,16 +144,16 @@ "@types/pako": "^1.0.1", "@types/parse5": "^6.0.0", "@types/qrcode": "^1.3.5", - "@types/react": "^17.0.2", + "@types/react": "17.0.14", "@types/react-beautiful-dnd": "^13.0.0", - "@types/react-dom": "^17.0.2", + "@types/react-dom": "17.0.9", "@types/react-transition-group": "^4.4.0", "@types/sanitize-html": "^2.3.1", "@types/zxcvbn": "^4.4.0", "@typescript-eslint/eslint-plugin": "^4.17.0", "@typescript-eslint/parser": "^4.17.0", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1", - "allchange": "^1.0.0", + "allchange": "^1.0.3", "babel-jest": "^26.6.3", "chokidar": "^3.5.1", "concurrently": "^5.3.0", @@ -180,9 +179,12 @@ "stylelint": "^13.9.0", "stylelint-config-standard": "^20.0.0", "stylelint-scss": "^3.18.0", - "typescript": "^4.1.3", + "typescript": "4.3.5", "walk": "^2.3.14" }, + "resolutions": { + "@types/react": "17.0.14" + }, "jest": { "testEnvironment": "./__test-utils__/environment.js", "testMatch": [ @@ -200,7 +202,6 @@ "decoderWorker\\.min\\.js": "/__mocks__/empty.js", "decoderWorker\\.min\\.wasm": "/__mocks__/empty.js", "waveWorker\\.min\\.js": "/__mocks__/empty.js", - "context-filter-polyfill": "/__mocks__/empty.js", "workers/(.+)\\.worker\\.ts": "/__mocks__/workerMock.js", "^!!raw-loader!.*": "jest-raw-loader", "RecorderWorklet": "/__mocks__/empty.js" diff --git a/res/css/_animations.scss b/res/css/_animations.scss index 4d3ad97141..26252fcaf6 100644 --- a/res/css/_animations.scss +++ b/res/css/_animations.scss @@ -34,18 +34,43 @@ limitations under the License. transition: opacity 300ms ease; } - @keyframes mx--anim-pulse { 0% { opacity: 1; } 50% { opacity: 0.7; } 100% { opacity: 1; } } +@keyframes mx_Dialog_lightbox_background_keyframes { + from { + opacity: 0; + } + to { + opacity: $lightbox-background-bg-opacity; + } +} + +@keyframes mx_ImageView_panel_keyframes { + from { + opacity: 0; + } + to { + opacity: 1; + } +} @media (prefers-reduced-motion) { @keyframes mx--anim-pulse { // Override all keyframes in reduced-motion } + + @keyframes mx_Dialog_lightbox_background_keyframes { + // Override all keyframes in reduced-motion + } + + @keyframes mx_ImageView_panel_keyframes { + // Override all keyframes in reduced-motion + } + .mx_rtg--fade-enter-active { transition: none; } diff --git a/res/css/_common.scss b/res/css/_common.scss index ae565d2fe8..d7f8355d81 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -53,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; @@ -89,7 +89,7 @@ b { } h2 { - color: $primary-fg-color; + color: $primary-content; font-weight: 400; font-size: $font-18px; margin-top: 16px; @@ -142,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 { @@ -173,7 +173,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { .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], @@ -184,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; } @@ -209,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; } } @@ -271,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; @@ -318,6 +318,8 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { .mx_Dialog_lightbox .mx_Dialog_background { opacity: $lightbox-background-bg-opacity; background-color: $lightbox-background-bg-color; + animation-name: mx_Dialog_lightbox_background_keyframes; + animation-duration: 300ms; } .mx_Dialog_lightbox .mx_Dialog { @@ -379,7 +381,7 @@ 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; } @@ -488,8 +490,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 2f9f8f28f1..62ce447dbd 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -28,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"; @@ -133,6 +133,7 @@ @import "./views/elements/_EditableItemList.scss"; @import "./views/elements/_ErrorBoundary.scss"; @import "./views/elements/_EventListSummary.scss"; +@import "./views/elements/_EventTilePreview.scss"; @import "./views/elements/_FacePile.scss"; @import "./views/elements/_Field.scss"; @import "./views/elements/_ImageView.scss"; diff --git a/res/css/structures/_BackdropPanel.scss b/res/css/structures/_BackdropPanel.scss index c7ada2b0a5..482507cb15 100644 --- a/res/css/structures/_BackdropPanel.scss +++ b/res/css/structures/_BackdropPanel.scss @@ -21,19 +21,12 @@ limitations under the License. height: 100vh; width: 100%; overflow: hidden; - - &::before { - content: " "; - position: absolute; - left: 0; - top: 0; - height: 100vh; - width: 100%; - background-color: var(--lp-background-overlay); - } + filter: blur(var(--lp-background-blur)); + // Force a new layer for the backdropPanel so it's better hardware supported + transform: translateZ(0); } -.mx_BackdropPanel--canvas { +.mx_BackdropPanel--image { position: absolute; top: 0; left: 0; @@ -41,11 +34,4 @@ limitations under the License. z-index: 0; pointer-events: none; overflow: hidden; - - &:nth-of-type(2n-1) { - opacity: 0.2; - } - &:nth-of-type(2n) { - opacity: 0.1; - } } 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 c62230edfc..ceea20ed79 100644 --- a/res/css/structures/_GroupFilterPanel.scss +++ b/res/css/structures/_GroupFilterPanel.scss @@ -14,13 +14,23 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_MatrixChat--with-avatar { - .mx_GroupFilterPanel { - background-color: transparent; - } +$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 { + z-index: 1; background-color: $groupFilterPanel-bg-color; flex: 1; cursor: pointer; @@ -63,12 +73,6 @@ limitations under the License. .mx_GroupFilterPanel .mx_TagTile { // opacity: 0.5; position: relative; - - .mx_BetaDot { - position: absolute; - right: -13px; - top: -11px; - } } .mx_GroupFilterPanel .mx_TagTile.mx_TagTile_prototype { @@ -82,13 +86,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 fb660f4194..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; @@ -397,7 +397,7 @@ limitations under the License. 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_AccessibleButton_kind_link { @@ -422,7 +422,7 @@ limitations under the License. mask-position: center; mask-size: 8px; mask-image: url('$(res)/img/image-view/close.svg'); - background-color: $secondary-fg-color; + background-color: $secondary-content; } } } diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index db634cd71f..5ddea244f3 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -14,7 +14,6 @@ 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 { @@ -24,28 +23,38 @@ $roomListCollapsedWidth: 68px; } } +.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; // Create a row-based flexbox for the GroupFilterPanel and the room list display: flex; contain: content; position: relative; - - .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 - } + 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 @@ -137,7 +146,7 @@ $roomListCollapsedWidth: 68px; mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $secondary-fg-color; + background: $secondary-content; } } @@ -160,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 { @@ -178,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 @@ -199,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 90e28fb0a9..fdf5cb1a03 100644 --- a/res/css/structures/_MatrixChat.scss +++ b/res/css/structures/_MatrixChat.scss @@ -47,9 +47,7 @@ limitations under the License. display: flex; flex: 1; - flex-grow: 0; min-height: 0; - max-width: 50%; } .mx_MatrixChat_syncError { @@ -65,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; @@ -93,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..b6219da9e4 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; @@ -183,3 +183,40 @@ limitations under the License. padding: 0; } } + +@media screen and (max-width: 700px) { + .mx_RoomDirectory_roomMemberCount { + padding: 0px; + } + + .mx_AccessibleButton_kind_secondary { + padding: 0px !important; + } + + .mx_RoomDirectory_join { + margin-left: 0px; + } + + .mx_RoomDirectory_alias { + margin-top: 10px; + margin-bottom: 10px; + } + + .mx_RoomDirectory_roomDescription { + padding-bottom: 0px; + } + + .mx_RoomDirectory_name { + margin-bottom: 5px; + } + + .mx_RoomDirectory_roomAvatar { + margin-top: 10px; + } + + .mx_RoomDirectory_table { + grid-template-columns: auto; + row-gap: 14px; + margin-top: 5px; + } +} 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 84f28b5ada..86c2efeb4a 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -14,6 +14,16 @@ 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; @@ -42,7 +52,7 @@ limitations under the License. pointer-events: none; - background-color: $primary-bg-color; + background-color: $background; opacity: 0.95; position: absolute; @@ -89,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 { @@ -155,7 +165,6 @@ limitations under the License. flex: 1; display: flex; flex-direction: column; - contain: content; } .mx_RoomView_statusArea { @@ -163,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; @@ -248,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 88e6a3f494..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; @@ -278,12 +270,12 @@ limitations under the License. } } - li.mx_SpaceRoomDirectory_roomTileWrapper { + li.mx_SpaceHierarchy_roomTileWrapper { list-style: none; } - .mx_SpaceRoomDirectory_roomTile, - .mx_SpaceRoomDirectory_subspace_children { + .mx_SpaceHierarchy_roomTile, + .mx_SpaceHierarchy_subspace_children { &::before { content: ""; position: absolute; @@ -295,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; } } @@ -311,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 e271d6bb00..30d421a351 100644 --- a/res/css/structures/_SpacePanel.scss +++ b/res/css/structures/_SpacePanel.scss @@ -20,13 +20,7 @@ $gutterSize: 16px; $activeBorderTransparentGap: 1px; $activeBackgroundColor: $roomtile-selected-bg-color; -$activeBorderColor: $secondary-fg-color; - -.mx_MatrixChat--with-avatar { - .mx_SpacePanel { - background-color: transparent; - } -} +$activeBorderColor: $secondary-content; .mx_SpacePanel { background-color: $groupFilterPanel-bg-color; @@ -34,6 +28,8 @@ $activeBorderColor: $secondary-fg-color; 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; @@ -107,6 +103,16 @@ $activeBorderColor: $secondary-fg-color; } } + .mx_SpaceItem_new { + position: relative; + + .mx_BetaDot { + position: absolute; + left: 33px; + top: -5px; + } + } + .mx_SpaceItem:not(.hasSubSpaces) > .mx_SpaceButton { margin-left: $gutterSize; min-width: 40px; @@ -118,6 +124,7 @@ $activeBorderColor: $secondary-fg-color; align-items: center; padding: 4px 4px 4px 0; width: 100%; + cursor: pointer; &.mx_SpaceButton_active { &:not(.mx_SpaceButton_narrow) .mx_SpaceButton_selectionWrapper { @@ -142,7 +149,6 @@ $activeBorderColor: $secondary-fg-color; &:not(.mx_SpaceButton_narrow) { .mx_SpaceButton_selectionWrapper { width: 100%; - padding-right: 16px; overflow: hidden; } } @@ -154,7 +160,6 @@ $activeBorderColor: $secondary-fg-color; display: block; text-overflow: ellipsis; overflow: hidden; - padding-right: 8px; font-size: $font-14px; line-height: $font-18px; } @@ -199,22 +204,17 @@ $activeBorderColor: $secondary-fg-color; } &.mx_SpaceButton_new .mx_SpaceButton_icon { - background-color: $accent-color; - transition: all .1s ease-in-out; // TODO transition + background-color: $roomlist-button-bg-color; &::before { - background-color: #ffffff; + background-color: $primary-content; mask-image: url('$(res)/img/element-icons/plus.svg'); transition: all .2s ease-in-out; // TODO transition } } - &.mx_SpaceButton_newCancel .mx_SpaceButton_icon { - background-color: $icon-button-color; - - &::before { - transform: rotate(45deg); - } + &.mx_SpaceButton_newCancel .mx_SpaceButton_icon::before { + transform: rotate(45deg); } .mx_BaseAvatar_image { @@ -228,8 +228,7 @@ $activeBorderColor: $secondary-fg-color; margin-top: auto; margin-bottom: auto; display: none; - position: absolute; - right: 4px; + position: relative; &::before { top: 2px; @@ -242,14 +241,12 @@ $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; } } } .mx_SpacePanel_badgeContainer { - position: absolute; - // Create a flexbox to make aligning dot badges easier display: flex; align-items: center; @@ -267,6 +264,7 @@ $activeBorderColor: $secondary-fg-color; &.collapsed { .mx_SpaceButton { .mx_SpacePanel_badgeContainer { + position: absolute; right: 0; top: 0; @@ -296,19 +294,12 @@ $activeBorderColor: $secondary-fg-color; } &:not(.collapsed) { - .mx_SpacePanel_badgeContainer { - position: absolute; - right: 4px; - } - .mx_SpaceButton:hover, .mx_SpaceButton:focus-within, .mx_SpaceButton_hasMenuOpen { &:not(.mx_SpaceButton_invite) { // Hide the badge container on hover because it'll be a menu button .mx_SpacePanel_badgeContainer { - width: 0; - height: 0; display: none; } diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 945de01eba..812b6dcea9 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,7 @@ $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; } } @@ -207,14 +210,15 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SpaceRoomView_preview_inviter_mxid { line-height: $font-24px; - color: $secondary-fg-color; + color: $secondary-content; } } } - > .mx_BaseAvatar_image, - > .mx_BaseAvatar > .mx_BaseAvatar_image { - border-radius: 12px; + > .mx_RoomAvatar_isSpaceRoom { + &.mx_BaseAvatar_image, .mx_BaseAvatar_image { + border-radius: 12px; + } } h1.mx_SpaceRoomView_preview_name { @@ -224,7 +228,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; @@ -248,6 +252,7 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SpaceRoomView_landing { display: flex; flex-direction: column; + min-width: 0; > .mx_BaseAvatar_image, > .mx_BaseAvatar > .mx_BaseAvatar_image { @@ -257,7 +262,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; @@ -330,7 +335,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; @@ -354,16 +359,11 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SpaceFeedbackPrompt { padding: 7px; // 8px - 1px border - border: 1px solid rgba($primary-fg-color, .1); + 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 { @@ -388,7 +388,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 { @@ -415,7 +415,7 @@ $SpaceRoomViewInnerWidth: 428px; position: absolute; top: 14px; left: 14px; - background-color: $secondary-fg-color; + background-color: $secondary-content; } } @@ -438,7 +438,7 @@ $SpaceRoomViewInnerWidth: 428px; } .mx_SpaceRoomView_inviteTeammates_buttons { - color: $secondary-fg-color; + color: $secondary-content; margin-top: 28px; .mx_AccessibleButton { @@ -454,7 +454,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; @@ -473,7 +473,7 @@ $SpaceRoomViewInnerWidth: 428px; } .mx_SpaceRoomView_info { - color: $secondary-fg-color; + color: $secondary-content; font-size: $font-15px; line-height: $font-24px; margin: 20px 0; @@ -492,7 +492,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 5cd938f1ce..6024df5dc0 100644 --- a/res/css/structures/_ToastContainer.scss +++ b/res/css/structures/_ToastContainer.scss @@ -36,8 +36,8 @@ limitations under the License. .mx_Toast_toast { grid-row: 1 / 3; grid-column: 1; - color: $primary-fg-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/structures/auth/_Login.scss b/res/css/structures/auth/_Login.scss index 9c98ca3a1c..c4aaaca1d0 100644 --- a/res/css/structures/auth/_Login.scss +++ b/res/css/structures/auth/_Login.scss @@ -96,3 +96,10 @@ div.mx_AccessibleButton_kind_link.mx_Login_forgot { cursor: not-allowed; } } +.mx_Login_spinner { + display: flex; + justify-content: center; + align-items: center; + align-content: center; + padding: 14px; +} 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/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..a6b61d3ead 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; } } } @@ -113,6 +113,7 @@ $dot-size: 12px; animation: mx_Beta_bluePulse 2s infinite; animation-iteration-count: 20; position: relative; + pointer-events: none; &::after { 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/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 index afa722e05e..6ff328f6ab 100644 --- a/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss +++ b/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss @@ -23,7 +23,7 @@ limitations under the License. .mx_CreateSpaceFromCommunityDialog { width: 480px; - color: $primary-fg-color; + color: $primary-content; display: flex; flex-direction: column; flex-wrap: nowrap; @@ -73,7 +73,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; @@ -86,7 +86,7 @@ limitations under the License. margin-top: 8px; font-size: $font-15px; line-height: $font-24px; - color: $primary-fg-color; + color: $primary-content; } > * { @@ -112,7 +112,7 @@ limitations under the License. margin-top: 4px; font-size: $font-12px; line-height: $font-15px; - color: $primary-fg-color; + color: $primary-content; } } @@ -138,7 +138,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; 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/_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/test/stores/SpaceStore-setup.ts b/res/css/views/elements/_EventTilePreview.scss similarity index 67% rename from test/stores/SpaceStore-setup.ts rename to res/css/views/elements/_EventTilePreview.scss index 78418d45cc..6bb726168f 100644 --- a/test/stores/SpaceStore-setup.ts +++ b/res/css/views/elements/_EventTilePreview.scss @@ -14,7 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This needs to be executed before the SpaceStore gets imported but due to ES6 import hoisting we have to do this here. -// SpaceStore reads the SettingsStore which needs the localStorage values set at init time. - -localStorage.setItem("mx_labs_feature_feature_spaces", "true"); +.mx_EventTilePreview_loader { + &.mx_IRCLayout, + &.mx_GroupLayout { + padding: 9px 0; + } +} 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 50cd14c4da..71d37a015d 100644 --- a/res/css/views/elements/_Field.scss +++ b/res/css/views/elements/_Field.scss @@ -46,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; } @@ -67,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; } @@ -98,14 +98,14 @@ limitations under the License. transition: font-size 0.25s ease-out 0.1s, color 0.25s ease-out 0.1s, - top 0.25s ease-out 0.1s, + transform 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; + transform: translateY(0); position: absolute; left: 0px; - top: 0px; margin: 7px 8px; padding: 2px; pointer-events: none; // Allow clicks to fall through to the input @@ -124,10 +124,10 @@ limitations under the License. transition: font-size 0.25s ease-out 0s, color 0.25s ease-out 0s, - top 0.25s ease-out 0s, + transform 0.25s ease-out 0s, background-color 0.25s ease-out 0s; font-size: $font-10px; - top: -13px; + transform: translateY(-13px); padding: 0 2px; background-color: $field-focused-label-bg-color; pointer-events: initial; diff --git a/res/css/views/elements/_ImageView.scss b/res/css/views/elements/_ImageView.scss index cf92ffec64..787d33ddc2 100644 --- a/res/css/views/elements/_ImageView.scss +++ b/res/css/views/elements/_ImageView.scss @@ -18,6 +18,10 @@ $button-size: 32px; $icon-size: 22px; $button-gap: 24px; +:root { + --image-view-panel-height: 68px; +} + .mx_ImageView { display: flex; width: 100%; @@ -36,14 +40,24 @@ $button-gap: 24px; .mx_ImageView_image { flex-shrink: 0; + + &.mx_ImageView_image_animating { + transition: transform 200ms ease 0s; + } + + &.mx_ImageView_image_animatingLoading { + transition: transform 300ms ease 0s; + } } .mx_ImageView_panel { width: 100%; - height: 68px; + height: var(--image-view-panel-height); display: flex; justify-content: space-between; align-items: center; + animation-name: mx_ImageView_panel_keyframes; + animation-duration: 300ms; } .mx_ImageView_info_wrapper { @@ -124,3 +138,13 @@ $button-gap: 24px; mask-size: 40%; } } + +@media (prefers-reduced-motion) { + .mx_ImageView_image_animating { + transition: none !important; + } + + .mx_ImageView_image_animatingLoading { + transition: none !important; + } +} 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 afc2c93f79..7934f8f3c2 100644 --- a/res/css/views/messages/_CallEvent.scss +++ b/res/css/views/messages/_CallEvent.scss @@ -41,7 +41,7 @@ limitations under the License. height: 16px; width: 16px; - background-color: $secondary-fg-color; + background-color: $secondary-content; mask-repeat: no-repeat; mask-size: contain; mask-position: center; @@ -116,7 +116,7 @@ limitations under the License. .mx_CallEvent_type { font-weight: 400; - color: $secondary-fg-color; + color: $secondary-content; font-size: 1.2rem; line-height: $font-13px; display: flex; @@ -132,7 +132,7 @@ limitations under the License. position: absolute; height: 13px; width: 13px; - background-color: $secondary-fg-color; + background-color: $secondary-content; mask-repeat: no-repeat; mask-size: contain; } @@ -145,7 +145,7 @@ limitations under the License. display: flex; flex-direction: row; align-items: center; - color: $secondary-fg-color; + color: $secondary-content; margin-right: 16px; gap: 8px; min-width: max-content; diff --git a/res/css/views/messages/_MImageBody.scss b/res/css/views/messages/_MImageBody.scss index b3a62896b2..920c3011f5 100644 --- a/res/css/views/messages/_MImageBody.scss +++ b/res/css/views/messages/_MImageBody.scss @@ -38,7 +38,7 @@ $timelineImageBorderRadius: 4px; } .mx_no-image-placeholder { - background-color: $primary-bg-color; + background-color: $primary-content; } } @@ -100,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..6805036e3d 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 { @@ -92,6 +92,10 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/message-bar/reply.svg'); } +.mx_MessageActionBar_threadButton::after { + mask-image: url('$(res)/img/element-icons/message/thread.svg'); +} + .mx_MessageActionBar_editButton::after { mask-image: url('$(res)/img/element-icons/room/message-bar/edit.svg'); } 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 663682da2e..c137bb7677 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; } } @@ -232,6 +232,10 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/files.svg'); } +.mx_RoomSummaryCard_icon_threads::before { + mask-image: url('$(res)/img/element-icons/message/thread.svg'); +} + .mx_RoomSummaryCard_icon_share::before { mask-image: url('$(res)/img/element-icons/room/share.svg'); } 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..fcdab37f5a 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; + overflow: clip; + display: flex; + flex-direction: column; 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,9 @@ .mx_Autocomplete_Completion_container_pill { margin: 12px; - display: flex; - flex-flow: wrap; + height: 100%; + overflow-y: scroll; + max-height: 35vh; } .mx_Autocomplete_Completion_container_truncate { @@ -68,7 +71,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 +85,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 544a96daba..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 { 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 f270146606..389a5c9706 100644 --- a/res/css/views/rooms/_EventBubbleTile.scss +++ b/res/css/views/rooms/_EventBubbleTile.scss @@ -23,16 +23,24 @@ limitations under the License. } .mx_EventTile[data-layout=bubble] { - position: relative; margin-top: var(--gutterSize); - margin-left: 50px; + margin-left: 49px; margin-right: 100px; + font-size: $font-14px; &.mx_EventTile_continuation { margin-top: 2px; } + &.mx_EventTile_highlight { + &::before { + background-color: $event-highlight-bg-color; + } + + color: $event-highlight-fg-color; + } + /* For replies */ .mx_EventTile { padding-top: 0; @@ -69,10 +77,11 @@ limitations under the License. max-width: 70%; } - .mx_SenderProfile { + > .mx_SenderProfile { position: relative; top: -2px; left: 2px; + font-size: $font-15px; } &[data-self=false] { @@ -188,8 +197,6 @@ limitations under the License. } .mx_ReplyThread { - margin: 0 calc(-1 * var(--gutterSize)); - .mx_EventTile_reply { max-width: 90%; padding: 0; @@ -223,11 +230,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; @@ -284,6 +286,8 @@ limitations under the License. .mx_EventTile_line, .mx_EventTile_info { min-width: 100%; + // Preserve alignment with left edge of text in bubbles + margin: 0; } .mx_EventTile_e2eIcon { @@ -291,9 +295,10 @@ limitations under the License. } .mx_EventTile_line > a { + // Align timestamps with those of normal bubble tiles right: auto; - top: -15px; - left: -68px; + top: -11px; + left: -95px; } } @@ -323,11 +328,10 @@ limitations under the License. } .mx_EventTile_line { - margin: 0 5px; + margin: 0; > a { - left: auto; - right: 0; - transform: translateX(calc(100% + 5px)); + // Align timestamps with those of normal bubble tiles + left: -76px; } } @@ -337,7 +341,8 @@ limitations under the License. } .mx_EventListSummary[data-expanded=false][data-layout=bubble] { - padding: 0 34px; + // Align with left edge of bubble tiles + padding: 0 49px; } /* events that do not require bubble layout */ diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 56cede0895..4495ec4f29 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 { @@ -514,7 +514,7 @@ $hover-select-border: 4px; .mx_EventTile:hover .mx_EventTile_body pre, .mx_EventTile.focus-visible:focus-within .mx_EventTile_body pre { - border: 1px solid #e5e5e5; // deliberate constant as we're behind an invert filter + border: 1px solid $tertiary-content; } .mx_EventTile_pre_container { @@ -618,7 +618,7 @@ $hover-select-border: 4px; } .mx_EventTile_keyRequestInfo_text a { - color: $primary-fg-color; + color: $primary-content; text-decoration: underline; cursor: pointer; } @@ -643,6 +643,7 @@ $hover-select-border: 4px; // Remove some of the default tile padding so that the error is centered margin-right: 0; + .mx_EventTile_line { padding-left: 0; margin-right: 0; @@ -674,3 +675,66 @@ $hover-select-border: 4px; margin-right: 0; } } + +.mx_ThreadInfo:hover { + cursor: pointer; +} + +.mx_ThreadView { + display: flex; + flex-direction: column; + + .mx_ScrollPanel { + margin-top: 20px; + + .mx_RoomView_MessageList { + padding: 0; + } + } + + .mx_EventTile_senderDetails { + display: flex; + align-items: center; + gap: 6px; + margin-bottom: 6px; + + a { + flex: 1; + min-width: none; + max-width: 100%; + display: flex; + align-items: center; + + .mx_SenderProfile { + flex: 1; + } + } + } + + .mx_ThreadView_List { + flex: 1; + overflow: scroll; + } + + .mx_EventTile_roomName { + display: none; + } + + .mx_EventTile_line { + padding-left: 0 !important; + order: 10 !important; + } + + .mx_EventTile { + width: 100%; + display: flex; + flex-direction: column; + margin-top: 0; + padding-bottom: 5px; + margin-bottom: 5px; + } + + .mx_MessageComposer_sendMessage { + margin-right: 0; + } +} 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..9ba966c083 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; @@ -186,11 +186,14 @@ limitations under the License. } .mx_MessageComposer_button { + --size: 26px; position: relative; margin-right: 6px; cursor: pointer; - height: 26px; - width: 26px; + height: var(--size); + line-height: var(--size); + width: auto; + padding-left: calc(var(--size) + 5px); border-radius: 100%; &::before { @@ -207,8 +210,22 @@ limitations under the License. mask-position: center; } - &:hover { - background: rgba($accent-color, 0.1); + &::after { + content: ''; + position: absolute; + left: 0; + top: 0; + z-index: 0; + width: var(--size); + height: var(--size); + border-radius: 50%; + } + + &:hover, + &.mx_MessageComposer_closeButtonMenu { + &::after { + background: rgba($accent-color, 0.1); + } &::before { background-color: $accent-color; @@ -237,10 +254,18 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/composer/sticker.svg'); } +.mx_MessageComposer_buttonMenu::before { + mask-image: url('$(res)/img/image-view/more.svg'); +} + +.mx_MessageComposer_closeButtonMenu::before { + transform: rotate(90deg); + transform-origin: center; +} + .mx_MessageComposer_sendMessage { cursor: pointer; position: relative; - margin-right: 6px; width: 32px; height: 32px; border-radius: 100%; @@ -340,3 +365,28 @@ limitations under the License. height: 50px; } } + +/** + * Unstable compact mode + */ + +.mx_MessageComposer.mx_MessageComposer--compact { + margin-right: 0; + + .mx_MessageComposer_wrapper { + padding: 0 0 0 25px; + } + + .mx_MessageComposer_button:last-child { + margin-right: 0; + } + + .mx_MessageComposer_e2eIcon { + left: 0; + } +} + +.mx_MessageComposer_Menu .mx_CallContextMenu_item { + display: flex; + align-items: center; +} 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..6db2185dd5 100644 --- a/res/css/views/rooms/_RoomSublist.scss +++ b/res/css/views/rooms/_RoomSublist.scss @@ -172,14 +172,12 @@ limitations under the License. } } - // In the general case, we leave height of headers alone even if sticky, so - // that the sublists below them do not jump. However, that leaves a gap - // when scrolled to the top above the first sublist (whose header can only - // ever stick to top), so we force height to 0 for only that first header. - // See also https://github.com/vector-im/element-web/issues/14429. - &:first-child .mx_RoomSublist_headerContainer { - height: 0; - padding-bottom: 4px; + // In the general case, we reserve space for each sublist header to prevent + // scroll jumps when they become sticky. However, that leaves a gap when + // scrolled to the top above the first sublist (whose header can only ever + // stick to top), so we make sure to exclude the first visible sublist. + &:not(.mx_RoomSublist_hidden) ~ .mx_RoomSublist .mx_RoomSublist_headerContainer { + height: 24px; } .mx_RoomSublist_resizeBox { @@ -233,7 +231,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 8196d5c67a..69fe292c0a 100644 --- a/res/css/views/rooms/_VoiceRecordComposerTile.scss +++ b/res/css/views/rooms/_VoiceRecordComposerTile.scss @@ -48,7 +48,7 @@ limitations under the License. .mx_VoiceRecordComposerTile_uploadingState { margin-right: 10px; - color: $secondary-fg-color; + color: $secondary-content; } .mx_VoiceRecordComposerTile_failedState { 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 index 924fe5ae1b..00fb8aba56 100644 --- a/res/css/views/settings/_LayoutSwitcher.scss +++ b/res/css/views/settings/_LayoutSwitcher.scss @@ -21,7 +21,7 @@ limitations under the License. flex-direction: row; gap: 24px; - color: $primary-fg-color; + color: $primary-content; > .mx_LayoutSwitcher_RadioButton { flex-grow: 0; 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 3290a998ab..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; } @@ -72,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; @@ -82,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 d8e617a40d..57c6e9b865 100644 --- a/res/css/views/settings/tabs/user/_AppearanceUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_AppearanceUserSettingsTab.scss @@ -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; @@ -156,7 +156,7 @@ limitations under the License. } .mx_AppearanceUserSettingsTab_Advanced { - color: $primary-fg-color; + color: $primary-content; > * { margin-bottom: 16px; diff --git a/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss b/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss index 4cdfa0b40f..16f607c95f 100644 --- a/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss @@ -21,6 +21,17 @@ limitations under the License. .mx_SettingsTab_section { margin-bottom: 30px; + + > details { + > summary { + cursor: pointer; + color: $primary-content; + } + + & + .mx_SettingsFlag { + margin-top: 20px; + } + } } .mx_PreferencesUserSettingsTab_CommunityMigrator { @@ -30,7 +41,7 @@ limitations under the License. font-weight: $font-semi-bold; font-size: $font-15px; line-height: $font-18px; - color: $primary-fg-color; + color: $primary-content; margin: 16px 0; .mx_BaseAvatar { 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 41536bc8b1..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,7 +40,7 @@ $spacePanelWidth: 71px; > p { font-size: $font-15px; - color: $secondary-fg-color; + color: $secondary-content; } .mx_SpaceFeedbackPrompt { @@ -76,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; @@ -108,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 eb80f2d5cf..cb05b1a977 100644 --- a/res/css/views/toasts/_IncomingCallToast.scss +++ b/res/css/views/toasts/_IncomingCallToast.scss @@ -43,7 +43,7 @@ limitations under the License. .mx_CallEvent_type { font-size: $font-12px; line-height: $font-15px; - color: $tertiary-fg-color; + color: $tertiary-content; margin-top: 4px; margin-bottom: 6px; @@ -62,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; } @@ -139,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/_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 63ca91267f..aa0aa4e2a6 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -74,9 +74,9 @@ limitations under the License. > .mx_VideoFeed { width: 100%; height: 100%; + border-width: 0 !important; // Override mx_VideoFeed_speaking &.mx_VideoFeed_voice { - background-color: $inverted-bg-color; display: flex; justify-content: center; align-items: center; 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 index 014cfce478..0575f4f535 100644 --- a/res/css/views/voip/_CallViewHeader.scss +++ b/res/css/views/voip/_CallViewHeader.scss @@ -53,7 +53,7 @@ limitations under the License. height: 20px; width: 20px; vertical-align: middle; - background-color: $secondary-fg-color; + background-color: $secondary-content; mask-repeat: no-repeat; mask-size: contain; mask-position: center; @@ -90,7 +90,7 @@ limitations under the License. .mx_CallViewHeader_callTypeSmall { font-size: 12px; - color: $secondary-fg-color; + color: $secondary-content; line-height: initial; height: 15px; overflow: hidden; @@ -113,7 +113,7 @@ limitations under the License. height: 16px; width: 16px; - background-color: $secondary-fg-color; + background-color: $secondary-content; mask-repeat: no-repeat; mask-size: contain; mask-position: center; diff --git a/res/css/views/voip/_CallViewSidebar.scss b/res/css/views/voip/_CallViewSidebar.scss index dbadc22028..fd9c76defc 100644 --- a/res/css/views/voip/_CallViewSidebar.scss +++ b/res/css/views/voip/_CallViewSidebar.scss @@ -33,10 +33,9 @@ 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; 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 7a8d39dfe3..1f17a54692 100644 --- a/res/css/views/voip/_VideoFeed.scss +++ b/res/css/views/voip/_VideoFeed.scss @@ -17,12 +17,23 @@ 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 { width: 100%; background-color: transparent; diff --git a/res/img/betas/.gitkeep b/res/img/betas/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/res/img/betas/spaces.png b/res/img/betas/spaces.png deleted file mode 100644 index f4cfa90b4e..0000000000 Binary files a/res/img/betas/spaces.png and /dev/null differ diff --git a/res/img/element-icons/message/thread.svg b/res/img/element-icons/message/thread.svg new file mode 100644 index 0000000000..b4a7cc0066 --- /dev/null +++ b/res/img/element-icons/message/thread.svg @@ -0,0 +1,4 @@ + + + + diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index cce7d6ab67..0bc61d438d 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -20,29 +20,18 @@ $space-nav: rgba($panel-base, 0.1); // unified palette // try to use these colors when possible -$bg-color: $background; -$base-color: $bg-color; -$base-text-color: $primary-content; $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: $primary-content; $text-secondary-color: #B9BEC6; -$quaternary-fg-color: $quaternary-content; $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: $secondary-content; -$tertiary-fg-color: $tertiary-content; - // used for dialog box text $light-fg-color: $header-panel-text-secondary-color; @@ -61,7 +50,7 @@ $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; @@ -82,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. @@ -93,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; @@ -117,11 +106,10 @@ $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; @@ -135,18 +123,16 @@ $composer-e2e-icon-color: $header-panel-text-primary-color; // ******************** $theme-button-bg-color: #e3e8f0; -$dialpad-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: $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); @@ -170,12 +156,12 @@ $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: $primary-content; @@ -198,6 +184,9 @@ $visual-bell-bg-color: #800; $room-warning-bg-color: $header-panel-bg-color; +$authpage-body-bg-color: $background; +$authpage-primary-color: $primary-content; + $dark-panel-bg-color: $header-panel-bg-color; $panel-gradient: rgba(34, 38, 46, 0), rgba(34, 38, 46, 1); @@ -217,21 +206,21 @@ $kbd-border-color: #000000; $tooltip-timeline-bg-color: $groupFilterPanel-bg-color; $tooltip-timeline-fg-color: $primary-content; -$interactive-tooltip-bg-color: $base-color; +$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-fg-color: $secondary-content; $message-body-panel-bg-color: $quinary-content; -$message-body-panel-icon-fg-color: $secondary-fg-color; -$message-body-panel-icon-bg-color: $system; // "System Dark" +$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; @@ -240,9 +229,7 @@ $appearance-tab-border-color: $room-highlight-color; // blur amounts for left left panel (only for element theme) :root { - --llp-background-blur: 160px; - --lp-background-blur: 90px; - --lp-background-overlay: rgba(255, 255, 255, 0.055); + --lp-background-blur: 45px; } $composer-shadow-color: rgba(0, 0, 0, 0.28); @@ -251,7 +238,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/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 3e3412c6c1..d5bc5e6dd7 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -24,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; @@ -117,7 +122,6 @@ $composer-e2e-icon-color: $header-panel-text-primary-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 diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index 3f722bcb30..47247e5e23 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -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; @@ -186,8 +191,6 @@ $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; diff --git a/res/themes/light-custom/css/_custom.scss b/res/themes/light-custom/css/_custom.scss index 6c37351414..455798a556 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); @@ -82,6 +82,8 @@ $tab-label-fg-color: var(--timeline-text-color); // was #4e5054 $authpage-lang-color: var(--timeline-text-color); $roomheader-color: var(--timeline-text-color); +// was #232f32 +$authpage-primary-color: var(--timeline-text-color); // --roomlist-text-secondary-color $roomtile-preview-color: var(--roomlist-text-secondary-color); $roomlist-header-color: var(--roomlist-text-secondary-color); @@ -139,7 +141,7 @@ $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); diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 982ca7cf08..96e5fd7155 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -37,14 +37,9 @@ $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: $secondary-content; -$tertiary-fg-color: #8D99A5; -$quaternary-fg-color: $quaternary-content; $header-panel-bg-color: #f3f8fd; // typical text (dark-on-white in light skin) -$primary-bg-color: $background; $muted-fg-color: #61708b; // Commonly used in headings and relevant alt text // used for dialog box text @@ -59,7 +54,7 @@ $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%; @@ -173,7 +168,6 @@ $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; @@ -191,19 +185,16 @@ $voipcall-plinth-color: $system; // ******************** $theme-button-bg-color: $quinary-content; -$dialpad-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: $background; $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; @@ -318,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; @@ -342,10 +333,10 @@ $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-fg-color: $secondary-content; $message-body-panel-bg-color: $quinary-content; -$message-body-panel-icon-fg-color: $secondary-fg-color; $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. @@ -353,8 +344,8 @@ $voice-record-stop-symbol-color: #ff4b55; $voice-record-live-circle-color: #ff4b55; $voice-record-stop-border-color: $quinary-content; -$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; -$voice-record-icon-color: $tertiary-fg-color; +$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; @@ -363,9 +354,7 @@ $appearance-tab-border-color: $input-darker-bg-color; // blur amounts for left left panel (only for element theme) :root { - --llp-background-blur: 120px; - --lp-background-blur: 60px; - --lp-background-overlay: rgba(0, 0, 0, 0.055); + --lp-background-blur: 40px; } $composer-shadow-color: rgba(0, 0, 0, 0.04); @@ -373,7 +362,7 @@ $composer-shadow-color: rgba(0, 0, 0, 0.04); $eventbubble-self-bg: #F0FBF8; $eventbubble-others-bg: $system; $eventbubble-bg-hover: #FAFBFD; -$eventbubble-avatar-outline: $primary-bg-color; +$eventbubble-avatar-outline: $background; $eventbubble-reply-color: $quaternary-content; // ***** Mixins! ***** diff --git a/scripts/ci/js-sdk-to-release.js b/scripts/ci/js-sdk-to-release.js new file mode 100755 index 0000000000..e1fecfde03 --- /dev/null +++ b/scripts/ci/js-sdk-to-release.js @@ -0,0 +1,17 @@ +#!/usr/bin/env node + +const fsProm = require('fs/promises'); + +const PKGJSON = 'node_modules/matrix-js-sdk/package.json'; + +async function main() { + const pkgJson = JSON.parse(await fsProm.readFile(PKGJSON, 'utf8')); + for (const field of ['main', 'typings']) { + if (pkgJson["matrix_lib_"+field] !== undefined) { + pkgJson[field] = pkgJson["matrix_lib_"+field]; + } + } + await fsProm.writeFile(PKGJSON, JSON.stringify(pkgJson, null, 2)); +} + +main(); diff --git a/scripts/fetchdep.sh b/scripts/fetchdep.sh index 0990af70ce..ec021236d9 100755 --- a/scripts/fetchdep.sh +++ b/scripts/fetchdep.sh @@ -10,6 +10,7 @@ defbranch="$3" rm -r "$defrepo" || true +# A function that clones a branch of a repo based on the org, repo and branch clone() { org=$1 repo=$2 @@ -21,45 +22,38 @@ clone() { fi } -# Try the PR author's branch in case it exists on the deps as well. -# First we check if GITHUB_HEAD_REF is defined, -# Then we check if BUILDKITE_BRANCH is defined, -# if they aren't we can assume this is a Netlify build -if [ -n "$GITHUB_HEAD_REF" ]; then - head=$GITHUB_HEAD_REF -elif [ -n "$BUILDKITE_BRANCH" ]; then - head=$BUILDKITE_BRANCH -else - # Netlify doesn't give us info about the fork so we have to get it from GitHub API - apiEndpoint="https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls/" - apiEndpoint+=$REVIEW_ID - head=$(curl $apiEndpoint | jq -r '.head.label') -fi +# A function that gets info about a PR from the GitHub API based on its number +getPRInfo() { + number=$1 + if [ -n "$number" ]; then + echo "Getting info about a PR with number $number" -# If head is set, it will contain on Buildkite either: -# * "branch" when the author's branch and target branch are in the same repo -# * "fork:branch" when the author's branch is in their fork or if this is a Netlify build -# We can split on `:` into an array to check. -# For GitHub Actions we need to inspect GITHUB_REPOSITORY and GITHUB_ACTOR -# to determine whether the branch is from a fork or not -BRANCH_ARRAY=(${head//:/ }) -if [[ "${#BRANCH_ARRAY[@]}" == "1" ]]; then + apiEndpoint="https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls/" + apiEndpoint+=$number - if [ -n "$GITHUB_HEAD_REF" ]; then - if [[ "$GITHUB_REPOSITORY" == "$deforg"* ]]; then - clone $deforg $defrepo $GITHUB_HEAD_REF - else - REPO_ARRAY=(${GITHUB_REPOSITORY//\// }) - clone $REPO_ARRAY[0] $defrepo $GITHUB_HEAD_REF - fi - else - clone $deforg $defrepo $BUILDKITE_BRANCH + head=$(curl $apiEndpoint | jq -r '.head.label') fi +} -elif [[ "${#BRANCH_ARRAY[@]}" == "2" ]]; then - clone ${BRANCH_ARRAY[0]} $defrepo ${BRANCH_ARRAY[1]} +# Some CIs don't give us enough info, so we just get the PR number and ask the +# GH API for more info - "fork:branch". Some give us this directly. +if [ -n "$BUILDKITE_BRANCH" ]; then + # BuildKite + head=$BUILDKITE_BRANCH +elif [ -n "$PR_NUMBER" ]; then + # GitHub + getPRInfo $PR_NUMBER +elif [ -n "$REVIEW_ID" ]; then + # Netlify + getPRInfo $REVIEW_ID fi +# $head will always be in the format "fork:branch", so we split it by ":" into +# an array. The first element will then be the fork and the second the branch. +# Based on that we clone +BRANCH_ARRAY=(${head//:/ }) +clone ${BRANCH_ARRAY[0]} $defrepo ${BRANCH_ARRAY[1]} + # Try the target branch of the push or PR. if [ -n $GITHUB_BASE_REF ]; then clone $deforg $defrepo $GITHUB_BASE_REF diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 9d6bc2c6fb..8ad93fa960 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -93,6 +93,26 @@ declare global { mxSetupEncryptionStore?: SetupEncryptionStore; mxRoomScrollStateStore?: RoomScrollStateStore; mxOnRecaptchaLoaded?: () => void; + electron?: Electron; + } + + interface DesktopCapturerSource { + id: string; + name: string; + thumbnailURL: string; + } + + interface GetSourcesOptions { + types: Array; + thumbnailSize?: { + height: number; + width: number; + }; + fetchWindowIcons?: boolean; + } + + interface Electron { + getDesktopCapturerSources(options: GetSourcesOptions): Promise>; } interface Document { diff --git a/src/AsyncWrapper.tsx b/src/AsyncWrapper.tsx index ef8924add8..68e33e02fe 100644 --- a/src/AsyncWrapper.tsx +++ b/src/AsyncWrapper.tsx @@ -20,6 +20,8 @@ import * as sdk from './index'; import { _t } from './languageHandler'; import { IDialogProps } from "./components/views/dialogs/IDialogProps"; +import { logger } from "matrix-js-sdk/src/logger"; + type AsyncImport = { default: T }; interface IProps extends IDialogProps { @@ -47,7 +49,7 @@ export default class AsyncWrapper extends React.Component { componentDidMount() { // XXX: temporary logging to try to diagnose // https://github.com/vector-im/element-web/issues/3148 - console.log('Starting load of AsyncWrapper for modal'); + logger.log('Starting load of AsyncWrapper for modal'); this.props.prom.then((result) => { if (this.unmounted) return; diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index e11e828864..bc9ccc4bcd 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -250,7 +250,15 @@ export default class CallHandler extends EventEmitter { * @returns {boolean} */ private areAnyCallsUnsilenced(): boolean { - return this.calls.size > this.silencedCalls.size; + for (const call of this.calls.values()) { + if ( + call.state === CallState.Ringing && + !this.isCallSilenced(call.callId) + ) { + return true; + } + } + return false; } private async checkProtocols(maxTries) { @@ -278,9 +286,9 @@ export default class CallHandler extends EventEmitter { dis.dispatch({ action: Action.VirtualRoomSupportUpdated }); } catch (e) { if (maxTries === 1) { - console.log("Failed to check for protocol support and no retries remain: assuming no support", e); + logger.log("Failed to check for protocol support and no retries remain: assuming no support", e); } else { - console.log("Failed to check for protocol support: will retry", e); + logger.log("Failed to check for protocol support: will retry", e); this.pstnSupportCheckTimer = setTimeout(() => { this.checkProtocols(maxTries - 1); }, 10000); @@ -391,7 +399,7 @@ export default class CallHandler extends EventEmitter { // or chrome doesn't think so and is denying the request. Not sure what // we can really do here... // https://github.com/vector-im/element-web/issues/7657 - console.log("Unable to play audio clip", e); + logger.log("Unable to play audio clip", e); } }; if (this.audioPromises.has(audioId)) { @@ -469,7 +477,7 @@ export default class CallHandler extends EventEmitter { call.on(CallEvent.Replaced, (newCall: MatrixCall) => { if (!this.matchesCallForThisRoom(call)) return; - console.log(`Call ID ${call.callId} is being replaced by call ID ${newCall.callId}`); + logger.log(`Call ID ${call.callId} is being replaced by call ID ${newCall.callId}`); if (call.state === CallState.Ringing) { this.pause(AudioID.Ring); @@ -477,15 +485,15 @@ export default class CallHandler extends EventEmitter { this.pause(AudioID.Ringback); } - this.calls.set(mappedRoomId, newCall); - this.emit(CallHandlerEvent.CallsChanged, this.calls); + this.removeCallForRoom(mappedRoomId); + this.addCallForRoom(mappedRoomId, newCall); this.setCallListeners(newCall); this.setCallState(newCall, newCall.state); }); call.on(CallEvent.AssertedIdentityChanged, async () => { if (!this.matchesCallForThisRoom(call)) return; - console.log(`Call ID ${call.callId} got new asserted identity:`, call.getRemoteAssertedIdentity()); + logger.log(`Call ID ${call.callId} got new asserted identity:`, call.getRemoteAssertedIdentity()); const newAssertedIdentity = call.getRemoteAssertedIdentity().id; let newNativeAssertedIdentity = newAssertedIdentity; @@ -495,7 +503,7 @@ export default class CallHandler extends EventEmitter { newNativeAssertedIdentity = response[0].userid; } } - console.log(`Asserted identity ${newAssertedIdentity} mapped to ${newNativeAssertedIdentity}`); + logger.log(`Asserted identity ${newAssertedIdentity} mapped to ${newNativeAssertedIdentity}`); if (newNativeAssertedIdentity) { this.assertedIdentityNativeUsers[call.callId] = newNativeAssertedIdentity; @@ -508,13 +516,12 @@ export default class CallHandler extends EventEmitter { await ensureDMExists(MatrixClientPeg.get(), newNativeAssertedIdentity); const newMappedRoomId = this.roomIdForCall(call); - console.log(`Old room ID: ${mappedRoomId}, new room ID: ${newMappedRoomId}`); + logger.log(`Old room ID: ${mappedRoomId}, new room ID: ${newMappedRoomId}`); if (newMappedRoomId !== mappedRoomId) { this.removeCallForRoom(mappedRoomId); mappedRoomId = newMappedRoomId; - console.log("Moving call to room " + mappedRoomId); - this.calls.set(mappedRoomId, call); - this.emit(CallHandlerEvent.CallChangeRoom, call); + logger.log("Moving call to room " + mappedRoomId); + this.addCallForRoom(mappedRoomId, call, true); } } }); @@ -649,7 +656,7 @@ export default class CallHandler extends EventEmitter { private setCallState(call: MatrixCall, status: CallState) { const mappedRoomId = CallHandler.sharedInstance().roomIdForCall(call); - console.log( + logger.log( `Call state in ${mappedRoomId} changed to ${status}`, ); @@ -674,7 +681,7 @@ export default class CallHandler extends EventEmitter { } private removeCallForRoom(roomId: string) { - console.log("Removing call for room ", roomId); + logger.log("Removing call for room ", roomId); this.calls.delete(roomId); this.emit(CallHandlerEvent.CallsChanged, this.calls); } @@ -745,12 +752,18 @@ export default class CallHandler extends EventEmitter { logger.debug("Mapped real room " + roomId + " to room ID " + mappedRoomId); const timeUntilTurnCresExpire = MatrixClientPeg.get().getTurnServersExpiry() - Date.now(); - console.log("Current turn creds expire in " + timeUntilTurnCresExpire + " ms"); + logger.log("Current turn creds expire in " + timeUntilTurnCresExpire + " ms"); const call = MatrixClientPeg.get().createCall(mappedRoomId); - console.log("Adding call for room ", roomId); - this.calls.set(roomId, call); - this.emit(CallHandlerEvent.CallsChanged, this.calls); + try { + this.addCallForRoom(roomId, call); + } catch (e) { + Modal.createTrackedDialog('Call Handler', 'Existing Call with user', ErrorDialog, { + title: _t('Already in call'), + description: _t("You're already in a call with this person."), + }); + return; + } if (transferee) { this.transferees[call.callId] = transferee; } @@ -802,13 +815,8 @@ export default class CallHandler extends EventEmitter { return; } - if (this.getCallForRoom(room.roomId)) { - Modal.createTrackedDialog('Call Handler', 'Existing Call with user', ErrorDialog, { - title: _t('Already in call'), - description: _t("You're already in a call with this person."), - }); - return; - } + // We leave the check for whether there's already a call in this room until later, + // otherwise it can race. const members = room.getJoinedMembers(); if (members.length <= 1) { @@ -854,7 +862,7 @@ export default class CallHandler extends EventEmitter { const mappedRoomId = CallHandler.sharedInstance().roomIdForCall(call); if (this.getCallForRoom(mappedRoomId)) { - console.log( + logger.log( "Got incoming call for room " + mappedRoomId + " but there's already a call for this room: ignoring", ); @@ -862,9 +870,8 @@ export default class CallHandler extends EventEmitter { } Analytics.trackEvent('voip', 'receiveCall', 'type', call.type); - console.log("Adding call for room ", mappedRoomId); - this.calls.set(mappedRoomId, call); - this.emit(CallHandlerEvent.CallsChanged, this.calls); + + this.addCallForRoom(mappedRoomId, call); this.setCallListeners(call); // Explicitly handle first state change this.onCallStateChanged(call.state, null, call); @@ -878,6 +885,8 @@ export default class CallHandler extends EventEmitter { break; case 'hangup': case 'reject': + this.stopRingingIfPossible(this.calls.get(payload.room_id).callId); + if (!this.calls.get(payload.room_id)) { return; // no call to hangup } @@ -890,11 +899,15 @@ export default class CallHandler extends EventEmitter { // the hangup event away) break; case 'hangup_all': + this.stopRingingIfPossible(this.calls.get(payload.room_id).callId); + for (const call of this.calls.values()) { call.hangup(CallErrorCode.UserHangup, false); } break; case 'answer': { + this.stopRingingIfPossible(this.calls.get(payload.room_id).callId); + if (!this.calls.has(payload.room_id)) { return; // no call to answer } @@ -929,6 +942,12 @@ export default class CallHandler extends EventEmitter { } }; + private stopRingingIfPossible(callId: string): void { + this.silencedCalls.delete(callId); + if (this.areAnyCallsUnsilenced()) return; + this.pause(AudioID.Ring); + } + private async dialNumber(number: string) { const results = await this.pstnLookup(number); if (!results || results.length === 0 || !results[0].userid) { @@ -947,7 +966,7 @@ export default class CallHandler extends EventEmitter { const nativeLookupResults = await this.sipNativeLookup(userId); const lookupSuccess = nativeLookupResults.length > 0 && nativeLookupResults[0].fields.lookup_success; nativeUserId = lookupSuccess ? nativeLookupResults[0].userid : userId; - console.log("Looked up " + number + " to " + userId + " and mapped to native user " + nativeUserId); + logger.log("Looked up " + number + " to " + userId + " and mapped to native user " + nativeUserId); } else { nativeUserId = userId; } @@ -995,7 +1014,7 @@ export default class CallHandler extends EventEmitter { try { await call.transfer(destination); } catch (e) { - console.log("Failed to transfer call", e); + logger.log("Failed to transfer call", e); Modal.createTrackedDialog('Failed to transfer call', '', ErrorDialog, { title: _t('Transfer Failed'), description: _t('Failed to transfer call'), @@ -1085,7 +1104,7 @@ export default class CallHandler extends EventEmitter { ); WidgetUtils.setRoomWidget(roomId, widgetId, WidgetType.JITSI, widgetUrl, 'Jitsi', widgetData).then(() => { - console.log('Jitsi widget added'); + logger.log('Jitsi widget added'); }).catch((e) => { if (e.errcode === 'M_FORBIDDEN') { Modal.createTrackedDialog('Call Failed', '', ErrorDialog, { @@ -1130,4 +1149,21 @@ export default class CallHandler extends EventEmitter { messaging.transport.send(ElementWidgetActions.HangupCall, {}); }); } + + private addCallForRoom(roomId: string, call: MatrixCall, changedRooms = false): void { + if (this.calls.has(roomId)) { + logger.log(`Couldn't add call to room ${roomId}: already have a call for this room`); + throw new Error("Already have a call for room " + roomId); + } + + logger.log("setting call for room " + roomId); + this.calls.set(roomId, call); + + // Should we always emit CallsChanged too? + if (changedRooms) { + this.emit(CallHandlerEvent.CallChangeRoom, call); + } else { + this.emit(CallHandlerEvent.CallsChanged, this.calls); + } + } } diff --git a/src/ContentMessages.tsx b/src/ContentMessages.tsx index 14a0c1ed51..60242b373a 100644 --- a/src/ContentMessages.tsx +++ b/src/ContentMessages.tsx @@ -39,6 +39,10 @@ import { import { IUpload } from "./models/IUpload"; import { IAbortablePromise, IImageInfo } from "matrix-js-sdk/src/@types/partials"; import { BlurhashEncoder } from "./BlurhashEncoder"; +import SettingsStore from "./settings/SettingsStore"; +import { decorateStartSendingTime, sendRoundTripMetric } from "./sendTimePerformanceMetrics"; + +import { logger } from "matrix-js-sdk/src/logger"; const MAX_WIDTH = 800; const MAX_HEIGHT = 600; @@ -539,6 +543,10 @@ export default class ContentMessages { msgtype: "", // set later }; + if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) { + decorateStartSendingTime(content); + } + // if we have a mime type for the file, add it to the message metadata if (file.type) { content.info.mimetype = file.type; @@ -614,6 +622,11 @@ export default class ContentMessages { }).then(function() { if (upload.canceled) throw new UploadCanceledError(); const prom = matrixClient.sendMessage(roomId, content); + if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) { + prom.then(resp => { + sendRoundTripMetric(matrixClient, roomId, resp.event_id); + }); + } CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, false, false, content); return prom; }, function(err) { @@ -667,13 +680,13 @@ export default class ContentMessages { private ensureMediaConfigFetched(matrixClient: MatrixClient) { if (this.mediaConfig !== null) return; - console.log("[Media Config] Fetching"); + logger.log("[Media Config] Fetching"); return matrixClient.getMediaConfig().then((config) => { - console.log("[Media Config] Fetched config:", config); + logger.log("[Media Config] Fetched config:", config); return config; }).catch(() => { // Media repo can't or won't report limits, so provide an empty object (no limits). - console.log("[Media Config] Could not fetch config, so not limiting uploads."); + logger.log("[Media Config] Could not fetch config, so not limiting uploads."); return {}; }).then((config) => { this.mediaConfig = config; diff --git a/src/CountlyAnalytics.ts b/src/CountlyAnalytics.ts index 72b0462bcd..aa47d3063f 100644 --- a/src/CountlyAnalytics.ts +++ b/src/CountlyAnalytics.ts @@ -30,6 +30,8 @@ const HEARTBEAT_INTERVAL = 5_000; // ms const SESSION_UPDATE_INTERVAL = 60; // seconds const MAX_PENDING_EVENTS = 1000; +export type Rating = 1 | 2 | 3 | 4 | 5; + enum Orientation { Landscape = "landscape", Portrait = "portrait", @@ -451,7 +453,7 @@ export default class CountlyAnalytics { window.removeEventListener("scroll", this.onUserActivity); } - public reportFeedback(rating: 1 | 2 | 3 | 4 | 5, comment: string) { + public reportFeedback(rating: Rating, comment: string) { this.track("[CLY]_star_rating", { rating, comment }, null, {}, true); } @@ -536,7 +538,7 @@ export default class CountlyAnalytics { // sanitize the error from identifiers error = await strReplaceAsync(error, /([!@+#]).+?:[\w:.]+/g, async (substring: string, glyph: string) => { - return glyph + await hashHex(substring.substring(1)); + return glyph + (await hashHex(substring.substring(1))); }); const metrics = this.getMetrics(); diff --git a/src/DateUtils.ts b/src/DateUtils.ts index 5901380ffd..221ecfeb2a 100644 --- a/src/DateUtils.ts +++ b/src/DateUtils.ts @@ -136,6 +136,18 @@ export function formatCallTime(delta: Date): string { return output; } +export function formatSeconds(inSeconds: number): string { + const hours = Math.floor(inSeconds / (60 * 60)).toFixed(0).padStart(2, '0'); + const minutes = Math.floor((inSeconds % (60 * 60)) / 60).toFixed(0).padStart(2, '0'); + const seconds = Math.floor(((inSeconds % (60 * 60)) % 60)).toFixed(0).padStart(2, '0'); + + let output = ""; + if (hours !== "00") output += `${hours}:`; + output += `${minutes}:${seconds}`; + + return output; +} + const MILLIS_IN_DAY = 86400000; export function wantsDateSeparator(prevEventDate: Date, nextEventDate: Date): boolean { if (!nextEventDate || !prevEventDate) { diff --git a/src/DeviceListener.ts b/src/DeviceListener.ts index 51c624e3c3..f218e6c6a7 100644 --- a/src/DeviceListener.ts +++ b/src/DeviceListener.ts @@ -35,6 +35,8 @@ import { isLoggedIn } from './components/structures/MatrixChat'; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { ActionPayload } from "./dispatcher/payloads"; +import { logger } from "matrix-js-sdk/src/logger"; + const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000; export default class DeviceListener { @@ -100,6 +102,7 @@ export default class DeviceListener { * @param {String[]} deviceIds List of device IDs to dismiss notifications for */ async dismissUnverifiedSessions(deviceIds: Iterable) { + logger.log("Dismissing unverified sessions: " + Array.from(deviceIds).join(',')); for (const d of deviceIds) { this.dismissed.add(d); } @@ -210,7 +213,7 @@ export default class DeviceListener { private async recheck() { const cli = MatrixClientPeg.get(); - if (!await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) return; + if (!(await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing"))) return; if (!cli.isCryptoEnabled()) return; // don't recheck until the initial sync is complete: lots of account data events will fire @@ -285,6 +288,9 @@ export default class DeviceListener { } } + logger.log("Old unverified sessions: " + Array.from(oldUnverifiedDeviceIds).join(',')); + logger.log("New unverified sessions: " + Array.from(newUnverifiedDeviceIds).join(',')); + // Display or hide the batch toast for old unverified sessions if (oldUnverifiedDeviceIds.size > 0) { showBulkUnverifiedSessionsToast(oldUnverifiedDeviceIds); diff --git a/src/IdentityAuthClient.js b/src/IdentityAuthClient.js index ffece510de..54cf3b43e3 100644 --- a/src/IdentityAuthClient.js +++ b/src/IdentityAuthClient.js @@ -29,6 +29,8 @@ import { } from './utils/IdentityServerUtils'; import { abbreviateUrl } from './utils/UrlUtils'; +import { logger } from "matrix-js-sdk/src/logger"; + export class AbortedIdentityActionError extends Error {} export default class IdentityAuthClient { @@ -127,7 +129,7 @@ export default class IdentityAuthClient { await this._matrixClient.getIdentityAccount(token); } catch (e) { if (e.errcode === "M_TERMS_NOT_SIGNED") { - console.log("Identity server requires new terms to be agreed to"); + logger.log("Identity server requires new terms to be agreed to"); await startTermsFlow([new Service( SERVICE_TYPES.IS, identityServerUrl, @@ -141,7 +143,7 @@ export default class IdentityAuthClient { if ( !this.tempClient && !doesAccountDataHaveIdentityServer() && - !await doesIdentityServerHaveTerms(identityServerUrl) + !(await doesIdentityServerHaveTerms(identityServerUrl)) ) { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const { finished } = Modal.createTrackedDialog('Default identity server terms warning', '', diff --git a/src/Lifecycle.ts b/src/Lifecycle.ts index e48fd52cb1..57c922aeb7 100644 --- a/src/Lifecycle.ts +++ b/src/Lifecycle.ts @@ -58,6 +58,8 @@ import LazyLoadingDisabledDialog from "./components/views/dialogs/LazyLoadingDis import SessionRestoreErrorDialog from "./components/views/dialogs/SessionRestoreErrorDialog"; import StorageEvictedDialog from "./components/views/dialogs/StorageEvictedDialog"; +import { logger } from "matrix-js-sdk/src/logger"; + const HOMESERVER_URL_KEY = "mx_hs_url"; const ID_SERVER_URL_KEY = "mx_is_url"; @@ -118,7 +120,7 @@ export async function loadSession(opts: ILoadSessionOpts = {}): Promise fragmentQueryParams.guest_user_id && fragmentQueryParams.guest_access_token ) { - console.log("Using guest access credentials"); + logger.log("Using guest access credentials"); return doSetLoggedIn({ userId: fragmentQueryParams.guest_user_id as string, accessToken: fragmentQueryParams.guest_access_token as string, @@ -204,7 +206,7 @@ export function attemptTokenLogin( initial_device_display_name: defaultDeviceDisplayName, }, ).then(function(creds) { - console.log("Logged in with token"); + logger.log("Logged in with token"); return clearStorage().then(async () => { await persistCredentials(creds); // remember that we just logged in @@ -273,7 +275,7 @@ function registerAsGuest( isUrl: string, defaultDeviceDisplayName: string, ): Promise { - console.log(`Doing guest login on ${hsUrl}`); + logger.log(`Doing guest login on ${hsUrl}`); // create a temporary MatrixClient to do the login const client = createClient({ @@ -285,7 +287,7 @@ function registerAsGuest( initial_device_display_name: defaultDeviceDisplayName, }, }).then((creds) => { - console.log(`Registered as guest: ${creds.user_id}`); + logger.log(`Registered as guest: ${creds.user_id}`); return doSetLoggedIn({ userId: creds.user_id, deviceId: creds.device_id, @@ -411,27 +413,27 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }): if (accessToken && userId && hsUrl) { if (ignoreGuest && isGuest) { - console.log("Ignoring stored guest account: " + userId); + logger.log("Ignoring stored guest account: " + userId); return false; } let decryptedAccessToken = accessToken; const pickleKey = await PlatformPeg.get().getPickleKey(userId, deviceId); if (pickleKey) { - console.log("Got pickle key"); + logger.log("Got pickle key"); if (typeof accessToken !== "string") { const encrKey = await pickleKeyToAesKey(pickleKey); decryptedAccessToken = await decryptAES(accessToken, encrKey, "access_token"); encrKey.fill(0); } } else { - console.log("No pickle key available"); + logger.log("No pickle key available"); } const freshLogin = sessionStorage.getItem("mx_fresh_login") === "true"; sessionStorage.removeItem("mx_fresh_login"); - console.log(`Restoring session for ${userId}`); + logger.log(`Restoring session for ${userId}`); await doSetLoggedIn({ userId: userId, deviceId: deviceId, @@ -444,7 +446,7 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }): }, false); return true; } else { - console.log("No previous session found."); + logger.log("No previous session found."); return false; } } @@ -488,9 +490,9 @@ export async function setLoggedIn(credentials: IMatrixClientCreds): Promise { - console.log(`Lifecycle: Starting MatrixClient`); + logger.log(`Lifecycle: Starting MatrixClient`); // dispatch this before starting the matrix client: it's used // to add listeners for the 'sync' event so otherwise we'd have diff --git a/src/Login.ts b/src/Login.ts index a8848210be..bb1ab2ef36 100644 --- a/src/Login.ts +++ b/src/Login.ts @@ -21,6 +21,8 @@ import { MatrixClient } from "matrix-js-sdk/src/client"; import { IMatrixClientCreds } from "./MatrixClientPeg"; import SecurityCustomisations from "./customisations/Security"; +import { logger } from "matrix-js-sdk/src/logger"; + interface ILoginOptions { defaultDeviceDisplayName?: string; } @@ -166,7 +168,7 @@ export default class Login { return sendLoginRequest( this.fallbackHsUrl, this.isUrl, 'm.login.password', loginParams, ).catch((fallbackError) => { - console.log("fallback HS login failed", fallbackError); + logger.log("fallback HS login failed", fallbackError); // throw the original error throw originalError; }); @@ -184,7 +186,7 @@ export default class Login { } throw originalLoginError; }).catch((error) => { - console.log("Login failed", error); + logger.log("Login failed", error); throw error; }); } @@ -218,12 +220,12 @@ export async function sendLoginRequest( if (wellknown) { if (wellknown["m.homeserver"] && wellknown["m.homeserver"]["base_url"]) { hsUrl = wellknown["m.homeserver"]["base_url"]; - console.log(`Overrode homeserver setting with ${hsUrl} from login response`); + logger.log(`Overrode homeserver setting with ${hsUrl} from login response`); } if (wellknown["m.identity_server"] && wellknown["m.identity_server"]["base_url"]) { // TODO: should we prompt here? isUrl = wellknown["m.identity_server"]["base_url"]; - console.log(`Overrode IS setting with ${isUrl} from login response`); + logger.log(`Overrode IS setting with ${isUrl} from login response`); } } diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts index f43351aab2..3860a5c133 100644 --- a/src/MatrixClientPeg.ts +++ b/src/MatrixClientPeg.ts @@ -36,6 +36,8 @@ import { crossSigningCallbacks, tryToUnlockSecretStorageWithDehydrationKey } fro import { SHOW_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode"; import SecurityCustomisations from "./customisations/Security"; +import { logger } from "matrix-js-sdk/src/logger"; + export interface IMatrixClientCreds { homeserverUrl: string; identityServerUrl: string; @@ -166,7 +168,7 @@ class MatrixClientPegClass implements IMatrixClientPeg { for (const dbType of ['indexeddb', 'memory']) { try { const promise = this.matrixClient.store.startup(); - console.log("MatrixClientPeg: waiting for MatrixClient store to initialise"); + logger.log("MatrixClientPeg: waiting for MatrixClient store to initialise"); await promise; break; } catch (err) { @@ -213,6 +215,7 @@ class MatrixClientPegClass implements IMatrixClientPeg { opts.pendingEventOrdering = PendingEventOrdering.Detached; opts.lazyLoadMembers = true; opts.clientWellKnownPollPeriod = 2 * 60 * 60; // 2 hours + opts.experimentalThreadSupport = SettingsStore.getValue("feature_thread"); // Connect the matrix client to the dispatcher and setting handlers MatrixActionCreators.start(this.matrixClient); @@ -224,9 +227,9 @@ class MatrixClientPegClass implements IMatrixClientPeg { public async start(): Promise { const opts = await this.assign(); - console.log(`MatrixClientPeg: really starting MatrixClient`); + logger.log(`MatrixClientPeg: really starting MatrixClient`); await this.get().startClient(opts); - console.log(`MatrixClientPeg: MatrixClient started`); + logger.log(`MatrixClientPeg: MatrixClient started`); } public getCredentials(): IMatrixClientCreds { diff --git a/src/MediaDeviceHandler.ts b/src/MediaDeviceHandler.ts index 073f24523d..154f167745 100644 --- a/src/MediaDeviceHandler.ts +++ b/src/MediaDeviceHandler.ts @@ -17,8 +17,8 @@ limitations under the License. import SettingsStore from "./settings/SettingsStore"; import { SettingLevel } from "./settings/SettingLevel"; -import { setMatrixCallAudioInput, setMatrixCallVideoInput } from "matrix-js-sdk/src/matrix"; import EventEmitter from 'events'; +import { MatrixClientPeg } from "./MatrixClientPeg"; // XXX: MediaDeviceKind is a union type, so we make our own enum export enum MediaDeviceKindEnum { @@ -74,8 +74,8 @@ export default class MediaDeviceHandler extends EventEmitter { const audioDeviceId = SettingsStore.getValue("webrtc_audioinput"); const videoDeviceId = SettingsStore.getValue("webrtc_videoinput"); - setMatrixCallAudioInput(audioDeviceId); - setMatrixCallVideoInput(videoDeviceId); + MatrixClientPeg.get().getMediaHandler().setAudioInput(audioDeviceId); + MatrixClientPeg.get().getMediaHandler().setVideoInput(videoDeviceId); } public setAudioOutput(deviceId: string): void { @@ -90,7 +90,7 @@ export default class MediaDeviceHandler extends EventEmitter { */ public setAudioInput(deviceId: string): void { SettingsStore.setValue("webrtc_audioinput", null, SettingLevel.DEVICE, deviceId); - setMatrixCallAudioInput(deviceId); + MatrixClientPeg.get().getMediaHandler().setAudioInput(deviceId); } /** @@ -100,7 +100,7 @@ export default class MediaDeviceHandler extends EventEmitter { */ public setVideoInput(deviceId: string): void { SettingsStore.setValue("webrtc_videoinput", null, SettingLevel.DEVICE, deviceId); - setMatrixCallVideoInput(deviceId); + MatrixClientPeg.get().getMediaHandler().setVideoInput(deviceId); } public setDevice(deviceId: string, kind: MediaDeviceKindEnum): void { diff --git a/src/Notifier.ts b/src/Notifier.ts index 1137e44aec..81c9bf7f4f 100644 --- a/src/Notifier.ts +++ b/src/Notifier.ts @@ -38,6 +38,8 @@ import UserActivity from "./UserActivity"; import { mediaFromMxc } from "./customisations/Media"; import ErrorDialog from "./components/views/dialogs/ErrorDialog"; +import { logger } from "matrix-js-sdk/src/logger"; + /* * Dispatches: * { @@ -160,7 +162,7 @@ export const Notifier = { _playAudioNotification: async function(ev: MatrixEvent, room: Room) { const sound = this.getSoundForRoom(room.roomId); - console.log(`Got sound ${sound && sound.name || "default"} for ${room.roomId}`); + logger.log(`Got sound ${sound && sound.name || "default"} for ${room.roomId}`); try { const selector = diff --git a/src/PosthogAnalytics.ts b/src/PosthogAnalytics.ts index 860a155aff..bdc0814b5d 100644 --- a/src/PosthogAnalytics.ts +++ b/src/PosthogAnalytics.ts @@ -18,6 +18,10 @@ import posthog, { PostHog } from 'posthog-js'; import PlatformPeg from './PlatformPeg'; import SdkConfig from './SdkConfig'; import SettingsStore from './settings/SettingsStore'; +import { MatrixClientPeg } from "./MatrixClientPeg"; +import { MatrixClient } from "matrix-js-sdk/src/client"; + +import { logger } from "matrix-js-sdk/src/logger"; /* Posthog analytics tracking. * @@ -27,10 +31,11 @@ import SettingsStore from './settings/SettingsStore'; * - If [Do Not Track](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/doNotTrack) is * enabled, events are not sent (this detection is built into posthog and turned on via the * `respect_dnt` flag being passed to `posthog.init`). - * - If the `feature_pseudonymous_analytics_opt_in` labs flag is `true`, track pseudonomously, i.e. - * hash all matrix identifiers in tracking events (user IDs, room IDs etc) using SHA-256. - * - Otherwise, if the existing `analyticsOptIn` flag is `true`, track anonymously, i.e. - * redact all matrix identifiers in tracking events. + * - If the `feature_pseudonymous_analytics_opt_in` labs flag is `true`, track pseudonomously by maintaining + * a randomised analytics ID in account_data for that user (shared between devices) and sending it to posthog to + identify the user. + * - Otherwise, if the existing `analyticsOptIn` flag is `true`, track anonymously, i.e. do not identify the user + using any identifier that would be consistent across devices. * - If both flags are false or not set, events are not sent. */ @@ -71,12 +76,6 @@ interface IPageView extends IAnonymousEvent { }; } -const hashHex = async (input: string): Promise => { - const buf = new TextEncoder().encode(input); - const digestBuf = await window.crypto.subtle.digest("sha-256", buf); - return [...new Uint8Array(digestBuf)].map((b: number) => b.toString(16).padStart(2, "0")).join(""); -}; - const whitelistedScreens = new Set([ "register", "login", "forgot_password", "soft_logout", "new", "settings", "welcome", "home", "start", "directory", "start_sso", "start_cas", "groups", "complete_security", "post_registration", "room", "user", "group", @@ -89,7 +88,6 @@ export async function getRedactedCurrentLocation( anonymity: Anonymity, ): Promise { // Redact PII from the current location. - // If anonymous is true, redact entirely, if false, substitute it with a hash. // For known screens, assumes a URL structure of //might/be/pii if (origin.startsWith('file://')) { pathname = "//"; @@ -99,17 +97,13 @@ export async function getRedactedCurrentLocation( if (hash == "") { hashStr = ""; } else { - let [beforeFirstSlash, screen, ...parts] = hash.split("/"); + let [beforeFirstSlash, screen] = hash.split("/"); if (!whitelistedScreens.has(screen)) { screen = ""; } - for (let i = 0; i < parts.length; i++) { - parts[i] = anonymity === Anonymity.Anonymous ? `` : await hashHex(parts[i]); - } - - hashStr = `${beforeFirstSlash}/${screen}/${parts.join("/")}`; + hashStr = `${beforeFirstSlash}/${screen}/`; } return origin + pathname + hashStr; } @@ -123,15 +117,15 @@ export class PosthogAnalytics { /* Wrapper for Posthog analytics. * 3 modes of anonymity are supported, governed by this.anonymity * - Anonymity.Disabled means *no data* is passed to posthog - * - Anonymity.Anonymous means all identifers will be redacted before being passed to posthog - * - Anonymity.Pseudonymous means all identifiers will be hashed via SHA-256 before being passed - * to Posthog + * - Anonymity.Anonymous means no identifier is passed to posthog + * - Anonymity.Pseudonymous means an analytics ID stored in account_data and shared between devices + * is passed to posthog. * * To update anonymity, call updateAnonymityFromSettings() or you can set it directly via setAnonymity(). * * To pass an event to Posthog: * - * 1. Declare a type for the event, extending IAnonymousEvent, IPseudonymousEvent or IRoomEvent. + * 1. Declare a type for the event, extending IAnonymousEvent or IPseudonymousEvent. * 2. Call the appropriate track*() method. Pseudonymous events will be dropped when anonymity is * Anonymous or Disabled; Anonymous events will be dropped when anonymity is Disabled. */ @@ -141,6 +135,7 @@ export class PosthogAnalytics { private enabled = false; private static _instance = null; private platformSuperProperties = {}; + private static ANALYTICS_ID_EVENT_TYPE = "im.vector.web.analytics_id"; public static get instance(): PosthogAnalytics { if (!this._instance) { @@ -182,7 +177,7 @@ export class PosthogAnalytics { // $redacted_current_url is injected by this class earlier in capture(), as its generation // is async and can't be done in this non-async callback. if (!properties['$redacted_current_url']) { - console.log("$redacted_current_url not set in sanitizeProperties, will drop $current_url entirely"); + logger.log("$redacted_current_url not set in sanitizeProperties, will drop $current_url entirely"); } properties['$current_url'] = properties['$redacted_current_url']; delete properties['$redacted_current_url']; @@ -274,9 +269,32 @@ export class PosthogAnalytics { this.anonymity = anonymity; } - public async identifyUser(userId: string): Promise { + private static getRandomAnalyticsId(): string { + return [...crypto.getRandomValues(new Uint8Array(16))].map((c) => c.toString(16)).join(''); + } + + public async identifyUser(client: MatrixClient, analyticsIdGenerator: () => string): Promise { if (this.anonymity == Anonymity.Pseudonymous) { - this.posthog.identify(await hashHex(userId)); + // Check the user's account_data for an analytics ID to use. Storing the ID in account_data allows + // different devices to send the same ID. + try { + const accountData = await client.getAccountDataFromServer(PosthogAnalytics.ANALYTICS_ID_EVENT_TYPE); + let analyticsID = accountData?.id; + if (!analyticsID) { + // Couldn't retrieve an analytics ID from user settings, so create one and set it on the server. + // Note there's a race condition here - if two devices do these steps at the same time, last write + // wins, and the first writer will send tracking with an ID that doesn't match the one on the server + // until the next time account data is refreshed and this function is called (most likely on next + // page load). This will happen pretty infrequently, so we can tolerate the possibility. + analyticsID = analyticsIdGenerator(); + await client.setAccountData("im.vector.web.analytics_id", { id: analyticsID }); + } + this.posthog.identify(analyticsID); + } catch (e) { + // The above could fail due to network requests, but not essential to starting the application, + // so swallow it. + logger.log("Unable to identify user for tracking" + e.toString()); + } } } @@ -307,18 +325,6 @@ export class PosthogAnalytics { await this.capture(eventName, properties); } - public async trackRoomEvent( - eventName: E["eventName"], - roomId: string, - properties: Omit, - ): Promise { - const updatedProperties = { - ...properties, - hashedRoomId: roomId ? await hashHex(roomId) : null, - }; - await this.trackPseudonymousEvent(eventName, updatedProperties); - } - public async trackPageView(durationMs: number): Promise { const hash = window.location.hash; @@ -349,7 +355,7 @@ export class PosthogAnalytics { // Identify the user (via hashed user ID) to posthog if anonymity is pseudonmyous this.setAnonymity(PosthogAnalytics.getAnonymityFromSettings()); if (userId && this.getAnonymity() == Anonymity.Pseudonymous) { - await this.identifyUser(userId); + await this.identifyUser(MatrixClientPeg.get(), PosthogAnalytics.getRandomAnalyticsId); } } } diff --git a/src/Resend.ts b/src/Resend.ts index 38b84a28e0..0b5c279165 100644 --- a/src/Resend.ts +++ b/src/Resend.ts @@ -20,6 +20,8 @@ import { Room } from 'matrix-js-sdk/src/models/room'; import { MatrixClientPeg } from './MatrixClientPeg'; import dis from './dispatcher/dispatcher'; +import { logger } from "matrix-js-sdk/src/logger"; + export default class Resend { static resendUnsentEvents(room: Room): Promise { return Promise.all(room.getPendingEvents().filter(function(ev: MatrixEvent) { @@ -47,12 +49,7 @@ export default class Resend { }, function(err: Error) { // XXX: temporary logging to try to diagnose // https://github.com/vector-im/element-web/issues/3148 - console.log('Resend got send failure: ' + err.name + '(' + err + ')'); - - dis.dispatch({ - action: 'message_send_failed', - event: event, - }); + logger.log('Resend got send failure: ' + err.name + '(' + err + ')'); }); } diff --git a/src/ScalarAuthClient.ts b/src/ScalarAuthClient.ts index 86dd4b7a0f..e791633c8e 100644 --- a/src/ScalarAuthClient.ts +++ b/src/ScalarAuthClient.ts @@ -25,6 +25,8 @@ import { WidgetType } from "./widgets/WidgetType"; import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types"; import { Room } from "matrix-js-sdk/src/models/room"; +import { logger } from "matrix-js-sdk/src/logger"; + // The version of the integration manager API we're intending to work with const imApiVersion = "1.1"; @@ -136,7 +138,7 @@ export default class ScalarAuthClient { return token; }).catch((e) => { if (e instanceof TermsNotSignedError) { - console.log("Integration manager requires new terms to be agreed to"); + logger.log("Integration manager requires new terms to be agreed to"); // The terms endpoints are new and so live on standard _matrix prefixes, // but IM rest urls are currently configured with paths, so remove the // path from the base URL before passing it to the js-sdk diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 600241bc06..609ac5c67c 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -245,6 +245,8 @@ import { IntegrationManagers } from "./integrations/IntegrationManagers"; import { WidgetType } from "./widgets/WidgetType"; import { objectClone } from "./utils/objects"; +import { logger } from "matrix-js-sdk/src/logger"; + function sendResponse(event, res) { const data = objectClone(event.data); data.response = res; @@ -266,7 +268,7 @@ function sendError(event, msg, nestedError) { } function inviteUser(event, roomId, userId) { - console.log(`Received request to invite ${userId} into room ${roomId}`); + logger.log(`Received request to invite ${userId} into room ${roomId}`); const client = MatrixClientPeg.get(); if (!client) { sendError(event, _t('You need to be logged in.')); @@ -400,7 +402,7 @@ function setPlumbingState(event, roomId, status) { if (typeof status !== 'string') { throw new Error('Plumbing state status should be a string'); } - console.log(`Received request to set plumbing state to status "${status}" in room ${roomId}`); + logger.log(`Received request to set plumbing state to status "${status}" in room ${roomId}`); const client = MatrixClientPeg.get(); if (!client) { sendError(event, _t('You need to be logged in.')); @@ -416,7 +418,7 @@ function setPlumbingState(event, roomId, status) { } function setBotOptions(event, roomId, userId) { - console.log(`Received request to set options for bot ${userId} in room ${roomId}`); + logger.log(`Received request to set options for bot ${userId} in room ${roomId}`); const client = MatrixClientPeg.get(); if (!client) { sendError(event, _t('You need to be logged in.')); @@ -437,7 +439,7 @@ function setBotPower(event, roomId, userId, level) { return; } - console.log(`Received request to set power level to ${level} for bot ${userId} in room ${roomId}.`); + logger.log(`Received request to set power level to ${level} for bot ${userId} in room ${roomId}.`); const client = MatrixClientPeg.get(); if (!client) { sendError(event, _t('You need to be logged in.')); @@ -463,17 +465,17 @@ function setBotPower(event, roomId, userId, level) { } function getMembershipState(event, roomId, userId) { - console.log(`membership_state of ${userId} in room ${roomId} requested.`); + logger.log(`membership_state of ${userId} in room ${roomId} requested.`); returnStateEvent(event, roomId, "m.room.member", userId); } function getJoinRules(event, roomId) { - console.log(`join_rules of ${roomId} requested.`); + logger.log(`join_rules of ${roomId} requested.`); returnStateEvent(event, roomId, "m.room.join_rules", ""); } function botOptions(event, roomId, userId) { - console.log(`bot_options of ${userId} in room ${roomId} requested.`); + logger.log(`bot_options of ${userId} in room ${roomId} requested.`); returnStateEvent(event, roomId, "m.room.bot.options", "_" + userId); } diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts index 370b21b396..925b023584 100644 --- a/src/SecurityManager.ts +++ b/src/SecurityManager.ts @@ -31,6 +31,8 @@ import SettingsStore from "./settings/SettingsStore"; import SecurityCustomisations from "./customisations/Security"; import { DeviceTrustLevel } from 'matrix-js-sdk/src/crypto/CrossSigning'; +import { logger } from "matrix-js-sdk/src/logger"; + // This stores the secret storage private keys in memory for the JS SDK. This is // only meant to act as a cache to avoid prompting the user multiple times // during the same single operation. Use `accessSecretStorage` below to scope a @@ -136,7 +138,7 @@ async function getSecretStorageKey( const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.(); if (keyFromCustomisations) { - console.log("Using key from security customisations (secret storage)"); + logger.log("Using key from security customisations (secret storage)"); cacheSecretStorageKey(keyId, keyInfo, keyFromCustomisations); return [keyId, keyFromCustomisations]; } @@ -186,7 +188,7 @@ export async function getDehydrationKey( ): Promise { const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.(); if (keyFromCustomisations) { - console.log("Using key from security customisations (dehydration)"); + logger.log("Using key from security customisations (dehydration)"); return keyFromCustomisations; } @@ -248,13 +250,13 @@ async function onSecretRequested( name: string, deviceTrust: DeviceTrustLevel, ): Promise { - console.log("onSecretRequested", userId, deviceId, requestId, name, deviceTrust); + logger.log("onSecretRequested", userId, deviceId, requestId, name, deviceTrust); const client = MatrixClientPeg.get(); if (userId !== client.getUserId()) { return; } if (!deviceTrust || !deviceTrust.isVerified()) { - console.log(`Ignoring secret request from untrusted device ${deviceId}`); + logger.log(`Ignoring secret request from untrusted device ${deviceId}`); return; } if ( @@ -267,7 +269,7 @@ async function onSecretRequested( const keyId = name.replace("m.cross_signing.", ""); const key = await callbacks.getCrossSigningKeyCache(keyId); if (!key) { - console.log( + logger.log( `${keyId} requested by ${deviceId}, but not found in cache`, ); } @@ -275,7 +277,7 @@ async function onSecretRequested( } else if (name === "m.megolm_backup.v1") { const key = await client.crypto.getSessionBackupPrivateKey(); if (!key) { - console.log( + logger.log( `session backup key requested by ${deviceId}, but not found in cache`, ); } @@ -329,7 +331,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f const cli = MatrixClientPeg.get(); secretStorageBeingAccessed = true; try { - if (!await cli.hasSecretStorageKey() || forceReset) { + if (!(await cli.hasSecretStorageKey()) || forceReset) { // This dialog calls bootstrap itself after guiding the user through // passphrase creation. const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '', @@ -383,12 +385,12 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f if (secretStorageKeyInfo[keyId] && secretStorageKeyInfo[keyId].passphrase) { dehydrationKeyInfo = { passphrase: secretStorageKeyInfo[keyId].passphrase }; } - console.log("Setting dehydration key"); + logger.log("Setting dehydration key"); await cli.setDehydrationKey(secretStorageKeys[keyId], dehydrationKeyInfo, "Backup device"); } else if (!keyId) { console.warn("Not setting dehydration key: no SSSS key found"); } else { - console.log("Not setting dehydration key: feature disabled"); + logger.log("Not setting dehydration key: feature disabled"); } } @@ -416,8 +418,8 @@ export async function tryToUnlockSecretStorageWithDehydrationKey( ): Promise { const key = dehydrationCache.key; let restoringBackup = false; - if (key && await client.isSecretStorageReady()) { - console.log("Trying to set up cross-signing using dehydration key"); + if (key && (await client.isSecretStorageReady())) { + logger.log("Trying to set up cross-signing using dehydration key"); secretStorageBeingAccessed = true; nonInteractive = true; try { diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index b4deb6d8c4..f3214c4757 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -50,12 +50,13 @@ import CallHandler from "./CallHandler"; import { guessAndSetDMRoom } from "./Rooms"; import { upgradeRoom } from './utils/RoomUpgrade'; import UploadConfirmDialog from './components/views/dialogs/UploadConfirmDialog'; -import ErrorDialog from './components/views/dialogs/ErrorDialog'; import DevtoolsDialog from './components/views/dialogs/DevtoolsDialog'; import RoomUpgradeWarningDialog from "./components/views/dialogs/RoomUpgradeWarningDialog"; import InfoDialog from "./components/views/dialogs/InfoDialog"; import SlashCommandHelpDialog from "./components/views/dialogs/SlashCommandHelpDialog"; +import { logger } from "matrix-js-sdk/src/logger"; + // XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816 interface HTMLInputEvent extends Event { target: HTMLInputElement & EventTarget; @@ -245,21 +246,6 @@ export const Commands = [ }, category: CommandCategories.messages, }), - new Command({ - command: 'ddg', - args: '', - description: _td('Searches DuckDuckGo for results'), - runFn: function() { - // TODO Don't explain this away, actually show a search UI here. - Modal.createTrackedDialog('Slash Commands', '/ddg is not a command', ErrorDialog, { - title: _t('/ddg is not a command'), - description: _t('To use it, just wait for autocomplete results to load and tab through them.'), - }); - return success(); - }, - category: CommandCategories.actions, - hideCompletionAfterSpace: true, - }), new Command({ command: 'upgraderoom', args: '', @@ -307,7 +293,7 @@ export const Commands = [ const cli = MatrixClientPeg.get(); const ev = cli.getRoom(roomId).currentState.getStateEvents('m.room.member', cli.getUserId()); const content = { - ...ev ? ev.getContent() : { membership: 'join' }, + ...(ev ? ev.getContent() : { membership: 'join' }), displayname: args, }; return success(cli.sendStateEvent(roomId, 'm.room.member', content, cli.getUserId())); @@ -351,7 +337,7 @@ export const Commands = [ if (!url) return; const ev = room.currentState.getStateEvents('m.room.member', userId); const content = { - ...ev ? ev.getContent() : { membership: 'join' }, + ...(ev ? ev.getContent() : { membership: 'join' }), avatar_url: url, }; return cli.sendStateEvent(roomId, 'm.room.member', content, userId); @@ -817,7 +803,7 @@ export const Commands = [ const iframe = embed.childNodes[0] as ChildElement; if (iframe.tagName.toLowerCase() === 'iframe' && iframe.attrs) { const srcAttr = iframe.attrs.find(a => a.name === 'src'); - console.log("Pulling URL out of iframe (embed code)"); + logger.log("Pulling URL out of iframe (embed code)"); widgetUrl = srcAttr.value; } } @@ -837,7 +823,7 @@ export const Commands = [ // Make the widget a Jitsi widget if it looks like a Jitsi widget const jitsiData = Jitsi.getInstance().parsePreferredConferenceUrl(widgetUrl); if (jitsiData) { - console.log("Making /addwidget widget a Jitsi conference"); + logger.log("Making /addwidget widget a Jitsi conference"); type = WidgetType.JITSI; name = "Jitsi Conference"; data = jitsiData; diff --git a/src/Terms.ts b/src/Terms.ts index 351d1c0951..86d006c832 100644 --- a/src/Terms.ts +++ b/src/Terms.ts @@ -21,6 +21,8 @@ import { MatrixClientPeg } from './MatrixClientPeg'; import * as sdk from '.'; import Modal from './Modal'; +import { logger } from "matrix-js-sdk/src/logger"; + export class TermsNotSignedError extends Error {} /** @@ -140,11 +142,11 @@ export async function startTermsFlow( const numAcceptedBeforeAgreement = agreedUrlSet.size; if (unagreedPoliciesAndServicePairs.length > 0) { const newlyAgreedUrls = await interactionCallback(unagreedPoliciesAndServicePairs, [...agreedUrlSet]); - console.log("User has agreed to URLs", newlyAgreedUrls); + logger.log("User has agreed to URLs", newlyAgreedUrls); // Merge with previously agreed URLs newlyAgreedUrls.forEach(url => agreedUrlSet.add(url)); } else { - console.log("User has already agreed to all required policies"); + logger.log("User has already agreed to all required policies"); } // We only ever add to the set of URLs, so if anything has changed then we'd see a different length @@ -188,7 +190,7 @@ export function dialogTermsInteractionCallback( extraClassNames?: string, ): Promise { return new Promise((resolve, reject) => { - console.log("Terms that need agreement", policiesAndServicePairs); + logger.log("Terms that need agreement", policiesAndServicePairs); // FIXME: Using an import will result in test failures const TermsDialog = sdk.getComponent("views.dialogs.TermsDialog"); diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx index 5f4ae4a702..6fb4107d20 100644 --- a/src/TextForEvent.tsx +++ b/src/TextForEvent.tsx @@ -462,6 +462,15 @@ function textForPowerEvent(event: MatrixEvent): () => string | null { }); } +const onPinnedOrUnpinnedMessageClick = (messageId: string, roomId: string): void => { + defaultDispatcher.dispatch({ + action: 'view_room', + event_id: messageId, + highlighted: true, + room_id: roomId, + }); +}; + const onPinnedMessagesClick = (): void => { defaultDispatcher.dispatch({ action: Action.SetRightPanelPhase, @@ -473,17 +482,77 @@ const onPinnedMessagesClick = (): void => { function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string | JSX.Element | null { if (!SettingsStore.getValue("feature_pinning")) return null; const senderName = event.sender ? event.sender.name : event.getSender(); + const roomId = event.getRoomId(); + + const pinned = event.getContent().pinned ?? []; + const previouslyPinned = event.getPrevContent().pinned ?? []; + const newlyPinned = pinned.filter(item => previouslyPinned.indexOf(item) < 0); + const newlyUnpinned = previouslyPinned.filter(item => pinned.indexOf(item) < 0); + + if (newlyPinned.length === 1 && newlyUnpinned.length === 0) { + // A single message was pinned, include a link to that message. + if (allowJSX) { + const messageId = newlyPinned.pop(); + + return () => ( + + { _t( + "%(senderName)s pinned a message to this room. See all pinned messages.", + { senderName }, + { + "a": (sub) => + onPinnedOrUnpinnedMessageClick(messageId, roomId)}> + { sub } + , + "b": (sub) => + + { sub } + , + }, + ) } + + ); + } + + return () => _t("%(senderName)s pinned a message to this room. See all pinned messages.", { senderName }); + } + + if (newlyUnpinned.length === 1 && newlyPinned.length === 0) { + // A single message was unpinned, include a link to that message. + if (allowJSX) { + const messageId = newlyUnpinned.pop(); + + return () => ( + + { _t( + "%(senderName)s unpinned a message from this room. See all pinned messages.", + { senderName }, + { + "a": (sub) => + onPinnedOrUnpinnedMessageClick(messageId, roomId)}> + { sub } + , + "b": (sub) => + + { sub } + , + }, + ) } + + ); + } + + return () => _t("%(senderName)s unpinned a message from this room. See all pinned messages.", { senderName }); + } if (allowJSX) { return () => ( - { - _t( - "%(senderName)s changed the pinned messages for the room.", - { senderName }, - { "a": (sub) => { sub } }, - ) - } + { _t( + "%(senderName)s changed the pinned messages for the room.", + { senderName }, + { "a": (sub) => { sub } }, + ) } ); } diff --git a/src/VoipUserMapper.ts b/src/VoipUserMapper.ts index dacb4262bd..e2e590548e 100644 --- a/src/VoipUserMapper.ts +++ b/src/VoipUserMapper.ts @@ -20,6 +20,8 @@ import DMRoomMap from "./utils/DMRoomMap"; import CallHandler, { VIRTUAL_ROOM_EVENT_TYPE } from './CallHandler'; import { Room } from 'matrix-js-sdk/src/models/room'; +import { logger } from "matrix-js-sdk/src/logger"; + // Functions for mapping virtual users & rooms. Currently the only lookup // is sip virtual: there could be others in the future. @@ -59,7 +61,7 @@ export default class VoipUserMapper { public nativeRoomForVirtualRoom(roomId: string): string { const cachedNativeRoomId = this.virtualToNativeRoomIdCache.get(roomId); if (cachedNativeRoomId) { - console.log( + logger.log( "Returning native room ID " + cachedNativeRoomId + " for virtual room ID " + roomId + " from cache", ); return cachedNativeRoomId; @@ -98,7 +100,7 @@ export default class VoipUserMapper { if (!CallHandler.sharedInstance().getSupportsVirtualRooms()) return; const inviterId = invitedRoom.getDMInviter(); - console.log(`Checking virtual-ness of room ID ${invitedRoom.roomId}, invited by ${inviterId}`); + logger.log(`Checking virtual-ness of room ID ${invitedRoom.roomId}, invited by ${inviterId}`); const result = await CallHandler.sharedInstance().sipNativeLookup(inviterId); if (result.length === 0) { return; diff --git a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx index 2748fda35a..ac7875b920 100644 --- a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx +++ b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx @@ -26,10 +26,9 @@ import { SettingLevel } from "../../../../settings/SettingLevel"; import Field from '../../../../components/views/elements/Field'; import BaseDialog from "../../../../components/views/dialogs/BaseDialog"; import DialogButtons from "../../../../components/views/elements/DialogButtons"; +import { IDialogProps } from "../../../../components/views/dialogs/IDialogProps"; -interface IProps { - onFinished: (confirmed: boolean) => void; -} +interface IProps extends IDialogProps {} interface IState { eventIndexSize: number; diff --git a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js index 641df4f897..5fbc97d2f1 100644 --- a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js @@ -34,6 +34,8 @@ import RestoreKeyBackupDialog from "../../../../components/views/dialogs/securit import { getSecureBackupSetupMethods, isSecureBackupRequired } from '../../../../utils/WellKnownUtils'; import SecurityCustomisations from "../../../../customisations/Security"; +import { logger } from "matrix-js-sdk/src/logger"; + const PHASE_LOADING = 0; const PHASE_LOADERROR = 1; const PHASE_CHOOSE_KEY_PASSPHRASE = 2; @@ -122,7 +124,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { _getInitialPhase() { const keyFromCustomisations = SecurityCustomisations.createSecretStorageKey?.(); if (keyFromCustomisations) { - console.log("Created key via customisations, jumping to bootstrap step"); + logger.log("Created key via customisations, jumping to bootstrap step"); this._recoveryKey = { privateKey: keyFromCustomisations, }; @@ -138,7 +140,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion(); const backupSigStatus = ( // we may not have started crypto yet, in which case we definitely don't trust the backup - MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo) + MatrixClientPeg.get().isCryptoEnabled() && (await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo)) ); const { forceReset } = this.props; @@ -165,10 +167,10 @@ export default class CreateSecretStorageDialog extends React.PureComponent { // We should never get here: the server should always require // UI auth to upload device signing keys. If we do, we upload // no keys which would be a no-op. - console.log("uploadDeviceSigningKeys unexpectedly succeeded without UI auth!"); + logger.log("uploadDeviceSigningKeys unexpectedly succeeded without UI auth!"); } catch (error) { if (!error.data || !error.data.flows) { - console.log("uploadDeviceSigningKeys advertised no flows!"); + logger.log("uploadDeviceSigningKeys advertised no flows!"); return; } const canUploadKeysWithPasswordOnly = error.data.flows.some(f => { @@ -304,7 +306,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { try { if (forceReset) { - console.log("Forcing secret storage reset"); + logger.log("Forcing secret storage reset"); await cli.bootstrapSecretStorage({ createSecretStorageKey: async () => this._recoveryKey, setupNewKeyBackup: true, diff --git a/src/audio/ManagedPlayback.ts b/src/audio/ManagedPlayback.ts index bff6ce7088..5db07671f1 100644 --- a/src/audio/ManagedPlayback.ts +++ b/src/audio/ManagedPlayback.ts @@ -26,7 +26,7 @@ export class ManagedPlayback extends Playback { } public async play(): Promise { - this.manager.playOnly(this); + this.manager.pauseAllExcept(this); return super.play(); } diff --git a/src/audio/Playback.ts b/src/audio/Playback.ts index 9dad828a79..9ad4c85df5 100644 --- a/src/audio/Playback.ts +++ b/src/audio/Playback.ts @@ -23,6 +23,8 @@ import { PlaybackClock } from "./PlaybackClock"; import { createAudioContext, decodeOgg } from "./compat"; import { clamp } from "../utils/numbers"; +import { logger } from "matrix-js-sdk/src/logger"; + export enum PlaybackState { Decoding = "decoding", Stopped = "stopped", // no progress on timeline @@ -117,6 +119,8 @@ export class Playback extends EventEmitter implements IDestroyable { } public destroy() { + // Dev note: It's critical that we call stop() during cleanup to ensure that downstream callers + // are aware of the final clock position before the user triggered an unload. // noinspection JSIgnoredPromiseFromCall - not concerned about being called async here this.stop(); this.removeAllListeners(); @@ -137,7 +141,7 @@ export class Playback extends EventEmitter implements IDestroyable { // audio buffer in memory, as that can balloon to far greater than the input buffer's // byte length. if (this.buf.byteLength > 5 * 1024 * 1024) { // 5mb - console.log("Audio file too large: processing through