diff --git a/.editorconfig b/.editorconfig index 880331a09e5..56631484cd5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -21,3 +21,6 @@ insert_final_newline = true indent_style = space indent_size = 4 trim_trailing_whitespace = true + +[*.{yml,yaml}] +indent_size = 2 diff --git a/.eslintignore b/.eslintignore index b715bcd4f69..5d117f54b54 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,5 +1,6 @@ -src/component-index.js test/end-to-end-tests/node_modules/ test/end-to-end-tests/element/ test/end-to-end-tests/synapse/ test/end-to-end-tests/lib/ +# Legacy skinning file that some people might still have +src/component-index.js diff --git a/.eslintrc.js b/.eslintrc.js index 45cd05506f6..67e6ab1e642 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -92,6 +92,7 @@ module.exports = { files: [ "src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}", + "cypress/**/*.ts", ], extends: [ "plugin:matrix-org/typescript", @@ -123,7 +124,6 @@ module.exports = { "src/components/structures/UserMenu.tsx", "src/components/views/avatars/WidgetAvatar.tsx", "src/components/views/dialogs/AddExistingToSpaceDialog.tsx", - "src/components/views/dialogs/CreateSpaceFromCommunityDialog.tsx", "src/components/views/dialogs/ForwardDialog.tsx", "src/components/views/dialogs/InviteDialog.tsx", "src/components/views/dialogs/ModalWidgetDialog.tsx", diff --git a/.github/codecov.yml b/.github/codecov.yml new file mode 100644 index 00000000000..449fa0a733a --- /dev/null +++ b/.github/codecov.yml @@ -0,0 +1,12 @@ +codecov: + allow_coverage_offsets: True +coverage: + status: + project: off + patch: off +comment: + layout: "diff, files" + behavior: default + require_changes: false + require_base: no + require_head: no diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml deleted file mode 100644 index 456c97d5807..00000000000 --- a/.github/workflows/develop.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Develop -on: - # These tests won't work for non-develop branches at the moment as they - # won't pull in the right versions of other repos, so they're only enabled - # on develop. - push: - branches: [develop] - pull_request: - branches: [develop] -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 - uses: actions/checkout@v2 - - name: Prepare End-to-End tests - run: ./scripts/ci/prepare-end-to-end-tests.sh - - name: Run End-to-End tests - run: ./scripts/ci/run-end-to-end-tests.sh - - name: Archive logs - uses: actions/upload-artifact@v2 - if: ${{ always() }} - with: - path: | - test/end-to-end-tests/logs/**/* - test/end-to-end-tests/synapse/installations/consent/homeserver.log - retention-days: 14 - - name: Download previous benchmark data - uses: actions/cache@v1 - with: - path: ./cache - key: ${{ runner.os }}-benchmark - - name: Store benchmark result - uses: matrix-org/github-action-benchmark@jsperfentry-1 - with: - tool: 'jsperformanceentry' - output-file-path: test/end-to-end-tests/performance-entries.json - fail-on-alert: false - comment-on-alert: false - # Only temporary to monitor where failures occur - alert-comment-cc-users: '@gsouquet' - github-token: ${{ secrets.DEPLOY_GH_PAGES }} - auto-push: ${{ github.ref == 'refs/heads/develop' }} diff --git a/.github/workflows/element-build-and-test.yaml b/.github/workflows/element-build-and-test.yaml new file mode 100644 index 00000000000..9b3d0f373a0 --- /dev/null +++ b/.github/workflows/element-build-and-test.yaml @@ -0,0 +1,102 @@ +# Produce a build of element-web with this version of react-sdk +# and any matching branches of element-web and js-sdk, output it +# as an artifact and run integration tests. +name: Element Web - Build and Test +on: + pull_request: { } + push: + branches: [ develop, master ] + repository_dispatch: + types: [ upstream-sdk-notify ] +env: + # These must be set for fetchdep.sh to get the right branch + REPOSITORY: ${{ github.repository }} + PR_NUMBER: ${{ github.event.pull_request.number }} +jobs: + build: + name: "Build Element-Web" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v3 + with: + cache: 'yarn' + + - name: Fetch layered build + id: layered_build + run: | + scripts/ci/layered.sh + JSSDK_SHA=$(git -C matrix-js-sdk rev-parse --short=12 HEAD) + REACT_SHA=$(git rev-parse --short=12 HEAD) + VECTOR_SHA=$(git -C element-web rev-parse --short=12 HEAD) + echo "::set-output name=VERSION::$VECTOR_SHA-react-$REACT_SHA-js-$JSSDK_SHA" + + - name: Copy config + run: cp element.io/develop/config.json config.json + working-directory: ./element-web + + - name: Build + env: + CI_PACKAGE: true + VERSION: "${{ steps.layered_build.outputs.VERSION }}" + run: yarn build + working-directory: ./element-web + + - name: Upload Artifact + uses: actions/upload-artifact@v2 + with: + name: previewbuild + path: element-web/webapp + # We'll only use this in a triggered job, then we're done with it + retention-days: 1 + + cypress: + name: "Cypress End to End Tests" + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Download build + uses: actions/download-artifact@v3 + with: + name: previewbuild + path: webapp + + - name: Run Cypress tests + uses: cypress-io/github-action@v2 + with: + # The built in Electron runner seems to grind to a halt trying + # to run the tests, so use chrome. + browser: chrome + start: npx serve -p 8080 webapp + record: true + env: + # pass the Dashboard record key as an environment variable + CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} + # pass GitHub token to allow accurately detecting a build vs a re-run build + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload Artifact + if: failure() + uses: actions/upload-artifact@v2 + with: + name: cypress-results + path: | + cypress/screenshots + cypress/videos + cypress/synapselogs + + app-tests: + name: Element Web Integration Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v3 + with: + cache: 'yarn' + + - name: Run tests + run: "./scripts/ci/app-tests.sh" diff --git a/.github/workflows/end-to-end-tests.yaml b/.github/workflows/end-to-end-tests.yaml new file mode 100644 index 00000000000..6c663a0e018 --- /dev/null +++ b/.github/workflows/end-to-end-tests.yaml @@ -0,0 +1,59 @@ +name: End-to-end Tests +on: + # These tests won't work for non-develop branches at the moment as they + # won't pull in the right versions of other repos, so they're only enabled + # on develop. + push: + branches: [ develop ] + pull_request: + branches: [ develop ] + repository_dispatch: + types: [ upstream-sdk-notify ] +env: + # These must be set for fetchdep.sh to get the right branch + REPOSITORY: ${{ github.repository }} + PR_NUMBER: ${{ github.event.pull_request.number }} +jobs: + end-to-end: + runs-on: ubuntu-latest + container: vectorim/element-web-ci-e2etests-env:latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - uses: actions/setup-node@v3 + with: + cache: 'yarn' + + - name: Prepare End-to-End tests + run: ./scripts/ci/prepare-end-to-end-tests.sh + + - name: Run End-to-End tests + run: ./scripts/ci/run-end-to-end-tests.sh + + - name: Archive logs + uses: actions/upload-artifact@v2 + if: ${{ always() }} + with: + path: | + test/end-to-end-tests/logs/**/* + test/end-to-end-tests/synapse/installations/consent/homeserver.log + retention-days: 14 + + - name: Download previous benchmark data + uses: actions/cache@v1 + with: + path: ./cache + key: ${{ runner.os }}-benchmark + + - name: Store benchmark result + uses: matrix-org/github-action-benchmark@jsperfentry-1 + with: + tool: 'jsperformanceentry' + output-file-path: test/end-to-end-tests/performance-entries.json + fail-on-alert: false + comment-on-alert: false + # Only temporary to monitor where failures occur + alert-comment-cc-users: '@gsouquet' + github-token: ${{ secrets.DEPLOY_GH_PAGES }} + auto-push: ${{ github.ref == 'refs/heads/develop' }} diff --git a/.github/workflows/layered-build.yaml b/.github/workflows/layered-build.yaml deleted file mode 100644 index fd531fc9689..00000000000 --- a/.github/workflows/layered-build.yaml +++ /dev/null @@ -1,20 +0,0 @@ -name: Layered Preview Build -on: - pull_request: -jobs: - build: - runs-on: ubuntu-latest - env: - PR_NUMBER: ${{github.event.number}} - steps: - - uses: actions/checkout@v2 - - name: Build - run: scripts/ci/layered.sh && cd element-web && cp element.io/develop/config.json config.json && CI_PACKAGE=true yarn build - - name: Upload Artifact - uses: actions/upload-artifact@v2 - with: - name: previewbuild - path: element-web/webapp - # We'll only use this in a triggered job, then we're done with it - retention-days: 1 - diff --git a/.github/workflows/netlify.yaml b/.github/workflows/netlify.yaml index 7c472ab24d1..260f8f130c5 100644 --- a/.github/workflows/netlify.yaml +++ b/.github/workflows/netlify.yaml @@ -1,75 +1,94 @@ +# Triggers after the layered build has finished, taking the artifact +# and uploading it to netlify name: Upload Preview Build to Netlify on: - workflow_run: - workflows: ["Layered Preview Build"] - types: - - completed + workflow_run: + workflows: [ "Element Web - Build and Test" ] + types: + - completed jobs: - build: - runs-on: ubuntu-latest - if: > - ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' }} - steps: - - name: "🔍 Read PR number" - id: readctx - # we need to find the PR number that corresponds to the branch, which we do by - # searching the GH API - # The workflow_run event includes a list of pull requests, but it doesn't get populated for - # forked PRs: https://docs.github.com/en/rest/reference/checks#create-a-check-run - run: | - head_branch='${{github.event.workflow_run.head_repository.owner.login}}:${{github.event.workflow_run.head_branch}}' - echo "head branch: $head_branch" - pulls_uri="https://api.github.com/repos/${{ github.repository }}/pulls?head=$(jq -Rr '@uri' <<<$head_branch)" - pr_number=$(curl -s -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' "$pulls_uri" | - jq -r '.[] | .number') - echo "PR number: $pr_number" - echo "::set-output name=prnumber::$pr_number" - # There's a 'download artifact' action but it hasn't been updated for the - # workflow_run action (https://github.com/actions/download-artifact/issues/60) - # so instead we get this mess: - - name: 'Download artifact' - uses: actions/github-script@v3.1.0 - with: - script: | - var artifacts = await github.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: ${{github.event.workflow_run.id }}, - }); - var matchArtifact = artifacts.data.artifacts.filter((artifact) => { - return artifact.name == "previewbuild" - })[0]; - var download = await github.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: matchArtifact.id, - archive_format: 'zip', - }); - var fs = require('fs'); - fs.writeFileSync('${{github.workspace}}/previewbuild.zip', Buffer.from(download.data)); - - name: Extract Artifacts - run: unzip -d webapp previewbuild.zip && rm previewbuild.zip - - name: Deploy to Netlify - id: netlify - uses: nwtgck/actions-netlify@v1.2 - with: - publish-dir: webapp - deploy-message: "Deploy from GitHub Actions" - # These don't work because we're in workflow_run - enable-pull-request-comment: false - enable-commit-comment: false - alias: pr${{ steps.readctx.outputs.prnumber }} - env: - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - timeout-minutes: 1 - - name: Edit PR Description - uses: Beakyn/gha-comment-pull-request@2167a7aee24f9e61ce76a23039f322e49a990409 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - pull-request-number: ${{ steps.readctx.outputs.prnumber }} - description-message: | - Preview: ${{ steps.netlify.outputs.deploy-url }} - ⚠️ Do you trust the author of this PR? Maybe this build will steal your keys or give you malware. Exercise caution. Use test accounts. + deploy: + runs-on: ubuntu-latest + if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' + steps: + - name: "🔍 Read PR number" + id: readctx + # We need to find the PR number that corresponds to the branch, which we do by searching the GH API + # The workflow_run event includes a list of pull requests, but it doesn't get populated for + # forked PRs: https://docs.github.com/en/rest/reference/checks#create-a-check-run + run: | + head_branch='${{github.event.workflow_run.head_repository.owner.login}}:${{github.event.workflow_run.head_branch}}' + echo "Head branch: $head_branch" + pulls_uri="https://api.github.com/repos/${{ github.repository }}/pulls?head=$(jq -Rr '@uri' <<<$head_branch)" + pr_number=$(curl -s -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' "$pulls_uri" | + jq -r '.[] | .number') + echo "PR number: $pr_number" + echo "::set-output name=prnumber::$pr_number" + - name: Create Deployment + uses: bobheadxi/deployments@v1 + id: deployment + with: + step: start + token: ${{ secrets.GITHUB_TOKEN }} + env: Netlify + ref: ${{ github.event.workflow_run.head_sha }} + desc: | + Do you trust the author of this PR? Maybe this build will steal your keys or give you malware. + Exercise caution. Use test accounts. + + # There's a 'download artifact' action, but it hasn't been updated for the + # workflow_run action (https://github.com/actions/download-artifact/issues/60) + # so instead we get this mess: + - name: 'Download artifact' + uses: actions/github-script@v3.1.0 + with: + script: | + const artifacts = await github.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{ github.event.workflow_run.id }}, + }); + const matchArtifact = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "previewbuild" + })[0]; + const download = await github.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + const fs = require('fs'); + fs.writeFileSync('${{github.workspace}}/previewbuild.zip', Buffer.from(download.data)); + + - name: Extract Artifacts + run: unzip -d webapp previewbuild.zip && rm previewbuild.zip + + - name: Deploy to Netlify + id: netlify + uses: nwtgck/actions-netlify@v1.2 + with: + publish-dir: webapp + deploy-message: "Deploy from GitHub Actions" + # These don't work because we're in workflow_run + enable-pull-request-comment: false + enable-commit-comment: false + alias: pr${{ steps.readctx.outputs.prnumber }} + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + timeout-minutes: 1 + + - name: Update deployment status + uses: bobheadxi/deployments@v1 + if: always() + with: + step: finish + token: ${{ secrets.GITHUB_TOKEN }} + status: ${{ job.status }} + env: ${{ steps.deployment.outputs.env }} + deployment_id: ${{ steps.deployment.outputs.deployment_id }} + env_url: ${{ steps.netlify.outputs.deploy-url }} + desc: | + Do you trust the author of this PR? Maybe this build will steal your keys or give you malware. + Exercise caution. Use test accounts. diff --git a/.github/workflows/notify-element-web.yml b/.github/workflows/notify-element-web.yml index ef463784f38..1d60a1523cc 100644 --- a/.github/workflows/notify-element-web.yml +++ b/.github/workflows/notify-element-web.yml @@ -1,15 +1,17 @@ name: Notify element-web on: - push: - branches: [develop] + push: + branches: [ develop ] + repository_dispatch: + types: [ upstream-sdk-notify ] jobs: - notify-element-web: - runs-on: ubuntu-latest - environment: develop - steps: - - name: Notify element-web repo that a new SDK build is on develop - uses: peter-evans/repository-dispatch@v1 - with: - token: ${{ secrets.ELEMENT_WEB_NOTIFY_TOKEN }} - repository: vector-im/element-web - event-type: element-web-notify + notify-element-web: + name: "Notify Element Web" + runs-on: ubuntu-latest + steps: + - name: Notify element-web repo that a new SDK build is on develop + uses: peter-evans/repository-dispatch@v1 + with: + token: ${{ secrets.ELEMENT_BOT_TOKEN }} + repository: vector-im/element-web + event-type: element-web-notify diff --git a/.github/workflows/preview_changelog.yaml b/.github/workflows/preview_changelog.yaml index d68d19361da..786d828d419 100644 --- a/.github/workflows/preview_changelog.yaml +++ b/.github/workflows/preview_changelog.yaml @@ -3,10 +3,10 @@ on: pull_request_target: types: [ opened, edited, labeled ] jobs: - changelog: - runs-on: ubuntu-latest - steps: - - name: Preview Changelog - uses: matrix-org/allchange@main - with: - ghToken: ${{ secrets.GITHUB_TOKEN }} + changelog: + runs-on: ubuntu-latest + steps: + - name: Preview Changelog + uses: matrix-org/allchange@main + with: + ghToken: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/static_analysis.yaml b/.github/workflows/static_analysis.yaml new file mode 100644 index 00000000000..63e939f7f9a --- /dev/null +++ b/.github/workflows/static_analysis.yaml @@ -0,0 +1,102 @@ +name: Static Analysis +on: + pull_request: { } + push: + branches: [ develop, master ] + repository_dispatch: + types: [ upstream-sdk-notify ] +env: + # These must be set for fetchdep.sh to get the right branch + REPOSITORY: ${{ github.repository }} + PR_NUMBER: ${{ github.event.pull_request.number }} +jobs: + ts_lint: + name: "Typescript Syntax Check" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v3 + with: + cache: 'yarn' + + - 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" + + i18n_lint: + name: "i18n Diff Check" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v3 + with: + cache: 'yarn' + + # Does not need branch matching as only analyses this layer + - name: Install Deps + run: "yarn install" + + - name: i18n Check + run: "yarn run diff-i18n" + + js_lint: + name: "ESLint" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v3 + with: + cache: 'yarn' + + # Does not need branch matching as only analyses this layer + - name: Install Deps + run: "yarn install" + + - name: Run Linter + run: "yarn run lint:js" + + style_lint: + name: "Style Lint" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v3 + with: + cache: 'yarn' + + # Does not need branch matching as only analyses this layer + - name: Install Deps + run: "yarn install" + + - name: Run Linter + run: "yarn run lint:style" + + sonarqube: + name: "SonarQube" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: SonarCloud Scan + uses: SonarSource/sonarcloud-github-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000000..f160e42844d --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,41 @@ +name: Tests +on: + pull_request: { } + push: + branches: [ develop, master ] + repository_dispatch: + types: [ upstream-sdk-notify ] +env: + # These must be set for fetchdep.sh to get the right branch + REPOSITORY: ${{ github.repository }} + PR_NUMBER: ${{ github.event.pull_request.number }} +jobs: + jest: + name: Jest with Codecov + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + # If this is a pull request, make sure we check out its head rather than the + # automatically generated merge commit, so that the coverage diff excludes + # unrelated changes in the base branch + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || '' }} + + - name: Yarn cache + uses: actions/setup-node@v3 + with: + cache: 'yarn' + + - name: Install Deps + run: "./scripts/ci/install-deps.sh --ignore-scripts" + + - name: Run tests with coverage + run: "yarn coverage" + + - name: Upload coverage + uses: codecov/codecov-action@v2 + with: + fail_ci_if_error: false + verbose: true + override_commit: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || '' }} diff --git a/.github/workflows/triage-move-review-requests.yml b/.github/workflows/triage-move-review-requests.yml deleted file mode 100644 index 49db29ff5c1..00000000000 --- a/.github/workflows/triage-move-review-requests.yml +++ /dev/null @@ -1,139 +0,0 @@ -name: Move pull requests asking for review to the relevant project -on: - pull_request_target: - types: [review_requested] - -jobs: - add_design_pr_to_project: - name: Move PRs asking for design review to the design board - runs-on: ubuntu-latest - steps: - - uses: octokit/graphql-action@v2.x - id: find_team_members - with: - headers: '{"GraphQL-Features": "projects_next_graphql"}' - query: | - query find_team_members($team: String!) { - organization(login: "matrix-org") { - team(slug: $team) { - members { - nodes { - login - } - } - } - } - } - team: ${{ env.TEAM }} - env: - TEAM: "design" - GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} - - id: any_matching_reviewers - run: | - # Fetch requested reviewers, and people who are on the team - echo '${{ tojson(fromjson(steps.find_team_members.outputs.data).organization.team.members.nodes[*].login) }}' | tee /tmp/team_members.json - echo '${{ tojson(github.event.pull_request.requested_reviewers[*].login) }}' | tee /tmp/reviewers.json - jq --raw-output .[] < /tmp/team_members.json | sort | tee /tmp/team_members.txt - jq --raw-output .[] < /tmp/reviewers.json | sort | tee /tmp/reviewers.txt - - # Fetch requested team reviewers, and the name of the team - echo '${{ tojson(github.event.pull_request.requested_teams[*].slug) }}' | tee /tmp/team_reviewers.json - jq --raw-output .[] < /tmp/team_reviewers.json | sort | tee /tmp/team_reviewers.txt - echo '${{ env.TEAM }}' | tee /tmp/team.txt - - # If either a reviewer matches a team member, or a team matches our team, say "true" - if [ $(join /tmp/team_members.txt /tmp/reviewers.txt | wc -l) != 0 ]; then - echo "::set-output name=match::true" - elif [ $(join /tmp/team.txt /tmp/team_reviewers.txt | wc -l) != 0 ]; then - echo "::set-output name=match::true" - else - echo "::set-output name=match::false" - fi - env: - TEAM: "design" - - uses: octokit/graphql-action@v2.x - id: add_to_project - if: steps.any_matching_reviewers.outputs.match == 'true' - with: - headers: '{"GraphQL-Features": "projects_next_graphql"}' - query: | - mutation add_to_project($projectid:ID!, $contentid:ID!) { - addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { - projectNextItem { - id - } - } - } - projectid: ${{ env.PROJECT_ID }} - contentid: ${{ github.event.pull_request.node_id }} - env: - PROJECT_ID: "PN_kwDOAM0swc0sUA" - TEAM: "design" - GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} - - add_product_pr_to_project: - name: Move PRs asking for design review to the design board - runs-on: ubuntu-latest - steps: - - uses: octokit/graphql-action@v2.x - id: find_team_members - with: - headers: '{"GraphQL-Features": "projects_next_graphql"}' - query: | - query find_team_members($team: String!) { - organization(login: "matrix-org") { - team(slug: $team) { - members { - nodes { - login - } - } - } - } - } - team: ${{ env.TEAM }} - env: - TEAM: "product" - GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} - - id: any_matching_reviewers - run: | - # Fetch requested reviewers, and people who are on the team - echo '${{ tojson(fromjson(steps.find_team_members.outputs.data).organization.team.members.nodes[*].login) }}' | tee /tmp/team_members.json - echo '${{ tojson(github.event.pull_request.requested_reviewers[*].login) }}' | tee /tmp/reviewers.json - jq --raw-output .[] < /tmp/team_members.json | sort | tee /tmp/team_members.txt - jq --raw-output .[] < /tmp/reviewers.json | sort | tee /tmp/reviewers.txt - - # Fetch requested team reviewers, and the name of the team - echo '${{ tojson(github.event.pull_request.requested_teams[*].slug) }}' | tee /tmp/team_reviewers.json - jq --raw-output .[] < /tmp/team_reviewers.json | sort | tee /tmp/team_reviewers.txt - echo '${{ env.TEAM }}' | tee /tmp/team.txt - - # If either a reviewer matches a team member, or a team matches our team, say "true" - if [ $(join /tmp/team_members.txt /tmp/reviewers.txt | wc -l) != 0 ]; then - echo "::set-output name=match::true" - elif [ $(join /tmp/team.txt /tmp/team_reviewers.txt | wc -l) != 0 ]; then - echo "::set-output name=match::true" - else - echo "::set-output name=match::false" - fi - env: - TEAM: "product" - - uses: octokit/graphql-action@v2.x - id: add_to_project - if: steps.any_matching_reviewers.outputs.match == 'true' - with: - headers: '{"GraphQL-Features": "projects_next_graphql"}' - query: | - mutation add_to_project($projectid:ID!, $contentid:ID!) { - addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { - projectNextItem { - id - } - } - } - projectid: ${{ env.PROJECT_ID }} - contentid: ${{ github.event.pull_request.node_id }} - env: - PROJECT_ID: "PN_kwDOAM0swc4AAg6N" - TEAM: "product" - GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} diff --git a/.github/workflows/typecheck.yaml b/.github/workflows/typecheck.yaml deleted file mode 100644 index f6ab6439582..00000000000 --- a/.github/workflows/typecheck.yaml +++ /dev/null @@ -1,26 +0,0 @@ -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/.gitignore b/.gitignore index 102f4b5ec1f..8e14ba9057b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ package-lock.json /matrix-react-sdk-*.tgz /.idea +# Legacy skinning file that some people might still have /src/component-index.js .DS_Store @@ -18,3 +19,11 @@ package-lock.json .vscode .vscode/ + +/cypress/videos +/cypress/downloads +/cypress/screenshots +/cypress/synapselogs +# These could have files in them but don't currently +# Cypress will still auto-create them though... +/cypress/fixtures diff --git a/.stylelintrc.js b/.stylelintrc.js index 0bdea3cccd7..e72e8ca55c3 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -23,5 +23,10 @@ module.exports = { // https://github.com/vector-im/element-web/issues/10544 "ignoreAtRules": ["define-mixin"], }], + // Disable `&_kind`-style selectors while our unused CSS approach is "Find & Replace All" + // rather than a CI thing. Shorthand selectors are harder to detect when searching for a + // class name. This regex is trying to *allow* anything except `&words`, such as `&::before`, + // `&.mx_Class`, etc. + "selector-nested-pattern": "^((&[ :.\\\[,])|([^&]))" } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aa6b18fc2a..841a7360a10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,253 @@ +Changes in [3.43.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.43.0) (2022-04-26) +===================================================================================================== + +## ✨ Features + * Improve performance of switching to rooms with lots of servers and ACLs ([\#8347](https://github.com/matrix-org/matrix-react-sdk/pull/8347)). + * Avoid a reflow when setting caret position on an empty composer ([\#8348](https://github.com/matrix-org/matrix-react-sdk/pull/8348)). + * Add message right-click context menu as a labs feature ([\#5672](https://github.com/matrix-org/matrix-react-sdk/pull/5672)). + * Live location sharing - basic maximised beacon map ([\#8310](https://github.com/matrix-org/matrix-react-sdk/pull/8310)). + * Live location sharing - render users own beacons in timeline ([\#8296](https://github.com/matrix-org/matrix-react-sdk/pull/8296)). + * Improve Threads beta around degraded mode ([\#8318](https://github.com/matrix-org/matrix-react-sdk/pull/8318)). + * Live location sharing - beacon in timeline happy path ([\#8285](https://github.com/matrix-org/matrix-react-sdk/pull/8285)). + * Add copy button to View Source screen ([\#8278](https://github.com/matrix-org/matrix-react-sdk/pull/8278)). Fixes vector-im/element-web#21482. Contributed by @olivialivia. + * Add heart effect ([\#6188](https://github.com/matrix-org/matrix-react-sdk/pull/6188)). Contributed by @CicadaCinema. + * Update new room icon ([\#8239](https://github.com/matrix-org/matrix-react-sdk/pull/8239)). + +## 🐛 Bug Fixes + * Fix: "Code formatting button does not escape backticks" ([\#8181](https://github.com/matrix-org/matrix-react-sdk/pull/8181)). Contributed by @yaya-usman. + * Fix beta indicator dot causing excessive CPU usage ([\#8340](https://github.com/matrix-org/matrix-react-sdk/pull/8340)). Fixes vector-im/element-web#21793. + * Fix overlapping timestamps on empty messages ([\#8205](https://github.com/matrix-org/matrix-react-sdk/pull/8205)). Fixes vector-im/element-web#21381. Contributed by @goelesha. + * Fix power selector not showing up in user info when state_default undefined ([\#8297](https://github.com/matrix-org/matrix-react-sdk/pull/8297)). Fixes vector-im/element-web#21669. + * Avoid looking up settings during timeline rendering ([\#8313](https://github.com/matrix-org/matrix-react-sdk/pull/8313)). Fixes vector-im/element-web#21740. + * Fix a soft crash with video rooms ([\#8333](https://github.com/matrix-org/matrix-react-sdk/pull/8333)). + * Fixes call tiles overflow ([\#8096](https://github.com/matrix-org/matrix-react-sdk/pull/8096)). Fixes vector-im/element-web#20254. Contributed by @luixxiul. + * Fix a bug with emoji autocomplete sorting where adding the final ":" would cause the emoji with the typed shortcode to no longer be at the top of the autocomplete list. ([\#8086](https://github.com/matrix-org/matrix-react-sdk/pull/8086)). Fixes vector-im/element-web#19302. Contributed by @commonlawfeature. + * Fix image preview sizing for edge cases ([\#8322](https://github.com/matrix-org/matrix-react-sdk/pull/8322)). Fixes vector-im/element-web#20088. + * Refactor SecurityRoomSettingsTab and remove unused state ([\#8306](https://github.com/matrix-org/matrix-react-sdk/pull/8306)). Fixes matrix-org/element-web-rageshakes#12002. + * Don't show the prompt to enable desktop notifications immediately after registration ([\#8274](https://github.com/matrix-org/matrix-react-sdk/pull/8274)). + * Stop tracking threads if threads support is disabled ([\#8308](https://github.com/matrix-org/matrix-react-sdk/pull/8308)). Fixes vector-im/element-web#21766. + * Fix some issues with threads rendering ([\#8305](https://github.com/matrix-org/matrix-react-sdk/pull/8305)). Fixes vector-im/element-web#21670. + * Fix threads rendering issue in Safari ([\#8298](https://github.com/matrix-org/matrix-react-sdk/pull/8298)). Fixes vector-im/element-web#21757. + * Fix space panel width change on hovering over space item ([\#8299](https://github.com/matrix-org/matrix-react-sdk/pull/8299)). Fixes vector-im/element-web#19891. + * Hide the reply in thread button in deployments where beta is forcibly disabled ([\#8294](https://github.com/matrix-org/matrix-react-sdk/pull/8294)). Fixes vector-im/element-web#21753. + * Prevent soft crash around room list header context menu when space changes ([\#8289](https://github.com/matrix-org/matrix-react-sdk/pull/8289)). Fixes matrix-org/element-web-rageshakes#11416, matrix-org/element-web-rageshakes#11692, matrix-org/element-web-rageshakes#11739, matrix-org/element-web-rageshakes#11772, matrix-org/element-web-rageshakes#11891 matrix-org/element-web-rageshakes#11858 and matrix-org/element-web-rageshakes#11456. + * When selecting reply in thread on a thread response open existing thread ([\#8291](https://github.com/matrix-org/matrix-react-sdk/pull/8291)). Fixes vector-im/element-web#21743. + * Handle thread bundled relationships coming from the server via MSC3666 ([\#8292](https://github.com/matrix-org/matrix-react-sdk/pull/8292)). Fixes vector-im/element-web#21450. + * Fix: Avatar preview does not update when same file is selected repeatedly ([\#8288](https://github.com/matrix-org/matrix-react-sdk/pull/8288)). Fixes vector-im/element-web#20098. + * Fix a bug where user gets a warning when changing powerlevel from **Admin** to **custom level (100)** ([\#8248](https://github.com/matrix-org/matrix-react-sdk/pull/8248)). Fixes vector-im/element-web#21682. Contributed by @Jumeb. + * Use a consistent alignment for all text items in a list ([\#8276](https://github.com/matrix-org/matrix-react-sdk/pull/8276)). Fixes vector-im/element-web#21731. Contributed by @luixxiul. + * Fixes button labels being collapsed per a character in CJK languages ([\#8212](https://github.com/matrix-org/matrix-react-sdk/pull/8212)). Fixes vector-im/element-web#21287. Contributed by @luixxiul. + * Fix: Remove jittery timeline scrolling after jumping to an event ([\#8263](https://github.com/matrix-org/matrix-react-sdk/pull/8263)). + * Fix regression of edits showing up in the timeline with hidden events shown ([\#8260](https://github.com/matrix-org/matrix-react-sdk/pull/8260)). Fixes vector-im/element-web#21694. + * Fix reporting events not working ([\#8257](https://github.com/matrix-org/matrix-react-sdk/pull/8257)). Fixes vector-im/element-web#21713. + * Make Jitsi widgets in video rooms immutable ([\#8244](https://github.com/matrix-org/matrix-react-sdk/pull/8244)). Fixes vector-im/element-web#21647. + * Fix: Ensure links to events scroll the correct events into view ([\#8250](https://github.com/matrix-org/matrix-react-sdk/pull/8250)). Fixes vector-im/element-web#19934. + +Changes in [3.42.4](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.42.4) (2022-04-14) +===================================================================================================== + +## 🐛 Bug Fixes + * Fixes around threads beta in degraded mode ([\#8319](https://github.com/matrix-org/matrix-react-sdk/pull/8319)). Fixes vector-im/element-web#21762. + +Changes in [3.42.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.42.3) (2022-04-12) +===================================================================================================== + +## ✨ Features + * Release threads as a beta feature ([\#8081](https://github.com/matrix-org/matrix-react-sdk/pull/8081)). Fixes vector-im/element-web#21351. + * More video rooms design updates ([\#8222](https://github.com/matrix-org/matrix-react-sdk/pull/8222)). + * Update video rooms to new design specs ([\#8207](https://github.com/matrix-org/matrix-react-sdk/pull/8207)). Fixes vector-im/element-web#21515, vector-im/element-web#21516 vector-im/element-web#21519 and vector-im/element-web#21526. + * Live Location Sharing - left panel warning with error ([\#8201](https://github.com/matrix-org/matrix-react-sdk/pull/8201)). + * Live location sharing - Stop publishing location to beacons with consecutive errors ([\#8194](https://github.com/matrix-org/matrix-react-sdk/pull/8194)). + * Live location sharing: allow retry when stop sharing fails ([\#8193](https://github.com/matrix-org/matrix-react-sdk/pull/8193)). + * Allow voice messages to be scrubbed in the timeline ([\#8079](https://github.com/matrix-org/matrix-react-sdk/pull/8079)). Fixes vector-im/element-web#18713. + * Live location sharing - stop sharing to beacons in rooms you left ([\#8187](https://github.com/matrix-org/matrix-react-sdk/pull/8187)). + * Allow sending and thumbnailing AVIF images ([\#8172](https://github.com/matrix-org/matrix-react-sdk/pull/8172)). + * Live location sharing - handle geolocation errors ([\#8179](https://github.com/matrix-org/matrix-react-sdk/pull/8179)). + * Show voice room participants when not connected ([\#8136](https://github.com/matrix-org/matrix-react-sdk/pull/8136)). Fixes vector-im/element-web#21513. + * Add margins between labs sections ([\#8169](https://github.com/matrix-org/matrix-react-sdk/pull/8169)). + * Live location sharing - send geolocation beacon events - happy path ([\#8127](https://github.com/matrix-org/matrix-react-sdk/pull/8127)). + * Add support for Animated (A)PNG ([\#8158](https://github.com/matrix-org/matrix-react-sdk/pull/8158)). Fixes vector-im/element-web#12967. + * Don't form continuations from thread roots ([\#8166](https://github.com/matrix-org/matrix-react-sdk/pull/8166)). Fixes vector-im/element-web#20908. + * Improve handling of animated GIF and WEBP images ([\#8153](https://github.com/matrix-org/matrix-react-sdk/pull/8153)). Fixes vector-im/element-web#16193 and vector-im/element-web#6684. + * Wire up file preview for video files ([\#8140](https://github.com/matrix-org/matrix-react-sdk/pull/8140)). Fixes vector-im/element-web#21539. + * When showing thread, always auto-focus its composer ([\#8115](https://github.com/matrix-org/matrix-react-sdk/pull/8115)). Fixes vector-im/element-web#21438. + * Live location sharing - refresh beacon expiry in room ([\#8116](https://github.com/matrix-org/matrix-react-sdk/pull/8116)). + * Use styled mxids in member list v2 ([\#8110](https://github.com/matrix-org/matrix-react-sdk/pull/8110)). Fixes vector-im/element-web#14825. Contributed by @SimonBrandner. + * Delete groups (legacy communities system) ([\#8027](https://github.com/matrix-org/matrix-react-sdk/pull/8027)). Fixes vector-im/element-web#17532. + * Add a prototype of voice rooms in labs ([\#8084](https://github.com/matrix-org/matrix-react-sdk/pull/8084)). Fixes vector-im/element-web#3546. + +## 🐛 Bug Fixes + * Fix editing `
    ` tags with a non-1 start attribute ([\#8211](https://github.com/matrix-org/matrix-react-sdk/pull/8211)). Fixes vector-im/element-web#21625. + * Fix URL previews being enabled when room first created ([\#8227](https://github.com/matrix-org/matrix-react-sdk/pull/8227)). Fixes vector-im/element-web#21659. + * Don't use m.call for Jitsi video rooms ([\#8223](https://github.com/matrix-org/matrix-react-sdk/pull/8223)). + * Scale emoji with size of surrounding text ([\#8224](https://github.com/matrix-org/matrix-react-sdk/pull/8224)). + * Make "Jump to date" translatable ([\#8218](https://github.com/matrix-org/matrix-react-sdk/pull/8218)). + * Normalize call buttons ([\#8129](https://github.com/matrix-org/matrix-react-sdk/pull/8129)). Fixes vector-im/element-web#21493. Contributed by @luixxiul. + * Show room preview bar with maximised widgets ([\#8180](https://github.com/matrix-org/matrix-react-sdk/pull/8180)). Fixes vector-im/element-web#21542. + * Update more strings to not wrongly mention room when it is/could be a space ([\#7722](https://github.com/matrix-org/matrix-react-sdk/pull/7722)). Fixes vector-im/element-web#20243 and vector-im/element-web#20910. + * Fix issue with redacting via edit composer flow causing stuck editStates ([\#8184](https://github.com/matrix-org/matrix-react-sdk/pull/8184)). + * Fix some image/video scroll jumps ([\#8182](https://github.com/matrix-org/matrix-react-sdk/pull/8182)). + * Fix "react error on share dialog" ([\#8170](https://github.com/matrix-org/matrix-react-sdk/pull/8170)). Contributed by @yaya-usman. + * Fix disambiguated profile in threads in bubble layout ([\#8168](https://github.com/matrix-org/matrix-react-sdk/pull/8168)). Fixes vector-im/element-web#21570. Contributed by @SimonBrandner. + * Responsive BetaCard on Labs ([\#8154](https://github.com/matrix-org/matrix-react-sdk/pull/8154)). Fixes vector-im/element-web#21554. Contributed by @luixxiul. + * Display button as inline in room directory dialog ([\#8164](https://github.com/matrix-org/matrix-react-sdk/pull/8164)). Fixes vector-im/element-web#21567. Contributed by @luixxiul. + * Null guard TimelinePanel unmount edge ([\#8171](https://github.com/matrix-org/matrix-react-sdk/pull/8171)). + * Fix beta pill label breaking ([\#8162](https://github.com/matrix-org/matrix-react-sdk/pull/8162)). Fixes vector-im/element-web#21566. Contributed by @luixxiul. + * Strip relations when forwarding ([\#7929](https://github.com/matrix-org/matrix-react-sdk/pull/7929)). Fixes vector-im/element-web#19769, vector-im/element-web#18067 vector-im/element-web#21015 and vector-im/element-web#10924. + * Don't try (and fail) to show replies for redacted events ([\#8141](https://github.com/matrix-org/matrix-react-sdk/pull/8141)). Fixes vector-im/element-web#21435. + * Fix 3pid member info for space member list ([\#8128](https://github.com/matrix-org/matrix-react-sdk/pull/8128)). Fixes vector-im/element-web#21534. + * Set max-width to user context menu ([\#8089](https://github.com/matrix-org/matrix-react-sdk/pull/8089)). Fixes vector-im/element-web#21486. Contributed by @luixxiul. + * Fix issue with falsey hrefs being sent in events ([\#8113](https://github.com/matrix-org/matrix-react-sdk/pull/8113)). Fixes vector-im/element-web#21417. + * Make video sizing consistent with images ([\#8102](https://github.com/matrix-org/matrix-react-sdk/pull/8102)). Fixes vector-im/element-web#20072. + +Changes in [3.42.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.42.0) (2022-03-15) +===================================================================================================== + +## 🔒 SECURITY FIXES + + * Fix a bug where URL previews could be enabled in the left-panel when they + should not have been. + +## ✨ Features + * Add unexposed account setting for hiding poll creation ([\#7972](https://github.com/matrix-org/matrix-react-sdk/pull/7972)). + * Allow pinning polls ([\#7922](https://github.com/matrix-org/matrix-react-sdk/pull/7922)). Fixes vector-im/element-web#20152. + * Make trailing `:` into a setting ([\#6711](https://github.com/matrix-org/matrix-react-sdk/pull/6711)). Fixes vector-im/element-web#16682. Contributed by @SimonBrandner. + * Location sharing > back button ([\#7958](https://github.com/matrix-org/matrix-react-sdk/pull/7958)). + * use LocationAssetType ([\#7965](https://github.com/matrix-org/matrix-react-sdk/pull/7965)). + * Location share type UI ([\#7924](https://github.com/matrix-org/matrix-react-sdk/pull/7924)). + * Add a few more UIComponent flags, and ensure they are used in existing code ([\#7937](https://github.com/matrix-org/matrix-react-sdk/pull/7937)). + * Add support for overriding strings in the app ([\#7886](https://github.com/matrix-org/matrix-react-sdk/pull/7886)). + * Add support for redirecting to external pages after logout ([\#7905](https://github.com/matrix-org/matrix-react-sdk/pull/7905)). + * Expose redaction power level in room settings ([\#7599](https://github.com/matrix-org/matrix-react-sdk/pull/7599)). Fixes vector-im/element-web#20590. Contributed by @SimonBrandner. + * Update and expand ways to access pinned messages ([\#7906](https://github.com/matrix-org/matrix-react-sdk/pull/7906)). Fixes vector-im/element-web#21209 and vector-im/element-web#21211. + * Add slash command to switch to a room's virtual room ([\#7839](https://github.com/matrix-org/matrix-react-sdk/pull/7839)). + +## 🐛 Bug Fixes + * Merge pull request from GHSA-qmf4-7w7j-vf23 ([\#8059](https://github.com/matrix-org/matrix-react-sdk/pull/8059)). + * Add another null guard for member ([\#7984](https://github.com/matrix-org/matrix-react-sdk/pull/7984)). Fixes vector-im/element-web#21319. + * Fix room account settings ([\#7999](https://github.com/matrix-org/matrix-react-sdk/pull/7999)). + * Fix missing summary text for pinned message changes ([\#7989](https://github.com/matrix-org/matrix-react-sdk/pull/7989)). Fixes vector-im/element-web#19823. + * Pass room to getRoomTombstone to avoid racing with setState ([\#7986](https://github.com/matrix-org/matrix-react-sdk/pull/7986)). + * Hide composer and call buttons when the room is tombstoned ([\#7975](https://github.com/matrix-org/matrix-react-sdk/pull/7975)). Fixes vector-im/element-web#21286. + * Fix bad ternary statement in autocomplete user pill insertions ([\#7977](https://github.com/matrix-org/matrix-react-sdk/pull/7977)). Fixes vector-im/element-web#21307. + * Fix sending locations into threads and fix i18n ([\#7943](https://github.com/matrix-org/matrix-react-sdk/pull/7943)). Fixes vector-im/element-web#21267. + * Fix location map attribution rendering over message action bar ([\#7974](https://github.com/matrix-org/matrix-react-sdk/pull/7974)). Fixes vector-im/element-web#21297. + * Fix wrongly asserting that PushRule::conditions is non-null ([\#7973](https://github.com/matrix-org/matrix-react-sdk/pull/7973)). Fixes vector-im/element-web#21305. + * Fix account & room settings race condition ([\#7953](https://github.com/matrix-org/matrix-react-sdk/pull/7953)). Fixes vector-im/element-web#21163. + * Fix bug with some space selections not being applied ([\#7971](https://github.com/matrix-org/matrix-react-sdk/pull/7971)). Fixes vector-im/element-web#21290. + * Revert "replace all require(.svg) with esm import" ([\#7969](https://github.com/matrix-org/matrix-react-sdk/pull/7969)). Fixes vector-im/element-web#21293. + * Hide unpinnable pinned messages in more cases ([\#7921](https://github.com/matrix-org/matrix-react-sdk/pull/7921)). + * Fix room list being laggy while scrolling 🐌 ([\#7939](https://github.com/matrix-org/matrix-react-sdk/pull/7939)). Fixes vector-im/element-web#21262. + * Make pinned messages more reliably reflect edits ([\#7920](https://github.com/matrix-org/matrix-react-sdk/pull/7920)). Fixes vector-im/element-web#17098. + * Improve accessibility of the BetaPill ([\#7949](https://github.com/matrix-org/matrix-react-sdk/pull/7949)). Fixes vector-im/element-web#21255. + * Autofocus correct composer after sending reaction ([\#7950](https://github.com/matrix-org/matrix-react-sdk/pull/7950)). Fixes vector-im/element-web#21273. + * Consider polls as message events for rendering redactions ([\#7944](https://github.com/matrix-org/matrix-react-sdk/pull/7944)). Fixes vector-im/element-web#21125. + * Prevent event tiles being shrunk/collapsed by flexbox ([\#7942](https://github.com/matrix-org/matrix-react-sdk/pull/7942)). Fixes vector-im/element-web#21269. + * Fix ExportDialog title on export cancellation ([\#7936](https://github.com/matrix-org/matrix-react-sdk/pull/7936)). Fixes vector-im/element-web#21260. Contributed by @luixxiul. + * Mandate use of js-sdk/src/matrix import over js-sdk/src ([\#7933](https://github.com/matrix-org/matrix-react-sdk/pull/7933)). Fixes vector-im/element-web#21253. + * Fix backspace not working in the invite dialog ([\#7931](https://github.com/matrix-org/matrix-react-sdk/pull/7931)). Fixes vector-im/element-web#21249. Contributed by @SimonBrandner. + * Fix right panel soft crashes due to missing room prop ([\#7923](https://github.com/matrix-org/matrix-react-sdk/pull/7923)). Fixes vector-im/element-web#21243. + * fix color of location share caret ([\#7917](https://github.com/matrix-org/matrix-react-sdk/pull/7917)). + * Wrap all EventTiles with a TileErrorBoundary and guard parsePermalink ([\#7916](https://github.com/matrix-org/matrix-react-sdk/pull/7916)). Fixes vector-im/element-web#21216. + * Fix changing space sometimes bouncing to the wrong space ([\#7910](https://github.com/matrix-org/matrix-react-sdk/pull/7910)). Fixes vector-im/element-web#20425. + * Ensure EventListSummary key does not change during backpagination ([\#7915](https://github.com/matrix-org/matrix-react-sdk/pull/7915)). Fixes vector-im/element-web#9192. + * Fix positioning of the thread context menu ([\#7918](https://github.com/matrix-org/matrix-react-sdk/pull/7918)). Fixes vector-im/element-web#21236. + * Inject sender into pinned messages ([\#7904](https://github.com/matrix-org/matrix-react-sdk/pull/7904)). Fixes vector-im/element-web#20314. + * Tweak info message padding in right panel timeline ([\#7901](https://github.com/matrix-org/matrix-react-sdk/pull/7901)). Fixes vector-im/element-web#21212. + * Fix another freeze on room switch ([\#7900](https://github.com/matrix-org/matrix-react-sdk/pull/7900)). Fixes vector-im/element-web#21127. + * Clean up error listener when location picker closes ([\#7902](https://github.com/matrix-org/matrix-react-sdk/pull/7902)). Fixes vector-im/element-web#21213. + * Fix edge case in context menu chevron positioning ([\#7899](https://github.com/matrix-org/matrix-react-sdk/pull/7899)). + * Fix composer format buttons on WebKit ([\#7898](https://github.com/matrix-org/matrix-react-sdk/pull/7898)). Fixes vector-im/element-web#20868. + * manage voicerecording state when deleting or sending a voice message ([\#7896](https://github.com/matrix-org/matrix-react-sdk/pull/7896)). Fixes vector-im/element-web#21151. + * Fix bug with useRoomHierarchy tight-looping loadMore on error ([\#7893](https://github.com/matrix-org/matrix-react-sdk/pull/7893)). + * Fix upload button & shortcut not working for narrow composer mode ([\#7894](https://github.com/matrix-org/matrix-react-sdk/pull/7894)). Fixes vector-im/element-web#21175 and vector-im/element-web#21142. + * Fix emoji insertion in thread composer going to the main composer ([\#7895](https://github.com/matrix-org/matrix-react-sdk/pull/7895)). Fixes vector-im/element-web#21202. + * Try harder to keep context menus inside the window ([\#7863](https://github.com/matrix-org/matrix-react-sdk/pull/7863)). Fixes vector-im/element-web#17527 and vector-im/element-web#18377. + * Fix edge case around event list summary layout ([\#7891](https://github.com/matrix-org/matrix-react-sdk/pull/7891)). Fixes vector-im/element-web#21180. + * Fix event list summary 1 hidden message pluralisation ([\#7890](https://github.com/matrix-org/matrix-react-sdk/pull/7890)). Fixes vector-im/element-web#21196. + * Fix vanishing recently viewed menu ([\#7887](https://github.com/matrix-org/matrix-react-sdk/pull/7887)). Fixes vector-im/element-web#20827. + * Fix freeze on room switch ([\#7884](https://github.com/matrix-org/matrix-react-sdk/pull/7884)). Fixes vector-im/element-web#21127. + * Check 'useSystemTheme' in quick settings theme switcher ([\#7809](https://github.com/matrix-org/matrix-react-sdk/pull/7809)). Fixes vector-im/element-web#21061. + * Fix 'my threads' filtering to include participated threads ([\#7882](https://github.com/matrix-org/matrix-react-sdk/pull/7882)). Fixes vector-im/element-web#20877. + * Remove log line to try to fix freeze on answering VoIP call ([\#7883](https://github.com/matrix-org/matrix-react-sdk/pull/7883)). + * Support social login & password on soft logout page ([\#7879](https://github.com/matrix-org/matrix-react-sdk/pull/7879)). Fixes vector-im/element-web#21099. + * Fix missing padding on server picker ([\#7864](https://github.com/matrix-org/matrix-react-sdk/pull/7864)). + * Throttle RoomState.members handlers ([\#7876](https://github.com/matrix-org/matrix-react-sdk/pull/7876)). Fixes vector-im/element-web#21127. + * Only show joined/invited in search dialog ([\#7875](https://github.com/matrix-org/matrix-react-sdk/pull/7875)). Fixes vector-im/element-web#21161. + * Don't pillify code blocks ([\#7861](https://github.com/matrix-org/matrix-react-sdk/pull/7861)). Fixes vector-im/element-web#20851 and vector-im/element-web#18687. + * Fix keyboard shortcut icons on macOS ([\#7869](https://github.com/matrix-org/matrix-react-sdk/pull/7869)). + +Changes in [3.42.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.42.0-rc.1) (2022-03-08) +=============================================================================================================== + +## ✨ Features + * Add unexposed account setting for hiding poll creation ([\#7972](https://github.com/matrix-org/matrix-react-sdk/pull/7972)). + * Allow pinning polls ([\#7922](https://github.com/matrix-org/matrix-react-sdk/pull/7922)). Fixes vector-im/element-web#20152. + * Make trailing `:` into a setting ([\#6711](https://github.com/matrix-org/matrix-react-sdk/pull/6711)). Fixes vector-im/element-web#16682. Contributed by @SimonBrandner. + * Location sharing > back button ([\#7958](https://github.com/matrix-org/matrix-react-sdk/pull/7958)). + * use LocationAssetType ([\#7965](https://github.com/matrix-org/matrix-react-sdk/pull/7965)). + * Location share type UI ([\#7924](https://github.com/matrix-org/matrix-react-sdk/pull/7924)). + * Add a few more UIComponent flags, and ensure they are used in existing code ([\#7937](https://github.com/matrix-org/matrix-react-sdk/pull/7937)). + * Add support for overriding strings in the app ([\#7886](https://github.com/matrix-org/matrix-react-sdk/pull/7886)). + * Add support for redirecting to external pages after logout ([\#7905](https://github.com/matrix-org/matrix-react-sdk/pull/7905)). + * Expose redaction power level in room settings ([\#7599](https://github.com/matrix-org/matrix-react-sdk/pull/7599)). Fixes vector-im/element-web#20590. Contributed by @SimonBrandner. + * Update and expand ways to access pinned messages ([\#7906](https://github.com/matrix-org/matrix-react-sdk/pull/7906)). Fixes vector-im/element-web#21209 and vector-im/element-web#21211. + * Add slash command to switch to a room's virtual room ([\#7839](https://github.com/matrix-org/matrix-react-sdk/pull/7839)). + +## 🐛 Bug Fixes + * Add another null guard for member ([\#7984](https://github.com/matrix-org/matrix-react-sdk/pull/7984)). Fixes vector-im/element-web#21319. + * Fix room account settings ([\#7999](https://github.com/matrix-org/matrix-react-sdk/pull/7999)). + * Fix missing summary text for pinned message changes ([\#7989](https://github.com/matrix-org/matrix-react-sdk/pull/7989)). Fixes vector-im/element-web#19823. + * Pass room to getRoomTombstone to avoid racing with setState ([\#7986](https://github.com/matrix-org/matrix-react-sdk/pull/7986)). + * Hide composer and call buttons when the room is tombstoned ([\#7975](https://github.com/matrix-org/matrix-react-sdk/pull/7975)). Fixes vector-im/element-web#21286. + * Fix bad ternary statement in autocomplete user pill insertions ([\#7977](https://github.com/matrix-org/matrix-react-sdk/pull/7977)). Fixes vector-im/element-web#21307. + * Fix sending locations into threads and fix i18n ([\#7943](https://github.com/matrix-org/matrix-react-sdk/pull/7943)). Fixes vector-im/element-web#21267. + * Fix location map attribution rendering over message action bar ([\#7974](https://github.com/matrix-org/matrix-react-sdk/pull/7974)). Fixes vector-im/element-web#21297. + * Fix wrongly asserting that PushRule::conditions is non-null ([\#7973](https://github.com/matrix-org/matrix-react-sdk/pull/7973)). Fixes vector-im/element-web#21305. + * Fix account & room settings race condition ([\#7953](https://github.com/matrix-org/matrix-react-sdk/pull/7953)). Fixes vector-im/element-web#21163. + * Fix bug with some space selections not being applied ([\#7971](https://github.com/matrix-org/matrix-react-sdk/pull/7971)). Fixes vector-im/element-web#21290. + * Revert "replace all require(.svg) with esm import" ([\#7969](https://github.com/matrix-org/matrix-react-sdk/pull/7969)). Fixes vector-im/element-web#21293. + * Hide unpinnable pinned messages in more cases ([\#7921](https://github.com/matrix-org/matrix-react-sdk/pull/7921)). + * Fix room list being laggy while scrolling 🐌 ([\#7939](https://github.com/matrix-org/matrix-react-sdk/pull/7939)). Fixes vector-im/element-web#21262. + * Make pinned messages more reliably reflect edits ([\#7920](https://github.com/matrix-org/matrix-react-sdk/pull/7920)). Fixes vector-im/element-web#17098. + * Improve accessibility of the BetaPill ([\#7949](https://github.com/matrix-org/matrix-react-sdk/pull/7949)). Fixes vector-im/element-web#21255. + * Autofocus correct composer after sending reaction ([\#7950](https://github.com/matrix-org/matrix-react-sdk/pull/7950)). Fixes vector-im/element-web#21273. + * Consider polls as message events for rendering redactions ([\#7944](https://github.com/matrix-org/matrix-react-sdk/pull/7944)). Fixes vector-im/element-web#21125. + * Prevent event tiles being shrunk/collapsed by flexbox ([\#7942](https://github.com/matrix-org/matrix-react-sdk/pull/7942)). Fixes vector-im/element-web#21269. + * Fix ExportDialog title on export cancellation ([\#7936](https://github.com/matrix-org/matrix-react-sdk/pull/7936)). Fixes vector-im/element-web#21260. Contributed by @luixxiul. + * Mandate use of js-sdk/src/matrix import over js-sdk/src ([\#7933](https://github.com/matrix-org/matrix-react-sdk/pull/7933)). Fixes vector-im/element-web#21253. + * Fix backspace not working in the invite dialog ([\#7931](https://github.com/matrix-org/matrix-react-sdk/pull/7931)). Fixes vector-im/element-web#21249. Contributed by @SimonBrandner. + * Fix right panel soft crashes due to missing room prop ([\#7923](https://github.com/matrix-org/matrix-react-sdk/pull/7923)). Fixes vector-im/element-web#21243. + * fix color of location share caret ([\#7917](https://github.com/matrix-org/matrix-react-sdk/pull/7917)). + * Wrap all EventTiles with a TileErrorBoundary and guard parsePermalink ([\#7916](https://github.com/matrix-org/matrix-react-sdk/pull/7916)). Fixes vector-im/element-web#21216. + * Fix changing space sometimes bouncing to the wrong space ([\#7910](https://github.com/matrix-org/matrix-react-sdk/pull/7910)). Fixes vector-im/element-web#20425. + * Ensure EventListSummary key does not change during backpagination ([\#7915](https://github.com/matrix-org/matrix-react-sdk/pull/7915)). Fixes vector-im/element-web#9192. + * Fix positioning of the thread context menu ([\#7918](https://github.com/matrix-org/matrix-react-sdk/pull/7918)). Fixes vector-im/element-web#21236. + * Inject sender into pinned messages ([\#7904](https://github.com/matrix-org/matrix-react-sdk/pull/7904)). Fixes vector-im/element-web#20314. + * Tweak info message padding in right panel timeline ([\#7901](https://github.com/matrix-org/matrix-react-sdk/pull/7901)). Fixes vector-im/element-web#21212. + * Fix another freeze on room switch ([\#7900](https://github.com/matrix-org/matrix-react-sdk/pull/7900)). Fixes vector-im/element-web#21127. + * Clean up error listener when location picker closes ([\#7902](https://github.com/matrix-org/matrix-react-sdk/pull/7902)). Fixes vector-im/element-web#21213. + * Fix edge case in context menu chevron positioning ([\#7899](https://github.com/matrix-org/matrix-react-sdk/pull/7899)). + * Fix composer format buttons on WebKit ([\#7898](https://github.com/matrix-org/matrix-react-sdk/pull/7898)). Fixes vector-im/element-web#20868. + * manage voicerecording state when deleting or sending a voice message ([\#7896](https://github.com/matrix-org/matrix-react-sdk/pull/7896)). Fixes vector-im/element-web#21151. + * Fix bug with useRoomHierarchy tight-looping loadMore on error ([\#7893](https://github.com/matrix-org/matrix-react-sdk/pull/7893)). + * Fix upload button & shortcut not working for narrow composer mode ([\#7894](https://github.com/matrix-org/matrix-react-sdk/pull/7894)). Fixes vector-im/element-web#21175 and vector-im/element-web#21142. + * Fix emoji insertion in thread composer going to the main composer ([\#7895](https://github.com/matrix-org/matrix-react-sdk/pull/7895)). Fixes vector-im/element-web#21202. + * Try harder to keep context menus inside the window ([\#7863](https://github.com/matrix-org/matrix-react-sdk/pull/7863)). Fixes vector-im/element-web#17527 and vector-im/element-web#18377. + * Fix edge case around event list summary layout ([\#7891](https://github.com/matrix-org/matrix-react-sdk/pull/7891)). Fixes vector-im/element-web#21180. + * Fix event list summary 1 hidden message pluralisation ([\#7890](https://github.com/matrix-org/matrix-react-sdk/pull/7890)). Fixes vector-im/element-web#21196. + * Fix vanishing recently viewed menu ([\#7887](https://github.com/matrix-org/matrix-react-sdk/pull/7887)). Fixes vector-im/element-web#20827. + * Fix freeze on room switch ([\#7884](https://github.com/matrix-org/matrix-react-sdk/pull/7884)). Fixes vector-im/element-web#21127. + * Check 'useSystemTheme' in quick settings theme switcher ([\#7809](https://github.com/matrix-org/matrix-react-sdk/pull/7809)). Fixes vector-im/element-web#21061. + * Fix 'my threads' filtering to include participated threads ([\#7882](https://github.com/matrix-org/matrix-react-sdk/pull/7882)). Fixes vector-im/element-web#20877. + * Remove log line to try to fix freeze on answering VoIP call ([\#7883](https://github.com/matrix-org/matrix-react-sdk/pull/7883)). + * Support social login & password on soft logout page ([\#7879](https://github.com/matrix-org/matrix-react-sdk/pull/7879)). Fixes vector-im/element-web#21099. + * Fix missing padding on server picker ([\#7864](https://github.com/matrix-org/matrix-react-sdk/pull/7864)). + * Throttle RoomState.members handlers ([\#7876](https://github.com/matrix-org/matrix-react-sdk/pull/7876)). Fixes vector-im/element-web#21127. + * Only show joined/invited in search dialog ([\#7875](https://github.com/matrix-org/matrix-react-sdk/pull/7875)). Fixes vector-im/element-web#21161. + * Don't pillify code blocks ([\#7861](https://github.com/matrix-org/matrix-react-sdk/pull/7861)). Fixes vector-im/element-web#20851 and vector-im/element-web#18687. + * Fix keyboard shortcut icons on macOS ([\#7869](https://github.com/matrix-org/matrix-react-sdk/pull/7869)). + Changes in [3.41.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.41.1) (2022-03-01) ===================================================================================================== @@ -278,7 +528,7 @@ Changes in [3.39.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/ ===================================================================================================== ## 🐛 Bug Fixes - * Fix the sticker picker ([\#7692](https://github.com/matrix-org/matrix-react-sdk/pull/7692)). Fixes vector-im/element-web#20797. + * Fix the sticker picker ([\#7692](https://github.com/matrix-org/matrix-react-sdk/pull/7692)). Fixes vector-im/element-web#20797. * Ensure UserInfo can be rendered without a room ([\#7687](https://github.com/matrix-org/matrix-react-sdk/pull/7687)). Fixes vector-im/element-web#20830. * Fix publishing address wrongly demanding the alias be available ([\#7690](https://github.com/matrix-org/matrix-react-sdk/pull/7690)). Fixes vector-im/element-web#12013 and vector-im/element-web#20833. @@ -1137,7 +1387,7 @@ Changes in [3.32.1](https://github.com/vector-im/element-desktop/releases/tag/v3 ## 🐛 Bug Fixes * Upgrade to matrix-js-sdk#14.0.1 - + Changes in [3.32.0](https://github.com/vector-im/element-desktop/releases/tag/v3.32.0) (2021-10-11) =================================================================================================== @@ -2283,7 +2533,7 @@ related to file upload. When uploading a file, the local file preview can lead to execution of scripts embedded in the uploaded file, but only after several user interactions to open the preview in a separate tab. This only impacts the local user while in the process of uploading. It cannot be exploited remotely -or by other users. Thanks to [Muhammad Zaid Ghifari](https://github.com/MR-ZHEEV) +or by other users. Thanks to [Muhammad Zaid Ghifari](https://github.com/MR-ZHEEV) for responsibly disclosing this via Matrix's Security Disclosure Policy. ## All changes @@ -6278,7 +6528,7 @@ Changes in [2.1.0-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/ ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.1.0-rc.1...v2.1.0-rc.2) - * Fix error in previous attempt to upgrade JS SDK + * Fix error in previous attempt to upgrade JS SDK Changes in [2.1.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.1.0-rc.1) (2020-02-13) ============================================================================================================= diff --git a/README.md b/README.md index 9059c5b5b8f..4664887360a 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ tracks lots of state for its child components which it passes into them for visu rendering via props. Good separation between the components is maintained by adopting various best -practices that anyone working with the SDK needs to be be aware of and uphold: +practices that anyone working with the SDK needs to be aware of and uphold: * Components are named with upper camel case (e.g. views/rooms/EventTile.js) @@ -65,13 +65,9 @@ practices that anyone working with the SDK needs to be be aware of and uphold: component is a view or a structure, and then a broad functional grouping (e.g. 'rooms' here) - * After creating a new component you must run `yarn reskindex` to regenerate - the `component-index.js` for the SDK (used in future for skinning) - - * The view's CSS file MUST have the same name (e.g. view/rooms/MessageTile.css). CSS for matrix-react-sdk currently resides in - https://github.com/vector-im/element-web/tree/master/src/skins/vector/css/matrix-react-sdk. + https://github.com/matrix-org/matrix-react-sdk/tree/master/res/css. * Per-view CSS is optional - it could choose to inherit all its styling from the context of the rest of the app, although this is unusual for any but @@ -158,9 +154,6 @@ cd matrix-react-sdk git checkout develop yarn link matrix-js-sdk yarn install - -# Generate the `component-index.js` file. -yarn reskindex ``` See the [help for `yarn link`](https://classic.yarnpkg.com/docs/cli/link) for diff --git a/__mocks__/maplibre-gl.js b/__mocks__/maplibre-gl.js index b1f114e8eff..599cacde13d 100644 --- a/__mocks__/maplibre-gl.js +++ b/__mocks__/maplibre-gl.js @@ -1,20 +1,30 @@ const EventEmitter = require("events"); -const { LngLat } = require('maplibre-gl'); +const { LngLat, NavigationControl, LngLatBounds } = require('maplibre-gl'); class MockMap extends EventEmitter { addControl = jest.fn(); removeControl = jest.fn(); + zoomIn = jest.fn(); + zoomOut = jest.fn(); + setCenter = jest.fn(); + setStyle = jest.fn(); + fitBounds = jest.fn(); } -class MockGeolocateControl extends EventEmitter { +const MockMapInstance = new MockMap(); +class MockGeolocateControl extends EventEmitter { + trigger = jest.fn(); } -class MockMarker extends EventEmitter { - setLngLat = jest.fn().mockReturnValue(this); - addTo = jest.fn(); -} +const MockGeolocateInstance = new MockGeolocateControl(); +const MockMarker = {} +MockMarker.setLngLat = jest.fn().mockReturnValue(MockMarker); +MockMarker.addTo = jest.fn().mockReturnValue(MockMarker); +MockMarker.remove = jest.fn().mockReturnValue(MockMarker); module.exports = { - Map: MockMap, - GeolocateControl: MockGeolocateControl, - Marker: MockMarker, + Map: jest.fn().mockReturnValue(MockMapInstance), + GeolocateControl: jest.fn().mockReturnValue(MockGeolocateInstance), + Marker: jest.fn().mockReturnValue(MockMarker), LngLat, + LngLatBounds, + NavigationControl, }; diff --git a/babel.config.js b/babel.config.js index f00e83652c1..ac94a29559e 100644 --- a/babel.config.js +++ b/babel.config.js @@ -13,7 +13,6 @@ module.exports = { "@babel/preset-react", ], "plugins": [ - ["@babel/plugin-proposal-decorators", {legacy: true}], "@babel/plugin-proposal-export-default-from", "@babel/plugin-proposal-numeric-separator", "@babel/plugin-proposal-class-properties", diff --git a/cypress.json b/cypress.json new file mode 100644 index 00000000000..2c39bb411fe --- /dev/null +++ b/cypress.json @@ -0,0 +1,5 @@ +{ + "baseUrl": "http://localhost:8080", + "videoUploadOnPasses": false, + "projectId": "ppvnzg" +} diff --git a/cypress/integration/1-register/register.spec.ts b/cypress/integration/1-register/register.spec.ts new file mode 100644 index 00000000000..f719da55477 --- /dev/null +++ b/cypress/integration/1-register/register.spec.ts @@ -0,0 +1,52 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/// + +import { SynapseInstance } from "../../plugins/synapsedocker/index"; + +describe("Registration", () => { + let synapseId; + let synapsePort; + + beforeEach(() => { + cy.task("synapseStart", "consent").then(result => { + synapseId = result.synapseId; + synapsePort = result.port; + }); + cy.visit("/#/register"); + }); + + afterEach(() => { + cy.task("synapseStop", synapseId); + }); + + it("registers an account and lands on the home screen", () => { + cy.get(".mx_ServerPicker_change", { timeout: 15000 }).click(); + cy.get(".mx_ServerPickerDialog_otherHomeserver").type(`http://localhost:${synapsePort}`); + cy.get(".mx_ServerPickerDialog_continue").click(); + // wait for the dialog to go away + cy.get('.mx_ServerPickerDialog').should('not.exist'); + cy.get("#mx_RegistrationForm_username").type("alice"); + cy.get("#mx_RegistrationForm_password").type("totally a great password"); + cy.get("#mx_RegistrationForm_passwordConfirm").type("totally a great password"); + cy.get(".mx_Login_submit").click(); + cy.get(".mx_RegistrationEmailPromptDialog button.mx_Dialog_primary").click(); + cy.get(".mx_InteractiveAuthEntryComponents_termsPolicy input").click(); + cy.get(".mx_InteractiveAuthEntryComponents_termsSubmit").click(); + cy.url().should('contain', '/#/home'); + }); +}); diff --git a/test/minimal-sdk.js b/cypress/plugins/index.ts similarity index 74% rename from test/minimal-sdk.js rename to cypress/plugins/index.ts index f39893f78c2..db01ceceb4f 100644 --- a/test/minimal-sdk.js +++ b/cypress/plugins/index.ts @@ -14,16 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* - * minimal-sdk.js - * - * Starts up the skin system with even less than `skinned-sdk`. - */ - -import * as sdk from "../src/index"; - -const components = {}; +/// -sdk.loadSkin({ components }); +import { synapseDocker } from "./synapsedocker/index"; -export default sdk; +export default function(on, config) { + synapseDocker(on, config); +} diff --git a/cypress/plugins/synapsedocker/index.ts b/cypress/plugins/synapsedocker/index.ts new file mode 100644 index 00000000000..0f029e7b2ed --- /dev/null +++ b/cypress/plugins/synapsedocker/index.ts @@ -0,0 +1,212 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/// + +import * as path from "path"; +import * as os from "os"; +import * as crypto from "crypto"; +import * as childProcess from "child_process"; +import * as fse from "fs-extra"; + +// A cypress plugins to add command to start & stop synapses in +// docker with preset templates. + +interface SynapseConfig { + configDir: string; + registrationSecret: string; +} + +export interface SynapseInstance extends SynapseConfig { + synapseId: string; + port: number; +} + +const synapses = new Map(); + +function randB64Bytes(numBytes: number): string { + return crypto.randomBytes(numBytes).toString("base64").replace(/=*$/, ""); +} + +async function cfgDirFromTemplate(template: string): Promise { + const templateDir = path.join(__dirname, "templates", template); + + const stats = await fse.stat(templateDir); + if (!stats?.isDirectory) { + throw new Error(`No such template: ${template}`); + } + const tempDir = await fse.mkdtemp(path.join(os.tmpdir(), 'react-sdk-synapsedocker-')); + + // change permissions on the temp directory so the docker container can see its contents + await fse.chmod(tempDir, 0o777); + + // copy the contents of the template dir, omitting homeserver.yaml as we'll template that + console.log(`Copy ${templateDir} -> ${tempDir}`); + await fse.copy(templateDir, tempDir, { filter: f => path.basename(f) !== 'homeserver.yaml' }); + + const registrationSecret = randB64Bytes(16); + const macaroonSecret = randB64Bytes(16); + const formSecret = randB64Bytes(16); + + // now copy homeserver.yaml, applying sustitutions + console.log(`Gen ${path.join(templateDir, "homeserver.yaml")}`); + let hsYaml = await fse.readFile(path.join(templateDir, "homeserver.yaml"), "utf8"); + hsYaml = hsYaml.replace(/{{REGISTRATION_SECRET}}/g, registrationSecret); + hsYaml = hsYaml.replace(/{{MACAROON_SECRET_KEY}}/g, macaroonSecret); + hsYaml = hsYaml.replace(/{{FORM_SECRET}}/g, formSecret); + await fse.writeFile(path.join(tempDir, "homeserver.yaml"), hsYaml); + + // now generate a signing key (we could use synapse's config generation for + // this, or we could just do this...) + // NB. This assumes the homeserver.yaml specifies the key in this location + const signingKey = randB64Bytes(32); + console.log(`Gen ${path.join(templateDir, "localhost.signing.key")}`); + await fse.writeFile(path.join(tempDir, "localhost.signing.key"), `ed25519 x ${signingKey}`); + + return { + configDir: tempDir, + registrationSecret, + }; +} + +// Start a synapse instance: the template must be the name of +// one of the templates in the cypress/plugins/synapsedocker/templates +// directory +async function synapseStart(template: string): Promise { + const synCfg = await cfgDirFromTemplate(template); + + console.log(`Starting synapse with config dir ${synCfg.configDir}...`); + + const containerName = `react-sdk-cypress-synapse-${crypto.randomBytes(4).toString("hex")}`; + + const synapseId = await new Promise((resolve, reject) => { + childProcess.execFile('docker', [ + "run", + "--name", containerName, + "-d", + "-v", `${synCfg.configDir}:/data`, + "-p", "8008/tcp", + "matrixdotorg/synapse:develop", + "run", + ], (err, stdout) => { + if (err) reject(err); + resolve(stdout.trim()); + }); + }); + + // Get the port that docker allocated: specifying only one + // port above leaves docker to just grab a free one, although + // in hindsight we need to put the port in public_baseurl in the + // config really, so this will probably need changing to use a fixed + // / configured port. + const port = await new Promise((resolve, reject) => { + childProcess.execFile('docker', [ + "port", synapseId, "8008", + ], { encoding: 'utf8' }, (err, stdout) => { + if (err) reject(err); + resolve(Number(stdout.trim().split(":")[1])); + }); + }); + + synapses.set(synapseId, Object.assign({ + port, + synapseId, + }, synCfg)); + + console.log(`Started synapse with id ${synapseId} on port ${port}.`); + return synapses.get(synapseId); +} + +async function synapseStop(id) { + const synCfg = synapses.get(id); + + if (!synCfg) throw new Error("Unknown synapse ID"); + + try { + const synapseLogsPath = path.join("cypress", "synapselogs", id); + await fse.ensureDir(synapseLogsPath); + + const stdoutFile = await fse.open(path.join(synapseLogsPath, "stdout.log"), "w"); + const stderrFile = await fse.open(path.join(synapseLogsPath, "stderr.log"), "w"); + await new Promise((resolve, reject) => { + childProcess.spawn('docker', [ + "logs", + id, + ], { + stdio: ["ignore", stdoutFile, stderrFile], + }).once('close', resolve); + }); + await fse.close(stdoutFile); + await fse.close(stderrFile); + + await new Promise((resolve, reject) => { + childProcess.execFile('docker', [ + "stop", + id, + ], err => { + if (err) reject(err); + resolve(); + }); + }); + } finally { + await new Promise((resolve, reject) => { + childProcess.execFile('docker', [ + "rm", + id, + ], err => { + if (err) reject(err); + resolve(); + }); + }); + } + + await fse.remove(synCfg.configDir); + + synapses.delete(id); + + console.log(`Stopped synapse id ${id}.`); + // cypres deliberately fails if you return 'undefined', so + // return null to signal all is well and we've handled the task. + return null; +} + +/** + * @type {Cypress.PluginConfig} + */ +// eslint-disable-next-line no-unused-vars +export function synapseDocker(on, config) { + on("task", { + synapseStart, synapseStop, + }); + + on("after:spec", async (spec) => { + // Cleans up any remaining synapse instances after a spec run + // This is on the theory that we should avoid re-using synapse + // instances between spec runs: they should be cheap enough to + // start that we can have a separate one for each spec run or even + // test. If we accidentally re-use synapses, we could inadvertantly + // make our tests depend on each other. + for (const synId of synapses.keys()) { + console.warn(`Cleaning up synapse ID ${synId} after ${spec.name}`); + await synapseStop(synId); + } + }); + + on("before:run", async () => { + // tidy up old synapse log files before each run + await fse.emptyDir(path.join("cypress", "synapselogs")); + }); +} diff --git a/cypress/plugins/synapsedocker/templates/COPYME/README.md b/cypress/plugins/synapsedocker/templates/COPYME/README.md new file mode 100644 index 00000000000..df1ed89e6e4 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/COPYME/README.md @@ -0,0 +1,3 @@ +# Meta-template for synapse templates + +To make another template, you can copy this directory diff --git a/cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml b/cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml new file mode 100644 index 00000000000..fab1bc1c451 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml @@ -0,0 +1,72 @@ +server_name: "localhost" +pid_file: /data/homeserver.pid +# XXX: This won't actually be right: it lets docker allocate an ephemeral port, +# so we have a chicken-and-egg problem +public_baseurl: http://localhost:8008/ +# Listener is always port 8008 (configured in the container) +listeners: + - port: 8008 + tls: false + bind_addresses: ['::'] + type: http + x_forwarded: true + + resources: + - names: [client, federation, consent] + compress: false + +# An sqlite in-memory database is fast & automatically wipes each time +database: + name: "sqlite3" + args: + database: ":memory:" + +# Needs to be configured to log to the console like a good docker process +log_config: "/data/log.config" + +rc_messages_per_second: 10000 +rc_message_burst_count: 10000 +rc_registration: + per_second: 10000 + burst_count: 10000 + +rc_login: + address: + per_second: 10000 + burst_count: 10000 + account: + per_second: 10000 + burst_count: 10000 + failed_attempts: + per_second: 10000 + burst_count: 10000 + +media_store_path: "/data/media_store" +uploads_path: "/data/uploads" +enable_registration: true +enable_registration_without_verification: true +disable_msisdn_registration: false +# These placeholders will be be replaced with values generated at start +registration_shared_secret: "{{REGISTRATION_SECRET}}" +report_stats: false +macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" +form_secret: "{{FORM_SECRET}}" +# Signing key must be here: it will be generated to this file +signing_key_path: "/data/localhost.signing.key" +email: + enable_notifs: false + smtp_host: "localhost" + smtp_port: 25 + smtp_user: "exampleusername" + smtp_pass: "examplepassword" + require_transport_security: False + notif_from: "Your Friendly %(app)s homeserver " + app_name: Matrix + notif_template_html: notif_mail.html + notif_template_text: notif_mail.txt + notif_for_new_users: True + client_base_url: "http://localhost/element" + +trusted_key_servers: + - server_name: "matrix.org" +suppress_key_server_warning: true diff --git a/cypress/plugins/synapsedocker/templates/COPYME/log.config b/cypress/plugins/synapsedocker/templates/COPYME/log.config new file mode 100644 index 00000000000..ac232762da3 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/COPYME/log.config @@ -0,0 +1,50 @@ +# Log configuration for Synapse. +# +# This is a YAML file containing a standard Python logging configuration +# dictionary. See [1] for details on the valid settings. +# +# Synapse also supports structured logging for machine readable logs which can +# be ingested by ELK stacks. See [2] for details. +# +# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema +# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html + +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + # A handler that writes logs to stderr. Unused by default, but can be used + # instead of "buffer" and "file" in the logger handlers. + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: INFO + + twisted: + # We send the twisted logging directly to the file handler, + # to work around https://github.com/matrix-org/synapse/issues/3471 + # when using "buffer" logger. Use "console" to log to stderr instead. + handlers: [console] + propagate: false + +root: + level: INFO + + # Write logs to the `buffer` handler, which will buffer them together in memory, + # then write them to a file. + # + # Replace "buffer" with "console" to log to stderr instead. (Note that you'll + # also need to update the configuration for the `twisted` logger above, in + # this case.) + # + handlers: [console] + +disable_existing_loggers: false diff --git a/cypress/plugins/synapsedocker/templates/consent/README.md b/cypress/plugins/synapsedocker/templates/consent/README.md new file mode 100644 index 00000000000..713e55f9d51 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/consent/README.md @@ -0,0 +1 @@ +A synapse configured with user privacy consent enabled diff --git a/cypress/plugins/synapsedocker/templates/consent/homeserver.yaml b/cypress/plugins/synapsedocker/templates/consent/homeserver.yaml new file mode 100644 index 00000000000..e26133f6d11 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/consent/homeserver.yaml @@ -0,0 +1,84 @@ +server_name: "localhost" +pid_file: /data/homeserver.pid +public_baseurl: http://localhost:5005/ +listeners: + - port: 8008 + tls: false + bind_addresses: ['::'] + type: http + x_forwarded: true + + resources: + - names: [client, federation, consent] + compress: false + +database: + name: "sqlite3" + args: + database: ":memory:" + +log_config: "/data/log.config" + +rc_messages_per_second: 10000 +rc_message_burst_count: 10000 +rc_registration: + per_second: 10000 + burst_count: 10000 + +rc_login: + address: + per_second: 10000 + burst_count: 10000 + account: + per_second: 10000 + burst_count: 10000 + failed_attempts: + per_second: 10000 + burst_count: 10000 + +media_store_path: "/data/media_store" +uploads_path: "/data/uploads" +enable_registration: true +enable_registration_without_verification: true +disable_msisdn_registration: false +registration_shared_secret: "{{REGISTRATION_SECRET}}" +report_stats: false +macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" +form_secret: "{{FORM_SECRET}}" +signing_key_path: "/data/localhost.signing.key" +email: + enable_notifs: false + smtp_host: "localhost" + smtp_port: 25 + smtp_user: "exampleusername" + smtp_pass: "examplepassword" + require_transport_security: False + notif_from: "Your Friendly %(app)s homeserver " + app_name: Matrix + notif_template_html: notif_mail.html + notif_template_text: notif_mail.txt + notif_for_new_users: True + client_base_url: "http://localhost/element" + +user_consent: + template_dir: /data/res/templates/privacy + version: 1.0 + server_notice_content: + msgtype: m.text + body: >- + To continue using this homeserver you must review and agree to the + terms and conditions at %(consent_uri)s + send_server_notice_to_guests: True + block_events_error: >- + To continue using this homeserver you must review and agree to the + terms and conditions at %(consent_uri)s + require_at_registration: true + +server_notices: + system_mxid_localpart: notices + system_mxid_display_name: "Server Notices" + system_mxid_avatar_url: "mxc://localhost:5005/oumMVlgDnLYFaPVkExemNVVZ" + room_name: "Server Notices" +trusted_key_servers: + - server_name: "matrix.org" +suppress_key_server_warning: true diff --git a/cypress/plugins/synapsedocker/templates/consent/log.config b/cypress/plugins/synapsedocker/templates/consent/log.config new file mode 100644 index 00000000000..ac232762da3 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/consent/log.config @@ -0,0 +1,50 @@ +# Log configuration for Synapse. +# +# This is a YAML file containing a standard Python logging configuration +# dictionary. See [1] for details on the valid settings. +# +# Synapse also supports structured logging for machine readable logs which can +# be ingested by ELK stacks. See [2] for details. +# +# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema +# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html + +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + # A handler that writes logs to stderr. Unused by default, but can be used + # instead of "buffer" and "file" in the logger handlers. + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: INFO + + twisted: + # We send the twisted logging directly to the file handler, + # to work around https://github.com/matrix-org/synapse/issues/3471 + # when using "buffer" logger. Use "console" to log to stderr instead. + handlers: [console] + propagate: false + +root: + level: INFO + + # Write logs to the `buffer` handler, which will buffer them together in memory, + # then write them to a file. + # + # Replace "buffer" with "console" to log to stderr instead. (Note that you'll + # also need to update the configuration for the `twisted` logger above, in + # this case.) + # + handlers: [console] + +disable_existing_loggers: false diff --git a/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html b/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html new file mode 100644 index 00000000000..d4959b4bcb3 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html @@ -0,0 +1,23 @@ + + + + Test Privacy policy + + + {% if has_consented %} +

    + Thank you, you've already accepted the license. +

    + {% else %} +

    + Please accept the license! +

    +
    + + + + +
    + {% endif %} + + \ No newline at end of file diff --git a/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html b/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html new file mode 100644 index 00000000000..abe27d87ca1 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html @@ -0,0 +1,9 @@ + + + + Test Privacy policy + + +

    Danke schon

    + + \ No newline at end of file diff --git a/cypress/support/index.ts b/cypress/support/index.ts new file mode 100644 index 00000000000..9901ef4cb80 --- /dev/null +++ b/cypress/support/index.ts @@ -0,0 +1,3 @@ +// Empty file to prevent cypress from recreating a helpful example +// file on every run (their example file doesn't use semicolons and +// so fails our lint rules). diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json new file mode 100644 index 00000000000..85239e1a2a7 --- /dev/null +++ b/cypress/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "target": "es2016", + "lib": ["es2020", "dom"], + "types": ["cypress"], + "moduleResolution": "node" + }, + "include": ["**/*.ts"] +} diff --git a/docs/features/keyboardShortcuts.md b/docs/features/keyboardShortcuts.md index 71814023543..349535918b3 100644 --- a/docs/features/keyboardShortcuts.md +++ b/docs/features/keyboardShortcuts.md @@ -1,6 +1,6 @@ # Keyboard shortcuts -## Using the `KeyBindingManger` +## Using the `KeyBindingManager` The `KeyBindingManager` (accessible using `getKeyBindingManager()`) is a class with several methods that allow you to get a `KeyBindingAction` based on a diff --git a/docs/settings.md b/docs/settings.md index 379f3c5dcd4..dae6eb22b81 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -1,38 +1,38 @@ # Settings Reference -This document serves as developer documentation for using "Granular Settings". Granular Settings allow users to specify -different values for a setting at particular levels of interest. For example, a user may say that in a particular room -they want URL previews off, but in all other rooms they want them enabled. The `SettingsStore` helps mask the complexity +This document serves as developer documentation for using "Granular Settings". Granular Settings allow users to specify +different values for a setting at particular levels of interest. For example, a user may say that in a particular room +they want URL previews off, but in all other rooms they want them enabled. The `SettingsStore` helps mask the complexity of dealing with the different levels and exposes easy to use getters and setters. ## Levels -Granular Settings rely on a series of known levels in order to use the correct value for the scenario. These levels, in +Granular Settings rely on a series of known levels in order to use the correct value for the scenario. These levels, in order of priority, are: * `device` - The current user's device * `room-device` - The current user's device, but only when in a specific room * `room-account` - The current user's account, but only when in a specific room * `account` - The current user's account * `room` - A specific room (setting for all members of the room) -* `config` - Values are defined by the `settingDefaults` key (usually) in `config.json` +* `config` - Values are defined by the `setting_defaults` key (usually) in `config.json` * `default` - The hardcoded default for the settings -Individual settings may control which levels are appropriate for them as part of the defaults. This is often to ensure +Individual settings may control which levels are appropriate for them as part of the defaults. This is often to ensure that room administrators cannot force account-only settings upon participants. ## Settings -Settings are the different options a user may set or experience in the application. These are pre-defined in +Settings are the different options a user may set or experience in the application. These are pre-defined in `src/settings/Settings.tsx` under the `SETTINGS` constant, and match the `ISetting` interface as defined there. -Settings that support the config level can be set in the config file under the `settingDefaults` key (note that some +Settings that support the config level can be set in the config file under the `setting_defaults` key (note that some settings, like the "theme" setting, are special cased in the config file): -```json +```json5 { ... - "settingDefaults": { + "setting_defaults": { "settingName": true }, ... @@ -41,20 +41,20 @@ settings, like the "theme" setting, are special cased in the config file): ### Getting values for a setting -After importing `SettingsStore`, simply make a call to `SettingsStore.getValue`. The `roomId` parameter should always -be supplied where possible, even if the setting does not have a per-room level value. This is to ensure that the value +After importing `SettingsStore`, simply make a call to `SettingsStore.getValue`. The `roomId` parameter should always +be supplied where possible, even if the setting does not have a per-room level value. This is to ensure that the value returned is best represented in the room, particularly if the setting ever gets a per-room level in the future. -In settings pages it is often desired to have the value at a particular level instead of getting the calculated value. -Call `SettingsStore.getValueAt` to get the value of a setting at a particular level, and optionally make it explicitly -at that level. By default `getValueAt` will traverse the tree starting at the provided level; making it explicit means -it will not go beyond the provided level. When using `getValueAt`, please be sure to use `SettingLevel` to represent the +In settings pages it is often desired to have the value at a particular level instead of getting the calculated value. +Call `SettingsStore.getValueAt` to get the value of a setting at a particular level, and optionally make it explicitly +at that level. By default `getValueAt` will traverse the tree starting at the provided level; making it explicit means +it will not go beyond the provided level. When using `getValueAt`, please be sure to use `SettingLevel` to represent the target level. ### Setting values for a setting -Values are defined at particular levels and should be done in a safe manner. There are two checks to perform to ensure a -clean save: is the level supported and can the user actually set the value. In most cases, neither should be an issue +Values are defined at particular levels and should be done in a safe manner. There are two checks to perform to ensure a +clean save: is the level supported and can the user actually set the value. In most cases, neither should be an issue although there are circumstances where this changes. An example of a safe call is: ```javascript const isSupported = SettingsStore.isLevelSupported(SettingLevel.ROOM); @@ -66,12 +66,12 @@ if (isSupported) { } ``` -These checks may also be performed in different areas of the application to avoid the verbose example above. For +These checks may also be performed in different areas of the application to avoid the verbose example above. For instance, the component which allows changing the setting may be hidden conditionally on the above conditions. ##### `SettingsFlag` component -Where possible, the `SettingsFlag` component should be used to set simple "flip-a-bit" (true/false) settings. The +Where possible, the `SettingsFlag` component should be used to set simple "flip-a-bit" (true/false) settings. The `SettingsFlag` also supports simple radio button options, such as the theme the user would like to use. ```html { @@ -163,27 +163,27 @@ SettingsStore.getValue(...); // this will return the value set in `setValue` abo ## Watching for changes -Most use cases do not need to set up a watcher because they are able to react to changes as they are made, or the -changes which are made are not significant enough for it to matter. Watchers are intended to be used in scenarios where -it is important to react to changes made by other logged in devices. Typically, this would be done within the component -itself, however the component should not be aware of the intricacies of setting inversion or remapping to particular -data structures. Instead, a generic watcher interface is provided on `SettingsStore` to watch (and subsequently unwatch) +Most use cases do not need to set up a watcher because they are able to react to changes as they are made, or the +changes which are made are not significant enough for it to matter. Watchers are intended to be used in scenarios where +it is important to react to changes made by other logged in devices. Typically, this would be done within the component +itself, however the component should not be aware of the intricacies of setting inversion or remapping to particular +data structures. Instead, a generic watcher interface is provided on `SettingsStore` to watch (and subsequently unwatch) for changes in a setting. An example of a watcher in action would be: ```javascript class MyComponent extends React.Component { - + settingWatcherRef = null; - + componentWillMount() { const callback = (settingName, roomId, level, newValAtLevel, newVal) => { this.setState({color: newVal}); }; this.settingWatcherRef = SettingsStore.watchSetting("roomColor", "!example:matrix.org", callback); } - + componentWillUnmount() { SettingsStore.unwatchSetting(this.settingWatcherRef); } @@ -193,29 +193,29 @@ class MyComponent extends React.Component { # Maintainers Reference -The granular settings system has a few complex parts to power it. This section is to document how the `SettingsStore` is +The granular settings system has a few complex parts to power it. This section is to document how the `SettingsStore` is supposed to work. ### General information -The `SettingsStore` uses the hardcoded `LEVEL_ORDER` constant to ensure that it is using the correct override procedure. -The array is checked from left to right, simulating the behaviour of overriding values from the higher levels. Each +The `SettingsStore` uses the hardcoded `LEVEL_ORDER` constant to ensure that it is using the correct override procedure. +The array is checked from left to right, simulating the behaviour of overriding values from the higher levels. Each level should be defined in this array, including `default`. -Handlers (`src/settings/handlers/SettingsHandler.ts`) represent a single level and are responsible for getting and -setting values at that level. Handlers also provide additional information to the `SettingsStore` such as if the level -is supported or if the current user may set values at the level. The `SettingsStore` will use the handler to enforce -checks and manipulate settings. Handlers are also responsible for dealing with migration patterns or legacy settings for -their level (for example, a setting being renamed or using a different key from other settings in the underlying store). -Handlers are provided to the `SettingsStore` via the `LEVEL_HANDLERS` constant. `SettingsStore` will optimize lookups by +Handlers (`src/settings/handlers/SettingsHandler.ts`) represent a single level and are responsible for getting and +setting values at that level. Handlers also provide additional information to the `SettingsStore` such as if the level +is supported or if the current user may set values at the level. The `SettingsStore` will use the handler to enforce +checks and manipulate settings. Handlers are also responsible for dealing with migration patterns or legacy settings for +their level (for example, a setting being renamed or using a different key from other settings in the underlying store). +Handlers are provided to the `SettingsStore` via the `LEVEL_HANDLERS` constant. `SettingsStore` will optimize lookups by only considering handlers that are supported on the platform. -Local echo is achieved through `src/settings/handlers/LocalEchoWrapper.ts` which acts as a wrapper around a given -handler. This is automatically applied to all defined `LEVEL_HANDLERS` and proxies the calls to the wrapped handler -where possible. The echo is achieved by a simple object cache stored within the class itself. The cache is invalidated +Local echo is achieved through `src/settings/handlers/LocalEchoWrapper.ts` which acts as a wrapper around a given +handler. This is automatically applied to all defined `LEVEL_HANDLERS` and proxies the calls to the wrapped handler +where possible. The echo is achieved by a simple object cache stored within the class itself. The cache is invalidated immediately upon the proxied save call succeeding or failing. -Controllers are notified of changes by the `SettingsStore`, and are given the opportunity to override values after the +Controllers are notified of changes by the `SettingsStore`, and are given the opportunity to override values after the `SettingsStore` has deemed the value calculated. Controllers are invoked as the last possible step in the code. ### Features @@ -224,17 +224,17 @@ See above for feature reference. ### Watchers -Watchers can appear complicated under the hood: there is a central `WatchManager` which handles the actual invocation -of callbacks, and callbacks are managed by the SettingsStore by redirecting the caller's callback to a dedicated -callback. This is done so that the caller can reuse the same function as their callback without worrying about whether -or not it'll unsubscribe all watchers. +Watchers can appear complicated under the hood: there is a central `WatchManager` which handles the actual invocation +of callbacks, and callbacks are managed by the SettingsStore by redirecting the caller's callback to a dedicated +callback. This is done so that the caller can reuse the same function as their callback without worrying about whether +or not it'll unsubscribe all watchers. -Setting changes are emitted into the default `WatchManager`, which calculates the new value for the setting. Ideally, -we'd also try and suppress updates which don't have a consequence on this value, however there's not an easy way to do -this. Instead, we just dispatch an update for all changes and leave it up to the consumer to deduplicate. +Setting changes are emitted into the default `WatchManager`, which calculates the new value for the setting. Ideally, +we'd also try and suppress updates which don't have a consequence on this value, however there's not an easy way to do +this. Instead, we just dispatch an update for all changes and leave it up to the consumer to deduplicate. -In practice, handlers which rely on remote changes (account data, room events, etc) will always attach a listener to the -`MatrixClient`. They then watch for changes to events they care about and send off appropriate updates to the -generalized `WatchManager` - a class specifically designed to deduplicate the logic of managing watchers. The handlers -which are localized to the local client (device) generally just trigger the `WatchManager` when they manipulate the +In practice, handlers which rely on remote changes (account data, room events, etc) will always attach a listener to the +`MatrixClient`. They then watch for changes to events they care about and send off appropriate updates to the +generalized `WatchManager` - a class specifically designed to deduplicate the logic of managing watchers. The handlers +which are localized to the local client (device) generally just trigger the `WatchManager` when they manipulate the setting themselves as there's nothing to really 'watch'. diff --git a/docs/skinning.md b/docs/skinning.md index 229bc783724..0186186c24a 100644 --- a/docs/skinning.md +++ b/docs/skinning.md @@ -1,71 +1,18 @@ # Skinning -The react-sdk can be skinned to replace presentation components, CSS, or -other relevant parts of the SDK. Typically consumers will replace entire -components and get the ability for custom CSS as a result. - -This doc isn't exhaustive on how skinning works, though it should cover -some of the more complicated parts such as component replacement. - -## Loading a skin - -1. Generate a `component-index.js` (preferably using the tools that the react-sdk -exposes). This can typically be done with a npm script like `"reskindex -h src/header"`. -2. In your app's entry point, add something like this code: - ```javascript - import {loadSkin} from "matrix-react-sdk"; - loadSkin(import("component-index").components); - // The rest of your imports go under this. - ``` -3. Import the remainder of the SDK and bootstrap your app. - -It is extremely important that you **do not** import anything else from the -SDK prior to loading your skin as otherwise the skin might not work. Loading -the skin should be one of the first things your app does, if not the very -first thing. - -Additionally, **do not** provide `loadSkin` with the react-sdk components -themselves otherwise the app might explode. The SDK is already aware of its -components and doesn't need to be told. - -## Replacing components - -Components that replace the react-sdk ones MUST have a `replaces` static -key on the component's class to describe which component it overrides. For -example, if your `VectorAuthPage` component is meant to replace the react-sdk -`AuthPage` component then you'd add `static replaces = 'views.auth.AuthPage';` -to the `VectorAuthPage` class. - -Other than that, the skin just needs to be loaded normally as mentioned above. -Consumers of the SDK likely will not be interested in the rest of this section. - -### SDK developer notes - -Components in the react-sdk MUST be decorated with the `@replaceableComponent` -function. For components that can't use the decorator, they must use a -variation that provides similar functionality. The decorator gives consumers -an opportunity to load skinned components by abusing import ordering and -behaviour. - -Decorators are executed at import time which is why we can abuse the import -ordering behaviour: importing `loadSkin` doesn't trigger any components to -be imported, allowing the consumer to specify a skin. When the consumer does -import a component (for example, `MatrixChat`), it starts to pull in all the -components via `import` statements. When the components get pulled in the -decorator checks with the skinned components to see if it should be replacing -the component being imported. The decorator then effectively replaces the -components when needed by specifying the skinned component as an override for -the SDK's component, which should in theory override critical functions like -`render()` and lifecycle event handlers. - -The decorator also means that older usage of `getComponent()` is no longer -required because components should be replaced by the decorator. Eventually -the react-sdk should only have one usage of `getComponent()`: the decorator. - -The decorator assumes that if `getComponent()` returns null that there is -no skinned version of the component and continues on using the SDK's component. -In previous versions of the SDK, the function would throw an error instead -because it also expected the skin to list the SDK's components as well, however -that is no longer possible due to the above. - -In short, components should always be `import`ed. +Skinning in the context of the react-sdk is component replacement rather than CSS. This means you can override (replace) +any accessible component in the project to implement custom behaviour, look & feel, etc. Depending on your approach, +overriding CSS classes to apply custom styling is also possible, though harder to do. + +At present, the react-sdk offers no stable interface for components - this means properties and state can and do change +at any time without notice. Once we determine the react-sdk to be stable enough to use as a proper SDK, we will adjust +this policy. In the meantime, skinning is done completely at your own risk. + +The approach you take is up to you - we suggest using a module replacement plugin, as found in +[webpack](https://webpack.js.org/plugins/normal-module-replacement-plugin/), though you're free to use whichever build +system works for you. The react-sdk does not have any particular functions to call to load skins, so simply replace or +extend the components/stores/etc you're after and build. As a reminder though, this is done completely at your own risk +as we cannot guarantee a stable interface at this time. + +Taking a look at [element-web](https://github.com/vector-im/element-web)'s approach to skinning may be worthwhile, as it +overrides some relatively simple components. diff --git a/docs/slate-formats.md b/docs/slate-formats.md deleted file mode 100644 index 7bb2fc9c5ff..00000000000 --- a/docs/slate-formats.md +++ /dev/null @@ -1,88 +0,0 @@ -Guide to data types used by the Slate-based Rich Text Editor ------------------------------------------------------------- - -We always store the Slate editor state in its Value form. - -The schema for the Value is the same whether the editor is in MD or rich text mode, and is currently (rather arbitrarily) -dictated by the schema expected by slate-md-serializer, simply because it was the only bit of the pipeline which -has opinions on the schema. (slate-html-serializer lets you define how to serialize whatever schema you like). - -The BLOCK_TAGS and MARK_TAGS give the mapping from HTML tags to the schema's node types (for blocks, which describe -block content like divs, and marks, which describe inline formatted sections like spans). - -We use

    as the parent tag for the message (XXX: although some tags are technically not allowed to be nested within p's) - -Various conversions are performed as content is moved between HTML, MD, and plaintext representations of HTML and MD. - -The primitives used are: - - * Markdown.js - models commonmark-formatted MD strings (as entered by the composer in MD mode) - * toHtml() - renders them to HTML suitable for sending on the wire - * isPlainText() - checks whether the parsed MD contains anything other than simple text. - * toPlainText() - renders MD to plain text in order to remove backslashes. Only works if the MD is already plaintext (otherwise it just emits HTML) - - * slate-html-serializer - * converts Values to HTML (serialising) using our schema rules - * converts HTML to Values (deserialising) using our schema rules - - * slate-md-serializer - * converts rich Values to MD strings (serialising) but using a non-commonmark generic MD dialect. - * This should use commonmark, but we use the serializer here for expedience rather than writing a commonmark one. - - * slate-plain-serializer - * converts Values to plain text strings (serialising them) by concatenating the strings together - * converts Values from plain text strings (deserialiasing them). - * Used to initialise the editor by deserializing "" into a Value. Apparently this is the idiomatic way to initialise a blank editor. - * Used (as a bodge) to turn a rich text editor into a MD editor, when deserialising the converted MD string of the editor into a value - - * PlainWithPillsSerializer - * A fork of slate-plain-serializer which is aware of Pills (hence the name) and Emoji. - * It can be configured to output Pills as: - * "plain": Pills are rendered via their 'completion' text - e.g. 'Matthew'; used for sending messages) - * "md": Pills are rendered as MD, e.g. [Matthew](https://matrix.to/#/@matthew:matrix.org) ) - * "id": Pills are rendered as IDs, e.g. '@matthew:matrix.org' (used for authoring / commands) - * Emoji nodes are converted to inline utf8 emoji. - -The actual conversion transitions are: - - * Quoting: - * The message being quoted is taken as HTML - * ...and deserialised into a Value - * ...and then serialised into MD via slate-md-serializer if the editor is in MD mode - - * Roundtripping between MD and rich text editor mode - * From MD to richtext (mdToRichEditorState): - * Serialise the MD-format Value to a MD string (converting pills to MD) with PlainWithPillsSerializer in 'md' mode - * Convert that MD string to HTML via Markdown.js - * Deserialise that Value to HTML via slate-html-serializer - * From richtext to MD (richToMdEditorState): - * Serialise the richtext-format Value to a MD string with slate-md-serializer (XXX: this should use commonmark) - * Deserialise that to a plain text value via slate-plain-serializer - - * Loading history in one format into an editor which is in the other format - * Uses the same functions as for roundtripping - - * Scanning the editor for a slash command - * If the editor is a single line node starting with /, then serialize it to a string with PlainWithPillsSerializer in 'id' mode - So that pills get converted to IDs suitable for commands being passed around - - * Sending messages - * In RT mode: - * If there is rich content, serialize the RT-format Value to HTML body via slate-html-serializer - * Serialize the RT-format Value to the plain text fallback via PlainWithPillsSerializer in 'plain' mode - * In MD mode: - * Serialize the MD-format Value into an MD string with PlainWithPillsSerializer in 'md' mode - * Parse the string with Markdown.js - * If it contains no formatting: - * Send as plaintext (as taken from Markdown.toPlainText()) - * Otherwise - * Send as HTML (as taken from Markdown.toHtml()) - * Serialize the RT-format Value to the plain text fallback via PlainWithPillsSerializer in 'plain' mode - - * Pasting HTML - * Deserialize HTML to a RT Value via slate-html-serializer - * In RT mode, insert it straight into the editor as a fragment - * In MD mode, serialise it to an MD string via slate-md-serializer and then insert the string into the editor as a fragment. - -The various scenarios and transitions could be drawn into a pretty diagram if one felt the urge, but hopefully the above -gives sufficient detail on how it's all meant to work. \ No newline at end of file diff --git a/package.json b/package.json index 957982c474d..c62184810c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.41.1", + "version": "3.43.0", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -22,10 +22,7 @@ "README.md", "package.json" ], - "bin": { - "reskindex": "scripts/reskindex.js" - }, - "main": "./src/index.ts", + "main": "./lib/index.ts", "matrix_src_main": "./src/index.ts", "matrix_lib_main": "./lib/index.ts", "matrix_lib_typings": "./lib/index.d.ts", @@ -37,23 +34,23 @@ "i18n": "matrix-gen-i18n", "prunei18n": "matrix-prune-i18n", "diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && matrix-gen-i18n && matrix-compare-i18n-files src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json", - "reskindex": "node scripts/reskindex.js -h header", "make-component": "node scripts/make-react-component.js", - "reskindex:watch": "node scripts/reskindex.js -h header -w", "rethemendex": "res/css/rethemendex.sh", "clean": "rimraf lib", "build": "yarn clean && git rev-parse HEAD > git-revision.txt && yarn build:compile && yarn build:types", - "build:compile": "yarn reskindex && babel -d lib --verbose --extensions \".ts,.js,.tsx\" src", + "build:compile": "babel -d lib --verbose --extensions \".ts,.js,.tsx\" src", "build:types": "tsc --emitDeclarationOnly --jsx react", "start": "echo THIS IS FOR LEGACY PURPOSES ONLY. && yarn start:all", - "start:all": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n build,reskindex \"yarn start:build\" \"yarn reskindex:watch\"", + "start:all": "echo THIS IS FOR LEGACY PURPOSES ONLY. && yarn start:build", "start:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"", "lint": "yarn lint:types && yarn lint:js && yarn lint:style", - "lint:js": "eslint --max-warnings 0 src test", - "lint:js-fix": "eslint --fix src test", - "lint:types": "tsc --noEmit --jsx react", - "lint:style": "stylelint 'res/css/**/*.scss'", + "lint:js": "eslint --max-warnings 0 src test cypress", + "lint:js-fix": "eslint --fix src test cypress", + "lint:types": "tsc --noEmit --jsx react && tsc --noEmit -p cypress", + "lint:style": "stylelint \"res/css/**/*.scss\"", "test": "jest", + "test:cypress": "cypress run", + "test:cypress:open": "cypress open", "test:e2e": "./test/end-to-end-tests/run.sh --app-url http://localhost:8080", "coverage": "yarn test --coverage" }, @@ -64,7 +61,6 @@ "@types/geojson": "^7946.0.8", "await-lock": "^2.1.0", "blurhash": "^1.1.3", - "browser-encrypt-attachment": "^0.3.0", "browser-request": "^0.3.3", "cheerio": "^1.0.0-rc.9", "classnames": "^2.2.6", @@ -72,8 +68,9 @@ "counterpart": "^0.18.6", "diff-dom": "^4.2.2", "diff-match-patch": "^1.0.5", - "emojibase-data": "^6.2.0", - "emojibase-regex": "^5.1.3", + "emojibase": "6.0.2", + "emojibase-data": "7.0.0", + "emojibase-regex": "6.0.0", "escape-html": "^1.0.3", "file-saver": "^2.0.5", "filesize": "6.1.0", @@ -91,7 +88,8 @@ "linkifyjs": "^4.0.0-beta.4", "lodash": "^4.17.20", "maplibre-gl": "^1.15.2", - "matrix-analytics-events": "github:matrix-org/matrix-analytics-events.git#daad3faed54f0b1f1e026a7498b4653e4d01cd90", + "matrix-analytics-events": "github:matrix-org/matrix-analytics-events.git#4aef17b56798639906f26a8739043a3c5c5fde7e", + "matrix-encrypt-attachment": "^1.0.3", "matrix-events-sdk": "^0.0.1-beta.7", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-widget-api": "^0.1.0-beta.18", @@ -124,7 +122,6 @@ "@babel/eslint-plugin": "^7.12.10", "@babel/parser": "^7.12.11", "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "^7.12.12", "@babel/plugin-proposal-export-default-from": "^7.12.1", "@babel/plugin-proposal-numeric-separator": "^7.12.7", "@babel/plugin-proposal-object-rest-spread": "^7.12.1", @@ -137,15 +134,17 @@ "@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz", "@peculiar/webcrypto": "^1.1.4", "@sentry/types": "^6.10.0", - "@sinonjs/fake-timers": "^7.0.2", + "@sinonjs/fake-timers": "^9.1.2", "@types/classnames": "^2.2.11", "@types/commonmark": "^0.27.4", "@types/counterpart": "^0.18.1", "@types/css-font-loading-module": "^0.0.6", "@types/diff-match-patch": "^1.0.32", "@types/enzyme": "^3.10.9", + "@types/escape-html": "^1.0.1", "@types/file-saver": "^2.0.3", "@types/flux": "^3.1.9", + "@types/fs-extra": "^9.0.13", "@types/jest": "^26.0.20", "@types/lodash": "^4.14.168", "@types/modernizr": "^3.5.3", @@ -156,6 +155,7 @@ "@types/react": "17.0.14", "@types/react-beautiful-dnd": "^13.0.0", "@types/react-dom": "17.0.9", + "@types/react-test-renderer": "^17.0.1", "@types/react-transition-group": "^4.4.0", "@types/sanitize-html": "^2.3.1", "@types/zxcvbn": "^4.4.0", @@ -164,8 +164,9 @@ "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1", "allchange": "^1.0.6", "babel-jest": "^26.6.3", + "blob-polyfill": "^6.0.20211015", "chokidar": "^3.5.1", - "concurrently": "^5.3.0", + "cypress": "^9.5.4", "enzyme": "^3.11.0", "enzyme-to-json": "^3.6.2", "eslint": "8.9.0", @@ -175,6 +176,7 @@ "eslint-plugin-matrix-org": "^0.4.0", "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", + "fs-extra": "^10.0.1", "glob": "^7.1.6", "jest": "^27.4.0", "jest-canvas-mock": "^2.3.0", @@ -231,7 +233,9 @@ "/src/**/*.{js,ts,tsx}" ], "coverageReporters": [ - "text" + "text", + "json" ] - } + }, + "typings": "./lib/index.d.ts" } diff --git a/res/css/_common.scss b/res/css/_common.scss index a4b470d0527..94ec5ea0115 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -254,7 +254,7 @@ legend { } // These are magic constants which are excluded from tinting, to let themes -// (which only have CSS, unlike skins) tell the app what their non-tinted +// (which only have CSS) tell the app what their non-tinted // colourscheme is by inspecting the stylesheet DOM. // // They are not used for layout!! @@ -294,7 +294,6 @@ legend { background-color: $background; color: $light-fg-color; z-index: 4012; - font-weight: 300; font-size: $font-15px; position: relative; padding: 24px; @@ -670,3 +669,54 @@ legend { line-height: inherit; cursor: pointer; } + +@define-mixin CallButton { + box-sizing: border-box; + font-weight: 600; + height: $font-24px; + line-height: $font-24px; + margin-right: 0; + + span { + display: flex; + align-items: center; + + &::before { + content: ''; + display: inline-block; + background-color: $button-fg-color; + mask-position: center; + mask-repeat: no-repeat; + margin-right: 8px; + } + } +} + +@define-mixin ThreadsAmount { + $threadInfoLineHeight: calc(2 * $font-12px); + + color: $secondary-content; + font-weight: $font-semi-bold; + line-height: $threadInfoLineHeight; + white-space: nowrap; + position: relative; + padding: 0 $spacing-12 0 $spacing-8; +} + +@define-mixin ThreadInfoIcon { + content: ""; + display: inline-block; + mask-image: url('$(res)/img/element-icons/thread-summary.svg'); + mask-position: center; + height: 18px; + min-width: 18px; + background-color: $secondary-content !important; + mask-repeat: no-repeat; + mask-size: contain; +} + +@define-mixin ListResetDefault { + list-style: none; + padding: 0; + margin: 0; +} diff --git a/res/css/_components.scss b/res/css/_components.scss index 65ce8742b87..3f371478d12 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -4,28 +4,38 @@ @import "./_font-sizes.scss"; @import "./_font-weights.scss"; @import "./_spacing.scss"; +@import "./components/views/beacon/_BeaconListItem.scss"; +@import "./components/views/beacon/_BeaconStatus.scss"; +@import "./components/views/beacon/_BeaconViewDialog.scss"; +@import "./components/views/beacon/_DialogOwnBeaconStatus.scss"; +@import "./components/views/beacon/_DialogSidebar.scss"; +@import "./components/views/beacon/_LeftPanelLiveShareWarning.scss"; +@import "./components/views/beacon/_LiveTimeRemaining.scss"; +@import "./components/views/beacon/_OwnBeaconStatus.scss"; +@import "./components/views/beacon/_RoomLiveShareWarning.scss"; +@import "./components/views/beacon/_StyledLiveBeaconIcon.scss"; +@import "./components/views/location/_EnableLiveShare.scss"; +@import "./components/views/location/_LiveDurationDropdown.scss"; @import "./components/views/location/_LocationShareMenu.scss"; +@import "./components/views/location/_MapError.scss"; +@import "./components/views/location/_Marker.scss"; @import "./components/views/location/_ShareDialogButtons.scss"; @import "./components/views/location/_ShareType.scss"; +@import "./components/views/location/_ZoomButtons.scss"; +@import "./components/views/messages/_MBeaconBody.scss"; @import "./components/views/spaces/_QuickThemeSwitcher.scss"; @import "./structures/_AutoHideScrollbar.scss"; @import "./structures/_BackdropPanel.scss"; @import "./structures/_CompatibilityPage.scss"; @import "./structures/_ContextualMenu.scss"; -@import "./structures/_CreateRoom.scss"; -@import "./structures/_CustomRoomTagPanel.scss"; @import "./structures/_FileDropTarget.scss"; @import "./structures/_FilePanel.scss"; @import "./structures/_GenericErrorPage.scss"; -@import "./structures/_GroupFilterPanel.scss"; -@import "./structures/_GroupView.scss"; @import "./structures/_HeaderButtons.scss"; @import "./structures/_HomePage.scss"; @import "./structures/_LeftPanel.scss"; -@import "./structures/_LeftPanelWidget.scss"; @import "./structures/_MainSplit.scss"; @import "./structures/_MatrixChat.scss"; -@import "./structures/_MyGroups.scss"; @import "./structures/_NonUrgentToastContainer.scss"; @import "./structures/_NotificationPanel.scss"; @import "./structures/_QuickSettingsButton.scss"; @@ -43,6 +53,7 @@ @import "./structures/_ToastContainer.scss"; @import "./structures/_UploadBar.scss"; @import "./structures/_UserMenu.scss"; +@import "./structures/_VideoRoomView.scss"; @import "./structures/_ViewSource.scss"; @import "./structures/auth/_CompleteSecurity.scss"; @import "./structures/auth/_Login.scss"; @@ -71,31 +82,24 @@ @import "./views/context_menus/_CallContextMenu.scss"; @import "./views/context_menus/_IconizedContextMenu.scss"; @import "./views/context_menus/_MessageContextMenu.scss"; -@import "./views/context_menus/_TagTileContextMenu.scss"; @import "./views/dialogs/_AddExistingToSpaceDialog.scss"; -@import "./views/dialogs/_AddressPickerDialog.scss"; @import "./views/dialogs/_Analytics.scss"; @import "./views/dialogs/_AnalyticsLearnMoreDialog.scss"; @import "./views/dialogs/_BugReportDialog.scss"; +@import "./views/dialogs/_BulkRedactDialog.scss"; @import "./views/dialogs/_ChangelogDialog.scss"; @import "./views/dialogs/_ChatCreateOrReuseChatDialog.scss"; -@import "./views/dialogs/_CommunityPrototypeInviteDialog.scss"; @import "./views/dialogs/_CompoundDialog.scss"; @import "./views/dialogs/_ConfirmSpaceUserActionDialog.scss"; @import "./views/dialogs/_ConfirmUserActionDialog.scss"; -@import "./views/dialogs/_CreateCommunityPrototypeDialog.scss"; -@import "./views/dialogs/_CreateGroupDialog.scss"; @import "./views/dialogs/_CreateRoomDialog.scss"; -@import "./views/dialogs/_CreateSpaceFromCommunityDialog.scss"; @import "./views/dialogs/_CreateSubspaceDialog.scss"; @import "./views/dialogs/_DeactivateAccountDialog.scss"; @import "./views/dialogs/_DevtoolsDialog.scss"; -@import "./views/dialogs/_EditCommunityPrototypeDialog.scss"; @import "./views/dialogs/_ExportDialog.scss"; @import "./views/dialogs/_FeedbackDialog.scss"; @import "./views/dialogs/_ForwardDialog.scss"; @import "./views/dialogs/_GenericFeatureFeedbackDialog.scss"; -@import "./views/dialogs/_GroupAddressPicker.scss"; @import "./views/dialogs/_HostSignupDialog.scss"; @import "./views/dialogs/_IncomingSasDialog.scss"; @import "./views/dialogs/_InviteDialog.scss"; @@ -181,13 +185,11 @@ @import "./views/elements/_TooltipButton.scss"; @import "./views/elements/_Validation.scss"; @import "./views/emojipicker/_EmojiPicker.scss"; -@import "./views/groups/_GroupPublicityToggle.scss"; -@import "./views/groups/_GroupRoomList.scss"; -@import "./views/groups/_GroupUserSettings.scss"; @import "./views/location/_LocationPicker.scss"; @import "./views/messages/_CallEvent.scss"; @import "./views/messages/_CreateEvent.scss"; @import "./views/messages/_DateSeparator.scss"; +@import "./views/messages/_DisambiguatedProfile.scss"; @import "./views/messages/_EventTileBubble.scss"; @import "./views/messages/_HiddenBody.scss"; @import "./views/messages/_JumpToDatePicker.scss"; @@ -210,7 +212,6 @@ @import "./views/messages/_ReactionsRowButton.scss"; @import "./views/messages/_RedactedBody.scss"; @import "./views/messages/_RoomAvatarEvent.scss"; -@import "./views/messages/_SenderProfile.scss"; @import "./views/messages/_TextualEvent.scss"; @import "./views/messages/_UnknownBody.scss"; @import "./views/messages/_ViewSourceEvent.scss"; @@ -248,6 +249,7 @@ @import "./views/rooms/_NotificationBadge.scss"; @import "./views/rooms/_PinnedEventTile.scss"; @import "./views/rooms/_PresenceLabel.scss"; +@import "./views/rooms/_ReadReceiptGroup.scss"; @import "./views/rooms/_RecentlyViewedButton.scss"; @import "./views/rooms/_ReplyPreview.scss"; @import "./views/rooms/_ReplyTile.scss"; @@ -262,6 +264,7 @@ @import "./views/rooms/_SearchBar.scss"; @import "./views/rooms/_SendMessageComposer.scss"; @import "./views/rooms/_Stickers.scss"; +@import "./views/rooms/_ThreadSummary.scss"; @import "./views/rooms/_TopUnreadMessagesBar.scss"; @import "./views/rooms/_VoiceRecordComposerTile.scss"; @import "./views/rooms/_WhoIsTypingTile.scss"; @@ -275,6 +278,7 @@ @import "./views/settings/_ImageSizePanel.scss"; @import "./views/settings/_IntegrationManager.scss"; @import "./views/settings/_JoinRuleSettings.scss"; +@import "./views/settings/_KeyboardShortcut.scss"; @import "./views/settings/_LayoutSwitcher.scss"; @import "./views/settings/_Notifications.scss"; @import "./views/settings/_PhoneNumbers.scss"; @@ -323,3 +327,4 @@ @import "./views/voip/_DialPadModal.scss"; @import "./views/voip/_PiPContainer.scss"; @import "./views/voip/_VideoFeed.scss"; +@import "./views/voip/_VideoLobby.scss"; diff --git a/res/css/components/views/beacon/_BeaconListItem.scss b/res/css/components/views/beacon/_BeaconListItem.scss new file mode 100644 index 00000000000..60311a4466f --- /dev/null +++ b/res/css/components/views/beacon/_BeaconListItem.scss @@ -0,0 +1,61 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_BeaconListItem { + box-sizing: border-box; + display: flex; + flex-direction: row; + align-items: flex-start; + padding: $spacing-12 0; + + border-bottom: 1px solid $system; +} + +.mx_BeaconListItem_avatarIcon { + flex: 0 0; + height: 32px; + width: 32px; +} + +.mx_BeaconListItem_avatar { + flex: 0 0; + box-sizing: border-box; + + margin-right: $spacing-8; + border: 2px solid $location-live-color; +} + +.mx_BeaconListItem_info { + flex: 1 1 0; + display: flex; + flex-direction: column; + align-items: stretch; +} + +.mx_BeaconListItem_status { + // override beacon status padding + padding: 0 !important; + margin-bottom: $spacing-8; + + .mx_BeaconStatus_label { + font-weight: $font-semi-bold; + } +} + +.mx_BeaconListItem_lastUpdated { + color: $tertiary-content; + font-size: $font-10px; +} diff --git a/res/css/components/views/beacon/_BeaconStatus.scss b/res/css/components/views/beacon/_BeaconStatus.scss new file mode 100644 index 00000000000..4dd3d325475 --- /dev/null +++ b/res/css/components/views/beacon/_BeaconStatus.scss @@ -0,0 +1,65 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_BeaconStatus { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + + box-sizing: border-box; + padding: $spacing-8; + + color: var(--color); + font-size: $font-12px; +} + +.mx_BeaconStatus_Loading, +.mx_BeaconStatus_Stopped { + --color: $tertiary-content; +} + +.mx_BeaconStatus_Active, +.mx_BeaconStatus_Error { + --color: $primary-content; +} + +.mx_BeaconStatus_icon { + height: 32px; + width: 32px; + + flex: 0 0 32px; + margin-right: $spacing-8; +} + +.mx_BeaconStatus_description { + flex: 1; + display: flex; + flex-direction: column; + line-height: $font-14px; + + padding-right: $spacing-8; + + // TODO handle text-overflow +} + +.mx_BeaconStatus_expiryTime { + color: $secondary-content; +} + +.mx_BeaconStatus_label { + margin-bottom: 2px; +} diff --git a/res/css/components/views/beacon/_BeaconViewDialog.scss b/res/css/components/views/beacon/_BeaconViewDialog.scss new file mode 100644 index 00000000000..6ad1a2a6139 --- /dev/null +++ b/res/css/components/views/beacon/_BeaconViewDialog.scss @@ -0,0 +1,88 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_BeaconViewDialog_wrapper .mx_Dialog { + padding: 0px; + + /* Unset contain and position to allow the close button + to appear outside the dialog */ + contain: unset; + position: unset; +} + +.mx_BeaconViewDialog { + /* subtract 0.5px to prevent single-pixel margin due to rounding */ + width: calc(80vw - 0.5px); + height: calc(80vh - 0.5px); + overflow: hidden; + + // sidebar is absolutely positioned inside + position: relative; + + .mx_Dialog_header { + margin: 0px; + padding: 0px; + position: unset; + + .mx_Dialog_title { + display: none; + } + + .mx_Dialog_cancelButton { + z-index: 4010; + position: fixed; + right: 5vw; + top: 5vh; + width: 20px; + height: 20px; + background-color: $dialog-close-external-color; + } + } +} + +.mx_BeaconViewDialog_map { + width: 80vw; + height: 80vh; + border-radius: 8px; +} + +.mx_BeaconViewDialog_mapFallback { + box-sizing: border-box; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + background: url('$(res)/img/location/map.svg'); + background-size: cover; +} + +.mx_BeaconViewDialog_mapFallbackIcon { + width: 65px; + margin-bottom: $spacing-16; + color: $quaternary-content; +} + +.mx_BeaconViewDialog_mapFallbackMessage { + color: $secondary-content; + margin-bottom: $spacing-16; +} + +.mx_BeaconViewDialog_viewListButton { + position: absolute; + top: $spacing-24; + left: $spacing-24; +} diff --git a/res/css/components/views/beacon/_DialogOwnBeaconStatus.scss b/res/css/components/views/beacon/_DialogOwnBeaconStatus.scss new file mode 100644 index 00000000000..791e276f050 --- /dev/null +++ b/res/css/components/views/beacon/_DialogOwnBeaconStatus.scss @@ -0,0 +1,55 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_DialogOwnBeaconStatus { + position: absolute; + bottom: $spacing-32; + width: 300px; + margin-left: -150px; + left: 50%; + + box-sizing: border-box; + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: stretch; + + background: $background; + border-radius: 8px; + box-shadow: 4px 4px 12px 0 $menu-box-shadow-color; + + padding: 0 $spacing-12; +} + +.mx_DialogOwnBeaconStatus_avatarIcon { + flex: 0 0; + height: 32px; + width: 32px; + margin: $spacing-8 0 $spacing-8 0; +} + +.mx_DialogOwnBeaconStatus_avatar { + flex: 0 0; + box-sizing: border-box; + + border: 2px solid $location-live-color; + margin: $spacing-8 0 $spacing-8 0; +} + +.mx_DialogOwnBeaconStatus_status { + flex: 1 1; + padding-right: 0; +} diff --git a/res/css/components/views/beacon/_DialogSidebar.scss b/res/css/components/views/beacon/_DialogSidebar.scss new file mode 100644 index 00000000000..1989b57c301 --- /dev/null +++ b/res/css/components/views/beacon/_DialogSidebar.scss @@ -0,0 +1,60 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_DialogSidebar { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 265px; + + display: flex; + flex-direction: column; + + box-sizing: border-box; + padding: $spacing-16; + + background-color: $background; + box-shadow: 0px 4px 4px $menu-box-shadow-color; +} + +.mx_DialogSidebar_header { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + + flex: 0 0; + margin-bottom: $spacing-16; + + color: $primary-content; +} + +.mx_DialogSidebar_closeButton { + @mixin ButtonResetDefault; +} + +.mx_DialogSidebar_closeButtonIcon { + color: $tertiary-content; + height: 12px; +} + +.mx_DialogSidebar_list { + @mixin ListResetDefault; + flex: 1 1 0; + width: 100%; + overflow: auto; +} diff --git a/res/css/components/views/beacon/_LeftPanelLiveShareWarning.scss b/res/css/components/views/beacon/_LeftPanelLiveShareWarning.scss new file mode 100644 index 00000000000..04645c965ed --- /dev/null +++ b/res/css/components/views/beacon/_LeftPanelLiveShareWarning.scss @@ -0,0 +1,36 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_LeftPanelLiveShareWarning { + @mixin ButtonResetDefault; + width: 100%; + box-sizing: border-box; + + padding: $spacing-4; + text-align: center; + + background-color: $accent; + color: #fff; + font-size: $font-10px; + + // panel backdrops overlay the whole sidepanel + // go above to get hover for title + z-index: 1; +} + +.mx_LeftPanelLiveShareWarning__error { + background-color: $alert; +} diff --git a/res/css/views/groups/_GroupUserSettings.scss b/res/css/components/views/beacon/_LiveTimeRemaining.scss similarity index 73% rename from res/css/views/groups/_GroupUserSettings.scss rename to res/css/components/views/beacon/_LiveTimeRemaining.scss index b207aa29585..de13f7aab2e 100644 --- a/res/css/views/groups/_GroupUserSettings.scss +++ b/res/css/components/views/beacon/_LiveTimeRemaining.scss @@ -1,5 +1,5 @@ /* -Copyright 2017 New Vector Ltd +Copyright 2022 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,9 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_GroupUserSettings_groupPublicity_scrollbox { - height: 200px; - border: 1px solid $primary-hairline-color; - border-radius: 3px; - overflow: hidden; +.mx_LiveTimeRemaining { + color: $secondary-content; + font-size: $font-12px; } diff --git a/res/css/components/views/beacon/_OwnBeaconStatus.scss b/res/css/components/views/beacon/_OwnBeaconStatus.scss new file mode 100644 index 00000000000..aa01b6269a4 --- /dev/null +++ b/res/css/components/views/beacon/_OwnBeaconStatus.scss @@ -0,0 +1,27 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_EventTile[data-layout="bubble"] .mx_OwnBeaconStatus_button { + // align to top to make room for timestamp + // in bubble view + align-self: start; +} + +.mx_OwnBeaconStatus_destructiveButton { + // override button link_inline styles + color: $alert !important; + font-weight: $font-semi-bold !important; +} diff --git a/res/css/components/views/beacon/_RoomLiveShareWarning.scss b/res/css/components/views/beacon/_RoomLiveShareWarning.scss new file mode 100644 index 00000000000..f82c7f4de40 --- /dev/null +++ b/res/css/components/views/beacon/_RoomLiveShareWarning.scss @@ -0,0 +1,58 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_RoomLiveShareWarning { + width: 100%; + + display: flex; + flex-direction: row; + align-items: center; + + box-sizing: border-box; + padding: $spacing-12 $spacing-16; + + color: $primary-content; + background-color: $system; +} + +.mx_RoomLiveShareWarning_icon { + height: 32px; + width: 32px; + margin-right: $spacing-8; +} + +.mx_RoomLiveShareWarning_label { + flex: 1; + font-size: $font-15px; +} + +.mx_RoomLiveShareWarning_spinner { + margin-right: $spacing-16; +} + +.mx_RoomLiveShareWarning_closeButton { + @mixin ButtonResetDefault; + margin-left: $spacing-16; +} + +.mx_RoomLiveShareWarning_stopButton { + margin-left: $spacing-16; +} + +.mx_RoomLiveShareWarning_closeButtonIcon { + height: $font-18px; + padding: $spacing-4; +} diff --git a/res/css/components/views/beacon/_StyledLiveBeaconIcon.scss b/res/css/components/views/beacon/_StyledLiveBeaconIcon.scss new file mode 100644 index 00000000000..9096c3c71f4 --- /dev/null +++ b/res/css/components/views/beacon/_StyledLiveBeaconIcon.scss @@ -0,0 +1,40 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_StyledLiveBeaconIcon { + flex-grow: 0; + flex-shrink: 0; + box-sizing: border-box; + border-width: 2px; + border-style: solid; + border-radius: 50%; + + background-color: $location-live-color; + border-color: $location-live-secondary-color; + padding: 2px; + // colors icon + color: white; +} + +.mx_StyledLiveBeaconIcon.mx_StyledLiveBeaconIcon_error { + background-color: $alert; + border-color: $alert; +} + +.mx_StyledLiveBeaconIcon.mx_StyledLiveBeaconIcon_idle { + background-color: $quaternary-content; + border-color: $quaternary-content; +} diff --git a/res/css/components/views/location/_EnableLiveShare.scss b/res/css/components/views/location/_EnableLiveShare.scss new file mode 100644 index 00000000000..7c10cc1923f --- /dev/null +++ b/res/css/components/views/location/_EnableLiveShare.scss @@ -0,0 +1,48 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_EnableLiveShare { + flex: 1 1 0; + display: flex; + flex-direction: column; + justify-content: flex-end; + align-items: center; + + padding: $spacing-32 $spacing-16; + text-align: center; + box-sizing: border-box; +} + +.mx_EnableLiveShare_heading { + padding-top: $spacing-24; +} + +.mx_EnableLiveShare_icon { + height: 58px; + width: 58px; +} + +.mx_EnableLiveShare_description { + padding: 0 $spacing-24; + margin-bottom: $spacing-32; + line-height: $font-20px; +} + +.mx_EnableLiveShare_button { + margin-top: $spacing-32; + height: 48px; + width: 100%; +} diff --git a/res/css/views/dialogs/_GroupAddressPicker.scss b/res/css/components/views/location/_LiveDurationDropdown.scss similarity index 82% rename from res/css/views/dialogs/_GroupAddressPicker.scss rename to res/css/components/views/location/_LiveDurationDropdown.scss index 5fa18931f0a..9b0e39a07c6 100644 --- a/res/css/views/dialogs/_GroupAddressPicker.scss +++ b/res/css/components/views/location/_LiveDurationDropdown.scss @@ -1,5 +1,5 @@ /* -Copyright 2017 New Vector Ltd +Copyright 2022 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_GroupAddressPicker_checkboxContainer { - margin-top: 10px; - display: flex; +.mx_LiveDurationDropdown { + margin-bottom: $spacing-16; } diff --git a/res/css/components/views/location/_MapError.scss b/res/css/components/views/location/_MapError.scss new file mode 100644 index 00000000000..83d6316ec44 --- /dev/null +++ b/res/css/components/views/location/_MapError.scss @@ -0,0 +1,36 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_MapError { + padding: 100px $spacing-32 0; + text-align: center; + + p { + margin: $spacing-16 0 $spacing-32; + } +} + +.mx_MapError_heading { + padding-top: $spacing-24; +} + +.mx_MapError_icon { + height: 58px; + + path { + fill: $secondary-content; + } +} diff --git a/res/css/components/views/location/_Marker.scss b/res/css/components/views/location/_Marker.scss new file mode 100644 index 00000000000..7a1baccf9f1 --- /dev/null +++ b/res/css/components/views/location/_Marker.scss @@ -0,0 +1,46 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_Marker_defaultColor { + color: $accent; +} + +.mx_Marker_border { + width: 42px; + height: 42px; + border-radius: 50%; + filter: drop-shadow(0px 3px 5px rgba(0, 0, 0, 0.2)); + background-color: currentColor; + + display: flex; + justify-content: center; + align-items: center; + + // caret down + &::before { + content: ''; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid currentColor; + position: absolute; + bottom: -4px; + } +} + +.mx_Marker_icon { + color: white; + height: 20px; +} diff --git a/res/css/components/views/location/_ShareType.scss b/res/css/components/views/location/_ShareType.scss index ba21a7caa0d..458be106eb0 100644 --- a/res/css/components/views/location/_ShareType.scss +++ b/res/css/components/views/location/_ShareType.scss @@ -83,19 +83,10 @@ limitations under the License. border-style: solid; border-radius: 50%; - &.Own { - // color is set by user color class - // generated from id - border-color: currentColor; - } + // Live is styled by StyledLiveBeaconIcon - &.Live { - background-color: $location-live-color; - // 20% brightness $location-live-color - border-color: #deddfd; - padding: 2px; - // colors icon - color: white; + &.Own { + border-color: $accent; } &.Pin { diff --git a/res/css/components/views/location/_ZoomButtons.scss b/res/css/components/views/location/_ZoomButtons.scss new file mode 100644 index 00000000000..59d52477f97 --- /dev/null +++ b/res/css/components/views/location/_ZoomButtons.scss @@ -0,0 +1,45 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_ZoomButtons { + position: absolute; + bottom: $spacing-32; + right: $spacing-24; +} + +.mx_ZoomButtons_button { + @mixin ButtonResetDefault; + + margin-top: $spacing-8; + border-radius: 4px; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + + height: 24px; + width: 24px; + + background: $background; + box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.25); +} + +.mx_ZoomButtons_icon { + height: 10px; + width: 10px; + + color: $primary-content; +} diff --git a/res/css/components/views/messages/_MBeaconBody.scss b/res/css/components/views/messages/_MBeaconBody.scss new file mode 100644 index 00000000000..dc63d6676db --- /dev/null +++ b/res/css/components/views/messages/_MBeaconBody.scss @@ -0,0 +1,65 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_MBeaconBody { + position: relative; + height: 220px; + width: 325px; + + border-radius: $timeline-image-border-radius; + overflow: hidden; +} + +.mx_MBeaconBody_map { + height: 100%; + width: 100%; + z-index: 0; // keeps the entire map under the message action bar + + &:not(.mx_MBeaconBody_mapFallback) { + cursor: pointer; + } +} + +.mx_MBeaconBody_mapFallback { + box-sizing: border-box; + display: flex; + justify-content: center; + align-items: center; + + // pushes spinner/icon up + // to appear more centered with the footer + padding-bottom: 50px; + + background: url('$(res)/img/location/map.svg'); + background-size: cover; +} + +.mx_MBeaconBody_mapFallbackIcon { + width: 65px; + color: $quaternary-content; +} + +.mx_MBeaconBody_chin { + position: absolute; + bottom: 0; + width: 100%; + background-color: $overlay-background; +} + +.mx_EventTile[data-layout="bubble"] .mx_EventTile_line .mx_MBeaconBody { + max-width: 100%; + width: 450px; +} diff --git a/res/css/structures/_CustomRoomTagPanel.scss b/res/css/structures/_CustomRoomTagPanel.scss deleted file mode 100644 index 627644f1020..00000000000 --- a/res/css/structures/_CustomRoomTagPanel.scss +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2019 New Vector Ltd. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// TODO: Update design for custom tags to match new designs - -.mx_CustomRoomTagPanel { - background-color: $groupFilterPanel-bg-color; - max-height: 40vh; -} - -.mx_CustomRoomTagPanel_scroller { - max-height: inherit; - display: flex; - flex-direction: column; - align-items: center; -} - -.mx_CustomRoomTagPanel .mx_AccessibleButton { - margin: 0 auto; - width: 40px; - padding: 10px 0 9px 0; - position: relative; -} - -.mx_CustomRoomTagPanel .mx_BaseAvatar_image { - box-sizing: border-box; - width: 40px; - height: 40px; -} - -.mx_CustomRoomTagPanel .mx_AccessibleButton.CustomRoomTagPanel_tileSelected::before { - content: ''; - height: 56px; - background-color: $accent-alt; - width: 5px; - position: absolute; - left: -9px; - border-radius: 0 3px 3px 0; - top: 5px; // just feels right (see comment above about designs needing to be updated) -} diff --git a/res/css/structures/_FilePanel.scss b/res/css/structures/_FilePanel.scss index c180a8a02dd..634ce9604cc 100644 --- a/res/css/structures/_FilePanel.scss +++ b/res/css/structures/_FilePanel.scss @@ -93,7 +93,7 @@ limitations under the License. text-decoration: none; } -.mx_FilePanel .mx_EventTile .mx_SenderProfile { +.mx_FilePanel .mx_EventTile .mx_DisambiguatedProfile { flex: 1 1 auto; line-height: initial; padding: 0px; diff --git a/res/css/structures/_GroupFilterPanel.scss b/res/css/structures/_GroupFilterPanel.scss deleted file mode 100644 index bdbd9f76435..00000000000 --- a/res/css/structures/_GroupFilterPanel.scss +++ /dev/null @@ -1,207 +0,0 @@ -/* -Copyright 2017 New Vector Ltd. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -$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; - position: relative; - - display: flex; - flex-direction: column; - align-items: center; - justify-content: space-between; - min-height: 0; -} - -.mx_GroupFilterPanel_items_selected { - cursor: pointer; -} - -.mx_GroupFilterPanel .mx_GroupFilterPanel_divider { - height: 0px; - width: 90%; - border: none; - border-bottom: 1px solid $tertiary-content; -} - -.mx_GroupFilterPanel .mx_GroupFilterPanel_scroller { - flex-grow: 1; - width: 100%; -} - -.mx_GroupFilterPanel .mx_GroupFilterPanel_tagTileContainer { - display: flex; - flex-direction: column; - align-items: center; - - padding-top: 6px; -} -.mx_GroupFilterPanel .mx_GroupFilterPanel_tagTileContainer > div { - margin: 6px 0; -} - -.mx_GroupFilterPanel .mx_TagTile { - // opacity: 0.5; - position: relative; -} - -.mx_GroupFilterPanel .mx_TagTile.mx_TagTile_prototype { - padding: 3px; -} - -.mx_GroupFilterPanel .mx_TagTile:focus, -.mx_GroupFilterPanel .mx_TagTile:hover, -.mx_GroupFilterPanel .mx_TagTile.mx_TagTile_selected { - // opacity: 1; -} - -.mx_GroupFilterPanel .mx_TagTile.mx_TagTile_selected_prototype { - background-color: $background; - border-radius: 6px; -} - -.mx_TagTile_selected_prototype { - .mx_TagTile_homeIcon::before { - background-color: $primary-content; // dark-on-light - } -} - -.mx_TagTile:not(.mx_TagTile_selected_prototype) .mx_TagTile_homeIcon { - background-color: $roomheader-addroom-bg-color; - border-radius: 48px; - - &::before { - background-color: $roomheader-addroom-fg-color; - } -} - -.mx_TagTile_homeIcon { - width: 32px; - height: 32px; - position: relative; - - &::before { - mask-image: url('$(res)/img/element-icons/home.svg'); - mask-position: center; - mask-repeat: no-repeat; - mask-size: 21px; - content: ''; - display: inline-block; - width: 32px; - height: 32px; - position: absolute; - top: calc(50% - 16px); - left: calc(50% - 16px); - } -} - -.mx_GroupFilterPanel .mx_TagTile_plus { - margin-bottom: 12px; - height: 32px; - width: 32px; - border-radius: 20px; - background-color: $roomheader-addroom-bg-color; - position: relative; - /* overwrite mx_RoleButton inline-block */ - display: block !important; - - &::before { - background-color: $roomheader-addroom-fg-color; - mask-image: url('$(res)/img/feather-customised/plus.svg'); - mask-position: center; - mask-repeat: no-repeat; - content: ''; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - } -} - -.mx_GroupFilterPanel .mx_TagTile.mx_TagTile_selected::before { - content: ''; - height: 100%; - background-color: $accent; - width: 4px; - position: absolute; - left: -12px; - border-radius: 0 3px 3px 0; -} - -.mx_GroupFilterPanel .mx_TagTile.mx_AccessibleButton:focus { - filter: none; -} - -.mx_TagTile_tooltip { - position: relative; - top: -30px; - left: 5px; -} - -.mx_TagTile_context_button { - min-width: 15px; - height: 15px; - position: absolute; - right: -5px; - top: -8px; - border-radius: 8px; - background-color: $neutral-badge-color; - color: #000; - font-weight: 600; - font-size: $font-10px; - text-align: center; - padding-top: 1px; - padding-left: 4px; - padding-right: 4px; -} - -.mx_TagTile_avatar { - position: relative; -} - -.mx_TagTile_badge { - position: absolute; - right: -4px; - top: -2px; - border-radius: 8px; - color: $accent-fg-color; - font-weight: 600; - font-size: $font-14px; - padding: 0 5px; - background-color: $muted-fg-color; -} - -.mx_TagTile_badgeHighlight { - background-color: $alert; -} diff --git a/res/css/structures/_GroupView.scss b/res/css/structures/_GroupView.scss deleted file mode 100644 index 9cbf632cdd0..00000000000 --- a/res/css/structures/_GroupView.scss +++ /dev/null @@ -1,434 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_GroupView { - display: flex; - flex-direction: column; - overflow: hidden; - flex-grow: 1; -} - -.mx_GroupView_error { - margin: auto; -} - -.mx_GroupView_header { - min-height: 52px; - align-items: center; - display: flex; - padding-bottom: 10px; - padding-left: 19px; -} - -.mx_GroupView_header_view { - border-bottom: 1px solid $primary-hairline-color; - padding-bottom: 0px; - padding-right: 8px; -} - -.mx_GroupView_header_avatar, .mx_GroupView_header_info { - display: table-cell; - vertical-align: middle; -} - -.mx_GroupHeader_button { - position: relative; - margin-left: 5px; - margin-right: 5px; - cursor: pointer; - height: 20px; - width: 20px; - - &::before { - content: ''; - position: absolute; - height: 20px; - width: 20px; - background-color: $header-panel-text-primary-color; - mask-repeat: no-repeat; - mask-size: contain; - } -} - -.mx_GroupHeader_editButton::before { - mask-image: url('$(res)/img/element-icons/settings.svg'); -} - -.mx_GroupHeader_shareButton::before { - mask-image: url('$(res)/img/element-icons/room/share.svg'); -} - -.mx_GroupView_hostingSignup img { - margin-left: 5px; -} - -.mx_GroupView_editable { - border-bottom: 1px solid $strong-input-border-color !important; - min-width: 150px; - cursor: text; -} - -.mx_GroupView_editable:focus { - border-bottom: 1px solid $accent !important; - outline: none; - box-shadow: none; -} - -.mx_GroupView_header_isUserMember .mx_GroupView_header_name:hover div:not(.mx_GroupView_editable) { - color: $accent; - cursor: pointer; -} - -.mx_GroupView_avatarPicker { - position: relative; -} - -.mx_GroupView_avatarPicker_edit { - position: absolute; - top: 50px; - left: 15px; -} - -.mx_GroupView_avatarPicker .mx_Spinner { - width: 48px; - height: 48px !important; -} - -.mx_GroupView_header_leftCol { - flex: 1; - - overflow: hidden; -} - -.mx_GroupView_header_rightCol { - display: flex; - align-items: center; -} - -.mx_GroupView_textButton { - display: inline-block; -} - -.mx_GroupView_header_groupid { - font-weight: normal; - font-size: initial; - padding-left: 10px; -} - -.mx_GroupView_header_name { - vertical-align: middle; - width: 100%; - height: 31px; - overflow: hidden; - color: $primary-content; - font-weight: bold; - font-size: $font-22px; - padding-left: 19px; - padding-right: 16px; - /* why isn't text-overflow working? */ - text-overflow: ellipsis; - border-bottom: 1px solid transparent; -} - -.mx_GroupView_header_shortDesc { - vertical-align: bottom; - float: left; - max-height: 42px; - color: $settings-grey-fg-color; - font-weight: 300; - font-size: $font-13px; - padding-left: 19px; - margin-right: 16px; - overflow: hidden; - text-overflow: ellipsis; - border-bottom: 1px solid transparent; -} - -.mx_GroupView_avatarPicker_label { - cursor: pointer; -} - -.mx_GroupView_cancelButton { - padding-left: 8px; -} - -.mx_GroupView_cancelButton img { - position: relative; - top: 5px; -} - -.mx_GroupView input[type='radio'] { - margin: 10px 10px 0px 10px; -} - -.mx_GroupView_label_text { - display: inline-block; - max-width: 80%; - vertical-align: 0.1em; - line-height: 2em; -} - -.mx_GroupView_body { - flex-grow: 1; - margin: 0 24px; -} - -.mx_GroupView_rooms { - flex-grow: 1; - display: flex; - flex-direction: column; - min-height: 200px; - user-select: none; -} - -.mx_GroupView h3 { - text-transform: uppercase; - color: $h3-color; - font-weight: 600; - font-size: $font-13px; - margin-bottom: 10px; -} - -.mx_GroupView_rooms_header .mx_AccessibleButton { - padding-left: 14px; - margin-bottom: 14px; - height: 24px; -} - -.mx_GroupView_group { - border-top: 1px solid $primary-hairline-color; -} - -.mx_GroupView_group_disabled { - opacity: 0.3; - pointer-events: none; -} - -.mx_GroupView_rooms_header_addRow_button { - display: inline-block; -} - -.mx_GroupView_rooms_header_addRow_button object { - pointer-events: none; -} - -.mx_GroupView_rooms_header_addRow_label { - display: inline-block; - vertical-align: top; - line-height: $font-24px; - padding-left: 28px; - color: $accent; -} - -.mx_GroupView_rooms .mx_RoomDetailList { - flex-grow: 1; - border-top: 1px solid $primary-hairline-color; - padding-top: 10px; - word-break: break-word; -} - -.mx_GroupView .mx_RoomView_messageListWrapper { - justify-content: flex-start; -} - -.mx_GroupView_membershipSection { - color: $info-plinth-fg-color; - margin-top: 10px; -} - -.mx_GroupView_membershipSubSection { - justify-content: space-between; - display: flex; - padding-bottom: 8px; -} - -.mx_GroupView_membershipSubSection .mx_Spinner { - justify-content: flex-end; -} - -.mx_GroupView_membershipSection_description { - /* To match textButton */ - line-height: $font-34px; -} - -.mx_GroupView_membershipSection_description .mx_BaseAvatar { - margin-right: 10px; -} - -.mx_GroupView_membershipSection .mx_GroupView_textButton { - margin-right: 0px; - margin-top: 0px; - margin-left: 8px; -} - -.mx_GroupView_memberSettings_toggle label { - cursor: pointer; - user-select: none; -} - -.mx_GroupView_memberSettings input { - margin-right: 6px; -} - -.mx_GroupView_featuredThings { - margin-top: 20px; -} - -.mx_GroupView_featuredThings_header { - font-weight: bold; - font-size: 120%; - margin-bottom: 20px; -} - -.mx_GroupView_featuredThings_category { - font-weight: bold; - font-size: 110%; - margin-top: 10px; -} - -.mx_GroupView_featuredThings_container { - display: flex; -} - -.mx_GroupView_featuredThings_addButton, -.mx_GroupView_featuredThing { - display: table-cell; - text-align: center; - - width: 100px; - margin: 0px 20px; -} - -.mx_GroupView_featuredThing { - position: relative; -} - -.mx_GroupView_featuredThing .mx_GroupView_featuredThing_deleteButton { - position: absolute; - top: -7px; - right: 11px; - opacity: 0.4; -} - -.mx_GroupView_featuredThing .mx_BaseAvatar { - /* To prevent misalignment with img (in addButton) */ - vertical-align: initial; -} - -.mx_GroupView_featuredThings_addButton object { - pointer-events: none; -} - -.mx_GroupView_featuredThing_name { - word-wrap: break-word; -} - -.mx_GroupView_uploadInput { - display: none; -} - -.mx_GroupView_body .mx_AutoHideScrollbar > * { - margin: 11px 50px 50px 68px; -} - -.mx_GroupView_groupDesc textarea { - width: 100%; - max-width: 100%; - height: 150px; -} - -.mx_GroupView_groupDesc_placeholder, -.mx_GroupView_changeDelayWarning { - background-color: $info-plinth-bg-color; - color: $info-plinth-fg-color; - border-radius: 10px; - text-align: center; - - margin: 20px 0px; -} - -.mx_GroupView_groupDesc_placeholder { - padding: 100px 20px; - cursor: pointer; -} - -.mx_GroupView_changeDelayWarning { - padding: 40px 20px; -} - -.mx_GroupView_spaceUpgradePrompt { - padding: 16px 50px; - background-color: $header-panel-bg-color; - border-radius: 8px; - max-width: 632px; - font-size: $font-15px; - line-height: $font-24px; - margin-top: 24px; - position: relative; - - > h2 { - font-size: inherit; - font-weight: $font-semi-bold; - } - - > p, h2 { - margin: 0; - } - - &::before { - content: ""; - position: absolute; - height: $font-24px; - width: 20px; - left: 18px; - mask-repeat: no-repeat; - mask-position: center; - mask-size: contain; - mask-image: url('$(res)/img/element-icons/room/room-summary.svg'); - background-color: $secondary-content; - } - - .mx_AccessibleButton_kind_link { - padding: 0; - } - - .mx_GroupView_spaceUpgradePrompt_close { - width: 16px; - height: 16px; - border-radius: 8px; - background-color: $input-darker-bg-color; - position: absolute; - top: 16px; - right: 16px; - - &::before { - content: ""; - position: absolute; - width: inherit; - height: inherit; - mask-repeat: no-repeat; - mask-position: center; - mask-size: 8px; - mask-image: url('$(res)/img/image-view/close.svg'); - background-color: $secondary-content; - } - } -} - -.mx_GroupView .mx_MemberInfo .mx_AutoHideScrollbar > :not(.mx_MemberInfo_avatar) { - padding-left: 16px; - padding-right: 16px; -} diff --git a/res/css/structures/_HomePage.scss b/res/css/structures/_HomePage.scss index 77da167099c..a85bb0c42b6 100644 --- a/res/css/structures/_HomePage.scss +++ b/res/css/structures/_HomePage.scss @@ -95,11 +95,13 @@ limitations under the License. &.mx_HomePage_button_sendDm::before { mask-image: url('$(res)/img/element-icons/feedback.svg'); } + &.mx_HomePage_button_explore::before { mask-image: url('$(res)/img/element-icons/roomlist/explore.svg'); } + &.mx_HomePage_button_createGroup::before { - mask-image: url('$(res)/img/element-icons/community-members.svg'); + mask-image: url('$(res)/img/element-icons/group-members.svg'); } } } diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index 1113a5d9efd..18ef247b5f0 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -23,13 +23,21 @@ $roomListCollapsedWidth: 68px; } } -.mx_LeftPanel_wrapper { +.mx_LeftPanel_outerWrapper { display: flex; + flex-direction: column; 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 { + display: flex; + flex-direction: row; + flex: 1; + height: 100%; // ensure space panel is still scrollable with an outer wrapper .mx_LeftPanel_wrapper--user { background-color: $roomlist-bg-color; @@ -45,9 +53,8 @@ $roomListCollapsedWidth: 68px; .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 - // Create a row-based flexbox for the GroupFilterPanel and the room list + // Create a row-based flexbox for the space panel and the room list display: flex; contain: content; position: relative; @@ -111,11 +118,6 @@ $roomListCollapsedWidth: 68px; display: flex; align-items: center; - .mx_UserMenu { - // mini-mode for when Space Panel is disabled - margin-right: 12px; - } - & + .mx_RoomListHeader { margin-top: 12px; } diff --git a/res/css/structures/_LeftPanelWidget.scss b/res/css/structures/_LeftPanelWidget.scss deleted file mode 100644 index 0a01a19b90a..00000000000 --- a/res/css/structures/_LeftPanelWidget.scss +++ /dev/null @@ -1,145 +0,0 @@ -/* -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_LeftPanelWidget { - // largely based on RoomSublist - margin-left: 8px; - margin-bottom: 4px; - - .mx_LeftPanelWidget_headerContainer { - display: flex; - align-items: center; - - height: 24px; - color: $tertiary-content; - margin-top: 4px; - - .mx_LeftPanelWidget_stickable { - flex: 1; - max-width: 100%; - - display: flex; - align-items: center; - } - - .mx_LeftPanelWidget_headerText { - flex: 1; - max-width: calc(100% - 16px); - line-height: $font-16px; - font-size: $font-13px; - font-weight: 600; - - // Ellipsize any text overflow - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - - .mx_LeftPanelWidget_collapseBtn { - display: inline-block; - position: relative; - width: 14px; - height: 14px; - margin-right: 6px; - - &::before { - content: ''; - width: 18px; - height: 18px; - position: absolute; - mask-position: center; - mask-size: contain; - mask-repeat: no-repeat; - background-color: $tertiary-content; - mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); - } - - &.mx_LeftPanelWidget_collapseBtn_collapsed::before { - transform: rotate(-90deg); - } - } - } - } - - .mx_LeftPanelWidget_resizeBox { - position: relative; - - display: flex; - flex-direction: column; - overflow: visible; // let the resize handle out - } - - .mx_AppTileFullWidth { - flex: 1 0 0; - overflow: hidden; - // need this to be flex otherwise the overflow hidden from above - // sometimes vertically centers the clipped list ... no idea why it would do this - // as the box model should be top aligned. Happens in both FF and Chromium - display: flex; - flex-direction: column; - box-sizing: border-box; - - mask-image: linear-gradient(0deg, transparent, black 4px); - } - - .mx_LeftPanelWidget_resizerHandle { - cursor: ns-resize; - border-radius: 3px; - - // Override styles from library - width: unset !important; - height: 4px !important; - - position: absolute; - top: -24px !important; // override from library - puts it in the margin-top of the headerContainer - - // Together, these make the bar 64px wide - // These are also overridden from the library - left: calc(50% - 32px) !important; - right: calc(50% - 32px) !important; - } - - &:hover .mx_LeftPanelWidget_resizerHandle { - opacity: 0.8; - background-color: $primary-content; - } - - .mx_LeftPanelWidget_maximizeButton { - margin-left: 8px; - margin-right: 7px; - position: relative; - width: 24px; - height: 24px; - border-radius: 32px; - - &::before { - content: ''; - width: 16px; - height: 16px; - position: absolute; - top: 4px; - left: 4px; - mask-position: center; - mask-size: contain; - mask-repeat: no-repeat; - mask-image: url("$(res)/img/element-icons/maximise-expand.svg"); - background: $muted-fg-color; - } - } -} - -.mx_LeftPanelWidget_maximizeButtonTooltip { - margin-top: -3px; -} diff --git a/res/css/structures/_MatrixChat.scss b/res/css/structures/_MatrixChat.scss index a95bfa9eb9f..0523e677616 100644 --- a/res/css/structures/_MatrixChat.scss +++ b/res/css/structures/_MatrixChat.scss @@ -62,8 +62,8 @@ limitations under the License. transform: translateX(-50%); } -/* not the left panel, and not the resize handle, so the roomview/groupview/... */ -.mx_MatrixChat > :not(.mx_LeftPanel):not(.mx_SpacePanel):not(.mx_ResizeHandle):not(.mx_LeftPanel_wrapper) { +/* not the left panel, and not the resize handle, so the roomview and friends */ +.mx_MatrixChat > :not(.mx_LeftPanel):not(.mx_SpacePanel):not(.mx_ResizeHandle):not(.mx_LeftPanel_outerWrapper) { background-color: $background; flex: 1 1 0; diff --git a/res/css/structures/_MyGroups.scss b/res/css/structures/_MyGroups.scss deleted file mode 100644 index 9c0062b72d3..00000000000 --- a/res/css/structures/_MyGroups.scss +++ /dev/null @@ -1,172 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_MyGroups { - display: flex; - flex-direction: column; - - .mx_BetaCard { - margin: 0 72px; - max-width: 760px; - } -} - -.mx_MyGroups .mx_RoomHeader_simpleHeader { - margin-left: 0px; -} - -.mx_MyGroups_header { - /* Keep mid-point of create button aligned with icon in page header */ - margin-left: 2px; - display: flex; - flex-wrap: wrap; -} - -.mx_MyGroups > :not(.mx_RoomHeader):not(.mx_BetaCard) { - max-width: 960px; - margin: 40px; -} - -.mx_MyGroups_headerCard { - flex: 1 0 50%; - margin-bottom: 30px; - min-width: 400px; - display: flex; - align-items: center; -} - -.mx_MyGroups_headerCard .mx_MyGroups_headerCard_button { - flex: 0 0 auto; - margin-right: 13px; - height: 40px; - width: 40px; - border-radius: 20px; - background-color: $roomheader-addroom-bg-color; - position: relative; - - &::before { - background-color: $roomheader-addroom-fg-color; - mask: url('$(res)/img/icons-create-room.svg'); - mask-repeat: no-repeat; - mask-position: center; - mask-size: 80%; - content: ''; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - } -} - -.mx_MyGroups_headerCard_header { - font-weight: bold; - margin-bottom: 10px; -} - -.mx_MyGroups_headerCard_content { - padding-right: 15px; -} - -/* Until the button is wired up */ -.mx_MyGroups_joinBox { - visibility: hidden; - - /* When joinBox wraps onto its own row, it should take up zero height so - that there isn't an awkward gap between MyGroups_createBox and - MyGroups_content. - */ - height: 0px; - margin: 0px; -} - -.mx_MyGroups_content { - margin-left: 2px; - - flex: 1 0 0; - - display: flex; - flex-direction: column; - overflow-y: auto; -} - -.mx_MyGroups_scrollable { - overflow-y: inherit; -} - -.mx_MyGroups_placeholder { - background-color: $info-plinth-bg-color; - color: $info-plinth-fg-color; - line-height: $font-400px; - border-radius: 10px; - text-align: center; -} - -.mx_MyGroups_joinedGroups { - border-top: 1px solid $primary-hairline-color; - overflow-x: hidden; - - display: flex; - flex-flow: row wrap; - align-content: flex-start; -} - -.mx_MyGroups_joinedGroups .mx_GroupTile { - min-width: 300px; - max-width: 33%; - flex: 1 0 300px; - height: 75px; - margin: 10px 0px; - display: flex; - align-items: flex-start; - cursor: pointer; -} - -.mx_GroupTile_avatar { - cursor: grab, -webkit-grab; -} - -.mx_GroupTile_profile { - margin-left: 10px; - display: flex; - flex-direction: column; - justify-content: center; -} - -.mx_GroupTile_profile .mx_GroupTile_name, -.mx_GroupTile_profile .mx_GroupTile_groupId, -.mx_GroupTile_profile .mx_GroupTile_desc { - padding-right: 10px; -} - -.mx_GroupTile_profile .mx_GroupTile_name { - margin: 0px; - font-size: $font-15px; -} - -.mx_GroupTile_profile .mx_GroupTile_groupId { - font-size: $font-13px; - opacity: 0.7; -} - -.mx_GroupTile_profile .mx_GroupTile_desc { - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - font-size: $font-13px; - max-height: 36px; - overflow: hidden; -} diff --git a/res/css/structures/_NotificationPanel.scss b/res/css/structures/_NotificationPanel.scss index 68e1dd6a9a0..be953a750fc 100644 --- a/res/css/structures/_NotificationPanel.scss +++ b/res/css/structures/_NotificationPanel.scss @@ -77,7 +77,7 @@ limitations under the License. display: none; // we don't need this in this view } -.mx_NotificationPanel .mx_EventTile .mx_SenderProfile, +.mx_NotificationPanel .mx_EventTile .mx_DisambiguatedProfile, .mx_NotificationPanel .mx_EventTile .mx_MessageTimestamp { color: $primary-content; font-size: $font-12px; diff --git a/res/css/structures/_QuickSettingsButton.scss b/res/css/structures/_QuickSettingsButton.scss index 17417fa36f4..153dedf6b73 100644 --- a/res/css/structures/_QuickSettingsButton.scss +++ b/res/css/structures/_QuickSettingsButton.scss @@ -66,8 +66,9 @@ limitations under the License. margin: 0 0 16px; } - .mx_AccessibleButton_kind_primary_outline { + .mx_AccessibleButton_hasKind { display: block; + margin-top: 4px; } > div > h4 { diff --git a/res/css/structures/_RightPanel.scss b/res/css/structures/_RightPanel.scss index 5fb57d19992..a25e172c731 100644 --- a/res/css/structures/_RightPanel.scss +++ b/res/css/structures/_RightPanel.scss @@ -93,17 +93,8 @@ limitations under the License. mask-position: center; } -.mx_RightPanel_groupMembersButton::before { - mask-image: url('$(res)/img/element-icons/community-members.svg'); - mask-position: center; -} - -.mx_RightPanel_roomsButton::before { - mask-image: url('$(res)/img/element-icons/community-rooms.svg'); - mask-position: center; -} - -$dot-size: 7px; +$dot-size: 8px; +$dot-offset: -3px; $pulse-color: $alert; .mx_RightPanel_pinnedMessagesButton { @@ -112,10 +103,11 @@ $pulse-color: $alert; mask-position: center; } } + .mx_RightPanel_headerButton_unreadIndicator_bg { position: absolute; - right: 0; - top: 0; + right: $dot-offset; + top: $dot-offset; margin: 4px; width: $dot-size; height: $dot-size; @@ -127,17 +119,9 @@ $pulse-color: $alert; .mx_RightPanel_headerButton_unreadIndicator { position: absolute; - right: 0; - top: 0; + right: $dot-offset; + top: $dot-offset; margin: 4px; - width: $dot-size; - height: $dot-size; - border-radius: 50%; - transform: scale(1); - background: rgba($pulse-color, 1); - box-shadow: 0 0 0 0 rgba($pulse-color, 1); - animation: mx_RightPanel_indicator_pulse 2s infinite; - animation-iteration-count: 1; &.mx_Indicator_red { background: rgba($alert, 1); @@ -145,29 +129,13 @@ $pulse-color: $alert; } &.mx_Indicator_gray { - background: rgba($roomtile-default-badge-bg-color, 1); - box-shadow: rgba($roomtile-default-badge-bg-color, 1); + background: rgba($room-icon-unread-color, 1); + box-shadow: rgba($room-icon-unread-color, 1); } &.mx_Indicator_bold { - background: rgba($input-darker-fg-color, 1); - box-shadow: rgba($input-darker-fg-color, 1); - } - - &::after { - content: ""; - position: absolute; - width: inherit; - height: inherit; - top: 0; - left: 0; - transform: scale(1); - transform-origin: center center; - animation-name: mx_RightPanel_indicator_pulse_shadow; - animation-duration: inherit; - animation-iteration-count: inherit; - border-radius: 50%; - background: inherit; + background: rgba($primary-content, 1); + box-shadow: rgba($primary-content, 1); } } @@ -207,7 +175,14 @@ $pulse-color: $alert; } } -.mx_RightPanel_headerButton_highlight { +.mx_RightPanel_headerButton_unread { + &::before { + background-color: $room-icon-unread-color !important; + } +} + +.mx_RightPanel_headerButton_highlight, +.mx_RightPanel_headerButton:hover { &::before { background-color: $accent !important; } @@ -234,7 +209,6 @@ $pulse-color: $alert; .mx_RightPanel .mx_MemberList, .mx_RightPanel .mx_MemberInfo, -.mx_RightPanel .mx_GroupRoomList, .mx_RightPanel_blank { order: 2; flex: 1 1 0; @@ -253,7 +227,8 @@ $pulse-color: $alert; margin: 16px 0; } - h2, p { + h2, + p { font-size: $font-14px; } diff --git a/res/css/structures/_RoomView.scss b/res/css/structures/_RoomView.scss index a6b2970ddf6..eba8ae8f6e8 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -70,10 +70,6 @@ limitations under the License. overflow-y: auto; flex: 1 1 0; overflow-anchor: none; - - &[data-scrollbar=false] { - overflow-y: hidden; - } } .mx_RoomView_messagePanelSearchSpinner { @@ -105,7 +101,9 @@ limitations under the License. flex: 1; min-width: 0; - .mx_RoomView_messagePanel, .mx_RoomView_messagePanelSpinner, .mx_RoomView_messagePanelSearchSpinner { + .mx_RoomView_messagePanel, + .mx_RoomView_messagePanelSpinner, + .mx_RoomView_messagePanelSearchSpinner { order: 2; } } @@ -147,20 +145,17 @@ limitations under the License. } .mx_RoomView_messageListWrapper { - min-height: 100%; - display: flex; - flex-direction: column; - justify-content: flex-end; + position: relative; } .mx_RoomView_searchResultsPanel { .mx_RoomView_messageListWrapper { justify-content: flex-start; - > .mx_RoomView_MessageList > li > ol { + >.mx_RoomView_MessageList > li > ol { list-style-type: none; } } @@ -212,6 +207,11 @@ hr.mx_RoomView_myReadMarker { opacity: 1; } +// Rooms with immersive content +.mx_RoomView_immersive .mx_RoomHeader_wrapper { + border: unset; +} + .mx_RoomView_callStatusBar .mx_UploadBar_uploadProgressInner { background-color: $background; } @@ -278,3 +278,62 @@ hr.mx_RoomView_myReadMarker { min-height: 42px; } } + +@keyframes mx_Indicator_pulse { + 0% { + transform: scale(0.95); + } + + 70% { + transform: scale(1); + } + + 100% { + transform: scale(0.95); + } +} + +@keyframes mx_Indicator_pulse_shadow { + 0% { + opacity: 0.7; + } + + 70% { + transform: scale(2.2); + opacity: 0; + } + + 100% { + opacity: 0; + } +} + +.mx_Indicator { + position: absolute; + right: -3px; + top: -3px; + width: $dot-size; + height: $dot-size; + border-radius: 50%; + transform: scale(1); + background: rgba($pulse-color, 1); + box-shadow: 0 0 0 0 rgba($pulse-color, 1); + animation: mx_Indicator_pulse 2s infinite; + animation-iteration-count: 1; + + &::after { + content: ""; + position: absolute; + width: inherit; + height: inherit; + top: 0; + left: 0; + transform: scale(1); + transform-origin: center center; + animation-name: mx_Indicator_pulse_shadow; + animation-duration: inherit; + animation-iteration-count: inherit; + border-radius: 50%; + background: inherit; + } +} diff --git a/res/css/structures/_SpaceHierarchy.scss b/res/css/structures/_SpaceHierarchy.scss index a43e538b721..32dda6b90d0 100644 --- a/res/css/structures/_SpaceHierarchy.scss +++ b/res/css/structures/_SpaceHierarchy.scss @@ -16,7 +16,6 @@ limitations under the License. .mx_SpaceRoomView_landing { .mx_AccessibleButton_kind_link { - padding: 0; font-size: inherit; } @@ -36,24 +35,31 @@ limitations under the License. .mx_SpaceHierarchy_listHeader { display: flex; - min-height: 32px; + flex-flow: wrap; + justify-content: space-between; align-items: center; + gap: 12px; font-size: $font-15px; line-height: $font-24px; color: $primary-content; margin-bottom: 12px; - > h4 { + .mx_SpaceHierarchy_listHeader_header { + grid-column-start: 1; font-weight: $font-semi-bold; margin: 0; } - .mx_AccessibleButton { - padding: 4px 12px; - font-weight: normal; + .mx_SpaceHierarchy_listHeader_buttons { + grid-column-start: 2; + display: flex; + flex-flow: wrap; + gap: 12px; + min-height: 32px; - & + .mx_AccessibleButton { - margin-left: 16px; + .mx_AccessibleButton { + padding: 4px 12px; + font-weight: normal; } } @@ -61,10 +67,6 @@ limitations under the License. .mx_AccessibleButton_kind_primary_outline { padding: 3px 12px; // to account for the 1px border } - - > span { - margin-left: auto; - } } .mx_SpaceHierarchy_error { @@ -89,12 +91,6 @@ limitations under the License. } } - .mx_SpaceHierarchy_list { - list-style: none; - padding: 0; - margin: 0; - } - .mx_SpaceHierarchy_roomCount { > h3 { display: inline; @@ -152,124 +148,146 @@ limitations under the License. padding-left: 12px; } - .mx_SpaceHierarchy_roomTile { - position: relative; - padding: 8px 16px; - border-radius: 8px; - box-sizing: border-box; - - display: grid; - grid-template-columns: 20px auto max-content; - grid-column-gap: 8px; - grid-row-gap: 6px; - align-items: center; + .mx_SpaceHierarchy_list { + list-style: none; + padding: 0; + margin: 0; - .mx_BaseAvatar { - grid-row: 1; - grid-column: 1; - } + li.mx_SpaceHierarchy_roomTileWrapper { + list-style: none; - .mx_SpaceHierarchy_roomTile_name { - font-weight: $font-semi-bold; - font-size: $font-15px; - line-height: $font-18px; - grid-row: 1; - grid-column: 2; - - .mx_InfoTooltip, - .mx_SpaceHierarchy_roomTile_joined { - display: inline; - margin-left: 12px; - color: $tertiary-content; - font-size: $font-12px; - line-height: $font-15px; - - .mx_InfoTooltip_icon { - margin-right: 4px; - position: relative; - vertical-align: text-top; - - &::before { - position: absolute; - top: 0; - left: 0; + .mx_SpaceHierarchy_roomTile { + position: relative; + padding: 8px 16px; + border-radius: 8px; + box-sizing: border-box; + + display: flex; + flex-wrap: wrap; + gap: 6px 12px; + + .mx_SpaceHierarchy_roomTile_item { + font-weight: $font-semi-bold; + font-size: $font-15px; + line-height: $font-18px; + display: grid; + grid-template-columns: 20px auto; + gap: 6px 8px; + align-items: center; + flex: 1; // wrap action buttons + + .mx_SpaceHierarchy_roomTile_avatar { + grid-row: 1; + grid-column: 1; } - } - } - .mx_SpaceHierarchy_roomTile_joined { - position: relative; - padding-left: 16px; - - &::before { - content: ''; - width: 20px; - height: 20px; - top: -2px; - left: -4px; - position: absolute; - mask-position: center; - mask-size: contain; - mask-repeat: no-repeat; - background-color: $accent; - mask-image: url('$(res)/img/element-icons/roomlist/checkmark.svg'); + .mx_SpaceHierarchy_roomTile_name { + grid-row: 1; + grid-column: 2; + + .mx_InfoTooltip, + .mx_SpaceHierarchy_roomTile_joined { + margin-left: 12px; + color: $tertiary-content; + font-size: $font-12px; + line-height: $font-15px; + + .mx_InfoTooltip_icon { + margin-right: 4px; + position: relative; + vertical-align: text-top; + + &::before { + position: absolute; + top: 0; + left: 0; + } + } + } + + .mx_InfoTooltip { + display: inline-block; + } + + .mx_SpaceHierarchy_roomTile_joined { + display: inline; + position: relative; + padding-left: 16px; + + &::before { + content: ''; + width: 20px; + height: 20px; + top: -2px; + left: -4px; + position: absolute; + mask-position: center; + mask-size: contain; + mask-repeat: no-repeat; + background-color: $accent; + mask-image: url('$(res)/img/element-icons/roomlist/checkmark.svg'); + } + } + } + + .mx_SpaceHierarchy_roomTile_info { + grid-row: 2; + grid-column: 2; + font-size: $font-14px; + font-weight: initial; + line-height: $font-18px; + color: $secondary-content; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + } } - } - } - .mx_SpaceHierarchy_roomTile_info { - font-size: $font-14px; - line-height: $font-18px; - color: $secondary-content; - grid-row: 2; - grid-column: 2/3; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 2; - overflow: hidden; - } + .mx_SpaceHierarchy_actions { + display: flex; + align-items: center; + column-gap: 12px; + margin-left: auto; + + .mx_AccessibleButton { + line-height: $font-24px; + padding: 4px 16px; + display: inline-block; + visibility: hidden; + } - .mx_SpaceHierarchy_actions { - text-align: right; - margin-left: 20px; - grid-column: 3; - grid-row: 1/3; + .mx_AccessibleButton_kind_danger_outline, + .mx_AccessibleButton_kind_primary_outline { + padding: 3px 16px; // to account for the 1px border + } - .mx_AccessibleButton { - line-height: $font-24px; - padding: 4px 16px; - display: inline-block; - visibility: hidden; - } + .mx_Checkbox { + display: inline-flex; - .mx_AccessibleButton_kind_danger_outline, - .mx_AccessibleButton_kind_primary_outline { - padding: 3px 16px; // to account for the 1px border - } + label { + width: 16px; + height: 16px; + } + } + } - .mx_Checkbox { - display: inline-flex; - vertical-align: middle; - margin-left: 12px; - } - } + &:hover, &:focus-within { + background-color: $spacePanel-bg-color; - &:hover, &:focus-within { - background-color: $groupFilterPanel-bg-color; + .mx_AccessibleButton { + visibility: visible; + } + } - .mx_AccessibleButton { - visibility: visible; + &.mx_SpaceHierarchy_joining { + .mx_AccessibleButton { + visibility: visible; + padding: 4px 18px; + } + } } } - - &.mx_SpaceHierarchy_joining .mx_AccessibleButton { - visibility: visible; - padding: 4px 18px; - } - } - - li.mx_SpaceHierarchy_roomTileWrapper { - list-style: none; } .mx_SpaceHierarchy_roomTile, @@ -277,7 +295,7 @@ limitations under the License. &::before { content: ""; position: absolute; - background-color: $groupFilterPanel-bg-color; + background-color: $spacePanel-bg-color; width: 1px; height: 100%; left: 6px; diff --git a/res/css/structures/_SpacePanel.scss b/res/css/structures/_SpacePanel.scss index d999ff89b8f..9d23dd5fc93 100644 --- a/res/css/structures/_SpacePanel.scss +++ b/res/css/structures/_SpacePanel.scss @@ -23,7 +23,7 @@ $activeBackgroundColor: $panel-actions; $activeBorderColor: $primary-content; .mx_SpacePanel { - background-color: $groupFilterPanel-bg-color; + background-color: $spacePanel-bg-color; flex: 0 0 auto; padding: 0; margin: 0; @@ -155,6 +155,7 @@ $activeBorderColor: $primary-content; border-radius: 12px; padding: 4px; width: calc(100% - 32px); + min-width: 0; } .mx_SpaceButton_name { @@ -251,7 +252,8 @@ $activeBorderColor: $primary-content; margin-top: auto; margin-bottom: auto; display: none; - position: relative; + position: absolute; + right: 4px; &::before { top: 3px; @@ -273,6 +275,7 @@ $activeBorderColor: $primary-content; display: flex; flex-direction: column; max-width: 250px; + min-width: 0; flex-grow: 1; .mx_BaseAvatar:not(.mx_UserMenu_userAvatar_BaseAvatar) .mx_BaseAvatar_initial { @@ -309,13 +312,13 @@ $activeBorderColor: $primary-content; .mx_NotificationBadge_dot { // make the smaller dot occupy the same width for centering margin: 0 -1px 0 0; - border: 3px solid $groupFilterPanel-bg-color; + border: 3px solid $spacePanel-bg-color; } .mx_NotificationBadge_2char, .mx_NotificationBadge_3char { margin: -5px -5px 0 0; - border: 2px solid $groupFilterPanel-bg-color; + border: 2px solid $spacePanel-bg-color; } } @@ -327,6 +330,16 @@ $activeBorderColor: $primary-content; } } + .mx_SpaceItem:not(.mx_SpaceItem_new) { + .mx_SpaceButton:hover, + .mx_SpaceButton:focus-within, + .mx_SpaceButton_hasMenuOpen { + &:not(.mx_SpaceButton_narrow):not(.mx_SpaceButton_invite) .mx_SpaceButton_name { + max-width: calc(100% - 56px); + } + } + } + /* root space buttons are bigger and not indented */ & > .mx_AutoHideScrollbar { flex: 1; diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 8fbd6fbb703..eed3d8830f6 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -137,6 +137,23 @@ $SpaceRoomViewInnerWidth: 428px; } } + .mx_SpaceRoomView_preview, + .mx_SpaceRoomView_landing { + .mx_SpaceRoomView_info_memberCount { + color: inherit; + position: relative; + padding: 0 0 0 16px; + font-size: $font-15px; + display: inline; // cancel inline-flex + + &::before { + content: "·"; // visual separator + position: absolute; + left: 6px; + } + } + } + .mx_SpaceRoomView_preview { padding: 32px 24px !important; // override default padding from above margin: auto; @@ -152,6 +169,7 @@ $SpaceRoomViewInnerWidth: 428px; right: 24px; top: 32px; } + // XXX remove this when spaces leaves Beta .mx_SpaceRoomView_preview_spaceBetaPrompt { font-weight: $font-semi-bold; @@ -183,18 +201,6 @@ $SpaceRoomViewInnerWidth: 428px; } } - .mx_SpaceRoomView_preview_migratedCommunity { - margin-bottom: 16px; - padding: 8px 12px; - border-radius: 8px; - border: 1px solid $input-border-color; - width: max-content; - - .mx_BaseAvatar { - margin-right: 4px; - } - } - .mx_SpaceRoomView_preview_inviter { display: flex; align-items: center; @@ -254,13 +260,27 @@ $SpaceRoomViewInnerWidth: 428px; flex-direction: column; min-width: 0; - > .mx_BaseAvatar { - width: 80px; - } + .mx_SpaceRoomView_landing_header { + display: flex; + justify-content: space-between; + + .mx_BaseAvatar { + width: 80px; - > .mx_BaseAvatar_image, - > .mx_BaseAvatar > .mx_BaseAvatar_image { - border-radius: 12px; + .mx_BaseAvatar_image { + border-radius: 12px; + } + } + + // XXX: Temporary for the Spaces release only + .mx_SpaceFeedbackPrompt { + padding: 7px; // 8px - 1px border + border: 1px solid rgba($primary-content, .1); + border-radius: 8px; + width: max-content; + height: fit-content; + margin-left: 24px; + } } .mx_SpaceRoomView_landing_name { @@ -269,13 +289,11 @@ $SpaceRoomViewInnerWidth: 428px; color: $secondary-content; > span { - display: inline-block; - } + display: flex; + flex-flow: column; + gap: 12px 0; - .mx_SpaceRoomView_landing_nameRow { - margin-top: 12px; - - > h1 { + h1 { display: inline-block; } } @@ -288,62 +306,101 @@ $SpaceRoomViewInnerWidth: 428px; } } - .mx_SpaceRoomView_landing_info { + .mx_SpaceRoomView_landing_infoBar { display: flex; align-items: center; + justify-content: space-between; + gap: 12px; + flex-wrap: wrap; + line-height: $font-24px; .mx_SpaceRoomView_info { + color: $secondary-content; + font-size: $font-15px; display: inline-block; - margin: 0 auto 0 0; - } - .mx_FacePile { - display: inline-block; - margin-right: 12px; + .mx_SpaceRoomView_info_public, + .mx_SpaceRoomView_info_private { + padding-left: 20px; + position: relative; + + &::before { + position: absolute; + content: ""; + width: 20px; + height: 20px; + top: 0; + left: -2px; + mask-position: center; + mask-repeat: no-repeat; + background-color: $tertiary-content; + } + } - .mx_FacePile_faces { - cursor: pointer; + .mx_SpaceRoomView_info_public::before { + mask-size: 12px; + mask-image: url("$(res)/img/globe.svg"); + } + + .mx_SpaceRoomView_info_private::before { + mask-size: 14px; + mask-image: url("$(res)/img/element-icons/lock.svg"); } } - .mx_SpaceRoomView_landing_inviteButton { - position: relative; - padding: 4px 18px 4px 40px; - line-height: $font-24px; - height: min-content; + .mx_SpaceRoomView_landing_infoBar_interactive { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 12px 12px; - &::before { - position: absolute; - content: ""; - left: 8px; - height: 16px; - width: 16px; - background: #ffffff; // white icon fill - mask-position: center; - mask-size: 16px; - mask-repeat: no-repeat; - mask-image: url('$(res)/img/element-icons/room/invite.svg'); + .mx_FacePile { + display: inline-block; + + .mx_FacePile_faces { + cursor: pointer; + } } - } - .mx_SpaceRoomView_landing_settingsButton { - position: relative; - margin-left: 16px; - width: 24px; - height: 24px; + .mx_SpaceRoomView_landing_inviteButton, + .mx_SpaceRoomView_landing_settingsButton { + position: relative; - &::before { - position: absolute; - content: ""; - left: 0; - top: 0; - height: 24px; + &::before { + position: absolute; + content: ""; + mask-position: center; + mask-repeat: no-repeat; + } + } + + .mx_SpaceRoomView_landing_inviteButton { + padding: 4px 18px 4px 40px; + height: min-content; + + &::before { + left: 8px; + height: 16px; + width: 16px; + background: #fff; // white icon fill + mask-size: 16px; + mask-image: url('$(res)/img/element-icons/room/invite.svg'); + } + } + + .mx_SpaceRoomView_landing_settingsButton { width: 24px; - background: $tertiary-content; - mask-position: center; - mask-size: contain; - mask-repeat: no-repeat; - mask-image: url('$(res)/img/element-icons/settings.svg'); + height: 24px; + + &::before { + left: 0; + top: 0; + height: 24px; + width: 24px; + background: $tertiary-content; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/settings.svg'); + } } } } @@ -360,14 +417,6 @@ $SpaceRoomViewInnerWidth: 428px; margin: 0 0 20px; flex: 0; } - - .mx_SpaceFeedbackPrompt { - padding: 7px; // 8px - 1px border - 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_SpaceRoomView_privateScope { @@ -380,7 +429,7 @@ $SpaceRoomViewInnerWidth: 428px; } .mx_SpaceRoomView_privateScope_meAndMyTeammatesButton::before { - mask-image: url('$(res)/img/element-icons/community-members.svg'); + mask-image: url('$(res)/img/element-icons/group-members.svg'); } } @@ -441,51 +490,3 @@ $SpaceRoomViewInnerWidth: 428px; } } } - -.mx_SpaceRoomView_info { - color: $secondary-content; - font-size: $font-15px; - line-height: $font-24px; - margin: 20px 0; - - .mx_SpaceRoomView_info_public, - .mx_SpaceRoomView_info_private { - padding-left: 20px; - position: relative; - - &::before { - position: absolute; - content: ""; - width: 20px; - height: 20px; - top: 0; - left: -2px; - mask-position: center; - mask-repeat: no-repeat; - background-color: $tertiary-content; - } - } - - .mx_SpaceRoomView_info_public::before { - mask-size: 12px; - mask-image: url("$(res)/img/globe.svg"); - } - - .mx_SpaceRoomView_info_private::before { - mask-size: 14px; - mask-image: url("$(res)/img/element-icons/lock.svg"); - } - - .mx_SpaceRoomView_info_memberCount { - color: inherit; - position: relative; - padding: 0 0 0 16px; - font-size: $font-15px; - - &::before { - content: "·"; // visual separator - position: absolute; - left: 6px; - } - } -} diff --git a/res/css/structures/_ToastContainer.scss b/res/css/structures/_ToastContainer.scss index e4fe3c1e664..00c7cd05b45 100644 --- a/res/css/structures/_ToastContainer.scss +++ b/res/css/structures/_ToastContainer.scss @@ -108,26 +108,25 @@ limitations under the License. } .mx_Toast_title { + display: flex; + align-items: center; + column-gap: 8px; width: 100%; box-sizing: border-box; h2 { - grid-column: 1 / 3; - grid-row: 1; margin: 0; font-size: $font-15px; font-weight: 600; display: inline; width: auto; - vertical-align: middle; } - span { - padding-left: 8px; - float: right; + .mx_Toast_title_countIndicator { font-size: $font-12px; line-height: $font-22px; color: $secondary-content; + margin-inline-start: auto; // on the end side of the div } } @@ -137,17 +136,14 @@ limitations under the License. } .mx_Toast_buttons { - float: right; display: flex; + justify-content: flex-end; + column-gap: 5px; .mx_AccessibleButton { min-width: 96px; box-sizing: border-box; } - - .mx_AccessibleButton + .mx_AccessibleButton { - margin-left: 5px; - } } .mx_Toast_description { @@ -157,11 +153,6 @@ limitations under the License. margin: 4px 0 11px 0; font-size: $font-12px; - .mx_AccessibleButton_kind_link { - font-size: inherit; - padding: 0; - } - a { text-decoration: none; } diff --git a/res/css/structures/_UserMenu.scss b/res/css/structures/_UserMenu.scss index aa4e7d6403e..a88e9eddb90 100644 --- a/res/css/structures/_UserMenu.scss +++ b/res/css/structures/_UserMenu.scss @@ -64,9 +64,13 @@ limitations under the License. } } -.mx_UserMenu_contextMenu { - width: 258px; +.mx_IconizedContextMenu { + &.mx_UserMenu_contextMenu { + width: 258px; + } +} +.mx_UserMenu_contextMenu { &.mx_IconizedContextMenu .mx_IconizedContextMenu_optionList_red { .mx_AccessibleButton { padding-top: 16px; @@ -87,12 +91,15 @@ limitations under the License. flex-direction: column; width: calc(100% - 40px); // 40px = 32px theme button + 8px margin to theme button - * { - // Automatically grow all subelements to fit the container + .mx_UserMenu_contextMenu_displayName, + .mx_UserMenu_contextMenu_userId { + font-size: $font-15px; + + // Automatically grow subelements to fit the container flex: 1; width: 100%; - // Ellipsize any text overflow + // Ellipsize text overflow text-overflow: ellipsis; overflow: hidden; white-space: nowrap; @@ -100,12 +107,10 @@ limitations under the License. .mx_UserMenu_contextMenu_displayName { font-weight: bold; - font-size: $font-15px; line-height: $font-20px; } .mx_UserMenu_contextMenu_userId { - font-size: $font-15px; line-height: $font-24px; } } @@ -142,12 +147,6 @@ limitations under the License. margin-top: 8px; } } - - .mx_AccessibleButton_kind_link { - font-weight: normal; - font-size: inherit; - padding: 0; - } } } diff --git a/res/css/structures/_VideoRoomView.scss b/res/css/structures/_VideoRoomView.scss new file mode 100644 index 00000000000..d99b3f5894b --- /dev/null +++ b/res/css/structures/_VideoRoomView.scss @@ -0,0 +1,41 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_VideoRoomView { + flex-grow: 1; + min-height: 0; + + display: flex; + flex-direction: column; + margin: $container-gap-width; + margin-right: calc($container-gap-width / 2); + + background-color: $header-panel-bg-color; + padding-top: 33px; // to match the right panel chat heading + border: 8px solid $header-panel-bg-color; + border-radius: 8px; + + .mx_AppTile { + width: auto; + height: 100%; + border: none; + } + + // While the lobby is shown, the widget needs to stay loaded but hidden in the background + .mx_VideoLobby ~ .mx_AppTile { + display: none; + } +} diff --git a/res/css/structures/_ViewSource.scss b/res/css/structures/_ViewSource.scss index e3d6135ef30..3dc3e21489e 100644 --- a/res/css/structures/_ViewSource.scss +++ b/res/css/structures/_ViewSource.scss @@ -34,8 +34,17 @@ limitations under the License. padding: 0.5em 1em 0.5em 1em; word-wrap: break-word; white-space: pre-wrap; + overflow-wrap: anywhere; } .mx_ViewSource_details { margin-top: 0.8em; } + +.mx_ViewSource_container { + max-width: calc(100% - 24px); +} + +.mx_ViewSource_container .mx_CopyableText_border { + width: 100%; +} diff --git a/res/css/structures/auth/_Login.scss b/res/css/structures/auth/_Login.scss index 2290b6a3455..638917f1c28 100644 --- a/res/css/structures/auth/_Login.scss +++ b/res/css/structures/auth/_Login.scss @@ -88,14 +88,12 @@ limitations under the License. div.mx_AccessibleButton_kind_link.mx_Login_forgot { display: block; margin: 0 auto; - // style it as a link - font-size: inherit; - padding: 0; &.mx_AccessibleButton_disabled { cursor: not-allowed; } } + .mx_Login_spinner { display: flex; justify-content: center; diff --git a/res/css/views/audio_messages/_PlaybackContainer.scss b/res/css/views/audio_messages/_PlaybackContainer.scss index 408a2953893..4999980beaf 100644 --- a/res/css/views/audio_messages/_PlaybackContainer.scss +++ b/res/css/views/audio_messages/_PlaybackContainer.scss @@ -1,5 +1,5 @@ /* -Copyright 2021 The Matrix.org Foundation C.I.C. +Copyright 2021 - 2022 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ limitations under the License. contain: content; + // Waveforms are present in live recording only .mx_Waveform { .mx_Waveform_bar { background-color: $quaternary-content; @@ -46,11 +47,22 @@ limitations under the License. .mx_Clock { width: $font-42px; // we're not using a monospace font, so fake it + min-width: $font-42px; // force sensible layouts in awkward flexboxes (file panel, for example) padding-right: 6px; // with the fixed width this ends up as a visual 8px most of the time, as intended. padding-left: 8px; // isolate from recording circle / play control } - &.mx_VoiceMessagePrimaryContainer_noWaveform { - max-width: 162px; // with all the padding this results in 185px wide + // For timeline-rendered playback, mirror the values for where the clock is in + // the waveform version. + .mx_SeekBar { + margin-left: 8px; + margin-right: 6px; + + & + .mx_Clock { + text-align: right; + + // Take the padding off the clock because it's accounted for in the seek bar + padding: 0; + } } } diff --git a/res/css/views/avatars/_DecoratedRoomAvatar.scss b/res/css/views/avatars/_DecoratedRoomAvatar.scss index b912302f382..7927f82c2f5 100644 --- a/res/css/views/avatars/_DecoratedRoomAvatar.scss +++ b/res/css/views/avatars/_DecoratedRoomAvatar.scss @@ -65,6 +65,10 @@ limitations under the License. background-color: $presence-away; } + .mx_DecoratedRoomAvatar_icon_busy::before { + background-color: $presence-busy; + } + .mx_NotificationBadge, .mx_RoomTile_badgeContainer { position: absolute; top: 0; diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss index 80a70ad0d62..658e43f051b 100644 --- a/res/css/views/beta/_BetaCard.scss +++ b/res/css/views/beta/_BetaCard.scss @@ -23,8 +23,13 @@ limitations under the License. .mx_BetaCard_columns { display: flex; + flex-flow: wrap; + gap: 20px; + justify-content: center; + + .mx_BetaCard_columns_description { + flex: 1; - > div { .mx_BetaCard_title { font-weight: $font-semi-bold; font-size: $font-18px; @@ -32,47 +37,60 @@ limitations under the License. color: $primary-content; margin: 4px 0 14px; - .mx_BetaCard_betaPill { - margin-left: 12px; - } + display: flex; + align-items: center; + column-gap: 12px; } .mx_BetaCard_caption { font-size: $font-15px; line-height: $font-20px; color: $secondary-content; - margin-bottom: 20px; } - .mx_BetaCard_buttons .mx_AccessibleButton { - display: block; - margin: 12px 0; - padding: 7px 40px; - width: auto; + .mx_BetaCard_buttons { + display: flex; + flex-wrap: wrap-reverse; + gap: 12px; + margin: 20px auto; + + .mx_AccessibleButton { + padding: 7px 40px; + width: auto; + flex: 1; + white-space: nowrap; // text might overflow + + &:nth-child(1) { + order: 2; // Place feedback button top and right + } + } } .mx_BetaCard_disclaimer { font-size: $font-12px; line-height: $font-15px; color: $secondary-content; - margin-top: 20px; > h4 { - margin: 0; + margin: 12px 0 0; } > p { - margin-top: 0; + margin: 0; } } } - > img { - margin: auto 0 auto 20px; - width: 300px; - object-fit: contain; - height: 100%; - border-radius: 4px; + .mx_BetaCard_columns_image_wrapper { + margin: auto 0; + + .mx_BetaCard_columns_image { + width: 100%; + max-width: 300px; + object-fit: contain; + height: 100%; + border-radius: 4px; + } } } @@ -104,6 +122,7 @@ limitations under the License. color: #FFFFFF; display: inline-block; vertical-align: text-bottom; + word-break: keep-all; // avoid multiple lines on CJK language &.mx_AccessibleButton { cursor: pointer; diff --git a/res/css/views/context_menus/_MessageContextMenu.scss b/res/css/views/context_menus/_MessageContextMenu.scss index e743619f8fd..b92ce10d355 100644 --- a/res/css/views/context_menus/_MessageContextMenu.scss +++ b/res/css/views/context_menus/_MessageContextMenu.scss @@ -90,6 +90,22 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/pin.svg'); } + .mx_MessageContextMenu_iconCopy::before { + mask-image: url($copy-button-url); + } + + .mx_MessageContextMenu_iconEdit::before { + mask-image: url('$(res)/img/element-icons/room/message-bar/edit.svg'); + } + + .mx_MessageContextMenu_iconReply::before { + mask-image: url('$(res)/img/element-icons/room/message-bar/reply.svg'); + } + + .mx_MessageContextMenu_iconReact::before { + mask-image: url('$(res)/img/element-icons/room/message-bar/emoji.svg'); + } + .mx_MessageContextMenu_iconViewInRoom::before { mask-image: url('$(res)/img/element-icons/view-in-room.svg'); } diff --git a/res/css/views/context_menus/_TagTileContextMenu.scss b/res/css/views/context_menus/_TagTileContextMenu.scss deleted file mode 100644 index 14f5ec817ef..00000000000 --- a/res/css/views/context_menus/_TagTileContextMenu.scss +++ /dev/null @@ -1,67 +0,0 @@ -/* -Copyright 2018 New Vector Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_TagTileContextMenu_item { - padding: 8px; - padding-right: 20px; - cursor: pointer; - white-space: nowrap; - display: flex; - align-items: center; - line-height: $font-16px; -} - -.mx_TagTileContextMenu_item::before { - content: ''; - height: 15px; - width: 15px; - background-color: currentColor; - mask-repeat: no-repeat; - mask-size: contain; - margin-right: 8px; -} - -.mx_TagTileContextMenu_viewCommunity::before { - mask-image: url('$(res)/img/element-icons/view-community.svg'); -} - -.mx_TagTileContextMenu_moveUp::before { - transform: rotate(180deg); - mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); -} - -.mx_TagTileContextMenu_moveDown::before { - mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); -} - -.mx_TagTileContextMenu_hideCommunity::before { - mask-image: url('$(res)/img/element-icons/hide.svg'); -} - -.mx_TagTileContextMenu_createSpace::before { - mask-image: url('$(res)/img/element-icons/message/fwd.svg'); -} - -.mx_TagTileContextMenu_separator { - margin-top: 0; - margin-bottom: 0; - border-bottom-style: none; - border-left-style: none; - border-right-style: none; - border-top-style: solid; - border-top-width: 1px; - border-color: $menu-border-color; -} diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss index 5d53a996610..f82a29c546b 100644 --- a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss @@ -54,7 +54,6 @@ limitations under the License. font-size: $font-12px; line-height: $font-15px; margin-top: 8px; - padding: 0; } } @@ -136,10 +135,6 @@ limitations under the License. left: 0; } } - - .mx_AccessibleButton_kind_link { - padding: 0; - } } } diff --git a/res/css/views/dialogs/_AddressPickerDialog.scss b/res/css/views/dialogs/_AddressPickerDialog.scss deleted file mode 100644 index 44e9f94c5f7..00000000000 --- a/res/css/views/dialogs/_AddressPickerDialog.scss +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright 2016 OpenMarket Ltd -Copyright 2019 New Vector Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_AddressPickerDialog { - a:link, - a:hover, - a:visited { - @mixin mx_Dialog_link; - } -} - -/* Using a textarea for this element, to circumvent autofill */ -.mx_AddressPickerDialog_input, -.mx_AddressPickerDialog_input:focus { - height: 26px; - font-size: $font-14px; - padding-left: 12px; - padding-right: 12px; - margin: 0 !important; - border: 0 !important; - outline: 0 !important; - width: 1000%; /* Pretend that this is an "input type=text" */ - resize: none; - overflow: hidden; - vertical-align: middle; - box-sizing: border-box; - word-wrap: nowrap; -} - -.mx_AddressPickerDialog .mx_Dialog_content { - min-height: 50px; -} - -.mx_AddressPickerDialog_inputContainer { - border-radius: 3px; - border: solid 1px $input-border-color; - line-height: $font-36px; - padding-left: 4px; - padding-right: 4px; - padding-top: 1px; - padding-bottom: 1px; - max-height: 150px; - overflow-x: hidden; - overflow-y: auto; -} - -.mx_AddressPickerDialog_error { - margin-top: 10px; - color: $alert; -} - -.mx_AddressPickerDialog_cancel { - position: absolute; - right: 11px; - top: 13px; - cursor: pointer; -} - -.mx_AddressPickerDialog_cancel object { - pointer-events: none; -} - -.mx_AddressPickerDialog_identityServer { - margin-top: 1em; -} diff --git a/res/css/views/dialogs/_BugReportDialog.scss b/res/css/views/dialogs/_BugReportDialog.scss index 1920ac33eaa..348d9ebb99e 100644 --- a/res/css/views/dialogs/_BugReportDialog.scss +++ b/res/css/views/dialogs/_BugReportDialog.scss @@ -17,7 +17,7 @@ limitations under the License. .mx_BugReportDialog { .mx_BugReportDialog_download { .mx_AccessibleButton_kind_link { - padding-left: 0; + margin-right: 18px; // Space between "Downloading logs..." } } } diff --git a/res/css/views/messages/_SenderProfile.scss b/res/css/views/dialogs/_BulkRedactDialog.scss similarity index 65% rename from res/css/views/messages/_SenderProfile.scss rename to res/css/views/dialogs/_BulkRedactDialog.scss index 08644b14e3f..c6b2adff874 100644 --- a/res/css/views/messages/_SenderProfile.scss +++ b/res/css/views/dialogs/_BulkRedactDialog.scss @@ -1,5 +1,5 @@ /* -Copyright 2015, 2016 OpenMarket Ltd +Copyright 2021 Robin Townsend Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,13 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_SenderProfile_displayName { - font-weight: 600; -} +.mx_BulkRedactDialog { + .mx_Checkbox, .mx_BulkRedactDialog_checkboxMicrocopy { + line-height: $font-20px; + } -.mx_SenderProfile_mxid { - font-weight: 600; - font-size: 1.1rem; - margin-left: 5px; - opacity: 0.5; // Match mx_TextualEvent + .mx_BulkRedactDialog_checkboxMicrocopy { + margin-left: 26px; + color: $secondary-content; + } } diff --git a/res/css/views/dialogs/_CommunityPrototypeInviteDialog.scss b/res/css/views/dialogs/_CommunityPrototypeInviteDialog.scss deleted file mode 100644 index 5d6c817b14d..00000000000 --- a/res/css/views/dialogs/_CommunityPrototypeInviteDialog.scss +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_CommunityPrototypeInviteDialog { - &.mx_Dialog_fixedWidth { - width: 360px; - } - - .mx_Dialog_content { - margin-bottom: 0; - - .mx_CommunityPrototypeInviteDialog_people { - position: relative; - margin-bottom: 4px; - - .mx_AccessibleButton { - display: inline-block; - background-color: $focus-bg-color; // XXX: Abuse of variables - border-radius: 4px; - padding: 3px 5px; - font-size: $font-12px; - float: right; - } - } - - .mx_CommunityPrototypeInviteDialog_morePeople { - margin-top: 8px; - } - - .mx_CommunityPrototypeInviteDialog_person { - position: relative; - margin-top: 4px; - - & > * { - vertical-align: middle; - } - - .mx_Checkbox { - position: absolute; - right: 0; - top: calc(50% - 8px); // checkbox is 16px high - width: 16px; // to force a square - } - - .mx_CommunityPrototypeInviteDialog_personIdentifiers { - display: inline-block; - - & > * { - display: block; - } - - .mx_CommunityPrototypeInviteDialog_personName { - font-weight: 600; - font-size: $font-14px; - color: $primary-content; - margin-left: 7px; - } - - .mx_CommunityPrototypeInviteDialog_personId { - font-size: $font-12px; - color: $muted-fg-color; - margin-left: 7px; - } - } - } - - .mx_CommunityPrototypeInviteDialog_primaryButton { - display: block; - font-size: $font-13px; - line-height: 20px; - height: 20px; - margin-top: 24px; - } - } -} diff --git a/res/css/views/dialogs/_CreateCommunityPrototypeDialog.scss b/res/css/views/dialogs/_CreateCommunityPrototypeDialog.scss deleted file mode 100644 index a2378115a85..00000000000 --- a/res/css/views/dialogs/_CreateCommunityPrototypeDialog.scss +++ /dev/null @@ -1,102 +0,0 @@ -/* -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_CreateCommunityPrototypeDialog { - .mx_Dialog_content { - display: flex; - flex-direction: row; - margin-bottom: 12px; - - .mx_CreateCommunityPrototypeDialog_colName { - flex-basis: 66.66%; - padding-right: 100px; - - .mx_Field input { - font-size: $font-16px; - line-height: $font-20px; - } - - .mx_CreateCommunityPrototypeDialog_subtext { - display: block; - color: $muted-fg-color; - margin-bottom: 16px; - - &:last-child { - margin-top: 16px; - } - - &.mx_CreateCommunityPrototypeDialog_subtext_error { - color: $alert; - } - } - - .mx_CreateCommunityPrototypeDialog_communityId { - position: relative; - - .mx_InfoTooltip { - float: right; - } - } - - .mx_AccessibleButton { - display: block; - height: 32px; - font-size: $font-16px; - line-height: 32px; - } - } - - .mx_CreateCommunityPrototypeDialog_colAvatar { - flex-basis: 33.33%; - - .mx_CreateCommunityPrototypeDialog_avatarContainer { - margin-top: 12px; - margin-bottom: 20px; - - .mx_CreateCommunityPrototypeDialog_avatar, - .mx_CreateCommunityPrototypeDialog_placeholderAvatar { - width: 96px; - height: 96px; - border-radius: 96px; - } - - .mx_CreateCommunityPrototypeDialog_placeholderAvatar { - background-color: #368bd6; // hardcoded for both themes - - &::before { - display: inline-block; - background-color: #fff; // hardcoded because the background is - mask-repeat: no-repeat; - mask-size: 96px; - width: 96px; - height: 96px; - mask-position: center; - content: ''; - vertical-align: middle; - mask-image: url('$(res)/img/element-icons/add-photo.svg'); - } - } - } - - .mx_CreateCommunityPrototypeDialog_tip { - & > b, & > span { - display: block; - color: $muted-fg-color; - } - } - } - } -} diff --git a/res/css/views/dialogs/_CreateGroupDialog.scss b/res/css/views/dialogs/_CreateGroupDialog.scss deleted file mode 100644 index ef9c2b73d43..00000000000 --- a/res/css/views/dialogs/_CreateGroupDialog.scss +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_CreateGroupDialog_inputRow { - margin-top: 10px; - margin-bottom: 10px; -} - -.mx_CreateGroupDialog_label { - text-align: left; - padding-bottom: 12px; -} - -.mx_CreateGroupDialog_input { - font-size: $font-15px; - border-radius: 3px; - border: 1px solid $input-border-color; - padding: 9px; - color: $primary-content; - background-color: $background; -} - -.mx_CreateGroupDialog_input_hasPrefixAndSuffix { - border-radius: 0px; -} - -.mx_CreateGroupDialog_input_group { - display: flex; -} - -.mx_CreateGroupDialog_prefix, -.mx_CreateGroupDialog_suffix { - padding: 0px 5px; - line-height: $font-37px; - background-color: $input-darker-bg-color; - border: 1px solid $input-border-color; - text-align: center; -} - -.mx_CreateGroupDialog_prefix { - border-right: 0px; - border-radius: 3px 0px 0px 3px; -} - -.mx_CreateGroupDialog_suffix { - border-left: 0px; - border-radius: 0px 3px 3px 0px; -} diff --git a/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss b/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss deleted file mode 100644 index 72c2d13ae38..00000000000 --- a/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss +++ /dev/null @@ -1,188 +0,0 @@ -/* -Copyright 2021 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_CreateSpaceFromCommunityDialog_wrapper { - .mx_Dialog { - display: flex; - flex-direction: column; - } -} - -.mx_CreateSpaceFromCommunityDialog { - width: 480px; - color: $primary-content; - display: flex; - flex-direction: column; - flex-wrap: nowrap; - min-height: 0; - - .mx_CreateSpaceFromCommunityDialog_content { - > p { - font-size: $font-15px; - line-height: $font-24px; - - &:first-of-type { - margin-top: 0; - } - - &.mx_CreateSpaceFromCommunityDialog_flairNotice { - font-size: $font-12px; - line-height: $font-15px; - } - } - - .mx_SpaceBasicSettings { - > p { - font-size: $font-12px; - line-height: $font-15px; - margin: 16px 0; - } - - .mx_Field_textarea { - margin-bottom: 0; - } - } - - .mx_JoinRuleDropdown .mx_Dropdown_menu { - width: auto !important; // override fixed width - } - - .mx_CreateSpaceFromCommunityDialog_nonPublicSpacer { - height: 63px; // balance the height of the missing room alias field to prevent modal bouncing - } - } - - .mx_CreateSpaceFromCommunityDialog_footer { - display: flex; - margin-top: 20px; - - > span { - flex-grow: 1; - font-size: $font-12px; - line-height: $font-15px; - color: $secondary-content; - margin-top: -13px; // match height of buttons to prevent height changing - - .mx_ProgressBar { - height: 8px; - width: 100%; - - @mixin ProgressBarBorderRadius 8px; - } - - .mx_CreateSpaceFromCommunityDialog_progressText { - margin-top: 8px; - font-size: $font-15px; - line-height: $font-24px; - color: $primary-content; - } - - > * { - vertical-align: middle; - } - } - - .mx_CreateSpaceFromCommunityDialog_error { - padding-left: 12px; - - > img { - align-self: center; - } - - .mx_CreateSpaceFromCommunityDialog_errorHeading { - font-weight: $font-semi-bold; - font-size: $font-15px; - line-height: $font-18px; - color: $alert; - } - - .mx_CreateSpaceFromCommunityDialog_errorCaption { - margin-top: 4px; - font-size: $font-12px; - line-height: $font-15px; - color: $primary-content; - } - } - - .mx_AccessibleButton { - display: inline-block; - align-self: center; - } - - .mx_AccessibleButton_kind_primary { - padding: 8px 36px; - margin-left: 24px; - } - - .mx_AccessibleButton_kind_primary_outline { - margin-left: auto; - } - - .mx_CreateSpaceFromCommunityDialog_retryButton { - margin-left: 12px; - padding-left: 24px; - position: relative; - - &::before { - content: ''; - position: absolute; - background-color: $primary-content; - mask-repeat: no-repeat; - mask-position: center; - mask-size: contain; - mask-image: url('$(res)/img/element-icons/retry.svg'); - width: 18px; - height: 18px; - left: 0; - } - } - - .mx_AccessibleButton_kind_link { - padding: 0; - } - } -} - -.mx_CreateSpaceFromCommunityDialog_SuccessInfoDialog { - .mx_InfoDialog { - max-width: 500px; - } - - .mx_AccessibleButton_kind_link { - padding: 0; - } - - .mx_CreateSpaceFromCommunityDialog_SuccessInfoDialog_checkmark { - position: relative; - border-radius: 50%; - border: 3px solid $accent; - width: 68px; - height: 68px; - margin: 12px auto 32px; - - &::before { - width: inherit; - height: inherit; - content: ''; - position: absolute; - background-color: $accent; - mask-repeat: no-repeat; - mask-position: center; - mask-image: url('$(res)/img/element-icons/roomlist/checkmark.svg'); - mask-size: 48px; - } - } -} diff --git a/res/css/views/dialogs/_CreateSubspaceDialog.scss b/res/css/views/dialogs/_CreateSubspaceDialog.scss index 1ed10df35c4..bcce6def89f 100644 --- a/res/css/views/dialogs/_CreateSubspaceDialog.scss +++ b/res/css/views/dialogs/_CreateSubspaceDialog.scss @@ -73,9 +73,5 @@ limitations under the License. margin-left: 16px; padding: 8px 36px; } - - .mx_AccessibleButton_kind_link { - padding: 0; - } } } diff --git a/res/css/views/dialogs/_DeactivateAccountDialog.scss b/res/css/views/dialogs/_DeactivateAccountDialog.scss index 192917b2d00..8941afaf39c 100644 --- a/res/css/views/dialogs/_DeactivateAccountDialog.scss +++ b/res/css/views/dialogs/_DeactivateAccountDialog.scss @@ -18,10 +18,6 @@ limitations under the License. margin-bottom: 30px; } -.mx_DeactivateAccountDialog .mx_DeactivateAccountDialog_input_section { - margin-top: 60px; -} - .mx_DeactivateAccountDialog .mx_DeactivateAccountDialog_input_section .mx_Field { width: 300px; } diff --git a/res/css/views/dialogs/_DevtoolsDialog.scss b/res/css/views/dialogs/_DevtoolsDialog.scss index 37974d1358d..b1fed0d29bd 100644 --- a/res/css/views/dialogs/_DevtoolsDialog.scss +++ b/res/css/views/dialogs/_DevtoolsDialog.scss @@ -14,36 +14,39 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_DevTools_content { - margin: 10px 0; +.mx_DevtoolsDialog_wrapper { + .mx_Dialog { + height: 100%; + } + + .mx_Dialog_fixedWidth { + overflow-y: hidden; + height: 100%; + } } -.mx_DevTools_ServersInRoomList_button { - /* Set the cursor back to default as `.mx_Dialog button` sets it to pointer */ - cursor: default !important; +.mx_DevTools_content { + overflow-y: auto; + height: calc(100% - 124px); // 58px for buttons + 50px for header + 8px margin around } .mx_DevTools_RoomStateExplorer_query { margin-bottom: 10px; } -.mx_DevTools_RoomStateExplorer_button { - font-family: monospace; +.mx_DevTools_button { + font-family: monospace !important; + margin-bottom: 8px !important; } .mx_DevTools_RoomStateExplorer_button_hasSpaces { text-decoration: underline; } -.mx_DevTools_RoomStateExplorer_button.mx_DevTools_RoomStateExplorer_button_emptyString { +.mx_DevTools_button.mx_DevTools_RoomStateExplorer_button_emptyString { font-style: italic; } -.mx_DevTools_RoomStateExplorer_button, .mx_DevTools_ServersInRoomList_button { - margin-bottom: 10px; - width: 100%; -} - .mx_DevTools_label_left { float: left; } @@ -83,108 +86,6 @@ limitations under the License. margin-right: 42px; } -.mx_DevTools_tgl { - display: none; - - // add default box-sizing for this scope - &, - &::after, - &::before, - & *, - & *::after, - & *::before, - & + .mx_DevTools_tgl-btn { - box-sizing: border-box; - &::selection { - background: none; - } - } - - + .mx_DevTools_tgl-btn { - outline: 0; - display: block; - width: 7em; - height: 2em; - position: relative; - cursor: pointer; - user-select: none; - &::after, - &::before { - position: relative; - display: block; - content: ""; - width: 50%; - height: 100%; - } - - &::after { - left: 0; - } - - &::before { - display: none; - } - } - - &:checked + .mx_DevTools_tgl-btn::after { - left: 50%; - } -} - -.mx_DevTools_tgl-flip { - + .mx_DevTools_tgl-btn { - padding: 2px; - transition: all .2s ease; - perspective: 100px; - &::after, - &::before { - display: inline-block; - transition: all .4s ease; - width: 100%; - text-align: center; - position: absolute; - line-height: 2em; - font-weight: bold; - color: #fff; - top: 0; - left: 0; - backface-visibility: hidden; - border-radius: 4px; - } - - &::after { - content: attr(data-tg-on); - background: #02c66f; - transform: rotateY(-180deg); - } - - &::before { - background: #ff3a19; - content: attr(data-tg-off); - } - - &:active::before { - transform: rotateY(-20deg); - } - } - - &:checked + .mx_DevTools_tgl-btn { - &::before { - transform: rotateY(180deg); - } - - &::after { - transform: rotateY(0); - left: 0; - background: #7fc6a6; - } - - &:active::after { - transform: rotateY(20deg); - } - } -} - .mx_DevTools_VerificationRequest { border: 1px solid #cccccc; border-radius: 3px; diff --git a/res/css/views/dialogs/_EditCommunityPrototypeDialog.scss b/res/css/views/dialogs/_EditCommunityPrototypeDialog.scss deleted file mode 100644 index 75a56bf6b37..00000000000 --- a/res/css/views/dialogs/_EditCommunityPrototypeDialog.scss +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// XXX: many of these styles are shared with the create dialog -.mx_EditCommunityPrototypeDialog { - &.mx_Dialog_fixedWidth { - width: 360px; - } - - .mx_Dialog_content { - margin-bottom: 12px; - - .mx_AccessibleButton.mx_AccessibleButton_kind_primary { - display: block; - height: 32px; - font-size: $font-16px; - line-height: 32px; - } - - .mx_EditCommunityPrototypeDialog_rowAvatar { - display: flex; - flex-direction: row; - align-items: center; - } - - .mx_EditCommunityPrototypeDialog_avatarContainer { - margin-top: 20px; - margin-bottom: 20px; - - .mx_EditCommunityPrototypeDialog_avatar, - .mx_EditCommunityPrototypeDialog_placeholderAvatar { - width: 96px; - height: 96px; - border-radius: 96px; - } - - .mx_EditCommunityPrototypeDialog_placeholderAvatar { - background-color: #368bd6; // hardcoded for both themes - - &::before { - display: inline-block; - background-color: #fff; // hardcoded because the background is - mask-repeat: no-repeat; - mask-size: 96px; - width: 96px; - height: 96px; - mask-position: center; - content: ''; - vertical-align: middle; - mask-image: url('$(res)/img/element-icons/add-photo.svg'); - } - } - } - - .mx_EditCommunityPrototypeDialog_tip { - margin-left: 20px; - - & > b, & > span { - display: block; - color: $muted-fg-color; - } - } - } -} diff --git a/res/css/views/dialogs/_FeedbackDialog.scss b/res/css/views/dialogs/_FeedbackDialog.scss index 9e4cf5e8aae..8d11b83fe11 100644 --- a/res/css/views/dialogs/_FeedbackDialog.scss +++ b/res/css/views/dialogs/_FeedbackDialog.scss @@ -58,11 +58,6 @@ limitations under the License. line-height: $font-15px; } - .mx_AccessibleButton_kind_link { - padding: 0; - font-size: inherit; - } - a, .mx_AccessibleButton_kind_link { color: $accent; text-decoration: underline; diff --git a/res/css/views/dialogs/_ForwardDialog.scss b/res/css/views/dialogs/_ForwardDialog.scss index 205aaaa2026..ad7bf9a8167 100644 --- a/res/css/views/dialogs/_ForwardDialog.scss +++ b/res/css/views/dialogs/_ForwardDialog.scss @@ -93,7 +93,7 @@ limitations under the License. border-radius: 8px; &:hover { - background-color: $groupFilterPanel-bg-color; + background-color: $spacePanel-bg-color; } .mx_ForwardList_roomButton { diff --git a/res/css/views/dialogs/_GenericFeatureFeedbackDialog.scss b/res/css/views/dialogs/_GenericFeatureFeedbackDialog.scss index ab7496249dc..83f93495143 100644 --- a/res/css/views/dialogs/_GenericFeatureFeedbackDialog.scss +++ b/res/css/views/dialogs/_GenericFeatureFeedbackDialog.scss @@ -21,10 +21,4 @@ limitations under the License. line-height: $font-20px; margin-bottom: 24px; } - - .mx_AccessibleButton_kind_link { - padding: 0; - font-size: inherit; - line-height: inherit; - } } diff --git a/res/css/views/dialogs/_InviteDialog.scss b/res/css/views/dialogs/_InviteDialog.scss index 546327ff40a..35fedd7cf28 100644 --- a/res/css/views/dialogs/_InviteDialog.scss +++ b/res/css/views/dialogs/_InviteDialog.scss @@ -43,7 +43,7 @@ limitations under the License. min-width: max-content; // prevent manipulation by flexbox } - // Mostly copied from AddressPickerDialog; overrides bunch of our default text input styles + // overrides bunch of our default text input styles > input[type="text"] { margin: 6px 0 !important; height: 24px; @@ -97,11 +97,9 @@ limitations under the License. color: $primary-content; } - .mx_InviteDialog_subname { - margin-bottom: 10px; - margin-top: -10px; // HACK: Positioning with margins is bad - font-size: $font-12px; - color: $muted-fg-color; + .mx_InviteDialog_section_showMore { + margin: 7px 18px; + display: block; } } @@ -273,10 +271,25 @@ limitations under the License. .mx_InviteDialog_other { // Prevent the dialog from jumping around randomly when elements change. height: 600px; - padding-left: 20px; // the design wants some padding on the left + + .mx_InviteDialog_addressBar { + margin-right: 0; + } .mx_InviteDialog_userSections { height: calc(100% - 115px); // mx_InviteDialog's height minus some for the upper and lower elements + padding-right: 0; + + .mx_InviteDialog_section { + padding-bottom: 0; + margin-top: 12px; + } + } + + .mx_InviteDialog_hasFooter { + .mx_InviteDialog_userSections { + height: calc(100% - 175px); // For displaying an invite link on the footer of the dialog + } } } @@ -432,3 +445,7 @@ limitations under the License. } } } + +.mx_InviteDialog_identityServer { + margin-top: 1em; +} diff --git a/res/css/views/dialogs/_JoinRuleDropdown.scss b/res/css/views/dialogs/_JoinRuleDropdown.scss index 19209e95361..b4d13909a77 100644 --- a/res/css/views/dialogs/_JoinRuleDropdown.scss +++ b/res/css/views/dialogs/_JoinRuleDropdown.scss @@ -60,7 +60,7 @@ limitations under the License. } .mx_JoinRuleDropdown_restricted::before { - mask-image: url('$(res)/img/element-icons/community-members.svg'); + mask-image: url('$(res)/img/element-icons/group-members.svg'); mask-size: contain; } } diff --git a/res/css/views/dialogs/_LeaveSpaceDialog.scss b/res/css/views/dialogs/_LeaveSpaceDialog.scss index baae73a90b9..aa20efe89a8 100644 --- a/res/css/views/dialogs/_LeaveSpaceDialog.scss +++ b/res/css/views/dialogs/_LeaveSpaceDialog.scss @@ -19,58 +19,49 @@ limitations under the License. display: flex; flex-direction: column; padding: 24px 32px; - } -} -.mx_LeaveSpaceDialog { - width: 440px; - display: flex; - flex-direction: column; - flex-wrap: nowrap; - height: 520px; + .mx_LeaveSpaceDialog { + width: 440px; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + height: 520px; - .mx_Dialog_content { - flex-grow: 1; - margin: 0; - overflow-y: auto; + .mx_Dialog_content { + flex-grow: 1; + margin: 0; + overflow-y: auto; - .mx_LeaveSpaceDialog_section_warning { - position: relative; - border-radius: 8px; - margin: 12px 0 0; - padding: 12px 8px 12px 42px; - background-color: $header-panel-bg-color; + .mx_LeaveSpaceDialog_section_warning { + position: relative; + border-radius: 8px; + margin: 12px 0 0; + padding: 12px 8px 12px 42px; + background-color: $header-panel-bg-color; - font-size: $font-12px; - line-height: $font-15px; - color: $secondary-content; + font-size: $font-12px; + line-height: $font-15px; + color: $secondary-content; - &::before { - content: ''; - position: absolute; - left: 10px; - top: calc(50% - 8px); // vertical centering - height: 16px; - width: 16px; - background-color: $secondary-content; - mask-repeat: no-repeat; - mask-size: contain; - mask-image: url('$(res)/img/element-icons/room/room-summary.svg'); - mask-position: center; - } - } + &::before { + content: ''; + position: absolute; + left: 10px; + top: calc(50% - 8px); // vertical centering + height: 16px; + width: 16px; + background-color: $secondary-content; + mask-repeat: no-repeat; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/room/room-summary.svg'); + mask-position: center; + } + } - > p { - color: $primary-content; - } - } - - .mx_Dialog_buttons { - margin-top: 20px; - - .mx_Dialog_primary { - background-color: $alert !important; // override default colour - border-color: $alert; + > p { + color: $primary-content; + } + } } } } diff --git a/res/css/views/dialogs/_LocationViewDialog.scss b/res/css/views/dialogs/_LocationViewDialog.scss index e7cdaf88007..600c3082657 100644 --- a/res/css/views/dialogs/_LocationViewDialog.scss +++ b/res/css/views/dialogs/_LocationViewDialog.scss @@ -48,49 +48,10 @@ limitations under the License. background-color: $dialog-close-external-color; } } +} - .mx_MLocationBody { - position: absolute; - - .mx_MLocationBody_map { - width: 80vw; - height: 80vh; - } - - .mx_MLocationBody_zoomButtons { - position: absolute; - display: grid; - grid-template-columns: auto; - grid-row-gap: 8px; - - right: 24px; - bottom: 48px; - - .mx_AccessibleButton { - background-color: $background; - box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.25); - border-radius: 4px; - width: 24px; - height: 24px; - - .mx_MLocationBody_zoomButton { - background-color: $primary-content; - margin: 4px; - width: 16px; - height: 16px; - mask-repeat: no-repeat; - mask-size: contain; - mask-position: center; - } - - .mx_MLocationBody_plusButton { - mask-image: url('$(res)/img/element-icons/plus-button.svg'); - } - - .mx_MLocationBody_minusButton { - mask-image: url('$(res)/img/element-icons/minus-button.svg'); - } - } - } - } +.mx_LocationViewDialog_map { + width: 80vw; + height: 80vh; + border-radius: 8px; } diff --git a/res/css/views/dialogs/_RoomSettingsDialogBridges.scss b/res/css/views/dialogs/_RoomSettingsDialogBridges.scss index f18b4917cf1..07735ad0278 100644 --- a/res/css/views/dialogs/_RoomSettingsDialogBridges.scss +++ b/res/css/views/dialogs/_RoomSettingsDialogBridges.scss @@ -22,84 +22,99 @@ limitations under the License. margin: 0; padding: 0; } -} -.mx_RoomSettingsDialog_BridgeList li { - list-style-type: none; - padding: 5px; - margin-bottom: 8px; - border-width: 1px 1px; - border-color: $primary-hairline-color; - border-style: solid; - border-radius: 5px; + li { + list-style-type: none; - .column-icon { - float: left; - padding-right: 10px; + &.mx_RoomSettingsDialog_BridgeList_listItem { + display: flex; + flex-wrap: wrap; + gap: $spacing-8; + padding: 5px; + margin-bottom: $spacing-8; - * { + // border-style around each bridge list item + border-width: 1px 1px; + border-color: $primary-hairline-color; + border-style: solid; border-radius: 5px; - border: 1px solid $input-darker-bg-color; - } - - .noProtocolIcon { - width: 48px; - height: 48px; - background: $input-darker-bg-color; - border-radius: 5px; - } - .protocol-icon { - float: left; - margin-right: 5px; - img { - border-radius: 5px; - border-width: 1px 1px; - border-color: $primary-hairline-color; + .mx_RoomSettingsDialog_column_icon { + .mx_RoomSettingsDialog_protocolIcon, + .mx_RoomSettingsDialog_protocolIcon span, + .mx_RoomSettingsDialog_noProtocolIcon { + box-sizing: border-box; + border-radius: 5px; + border: 1px solid $input-darker-bg-color; + } + + .mx_RoomSettingsDialog_noProtocolIcon, + .mx_RoomSettingsDialog_protocolIcon img { + border-radius: 5px; + } + + .mx_RoomSettingsDialog_noProtocolIcon { + width: 48px; + height: 48px; + background: $input-darker-bg-color; + } + + .mx_RoomSettingsDialog_protocolIcon { + img { + border-width: 1px 1px; + border-color: $primary-hairline-color; + } + + span { + /* Correct letter placement */ + left: auto; + } + } } - span { - /* Correct letter placement */ - left: auto; - } - } - } - - .column-data { - display: inline-block; - width: 85%; - - > h3 { - margin-top: 0px; - margin-bottom: 0px; - font-size: 16pt; - color: $primary-content; - } - - > * { - margin-top: 4px; - margin-bottom: 0; - } - - .workspace-channel-details { - color: $primary-content; - font-weight: 600; - - .channel { - margin-left: 5px; - } - } - .metadata { - color: $muted-fg-color; - margin-bottom: 0; - overflow-y: visible; - text-overflow: ellipsis; - white-space: normal; - padding: 0; - - > li { - padding: 0; - border: 0; + .mx_RoomSettingsDialog_column_data { + display: inline-block; + width: 85%; + + .mx_RoomSettingsDialog_column_data_details, + .mx_RoomSettingsDialog_column_data_metadata, + .mx_RoomSettingsDialog_column_data_metadata li, + .mx_RoomSettingsDialog_column_data_protocolName { + margin-bottom: 0; + } + + .mx_RoomSettingsDialog_column_data_details, + .mx_RoomSettingsDialog_column_data_metadata { + margin-top: $spacing-4; + } + + .mx_RoomSettingsDialog_column_data_metadata li { + margin-top: $spacing-8; + } + + .mx_RoomSettingsDialog_column_data_protocolName { + margin-top: 0; + font-size: 16pt; + color: $primary-content; + } + + .mx_RoomSettingsDialog_workspace_channel_details { + color: $primary-content; + font-weight: $font-semi-bold; + + .mx_RoomSettingsDialog_channel { + margin-inline-start: 5px; + } + } + + .mx_RoomSettingsDialog_metadata { + color: $muted-fg-color; + margin-bottom: 0; + overflow-y: visible; + text-overflow: ellipsis; + white-space: normal; + padding: 0; + } } } } diff --git a/res/css/views/dialogs/_SpaceSettingsDialog.scss b/res/css/views/dialogs/_SpaceSettingsDialog.scss index 8f064f6b380..ead082dba68 100644 --- a/res/css/views/dialogs/_SpaceSettingsDialog.scss +++ b/res/css/views/dialogs/_SpaceSettingsDialog.scss @@ -76,11 +76,13 @@ limitations under the License. } .mx_AccessibleButton_hasKind { - padding: 8px 22px; + &.mx_AccessibleButton_kind_link { + font-size: $font-14px; + margin: 7px 18px; - &.mx_SettingsTab_showAdvanced { - margin: 16px 0; - padding: 0; + &.mx_SettingsTab_showAdvanced { + margin: 18px 0; + } } } diff --git a/res/css/views/dialogs/_SpotlightDialog.scss b/res/css/views/dialogs/_SpotlightDialog.scss index 31358ad8a3b..9f78d905b52 100644 --- a/res/css/views/dialogs/_SpotlightDialog.scss +++ b/res/css/views/dialogs/_SpotlightDialog.scss @@ -100,6 +100,7 @@ limitations under the License. display: flex; white-space: nowrap; overflow-x: hidden; + margin-right: 1px; // occlude the 1px visible of the very next tile to prevent it looking broken } .mx_AccessibleButton { @@ -109,15 +110,16 @@ limitations under the License. font-size: $font-12px; line-height: $font-15px; display: inline-block; - width: 50px; - min-width: 50px; + width: 58px; + height: 58px; + min-width: 58px; box-sizing: border-box; text-align: center; overflow: hidden; text-overflow: ellipsis; .mx_DecoratedRoomAvatar { - margin: 0 5px 4px; // maintain centering + margin: 0 9px 4px; // maintain centering } & + .mx_AccessibleButton { @@ -150,8 +152,8 @@ limitations under the License. > .mx_DecoratedRoomAvatar, > .mx_BaseAvatar { margin-right: 8px; - width: 20px; - height: 20px; + width: 24px; + height: 24px; .mx_BaseAvatar { width: inherit; @@ -186,8 +188,8 @@ limitations under the License. mask-repeat: no-repeat; mask-position: center; mask-size: contain; - width: 20px; - height: 20px; + width: 24px; + height: 24px; position: absolute; left: 4px; top: 50%; @@ -214,9 +216,8 @@ limitations under the License. .mx_SpotlightDialog_otherSearches_messageSearchIcon { display: inline-block; - margin-left: 8px; - width: 20px; - height: 20px; + width: 24px; + height: 24px; background-color: $secondary-content; vertical-align: text-bottom; mask-repeat: no-repeat; @@ -240,7 +241,6 @@ limitations under the License. .mx_SpotlightDialog_recentSearches > h4 > .mx_AccessibleButton_kind_link { padding: 0; float: right; - font-weight: normal; font-size: $font-12px; line-height: $font-15px; color: $secondary-content; diff --git a/res/css/views/dialogs/_UserSettingsDialog.scss b/res/css/views/dialogs/_UserSettingsDialog.scss index b013b4998af..79cacb5c507 100644 --- a/res/css/views/dialogs/_UserSettingsDialog.scss +++ b/res/css/views/dialogs/_UserSettingsDialog.scss @@ -60,7 +60,3 @@ limitations under the License. .mx_UserSettingsDialog_mjolnirIcon::before { mask-image: url('$(res)/img/element-icons/room/composer/emoji.svg'); } - -.mx_UserSettingsDialog_flairIcon::before { - mask-image: url('$(res)/img/element-icons/settings/flair.svg'); -} diff --git a/res/css/views/dialogs/security/_AccessSecretStorageDialog.scss b/res/css/views/dialogs/security/_AccessSecretStorageDialog.scss index e8bde18232a..609c022f855 100644 --- a/res/css/views/dialogs/security/_AccessSecretStorageDialog.scss +++ b/res/css/views/dialogs/security/_AccessSecretStorageDialog.scss @@ -18,6 +18,8 @@ limitations under the License. position: relative; padding-left: 24px; // 16px icon + 8px padding margin-top: 7px; // vertical alignment to buttons + margin-bottom: 7px; // space between the buttons and the text when float is activated + text-align: left; &::before { content: ""; diff --git a/res/css/views/elements/_AccessibleButton.scss b/res/css/views/elements/_AccessibleButton.scss index bf5440d6829..021e8ffc8c1 100644 --- a/res/css/views/elements/_AccessibleButton.scss +++ b/res/css/views/elements/_AccessibleButton.scss @@ -16,152 +16,159 @@ limitations under the License. .mx_AccessibleButton { cursor: pointer; -} - -.mx_AccessibleButton_disabled { - cursor: default; -} - -.mx_AccessibleButton_hasKind { - padding: 7px 18px; - text-align: center; - border-radius: 8px; - display: inline-flex; - align-items: center; - justify-content: center; - font-size: $font-14px; - border: none; // override default