diff --git a/.buildkite/pipeline.yaml b/.buildkite/pipeline.yaml deleted file mode 100644 index 4bc69a76bd..0000000000 --- a/.buildkite/pipeline.yaml +++ /dev/null @@ -1,119 +0,0 @@ -steps: - - label: ":eslint: JS Lint" - command: - # We fetch the develop js-sdk to get our latest eslint rules - - "echo '--- Install js-sdk'" - - "./scripts/ci/install-deps.sh --ignore-scripts" - - "echo '+++ Lint'" - - "yarn lint:js" - plugins: - - docker#v3.0.1: - image: "node:12" - - - label: ":eslint: TS Lint" - command: - - "echo '--- Install'" - - "yarn install --ignore-scripts" - - "echo '+++ Lint'" - - "yarn lint:ts" - plugins: - - docker#v3.0.1: - image: "node:12" - - - label: ":eslint: Types Lint" - command: - - "echo '--- Install'" - - "yarn install --ignore-scripts" - - "echo '+++ Lint'" - - "yarn lint:types" - plugins: - - docker#v3.0.1: - image: "node:12" - - label: ":stylelint: Style Lint" - command: - - "echo '--- Install'" - - "yarn install --ignore-scripts" - - "yarn lint:style" - plugins: - - docker#v3.0.1: - image: "node:12" - - - label: ":jest: Tests" - agents: - # We use a medium sized instance instead of the normal small ones because - # webpack loves to gorge itself on resources. - queue: "medium" - command: - - "echo '--- Install js-sdk'" - # We don't use the babel-ed output for anything so we can --ignore-scripts - # to save transpiling the files. We run the transpile step explicitly in - # the 'build' job. - - "./scripts/ci/install-deps.sh --ignore-scripts" - - "yarn run reskindex" - - "echo '+++ Running Tests'" - - "yarn test" - plugins: - - docker#v3.0.1: - image: "node:12" - - - label: "🛠 Build" - command: - - "echo '+++ Install & Build'" - - "yarn install" - plugins: - - docker#v3.0.1: - image: "node:12" - - - label: ":chains: End-to-End Tests" - agents: - # We use a xlarge sized instance instead of the normal small ones because - # e2e tests otherwise take +-8min - queue: "xlarge" - command: - - "echo '--- Install js-sdk'" - - "./scripts/ci/install-deps.sh --ignore-scripts" - - "echo '+++ Running Tests'" - - "./scripts/ci/end-to-end-tests.sh" - plugins: - - docker#v3.0.1: - image: "matrixdotorg/riotweb-ci-e2etests-env:latest" - propagate-environment: true - workdir: "/workdir/matrix-react-sdk" - retry: - automatic: - - exit_status: 1 # retry end-to-end tests once as Puppeteer sometimes fails - limit: 1 - - - label: "🔧 Riot Tests" - agents: - # We use a medium sized instance instead of the normal small ones because - # webpack loves to gorge itself on resources. - queue: "medium" - command: - - "echo '+++ Running Tests'" - - "./scripts/ci/riot-unit-tests.sh" - plugins: - - docker#v3.0.1: - image: "node:10" - propagate-environment: true - workdir: "/workdir/matrix-react-sdk" - - - label: "🌐 i18n" - command: - - "echo '--- Fetching Dependencies'" - - "yarn install --ignore-scripts" - - "echo '+++ Testing i18n output'" - - "yarn diff-i18n" - plugins: - - docker#v3.0.1: - image: "node:10" - - - wait - - - label: "🐴 Trigger riot-web" - trigger: "riot-web" - branches: "develop" - build: - branch: "develop" - message: "[react-sdk] ${BUILDKITE_MESSAGE}" - async: true diff --git a/.eslintignore b/.eslintignore index c4c7fe5067..c4f7298047 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,4 @@ src/component-index.js +test/end-to-end-tests/node_modules/ +test/end-to-end-tests/riot/ +test/end-to-end-tests/synapse/ diff --git a/.eslintignore.errorfiles b/.eslintignore.errorfiles index e326f15002..ffc3b21181 100644 --- a/.eslintignore.errorfiles +++ b/.eslintignore.errorfiles @@ -1,6 +1,5 @@ # autogenerated file: run scripts/generate-eslint-error-ignore-file to update. -src/component-index.js src/components/structures/RoomDirectory.js src/components/structures/RoomStatusBar.js src/components/structures/RoomView.js @@ -9,7 +8,6 @@ src/components/structures/SearchBox.js src/components/structures/UploadBar.js src/components/views/avatars/MemberAvatar.js src/components/views/create_room/RoomAlias.js -src/components/views/dialogs/DeactivateAccountDialog.js src/components/views/dialogs/SetPasswordDialog.js src/components/views/dialogs/UnknownDeviceDialog.js src/components/views/elements/AddressSelector.js @@ -30,7 +28,6 @@ src/components/views/rooms/MemberInfo.js src/components/views/rooms/MemberList.js src/components/views/rooms/RoomList.js src/components/views/rooms/RoomPreviewBar.js -src/components/views/rooms/SearchBar.js src/components/views/rooms/SearchResultTile.js src/components/views/settings/ChangeAvatar.js src/components/views/settings/ChangePassword.js @@ -43,7 +40,6 @@ src/notifications/ContentRules.js src/notifications/PushRuleVectorState.js src/PlatformPeg.js src/rageshake/rageshake.js -src/rageshake/submit-rageshake.js src/ratelimitedfunc.js src/Rooms.js src/Unread.js @@ -59,4 +55,7 @@ test/components/views/dialogs/InteractiveAuthDialog-test.js test/mock-clock.js test/notifications/ContentRules-test.js test/notifications/PushRuleVectorState-test.js -test/stores/RoomViewStore-test.js +src/component-index.js +test/end-to-end-tests/node_modules/ +test/end-to-end-tests/riot/ +test/end-to-end-tests/synapse/ diff --git a/CHANGELOG.md b/CHANGELOG.md index fa02dc1ae3..0706e20085 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,766 @@ +Changes in [2.5.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0) (2020-05-05) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.6...v2.5.0) + + * Upgrade to JS SDK 6.0.0 + * EventIndex: Reduce the logging the event index is producing. + [\#4551](https://github.com/matrix-org/matrix-react-sdk/pull/4551) + * Differentiate copy for own untrusted device dialog + [\#4550](https://github.com/matrix-org/matrix-react-sdk/pull/4550) + * More detailed progress for key backup progress + [\#4545](https://github.com/matrix-org/matrix-react-sdk/pull/4545) + * Increase rageshake size limit to 5mb + [\#4544](https://github.com/matrix-org/matrix-react-sdk/pull/4544) + +Changes in [2.5.0-rc.6](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.6) (2020-05-01) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.5...v2.5.0-rc.6) + + * Upgrade to JS SDK 6.0.0-rc.2 + * Wait for user to be verified in e2e setup + [\#4538](https://github.com/matrix-org/matrix-react-sdk/pull/4538) + * Add device name to unverified session toast + [\#4536](https://github.com/matrix-org/matrix-react-sdk/pull/4536) + +Changes in [2.5.0-rc.5](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.5) (2020-04-30) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.4...v2.5.0-rc.5) + + * Upgrade to JS SDK 6.0.0-rc.1 + * Fix device verification toasts not disappearing + [\#4533](https://github.com/matrix-org/matrix-react-sdk/pull/4533) + * Allow resetting storage from the access dialog + [\#4526](https://github.com/matrix-org/matrix-react-sdk/pull/4526) + * Update toast copy again + [\#4530](https://github.com/matrix-org/matrix-react-sdk/pull/4530) + * Reduce maximum width of toasts & allow multiple lines + [\#4528](https://github.com/matrix-org/matrix-react-sdk/pull/4528) + * Treat sessions that are there when we log in as old + [\#4527](https://github.com/matrix-org/matrix-react-sdk/pull/4527) + * Update (bulk) unverified device toast copy + [\#4523](https://github.com/matrix-org/matrix-react-sdk/pull/4523) + * Make new device toasts appear above review toasts + [\#4520](https://github.com/matrix-org/matrix-react-sdk/pull/4520) + * Separate toasts for existing & new device verification + [\#4517](https://github.com/matrix-org/matrix-react-sdk/pull/4517) + * Aggregate device verify toasts + [\#4516](https://github.com/matrix-org/matrix-react-sdk/pull/4516) + * Fix set up encryption toast to use "set up" as action + [\#4515](https://github.com/matrix-org/matrix-react-sdk/pull/4515) + * Fix internal link styling in Security Settings + [\#4512](https://github.com/matrix-org/matrix-react-sdk/pull/4512) + * Don't enable e2ee when inviting a 3pid + [\#4513](https://github.com/matrix-org/matrix-react-sdk/pull/4513) + * only clear on continuations where the clear isn't done by SenderProfile + [\#4505](https://github.com/matrix-org/matrix-react-sdk/pull/4505) + * cap width of editable item list item to leave space for its X button + [\#4504](https://github.com/matrix-org/matrix-react-sdk/pull/4504) + * Add a link from settings / devices to your user profile + [\#4499](https://github.com/matrix-org/matrix-react-sdk/pull/4499) + * Make icon change in SetupEncryptionDialog + [\#4490](https://github.com/matrix-org/matrix-react-sdk/pull/4490) + * Remove invite only padlocks feature flag for release + [\#4488](https://github.com/matrix-org/matrix-react-sdk/pull/4488) + * Fix incorrect toast if security setup skipped + [\#4489](https://github.com/matrix-org/matrix-react-sdk/pull/4489) + * Revert "Update emojibase for fixed emoji codepoints and Emoji 13 support" + [\#4483](https://github.com/matrix-org/matrix-react-sdk/pull/4483) + * Fix recovery link on login verification flow + [\#4480](https://github.com/matrix-org/matrix-react-sdk/pull/4480) + +Changes in [2.5.0-rc.4](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.4) (2020-04-23) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.3...v2.5.0-rc.4) + + * Upgrade to JS SDK 5.3.1-rc.4 + * Take encrypted message search out of labs for release + [\#4468](https://github.com/matrix-org/matrix-react-sdk/pull/4468) + * Update login security copy and design to match Figma [to release] + [\#4474](https://github.com/matrix-org/matrix-react-sdk/pull/4474) + * Fix i18n of SSO UIA copy in Deactivate Account Dialog on release + [\#4473](https://github.com/matrix-org/matrix-react-sdk/pull/4473) + * Skip auth flow test for signing upload when password present + [\#4465](https://github.com/matrix-org/matrix-react-sdk/pull/4465) + * Fix: wait until cross-signing keys are fetched to show verify button + [\#4457](https://github.com/matrix-org/matrix-react-sdk/pull/4457) + * Handle load error in create secret storage dialog + [\#4454](https://github.com/matrix-org/matrix-react-sdk/pull/4454) + * Don't recheck DeviceListener until after initial sync is finished + [\#4450](https://github.com/matrix-org/matrix-react-sdk/pull/4450) + * EventIndex: Filter out events that don't have a propper content value. + [\#4447](https://github.com/matrix-org/matrix-react-sdk/pull/4447) + +Changes in [2.5.0-rc.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.3) (2020-04-17) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.2...v2.5.0-rc.3) + + * Upgrade to JS SDK 5.3.1-rc.3 + +Changes in [2.5.0-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.2) (2020-04-16) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.1...v2.5.0-rc.2) + + * Upgrade to JS SDK 5.3.1-rc.2 + * [Release] Convert cross-signing flag to a setting + [\#4429](https://github.com/matrix-org/matrix-react-sdk/pull/4429) + * Iterate cross-signing copy + [\#4426](https://github.com/matrix-org/matrix-react-sdk/pull/4426) + * Fix: ensure twemoji font is loaded when showing SAS emojis + [\#4423](https://github.com/matrix-org/matrix-react-sdk/pull/4423) + +Changes in [2.5.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.1) (2020-04-15) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.4.0-rc.1...v2.5.0-rc.1) + + * Upgrade to JS SDK 5.3.1-rc.1 + * null-guard MatrixClientPeg in RoomViewStore + [\#4415](https://github.com/matrix-org/matrix-react-sdk/pull/4415) + * Fix: prevent spurious notifications from indexer + [\#4414](https://github.com/matrix-org/matrix-react-sdk/pull/4414) + * Login block on initialSync with spinners + [\#4413](https://github.com/matrix-org/matrix-react-sdk/pull/4413) + * Allow network dropdown to be scrollable and fix context menu padding calc + [\#4408](https://github.com/matrix-org/matrix-react-sdk/pull/4408) + * Remove end-to-end message info option when cross-signing is used + [\#4412](https://github.com/matrix-org/matrix-react-sdk/pull/4412) + * Minimize widgets by default + [\#4378](https://github.com/matrix-org/matrix-react-sdk/pull/4378) + * Add comments to highlight where we'll need m.widget support + [\#4380](https://github.com/matrix-org/matrix-react-sdk/pull/4380) + * Fix: dont try to enable 4S if cross-signing is disabled + [\#4407](https://github.com/matrix-org/matrix-react-sdk/pull/4407) + * Fix: don't confuse user with spinner during complete security step + [\#4406](https://github.com/matrix-org/matrix-react-sdk/pull/4406) + * Fix: avoid potential crash during certain verification paths + [\#4405](https://github.com/matrix-org/matrix-react-sdk/pull/4405) + * Add riot-desktop shortcuts for forward/back matching browsers&slack + [\#4392](https://github.com/matrix-org/matrix-react-sdk/pull/4392) + * Convert LoggedInView to an ES6 PureComponent Class & TypeScript + [\#4398](https://github.com/matrix-org/matrix-react-sdk/pull/4398) + * Fix width of MVideoBody in FilePanel + [\#4396](https://github.com/matrix-org/matrix-react-sdk/pull/4396) + * Remove unused react-addons-css-transition-group + [\#4397](https://github.com/matrix-org/matrix-react-sdk/pull/4397) + * Fix emoji tooltip flickering + [\#4395](https://github.com/matrix-org/matrix-react-sdk/pull/4395) + * Pass along key backup for bootstrap + [\#4374](https://github.com/matrix-org/matrix-react-sdk/pull/4374) + * Fix create room dialog e2ee private room setting + [\#4403](https://github.com/matrix-org/matrix-react-sdk/pull/4403) + * Sort emoji by shortcodes for autocomplete primarily for :-1 and :+1 + [\#4391](https://github.com/matrix-org/matrix-react-sdk/pull/4391) + * Fix invalid commands when figuring out whether to set isTyping + [\#4390](https://github.com/matrix-org/matrix-react-sdk/pull/4390) + * op/deop return error if trying to affect an unknown user + [\#4389](https://github.com/matrix-org/matrix-react-sdk/pull/4389) + * Composer pills respect showPillAvatar setting + [\#4384](https://github.com/matrix-org/matrix-react-sdk/pull/4384) + * Only send typing notification when composing commands which send messages + [\#4385](https://github.com/matrix-org/matrix-react-sdk/pull/4385) + * Reverse order of they match/they don't match buttons + [\#4386](https://github.com/matrix-org/matrix-react-sdk/pull/4386) + * Use singular text on 'delete sessions' button for SSO + [\#4383](https://github.com/matrix-org/matrix-react-sdk/pull/4383) + * Pass widget data through from sticker picker + [\#4377](https://github.com/matrix-org/matrix-react-sdk/pull/4377) + * Obliterate widgets when they are minimized + [\#4376](https://github.com/matrix-org/matrix-react-sdk/pull/4376) + * Fix image thumbnail width when read receipts are hidden + [\#4370](https://github.com/matrix-org/matrix-react-sdk/pull/4370) + * Add toggle for e2ee when creating private room + [\#4362](https://github.com/matrix-org/matrix-react-sdk/pull/4362) + * Fix logging for failed searches + [\#4372](https://github.com/matrix-org/matrix-react-sdk/pull/4372) + * Ensure UI is updated when cross-signing gets disabled + [\#4369](https://github.com/matrix-org/matrix-react-sdk/pull/4369) + * Retry the request for the master key from SSSS on login + [\#4371](https://github.com/matrix-org/matrix-react-sdk/pull/4371) + * Upgrade deps + [\#4365](https://github.com/matrix-org/matrix-react-sdk/pull/4365) + * App load tweaks, i18n and localStorage + [\#4367](https://github.com/matrix-org/matrix-react-sdk/pull/4367) + * Fix encoding of widget arguments + [\#4366](https://github.com/matrix-org/matrix-react-sdk/pull/4366) + +Changes in [2.4.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.4.0-rc.1) (2020-04-08) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.3.1...v2.4.0-rc.1) + + * Upgrade to JS SDK to 5.3.0-rc.1 + * EventIndex: Log if we had all events in a checkpoint but are continuing. + [\#4363](https://github.com/matrix-org/matrix-react-sdk/pull/4363) + * Update from Weblate + [\#4364](https://github.com/matrix-org/matrix-react-sdk/pull/4364) + * Support deactivating your account with SSO + [\#4356](https://github.com/matrix-org/matrix-react-sdk/pull/4356) + * Add debug status for cached backup key format + [\#4359](https://github.com/matrix-org/matrix-react-sdk/pull/4359) + * Fix composer placeholder not updating + [\#4361](https://github.com/matrix-org/matrix-react-sdk/pull/4361) + * Fix sas verification buttons to match figma + [\#4358](https://github.com/matrix-org/matrix-react-sdk/pull/4358) + * Don't show fallback text for verification requests + [\#4345](https://github.com/matrix-org/matrix-react-sdk/pull/4345) + * Fix share dialog correctly + [\#4360](https://github.com/matrix-org/matrix-react-sdk/pull/4360) + * Use singular copy when only deleting one device + [\#4357](https://github.com/matrix-org/matrix-react-sdk/pull/4357) + * Deem m.sticker events as actionable for reacting + [\#4288](https://github.com/matrix-org/matrix-react-sdk/pull/4288) + * Don't show spinner over encryption setup dialogs + [\#4354](https://github.com/matrix-org/matrix-react-sdk/pull/4354) + * Support Jitsi information from client .well-known + [\#4348](https://github.com/matrix-org/matrix-react-sdk/pull/4348) + * Add new default home page fallback + [\#4350](https://github.com/matrix-org/matrix-react-sdk/pull/4350) + * Check more account data in toast listener + [\#4351](https://github.com/matrix-org/matrix-react-sdk/pull/4351) + * Don't try to send presence updates until the client is started + [\#4353](https://github.com/matrix-org/matrix-react-sdk/pull/4353) + * Fix copy button on code blocks when there is no code tag just pre + [\#4352](https://github.com/matrix-org/matrix-react-sdk/pull/4352) + * Clear sessionStorage on sign out + [\#4346](https://github.com/matrix-org/matrix-react-sdk/pull/4346) + * Re-request room keys after auth + [\#4341](https://github.com/matrix-org/matrix-react-sdk/pull/4341) + * Update emojibase for fixed emoji codepoints and Emoji 13 support + [\#4344](https://github.com/matrix-org/matrix-react-sdk/pull/4344) + * App load order tweaks for code splitting + [\#4343](https://github.com/matrix-org/matrix-react-sdk/pull/4343) + * Fix alignment of e2e icon in userinfo and expose full displayname in title + [\#4312](https://github.com/matrix-org/matrix-react-sdk/pull/4312) + * Adjust copy & UX for self-verification + [\#4342](https://github.com/matrix-org/matrix-react-sdk/pull/4342) + * QR code reciprocation + [\#4334](https://github.com/matrix-org/matrix-react-sdk/pull/4334) + * Fix Hangul typing does not work properly + [\#4339](https://github.com/matrix-org/matrix-react-sdk/pull/4339) + * Fix: dismiss setup encryption toast if cross-signing is ready + [\#4336](https://github.com/matrix-org/matrix-react-sdk/pull/4336) + * Fix read marker visibility for grouped events + [\#4340](https://github.com/matrix-org/matrix-react-sdk/pull/4340) + * Make all 'font-size's and 'line-height's rem + [\#4305](https://github.com/matrix-org/matrix-react-sdk/pull/4305) + * Fix spurious extra devices on registration + [\#4337](https://github.com/matrix-org/matrix-react-sdk/pull/4337) + * Fix the edit messager composer + [\#4333](https://github.com/matrix-org/matrix-react-sdk/pull/4333) + * Fix Room Settings Dialog Notifications tab icon + [\#4321](https://github.com/matrix-org/matrix-react-sdk/pull/4321) + * Fix various cases of React warnings by silencing them + [\#4331](https://github.com/matrix-org/matrix-react-sdk/pull/4331) + * Only apply padding to standard textual buttons (kind buttons) + [\#4332](https://github.com/matrix-org/matrix-react-sdk/pull/4332) + * Use console.log in place of console.warn for less warnings + [\#4330](https://github.com/matrix-org/matrix-react-sdk/pull/4330) + * Revert componentDidMount changes on breadcrumbs + [\#4329](https://github.com/matrix-org/matrix-react-sdk/pull/4329) + * Use new method for checking secret storage key + [\#4309](https://github.com/matrix-org/matrix-react-sdk/pull/4309) + * Label and use UNSAFE_componentWillMount to minimize warnings + [\#4315](https://github.com/matrix-org/matrix-react-sdk/pull/4315) + * Fix a number of minor code quality issues + [\#4314](https://github.com/matrix-org/matrix-react-sdk/pull/4314) + * Use componentDidMount in place of componentWillMount where possible + [\#4313](https://github.com/matrix-org/matrix-react-sdk/pull/4313) + * EventIndex: Mark the initial checkpoints for a full crawl. + [\#4325](https://github.com/matrix-org/matrix-react-sdk/pull/4325) + * Fix UserInfo e2e buttons to match Figma + [\#4320](https://github.com/matrix-org/matrix-react-sdk/pull/4320) + * Only auto-scroll to RoomTile when clicking on RoomTile or via shortcuts + [\#4316](https://github.com/matrix-org/matrix-react-sdk/pull/4316) + * Support SSO for interactive authentication + [\#4292](https://github.com/matrix-org/matrix-react-sdk/pull/4292) + * Fix /invite Slash Command + [\#4328](https://github.com/matrix-org/matrix-react-sdk/pull/4328) + * Fix jitsi popout URL + [\#4326](https://github.com/matrix-org/matrix-react-sdk/pull/4326) + * Use our own jitsi widget for the popout URL + [\#4323](https://github.com/matrix-org/matrix-react-sdk/pull/4323) + * Fix popout support for jitsi widgets + [\#4319](https://github.com/matrix-org/matrix-react-sdk/pull/4319) + * Fix: legacy verify user throwing error + [\#4318](https://github.com/matrix-org/matrix-react-sdk/pull/4318) + * Document settingDefaults + [\#3046](https://github.com/matrix-org/matrix-react-sdk/pull/3046) + * Fix Ctrl+/ for Finnish keyboard where it includes Shift + [\#4317](https://github.com/matrix-org/matrix-react-sdk/pull/4317) + * Rework SlashCommands to better expose aliases + [\#4302](https://github.com/matrix-org/matrix-react-sdk/pull/4302) + * Fix EventListSummary when RR rendering is disabled + [\#4311](https://github.com/matrix-org/matrix-react-sdk/pull/4311) + * Update link to css location. + [\#4299](https://github.com/matrix-org/matrix-react-sdk/pull/4299) + * Fix peeking keeping two timeline update mechanisms in play + [\#4310](https://github.com/matrix-org/matrix-react-sdk/pull/4310) + * Pass new secret storage key to bootstrap path + [\#4308](https://github.com/matrix-org/matrix-react-sdk/pull/4308) + * Show red shield for users that become unverified + [\#4303](https://github.com/matrix-org/matrix-react-sdk/pull/4303) + * Accessibility fixed for Event List Summary and Composer Format Bar + [\#4295](https://github.com/matrix-org/matrix-react-sdk/pull/4295) + * Support $riot: Templates for SSO/CAS urls in the welcome.html page + [\#4279](https://github.com/matrix-org/matrix-react-sdk/pull/4279) + * Added the /html command + [\#4296](https://github.com/matrix-org/matrix-react-sdk/pull/4296) + * EventIndex: Better logging on how many events are added. + [\#4301](https://github.com/matrix-org/matrix-react-sdk/pull/4301) + * Field: mark id as optional in propTypes + [\#4307](https://github.com/matrix-org/matrix-react-sdk/pull/4307) + * Fix view community link icon contrast + [\#4254](https://github.com/matrix-org/matrix-react-sdk/pull/4254) + * Remove underscore from Jitsi conference names + [\#4304](https://github.com/matrix-org/matrix-react-sdk/pull/4304) + * Refactor shield display logic; changed rules for DMs + [\#4290](https://github.com/matrix-org/matrix-react-sdk/pull/4290) + * Fix: bring back global thin scrollbars + [\#4300](https://github.com/matrix-org/matrix-react-sdk/pull/4300) + * Keyboard shortcuts: Escape cancel reply and fix Ctrl+K + [\#4297](https://github.com/matrix-org/matrix-react-sdk/pull/4297) + * Field: make id optional, generate one if not provided + [\#4298](https://github.com/matrix-org/matrix-react-sdk/pull/4298) + * Fix ugly scrollbars in TabbedView (settings), emojipicker and widgets + [\#4293](https://github.com/matrix-org/matrix-react-sdk/pull/4293) + * Rename secret storage force-reset variable to avoid confusion + [\#4274](https://github.com/matrix-org/matrix-react-sdk/pull/4274) + * Fix: can't dismiss unverified session toast when encryption hasn't been + upgraded + [\#4291](https://github.com/matrix-org/matrix-react-sdk/pull/4291) + * Blank out UserInfo avatar when changing between members + [\#4289](https://github.com/matrix-org/matrix-react-sdk/pull/4289) + * Add cancel button to verification panel + [\#4283](https://github.com/matrix-org/matrix-react-sdk/pull/4283) + * Show ongoing verification request straight away when navigating to member + [\#4284](https://github.com/matrix-org/matrix-react-sdk/pull/4284) + * Fix: allow scrolling while window is not focused & remove scrollbar hack + [\#4276](https://github.com/matrix-org/matrix-react-sdk/pull/4276) + * Show whether backup key is cached + [\#4287](https://github.com/matrix-org/matrix-react-sdk/pull/4287) + * Rename unverified session toast + [\#4285](https://github.com/matrix-org/matrix-react-sdk/pull/4285) + * Fix: pick last active DM for verification request + [\#4286](https://github.com/matrix-org/matrix-react-sdk/pull/4286) + * Fix formatBar not hidden after highlight and backspacing some text + [\#4269](https://github.com/matrix-org/matrix-react-sdk/pull/4269) + +Changes in [2.3.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.3.1) (2020-04-01) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.3.0...v2.3.1) + + * Fix jitsi popout URL + [\#4327](https://github.com/matrix-org/matrix-react-sdk/pull/4327) + * Remove underscore from Jitsi conference names + [\#4324](https://github.com/matrix-org/matrix-react-sdk/pull/4324) + * Fix popout support for jitsi widgets + [\#4322](https://github.com/matrix-org/matrix-react-sdk/pull/4322) + +Changes in [2.3.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.3.0) (2020-03-30) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.3.0-rc.1...v2.3.0) + + * Upgrade JS SDK to 5.2.0 + +Changes in [2.3.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.3.0-rc.1) (2020-03-26) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.3...v2.3.0-rc.1) + + * Upgrade JS SDK to 5.2.0-rc.1 + * Add a flag to control whether cross-signing signatures are trusted + [\#4277](https://github.com/matrix-org/matrix-react-sdk/pull/4277) + * Update from Weblate + [\#4282](https://github.com/matrix-org/matrix-react-sdk/pull/4282) + * Update copy on SSSS symmetric upgrade toast + [\#4281](https://github.com/matrix-org/matrix-react-sdk/pull/4281) + * Wait for SSSS upgrade to complete + [\#4270](https://github.com/matrix-org/matrix-react-sdk/pull/4270) + * Update cross-signing verification copy and fix i18n + [\#4278](https://github.com/matrix-org/matrix-react-sdk/pull/4278) + * Fix soft-crash on bad permalinks + [\#4280](https://github.com/matrix-org/matrix-react-sdk/pull/4280) + * Fix: make self-verification wait for incoming request + [\#4267](https://github.com/matrix-org/matrix-react-sdk/pull/4267) + * Fall back to non-standard persisted api for Safari + [\#4272](https://github.com/matrix-org/matrix-react-sdk/pull/4272) + * Respond to backup key sharing requests + [\#4275](https://github.com/matrix-org/matrix-react-sdk/pull/4275) + * Log and display secret sharing cache state + [\#4268](https://github.com/matrix-org/matrix-react-sdk/pull/4268) + * Support sending config and ready events to capable widgets (Jitsi) + [\#4266](https://github.com/matrix-org/matrix-react-sdk/pull/4266) + * If cached keys are present in the key backup dialog, use them + [\#4273](https://github.com/matrix-org/matrix-react-sdk/pull/4273) + * Fix formatbar not hidden on highlighted message sent + [\#4265](https://github.com/matrix-org/matrix-react-sdk/pull/4265) + * Support Jitsi conferences sent/received on Riot Mobile and older Riot Webs + [\#4252](https://github.com/matrix-org/matrix-react-sdk/pull/4252) + * Use unified function to check cross-signing is ready + [\#4263](https://github.com/matrix-org/matrix-react-sdk/pull/4263) + * Migrate SSSS to symmetric + [\#4224](https://github.com/matrix-org/matrix-react-sdk/pull/4224) + * Migration to symmetric SSSS + [\#4242](https://github.com/matrix-org/matrix-react-sdk/pull/4242) + * Always display verification request toasts on top + [\#4262](https://github.com/matrix-org/matrix-react-sdk/pull/4262) + * Fix: assume SAS is supported when starting request with .start + [\#4249](https://github.com/matrix-org/matrix-react-sdk/pull/4249) + * Fix logout when Olm failed to load. + [\#4261](https://github.com/matrix-org/matrix-react-sdk/pull/4261) + * Improve naming of Jitsi conferences + [\#4251](https://github.com/matrix-org/matrix-react-sdk/pull/4251) + * Handle matrix.to user permalink in-room rather than solo + [\#4245](https://github.com/matrix-org/matrix-react-sdk/pull/4245) + * Fix: filter room list (again) by canonical and alternative aliases + [\#4260](https://github.com/matrix-org/matrix-react-sdk/pull/4260) + * EventIndex: Add some logging to the file panel populating. + [\#4250](https://github.com/matrix-org/matrix-react-sdk/pull/4250) + * Update from Weblate + [\#4259](https://github.com/matrix-org/matrix-react-sdk/pull/4259) + * Migrate RoomView to React Contexts in the hope for better temporal stability + [\#4258](https://github.com/matrix-org/matrix-react-sdk/pull/4258) + * Update WidgetUtils.js fix Jitsi path + [\#4256](https://github.com/matrix-org/matrix-react-sdk/pull/4256) + * Fix local jitsi build url fail and missing argument + [\#4255](https://github.com/matrix-org/matrix-react-sdk/pull/4255) + * Add shortcut CmdOrCtrl+. to toggle right panel + [\#4244](https://github.com/matrix-org/matrix-react-sdk/pull/4244) + * Improve Keyboard Shortcuts. Add alt-arrows & alt-shift-arrows + [\#4241](https://github.com/matrix-org/matrix-react-sdk/pull/4241) + * Bring back legacy verification by comparing public device keys + [\#4240](https://github.com/matrix-org/matrix-react-sdk/pull/4240) + * Searching: Return an empty result if the search term is an empty string. + [\#4248](https://github.com/matrix-org/matrix-react-sdk/pull/4248) + * Break continuation on showHiddenEvents-rendered events + [\#4247](https://github.com/matrix-org/matrix-react-sdk/pull/4247) + * Watch for show-RR settings changes, use room-specific and fix margins + [\#4246](https://github.com/matrix-org/matrix-react-sdk/pull/4246) + * Register Mac electron specific Cmd+, shortcut to User Settings + [\#4243](https://github.com/matrix-org/matrix-react-sdk/pull/4243) + * Use a local wrapper for Jitsi calls + [\#4234](https://github.com/matrix-org/matrix-react-sdk/pull/4234) + * Invite Dialog fixes + [\#4233](https://github.com/matrix-org/matrix-react-sdk/pull/4233) + * RoomPreviewBar word-break the sender name too + [\#4239](https://github.com/matrix-org/matrix-react-sdk/pull/4239) + * Report to the user when a key signature upload fails + [\#4229](https://github.com/matrix-org/matrix-react-sdk/pull/4229) + * pre-send megolm keys when possible when a user starts typing + [\#4235](https://github.com/matrix-org/matrix-react-sdk/pull/4235) + * we don't do mx_fadable anymore so get rid of broken RightPanel disabling + [\#4238](https://github.com/matrix-org/matrix-react-sdk/pull/4238) + * Fix left left panel overflowing vertically + [\#4237](https://github.com/matrix-org/matrix-react-sdk/pull/4237) + * Fix custom tags causing left panel to over-expand + [\#4236](https://github.com/matrix-org/matrix-react-sdk/pull/4236) + * Add Keyboard shortcuts dialog + [\#4231](https://github.com/matrix-org/matrix-react-sdk/pull/4231) + * Don't use buildkite agent to upload logs + [\#4232](https://github.com/matrix-org/matrix-react-sdk/pull/4232) + * Remove Gemini Scrollbars + [\#4217](https://github.com/matrix-org/matrix-react-sdk/pull/4217) + * Room Directory Explore Servers redesign + [\#4209](https://github.com/matrix-org/matrix-react-sdk/pull/4209) + * Fix redo keyboard shortcut on macOS + [\#4110](https://github.com/matrix-org/matrix-react-sdk/pull/4110) + * Fix: ensure local state for aliases doesn't get garbled up + [\#4230](https://github.com/matrix-org/matrix-react-sdk/pull/4230) + * Rename 'jump to bottom' to avoid ublock block + [\#4208](https://github.com/matrix-org/matrix-react-sdk/pull/4208) + * Restore key backup in background after complete security + [\#4225](https://github.com/matrix-org/matrix-react-sdk/pull/4225) + * Fix key backup trust text for cross-signing + [\#4223](https://github.com/matrix-org/matrix-react-sdk/pull/4223) + * Add default on config setting to control call button in composer + [\#4227](https://github.com/matrix-org/matrix-react-sdk/pull/4227) + * Fix: make alternative addresses UX less confusing + [\#4221](https://github.com/matrix-org/matrix-react-sdk/pull/4221) + * Wait for verification request on login + [\#4222](https://github.com/matrix-org/matrix-react-sdk/pull/4222) + * EventIndex: Add support to delete events from the index. + [\#4204](https://github.com/matrix-org/matrix-react-sdk/pull/4204) + * EventIndex: Remove a checkpoint if the HTTP request returns a 403. + [\#4214](https://github.com/matrix-org/matrix-react-sdk/pull/4214) + * Move to composer when typing letters with Shift held + [\#4216](https://github.com/matrix-org/matrix-react-sdk/pull/4216) + * Wrap large room names when previewing them + [\#4213](https://github.com/matrix-org/matrix-react-sdk/pull/4213) + * Rename Review Devices to Review Sessions + [\#4219](https://github.com/matrix-org/matrix-react-sdk/pull/4219) + * Fix typo in tabIndex to make React happy + [\#4215](https://github.com/matrix-org/matrix-react-sdk/pull/4215) + * Proof of concept for custom theme adding + [\#4148](https://github.com/matrix-org/matrix-react-sdk/pull/4148) + * Remove stuff that yarn install doesn't think we need + [\#4205](https://github.com/matrix-org/matrix-react-sdk/pull/4205) + * Declare jsx in tsconfig for IDEs + [\#4207](https://github.com/matrix-org/matrix-react-sdk/pull/4207) + * Fix: best-effort to join room without canonical alias over federation from + room directory + [\#4210](https://github.com/matrix-org/matrix-react-sdk/pull/4210) + * Test for cross-signing homeserver support during login, toasts + [\#4206](https://github.com/matrix-org/matrix-react-sdk/pull/4206) + * Send verification request to a single device in a way compatible with non- + cross-signing + [\#4202](https://github.com/matrix-org/matrix-react-sdk/pull/4202) + * Fixes for removing local alias + [\#4199](https://github.com/matrix-org/matrix-react-sdk/pull/4199) + * yarn upgrade + [\#4201](https://github.com/matrix-org/matrix-react-sdk/pull/4201) + * Support TypeScript for React components + [\#4203](https://github.com/matrix-org/matrix-react-sdk/pull/4203) + * When room name is changed, show both the old and new name + [\#4183](https://github.com/matrix-org/matrix-react-sdk/pull/4183) + +Changes in [2.2.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.3) (2020-03-17) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.3-rc.1...v2.2.3) + + * Upgrade JS SDK to 5.1.1 + * Add default on config setting to control call button in composer + [\#4228](https://github.com/matrix-org/matrix-react-sdk/pull/4228) + * Fix: make alternative addresses UX less confusing + [\#4226](https://github.com/matrix-org/matrix-react-sdk/pull/4226) + * Fix: best-effort to join room without canonical alias over federation from + room directory + [\#4211](https://github.com/matrix-org/matrix-react-sdk/pull/4211) + +Changes in [2.2.3-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.3-rc.1) (2020-03-11) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.1...v2.2.3-rc.1) + + * Update from Weblate + [\#4200](https://github.com/matrix-org/matrix-react-sdk/pull/4200) + * Revert "enable 4s when accepting a verification request" + [\#4198](https://github.com/matrix-org/matrix-react-sdk/pull/4198) + * Don't remount main split children on rhs collapse + [\#4197](https://github.com/matrix-org/matrix-react-sdk/pull/4197) + * Add fallback label for canonical alias events that dont change anything + [\#4195](https://github.com/matrix-org/matrix-react-sdk/pull/4195) + * Immediately switch to verification dialog when clicking [Continue] from new + session dialog + [\#4196](https://github.com/matrix-org/matrix-react-sdk/pull/4196) + * Enable 4S if needed when trying to verify or accepting verification + [\#4194](https://github.com/matrix-org/matrix-react-sdk/pull/4194) + * Remove extraneous tab stop from room tree view. + [\#4193](https://github.com/matrix-org/matrix-react-sdk/pull/4193) + * Remove v1 identity server fallbacks + [\#4191](https://github.com/matrix-org/matrix-react-sdk/pull/4191) + * Allow editing of alt_aliases according to MSC2432 + [\#4187](https://github.com/matrix-org/matrix-react-sdk/pull/4187) + * Update timeline rendering of aliases + [\#4189](https://github.com/matrix-org/matrix-react-sdk/pull/4189) + * Fix mark as read button for dark theme + [\#4190](https://github.com/matrix-org/matrix-react-sdk/pull/4190) + * Un-linkify version in settings + [\#4188](https://github.com/matrix-org/matrix-react-sdk/pull/4188) + * Make Mjolnir stop more robust + [\#4186](https://github.com/matrix-org/matrix-react-sdk/pull/4186) + * Fix secret sharing names to match spec + [\#4185](https://github.com/matrix-org/matrix-react-sdk/pull/4185) + * Share secrets with another device on request + [\#4172](https://github.com/matrix-org/matrix-react-sdk/pull/4172) + * Fall back to to_device verification if other user hasn't uploaded cross- + signing keys + [\#4181](https://github.com/matrix-org/matrix-react-sdk/pull/4181) + * Disable edits on redacted events + [\#4182](https://github.com/matrix-org/matrix-react-sdk/pull/4182) + * Use crypto.verification.request even when xsign is disabled + [\#4180](https://github.com/matrix-org/matrix-react-sdk/pull/4180) + * Reword the status for the currently indexing rooms. + [\#4084](https://github.com/matrix-org/matrix-react-sdk/pull/4084) + * Moved read receipts to the bottom of the message + [\#3892](https://github.com/matrix-org/matrix-react-sdk/pull/3892) + * Include a mark as read X under the scroll to unread button + [\#4159](https://github.com/matrix-org/matrix-react-sdk/pull/4159) + * Show the room presence indicator, even when cross-singing is enabled + [\#4178](https://github.com/matrix-org/matrix-react-sdk/pull/4178) + * Add local echo when clicking "Manually Verify" in unverified session dialog + [\#4179](https://github.com/matrix-org/matrix-react-sdk/pull/4179) + * link to matrix.org/security-disclosure-policy in help screen + [\#4129](https://github.com/matrix-org/matrix-react-sdk/pull/4129) + * only show verify button if user has uploaded cross-signing keys + [\#4174](https://github.com/matrix-org/matrix-react-sdk/pull/4174) + * Fix room alias references in topics + [\#4176](https://github.com/matrix-org/matrix-react-sdk/pull/4176) + * Fix not being able to start chats when you have no rooms + [\#4177](https://github.com/matrix-org/matrix-react-sdk/pull/4177) + * Disable registration flows on SSO servers + [\#4170](https://github.com/matrix-org/matrix-react-sdk/pull/4170) + * Don't group blank membership changes + [\#4160](https://github.com/matrix-org/matrix-react-sdk/pull/4160) + * Ensure the room list always triggers updates on itself + [\#4175](https://github.com/matrix-org/matrix-react-sdk/pull/4175) + * Fix composer touch bar flickering on keypress in Chrome + [\#4173](https://github.com/matrix-org/matrix-react-sdk/pull/4173) + * Document scrollpanel and BACAT scrolling + [\#4167](https://github.com/matrix-org/matrix-react-sdk/pull/4167) + * riot-desktop open SSO in browser so user doesn't have to auth twice + [\#4158](https://github.com/matrix-org/matrix-react-sdk/pull/4158) + * Lock login and registration buttons after submit + [\#4165](https://github.com/matrix-org/matrix-react-sdk/pull/4165) + * Suggest the server's results as lower quality in the invite dialog + [\#4149](https://github.com/matrix-org/matrix-react-sdk/pull/4149) + * Adjust scroll offset with relative scrolling + [\#4166](https://github.com/matrix-org/matrix-react-sdk/pull/4166) + * only automatically download in usercontent if user requested it + [\#4163](https://github.com/matrix-org/matrix-react-sdk/pull/4163) + * Fix having to decrypt & download in two steps + [\#4162](https://github.com/matrix-org/matrix-react-sdk/pull/4162) + * Use bash for release script + [\#4161](https://github.com/matrix-org/matrix-react-sdk/pull/4161) + * Revert to manual sorting for custom tag rooms + [\#4157](https://github.com/matrix-org/matrix-react-sdk/pull/4157) + * Fix the last char of people's names being cut off in the invite dialog + [\#4150](https://github.com/matrix-org/matrix-react-sdk/pull/4150) + * Add /whois SlashCommand to open UserInfo + [\#4154](https://github.com/matrix-org/matrix-react-sdk/pull/4154) + * word-break in pills and wrap the background correctly + [\#4155](https://github.com/matrix-org/matrix-react-sdk/pull/4155) + * don't show "This alias is available to use" if the alias is invalid + [\#4153](https://github.com/matrix-org/matrix-react-sdk/pull/4153) + * Don't ask to enable analytics when Do Not Track is enabled + [\#4098](https://github.com/matrix-org/matrix-react-sdk/pull/4098) + * Fix MELS not breaking on day boundaries regression + [\#4152](https://github.com/matrix-org/matrix-react-sdk/pull/4152) + * Fix Quote on search results page + [\#4151](https://github.com/matrix-org/matrix-react-sdk/pull/4151) + * Ensure errors when creating a DM are raised to the user + [\#4144](https://github.com/matrix-org/matrix-react-sdk/pull/4144) + * Add a Login button to startAnyRegistrationFlow + [\#3829](https://github.com/matrix-org/matrix-react-sdk/pull/3829) + * Use latest backup status directly rather than via state + [\#4147](https://github.com/matrix-org/matrix-react-sdk/pull/4147) + * Prefer account password variation of upgrading + [\#4146](https://github.com/matrix-org/matrix-react-sdk/pull/4146) + * Hide user avatars from screen readers in group and room user lists. + [\#4145](https://github.com/matrix-org/matrix-react-sdk/pull/4145) + * Room List sorting algorithms + [\#4085](https://github.com/matrix-org/matrix-react-sdk/pull/4085) + * Clear selected tags when disabling tag panel + [\#4143](https://github.com/matrix-org/matrix-react-sdk/pull/4143) + * Ignore cursor jumping shortcuts with shift + [\#4142](https://github.com/matrix-org/matrix-react-sdk/pull/4142) + * add local echo for clicking 'start verification' button + [\#4138](https://github.com/matrix-org/matrix-react-sdk/pull/4138) + * Fix formatting buttons not marking the composer as modified + [\#4141](https://github.com/matrix-org/matrix-react-sdk/pull/4141) + * Upgrade deps + [\#4136](https://github.com/matrix-org/matrix-react-sdk/pull/4136) + * Remove debug line from Analytics + [\#4137](https://github.com/matrix-org/matrix-react-sdk/pull/4137) + * Use the right function for creating binary verification QR codes + [\#4140](https://github.com/matrix-org/matrix-react-sdk/pull/4140) + * Ensure verification QR codes use the right buffer size + [\#4139](https://github.com/matrix-org/matrix-react-sdk/pull/4139) + * Don't prefix QR codes with the length of the static marker string + [\#4128](https://github.com/matrix-org/matrix-react-sdk/pull/4128) + * Solve fixed-width digit display in flowed text + [\#4127](https://github.com/matrix-org/matrix-react-sdk/pull/4127) + * Limit UserInfo Displayname to 3 lines to get rid of scrollbars + [\#4135](https://github.com/matrix-org/matrix-react-sdk/pull/4135) + +Changes in [2.2.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.1) (2020-03-04) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.0...v2.2.1) + + * Adjust scroll offset with relative scrolling + [\#4171](https://github.com/matrix-org/matrix-react-sdk/pull/4171) + * Disable registration flows on SSO servers + [\#4169](https://github.com/matrix-org/matrix-react-sdk/pull/4169) + +Changes in [2.2.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.0) (2020-03-02) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.0-rc.1...v2.2.0) + + * Upgrade JS SDK to 5.1.0 + * Ignore cursor jumping shortcuts with shift + [\#4142](https://github.com/matrix-org/matrix-react-sdk/pull/4142) + +Changes in [2.2.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.0-rc.1) (2020-02-26) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.1.1...v2.2.0-rc.1) + + * Upgrade JS SDK to 5.1.0-rc.1 + * Fix message context menu breaking on invalid m.room.pinned_events event + [\#4133](https://github.com/matrix-org/matrix-react-sdk/pull/4133) + * Update from Weblate + [\#4134](https://github.com/matrix-org/matrix-react-sdk/pull/4134) + * Notify platform of language changes + [\#4121](https://github.com/matrix-org/matrix-react-sdk/pull/4121) + * Handle errors when previewing rooms more safely + [\#4132](https://github.com/matrix-org/matrix-react-sdk/pull/4132) + * Don't try to collapse zero events with a group + [\#4131](https://github.com/matrix-org/matrix-react-sdk/pull/4131) + * Don't print errors when the tab is used with no autocomplete present + [\#4130](https://github.com/matrix-org/matrix-react-sdk/pull/4130) + * Improve UI feedback while waiting for network + [\#4126](https://github.com/matrix-org/matrix-react-sdk/pull/4126) + * Ensure DMs tagged outside of account data work in the invite dialog + [\#4123](https://github.com/matrix-org/matrix-react-sdk/pull/4123) + * Show a warning dialog when user indicates a new session wasn't them + [\#4125](https://github.com/matrix-org/matrix-react-sdk/pull/4125) + * Show cancel events as hidden events if we wouldn't usually render them + [\#4120](https://github.com/matrix-org/matrix-react-sdk/pull/4120) + * Collapsed room list has unaligned room tiles #4030 version 2 + [\#4033](https://github.com/matrix-org/matrix-react-sdk/pull/4033) + * Check for cross-signing homeserver support + [\#4118](https://github.com/matrix-org/matrix-react-sdk/pull/4118) + * Don't leak if show_sas never comes (or already came) + [\#4119](https://github.com/matrix-org/matrix-react-sdk/pull/4119) + * Add verification request viewer in devtools + [\#4106](https://github.com/matrix-org/matrix-react-sdk/pull/4106) + * update phase when request prop changes + [\#4117](https://github.com/matrix-org/matrix-react-sdk/pull/4117) + * Handle file downloading locally in electron rather than sending to browser + [\#4113](https://github.com/matrix-org/matrix-react-sdk/pull/4113) + * Remove unused CIDER setting watcher + [\#4116](https://github.com/matrix-org/matrix-react-sdk/pull/4116) + * Use alt_aliases for pills and autocomplete + [\#4102](https://github.com/matrix-org/matrix-react-sdk/pull/4102) + * Add shortcuts for beginning / end of composer + [\#4108](https://github.com/matrix-org/matrix-react-sdk/pull/4108) + * Update from Weblate + [\#4115](https://github.com/matrix-org/matrix-react-sdk/pull/4115) + * Revert "Fix escaped markdown passing backslashes through" + [\#4114](https://github.com/matrix-org/matrix-react-sdk/pull/4114) + * Fix a couple of React warnings/errors + [\#4112](https://github.com/matrix-org/matrix-react-sdk/pull/4112) + * Fix two big DOM leaks which were locking Chrome solid. + [\#4111](https://github.com/matrix-org/matrix-react-sdk/pull/4111) + * Filter out empty strings when pasting IDs into the invite dialog + [\#4109](https://github.com/matrix-org/matrix-react-sdk/pull/4109) + * Remove buildkite pipeline + [\#4107](https://github.com/matrix-org/matrix-react-sdk/pull/4107) + * Use binary packing for verification QR codes + [\#4091](https://github.com/matrix-org/matrix-react-sdk/pull/4091) + * Fix several small bugs with the invite/DM dialog + [\#4099](https://github.com/matrix-org/matrix-react-sdk/pull/4099) + * ignore e2e tests node_modules during linting + [\#4103](https://github.com/matrix-org/matrix-react-sdk/pull/4103) + * Apply null-guard to room pills for when we can't fetch the room + [\#4104](https://github.com/matrix-org/matrix-react-sdk/pull/4104) + * Fix theme being overridden to light even after login is completed + [\#4105](https://github.com/matrix-org/matrix-react-sdk/pull/4105) + * Fix bug where SSSS could be overwritten if user never cross-signs + [\#4100](https://github.com/matrix-org/matrix-react-sdk/pull/4100) + * Accept canonical alias for pills + [\#4096](https://github.com/matrix-org/matrix-react-sdk/pull/4096) + * Fix: don't advertise ability to scan a QR code for verification + [\#4094](https://github.com/matrix-org/matrix-react-sdk/pull/4094) + * Fixes for printing event indexing stats. + [\#4082](https://github.com/matrix-org/matrix-react-sdk/pull/4082) + * Remove exec so release script continues + [\#4095](https://github.com/matrix-org/matrix-react-sdk/pull/4095) + * Use Persistent Storage where possible + [\#4092](https://github.com/matrix-org/matrix-react-sdk/pull/4092) + * Fix user page (missing null check) + [\#4088](https://github.com/matrix-org/matrix-react-sdk/pull/4088) + * Cancel verification request on dialog close + [\#4081](https://github.com/matrix-org/matrix-react-sdk/pull/4081) + * Fix various memory leaks due to method re-binding + [\#4093](https://github.com/matrix-org/matrix-react-sdk/pull/4093) + * Fix share message context menu option keyboard a11y + [\#4073](https://github.com/matrix-org/matrix-react-sdk/pull/4073) + Changes in [2.1.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.1.1) (2020-02-19) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.1.0...v2.1.1) diff --git a/README.md b/README.md index 0fbed22030..5f5da9a40d 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ All code lands on the `develop` branch - `master` is only used for stable releas **Please file PRs against `develop`!!** Please follow the standard Matrix contributor's guide: -https://github.com/matrix-org/synapse/tree/master/CONTRIBUTING.rst +https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.rst Please follow the Matrix JS/React code style as per: https://github.com/matrix-org/matrix-react-sdk/blob/master/code_style.md @@ -45,7 +45,7 @@ Code should be committed as follows: * In practice, `matrix-react-sdk` is still evolving so fast that the maintenance burden of customising and overriding these components for Riot can seriously impede development. So right now, there should be very few (if any) customisations for Riot. - * CSS: https://github.com/vector-im/riot-web/tree/master/src/skins/vector/css/matrix-react-sdk + * CSS: https://github.com/matrix-org/matrix-react-sdk/tree/master/res/css * Theme specific CSS & resources: https://github.com/matrix-org/matrix-react-sdk/tree/master/res/themes React components in matrix-react-sdk are come in two different flavours: @@ -133,8 +133,10 @@ Development Ensure you have the latest LTS version of Node.js installed. -Using `yarn` instead of `npm` is recommended. Please see the Yarn [install -guide](https://yarnpkg.com/docs/install/) if you do not have it already. +Using `yarn` instead of `npm` is recommended. Please see the Yarn 1 [install +guide](https://classic.yarnpkg.com/docs/install) if you do not have it +already. This project has not yet been migrated to Yarn 2, so please ensure +`yarn --version` shows a version from the 1.x series. `matrix-react-sdk` depends on `matrix-js-sdk`. To make use of changes in the latter and to ensure tests run against the develop branch of `matrix-js-sdk`, diff --git a/docs/jitsi.md b/docs/jitsi.md new file mode 100644 index 0000000000..779ef79d3a --- /dev/null +++ b/docs/jitsi.md @@ -0,0 +1,31 @@ +# Jitsi Wrapper + +**Note**: These are developer docs. Please consult your client's documentation for +instructions on setting up Jitsi. + +The react-sdk wraps all Jitsi call widgets in a local wrapper called `jitsi.html` +which takes several parameters: + +*Query string*: +* `widgetId`: The ID of the widget. This is needed for communication back to the + react-sdk. +* `parentUrl`: The URL of the parent window. This is also needed for + communication back to the react-sdk. + +*Hash/fragment (formatted as a query string)*: +* `conferenceDomain`: The domain to connect Jitsi Meet to. +* `conferenceId`: The room or conference ID to connect Jitsi Meet to. +* `isAudioOnly`: Boolean for whether this is a voice-only conference. May not + be present, should default to `false`. +* `displayName`: The display name of the user viewing the widget. May not + be present or could be null. +* `avatarUrl`: The HTTP(S) URL for the avatar of the user viewing the widget. May + not be present or could be null. +* `userId`: The MXID of the user viewing the widget. May not be present or could + be null. + +The react-sdk will assume that `jitsi.html` is at the path of wherever it is currently +being served. For example, `https://riot.im/develop/jitsi.html` or `vector://webapp/jitsi.html`. + +The `jitsi.html` wrapper can use the react-sdk's `WidgetApi` to communicate, making +it easier to actually implement the feature. diff --git a/docs/scrolling.md b/docs/scrolling.md new file mode 100644 index 0000000000..71329e5c32 --- /dev/null +++ b/docs/scrolling.md @@ -0,0 +1,28 @@ +# ScrollPanel + +## Updates + +During an onscroll event, we check whether we're getting close to the top or bottom edge of the loaded content. If close enough, we fire a request to load more through the callback passed in the `onFillRequest` prop. This returns a promise is passed down from `TimelinePanel`, where it will call paginate on the `TimelineWindow` and once the events are received back, update its state with the new events. This update trickles down to the `MessagePanel`, which rerenders all tiles and passed that to `ScrollPanel`. ScrollPanels `componentDidUpdate` method gets called, and we do the scroll housekeeping there (read below). Once the rerender has completed, the `setState` callback is called and we resolve the promise returned by `onFillRequest`. Now we check the DOM to see if we need more fill requests. + +## Prevent Shrinking + +ScrollPanel supports a mode to prevent it shrinking. This is used to prevent a jump when at the bottom of the timeline and people start and stop typing. It gets cleared automatically when 200px above the bottom of the timeline. + + +## BACAT (Bottom-Aligned, Clipped-At-Top) scrolling + +BACAT scrolling implements a different way of restoring the scroll position in the timeline while tiles out of view are changing height or tiles are being added or removed. It was added in https://github.com/matrix-org/matrix-react-sdk/pull/2842. + +The motivation for the changes is having noticed that setting scrollTop while scrolling tends to not work well, with it interrupting ongoing scrolling and also querying scrollTop reporting outdated values and consecutive scroll adjustments cancelling each out previous ones. This seems to be worse on macOS than other platforms, presumably because of a higher resolution in scroll events there. Also see https://github.com/vector-im/riot-web/issues/528. The BACAT approach allows to only have to change the scroll offset when adding or removing tiles. + +The approach taken instead is to vertically align the timeline tiles to the bottom of the scroll container (using flexbox) and give the timeline inside the scroll container an explicit height, initially set to a multiple of the PAGE_SIZE (400px at time of writing) as needed by the content. When scrolled up, we can compensate for anything that grew below the viewport by changing the height of the timeline to maintain what's currently visible in the viewport without adjusting the scrollTop and hence without jumping. + +For anything above the viewport growing or shrinking, we don't need to do anything as the timeline is bottom-aligned. We do need to update the height manually to keep all content visible as more is loaded. To maintain scroll position after the portion above the viewport changes height, we need to set the scrollTop, as we cannot balance it out with more height changes. We do this 100ms after the user has stopped scrolling, so setting scrollTop has not nasty side-effects. + +As of https://github.com/matrix-org/matrix-react-sdk/pull/4166, we are scrolling to compensate for height changes by calling `scrollBy(0, x)` rather than reading and than setting `scrollTop`, as reading `scrollTop` can (again, especially on macOS) easily return values that are out of sync with what is on the screen, probably because scrolling can be done [off the main thread](https://wiki.mozilla.org/Platform/GFX/APZ) in some circumstances. This seems to further prevent jumps. + +### How does it work? + +`componentDidUpdate` is called when a tile in the timeline is updated (as we rerender the whole timeline) or tiles are added or removed (see Updates section before). From here, `checkScroll` is called, which calls `_restoreSavedScrollState`. Now, we increase the timeline height if something below the viewport grew by adjusting `this._bottomGrowth`. `bottomGrowth` is the height added to the timeline (on top of the height from the number of pages calculated at the last `_updateHeight` run) to compensate for growth below the viewport. This is cleared during the next run of `_updateHeight`. Remember that the tiles in the timeline are aligned to the bottom. + +From `_restoreSavedScrollState` we also call `_updateHeight` which waits until the user stops scrolling for 100ms and then recalculates the amount of pages of 400px the timeline should be sized to, to be able to show all of its (newly added) content. We have to adjust the scroll offset (which is why we wait until scrolling has stopped) now because the space above the viewport has likely changed. diff --git a/docs/settings.md b/docs/settings.md index 9b780c27c9..46e4a68fdb 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -51,6 +51,17 @@ Settings are the different options a user may set or experience in the applicati } ``` +Settings that support the config level can be set in the config file under the `settingDefaults` key (note that some settings, like the "theme" setting, are special cased in the config file): +```json +{ + ... + "settingDefaults": { + "settingName": true + }, + ... +} +``` + ### Getting values for a setting After importing `SettingsStore`, simply make a call to `SettingsStore.getValue`. The `roomId` parameter should always diff --git a/package.json b/package.json index a68dcfddb4..dda4a5a897 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.1.1", + "version": "2.5.0", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -40,15 +40,15 @@ "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\" src", - "build:types": "tsc --emitDeclarationOnly", + "build:compile": "yarn reskindex && 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:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"", "lint": "yarn lint:types && yarn lint:ts && yarn lint:js && yarn lint:style", "lint:js": "eslint --max-warnings 0 --ignore-path .eslintignore.errorfiles src test", "lint:ts": "tslint --project ./tsconfig.json -t stylish", - "lint:types": "tsc --noEmit", + "lint:types": "tsc --noEmit --jsx react", "lint:style": "stylelint 'res/css/**/*.scss'", "test": "jest", "test:e2e": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080" @@ -72,7 +72,6 @@ "flux": "2.1.1", "focus-visible": "^5.0.2", "fuse.js": "^2.2.0", - "gemini-scrollbar": "github:matrix-org/gemini-scrollbar#91e1e566", "gfm.css": "^1.1.1", "glob-to-regexp": "^0.4.1", "highlight.js": "^9.15.8", @@ -80,19 +79,19 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "5.0.1", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "minimist": "^1.2.0", "pako": "^1.0.5", + "parse5": "^5.1.1", "png-chunks-extract": "^1.0.0", + "project-name-generator": "^2.1.7", "prop-types": "^15.5.8", - "qrcode-react": "^0.1.16", + "qrcode": "^1.4.4", "qs": "^6.6.0", "react": "^16.9.0", - "react-addons-css-transition-group": "15.6.2", "react-beautiful-dnd": "^4.0.1", "react-dom": "^16.9.0", "react-focus-lock": "^2.2.1", - "react-gemini-scrollbar": "github:matrix-org/react-gemini-scrollbar#9cf17f63b7c0b0ec5f31df27da0f82f7238dc594", "resize-observer-polyfill": "^1.5.0", "sanitize-html": "^1.18.4", "text-encoding-utf-8": "^1.0.1", @@ -117,6 +116,10 @@ "@babel/preset-typescript": "^7.7.4", "@babel/register": "^7.7.4", "@peculiar/webcrypto": "^1.0.22", + "@types/classnames": "^2.2.10", + "@types/modernizr": "^3.5.3", + "@types/qrcode": "^1.3.4", + "@types/react": "16.9", "babel-eslint": "^10.0.3", "babel-jest": "^24.9.0", "chokidar": "^3.3.1", diff --git a/release.sh b/release.sh index c585708326..23b8822041 100755 --- a/release.sh +++ b/release.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Script to perform a release of matrix-react-sdk. # @@ -11,6 +11,7 @@ cd `dirname $0` for i in matrix-js-sdk do + echo "Checking version of $i..." depver=`cat package.json | jq -r .dependencies[\"$i\"]` latestver=`yarn info -s $i dist-tags.next` if [ "$depver" != "$latestver" ] @@ -35,7 +36,7 @@ do fi done -exec ./node_modules/matrix-js-sdk/release.sh -z "$@" +./node_modules/matrix-js-sdk/release.sh -z "$@" release="${1#v}" prerelease=0 diff --git a/res/css/_common.scss b/res/css/_common.scss index e062e0bd73..03442ca510 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -16,6 +16,12 @@ See the License for the specific language governing permissions and limitations under the License. */ +@import "./_font-sizes.scss"; + +:root { + font-size: 15px; +} + html { /* hack to stop overscroll bounce on OSX and iOS. N.B. Breaks things when we have legitimate horizontal overscroll */ @@ -25,7 +31,7 @@ html { body { font-family: $font-family; - font-size: 15px; + font-size: $font-15px; background-color: $primary-bg-color; color: $primary-fg-color; border: 0px; @@ -42,10 +48,15 @@ pre, code { font-size: 100% !important; } -.error, .warning { +.error, .warning, +.text-error, .text-warning { color: $warning-color; } +.text-success { + color: $accent-color; +} + b { // On Firefox, the default weight for `` is `bolder` which results in no bold // effect since we only have specific weights of our fonts available. @@ -55,7 +66,7 @@ b { h2 { color: $primary-fg-color; font-weight: 400; - font-size: 18px; + font-size: $font-18px; margin-top: 16px; margin-bottom: 16px; } @@ -71,7 +82,7 @@ input[type=search], input[type=password] { padding: 9px; font-family: $font-family; - font-size: 14px; + font-size: $font-14px; font-weight: 600; min-width: 0; } @@ -202,37 +213,6 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { transition: opacity 0.2s ease-in-out; } -/* XXX: critical hack to GeminiScrollbar to allow them to work in FF 42 and Chrome 48. - Stop the scrollbar view from pushing out the container's overall sizing, which causes - flexbox to adapt to the new size and cause the view to keep growing. - */ -.gm-scrollbar-container .gm-scroll-view { - position: absolute; -} - -/* Expand thumbs on hoverover */ -.gm-scrollbar { - border-radius: 5px !important; -} -.gm-scrollbar.-vertical { - width: 6px; - transition: width 120ms ease-out !important; -} -.gm-scrollbar.-vertical:hover, -.gm-scrollbar.-vertical:active { - width: 8px; - transition: width 120ms ease-out !important; -} -.gm-scrollbar.-horizontal { - height: 6px; - transition: height 120ms ease-out !important; -} -.gm-scrollbar.-horizontal:hover, -.gm-scrollbar.-horizontal:active { - height: 8px; - transition: height 120ms ease-out !important; -} - // 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 // colourscheme is by inspecting the stylesheet DOM. @@ -279,7 +259,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { color: $light-fg-color; z-index: 4012; font-weight: 300; - font-size: 15px; + font-size: $font-15px; position: relative; padding: 25px 30px 30px 30px; max-height: 80%; @@ -347,8 +327,8 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { } .mx_Dialog_title { - font-size: 22px; - line-height: 36px; + font-size: $font-22px; + line-height: $font-36px; color: $dialog-title-fg-color; } @@ -376,7 +356,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { .mx_Dialog_content { margin: 24px 0 68px; - font-size: 14px; + font-size: $font-14px; color: $primary-fg-color; word-wrap: break-word; } @@ -472,7 +452,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { } .mx_TextInputDialog_input { - font-size: 15px; + font-size: $font-15px; border-radius: 3px; border: 1px solid $input-border-color; padding: 9px; diff --git a/res/css/_components.scss b/res/css/_components.scss index bc636eb3c6..c05e2cabc6 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -1,5 +1,6 @@ // autogenerated by rethemendex.sh @import "./_common.scss"; +@import "./_font-sizes.scss"; @import "./structures/_AutoHideScrollbar.scss"; @import "./structures/_CompatibilityPage.scss"; @import "./structures/_ContextualMenu.scss"; @@ -65,6 +66,7 @@ @import "./views/dialogs/_GroupAddressPicker.scss"; @import "./views/dialogs/_IncomingSasDialog.scss"; @import "./views/dialogs/_InviteDialog.scss"; +@import "./views/dialogs/_KeyboardShortcutsDialog.scss"; @import "./views/dialogs/_MessageEditHistoryDialog.scss"; @import "./views/dialogs/_NewSessionReviewDialog.scss"; @import "./views/dialogs/_RoomSettingsDialog.scss"; @@ -106,6 +108,7 @@ @import "./views/elements/_ManageIntegsButton.scss"; @import "./views/elements/_PowerSelector.scss"; @import "./views/elements/_ProgressBar.scss"; +@import "./views/elements/_QRCode.scss"; @import "./views/elements/_ReplyThread.scss"; @import "./views/elements/_ResizeHandle.scss"; @import "./views/elements/_RichText.scss"; @@ -131,12 +134,14 @@ @import "./views/messages/_MNoticeBody.scss"; @import "./views/messages/_MStickerBody.scss"; @import "./views/messages/_MTextBody.scss"; +@import "./views/messages/_MVideoBody.scss"; @import "./views/messages/_MessageActionBar.scss"; @import "./views/messages/_MessageTimestamp.scss"; @import "./views/messages/_MjolnirBody.scss"; @import "./views/messages/_ReactionsRow.scss"; @import "./views/messages/_ReactionsRowButton.scss"; @import "./views/messages/_ReactionsRowButtonTooltip.scss"; +@import "./views/messages/_RedactedBody.scss"; @import "./views/messages/_RoomAvatarEvent.scss"; @import "./views/messages/_SenderProfile.scss"; @import "./views/messages/_TextualEvent.scss"; @@ -177,7 +182,6 @@ @import "./views/rooms/_RoomTile.scss"; @import "./views/rooms/_RoomUpgradeWarningBar.scss"; @import "./views/rooms/_SearchBar.scss"; -@import "./views/rooms/_SearchableEntityList.scss"; @import "./views/rooms/_SendMessageComposer.scss"; @import "./views/rooms/_Stickers.scss"; @import "./views/rooms/_TopUnreadMessagesBar.scss"; @@ -186,6 +190,7 @@ @import "./views/settings/_AvatarSetting.scss"; @import "./views/settings/_CrossSigningPanel.scss"; @import "./views/settings/_DevicesPanel.scss"; +@import "./views/settings/_E2eAdvancedPanel.scss"; @import "./views/settings/_EmailAddresses.scss"; @import "./views/settings/_IntegrationManager.scss"; @import "./views/settings/_KeyBackupPanel.scss"; diff --git a/res/css/_font-sizes.scss b/res/css/_font-sizes.scss new file mode 100644 index 0000000000..76a9b16425 --- /dev/null +++ b/res/css/_font-sizes.scss @@ -0,0 +1,71 @@ +/* +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. +*/ + +$font-1px: 0.067rem; +$font-2px: 0.133rem; +$font-3px: 0.200rem; +$font-4px: 0.267rem; +$font-5px: 0.333rem; +$font-6px: 0.400rem; +$font-7px: 0.467rem; +$font-8px: 0.533rem; +$font-9px: 0.600rem; +$font-10px: 0.667rem; +$font-10-4px: 0.693rem; +$font-11px: 0.733rem; +$font-12px: 0.800rem; +$font-13px: 0.867rem; +$font-14px: 0.933rem; +$font-15px: 1.000rem; +$font-16px: 1.067rem; +$font-17px: 1.133rem; +$font-18px: 1.200rem; +$font-19px: 1.267rem; +$font-20px: 1.3333333rem; +$font-21px: 1.400rem; +$font-22px: 1.467rem; +$font-23px: 1.533rem; +$font-24px: 1.600rem; +$font-25px: 1.667rem; +$font-26px: 1.733rem; +$font-27px: 1.800rem; +$font-28px: 1.867rem; +$font-29px: 1.933rem; +$font-30px: 2.000rem; +$font-31px: 2.067rem; +$font-32px: 2.133rem; +$font-33px: 2.200rem; +$font-34px: 2.267rem; +$font-35px: 2.333rem; +$font-36px: 2.400rem; +$font-37px: 2.467rem; +$font-38px: 2.533rem; +$font-39px: 2.600rem; +$font-40px: 2.667rem; +$font-41px: 2.733rem; +$font-42px: 2.800rem; +$font-43px: 2.867rem; +$font-44px: 2.933rem; +$font-45px: 3.000rem; +$font-46px: 3.067rem; +$font-47px: 3.133rem; +$font-48px: 3.200rem; +$font-49px: 3.267rem; +$font-50px: 3.333rem; +$font-51px: 3.400rem; +$font-52px: 3.467rem; +$font-88px: 5.887rem; +$font-400px: 26.667rem; diff --git a/res/css/structures/_AutoHideScrollbar.scss b/res/css/structures/_AutoHideScrollbar.scss index 6e4484157c..50842c71bc 100644 --- a/res/css/structures/_AutoHideScrollbar.scss +++ b/res/css/structures/_AutoHideScrollbar.scss @@ -14,69 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* This file has CSS for both native and non-native scrollbars in an order - * that's fairly logical to read but duplicates a selector to separate the - * hiding/showing from the sizing. - */ -/* stylelint-disable no-duplicate-selectors */ - -/* -1. for browsers that support native overlay auto-hiding scrollbars -*/ -.mx_AutoHideScrollbar { - overflow-x: hidden; - overflow-y: auto; - -ms-overflow-style: -ms-autohiding-scrollbar; -} -/* -2. webkit also supports overflow:overlay where the scrollbars don't take any space -in the layout but they don't autohide, so do that only on hover -*/ -body.mx_scrollbar_overlay_noautohide .mx_AutoHideScrollbar { - overflow-y: hidden; -} - -body.mx_scrollbar_overlay_noautohide .mx_AutoHideScrollbar:hover { - overflow-y: overlay; -} -/* -3. as a last fallback, compensate for the scrollbar taking up space in the layout -by having giving the child element (.mx_AutoHideScrollbar_offset) a -negative right margin of the width of the scrollbar when the container -is overflowing. This is what Firefox ends up using. Overflow is detected -in javascript, and adds the mx_AutoHideScrollbar_overflow class to the container. -This only works in Firefox, which should be fine as this fallback is only needed there. -*/ -body.mx_scrollbar_nooverlay { - .mx_AutoHideScrollbar { - overflow-y: hidden; - } - - .mx_AutoHideScrollbar:hover { - overflow-y: auto; - } - - /* - offset scrollbar width with negative margin-right - - include before and after psuedo-elements here so they can - be used to do something interesting like scroll-indicating - gradients (see IndicatorScrollBar) - */ - .mx_AutoHideScrollbar:hover.mx_AutoHideScrollbar_overflow > .mx_AutoHideScrollbar_offset, - .mx_AutoHideScrollbar:hover.mx_AutoHideScrollbar_overflow::before, - .mx_AutoHideScrollbar:hover.mx_AutoHideScrollbar_overflow::after { - margin-right: calc(-1 * var(--scrollbar-width)); - } -} - -// style the native scrollbars ... -// ... standard css scrollbars (firefox at time of writing) -.mx_AutoHideScrollbar { +// make any scrollbar grey and thin +html { scrollbar-color: $scrollbar-thumb-color $scrollbar-track-color; +} +// scrollbar-width is not inherited (but -color is, why?!), +// so declare it on every element +* { scrollbar-width: thin; } -// or fallback for webkit browsers + ::-webkit-scrollbar { width: 6px; height: 6px; @@ -84,6 +31,37 @@ body.mx_scrollbar_nooverlay { } ::-webkit-scrollbar-thumb { - background-color: $scrollbar-thumb-color; border-radius: 3px; + background-color: $scrollbar-thumb-color; +} + +// make auto-hide scrollbars not transparent again on hover +.mx_AutoHideScrollbar:hover { + scrollbar-color: $scrollbar-thumb-color $scrollbar-track-color; + + &::-webkit-scrollbar { + background-color: $scrollbar-track-color; + } + + &::-webkit-scrollbar-thumb { + background-color: $scrollbar-thumb-color; + } +} + +// make scrollbars transparent for autohide scrollbars +.mx_AutoHideScrollbar { + overflow-x: hidden; + overflow-y: auto; + overflow-y: overlay; // where supported + -ms-overflow-style: -ms-autohiding-scrollbar; + + &::-webkit-scrollbar { + background-color: transparent; + } + + &::-webkit-scrollbar-thumb { + background-color: transparent; + } + + scrollbar-color: transparent transparent; } diff --git a/res/css/structures/_ContextualMenu.scss b/res/css/structures/_ContextualMenu.scss index fa2d87029d..61070a0541 100644 --- a/res/css/structures/_ContextualMenu.scss +++ b/res/css/structures/_ContextualMenu.scss @@ -36,7 +36,7 @@ limitations under the License. background-color: $menu-bg-color; color: $primary-fg-color; position: absolute; - font-size: 14px; + font-size: $font-14px; z-index: 5001; } diff --git a/res/css/structures/_CreateRoom.scss b/res/css/structures/_CreateRoom.scss index 10f9e23a02..e859beb20e 100644 --- a/res/css/structures/_CreateRoom.scss +++ b/res/css/structures/_CreateRoom.scss @@ -26,7 +26,7 @@ limitations under the License. border-radius: 3px; border: 1px solid $strong-input-border-color; font-weight: 300; - font-size: 13px; + font-size: $font-13px; padding: 9px; margin-top: 6px; } diff --git a/res/css/structures/_FilePanel.scss b/res/css/structures/_FilePanel.scss index 87e885e668..859ee28035 100644 --- a/res/css/structures/_FilePanel.scss +++ b/res/css/structures/_FilePanel.scss @@ -49,7 +49,7 @@ limitations under the License. .mx_FilePanel .mx_EventTile .mx_MFileBody_download { display: flex; - font-size: 14px; + font-size: $font-14px; color: $event-timestamp-color; } @@ -60,7 +60,7 @@ limitations under the License. .mx_FilePanel .mx_EventTile .mx_MImageBody_size { flex: 1 0 0; - font-size: 11px; + font-size: $font-11px; text-align: right; white-space: nowrap; } @@ -80,7 +80,7 @@ limitations under the License. flex: 1 1 auto; line-height: initial; padding: 0px; - font-size: 11px; + font-size: $font-11px; opacity: 1.0; color: $event-timestamp-color; } @@ -90,7 +90,7 @@ limitations under the License. text-align: right; visibility: visible; position: initial; - font-size: 11px; + font-size: $font-11px; opacity: 1.0; color: $event-timestamp-color; } diff --git a/res/css/structures/_GroupView.scss b/res/css/structures/_GroupView.scss index 517b8b1922..ed0cf121a4 100644 --- a/res/css/structures/_GroupView.scss +++ b/res/css/structures/_GroupView.scss @@ -134,7 +134,7 @@ limitations under the License. overflow: hidden; color: $primary-fg-color; font-weight: bold; - font-size: 22px; + font-size: $font-22px; padding-left: 19px; padding-right: 16px; /* why isn't text-overflow working? */ @@ -148,7 +148,7 @@ limitations under the License. max-height: 42px; color: $settings-grey-fg-color; font-weight: 300; - font-size: 13px; + font-size: $font-13px; padding-left: 19px; margin-right: 16px; overflow: hidden; @@ -180,10 +180,6 @@ limitations under the License. line-height: 2em; } -.mx_GroupView > .mx_MainSplit { - flex: 1; -} - .mx_GroupView_body { flex-grow: 1; } @@ -200,7 +196,7 @@ limitations under the License. text-transform: uppercase; color: $h3-color; font-weight: 600; - font-size: 13px; + font-size: $font-13px; margin-bottom: 10px; } @@ -230,7 +226,7 @@ limitations under the License. .mx_GroupView_rooms_header_addRow_label { display: inline-block; vertical-align: top; - line-height: 24px; + line-height: $font-24px; padding-left: 28px; color: $accent-color; } @@ -262,7 +258,7 @@ limitations under the License. .mx_GroupView_membershipSection_description { /* To match textButton */ - line-height: 34px; + line-height: $font-34px; } .mx_GroupView_membershipSection_description .mx_BaseAvatar { @@ -341,8 +337,8 @@ limitations under the License. display: none; } -.mx_GroupView_body .gm-scroll-view > * { - margin: 11px 50px 0px 68px; +.mx_GroupView_body .mx_AutoHideScrollbar > * { + margin: 11px 50px 50px 68px; } .mx_GroupView_groupDesc textarea { @@ -370,7 +366,7 @@ limitations under the License. padding: 40px 20px; } -.mx_GroupView .mx_MemberInfo .gm-scroll-view > :not(.mx_MemberInfo_avatar) { +.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 3aa80f6f59..0160cf368b 100644 --- a/res/css/structures/_HomePage.scss +++ b/res/css/structures/_HomePage.scss @@ -23,3 +23,84 @@ limitations under the License. margin-left: auto; margin-right: auto; } + +.mx_HomePage_default { + text-align: center; + + .mx_HomePage_default_wrapper { + padding: 25vh 0 12px; + } + + img { + height: 48px; + } + + h1 { + font-weight: 600; + font-size: $font-32px; + line-height: $font-44px; + margin-bottom: 4px; + } + + h4 { + margin-top: 4px; + font-weight: 600; + font-size: $font-18px; + line-height: $font-25px; + color: $muted-fg-color; + } + + .mx_HomePage_default_buttons { + margin: 80px auto 0; + width: fit-content; + + .mx_AccessibleButton { + padding: 73px 8px 15px; // top: 20px top padding + 40px icon + 13px margin + + width: 104px; // 120px - 2* 8px + margin: 0 39px; // 55px - 2* 8px + position: relative; + display: inline-block; + border-radius: 8px; + vertical-align: top; + word-break: break-word; + + font-weight: 600; + font-size: $font-15px; + line-height: $font-20px; + color: $muted-fg-color; + + &:hover { + color: $accent-color; + background: rgba(#03b381, 0.06); + + &::before { + background-color: $accent-color; + } + } + + &::before { + top: 20px; + left: 40px; // (120px-40px)/2 + width: 40px; + height: 40px; + + content: ''; + position: absolute; + background-color: $muted-fg-color; + mask-repeat: no-repeat; + mask-size: contain; + } + + &.mx_HomePage_button_sendDm::before { + mask-image: url('$(res)/img/feather-customised/message-circle.svg'); + } + &.mx_HomePage_button_explore::before { + mask-image: url('$(res)/img/feather-customised/explore.svg'); + } + &.mx_HomePage_button_createGroup::before { + mask-image: url('$(res)/img/feather-customised/group.svg'); + } + } + } +} diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index 85fdfa092d..7d57425f6f 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -147,7 +147,7 @@ limitations under the License. } .mx_AccessibleButton { - font-size: 14px; + font-size: $font-14px; margin: 4px 0 1px 9px; padding: 9px; padding-left: 42px; diff --git a/res/css/structures/_MainSplit.scss b/res/css/structures/_MainSplit.scss index 4d73953cd7..25e1153fce 100644 --- a/res/css/structures/_MainSplit.scss +++ b/res/css/structures/_MainSplit.scss @@ -18,6 +18,7 @@ limitations under the License. display: flex; flex-direction: row; min-width: 0; + height: 100%; } // move hit area 5px to the right so it doesn't overlap with the timeline scrollbar diff --git a/res/css/structures/_MatrixChat.scss b/res/css/structures/_MatrixChat.scss index f2ce7e1d5c..c5a5d50068 100644 --- a/res/css/structures/_MatrixChat.scss +++ b/res/css/structures/_MatrixChat.scss @@ -76,13 +76,6 @@ limitations under the License. flex: 1 1 0; min-width: 0; - /* Experimental fix for https://github.com/vector-im/vector-web/issues/947 - and https://github.com/vector-im/vector-web/issues/946. - Empirically this stops the MessagePanel's width exploding outwards when - gemini is in 'prevented' mode - */ - overflow-x: auto; - /* To fix https://github.com/vector-im/riot-web/issues/3298 where Safari needed height 100% all the way down to the HomePage. Height does not have to be auto, empirically. diff --git a/res/css/structures/_MyGroups.scss b/res/css/structures/_MyGroups.scss index d25789ab94..73f1332cd0 100644 --- a/res/css/structures/_MyGroups.scss +++ b/res/css/structures/_MyGroups.scss @@ -67,9 +67,6 @@ limitations under the License. } } - - - .mx_MyGroups_headerCard_header { font-weight: bold; margin-bottom: 10px; @@ -98,12 +95,17 @@ limitations under the License. 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: 400px; + line-height: $font-400px; border-radius: 10px; text-align: center; } @@ -147,11 +149,11 @@ limitations under the License. .mx_GroupTile_profile .mx_GroupTile_name { margin: 0px; - font-size: 15px; + font-size: $font-15px; } .mx_GroupTile_profile .mx_GroupTile_groupId { - font-size: 13px; + font-size: $font-13px; opacity: 0.7; } @@ -159,7 +161,7 @@ limitations under the License. display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; - font-size: 13px; + font-size: $font-13px; max-height: 36px; overflow: hidden; } diff --git a/res/css/structures/_NotificationPanel.scss b/res/css/structures/_NotificationPanel.scss index c9e0261ec9..44205b1f01 100644 --- a/res/css/structures/_NotificationPanel.scss +++ b/res/css/structures/_NotificationPanel.scss @@ -39,7 +39,7 @@ limitations under the License. .mx_NotificationPanel .mx_EventTile_roomName { font-weight: bold; - font-size: 14px; + font-size: $font-14px; } .mx_NotificationPanel .mx_EventTile_roomName a { @@ -54,7 +54,7 @@ limitations under the License. .mx_NotificationPanel .mx_EventTile .mx_SenderProfile, .mx_NotificationPanel .mx_EventTile .mx_MessageTimestamp { color: $primary-fg-color; - font-size: 12px; + font-size: $font-12px; display: inline; padding-left: 0px; } diff --git a/res/css/structures/_RightPanel.scss b/res/css/structures/_RightPanel.scss index 3c373e8883..10878322e3 100644 --- a/res/css/structures/_RightPanel.scss +++ b/res/css/structures/_RightPanel.scss @@ -96,7 +96,7 @@ limitations under the License. } .mx_RightPanel_headerButton_badge { - font-size: 8px; + font-size: $font-8px; border-radius: 8px; color: $accent-fg-color; background-color: $accent-color; diff --git a/res/css/structures/_RoomDirectory.scss b/res/css/structures/_RoomDirectory.scss index 5ae8df7176..e0814182f5 100644 --- a/res/css/structures/_RoomDirectory.scss +++ b/res/css/structures/_RoomDirectory.scss @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +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. @@ -45,9 +46,8 @@ limitations under the License. } .mx_RoomDirectory_listheader { - display: flex; - margin-top: 12px; - margin-bottom: 12px; + display: block; + margin-top: 13px; } .mx_RoomDirectory_searchbox { @@ -64,7 +64,7 @@ limitations under the License. } .mx_RoomDirectory_table { - font-size: 14px; + font-size: $font-12px; color: $primary-fg-color; width: 100%; text-align: left; @@ -112,6 +112,7 @@ limitations under the License. .mx_RoomDirectory_name { display: inline-block; + font-size: $font-18px; font-weight: 600; } @@ -123,7 +124,7 @@ limitations under the License. border-radius: 10px; display: inline-block; height: 20px; - line-height: 20px; + line-height: $font-20px; padding: 0 5px; color: $accent-fg-color; background-color: $rte-room-pill-color; @@ -135,7 +136,7 @@ limitations under the License. } .mx_RoomDirectory_alias { - font-size: 12px; + font-size: $font-12px; color: $settings-grey-fg-color; } @@ -148,8 +149,8 @@ limitations under the License. padding: 0; } -.mx_RoomDirectory p { - font-size: 14px; +.mx_RoomDirectory > span { + font-size: $font-15px; margin-top: 0; .mx_AccessibleButton { diff --git a/res/css/structures/_RoomStatusBar.scss b/res/css/structures/_RoomStatusBar.scss index 090a40235f..cd4390ee5c 100644 --- a/res/css/structures/_RoomStatusBar.scss +++ b/res/css/structures/_RoomStatusBar.scss @@ -32,7 +32,7 @@ limitations under the License. .mx_RoomStatusBar_callBar { height: 50px; - line-height: 50px; + line-height: $font-50px; } .mx_RoomStatusBar_placeholderIndicator span { @@ -94,7 +94,7 @@ limitations under the License. border-radius: 40px; width: 24px; height: 24px; - line-height: 24px; + line-height: $font-24px; font-size: 0.8em; vertical-align: top; text-align: center; @@ -132,7 +132,7 @@ limitations under the License. .mx_RoomStatusBar_connectionLostBar_desc { color: $primary-fg-color; - font-size: 13px; + font-size: $font-13px; opacity: 0.5; padding-bottom: 20px; } @@ -145,7 +145,7 @@ limitations under the License. .mx_RoomStatusBar_typingBar { height: 50px; - line-height: 50px; + line-height: $font-50px; color: $primary-fg-color; opacity: 0.5; @@ -155,7 +155,7 @@ limitations under the License. .mx_RoomStatusBar_isAlone { height: 50px; - line-height: 50px; + line-height: $font-50px; color: $primary-fg-color; opacity: 0.5; @@ -174,11 +174,11 @@ limitations under the License. .mx_RoomStatusBar_callBar { height: 40px; - line-height: 40px; + line-height: $font-40px; } .mx_RoomStatusBar_typingBar { height: 40px; - line-height: 40px; + line-height: $font-40px; } } diff --git a/res/css/structures/_RoomSubList.scss b/res/css/structures/_RoomSubList.scss index be44563cfb..2c53258b08 100644 --- a/res/css/structures/_RoomSubList.scss +++ b/res/css/structures/_RoomSubList.scss @@ -68,15 +68,15 @@ limitations under the License. text-transform: uppercase; color: $roomsublist-label-fg-color; font-weight: 700; - font-size: 12px; + font-size: $font-12px; margin-left: 8px; } .mx_RoomSubList_badge > div { flex: 0 0 auto; - border-radius: 8px; + border-radius: $font-16px; font-weight: 600; - font-size: 12px; + font-size: $font-12px; padding: 0 5px; color: $roomtile-badge-fg-color; background-color: $roomtile-name-color; @@ -166,41 +166,22 @@ limitations under the License. // overflow indicators .mx_RoomSubList:not(.resized-all) > .mx_RoomSubList_scroll { - &.mx_IndicatorScrollbar_topOverflow::before, - &.mx_IndicatorScrollbar_bottomOverflow::after { + &.mx_IndicatorScrollbar_topOverflow::before { position: sticky; + content: ""; + top: 0; left: 0; right: 0; height: 8px; - content: ""; - display: block; z-index: 100; + display: block; pointer-events: none; - } - - &.mx_IndicatorScrollbar_topOverflow > .mx_AutoHideScrollbar_offset { - margin-top: -8px; - } - &.mx_IndicatorScrollbar_bottomOverflow > .mx_AutoHideScrollbar_offset { - margin-bottom: -8px; - } - - &.mx_IndicatorScrollbar_topOverflow::before { - top: 0; transition: background-image 0.1s ease-in; background: linear-gradient(to top, $panel-gradient); } - /* - // for now, we remove the bottomOverflow entirely as we don't want to - // lose the screen real-estate due to a bg-colored gradient, but we also - // don't want to use drop shadows and risk a confusing hierarchy of cards. - // so, instead, we hard-clip at the bottom but soft-clip at the top. - &.mx_IndicatorScrollbar_bottomOverflow::after { - bottom: 0; - transition: background-image 0.1s ease-in; - margin: 0px -8px; - background: linear-gradient(to bottom, rgba(0,0,0,0.1), rgba(0,0,0,0.0)); + + &.mx_IndicatorScrollbar_topOverflow { + margin-top: -8px; } - */ } diff --git a/res/css/structures/_RoomView.scss b/res/css/structures/_RoomView.scss index 5e826306c6..f2154ef448 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -23,7 +23,7 @@ limitations under the License. .mx_RoomView_fileDropTarget { min-width: 0px; width: 100%; - font-size: 18px; + font-size: $font-18px; text-align: center; pointer-events: none; @@ -186,7 +186,7 @@ limitations under the License. .mx_RoomView_empty { flex: 1 1 auto; - font-size: 13px; + font-size: $font-13px; padding-left: 3em; padding-right: 3em; margin-right: 20px; diff --git a/res/css/structures/_TabbedView.scss b/res/css/structures/_TabbedView.scss index 7904df5a82..4a4bb125a3 100644 --- a/res/css/structures/_TabbedView.scss +++ b/res/css/structures/_TabbedView.scss @@ -39,7 +39,7 @@ limitations under the License. cursor: pointer; display: block; border-radius: 3px; - font-size: 14px; + font-size: $font-14px; min-height: 24px; // use min-height instead of height to allow the label to overflow a bit margin-bottom: 6px; position: relative; diff --git a/res/css/structures/_TagPanel.scss b/res/css/structures/_TagPanel.scss index dddd2e324c..4a78c8df92 100644 --- a/res/css/structures/_TagPanel.scss +++ b/res/css/structures/_TagPanel.scss @@ -23,6 +23,7 @@ limitations under the License. flex-direction: column; align-items: center; justify-content: space-between; + min-height: 0; } .mx_TagPanel_items_selected { @@ -57,6 +58,7 @@ limitations under the License. .mx_TagPanel .mx_TagPanel_scroller { flex-grow: 1; + width: 100%; } .mx_TagPanel .mx_TagPanel_tagTileContainer { @@ -67,7 +69,7 @@ limitations under the License. height: 100%; } .mx_TagPanel .mx_TagPanel_tagTileContainer > div { - height: 40px; + height: $font-40px; padding: 10px 0 9px 0; } @@ -108,13 +110,13 @@ limitations under the License. .mx_TagPanel .mx_TagTile.mx_TagTile_selected::before { content: ''; - height: 56px; + height: calc(100% + 16px); background-color: $accent-color; width: 5px; position: absolute; left: -15px; border-radius: 0 3px 3px 0; - top: -8px; // (56 - 40)/2 + top: -8px; // (16px / 2) } .mx_TagPanel .mx_TagTile.mx_AccessibleButton:focus { @@ -135,9 +137,9 @@ limitations under the License. top: -8px; border-radius: 8px; background-color: $neutral-badge-color; - color: #ffffff; + color: #000; font-weight: 600; - font-size: 10px; + font-size: $font-10px; text-align: center; padding-top: 1px; padding-left: 4px; @@ -155,7 +157,7 @@ limitations under the License. border-radius: 8px; color: $accent-fg-color; font-weight: 600; - font-size: 14px; + font-size: $font-14px; padding: 0 5px; background-color: $roomtile-name-color; } diff --git a/res/css/structures/_ToastContainer.scss b/res/css/structures/_ToastContainer.scss index d1687743d6..6ec4a0d152 100644 --- a/res/css/structures/_ToastContainer.scss +++ b/res/css/structures/_ToastContainer.scss @@ -77,7 +77,7 @@ limitations under the License. grid-column: 1 / 3; grid-row: 1; margin: 0; - font-size: 15px; + font-size: $font-15px; font-weight: 600; } @@ -91,16 +91,15 @@ limitations under the License. } .mx_Toast_description { - max-width: 400px; + max-width: 272px; overflow: hidden; - white-space: nowrap; text-overflow: ellipsis; margin: 4px 0 11px 0; - font-size: 12px; + font-size: $font-12px; } .mx_Toast_deviceID { - font-size: 10px; + font-size: $font-10px; } } } diff --git a/res/css/structures/_TopLeftMenuButton.scss b/res/css/structures/_TopLeftMenuButton.scss index ee03978f18..53d44e7c24 100644 --- a/res/css/structures/_TopLeftMenuButton.scss +++ b/res/css/structures/_TopLeftMenuButton.scss @@ -32,7 +32,7 @@ limitations under the License. .mx_TopLeftMenuButton_name { margin: 0 7px; - font-size: 18px; + font-size: $font-18px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; diff --git a/res/css/structures/_ViewSource.scss b/res/css/structures/_ViewSource.scss index b908861c6f..421d1f03cd 100644 --- a/res/css/structures/_ViewSource.scss +++ b/res/css/structures/_ViewSource.scss @@ -29,7 +29,7 @@ limitations under the License. .mx_ViewSource pre { text-align: left; - font-size: 12px; + font-size: $font-12px; padding: 0.5em 1em 0.5em 1em; word-wrap: break-word; white-space: pre-wrap; diff --git a/res/css/structures/auth/_CompleteSecurity.scss b/res/css/structures/auth/_CompleteSecurity.scss index 2bf51d9574..f742be70e4 100644 --- a/res/css/structures/auth/_CompleteSecurity.scss +++ b/res/css/structures/auth/_CompleteSecurity.scss @@ -26,6 +26,50 @@ limitations under the License. position: relative; } +.mx_CompleteSecurity_clients { + width: max-content; + margin: 36px auto 0; + + .mx_CompleteSecurity_clients_desktop, .mx_CompleteSecurity_clients_mobile { + position: relative; + width: 160px; + text-align: center; + padding-top: 64px; + display: inline-block; + + &::before { + content: ''; + position: absolute; + height: 48px; + width: 48px; + left: 56px; + top: 0; + background-color: $muted-fg-color; + mask-repeat: no-repeat; + mask-size: contain; + } + } + + .mx_CompleteSecurity_clients_desktop { + margin-right: 56px; + } + + .mx_CompleteSecurity_clients_desktop::before { + mask-image: url('$(res)/img/feather-customised/monitor.svg'); + } + + .mx_CompleteSecurity_clients_mobile::before { + mask-image: url('$(res)/img/feather-customised/smartphone.svg'); + } + + p { + margin-top: 16px; + font-size: $font-12px; + color: $muted-fg-color; + text-align: center; + } +} + .mx_CompleteSecurity_heroIcon { width: 128px; height: 128px; @@ -34,12 +78,17 @@ limitations under the License. } .mx_CompleteSecurity_body { - font-size: 15px; + font-size: $font-15px; +} + +.mx_CompleteSecurity_waiting { + color: $notice-secondary-color; } .mx_CompleteSecurity_actionRow { display: flex; justify-content: flex-end; + margin-top: $font-28px; .mx_AccessibleButton { margin-inline-start: 18px; diff --git a/res/css/structures/auth/_Login.scss b/res/css/structures/auth/_Login.scss index 4ce90cc6bd..02436833a2 100644 --- a/res/css/structures/auth/_Login.scss +++ b/res/css/structures/auth/_Login.scss @@ -89,3 +89,13 @@ limitations under the License. .mx_Login_underlinedServerName { border-bottom: 1px dashed $accent-color; } + +div.mx_AccessibleButton_kind_link.mx_Login_forgot { + // style it as a link + font-size: inherit; + padding: 0; + + &.mx_AccessibleButton_disabled { + cursor: not-allowed; + } +} diff --git a/res/css/views/auth/_AuthBody.scss b/res/css/views/auth/_AuthBody.scss index 7c5b008535..4b2d6b1bf1 100644 --- a/res/css/views/auth/_AuthBody.scss +++ b/res/css/views/auth/_AuthBody.scss @@ -17,7 +17,7 @@ limitations under the License. .mx_AuthBody { width: 500px; - font-size: 12px; + font-size: $font-12px; color: $authpage-secondary-color; background-color: $authpage-body-bg-color; border-radius: 0 4px 4px 0; @@ -25,14 +25,14 @@ limitations under the License. box-sizing: border-box; h2 { - font-size: 24px; + font-size: $font-24px; font-weight: 600; margin-top: 8px; color: $authpage-primary-color; } h3 { - font-size: 14px; + font-size: $font-14px; font-weight: 600; color: $authpage-primary-color; } @@ -98,7 +98,7 @@ limitations under the License. .mx_AuthBody_editServerDetails { padding-left: 1em; - font-size: 12px; + font-size: $font-12px; font-weight: normal; } @@ -119,6 +119,24 @@ limitations under the License. margin-right: 0; } +.mx_AuthBody_paddedFooter { + height: 80px; // height of the submit button + register link + padding-top: 28px; + text-align: center; + + .mx_AuthBody_paddedFooter_title { + margin-top: 16px; + font-size: $font-15px; + line-height: $font-24px; + } + + .mx_AuthBody_paddedFooter_subtitle { + margin-top: 8px; + font-size: $font-10px; + line-height: $font-14px; + } +} + .mx_AuthBody_changeFlow { display: block; text-align: center; diff --git a/res/css/views/auth/_AuthButtons.scss b/res/css/views/auth/_AuthButtons.scss index 553adeee14..8deb0f80ac 100644 --- a/res/css/views/auth/_AuthButtons.scss +++ b/res/css/views/auth/_AuthButtons.scss @@ -43,7 +43,7 @@ limitations under the License. cursor: pointer; - font-size: 15px; + font-size: $font-15px; padding: 0 11px; word-break: break-word; } diff --git a/res/css/views/auth/_AuthFooter.scss b/res/css/views/auth/_AuthFooter.scss index ab169a6898..0bc2743d54 100644 --- a/res/css/views/auth/_AuthFooter.scss +++ b/res/css/views/auth/_AuthFooter.scss @@ -17,7 +17,7 @@ limitations under the License. .mx_AuthFooter { text-align: center; width: 100%; - font-size: 14px; + font-size: $font-14px; opacity: 0.72; padding: 20px 0; background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.8)); diff --git a/res/css/views/auth/_CompleteSecurityBody.scss b/res/css/views/auth/_CompleteSecurityBody.scss index c7860fbe74..46b7abe2cc 100644 --- a/res/css/views/auth/_CompleteSecurityBody.scss +++ b/res/css/views/auth/_CompleteSecurityBody.scss @@ -24,13 +24,13 @@ limitations under the License. box-sizing: border-box; h2 { - font-size: 24px; + font-size: $font-24px; font-weight: 600; margin-top: 0; } h3 { - font-size: 14px; + font-size: $font-14px; font-weight: 600; } diff --git a/res/css/views/auth/_InteractiveAuthEntryComponents.scss b/res/css/views/auth/_InteractiveAuthEntryComponents.scss index 85007aeecb..05cddf2c48 100644 --- a/res/css/views/auth/_InteractiveAuthEntryComponents.scss +++ b/res/css/views/auth/_InteractiveAuthEntryComponents.scss @@ -60,3 +60,14 @@ limitations under the License. .mx_InteractiveAuthEntryComponents_passwordSection { width: 300px; } + +.mx_InteractiveAuthEntryComponents_sso_buttons { + display: flex; + flex-direction: row; + justify-content: flex-end; + margin-top: 20px; + + .mx_AccessibleButton { + margin-left: 5px; + } +} diff --git a/res/css/views/auth/_LanguageSelector.scss b/res/css/views/auth/_LanguageSelector.scss index 6f7eac0cf6..781561f876 100644 --- a/res/css/views/auth/_LanguageSelector.scss +++ b/res/css/views/auth/_LanguageSelector.scss @@ -20,7 +20,7 @@ limitations under the License. .mx_AuthBody_language .mx_Dropdown_input { border: none; - font-size: 14px; + font-size: $font-14px; font-weight: 600; color: $authpage-lang-color; } diff --git a/res/css/views/auth/_ServerTypeSelector.scss b/res/css/views/auth/_ServerTypeSelector.scss index ed781726b7..fbd3d2655d 100644 --- a/res/css/views/auth/_ServerTypeSelector.scss +++ b/res/css/views/auth/_ServerTypeSelector.scss @@ -65,5 +65,5 @@ limitations under the License. } .mx_ServerTypeSelector_description { - font-size: 10px; + font-size: $font-10px; } diff --git a/res/css/views/avatars/_MemberStatusMessageAvatar.scss b/res/css/views/avatars/_MemberStatusMessageAvatar.scss index c101a5d8a8..975b4e5ce9 100644 --- a/res/css/views/avatars/_MemberStatusMessageAvatar.scss +++ b/res/css/views/avatars/_MemberStatusMessageAvatar.scss @@ -17,7 +17,7 @@ limitations under the License. .mx_MessageComposer_avatar .mx_BaseAvatar { padding: 2px; border: 1px solid transparent; - border-radius: 15px; + border-radius: 100%; } .mx_MessageComposer_avatar .mx_BaseAvatar_initial { diff --git a/res/css/views/context_menus/_MessageContextMenu.scss b/res/css/views/context_menus/_MessageContextMenu.scss index d15d566bdb..2ecb93e734 100644 --- a/res/css/views/context_menus/_MessageContextMenu.scss +++ b/res/css/views/context_menus/_MessageContextMenu.scss @@ -19,6 +19,7 @@ limitations under the License. } .mx_MessageContextMenu_field { + display: block; padding: 3px 6px 3px 6px; cursor: pointer; white-space: nowrap; diff --git a/res/css/views/context_menus/_RoomTileContextMenu.scss b/res/css/views/context_menus/_RoomTileContextMenu.scss index 308cecfe1e..9697ac9bef 100644 --- a/res/css/views/context_menus/_RoomTileContextMenu.scss +++ b/res/css/views/context_menus/_RoomTileContextMenu.scss @@ -38,7 +38,7 @@ limitations under the License. white-space: nowrap; display: flex; align-items: center; - line-height: 16px; + line-height: $font-16px; } .mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldSet { diff --git a/res/css/views/context_menus/_StatusMessageContextMenu.scss b/res/css/views/context_menus/_StatusMessageContextMenu.scss index 2c8d608950..fceb7fba34 100644 --- a/res/css/views/context_menus/_StatusMessageContextMenu.scss +++ b/res/css/views/context_menus/_StatusMessageContextMenu.scss @@ -44,7 +44,7 @@ input.mx_StatusMessageContextMenu_message { .mx_StatusMessageContextMenu_clear { @mixin mx_DialogButton; align-self: start; - font-size: 12px; + font-size: $font-12px; padding: 6px 1em; border: 1px solid transparent; margin-right: 10px; diff --git a/res/css/views/context_menus/_TagTileContextMenu.scss b/res/css/views/context_menus/_TagTileContextMenu.scss index 46b279ce2d..e4ccc030a2 100644 --- a/res/css/views/context_menus/_TagTileContextMenu.scss +++ b/res/css/views/context_menus/_TagTileContextMenu.scss @@ -22,7 +22,7 @@ limitations under the License. white-space: nowrap; display: flex; align-items: center; - line-height: 16px; + line-height: $font-16px; } .mx_TagTileContextMenu_item object { diff --git a/res/css/views/context_menus/_TopLeftMenu.scss b/res/css/views/context_menus/_TopLeftMenu.scss index ed0d0106bc..e0f5dd47bd 100644 --- a/res/css/views/context_menus/_TopLeftMenu.scss +++ b/res/css/views/context_menus/_TopLeftMenu.scss @@ -19,12 +19,12 @@ limitations under the License. border-radius: 4px; .mx_TopLeftMenu_greyedText { - font-size: 12px; + font-size: $font-12px; opacity: 0.5; } .mx_TopLeftMenu_upgradeLink { - font-size: 12px; + font-size: $font-12px; img { margin-left: 5px; @@ -72,10 +72,10 @@ limitations under the License. .mx_AccessibleButton::after { mask-repeat: no-repeat; mask-position: 0 center; - mask-size: 16px; + mask-size: $font-16px; position: absolute; - width: 16px; - height: 16px; + width: $font-16px; + height: $font-16px; content: ""; top: 5px; left: 14px; diff --git a/res/css/views/dialogs/_AddressPickerDialog.scss b/res/css/views/dialogs/_AddressPickerDialog.scss index 39a9260ba3..136e497994 100644 --- a/res/css/views/dialogs/_AddressPickerDialog.scss +++ b/res/css/views/dialogs/_AddressPickerDialog.scss @@ -28,7 +28,7 @@ limitations under the License. .mx_AddressPickerDialog_input, .mx_AddressPickerDialog_input:focus { height: 26px; - font-size: 14px; + font-size: $font-14px; font-family: $font-family; padding-left: 12px; padding-right: 12px; @@ -50,7 +50,7 @@ limitations under the License. .mx_AddressPickerDialog_inputContainer { border-radius: 3px; border: solid 1px $input-border-color; - line-height: 36px; + line-height: $font-36px; padding-left: 4px; padding-right: 4px; padding-top: 1px; diff --git a/res/css/views/dialogs/_ConfirmUserActionDialog.scss b/res/css/views/dialogs/_ConfirmUserActionDialog.scss index b859d6bf4d..823f4d1e28 100644 --- a/res/css/views/dialogs/_ConfirmUserActionDialog.scss +++ b/res/css/views/dialogs/_ConfirmUserActionDialog.scss @@ -26,22 +26,22 @@ limitations under the License. } .mx_ConfirmUserActionDialog_name { - font-size: 18px; + font-size: $font-18px; } .mx_ConfirmUserActionDialog_userId { - font-size: 13px; + font-size: $font-13px; } .mx_ConfirmUserActionDialog_reasonField { font-family: $font-family; - font-size: 14px; + font-size: $font-14px; color: $primary-fg-color; background-color: $primary-bg-color; border-radius: 3px; border: solid 1px $input-border-color; - line-height: 36px; + line-height: $font-36px; padding-left: 16px; padding-right: 16px; padding-top: 1px; diff --git a/res/css/views/dialogs/_CreateGroupDialog.scss b/res/css/views/dialogs/_CreateGroupDialog.scss index 128eacc3ce..f7bfc61a98 100644 --- a/res/css/views/dialogs/_CreateGroupDialog.scss +++ b/res/css/views/dialogs/_CreateGroupDialog.scss @@ -25,7 +25,7 @@ limitations under the License. } .mx_CreateGroupDialog_input { - font-size: 15px; + font-size: $font-15px; border-radius: 3px; border: 1px solid $input-border-color; padding: 9px; @@ -44,7 +44,7 @@ limitations under the License. .mx_CreateGroupDialog_prefix, .mx_CreateGroupDialog_suffix { padding: 0px 5px; - line-height: 37px; + line-height: $font-37px; background-color: $input-darker-bg-color; border: 1px solid $input-border-color; text-align: center; diff --git a/res/css/views/dialogs/_CreateRoomDialog.scss b/res/css/views/dialogs/_CreateRoomDialog.scss index 7416ec2ef4..2678f7b4ad 100644 --- a/res/css/views/dialogs/_CreateRoomDialog.scss +++ b/res/css/views/dialogs/_CreateRoomDialog.scss @@ -15,6 +15,8 @@ limitations under the License. */ .mx_CreateRoomDialog_details { + margin-top: 15px; + .mx_CreateRoomDialog_details_summary { outline: none; list-style: none; @@ -49,7 +51,7 @@ limitations under the License. } .mx_CreateRoomDialog_input { - font-size: 15px; + font-size: $font-15px; border-radius: 3px; border: 1px solid $input-border-color; padding: 9px; @@ -71,11 +73,19 @@ limitations under the License. } .mx_CreateRoomDialog { - &.mx_Dialog_fixedWidth { width: 450px; } + .mx_Dialog_content { + margin-bottom: 40px; + } + + p, + .mx_Field_input label { + color: $muted-fg-color; + } + .mx_SettingsFlag { display: flex; } @@ -90,5 +100,18 @@ limitations under the License. flex: 0 0 auto; margin-left: 30px; } + + .mx_CreateRoomDialog_topic { + margin-bottom: 36px; + } + + .mx_Dialog_content > .mx_SettingsFlag { + margin-top: 24px; + } + + p { + margin: 0 85px 0 0; + font-size: $font-12px; + } } diff --git a/res/css/views/dialogs/_DevtoolsDialog.scss b/res/css/views/dialogs/_DevtoolsDialog.scss index 9d58c999c3..35cb6bc7ab 100644 --- a/res/css/views/dialogs/_DevtoolsDialog.scss +++ b/res/css/views/dialogs/_DevtoolsDialog.scss @@ -68,11 +68,11 @@ limitations under the License. width: 240px; color: $input-fg-color; font-family: $font-family; - font-size: 16px; + font-size: $font-16px; } .mx_DevTools_textarea { - font-size: 12px; + font-size: $font-12px; max-width: 684px; min-height: 250px; padding: 10px; @@ -189,3 +189,37 @@ limitations under the License. } } } + +.mx_DevTools_VerificationRequest { + border: 1px solid #cccccc; + border-radius: 3px; + padding: 1px 5px; + margin-bottom: 6px; + font-family: $monospace-font-family; + + dl { + display: grid; + grid-template-columns: max-content auto; + margin: 0; + } + + dd { + grid-column-start: 2; + } + + dd:empty { + color: #666666; + &::after { + content: "(empty)"; + } + } + + dt { + font-weight: bold; + grid-column-start: 1; + } + + dt::after { + content: ":"; + } +} diff --git a/res/css/views/dialogs/_InviteDialog.scss b/res/css/views/dialogs/_InviteDialog.scss index 5e0893b8fd..a77d0bfbba 100644 --- a/res/css/views/dialogs/_InviteDialog.scss +++ b/res/css/views/dialogs/_InviteDialog.scss @@ -40,8 +40,8 @@ limitations under the License. textarea, textarea:focus { height: 34px; - line-height: 34px; - font-size: 14px; + line-height: $font-34px; + font-size: $font-14px; padding-left: 12px; margin: 0 !important; border: 0 !important; @@ -65,7 +65,7 @@ limitations under the License. min-width: 48px; margin-left: 10px; height: 25px; - line-height: 25px; + line-height: $font-25px; } .mx_InviteDialog_buttonAndSpinner { @@ -84,7 +84,7 @@ limitations under the License. padding-bottom: 10px; h3 { - font-size: 12px; + font-size: $font-12px; color: $muted-fg-color; font-weight: bold; text-transform: uppercase; @@ -143,23 +143,23 @@ limitations under the License. .mx_InviteDialog_roomTile_name { font-weight: 600; - font-size: 14px; + font-size: $font-14px; color: $primary-fg-color; margin-left: 7px; } .mx_InviteDialog_roomTile_userId { - font-size: 12px; + font-size: $font-12px; color: $muted-fg-color; margin-left: 7px; } .mx_InviteDialog_roomTile_time { text-align: right; - font-size: 12px; + font-size: $font-12px; color: $muted-fg-color; float: right; - line-height: 36px; // Height of the avatar to keep the time vertically aligned + line-height: $font-36px; // Height of the avatar to keep the time vertically aligned } .mx_InviteDialog_roomTile_highlight { @@ -176,7 +176,7 @@ limitations under the License. border-radius: 12px; display: inline-block; height: 24px; - line-height: 24px; + line-height: $font-24px; padding-left: 8px; padding-right: 8px; color: #ffffff; // this is fine without a var because it's for both themes diff --git a/res/css/views/dialogs/_KeyboardShortcutsDialog.scss b/res/css/views/dialogs/_KeyboardShortcutsDialog.scss new file mode 100644 index 0000000000..638cacd41f --- /dev/null +++ b/res/css/views/dialogs/_KeyboardShortcutsDialog.scss @@ -0,0 +1,65 @@ +/* +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_KeyboardShortcutsDialog { + display: flex; + flex-wrap: wrap; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + flex-direction: column; + margin-bottom: -50px; + max-height: 1100px; // XXX: this may need adjusting when adding new shortcuts + + .mx_KeyboardShortcutsDialog_category { + width: 33.3333%; // 3 columns + margin: 0 0 40px; + + & > div { + padding-left: 5px; + } + } + + h3 { + margin: 0 0 10px; + } + + h5 { + margin: 15px 0 5px; + font-weight: normal; + } + + kbd { + padding: 5px; + border-radius: 4px; + background-color: $reaction-row-button-bg-color; + margin-right: 5px; + min-width: 20px; + text-align: center; + display: inline-block; + border: 1px solid $kbd-border-color; + box-shadow: 0 2px $kbd-border-color; + margin-bottom: 4px; + text-transform: capitalize; + + & + kbd { + margin-left: 5px; + } + } + + .mx_KeyboardShortcutsDialog_inline div { + display: inline; + } +} diff --git a/res/css/views/dialogs/_MessageEditHistoryDialog.scss b/res/css/views/dialogs/_MessageEditHistoryDialog.scss index 0066faccae..e9d777effd 100644 --- a/res/css/views/dialogs/_MessageEditHistoryDialog.scss +++ b/res/css/views/dialogs/_MessageEditHistoryDialog.scss @@ -35,7 +35,7 @@ limitations under the License. .mx_MessageEditHistoryDialog_edits { list-style-type: none; - font-size: 14px; + font-size: $font-14px; padding: 0; color: $primary-fg-color; @@ -60,7 +60,7 @@ limitations under the License. } .mx_MessageActionBar .mx_AccessibleButton { - font-size: 10px; + font-size: $font-10px; padding: 0 8px; } } diff --git a/res/css/views/dialogs/_NewSessionReviewDialog.scss b/res/css/views/dialogs/_NewSessionReviewDialog.scss index 7e35fe941e..b35c570c80 100644 --- a/res/css/views/dialogs/_NewSessionReviewDialog.scss +++ b/res/css/views/dialogs/_NewSessionReviewDialog.scss @@ -32,6 +32,6 @@ limitations under the License. } .mx_NewSessionReviewDialog_deviceID { - font-size: 12px; + font-size: $font-12px; color: $notice-secondary-color; } diff --git a/res/css/views/dialogs/_RoomSettingsDialog.scss b/res/css/views/dialogs/_RoomSettingsDialog.scss index 2a4e62f9aa..3751c15643 100644 --- a/res/css/views/dialogs/_RoomSettingsDialog.scss +++ b/res/css/views/dialogs/_RoomSettingsDialog.scss @@ -29,6 +29,10 @@ limitations under the License. mask-image: url('$(res)/img/feather-customised/users-sm.svg'); } +.mx_RoomSettingsDialog_notificationsIcon::before { + mask-image: url('$(res)/img/feather-customised/notifications.svg'); +} + .mx_RoomSettingsDialog_bridgesIcon::before { // This icon is pants, please improve :) mask-image: url('$(res)/img/feather-customised/bridge.svg'); diff --git a/res/css/views/dialogs/_SetEmailDialog.scss b/res/css/views/dialogs/_SetEmailDialog.scss index 9d09a208df..37bee7a9ff 100644 --- a/res/css/views/dialogs/_SetEmailDialog.scss +++ b/res/css/views/dialogs/_SetEmailDialog.scss @@ -20,7 +20,7 @@ limitations under the License. padding: 9px; color: $input-fg-color; background-color: $primary-bg-color; - font-size: 15px; + font-size: $font-15px; width: 100%; max-width: 280px; margin-bottom: 10px; diff --git a/res/css/views/dialogs/_SetMxIdDialog.scss b/res/css/views/dialogs/_SetMxIdDialog.scss index f7d8a3d001..1df34f3408 100644 --- a/res/css/views/dialogs/_SetMxIdDialog.scss +++ b/res/css/views/dialogs/_SetMxIdDialog.scss @@ -29,7 +29,7 @@ limitations under the License. padding: 9px; color: $primary-fg-color; background-color: $primary-bg-color; - font-size: 15px; + font-size: $font-15px; width: 100%; max-width: 280px; } diff --git a/res/css/views/dialogs/_SetPasswordDialog.scss b/res/css/views/dialogs/_SetPasswordDialog.scss index 325ff6c6ed..1f99353298 100644 --- a/res/css/views/dialogs/_SetPasswordDialog.scss +++ b/res/css/views/dialogs/_SetPasswordDialog.scss @@ -20,7 +20,7 @@ limitations under the License. padding: 9px; color: $primary-fg-color; background-color: $primary-bg-color; - font-size: 15px; + font-size: $font-15px; max-width: 280px; margin-bottom: 10px; } diff --git a/res/css/views/dialogs/_ShareDialog.scss b/res/css/views/dialogs/_ShareDialog.scss index 9a2f67dea3..e08469ec6d 100644 --- a/res/css/views/dialogs/_ShareDialog.scss +++ b/res/css/views/dialogs/_ShareDialog.scss @@ -64,9 +64,6 @@ limitations under the License. .mx_ShareDialog_qrcode_container { float: left; - background-color: #ffffff; - padding: 5px; // makes qr code more readable in dark theme - border-radius: 5px; height: 256px; width: 256px; margin-right: 64px; diff --git a/res/css/views/dialogs/_TermsDialog.scss b/res/css/views/dialogs/_TermsDialog.scss index beb507e778..939a31dee6 100644 --- a/res/css/views/dialogs/_TermsDialog.scss +++ b/res/css/views/dialogs/_TermsDialog.scss @@ -31,7 +31,7 @@ limitations under the License. } .mx_TermsDialog_termsTable { - font-size: 12px; + font-size: $font-12px; width: 100%; } diff --git a/res/css/views/dialogs/_UnknownDeviceDialog.scss b/res/css/views/dialogs/_UnknownDeviceDialog.scss index 02e0fb1fe5..daa6bd2352 100644 --- a/res/css/views/dialogs/_UnknownDeviceDialog.scss +++ b/res/css/views/dialogs/_UnknownDeviceDialog.scss @@ -14,14 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -// CSS voodoo to support a gemini-scrollbar for the contents of the dialog -.mx_Dialog_unknownDevice .mx_Dialog { - // ideally we'd shrink the height to fit when needed, but in practice this - // is a pain in the ass. plus might as well make the dialog big given how - // important it is. - height: 100%; -} - .mx_UnknownDeviceDialog { height: 100%; display: flex; @@ -35,7 +27,7 @@ limitations under the License. // userid .mx_UnknownDeviceDialog p { font-weight: bold; - font-size: 16px; + font-size: $font-16px; } .mx_UnknownDeviceDialog .mx_DeviceVerifyButtons { @@ -44,6 +36,7 @@ limitations under the License. .mx_UnknownDeviceDialog .mx_Dialog_content { margin-bottom: 24px; + overflow-y: scroll; } .mx_UnknownDeviceDialog_deviceList > li { diff --git a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss index 9cba8e0da9..5689d84bc5 100644 --- a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss +++ b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss @@ -32,3 +32,9 @@ limitations under the License. padding: 10px; } +.mx_RestoreKeyBackupDialog_content > div { + display: flex; + flex-direction: column; + justify-content: space-between; + min-height: 110px; /* Empirically measured */ +} diff --git a/res/css/views/directory/_NetworkDropdown.scss b/res/css/views/directory/_NetworkDropdown.scss index d402f6c48f..bd5c67c7ed 100644 --- a/res/css/views/directory/_NetworkDropdown.scss +++ b/res/css/views/directory/_NetworkDropdown.scss @@ -1,5 +1,5 @@ /* -Copyright 2015, 2016 OpenMarket Ltd +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. @@ -15,70 +15,152 @@ limitations under the License. */ .mx_NetworkDropdown { + height: 32px; position: relative; -} + width: max-content; + padding-right: 32px; + margin-left: auto; + margin-right: 9px; + margin-top: 12px; -.mx_NetworkDropdown_input { - position: relative; - border-radius: 3px; - border: 1px solid $strong-input-border-color; - font-weight: 300; - font-size: 13px; - user-select: none; -} - -.mx_NetworkDropdown_arrow { - border-color: $primary-fg-color transparent transparent; - border-style: solid; - border-width: 5px 5px 0; - display: block; - height: 0; - position: absolute; - right: 10px; - top: 16px; - width: 0; -} - -.mx_NetworkDropdown_networkoption { - height: 37px; - line-height: 37px; - padding-left: 8px; - padding-right: 8px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -.mx_NetworkDropdown_networkoption img { - margin: 5px; - width: 25px; - vertical-align: middle; -} - -input.mx_NetworkDropdown_networkoption, input.mx_NetworkDropdown_networkoption:focus { - border: 0; - padding-top: 0; - padding-bottom: 0; + .mx_AccessibleButton { + width: max-content; + } } .mx_NetworkDropdown_menu { - position: absolute; - left: -1px; - right: -1px; - top: 100%; - z-index: 2; + min-width: 204px; margin: 0; - padding: 0px; - border-radius: 3px; - border: 1px solid $accent-color; + box-sizing: border-box; + border-radius: 4px; + border: 1px solid $dialog-close-fg-color; background-color: $primary-bg-color; -} - -.mx_NetworkDropdown_menu .mx_NetworkDropdown_networkoption:hover { - background-color: $focus-bg-color; + max-height: calc(100vh - 20px); // allow 10px padding on both top and bottom + overflow-y: auto; } .mx_NetworkDropdown_menu_network { font-weight: bold; } +.mx_NetworkDropdown_server { + padding: 12px 0; + border-bottom: 1px solid $input-darker-fg-color; + + .mx_NetworkDropdown_server_title { + padding: 0 10px; + font-size: $font-15px; + font-weight: 600; + line-height: $font-20px; + margin-bottom: 4px; + position: relative; + + // remove server button + .mx_AccessibleButton { + position: absolute; + display: inline; + right: 10px; + height: 16px; + width: 16px; + margin-top: 2px; + + &::after { + content: ""; + position: absolute; + width: 16px; + height: 16px; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + mask-image: url('$(res)/img/feather-customised/x.svg'); + background-color: $notice-primary-color; + } + } + } + + .mx_NetworkDropdown_server_subtitle { + padding: 0 10px; + font-size: $font-10px; + line-height: $font-14px; + margin-top: -4px; + margin-bottom: 4px; + color: $muted-fg-color; + } + + .mx_NetworkDropdown_server_network { + font-size: $font-12px; + line-height: $font-16px; + padding: 4px 10px; + cursor: pointer; + position: relative; + + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + + &[aria-checked=true]::after { + content: ""; + position: absolute; + width: 16px; + height: 16px; + right: 10px; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + mask-image: url('$(res)/img/feather-customised/check.svg'); + background-color: $input-valid-border-color; + } + } +} + +.mx_NetworkDropdown_server_add, +.mx_NetworkDropdown_server_network { + &:hover { + background-color: $header-panel-bg-color; + } +} + +.mx_NetworkDropdown_server_add { + padding: 16px 10px 16px 32px; + position: relative; + border-radius: 0 0 4px 4px; + + &::before { + content: ""; + position: absolute; + width: 16px; + height: 16px; + left: 7px; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + mask-image: url('$(res)/img/feather-customised/plus.svg'); + background-color: $muted-fg-color; + } +} + +.mx_NetworkDropdown_handle { + position: relative; + + &::after { + content: ""; + position: absolute; + width: 24px; + height: 24px; + right: -28px; // - (24 + 4) + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); + background-color: $primary-fg-color; + } + + .mx_NetworkDropdown_handle_server { + color: $muted-fg-color; + font-size: $font-12px; + } +} + +.mx_NetworkDropdown_dialog .mx_Dialog { + width: 45vw; +} diff --git a/res/css/views/elements/_AccessibleButton.scss b/res/css/views/elements/_AccessibleButton.scss index b87071745d..96269cea43 100644 --- a/res/css/views/elements/_AccessibleButton.scss +++ b/res/css/views/elements/_AccessibleButton.scss @@ -27,7 +27,7 @@ limitations under the License. text-align: center; border-radius: 4px; display: inline-block; - font-size: 14px; + font-size: $font-14px; } .mx_AccessibleButton_kind_primary { @@ -36,12 +36,20 @@ limitations under the License. font-weight: 600; } +.mx_AccessibleButton_kind_primary_outline { + color: $button-primary-bg-color; + background-color: $button-secondary-bg-color; + border: 1px solid $button-primary-bg-color; + font-weight: 600; +} + .mx_AccessibleButton_kind_secondary { color: $accent-color; font-weight: 600; } -.mx_AccessibleButton_kind_primary.mx_AccessibleButton_disabled { +.mx_AccessibleButton_kind_primary.mx_AccessibleButton_disabled, +.mx_AccessibleButton_kind_primary_outline.mx_AccessibleButton_disabled { opacity: 0.4; } @@ -60,7 +68,14 @@ limitations under the License. background-color: $button-danger-bg-color; } -.mx_AccessibleButton_kind_danger.mx_AccessibleButton_disabled { +.mx_AccessibleButton_kind_danger_outline { + color: $button-danger-bg-color; + background-color: $button-secondary-bg-color; + border: 1px solid $button-danger-bg-color; +} + +.mx_AccessibleButton_kind_danger.mx_AccessibleButton_disabled, +.mx_AccessibleButton_kind_danger_outline.mx_AccessibleButton_disabled { color: $button-danger-disabled-fg-color; background-color: $button-danger-disabled-bg-color; } diff --git a/res/css/views/elements/_AddressTile.scss b/res/css/views/elements/_AddressTile.scss index 0ecfb17c83..c42f52f8f4 100644 --- a/res/css/views/elements/_AddressTile.scss +++ b/res/css/views/elements/_AddressTile.scss @@ -19,9 +19,9 @@ limitations under the License. border-radius: 3px; background-color: rgba(74, 73, 74, 0.1); border: solid 1px $input-border-color; - line-height: 26px; + line-height: $font-26px; color: $primary-fg-color; - font-size: 14px; + font-size: $font-14px; font-weight: normal; margin-right: 4px; } diff --git a/res/css/views/elements/_DirectorySearchBox.scss b/res/css/views/elements/_DirectorySearchBox.scss index ef944f6fa0..e4b1ac5574 100644 --- a/res/css/views/elements/_DirectorySearchBox.scss +++ b/res/css/views/elements/_DirectorySearchBox.scss @@ -18,7 +18,6 @@ limitations under the License. display: flex; padding-left: 9px; padding-right: 9px; - margin: 0 5px 0 0 !important; } .mx_DirectorySearchBox_joinButton { @@ -33,7 +32,7 @@ limitations under the License. background-repeat: no-repeat; text-indent: 18px; font-weight: 600; - font-size: 12px; + font-size: $font-12px; user-select: none; cursor: pointer; } diff --git a/res/css/views/elements/_Dropdown.scss b/res/css/views/elements/_Dropdown.scss index 102ac56bf9..2a2508c17c 100644 --- a/res/css/views/elements/_Dropdown.scss +++ b/res/css/views/elements/_Dropdown.scss @@ -29,10 +29,14 @@ limitations under the License. position: relative; border-radius: 3px; border: 1px solid $strong-input-border-color; - font-size: 12px; + font-size: $font-12px; user-select: none; } +.mx_Dropdown_input.mx_AccessibleButton_disabled { + cursor: not-allowed; +} + .mx_Dropdown_input:focus { border-color: $input-focused-border-color; } @@ -53,7 +57,7 @@ limitations under the License. .mx_Dropdown_option { height: 35px; - line-height: 35px; + line-height: $font-35px; padding-left: 8px; padding-right: 8px; } @@ -63,6 +67,8 @@ limitations under the License. text-overflow: ellipsis; white-space: nowrap; flex: 1; + display: inline-flex; + align-items: center; } .mx_Dropdown_option div { @@ -71,12 +77,18 @@ limitations under the License. white-space: nowrap; } -.mx_Dropdown_option img { +.mx_Dropdown_option img, +.mx_Dropdown_option .mx_Dropdown_option_emoji { margin: 5px; width: 16px; vertical-align: middle; } +.mx_Dropdown_option_emoji { + font-size: $font-16px; + line-height: $font-16px; +} + input.mx_Dropdown_option, input.mx_Dropdown_option:focus { font-weight: normal; diff --git a/res/css/views/elements/_EditableItemList.scss b/res/css/views/elements/_EditableItemList.scss index 51fa4c4423..f089fa3dc2 100644 --- a/res/css/views/elements/_EditableItemList.scss +++ b/res/css/views/elements/_EditableItemList.scss @@ -20,14 +20,21 @@ limitations under the License. } .mx_EditableItem { + display: flex; margin-bottom: 5px; - margin-left: 15px; } .mx_EditableItem_delete { + order: 3; margin-right: 5px; cursor: pointer; vertical-align: middle; + width: 14px; + height: 14px; + mask-image: url('$(res)/img/feather-customised/cancel.svg'); + mask-repeat: no-repeat; + background-color: $warning-color; + mask-size: 100%; } .mx_EditableItem_email { @@ -36,12 +43,22 @@ limitations under the License. .mx_EditableItem_promptText { margin-right: 10px; + order: 2; } .mx_EditableItem_confirmBtn { margin-right: 5px; } +.mx_EditableItem_item { + flex: auto 1 0; + order: 1; + width: calc(100% - 14px); // leave space for the remove button + overflow-x: hidden; + text-overflow: ellipsis; +} + .mx_EditableItemList_label { margin-bottom: 5px; } + diff --git a/res/css/views/elements/_EventListSummary.scss b/res/css/views/elements/_EventListSummary.scss index 99a5c06a5f..f3e9f77aa3 100644 --- a/res/css/views/elements/_EventListSummary.scss +++ b/res/css/views/elements/_EventListSummary.scss @@ -19,7 +19,7 @@ limitations under the License. } .mx_TextualEvent.mx_EventListSummary_summary { - font-size: 14px; + font-size: $font-14px; display: inline-flex; } @@ -27,7 +27,7 @@ limitations under the License. display: inline-block; margin-right: 8px; padding-top: 8px; - line-height: 12px; + line-height: $font-12px; } .mx_EventListSummary_avatars .mx_BaseAvatar { @@ -46,19 +46,19 @@ limitations under the License. .mx_EventListSummary_line { border-bottom: 1px solid $primary-hairline-color; margin-left: 63px; - line-height: 30px; + line-height: $font-30px; } .mx_MatrixChat_useCompactLayout { .mx_EventListSummary { - font-size: 13px; + font-size: $font-13px; .mx_EventTile_line { - line-height: 20px; + line-height: $font-20px; } } .mx_EventListSummary_line { - line-height: 22px; + line-height: $font-22px; } .mx_EventListSummary_toggle { @@ -66,6 +66,6 @@ limitations under the License. } .mx_TextualEvent.mx_EventListSummary_summary { - font-size: 13px; + font-size: $font-13px; } } diff --git a/res/css/views/elements/_Field.scss b/res/css/views/elements/_Field.scss index b260d4b097..cf5bc7ab41 100644 --- a/res/css/views/elements/_Field.scss +++ b/res/css/views/elements/_Field.scss @@ -40,7 +40,7 @@ limitations under the License. .mx_Field textarea { font-weight: normal; font-family: $font-family; - font-size: 14px; + font-size: $font-14px; border: none; // Even without a border here, we still need this avoid overlapping the rounded // corners on the field above. @@ -102,7 +102,7 @@ limitations under the License. background-color 0.25s ease-out 0.1s; color: $primary-fg-color; background-color: transparent; - font-size: 14px; + font-size: $font-14px; position: absolute; left: 0px; top: 0px; @@ -126,7 +126,7 @@ limitations under the License. color 0.25s ease-out 0s, top 0.25s ease-out 0s, background-color 0.25s ease-out 0s; - font-size: 10px; + font-size: $font-10px; top: -13px; padding: 0 2px; background-color: $field-focused-label-bg-color; diff --git a/res/css/views/elements/_FormButton.scss b/res/css/views/elements/_FormButton.scss index 1483fe2091..7ec01f17e6 100644 --- a/res/css/views/elements/_FormButton.scss +++ b/res/css/views/elements/_FormButton.scss @@ -15,9 +15,9 @@ limitations under the License. */ .mx_FormButton { - line-height: 16px; + line-height: $font-16px; padding: 5px 15px; - font-size: 12px; + font-size: $font-12px; height: min-content; &:not(:last-child) { diff --git a/res/css/views/elements/_ImageView.scss b/res/css/views/elements/_ImageView.scss index 67b0d6d7df..0a4ed2a194 100644 --- a/res/css/views/elements/_ImageView.scss +++ b/res/css/views/elements/_ImageView.scss @@ -102,13 +102,13 @@ limitations under the License. } .mx_ImageView_name { - font-size: 18px; + font-size: $font-18px; margin-bottom: 6px; word-wrap: break-word; } .mx_ImageView_metadata { - font-size: 15px; + font-size: $font-15px; opacity: 0.5; } @@ -118,13 +118,13 @@ limitations under the License. margin-bottom: 6px; border-radius: 5px; background-color: $lightbox-bg-color; - font-size: 14px; + font-size: $font-14px; padding: 9px; border: 1px solid $lightbox-border-color; } .mx_ImageView_size { - font-size: 11px; + font-size: $font-11px; } .mx_ImageView_link { @@ -133,7 +133,7 @@ limitations under the License. } .mx_ImageView_button { - font-size: 15px; + font-size: $font-15px; opacity: 0.5; margin-top: 18px; cursor: pointer; diff --git a/res/css/views/elements/_InteractiveTooltip.scss b/res/css/views/elements/_InteractiveTooltip.scss index 17a76436e8..db98d95709 100644 --- a/res/css/views/elements/_InteractiveTooltip.scss +++ b/res/css/views/elements/_InteractiveTooltip.scss @@ -24,7 +24,7 @@ limitations under the License. background-color: $interactive-tooltip-bg-color; color: $interactive-tooltip-fg-color; position: absolute; - font-size: 10px; + font-size: $font-10px; font-weight: 600; padding: 6px; z-index: 5001; diff --git a/res/css/views/elements/_QRCode.scss b/res/css/views/elements/_QRCode.scss new file mode 100644 index 0000000000..96d9114b54 --- /dev/null +++ b/res/css/views/elements/_QRCode.scss @@ -0,0 +1,21 @@ +/* +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_QRCode { + img { + border-radius: 8px; + } +} diff --git a/res/css/views/elements/_RichText.scss b/res/css/views/elements/_RichText.scss index 73f0be291f..d60282695c 100644 --- a/res/css/views/elements/_RichText.scss +++ b/res/css/views/elements/_RichText.scss @@ -6,11 +6,33 @@ .mx_RoomPill, .mx_GroupPill, .mx_AtRoomPill { - border-radius: 16px; - display: inline-block; - height: 20px; - line-height: 20px; - padding-left: 5px; + display: inline-flex; + align-items: center; + vertical-align: middle; + border-radius: $font-16px; + line-height: $font-15px; + padding-left: 0; +} + +a.mx_Pill { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: calc(100% - 1ch); +} + +.mx_Pill { + padding: $font-1px; + padding-right: 0.4em; + vertical-align: text-top; + line-height: $font-17px; +} + +/* More specific to override `.markdown-body a` color */ +.mx_EventTile_content .markdown-body a.mx_GroupPill, +.mx_GroupPill { + color: $accent-fg-color; + background-color: $rte-group-pill-color; } /* More specific to override `.markdown-body a` text-decoration */ @@ -23,7 +45,6 @@ .mx_UserPill { color: $primary-fg-color; background-color: $other-user-pill-bg-color; - padding-right: 5px; } .mx_UserPill_selected { @@ -37,7 +58,6 @@ .mx_MessageComposer_input .mx_AtRoomPill { color: $accent-fg-color; background-color: $mention-user-pill-bg-color; - padding-right: 5px; } /* More specific to override `.markdown-body a` color */ @@ -47,15 +67,6 @@ .mx_GroupPill { color: $accent-fg-color; background-color: $rte-room-pill-color; - padding-right: 5px; -} - -/* More specific to override `.markdown-body a` color */ -.mx_EventTile_content .markdown-body a.mx_GroupPill, -.mx_GroupPill { - color: $accent-fg-color; - background-color: $rte-group-pill-color; - padding-right: 5px; } .mx_EventTile_body .mx_UserPill, @@ -69,8 +80,10 @@ .mx_GroupPill .mx_BaseAvatar, .mx_AtRoomPill .mx_BaseAvatar { position: relative; - left: -3px; - top: 2px; + display: inline-flex; + align-items: center; + border-radius: 10rem; + margin-right: 0.24rem; } .mx_Markdown_BOLD { diff --git a/res/css/views/elements/_ToggleSwitch.scss b/res/css/views/elements/_ToggleSwitch.scss index 1f4445b88c..62669889ee 100644 --- a/res/css/views/elements/_ToggleSwitch.scss +++ b/res/css/views/elements/_ToggleSwitch.scss @@ -16,11 +16,13 @@ limitations under the License. .mx_ToggleSwitch { transition: background-color 0.20s ease-out 0.1s; - width: 48px; - height: 24px; - border-radius: 14px; + + width: $font-44px; + height: $font-20px; + border-radius: 1.5rem; + padding: 2px; + background-color: $togglesw-off-color; - position: relative; opacity: 0.5; } @@ -31,23 +33,18 @@ limitations under the License. .mx_ToggleSwitch.mx_ToggleSwitch_on { background-color: $togglesw-on-color; + + > .mx_ToggleSwitch_ball { + left: calc(100% - $font-20px); + } } .mx_ToggleSwitch_ball { - transition: left 0.15s ease-out 0.1s; - margin: 2px; - width: 20px; - height: 20px; - border-radius: 20px; + position: relative; + width: $font-20px; + height: $font-20px; + border-radius: $font-20px; background-color: $togglesw-ball-color; - position: absolute; - top: 0; -} - -.mx_ToggleSwitch_on > .mx_ToggleSwitch_ball { - left: 23px; // 48px switch - 20px ball - 5px padding = 23px -} - -.mx_ToggleSwitch:not(.mx_ToggleSwitch_on) > .mx_ToggleSwitch_ball { - left: 2px; + transition: left 0.15s ease-out 0.1s; + left: 0; } diff --git a/res/css/views/elements/_Tooltip.scss b/res/css/views/elements/_Tooltip.scss index cc4eb409df..73ac9b3558 100644 --- a/res/css/views/elements/_Tooltip.scss +++ b/res/css/views/elements/_Tooltip.scss @@ -58,8 +58,8 @@ limitations under the License. z-index: 4000; // Higher than dialogs so tooltips can be used in dialogs padding: 10px; pointer-events: none; - line-height: 14px; - font-size: 12px; + line-height: $font-14px; + font-size: $font-12px; font-weight: 600; color: $primary-fg-color; max-width: 200px; @@ -82,7 +82,7 @@ limitations under the License. text-align: center; border: none; border-radius: 3px; - font-size: 14px; + font-size: $font-14px; line-height: 1.2; padding: 6px 8px; diff --git a/res/css/views/elements/_TooltipButton.scss b/res/css/views/elements/_TooltipButton.scss index 6ea36c800e..0c85dac818 100644 --- a/res/css/views/elements/_TooltipButton.scss +++ b/res/css/views/elements/_TooltipButton.scss @@ -28,7 +28,7 @@ limitations under the License. transition: opacity 0.2s ease-in; opacity: 0.6; - line-height: 11px; + line-height: $font-11px; text-align: center; cursor: pointer; diff --git a/res/css/views/emojipicker/_EmojiPicker.scss b/res/css/views/emojipicker/_EmojiPicker.scss index 5d9b3f2687..24561eeeb9 100644 --- a/res/css/views/emojipicker/_EmojiPicker.scss +++ b/res/css/views/emojipicker/_EmojiPicker.scss @@ -163,7 +163,7 @@ limitations under the License. .mx_EmojiPicker_item { display: inline-block; - font-size: 20px; + font-size: $font-20px; padding: 5px; width: 100%; height: 100%; @@ -183,7 +183,7 @@ limitations under the License. } .mx_EmojiPicker_category_label, .mx_EmojiPicker_preview_name { - font-size: 16px; + font-size: $font-16px; font-weight: 600; margin: 0; } @@ -197,7 +197,7 @@ limitations under the License. } .mx_EmojiPicker_preview_emoji { - font-size: 32px; + font-size: $font-32px; padding: 8px 16px; } @@ -212,7 +212,7 @@ limitations under the License. .mx_EmojiPicker_shortcode { color: $light-fg-color; - font-size: 14px; + font-size: $font-14px; &::before, &::after { content: ":"; diff --git a/res/css/views/messages/_DateSeparator.scss b/res/css/views/messages/_DateSeparator.scss index 935ee1aba3..867f58d860 100644 --- a/res/css/views/messages/_DateSeparator.scss +++ b/res/css/views/messages/_DateSeparator.scss @@ -19,7 +19,7 @@ limitations under the License. margin: 4px 0; display: flex; align-items: center; - font-size: 14px; + font-size: $font-14px; color: $roomtopic-color; } diff --git a/res/css/views/messages/_MVideoBody.scss b/res/css/views/messages/_MVideoBody.scss new file mode 100644 index 0000000000..3b05c53f34 --- /dev/null +++ b/res/css/views/messages/_MVideoBody.scss @@ -0,0 +1,22 @@ +/* +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. +*/ + +span.mx_MVideoBody { + video.mx_MVideoBody { + max-width: 100%; + height: auto; + } +} diff --git a/res/css/views/messages/_MessageActionBar.scss b/res/css/views/messages/_MessageActionBar.scss index c032051c36..9f3971ecf0 100644 --- a/res/css/views/messages/_MessageActionBar.scss +++ b/res/css/views/messages/_MessageActionBar.scss @@ -21,7 +21,7 @@ limitations under the License. cursor: pointer; display: flex; height: 24px; - line-height: 24px; + line-height: $font-24px; border-radius: 4px; background: $message-action-bar-bg-color; top: -18px; diff --git a/res/css/views/messages/_MessageTimestamp.scss b/res/css/views/messages/_MessageTimestamp.scss index e5c228aa68..f8d91cc083 100644 --- a/res/css/views/messages/_MessageTimestamp.scss +++ b/res/css/views/messages/_MessageTimestamp.scss @@ -16,5 +16,5 @@ limitations under the License. .mx_MessageTimestamp { color: $event-timestamp-color; - font-size: 10px; + font-size: $font-10px; } diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss index 57c02ed3e5..2f5695e1fb 100644 --- a/res/css/views/messages/_ReactionsRow.scss +++ b/res/css/views/messages/_ReactionsRow.scss @@ -21,7 +21,7 @@ limitations under the License. .mx_ReactionsRow_showAll { text-decoration: none; - font-size: 10px; + font-size: $font-10px; font-weight: 600; margin-left: 6px; vertical-align: top; diff --git a/res/css/views/messages/_ReactionsRowButton.scss b/res/css/views/messages/_ReactionsRowButton.scss index e54201d963..fe5b081042 100644 --- a/res/css/views/messages/_ReactionsRowButton.scss +++ b/res/css/views/messages/_ReactionsRowButton.scss @@ -17,7 +17,7 @@ limitations under the License. .mx_ReactionsRowButton { display: inline-flex; height: 20px; - line-height: 21px; + line-height: $font-21px; margin-right: 6px; padding: 0 6px; border: 1px solid $reaction-row-button-border-color; @@ -34,12 +34,17 @@ limitations under the License. background-color: $reaction-row-button-selected-bg-color; border-color: $reaction-row-button-selected-border-color; } -} -.mx_ReactionsRowButton_content { - max-width: 100px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - padding-right: 4px; + // ignore mouse events for all children, treat it as one entire hoverable entity + * { + pointer-events: none; + } + + .mx_ReactionsRowButton_content { + max-width: 100px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + padding-right: 4px; + } } diff --git a/res/css/views/messages/_RedactedBody.scss b/res/css/views/messages/_RedactedBody.scss new file mode 100644 index 0000000000..e4ab0c0835 --- /dev/null +++ b/res/css/views/messages/_RedactedBody.scss @@ -0,0 +1,36 @@ +/* +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_RedactedBody { + white-space: pre-wrap; + color: $muted-fg-color; + vertical-align: middle; + + padding-left: 20px; + position: relative; + + &::before { + height: 14px; + width: 14px; + background-color: $muted-fg-color; + mask-image: url('$(res)/img/feather-customised/trash.custom.svg'); + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + content: ''; + position: absolute; + top: 2px; + left: 0; + } +} diff --git a/res/css/views/messages/_ViewSourceEvent.scss b/res/css/views/messages/_ViewSourceEvent.scss index a15924e759..076932ee97 100644 --- a/res/css/views/messages/_ViewSourceEvent.scss +++ b/res/css/views/messages/_ViewSourceEvent.scss @@ -17,7 +17,7 @@ limitations under the License. .mx_EventTile_content.mx_ViewSourceEvent { display: flex; opacity: 0.6; - font-size: 12px; + font-size: $font-12px; pre, code { flex: 1; diff --git a/res/css/views/messages/_common_CryptoEvent.scss b/res/css/views/messages/_common_CryptoEvent.scss index 98e1e97e39..637d25d7a1 100644 --- a/res/css/views/messages/_common_CryptoEvent.scss +++ b/res/css/views/messages/_common_CryptoEvent.scss @@ -45,7 +45,7 @@ limitations under the License. .mx_cryptoEvent_title { font-weight: 600; - font-size: 15px; + font-size: $font-15px; grid-column: 2; grid-row: 1; } @@ -56,7 +56,7 @@ limitations under the License. } .mx_cryptoEvent_state, .mx_cryptoEvent_subtitle { - font-size: 12px; + font-size: $font-12px; } .mx_cryptoEvent_state, .mx_cryptoEvent_buttons { diff --git a/res/css/views/right_panel/_UserInfo.scss b/res/css/views/right_panel/_UserInfo.scss index 46d5e99d64..26b81e94f3 100644 --- a/res/css/views/right_panel/_UserInfo.scss +++ b/res/css/views/right_panel/_UserInfo.scss @@ -20,7 +20,7 @@ limitations under the License. flex-direction: column; flex: 1; overflow-y: auto; - font-size: 12px; + font-size: $font-12px; .mx_UserInfo_cancel { cursor: pointer; @@ -43,7 +43,7 @@ limitations under the License. } h2 { - font-size: 18px; + font-size: $font-18px; font-weight: 600; margin: 18px 0 0 0; } @@ -98,8 +98,8 @@ limitations under the License. position: absolute; top: 0; left: 0; - width: 100%; - height: 100%; + width: 100% !important; + height: 100% !important; } .mx_UserInfo_avatar .mx_BaseAvatar_initial { @@ -109,7 +109,7 @@ limitations under the License. justify-content: center; // override the calculated sizes so that the letter isn't HUGE - font-size: 56px !important; + font-size: 6rem !important; width: 100% !important; transition: font-size 0.5s; } @@ -122,7 +122,7 @@ limitations under the License. text-transform: uppercase; color: $notice-secondary-color; font-weight: bold; - font-size: 12px; + font-size: $font-12px; margin: 4px 0; } @@ -134,17 +134,28 @@ limitations under the License. text-align: center; h2 { - font-size: 18px; - line-height: 25px; - flex: 1; - overflow-x: auto; - max-height: 50px; display: flex; + font-size: $font-18px; + line-height: $font-25px; + flex: 1; justify-content: center; - align-items: center; + + span { + // limit to 2 lines, show an ellipsis if it overflows + // this looks webkit specific but is supported by Firefox 68+ + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + + overflow: hidden; + word-break: break-all; + text-overflow: ellipsis; + } .mx_E2EIcon { - margin: 5px; + margin-top: 3px; // visual vertical centering to the top line of text + margin-right: 4px; // margin from displyname + min-width: 18px; // convince flexbox to not collapse it } } @@ -190,7 +201,7 @@ limitations under the License. .mx_UserInfo_field { cursor: pointer; color: $accent-color; - line-height: 16px; + line-height: $font-16px; margin: 8px 0; &.mx_UserInfo_destructive { @@ -199,7 +210,7 @@ limitations under the License. } .mx_UserInfo_statusMessage { - font-size: 11px; + font-size: $font-11px; opacity: 0.5; overflow: hidden; white-space: nowrap; @@ -259,12 +270,31 @@ limitations under the License. } } + .mx_AccessibleButton.mx_AccessibleButton_hasKind { + padding: 8px 18px; + + &.mx_AccessibleButton_kind_primary { + color: $accent-color; + background-color: $accent-bg-color; + } + + &.mx_AccessibleButton_kind_danger { + color: $notice-primary-color; + background-color: $notice-primary-bg-color; + } + } + + .mx_VerificationShowSas .mx_AccessibleButton, .mx_UserInfo_wideButton { display: block; - margin: 16px 0; + margin: 16px 0 8px; } - button.mx_UserInfo_wideButton { - width: 100%; // FIXME get rid of this once we get rid of DialogButtons here + + + .mx_VerificationShowSas { + .mx_AccessibleButton + .mx_AccessibleButton { + margin: 8px 0; // space between buttons + } } } diff --git a/res/css/views/right_panel/_VerificationPanel.scss b/res/css/views/right_panel/_VerificationPanel.scss index 2a733d11a7..a8466a1626 100644 --- a/res/css/views/right_panel/_VerificationPanel.scss +++ b/res/css/views/right_panel/_VerificationPanel.scss @@ -14,10 +14,30 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_UserInfo { - .mx_VerificationPanel_verified_section .mx_E2EIcon { +.mx_VerificationPanel_verified_section, +.mx_VerificationPanel_reciprocate_section { + // center the big shield icon + .mx_E2EIcon { // Override general user info margin - margin: 0 auto !important; + margin: 20px auto !important; + } +} + + +.mx_UserInfo { + .mx_EncryptionPanel_cancel { + mask: url('$(res)/img/feather-customised/cancel.svg'); + mask-repeat: no-repeat; + mask-position: center; + mask-size: cover; + width: 14px; + height: 14px; + background-color: $settings-subsection-fg-color; + cursor: pointer; + position: absolute; + z-index: 100; + top: 14px; + right: 14px; } .mx_VerificationPanel_qrCode { @@ -36,6 +56,16 @@ limitations under the License. max-width: 240px; } } + + .mx_VerificationPanel_reciprocate_section { + .mx_FormButton { + width: 100%; + box-sizing: border-box; + padding: 10px; + display: block; + margin: 10px 0; + } + } } // Special case styling for EncryptionPanel in a Modal dialog @@ -45,6 +75,7 @@ limitations under the License. margin-top: 10px; margin-bottom: 10px; align-items: stretch; + justify-content: center; > .mx_VerificationPanel_QRPhase_betweenText { width: 50px; @@ -60,10 +91,12 @@ limitations under the License. border-radius: 10px; flex: 1; display: flex; - padding: 10px; + padding: 20px; align-items: center; flex-direction: column; position: relative; + max-width: 310px; + justify-content: space-between; canvas, .mx_VerificationPanel_QRPhase_noQR { width: 220px !important; @@ -76,31 +109,36 @@ limitations under the License. } > p { + margin-top: 0; font-weight: 700; } .mx_VerificationPanel_QRPhase_helpText { - font-size: 14px; - margin-top: 71px; + font-size: $font-14px; + margin: 30px 0; text-align: center; } - - .mx_AccessibleButton { - position: absolute; - bottom: 30px; - } } } // EncryptionPanel when verification is done .mx_VerificationPanel_verified_section { - // center the big shield icon - .mx_E2EIcon { - margin: 0 auto; - } // right align the "Got it" button .mx_AccessibleButton { float: right; } } + + .mx_VerificationPanel_reciprocate_section { + .mx_AccessibleButton { + margin-left: 10px; + padding: 7px 40px; + } + + .mx_VerificationPanel_reciprocateButtons { + display: flex; + flex-direction: row; + justify-content: flex-end; + } + } } diff --git a/res/css/views/room_settings/_AliasSettings.scss b/res/css/views/room_settings/_AliasSettings.scss index d4ae58e5b0..f8d92e7828 100644 --- a/res/css/views/room_settings/_AliasSettings.scss +++ b/res/css/views/room_settings/_AliasSettings.scss @@ -26,3 +26,21 @@ limitations under the License. outline: none; box-shadow: none; } + +.mx_AliasSettings { + summary { + cursor: pointer; + color: $accent-color; + font-weight: 600; + list-style: none; + + // list-style doesn't do it for webkit + &::-webkit-details-marker { + display: none; + } + } + + .mx_AliasSettings_localAliasHeader { + margin-top: 35px; + } +} diff --git a/res/css/views/rooms/_AppsDrawer.scss b/res/css/views/rooms/_AppsDrawer.scss index a3fe573ad0..1b1bab67bc 100644 --- a/res/css/views/rooms/_AppsDrawer.scss +++ b/res/css/views/rooms/_AppsDrawer.scss @@ -46,7 +46,7 @@ $AppsDrawerBodyHeight: 273px; padding: 0; margin: 5px auto 5px auto; color: $accent-color; - font-size: 12px; + font-size: $font-12px; } .mx_AddWidget_button_full_width { @@ -59,7 +59,7 @@ $AppsDrawerBodyHeight: 273px; padding: 9px; color: $primary-hairline-color; background-color: $primary-bg-color; - font-size: 15px; + font-size: $font-15px; } .mx_AppTile { @@ -102,7 +102,7 @@ $AppsDrawerBodyHeight: 273px; .mx_AppTileMenuBar { margin: 0; - font-size: 12px; + font-size: $font-12px; background-color: $widget-menu-bar-bg-color; display: flex; flex-direction: row; @@ -272,7 +272,7 @@ form.mx_Custom_Widget_Form div { flex-direction: column; justify-content: center; align-items: center; - font-size: 16px; + font-size: $font-16px; } .mx_AppPermissionWarning_row { @@ -280,7 +280,7 @@ form.mx_Custom_Widget_Form div { } .mx_AppPermissionWarning_smallText { - font-size: 12px; + font-size: $font-12px; } .mx_AppPermissionWarning_bolder { diff --git a/res/css/views/rooms/_Autocomplete.scss b/res/css/views/rooms/_Autocomplete.scss index e5316f5a46..a4aebdb708 100644 --- a/res/css/views/rooms/_Autocomplete.scss +++ b/res/css/views/rooms/_Autocomplete.scss @@ -31,9 +31,10 @@ } .mx_Autocomplete_Completion_pill { - border-radius: 17px; - height: 34px; - padding: 0px 5px; + box-sizing: border-box; + border-radius: 2rem; + height: $font-34px; + padding: 0.4rem; display: flex; user-select: none; cursor: pointer; @@ -42,7 +43,7 @@ } .mx_Autocomplete_Completion_pill > * { - margin: 0 3px; + margin-right: 0.3rem; } /* styling for common completion elements */ diff --git a/res/css/views/rooms/_BasicMessageComposer.scss b/res/css/views/rooms/_BasicMessageComposer.scss index ce519b1ea7..e126e523a6 100644 --- a/res/css/views/rooms/_BasicMessageComposer.scss +++ b/res/css/views/rooms/_BasicMessageComposer.scss @@ -44,27 +44,26 @@ limitations under the License. outline: none; overflow-x: hidden; - span.mx_UserPill, span.mx_RoomPill { - padding-left: 21px; - position: relative; + &.mx_BasicMessageComposer_input_shouldShowPillAvatar { + span.mx_UserPill, span.mx_RoomPill { + position: relative; - // avatar psuedo element - &::before { - position: absolute; - left: 2px; - top: 2px; - content: var(--avatar-letter); - width: 16px; - height: 16px; - background: var(--avatar-background), $avatar-bg-color; - color: $avatar-initial-color; - background-repeat: no-repeat; - background-size: 16px; - border-radius: 8px; - text-align: center; - font-weight: normal; - line-height: 16px; - font-size: 10.4px; + // avatar psuedo element + &::before { + content: var(--avatar-letter); + width: $font-16px; + height: $font-16px; + margin-right: 0.24rem; + background: var(--avatar-background), $avatar-bg-color; + color: $avatar-initial-color; + background-repeat: no-repeat; + background-size: $font-16px; + border-radius: $font-16px; + text-align: center; + font-weight: normal; + line-height: $font-16px; + font-size: $font-10-4px; + } } } } diff --git a/res/css/views/rooms/_EntityTile.scss b/res/css/views/rooms/_EntityTile.scss index a2867de3a7..8db71f297c 100644 --- a/res/css/views/rooms/_EntityTile.scss +++ b/res/css/views/rooms/_EntityTile.scss @@ -69,8 +69,6 @@ limitations under the License. padding-right: 12px; padding-top: 4px; padding-bottom: 4px; - width: 36px; - height: 36px; position: relative; } @@ -78,7 +76,7 @@ limitations under the License. .mx_GroupRoomTile_name { flex: 1 1 0; overflow: hidden; - font-size: 14px; + font-size: $font-14px; text-overflow: ellipsis; white-space: nowrap; } @@ -116,7 +114,7 @@ limitations under the License. } .mx_EntityTile_subtext { - font-size: 11px; + font-size: $font-11px; opacity: 0.5; overflow: hidden; white-space: nowrap; @@ -125,7 +123,7 @@ limitations under the License. .mx_EntityTile_power { padding-inline-start: 6px; - font-size: 10px; + font-size: $font-10px; color: $notice-secondary-color; max-width: 6em; overflow: hidden; diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index d292c729dd..d4e54f4473 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -19,7 +19,7 @@ limitations under the License. max-width: 100%; clear: both; padding-top: 18px; - font-size: 14px; + font-size: $font-14px; position: relative; } @@ -45,7 +45,7 @@ limitations under the License. } .mx_EventTile.mx_EventTile_info .mx_EventTile_avatar { - top: 8px; + top: $font-8px; left: 65px; } @@ -64,7 +64,7 @@ limitations under the License. .mx_EventTile .mx_SenderProfile { color: $primary-fg-color; - font-size: 14px; + font-size: $font-14px; display: inline-block; /* anti-zalgo, with overflow hidden */ overflow: hidden; cursor: pointer; @@ -72,7 +72,7 @@ limitations under the License. padding-bottom: 0px; padding-top: 0px; margin: 0px; - line-height: 17px; + line-height: $font-17px; /* the next three lines, along with overflow hidden, truncate long display names */ white-space: nowrap; text-overflow: ellipsis; @@ -110,16 +110,26 @@ limitations under the License. user-select: none; } +.mx_EventTile_continuation .mx_EventTile_line { + clear: both; +} + .mx_EventTile_line, .mx_EventTile_reply { position: relative; - /* ideally should be 100px, but 95px gives us a max thumbnail size of 800x600, which is nice */ - margin-right: 110px; padding-left: 65px; /* left gutter */ - padding-top: 4px; - padding-bottom: 2px; + padding-top: 3px; + padding-bottom: 3px; border-radius: 4px; - min-height: 24px; - line-height: 22px; + line-height: $font-22px; +} + +.mx_RoomView_timeline_rr_enabled, +// on ELS we need the margin to allow interaction with the expand/collapse button which is normally in the RR gutter +.mx_EventListSummary { + .mx_EventTile_line { + /* ideally should be 100px, but 95px gives us a max thumbnail size of 800x600, which is nice */ + margin-right: 110px; + } } .mx_EventTile_bubbleContainer { @@ -234,34 +244,6 @@ limitations under the License. color: $event-notsent-color; } -.mx_EventTile_redacted .mx_EventTile_line .mx_UnknownBody, -.mx_EventTile_redacted .mx_EventTile_reply .mx_UnknownBody { - --lozenge-color: $event-redacted-fg-color; - --lozenge-border-color: $event-redacted-border-color; - display: block; - height: 22px; - width: 250px; - border-radius: 11px; - background: - repeating-linear-gradient( - -45deg, - var(--lozenge-color), - var(--lozenge-color) 3px, - transparent 3px, - transparent 6px - ); - box-shadow: 0px 0px 3px var(--lozenge-border-color) inset; -} - -.mx_EventTile_sending.mx_EventTile_redacted .mx_UnknownBody { - opacity: 0.4; -} - -div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody { - --lozenge-color: $event-notsent-color; - --lozenge-border-color: $event-notsent-color; -} - .mx_EventTile_contextual { opacity: 0.4; } @@ -303,11 +285,13 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody { .mx_EventTile_readAvatars .mx_BaseAvatar { position: absolute; display: inline-block; + height: $font-14px; + width: $font-14px; } .mx_EventTile_readAvatarRemainder { color: $event-timestamp-color; - font-size: 11px; + font-size: $font-11px; position: absolute; } @@ -336,7 +320,7 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody { .mx_EventTile_spoiler_reason { color: $event-timestamp-color; - font-size: 11px; + font-size: $font-11px; } .mx_EventTile_spoiler_content { @@ -388,7 +372,7 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody { } .mx_EventTile_keyRequestInfo { - font-size: 12px; + font-size: $font-12px; } .mx_EventTile_keyRequestInfo_text { @@ -466,7 +450,7 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody { .mx_EventTile_content .mx_EventTile_edited { user-select: none; - font-size: 12px; + font-size: $font-12px; color: $roomtopic-color; display: inline-block; margin-left: 9px; @@ -484,7 +468,7 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody { white-space: normal !important; line-height: inherit !important; color: inherit; // inherit the colour from the dark or light theme by default (but not for code blocks) - font-size: 14px; + font-size: $font-14px; pre, code { font-family: $monospace-font-family !important; @@ -584,9 +568,9 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody { .mx_EventTile.mx_EventTile_info { // same as the padding for non-compact .mx_EventTile.mx_EventTile_info padding-top: 0px; - font-size: 13px; + font-size: $font-13px; .mx_EventTile_line, .mx_EventTile_reply { - line-height: 20px; + line-height: $font-20px; } .mx_EventTile_avatar { top: 4px; @@ -594,7 +578,7 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody { } .mx_EventTile .mx_SenderProfile { - font-size: 13px; + font-size: $font-13px; } .mx_EventTile.mx_EventTile_emote { @@ -653,3 +637,23 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody { } } } + +.mx_EventTile_tileError { + color: red; + text-align: center; + + // Remove some of the default tile padding so that the error is centered + margin-right: 0; + .mx_EventTile_line { + padding-left: 0; + margin-right: 0; + } + + .mx_EventTile_line span { + padding: 4px 8px; + } + + a { + margin-left: 1em; + } +} diff --git a/res/css/views/rooms/_InviteOnlyIcon.scss b/res/css/views/rooms/_InviteOnlyIcon.scss index 6943d1797b..b71fd6348d 100644 --- a/res/css/views/rooms/_InviteOnlyIcon.scss +++ b/res/css/views/rooms/_InviteOnlyIcon.scss @@ -14,27 +14,45 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_InviteOnlyIcon { +@define-mixin mx_InviteOnlyIcon { width: 12px; height: 12px; position: relative; display: block !important; - // Align the padlock with unencrypted room names +} + +@define-mixin mx_InviteOnlyIcon_padlock { + background-color: $roomtile-name-color; + mask-image: url("$(res)/img/feather-customised/lock-solid.svg"); + mask-position: center; + mask-repeat: no-repeat; + mask-size: contain; + content: ""; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + +.mx_InviteOnlyIcon_large { + @mixin mx_InviteOnlyIcon; margin: 0 4px; &::before { - background-color: $roomtile-name-color; - mask-image: url('$(res)/img/feather-customised/lock-solid.svg'); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - content: ''; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; + @mixin mx_InviteOnlyIcon_padlock; width: 12px; height: 12px; } } + +.mx_InviteOnlyIcon_small { + @mixin mx_InviteOnlyIcon; + left: -2px; + + &::before { + @mixin mx_InviteOnlyIcon_padlock; + width: 10px; + height: 10px; + } +} diff --git a/res/css/views/rooms/_JumpToBottomButton.scss b/res/css/views/rooms/_JumpToBottomButton.scss index 7f458092fb..63cf574596 100644 --- a/res/css/views/rooms/_JumpToBottomButton.scss +++ b/res/css/views/rooms/_JumpToBottomButton.scss @@ -34,8 +34,8 @@ limitations under the License. top: -12px; border-radius: 16px; font-weight: bold; - font-size: 12px; - line-height: 14px; + font-size: $font-12px; + line-height: $font-14px; text-align: center; // to be able to get it centered // with text-align in parent diff --git a/res/css/views/rooms/_MemberDeviceInfo.scss b/res/css/views/rooms/_MemberDeviceInfo.scss index 15b4832dc5..71b05a93fc 100644 --- a/res/css/views/rooms/_MemberDeviceInfo.scss +++ b/res/css/views/rooms/_MemberDeviceInfo.scss @@ -59,7 +59,7 @@ limitations under the License. .mx_MemberDeviceInfo_deviceId { word-break: break-word; - font-size: 13px; + font-size: $font-13px; } .mx_MemberDeviceInfo_deviceInfo { diff --git a/res/css/views/rooms/_MemberInfo.scss b/res/css/views/rooms/_MemberInfo.scss index e3f746e9d3..fb082843f1 100644 --- a/res/css/views/rooms/_MemberInfo.scss +++ b/res/css/views/rooms/_MemberInfo.scss @@ -48,7 +48,7 @@ limitations under the License. } .mx_MemberInfo h2 { - font-size: 18px; + font-size: $font-18px; font-weight: 600; margin: 16px 0 16px 15px; } @@ -94,12 +94,12 @@ limitations under the License. text-transform: uppercase; color: $input-darker-fg-color; font-weight: bold; - font-size: 12px; + font-size: $font-12px; margin: 4px 0; } .mx_MemberInfo_profileField { - font-size: 15px; + font-size: $font-15px; position: relative; } @@ -109,10 +109,10 @@ limitations under the License. .mx_MemberInfo_field { cursor: pointer; - font-size: 15px; + font-size: $font-15px; color: $primary-fg-color; margin-left: 8px; - line-height: 23px; + line-height: $font-23px; } .mx_MemberInfo_createRoom { @@ -128,7 +128,7 @@ limitations under the License. } .mx_MemberInfo label { - font-size: 13px; + font-size: $font-13px; } .mx_MemberInfo label .mx_MemberInfo_label_text { @@ -144,7 +144,7 @@ limitations under the License. } .mx_MemberInfo_statusMessage { - font-size: 11px; + font-size: $font-11px; opacity: 0.5; overflow: hidden; white-space: nowrap; diff --git a/res/css/views/rooms/_MemberList.scss b/res/css/views/rooms/_MemberList.scss index 6e4465583c..99dc2338d4 100644 --- a/res/css/views/rooms/_MemberList.scss +++ b/res/css/views/rooms/_MemberList.scss @@ -30,7 +30,7 @@ limitations under the License. text-transform: uppercase; color: $h3-color; font-weight: 600; - font-size: 13px; + font-size: $font-13px; padding-left: 3px; padding-right: 12px; margin-top: 8px; diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index a05b4c0c0e..7b223be3a4 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -105,7 +105,7 @@ limitations under the License. min-height: 60px; justify-content: flex-start; align-items: flex-start; - font-size: 14px; + font-size: $font-14px; margin-right: 6px; } @@ -161,7 +161,7 @@ limitations under the License. box-shadow: none; color: $primary-fg-color; background-color: $primary-bg-color; - font-size: 14px; + font-size: $font-14px; max-height: 120px; overflow: auto; /* needed for FF */ @@ -242,7 +242,7 @@ limitations under the License. flex-direction: row; align-items: center; - font-size: 10px; + font-size: $font-10px; color: $greyed-fg-color; } diff --git a/res/css/views/rooms/_MessageComposerFormatBar.scss b/res/css/views/rooms/_MessageComposerFormatBar.scss index 1b5a21bed0..27ee7b9795 100644 --- a/res/css/views/rooms/_MessageComposerFormatBar.scss +++ b/res/css/views/rooms/_MessageComposerFormatBar.scss @@ -97,13 +97,13 @@ limitations under the License. .mx_MessageComposerFormatBar_buttonTooltip { white-space: nowrap; - font-size: 13px; + font-size: $font-13px; font-weight: 600; min-width: 54px; text-align: center; .mx_MessageComposerFormatBar_tooltipShortcut { - font-size: 9px; + font-size: $font-9px; opacity: 0.7; } } diff --git a/res/css/views/rooms/_PresenceLabel.scss b/res/css/views/rooms/_PresenceLabel.scss index 26ed1aa6a3..5be83c77d7 100644 --- a/res/css/views/rooms/_PresenceLabel.scss +++ b/res/css/views/rooms/_PresenceLabel.scss @@ -15,6 +15,6 @@ limitations under the License. */ .mx_PresenceLabel { - font-size: 11px; + font-size: $font-11px; opacity: 0.5; } diff --git a/res/css/views/rooms/_RoomBreadcrumbs.scss b/res/css/views/rooms/_RoomBreadcrumbs.scss index 67350aac34..3858d836e6 100644 --- a/res/css/views/rooms/_RoomBreadcrumbs.scss +++ b/res/css/views/rooms/_RoomBreadcrumbs.scss @@ -41,7 +41,7 @@ limitations under the License. overflow-x: visible; } - .mx_AutoHideScrollbar_offset { + .mx_AutoHideScrollbar { display: flex; flex-direction: row; height: 100%; diff --git a/res/css/views/rooms/_RoomDropTarget.scss b/res/css/views/rooms/_RoomDropTarget.scss index 1076a0563a..2e8145c2c9 100644 --- a/res/css/views/rooms/_RoomDropTarget.scss +++ b/res/css/views/rooms/_RoomDropTarget.scss @@ -28,7 +28,7 @@ limitations under the License. } .mx_RoomDropTarget { - font-size: 13px; + font-size: $font-13px; padding-top: 5px; padding-bottom: 5px; border: 1px dashed $accent-color; @@ -41,7 +41,7 @@ limitations under the License. .mx_RoomDropTarget_label { position: relative; margin-top: 3px; - line-height: 21px; + line-height: $font-21px; z-index: 1; text-align: center; } diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index 47b8131ef0..80f6c40f39 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -77,9 +77,9 @@ limitations under the License. } .mx_RoomHeader_simpleHeader { - line-height: 52px; + line-height: $font-52px; color: $roomheader-color; - font-size: 18px; + font-size: $font-18px; font-weight: 600; overflow: hidden; margin-left: 63px; @@ -102,7 +102,7 @@ limitations under the License. overflow: hidden; color: $roomheader-color; font-weight: 600; - font-size: 18px; + font-size: $font-18px; margin: 0 7px; border-bottom: 1px solid transparent; display: flex; @@ -161,7 +161,7 @@ limitations under the License. flex: 1; color: $roomtopic-color; font-weight: 400; - font-size: 13px; + font-size: $font-13px; margin: 0 7px; margin-top: 4px; // to align baseline of topic with room name overflow: hidden; @@ -173,8 +173,6 @@ limitations under the License. .mx_RoomHeader_avatar { flex: 0; - width: 28px; - height: 28px; margin: 0 7px; position: relative; } diff --git a/res/css/views/rooms/_RoomList.scss b/res/css/views/rooms/_RoomList.scss index 5ed22f997d..50a9e7ee1f 100644 --- a/res/css/views/rooms/_RoomList.scss +++ b/res/css/views/rooms/_RoomList.scss @@ -47,13 +47,13 @@ limitations under the License. } .mx_RoomList_emptySubListTip { - font-size: 13px; + font-size: $font-13px; padding: 5px; border: 1px dashed $accent-color; color: $primary-fg-color; background-color: $droptarget-bg-color; border-radius: 4px; - line-height: 16px; + line-height: $font-16px; } .mx_RoomList_emptySubListTip .mx_RoleButton { diff --git a/res/css/views/rooms/_RoomPreviewBar.scss b/res/css/views/rooms/_RoomPreviewBar.scss index 85b6916226..8708f13ada 100644 --- a/res/css/views/rooms/_RoomPreviewBar.scss +++ b/res/css/views/rooms/_RoomPreviewBar.scss @@ -23,7 +23,7 @@ limitations under the License. -webkit-align-items: center; h3 { - font-size: 18px; + font-size: $font-18px; font-weight: 600; &.mx_RoomPreviewBar_spinnerTitle { @@ -33,6 +33,13 @@ limitations under the License. } } + h3, + .mx_RoomPreviewBar_message p { + // break-word, with fallback to break-all, which is wider supported + word-break: break-all; + word-break: break-word; + } + .mx_Spinner { width: auto; height: auto; @@ -41,8 +48,8 @@ limitations under the License. } .mx_RoomPreviewBar_footer { - font-size: 12px; - line-height: 20px; + font-size: $font-12px; + line-height: $font-20px; .mx_Spinner { vertical-align: middle; diff --git a/res/css/views/rooms/_RoomRecoveryReminder.scss b/res/css/views/rooms/_RoomRecoveryReminder.scss index 85d42ca4b4..09b28ae235 100644 --- a/res/css/views/rooms/_RoomRecoveryReminder.scss +++ b/res/css/views/rooms/_RoomRecoveryReminder.scss @@ -33,11 +33,6 @@ limitations under the License. margin-bottom: 1em; } -.mx_RoomRecoveryReminder_button { - @mixin mx_DialogButton; - margin: 0 10px; -} - .mx_RoomRecoveryReminder_secondary { font-size: 90%; margin-top: 1em; diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index 31d887cbbb..5bc7d5624d 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -20,10 +20,24 @@ limitations under the License. flex-direction: row; align-items: center; cursor: pointer; - height: 34px; + height: $font-34px; margin: 0; padding: 0 8px 0 10px; position: relative; + + .mx_RoomTile_menuButton { + display: none; + flex: 0 0 16px; + height: 16px; + background-image: url('$(res)/img/icon_context.svg'); + background-repeat: no-repeat; + background-position: center; + } + + .mx_UserOnlineDot { + display: block; + margin-right: 5px; + } } .mx_RoomTile:focus { @@ -31,15 +45,6 @@ limitations under the License. background-color: $roomtile-focused-bg-color; } -.mx_RoomTile_menuButton { - display: none; - flex: 0 0 16px; - height: 16px; - background-image: url('$(res)/img/icon_context.svg'); - background-repeat: no-repeat; - background-position: center; -} - .mx_RoomTile_tooltip { display: inline-block; position: relative; @@ -64,7 +69,7 @@ limitations under the License. .mx_RoomTile_subtext { display: inline-block; - font-size: 11px; + font-size: $font-11px; padding: 0 0 0 7px; margin: 0; overflow: hidden; @@ -112,7 +117,7 @@ limitations under the License. } .mx_RoomTile_name { - font-size: 14px; + font-size: $font-14px; padding: 0 4px; color: $roomtile-name-color; white-space: nowrap; @@ -126,7 +131,7 @@ limitations under the License. padding: 0 0.4em; color: $roomtile-badge-fg-color; font-weight: 600; - font-size: 12px; + font-size: $font-12px; } .collapsed { @@ -151,7 +156,10 @@ limitations under the License. } .mx_RoomTile_menuButton { - display: none; //no design for this for now + display: none; // no design for this for now + } + .mx_UserOnlineDot { + display: none; // no design for this for now } } @@ -164,6 +172,9 @@ limitations under the License. .mx_RoomTile_menuButton { display: block; } + .mx_UserOnlineDot { + display: none; + } } .mx_RoomTile_unreadNotify .mx_RoomTile_badge, diff --git a/res/css/views/rooms/_SearchBar.scss b/res/css/views/rooms/_SearchBar.scss index b6748e5ad2..fecc8d78d8 100644 --- a/res/css/views/rooms/_SearchBar.scss +++ b/res/css/views/rooms/_SearchBar.scss @@ -22,7 +22,7 @@ limitations under the License. .mx_SearchBar_input { // border: 1px solid $input-border-color; - // font-size: 15px; + // font-size: $font-15px; flex: 1 1 0; margin-left: 22px; } @@ -45,7 +45,7 @@ limitations under the License. border: 0; margin: 0 0 0 22px; padding: 5px; - font-size: 15px; + font-size: $font-15px; cursor: pointer; color: $primary-fg-color; border-bottom: 2px solid $accent-color; diff --git a/res/css/views/rooms/_SearchableEntityList.scss b/res/css/views/rooms/_SearchableEntityList.scss deleted file mode 100644 index 37a663123d..0000000000 --- a/res/css/views/rooms/_SearchableEntityList.scss +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2016 OpenMarket 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_SearchableEntityList { - display: flex; - - flex-direction: column; -} - -.mx_SearchableEntityList_query { - font-family: $font-family; - border-radius: 3px; - border: 1px solid $input-border-color; - padding: 9px; - color: $primary-fg-color; - background-color: $primary-bg-color; - margin-left: 3px; - font-size: 15px; - margin-bottom: 8px; - width: 189px; -} - -.mx_SearchableEntityList_query::-moz-placeholder { - color: $primary-fg-color; - opacity: 0.5; - font-size: 12px; -} - -.mx_SearchableEntityList_query::-webkit-input-placeholder { - color: $primary-fg-color; - opacity: 0.5; - font-size: 12px; -} - -.mx_SearchableEntityList_listWrapper { - flex: 1; - - overflow-y: auto; -} - -.mx_SearchableEntityList_list { - display: table; - table-layout: fixed; - width: 100%; -} - -.mx_SearchableEntityList_list .mx_EntityTile_chevron { - display: none; -} - -.mx_SearchableEntityList_hrWrapper { - width: 100%; - flex: 0 0 auto; -} - -.mx_SearchableEntityList hr { - height: 1px; - border: 0px; - color: $primary-fg-color; - background-color: $primary-fg-color; - margin-right: 15px; - margin-top: 11px; - margin-bottom: 11px; -} diff --git a/res/css/views/rooms/_SendMessageComposer.scss b/res/css/views/rooms/_SendMessageComposer.scss index d20f7107b3..0b646666e7 100644 --- a/res/css/views/rooms/_SendMessageComposer.scss +++ b/res/css/views/rooms/_SendMessageComposer.scss @@ -18,7 +18,7 @@ limitations under the License. flex: 1; display: flex; flex-direction: column; - font-size: 14px; + font-size: $font-14px; justify-content: center; margin-right: 6px; // don't grow wider than available space diff --git a/res/css/views/rooms/_TopUnreadMessagesBar.scss b/res/css/views/rooms/_TopUnreadMessagesBar.scss index a3916f321a..28eddf1fa2 100644 --- a/res/css/views/rooms/_TopUnreadMessagesBar.scss +++ b/res/css/views/rooms/_TopUnreadMessagesBar.scss @@ -51,8 +51,30 @@ limitations under the License. position: absolute; width: 38px; height: 38px; - mask: url('$(res)/img/icon-jump-to-first-unread.svg'); + mask-image: url('$(res)/img/icon-jump-to-first-unread.svg'); mask-repeat: no-repeat; mask-position: 9px 13px; background: $roomtile-name-color; } + +.mx_TopUnreadMessagesBar_markAsRead { + display: block; + width: 18px; + height: 18px; + background: $primary-bg-color; + border: 1.3px solid $roomtile-name-color; + border-radius: 10px; + margin: 5px auto; +} + +.mx_TopUnreadMessagesBar_markAsRead::before { + content: ""; + position: absolute; + width: 18px; + height: 18px; + mask-image: url('$(res)/img/cancel.svg'); + mask-repeat: no-repeat; + mask-size: 10px; + mask-position: 4px 4px; + background: $roomtile-name-color; +} diff --git a/res/css/views/rooms/_UserOnlineDot.scss b/res/css/views/rooms/_UserOnlineDot.scss index 339e5cc48a..f9da8648ed 100644 --- a/res/css/views/rooms/_UserOnlineDot.scss +++ b/res/css/views/rooms/_UserOnlineDot.scss @@ -17,7 +17,7 @@ limitations under the License. .mx_UserOnlineDot { border-radius: 50%; background-color: $accent-color; - height: 5px; - width: 5px; + height: 6px; + width: 6px; display: inline-block; } diff --git a/res/css/views/rooms/_WhoIsTypingTile.scss b/res/css/views/rooms/_WhoIsTypingTile.scss index 579ea7e73e..8b135152d6 100644 --- a/res/css/views/rooms/_WhoIsTypingTile.scss +++ b/res/css/views/rooms/_WhoIsTypingTile.scss @@ -49,7 +49,7 @@ limitations under the License. border-radius: 40px; width: 24px; height: 24px; - line-height: 24px; + line-height: $font-24px; font-size: 0.8em; vertical-align: top; text-align: center; @@ -57,7 +57,7 @@ limitations under the License. .mx_WhoIsTypingTile_label { flex: 1; - font-size: 14px; + font-size: $font-14px; font-weight: 600; color: $eventtile-meta-color; } diff --git a/res/css/views/settings/_AvatarSetting.scss b/res/css/views/settings/_AvatarSetting.scss index 35dba90f85..9fa10907b4 100644 --- a/res/css/views/settings/_AvatarSetting.scss +++ b/res/css/views/settings/_AvatarSetting.scss @@ -15,13 +15,13 @@ limitations under the License. */ .mx_AvatarSetting_avatar { - width: 88px; - height: 88px; + width: $font-88px; + height: $font-88px; margin-left: 13px; position: relative; & > * { - width: 88px; + width: $font-88px; box-sizing: border-box; } @@ -63,7 +63,7 @@ limitations under the License. & > img, .mx_AvatarSetting_avatarPlaceholder { display: block; - height: 88px; + height: $font-88px; border-radius: 4px; } diff --git a/res/css/views/settings/_E2eAdvancedPanel.scss b/res/css/views/settings/_E2eAdvancedPanel.scss new file mode 100644 index 0000000000..9e32685d12 --- /dev/null +++ b/res/css/views/settings/_E2eAdvancedPanel.scss @@ -0,0 +1,20 @@ +/* +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_E2eAdvancedPanel_settingLongDescription { + margin-right: 150px; +} + diff --git a/res/css/views/settings/tabs/_SettingsTab.scss b/res/css/views/settings/tabs/_SettingsTab.scss index 794c8106be..e3a61e6825 100644 --- a/res/css/views/settings/tabs/_SettingsTab.scss +++ b/res/css/views/settings/tabs/_SettingsTab.scss @@ -19,7 +19,7 @@ limitations under the License. } .mx_SettingsTab_heading { - font-size: 20px; + font-size: $font-20px; font-weight: 600; color: $primary-fg-color; } @@ -29,7 +29,7 @@ limitations under the License. } .mx_SettingsTab_subheading { - font-size: 16px; + font-size: $font-16px; display: block; font-family: $font-family; font-weight: 600; @@ -40,22 +40,30 @@ limitations under the License. .mx_SettingsTab_subsectionText { color: $settings-subsection-fg-color; - font-size: 14px; + font-size: $font-14px; display: block; margin: 10px 100px 10px 0; // Align with the rest of the view } -.mx_SettingsTab_section .mx_SettingsFlag { - margin-right: 100px; - margin-bottom: 10px; +.mx_SettingsTab_section { + margin-bottom: 24px; + + .mx_SettingsFlag { + margin-right: 100px; + margin-bottom: 10px; + } + + &.mx_SettingsTab_subsectionText .mx_SettingsFlag { + margin-right: 0px !important; + } } .mx_SettingsTab_section .mx_SettingsFlag .mx_SettingsFlag_label { vertical-align: middle; display: inline-block; - font-size: 14px; + font-size: $font-14px; color: $primary-fg-color; - max-width: calc(100% - 48px); // Force word wrap instead of colliding with the switch + max-width: calc(100% - $font-48px); // Force word wrap instead of colliding with the switch box-sizing: border-box; padding-right: 10px; } diff --git a/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss b/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss index 62d230e752..95a46b51ee 100644 --- a/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss @@ -23,6 +23,12 @@ limitations under the License. margin-top: 0; } +.mx_GeneralUserSettingsTab_accountSection .mx_Spinner, +.mx_GeneralUserSettingsTab_discovery .mx_Spinner { + // Move the spinner to the left side of the container (default center) + justify-content: left; +} + .mx_GeneralUserSettingsTab_accountSection .mx_EmailAddresses, .mx_GeneralUserSettingsTab_accountSection .mx_PhoneNumbers, .mx_GeneralUserSettingsTab_discovery .mx_ExistingEmailAddress, diff --git a/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss b/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss index d003e175d9..be0af9123b 100644 --- a/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_PreferencesUserSettingsTab.scss @@ -14,6 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_PreferencesUserSettingsTab .mx_Field { - @mixin mx_Settings_fullWidthField; +.mx_PreferencesUserSettingsTab { + .mx_Field { + @mixin mx_Settings_fullWidthField; + } + + .mx_SettingsTab_section { + margin-bottom: 30px; + } } diff --git a/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss b/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss index b5a6693006..8700f8747d 100644 --- a/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_SecurityUserSettingsTab.scss @@ -55,3 +55,12 @@ limitations under the License. .mx_SecurityUserSettingsTab_ignoredUser .mx_AccessibleButton { margin-right: 10px; } + +.mx_SecurityUserSettingsTab { + .mx_SettingsTab_section { + .mx_AccessibleButton_kind_link { + padding: 0; + font-size: inherit; + } + } +} diff --git a/res/css/views/terms/_InlineTermsAgreement.scss b/res/css/views/terms/_InlineTermsAgreement.scss index e00dcf31d1..1d0e3ea8c5 100644 --- a/res/css/views/terms/_InlineTermsAgreement.scss +++ b/res/css/views/terms/_InlineTermsAgreement.scss @@ -16,7 +16,7 @@ limitations under the License. .mx_InlineTermsAgreement_cbContainer { margin-bottom: 10px; - font-size: 14px; + font-size: $font-14px; a { color: $accent-color; diff --git a/res/css/views/verification/_VerificationShowSas.scss b/res/css/views/verification/_VerificationShowSas.scss index 5038d40b73..af003112f7 100644 --- a/res/css/views/verification/_VerificationShowSas.scss +++ b/res/css/views/verification/_VerificationShowSas.scss @@ -48,16 +48,34 @@ limitations under the License. } .mx_VerificationShowSas_emojiSas_emoji { - font-size: 32px; + font-size: $font-32px; } .mx_VerificationShowSas_emojiSas_label { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; - font-size: 12px; + font-size: $font-12px; } .mx_VerificationShowSas_emojiSas_break { flex-basis: 100%; } + +.mx_VerificationShowSas { + .mx_Dialog_buttons { + // this is more specific than the DialogButtons css so gets preference + button.mx_VerificationShowSas_matchButton { + color: $accent-color; + background-color: $accent-bg-color; + border: none; + } + + // this is more specific than the DialogButtons css so gets preference + button.mx_VerificationShowSas_noMatchButton { + color: $notice-primary-color; + background-color: $notice-primary-bg-color; + border: none; + } + } +} diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index b01fbf8c66..4650f30c1d 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -21,5 +21,5 @@ limitations under the License. text-align: center; padding: 6px; font-weight: bold; - font-size: 13px; + font-size: $font-13px; } diff --git a/res/css/views/voip/_IncomingCallbox.scss b/res/css/views/voip/_IncomingCallbox.scss index 64eac25d01..ed33de470d 100644 --- a/res/css/views/voip/_IncomingCallbox.scss +++ b/res/css/views/voip/_IncomingCallbox.scss @@ -54,7 +54,7 @@ limitations under the License. vertical-align: middle; width: 80px; height: 36px; - line-height: 36px; + line-height: $font-36px; border-radius: 36px; color: $accent-fg-color; margin: auto; diff --git a/res/img/03b381.png b/res/img/03b381.png deleted file mode 100644 index cf28fc7e59..0000000000 Binary files a/res/img/03b381.png and /dev/null differ diff --git a/res/img/368bd6.png b/res/img/368bd6.png deleted file mode 100644 index a2700bd0ae..0000000000 Binary files a/res/img/368bd6.png and /dev/null differ diff --git a/res/img/ac3ba8.png b/res/img/ac3ba8.png deleted file mode 100644 index 031471d85a..0000000000 Binary files a/res/img/ac3ba8.png and /dev/null differ diff --git a/res/img/feather-customised/chevron-down.svg b/res/img/feather-customised/chevron-down.svg new file mode 100644 index 0000000000..bcb185ede7 --- /dev/null +++ b/res/img/feather-customised/chevron-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/feather-customised/explore.svg b/res/img/feather-customised/explore.svg new file mode 100644 index 0000000000..45be889bb7 --- /dev/null +++ b/res/img/feather-customised/explore.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/res/img/feather-customised/group.svg b/res/img/feather-customised/group.svg new file mode 100644 index 0000000000..7051860e62 --- /dev/null +++ b/res/img/feather-customised/group.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/res/img/feather-customised/message-circle.svg b/res/img/feather-customised/message-circle.svg new file mode 100644 index 0000000000..acc6d2fb0f --- /dev/null +++ b/res/img/feather-customised/message-circle.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/feather-customised/monitor.svg b/res/img/feather-customised/monitor.svg new file mode 100644 index 0000000000..231811d5a6 --- /dev/null +++ b/res/img/feather-customised/monitor.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/res/img/feather-customised/smartphone.svg b/res/img/feather-customised/smartphone.svg new file mode 100644 index 0000000000..fde78c82e2 --- /dev/null +++ b/res/img/feather-customised/smartphone.svg @@ -0,0 +1,4 @@ + + + + diff --git a/res/img/feather-customised/trash.custom.svg b/res/img/feather-customised/trash.custom.svg new file mode 100644 index 0000000000..dc1985ddb2 --- /dev/null +++ b/res/img/feather-customised/trash.custom.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/res/img/flags/AD.png b/res/img/flags/AD.png deleted file mode 100644 index d5d59645fe..0000000000 Binary files a/res/img/flags/AD.png and /dev/null differ diff --git a/res/img/flags/AE.png b/res/img/flags/AE.png deleted file mode 100644 index 05c7418aa4..0000000000 Binary files a/res/img/flags/AE.png and /dev/null differ diff --git a/res/img/flags/AF.png b/res/img/flags/AF.png deleted file mode 100644 index bc7cef0916..0000000000 Binary files a/res/img/flags/AF.png and /dev/null differ diff --git a/res/img/flags/AG.png b/res/img/flags/AG.png deleted file mode 100644 index d48facad47..0000000000 Binary files a/res/img/flags/AG.png and /dev/null differ diff --git a/res/img/flags/AI.png b/res/img/flags/AI.png deleted file mode 100644 index 8fd27cd39e..0000000000 Binary files a/res/img/flags/AI.png and /dev/null differ diff --git a/res/img/flags/AL.png b/res/img/flags/AL.png deleted file mode 100644 index 883835ffb3..0000000000 Binary files a/res/img/flags/AL.png and /dev/null differ diff --git a/res/img/flags/AM.png b/res/img/flags/AM.png deleted file mode 100644 index b1bb36b987..0000000000 Binary files a/res/img/flags/AM.png and /dev/null differ diff --git a/res/img/flags/AO.png b/res/img/flags/AO.png deleted file mode 100644 index ae68b12c44..0000000000 Binary files a/res/img/flags/AO.png and /dev/null differ diff --git a/res/img/flags/AQ.png b/res/img/flags/AQ.png deleted file mode 100644 index 146e9c0a04..0000000000 Binary files a/res/img/flags/AQ.png and /dev/null differ diff --git a/res/img/flags/AR.png b/res/img/flags/AR.png deleted file mode 100644 index 8142adfc83..0000000000 Binary files a/res/img/flags/AR.png and /dev/null differ diff --git a/res/img/flags/AS.png b/res/img/flags/AS.png deleted file mode 100644 index cc5bf30daf..0000000000 Binary files a/res/img/flags/AS.png and /dev/null differ diff --git a/res/img/flags/AT.png b/res/img/flags/AT.png deleted file mode 100644 index e32414bd6a..0000000000 Binary files a/res/img/flags/AT.png and /dev/null differ diff --git a/res/img/flags/AU.png b/res/img/flags/AU.png deleted file mode 100644 index 8d1e143791..0000000000 Binary files a/res/img/flags/AU.png and /dev/null differ diff --git a/res/img/flags/AW.png b/res/img/flags/AW.png deleted file mode 100644 index 6ec178847e..0000000000 Binary files a/res/img/flags/AW.png and /dev/null differ diff --git a/res/img/flags/AX.png b/res/img/flags/AX.png deleted file mode 100644 index ba269c0453..0000000000 Binary files a/res/img/flags/AX.png and /dev/null differ diff --git a/res/img/flags/AZ.png b/res/img/flags/AZ.png deleted file mode 100644 index 2bf3c746e7..0000000000 Binary files a/res/img/flags/AZ.png and /dev/null differ diff --git a/res/img/flags/BA.png b/res/img/flags/BA.png deleted file mode 100644 index 3e3ec3fc76..0000000000 Binary files a/res/img/flags/BA.png and /dev/null differ diff --git a/res/img/flags/BB.png b/res/img/flags/BB.png deleted file mode 100644 index 694050ca46..0000000000 Binary files a/res/img/flags/BB.png and /dev/null differ diff --git a/res/img/flags/BD.png b/res/img/flags/BD.png deleted file mode 100644 index 6de2cde85b..0000000000 Binary files a/res/img/flags/BD.png and /dev/null differ diff --git a/res/img/flags/BE.png b/res/img/flags/BE.png deleted file mode 100644 index 742ba9231f..0000000000 Binary files a/res/img/flags/BE.png and /dev/null differ diff --git a/res/img/flags/BF.png b/res/img/flags/BF.png deleted file mode 100644 index 17f9f67d26..0000000000 Binary files a/res/img/flags/BF.png and /dev/null differ diff --git a/res/img/flags/BG.png b/res/img/flags/BG.png deleted file mode 100644 index b01d3ff57b..0000000000 Binary files a/res/img/flags/BG.png and /dev/null differ diff --git a/res/img/flags/BH.png b/res/img/flags/BH.png deleted file mode 100644 index d0f82e8285..0000000000 Binary files a/res/img/flags/BH.png and /dev/null differ diff --git a/res/img/flags/BI.png b/res/img/flags/BI.png deleted file mode 100644 index 21865ac720..0000000000 Binary files a/res/img/flags/BI.png and /dev/null differ diff --git a/res/img/flags/BJ.png b/res/img/flags/BJ.png deleted file mode 100644 index a7c6091434..0000000000 Binary files a/res/img/flags/BJ.png and /dev/null differ diff --git a/res/img/flags/BL.png b/res/img/flags/BL.png deleted file mode 100644 index 6d50a0f544..0000000000 Binary files a/res/img/flags/BL.png and /dev/null differ diff --git a/res/img/flags/BM.png b/res/img/flags/BM.png deleted file mode 100644 index 310a25ea23..0000000000 Binary files a/res/img/flags/BM.png and /dev/null differ diff --git a/res/img/flags/BN.png b/res/img/flags/BN.png deleted file mode 100644 index bc4da8d9a6..0000000000 Binary files a/res/img/flags/BN.png and /dev/null differ diff --git a/res/img/flags/BO.png b/res/img/flags/BO.png deleted file mode 100644 index 144b8d32db..0000000000 Binary files a/res/img/flags/BO.png and /dev/null differ diff --git a/res/img/flags/BQ.png b/res/img/flags/BQ.png deleted file mode 100644 index 0897943760..0000000000 Binary files a/res/img/flags/BQ.png and /dev/null differ diff --git a/res/img/flags/BR.png b/res/img/flags/BR.png deleted file mode 100644 index 0278492592..0000000000 Binary files a/res/img/flags/BR.png and /dev/null differ diff --git a/res/img/flags/BS.png b/res/img/flags/BS.png deleted file mode 100644 index 2b05a8fc7c..0000000000 Binary files a/res/img/flags/BS.png and /dev/null differ diff --git a/res/img/flags/BT.png b/res/img/flags/BT.png deleted file mode 100644 index 1f031df071..0000000000 Binary files a/res/img/flags/BT.png and /dev/null differ diff --git a/res/img/flags/BV.png b/res/img/flags/BV.png deleted file mode 100644 index aafb0f1776..0000000000 Binary files a/res/img/flags/BV.png and /dev/null differ diff --git a/res/img/flags/BW.png b/res/img/flags/BW.png deleted file mode 100644 index 3084016718..0000000000 Binary files a/res/img/flags/BW.png and /dev/null differ diff --git a/res/img/flags/BY.png b/res/img/flags/BY.png deleted file mode 100644 index ce9de9c9c7..0000000000 Binary files a/res/img/flags/BY.png and /dev/null differ diff --git a/res/img/flags/BZ.png b/res/img/flags/BZ.png deleted file mode 100644 index 33620c3f31..0000000000 Binary files a/res/img/flags/BZ.png and /dev/null differ diff --git a/res/img/flags/CA.png b/res/img/flags/CA.png deleted file mode 100644 index 4bbf8b1169..0000000000 Binary files a/res/img/flags/CA.png and /dev/null differ diff --git a/res/img/flags/CC.png b/res/img/flags/CC.png deleted file mode 100644 index fd40fc8a78..0000000000 Binary files a/res/img/flags/CC.png and /dev/null differ diff --git a/res/img/flags/CD.png b/res/img/flags/CD.png deleted file mode 100644 index 230aacd454..0000000000 Binary files a/res/img/flags/CD.png and /dev/null differ diff --git a/res/img/flags/CF.png b/res/img/flags/CF.png deleted file mode 100644 index c58ed4f7b2..0000000000 Binary files a/res/img/flags/CF.png and /dev/null differ diff --git a/res/img/flags/CG.png b/res/img/flags/CG.png deleted file mode 100644 index 6c2441e3e0..0000000000 Binary files a/res/img/flags/CG.png and /dev/null differ diff --git a/res/img/flags/CH.png b/res/img/flags/CH.png deleted file mode 100644 index 9fd87167df..0000000000 Binary files a/res/img/flags/CH.png and /dev/null differ diff --git a/res/img/flags/CI.png b/res/img/flags/CI.png deleted file mode 100644 index 9741b9b11f..0000000000 Binary files a/res/img/flags/CI.png and /dev/null differ diff --git a/res/img/flags/CK.png b/res/img/flags/CK.png deleted file mode 100644 index 6cca35967c..0000000000 Binary files a/res/img/flags/CK.png and /dev/null differ diff --git a/res/img/flags/CL.png b/res/img/flags/CL.png deleted file mode 100644 index 13b993d15d..0000000000 Binary files a/res/img/flags/CL.png and /dev/null differ diff --git a/res/img/flags/CM.png b/res/img/flags/CM.png deleted file mode 100644 index bca5730fb5..0000000000 Binary files a/res/img/flags/CM.png and /dev/null differ diff --git a/res/img/flags/CN.png b/res/img/flags/CN.png deleted file mode 100644 index e086855c73..0000000000 Binary files a/res/img/flags/CN.png and /dev/null differ diff --git a/res/img/flags/CO.png b/res/img/flags/CO.png deleted file mode 100644 index 65c0aba447..0000000000 Binary files a/res/img/flags/CO.png and /dev/null differ diff --git a/res/img/flags/CR.png b/res/img/flags/CR.png deleted file mode 100644 index b351c67a53..0000000000 Binary files a/res/img/flags/CR.png and /dev/null differ diff --git a/res/img/flags/CU.png b/res/img/flags/CU.png deleted file mode 100644 index e7a25c60b3..0000000000 Binary files a/res/img/flags/CU.png and /dev/null differ diff --git a/res/img/flags/CV.png b/res/img/flags/CV.png deleted file mode 100644 index f249bbaa46..0000000000 Binary files a/res/img/flags/CV.png and /dev/null differ diff --git a/res/img/flags/CW.png b/res/img/flags/CW.png deleted file mode 100644 index e02cacd3dd..0000000000 Binary files a/res/img/flags/CW.png and /dev/null differ diff --git a/res/img/flags/CX.png b/res/img/flags/CX.png deleted file mode 100644 index 3ea21422f0..0000000000 Binary files a/res/img/flags/CX.png and /dev/null differ diff --git a/res/img/flags/CY.png b/res/img/flags/CY.png deleted file mode 100644 index 3182f48bd2..0000000000 Binary files a/res/img/flags/CY.png and /dev/null differ diff --git a/res/img/flags/CZ.png b/res/img/flags/CZ.png deleted file mode 100644 index 5462334638..0000000000 Binary files a/res/img/flags/CZ.png and /dev/null differ diff --git a/res/img/flags/DE.png b/res/img/flags/DE.png deleted file mode 100644 index 93e269166b..0000000000 Binary files a/res/img/flags/DE.png and /dev/null differ diff --git a/res/img/flags/DJ.png b/res/img/flags/DJ.png deleted file mode 100644 index 243bb7390d..0000000000 Binary files a/res/img/flags/DJ.png and /dev/null differ diff --git a/res/img/flags/DK.png b/res/img/flags/DK.png deleted file mode 100644 index fc74cc396c..0000000000 Binary files a/res/img/flags/DK.png and /dev/null differ diff --git a/res/img/flags/DM.png b/res/img/flags/DM.png deleted file mode 100644 index c3a0e9d102..0000000000 Binary files a/res/img/flags/DM.png and /dev/null differ diff --git a/res/img/flags/DO.png b/res/img/flags/DO.png deleted file mode 100644 index 5c4a004fef..0000000000 Binary files a/res/img/flags/DO.png and /dev/null differ diff --git a/res/img/flags/DZ.png b/res/img/flags/DZ.png deleted file mode 100644 index 1589d0cc40..0000000000 Binary files a/res/img/flags/DZ.png and /dev/null differ diff --git a/res/img/flags/EC.png b/res/img/flags/EC.png deleted file mode 100644 index 4c53dead1c..0000000000 Binary files a/res/img/flags/EC.png and /dev/null differ diff --git a/res/img/flags/EE.png b/res/img/flags/EE.png deleted file mode 100644 index 3668de7919..0000000000 Binary files a/res/img/flags/EE.png and /dev/null differ diff --git a/res/img/flags/EG.png b/res/img/flags/EG.png deleted file mode 100644 index 66ec709df7..0000000000 Binary files a/res/img/flags/EG.png and /dev/null differ diff --git a/res/img/flags/EH.png b/res/img/flags/EH.png deleted file mode 100644 index 148be93c08..0000000000 Binary files a/res/img/flags/EH.png and /dev/null differ diff --git a/res/img/flags/ER.png b/res/img/flags/ER.png deleted file mode 100644 index 7cb8441514..0000000000 Binary files a/res/img/flags/ER.png and /dev/null differ diff --git a/res/img/flags/ES.png b/res/img/flags/ES.png deleted file mode 100644 index aae73b6fcb..0000000000 Binary files a/res/img/flags/ES.png and /dev/null differ diff --git a/res/img/flags/ET.png b/res/img/flags/ET.png deleted file mode 100644 index 7b420f02f4..0000000000 Binary files a/res/img/flags/ET.png and /dev/null differ diff --git a/res/img/flags/FI.png b/res/img/flags/FI.png deleted file mode 100644 index 42f64bf360..0000000000 Binary files a/res/img/flags/FI.png and /dev/null differ diff --git a/res/img/flags/FJ.png b/res/img/flags/FJ.png deleted file mode 100644 index cecc683c9c..0000000000 Binary files a/res/img/flags/FJ.png and /dev/null differ diff --git a/res/img/flags/FK.png b/res/img/flags/FK.png deleted file mode 100644 index 6074fea09c..0000000000 Binary files a/res/img/flags/FK.png and /dev/null differ diff --git a/res/img/flags/FM.png b/res/img/flags/FM.png deleted file mode 100644 index 45fdb66426..0000000000 Binary files a/res/img/flags/FM.png and /dev/null differ diff --git a/res/img/flags/FO.png b/res/img/flags/FO.png deleted file mode 100644 index d8fd75c638..0000000000 Binary files a/res/img/flags/FO.png and /dev/null differ diff --git a/res/img/flags/FR.png b/res/img/flags/FR.png deleted file mode 100644 index 6d50a0f544..0000000000 Binary files a/res/img/flags/FR.png and /dev/null differ diff --git a/res/img/flags/GA.png b/res/img/flags/GA.png deleted file mode 100644 index 3808a61f1d..0000000000 Binary files a/res/img/flags/GA.png and /dev/null differ diff --git a/res/img/flags/GB.png b/res/img/flags/GB.png deleted file mode 100644 index 589be70063..0000000000 Binary files a/res/img/flags/GB.png and /dev/null differ diff --git a/res/img/flags/GD.png b/res/img/flags/GD.png deleted file mode 100644 index babe1e4cc6..0000000000 Binary files a/res/img/flags/GD.png and /dev/null differ diff --git a/res/img/flags/GE.png b/res/img/flags/GE.png deleted file mode 100644 index d34cddeca9..0000000000 Binary files a/res/img/flags/GE.png and /dev/null differ diff --git a/res/img/flags/GF.png b/res/img/flags/GF.png deleted file mode 100644 index 98828a5906..0000000000 Binary files a/res/img/flags/GF.png and /dev/null differ diff --git a/res/img/flags/GG.png b/res/img/flags/GG.png deleted file mode 100644 index aec8969b28..0000000000 Binary files a/res/img/flags/GG.png and /dev/null differ diff --git a/res/img/flags/GH.png b/res/img/flags/GH.png deleted file mode 100644 index 70b1a623de..0000000000 Binary files a/res/img/flags/GH.png and /dev/null differ diff --git a/res/img/flags/GI.png b/res/img/flags/GI.png deleted file mode 100644 index 9aa58327e3..0000000000 Binary files a/res/img/flags/GI.png and /dev/null differ diff --git a/res/img/flags/GL.png b/res/img/flags/GL.png deleted file mode 100644 index cf1645c2b5..0000000000 Binary files a/res/img/flags/GL.png and /dev/null differ diff --git a/res/img/flags/GM.png b/res/img/flags/GM.png deleted file mode 100644 index ec374fb3c3..0000000000 Binary files a/res/img/flags/GM.png and /dev/null differ diff --git a/res/img/flags/GN.png b/res/img/flags/GN.png deleted file mode 100644 index 46874b4d98..0000000000 Binary files a/res/img/flags/GN.png and /dev/null differ diff --git a/res/img/flags/GP.png b/res/img/flags/GP.png deleted file mode 100644 index 81b7abdf0e..0000000000 Binary files a/res/img/flags/GP.png and /dev/null differ diff --git a/res/img/flags/GQ.png b/res/img/flags/GQ.png deleted file mode 100644 index 7fd1015e8b..0000000000 Binary files a/res/img/flags/GQ.png and /dev/null differ diff --git a/res/img/flags/GR.png b/res/img/flags/GR.png deleted file mode 100644 index 101de51eab..0000000000 Binary files a/res/img/flags/GR.png and /dev/null differ diff --git a/res/img/flags/GS.png b/res/img/flags/GS.png deleted file mode 100644 index 772c2cbe6d..0000000000 Binary files a/res/img/flags/GS.png and /dev/null differ diff --git a/res/img/flags/GT.png b/res/img/flags/GT.png deleted file mode 100644 index d5bd8c1e46..0000000000 Binary files a/res/img/flags/GT.png and /dev/null differ diff --git a/res/img/flags/GU.png b/res/img/flags/GU.png deleted file mode 100644 index 8923085d5a..0000000000 Binary files a/res/img/flags/GU.png and /dev/null differ diff --git a/res/img/flags/GW.png b/res/img/flags/GW.png deleted file mode 100644 index 20c268ce06..0000000000 Binary files a/res/img/flags/GW.png and /dev/null differ diff --git a/res/img/flags/GY.png b/res/img/flags/GY.png deleted file mode 100644 index 86f56635ef..0000000000 Binary files a/res/img/flags/GY.png and /dev/null differ diff --git a/res/img/flags/HK.png b/res/img/flags/HK.png deleted file mode 100644 index 907dc59624..0000000000 Binary files a/res/img/flags/HK.png and /dev/null differ diff --git a/res/img/flags/HM.png b/res/img/flags/HM.png deleted file mode 100644 index 8d1e143791..0000000000 Binary files a/res/img/flags/HM.png and /dev/null differ diff --git a/res/img/flags/HN.png b/res/img/flags/HN.png deleted file mode 100644 index 4cf8c3112c..0000000000 Binary files a/res/img/flags/HN.png and /dev/null differ diff --git a/res/img/flags/HR.png b/res/img/flags/HR.png deleted file mode 100644 index 413ceb1586..0000000000 Binary files a/res/img/flags/HR.png and /dev/null differ diff --git a/res/img/flags/HT.png b/res/img/flags/HT.png deleted file mode 100644 index 097abeb434..0000000000 Binary files a/res/img/flags/HT.png and /dev/null differ diff --git a/res/img/flags/HU.png b/res/img/flags/HU.png deleted file mode 100644 index 23499bf63c..0000000000 Binary files a/res/img/flags/HU.png and /dev/null differ diff --git a/res/img/flags/ID.png b/res/img/flags/ID.png deleted file mode 100644 index 80200657c6..0000000000 Binary files a/res/img/flags/ID.png and /dev/null differ diff --git a/res/img/flags/IE.png b/res/img/flags/IE.png deleted file mode 100644 index 63f2220118..0000000000 Binary files a/res/img/flags/IE.png and /dev/null differ diff --git a/res/img/flags/IL.png b/res/img/flags/IL.png deleted file mode 100644 index 0268826321..0000000000 Binary files a/res/img/flags/IL.png and /dev/null differ diff --git a/res/img/flags/IM.png b/res/img/flags/IM.png deleted file mode 100644 index c777acc490..0000000000 Binary files a/res/img/flags/IM.png and /dev/null differ diff --git a/res/img/flags/IN.png b/res/img/flags/IN.png deleted file mode 100644 index 85fa9bfe72..0000000000 Binary files a/res/img/flags/IN.png and /dev/null differ diff --git a/res/img/flags/IO.png b/res/img/flags/IO.png deleted file mode 100644 index 1675d8e7db..0000000000 Binary files a/res/img/flags/IO.png and /dev/null differ diff --git a/res/img/flags/IQ.png b/res/img/flags/IQ.png deleted file mode 100644 index f2c21f7260..0000000000 Binary files a/res/img/flags/IQ.png and /dev/null differ diff --git a/res/img/flags/IR.png b/res/img/flags/IR.png deleted file mode 100644 index 0b8e67506c..0000000000 Binary files a/res/img/flags/IR.png and /dev/null differ diff --git a/res/img/flags/IS.png b/res/img/flags/IS.png deleted file mode 100644 index 5ee3e63c5c..0000000000 Binary files a/res/img/flags/IS.png and /dev/null differ diff --git a/res/img/flags/IT.png b/res/img/flags/IT.png deleted file mode 100644 index 53b967be99..0000000000 Binary files a/res/img/flags/IT.png and /dev/null differ diff --git a/res/img/flags/JE.png b/res/img/flags/JE.png deleted file mode 100644 index a1437aba78..0000000000 Binary files a/res/img/flags/JE.png and /dev/null differ diff --git a/res/img/flags/JM.png b/res/img/flags/JM.png deleted file mode 100644 index 0d462fa3ae..0000000000 Binary files a/res/img/flags/JM.png and /dev/null differ diff --git a/res/img/flags/JO.png b/res/img/flags/JO.png deleted file mode 100644 index 8934db7eca..0000000000 Binary files a/res/img/flags/JO.png and /dev/null differ diff --git a/res/img/flags/JP.png b/res/img/flags/JP.png deleted file mode 100644 index 6f92d52365..0000000000 Binary files a/res/img/flags/JP.png and /dev/null differ diff --git a/res/img/flags/KE.png b/res/img/flags/KE.png deleted file mode 100644 index 866b3f15dc..0000000000 Binary files a/res/img/flags/KE.png and /dev/null differ diff --git a/res/img/flags/KG.png b/res/img/flags/KG.png deleted file mode 100644 index 56b433c756..0000000000 Binary files a/res/img/flags/KG.png and /dev/null differ diff --git a/res/img/flags/KH.png b/res/img/flags/KH.png deleted file mode 100644 index e1ddd5f84c..0000000000 Binary files a/res/img/flags/KH.png and /dev/null differ diff --git a/res/img/flags/KI.png b/res/img/flags/KI.png deleted file mode 100644 index 8b7c54bc0f..0000000000 Binary files a/res/img/flags/KI.png and /dev/null differ diff --git a/res/img/flags/KM.png b/res/img/flags/KM.png deleted file mode 100644 index 227a3b3396..0000000000 Binary files a/res/img/flags/KM.png and /dev/null differ diff --git a/res/img/flags/KN.png b/res/img/flags/KN.png deleted file mode 100644 index bc6189bed1..0000000000 Binary files a/res/img/flags/KN.png and /dev/null differ diff --git a/res/img/flags/KP.png b/res/img/flags/KP.png deleted file mode 100644 index c92248b910..0000000000 Binary files a/res/img/flags/KP.png and /dev/null differ diff --git a/res/img/flags/KR.png b/res/img/flags/KR.png deleted file mode 100644 index ab1cb94943..0000000000 Binary files a/res/img/flags/KR.png and /dev/null differ diff --git a/res/img/flags/KW.png b/res/img/flags/KW.png deleted file mode 100644 index 0b41c7a532..0000000000 Binary files a/res/img/flags/KW.png and /dev/null differ diff --git a/res/img/flags/KY.png b/res/img/flags/KY.png deleted file mode 100644 index 7af5290d31..0000000000 Binary files a/res/img/flags/KY.png and /dev/null differ diff --git a/res/img/flags/KZ.png b/res/img/flags/KZ.png deleted file mode 100644 index e10a1255a0..0000000000 Binary files a/res/img/flags/KZ.png and /dev/null differ diff --git a/res/img/flags/LA.png b/res/img/flags/LA.png deleted file mode 100644 index 6ad67d4255..0000000000 Binary files a/res/img/flags/LA.png and /dev/null differ diff --git a/res/img/flags/LB.png b/res/img/flags/LB.png deleted file mode 100644 index 865df57a42..0000000000 Binary files a/res/img/flags/LB.png and /dev/null differ diff --git a/res/img/flags/LC.png b/res/img/flags/LC.png deleted file mode 100644 index e83a2d08bc..0000000000 Binary files a/res/img/flags/LC.png and /dev/null differ diff --git a/res/img/flags/LI.png b/res/img/flags/LI.png deleted file mode 100644 index 57034d367c..0000000000 Binary files a/res/img/flags/LI.png and /dev/null differ diff --git a/res/img/flags/LK.png b/res/img/flags/LK.png deleted file mode 100644 index 6e7ad58254..0000000000 Binary files a/res/img/flags/LK.png and /dev/null differ diff --git a/res/img/flags/LR.png b/res/img/flags/LR.png deleted file mode 100644 index 46c3b84a92..0000000000 Binary files a/res/img/flags/LR.png and /dev/null differ diff --git a/res/img/flags/LS.png b/res/img/flags/LS.png deleted file mode 100644 index 79b505d490..0000000000 Binary files a/res/img/flags/LS.png and /dev/null differ diff --git a/res/img/flags/LT.png b/res/img/flags/LT.png deleted file mode 100644 index 7740cdc0a0..0000000000 Binary files a/res/img/flags/LT.png and /dev/null differ diff --git a/res/img/flags/LU.png b/res/img/flags/LU.png deleted file mode 100644 index 8f383e674e..0000000000 Binary files a/res/img/flags/LU.png and /dev/null differ diff --git a/res/img/flags/LV.png b/res/img/flags/LV.png deleted file mode 100644 index a0f36d89c4..0000000000 Binary files a/res/img/flags/LV.png and /dev/null differ diff --git a/res/img/flags/LY.png b/res/img/flags/LY.png deleted file mode 100644 index 2884c4c0a9..0000000000 Binary files a/res/img/flags/LY.png and /dev/null differ diff --git a/res/img/flags/MA.png b/res/img/flags/MA.png deleted file mode 100644 index 1f76cfc9bd..0000000000 Binary files a/res/img/flags/MA.png and /dev/null differ diff --git a/res/img/flags/MC.png b/res/img/flags/MC.png deleted file mode 100644 index 06fc2ad166..0000000000 Binary files a/res/img/flags/MC.png and /dev/null differ diff --git a/res/img/flags/MD.png b/res/img/flags/MD.png deleted file mode 100644 index 8e54c2b815..0000000000 Binary files a/res/img/flags/MD.png and /dev/null differ diff --git a/res/img/flags/ME.png b/res/img/flags/ME.png deleted file mode 100644 index 97424d4ec2..0000000000 Binary files a/res/img/flags/ME.png and /dev/null differ diff --git a/res/img/flags/MF.png b/res/img/flags/MF.png deleted file mode 100644 index 6d50a0f544..0000000000 Binary files a/res/img/flags/MF.png and /dev/null differ diff --git a/res/img/flags/MG.png b/res/img/flags/MG.png deleted file mode 100644 index 28bfccc9e8..0000000000 Binary files a/res/img/flags/MG.png and /dev/null differ diff --git a/res/img/flags/MH.png b/res/img/flags/MH.png deleted file mode 100644 index e482a65924..0000000000 Binary files a/res/img/flags/MH.png and /dev/null differ diff --git a/res/img/flags/MK.png b/res/img/flags/MK.png deleted file mode 100644 index 84e2e65e76..0000000000 Binary files a/res/img/flags/MK.png and /dev/null differ diff --git a/res/img/flags/ML.png b/res/img/flags/ML.png deleted file mode 100644 index 38fec34796..0000000000 Binary files a/res/img/flags/ML.png and /dev/null differ diff --git a/res/img/flags/MM.png b/res/img/flags/MM.png deleted file mode 100644 index 70a03c6b14..0000000000 Binary files a/res/img/flags/MM.png and /dev/null differ diff --git a/res/img/flags/MN.png b/res/img/flags/MN.png deleted file mode 100644 index 1e1bbe6089..0000000000 Binary files a/res/img/flags/MN.png and /dev/null differ diff --git a/res/img/flags/MO.png b/res/img/flags/MO.png deleted file mode 100644 index 3833d683e7..0000000000 Binary files a/res/img/flags/MO.png and /dev/null differ diff --git a/res/img/flags/MP.png b/res/img/flags/MP.png deleted file mode 100644 index 63119096b0..0000000000 Binary files a/res/img/flags/MP.png and /dev/null differ diff --git a/res/img/flags/MQ.png b/res/img/flags/MQ.png deleted file mode 100644 index 9cab441aec..0000000000 Binary files a/res/img/flags/MQ.png and /dev/null differ diff --git a/res/img/flags/MR.png b/res/img/flags/MR.png deleted file mode 100644 index c144de17f7..0000000000 Binary files a/res/img/flags/MR.png and /dev/null differ diff --git a/res/img/flags/MS.png b/res/img/flags/MS.png deleted file mode 100644 index 1221707042..0000000000 Binary files a/res/img/flags/MS.png and /dev/null differ diff --git a/res/img/flags/MT.png b/res/img/flags/MT.png deleted file mode 100644 index 7963aa618a..0000000000 Binary files a/res/img/flags/MT.png and /dev/null differ diff --git a/res/img/flags/MU.png b/res/img/flags/MU.png deleted file mode 100644 index d5d4d4008d..0000000000 Binary files a/res/img/flags/MU.png and /dev/null differ diff --git a/res/img/flags/MV.png b/res/img/flags/MV.png deleted file mode 100644 index 0f2ecb4389..0000000000 Binary files a/res/img/flags/MV.png and /dev/null differ diff --git a/res/img/flags/MW.png b/res/img/flags/MW.png deleted file mode 100644 index d0a5d24f55..0000000000 Binary files a/res/img/flags/MW.png and /dev/null differ diff --git a/res/img/flags/MX.png b/res/img/flags/MX.png deleted file mode 100644 index 096cb1111f..0000000000 Binary files a/res/img/flags/MX.png and /dev/null differ diff --git a/res/img/flags/MY.png b/res/img/flags/MY.png deleted file mode 100644 index 17f18ac519..0000000000 Binary files a/res/img/flags/MY.png and /dev/null differ diff --git a/res/img/flags/MZ.png b/res/img/flags/MZ.png deleted file mode 100644 index 66be6563c6..0000000000 Binary files a/res/img/flags/MZ.png and /dev/null differ diff --git a/res/img/flags/NA.png b/res/img/flags/NA.png deleted file mode 100644 index 7ecfd317c7..0000000000 Binary files a/res/img/flags/NA.png and /dev/null differ diff --git a/res/img/flags/NC.png b/res/img/flags/NC.png deleted file mode 100644 index 11126ade77..0000000000 Binary files a/res/img/flags/NC.png and /dev/null differ diff --git a/res/img/flags/NE.png b/res/img/flags/NE.png deleted file mode 100644 index d584fa8429..0000000000 Binary files a/res/img/flags/NE.png and /dev/null differ diff --git a/res/img/flags/NF.png b/res/img/flags/NF.png deleted file mode 100644 index c054042591..0000000000 Binary files a/res/img/flags/NF.png and /dev/null differ diff --git a/res/img/flags/NG.png b/res/img/flags/NG.png deleted file mode 100644 index 73aee15b3f..0000000000 Binary files a/res/img/flags/NG.png and /dev/null differ diff --git a/res/img/flags/NI.png b/res/img/flags/NI.png deleted file mode 100644 index fd044933e4..0000000000 Binary files a/res/img/flags/NI.png and /dev/null differ diff --git a/res/img/flags/NL.png b/res/img/flags/NL.png deleted file mode 100644 index 0897943760..0000000000 Binary files a/res/img/flags/NL.png and /dev/null differ diff --git a/res/img/flags/NO.png b/res/img/flags/NO.png deleted file mode 100644 index aafb0f1776..0000000000 Binary files a/res/img/flags/NO.png and /dev/null differ diff --git a/res/img/flags/NP.png b/res/img/flags/NP.png deleted file mode 100644 index 744458e17e..0000000000 Binary files a/res/img/flags/NP.png and /dev/null differ diff --git a/res/img/flags/NR.png b/res/img/flags/NR.png deleted file mode 100644 index 58c2afb228..0000000000 Binary files a/res/img/flags/NR.png and /dev/null differ diff --git a/res/img/flags/NU.png b/res/img/flags/NU.png deleted file mode 100644 index 007c99eca5..0000000000 Binary files a/res/img/flags/NU.png and /dev/null differ diff --git a/res/img/flags/NZ.png b/res/img/flags/NZ.png deleted file mode 100644 index 839368dd7b..0000000000 Binary files a/res/img/flags/NZ.png and /dev/null differ diff --git a/res/img/flags/OM.png b/res/img/flags/OM.png deleted file mode 100644 index 63a893367f..0000000000 Binary files a/res/img/flags/OM.png and /dev/null differ diff --git a/res/img/flags/PA.png b/res/img/flags/PA.png deleted file mode 100644 index 3515d95d37..0000000000 Binary files a/res/img/flags/PA.png and /dev/null differ diff --git a/res/img/flags/PE.png b/res/img/flags/PE.png deleted file mode 100644 index 58f70b8d18..0000000000 Binary files a/res/img/flags/PE.png and /dev/null differ diff --git a/res/img/flags/PF.png b/res/img/flags/PF.png deleted file mode 100644 index 2f33f2574f..0000000000 Binary files a/res/img/flags/PF.png and /dev/null differ diff --git a/res/img/flags/PG.png b/res/img/flags/PG.png deleted file mode 100644 index c796f587c6..0000000000 Binary files a/res/img/flags/PG.png and /dev/null differ diff --git a/res/img/flags/PH.png b/res/img/flags/PH.png deleted file mode 100644 index 0d98de0386..0000000000 Binary files a/res/img/flags/PH.png and /dev/null differ diff --git a/res/img/flags/PK.png b/res/img/flags/PK.png deleted file mode 100644 index 87f4e2f492..0000000000 Binary files a/res/img/flags/PK.png and /dev/null differ diff --git a/res/img/flags/PL.png b/res/img/flags/PL.png deleted file mode 100644 index 273869dfc6..0000000000 Binary files a/res/img/flags/PL.png and /dev/null differ diff --git a/res/img/flags/PM.png b/res/img/flags/PM.png deleted file mode 100644 index b74c396d92..0000000000 Binary files a/res/img/flags/PM.png and /dev/null differ diff --git a/res/img/flags/PN.png b/res/img/flags/PN.png deleted file mode 100644 index e34c62d598..0000000000 Binary files a/res/img/flags/PN.png and /dev/null differ diff --git a/res/img/flags/PR.png b/res/img/flags/PR.png deleted file mode 100644 index 8efdb91252..0000000000 Binary files a/res/img/flags/PR.png and /dev/null differ diff --git a/res/img/flags/PS.png b/res/img/flags/PS.png deleted file mode 100644 index 7a0cceec00..0000000000 Binary files a/res/img/flags/PS.png and /dev/null differ diff --git a/res/img/flags/PT.png b/res/img/flags/PT.png deleted file mode 100644 index 49e290827c..0000000000 Binary files a/res/img/flags/PT.png and /dev/null differ diff --git a/res/img/flags/PW.png b/res/img/flags/PW.png deleted file mode 100644 index 6cb2e1e70d..0000000000 Binary files a/res/img/flags/PW.png and /dev/null differ diff --git a/res/img/flags/PY.png b/res/img/flags/PY.png deleted file mode 100644 index a61c42c423..0000000000 Binary files a/res/img/flags/PY.png and /dev/null differ diff --git a/res/img/flags/QA.png b/res/img/flags/QA.png deleted file mode 100644 index bb091cc88c..0000000000 Binary files a/res/img/flags/QA.png and /dev/null differ diff --git a/res/img/flags/RE.png b/res/img/flags/RE.png deleted file mode 100644 index 6d50a0f544..0000000000 Binary files a/res/img/flags/RE.png and /dev/null differ diff --git a/res/img/flags/RO.png b/res/img/flags/RO.png deleted file mode 100644 index 4495d29eb0..0000000000 Binary files a/res/img/flags/RO.png and /dev/null differ diff --git a/res/img/flags/RS.png b/res/img/flags/RS.png deleted file mode 100644 index ebb0f28a7b..0000000000 Binary files a/res/img/flags/RS.png and /dev/null differ diff --git a/res/img/flags/RU.png b/res/img/flags/RU.png deleted file mode 100644 index 64532ffa58..0000000000 Binary files a/res/img/flags/RU.png and /dev/null differ diff --git a/res/img/flags/RW.png b/res/img/flags/RW.png deleted file mode 100644 index 64b3cfff04..0000000000 Binary files a/res/img/flags/RW.png and /dev/null differ diff --git a/res/img/flags/SA.png b/res/img/flags/SA.png deleted file mode 100644 index 250de6f6f5..0000000000 Binary files a/res/img/flags/SA.png and /dev/null differ diff --git a/res/img/flags/SB.png b/res/img/flags/SB.png deleted file mode 100644 index 5833c130eb..0000000000 Binary files a/res/img/flags/SB.png and /dev/null differ diff --git a/res/img/flags/SC.png b/res/img/flags/SC.png deleted file mode 100644 index ce5248f434..0000000000 Binary files a/res/img/flags/SC.png and /dev/null differ diff --git a/res/img/flags/SD.png b/res/img/flags/SD.png deleted file mode 100644 index d8711a83d6..0000000000 Binary files a/res/img/flags/SD.png and /dev/null differ diff --git a/res/img/flags/SE.png b/res/img/flags/SE.png deleted file mode 100644 index 81880931f3..0000000000 Binary files a/res/img/flags/SE.png and /dev/null differ diff --git a/res/img/flags/SG.png b/res/img/flags/SG.png deleted file mode 100644 index 6f00e57923..0000000000 Binary files a/res/img/flags/SG.png and /dev/null differ diff --git a/res/img/flags/SH.png b/res/img/flags/SH.png deleted file mode 100644 index 055dde68bc..0000000000 Binary files a/res/img/flags/SH.png and /dev/null differ diff --git a/res/img/flags/SI.png b/res/img/flags/SI.png deleted file mode 100644 index 9635983406..0000000000 Binary files a/res/img/flags/SI.png and /dev/null differ diff --git a/res/img/flags/SJ.png b/res/img/flags/SJ.png deleted file mode 100644 index aafb0f1776..0000000000 Binary files a/res/img/flags/SJ.png and /dev/null differ diff --git a/res/img/flags/SK.png b/res/img/flags/SK.png deleted file mode 100644 index 84c7021f0a..0000000000 Binary files a/res/img/flags/SK.png and /dev/null differ diff --git a/res/img/flags/SL.png b/res/img/flags/SL.png deleted file mode 100644 index c5ed199141..0000000000 Binary files a/res/img/flags/SL.png and /dev/null differ diff --git a/res/img/flags/SM.png b/res/img/flags/SM.png deleted file mode 100644 index 1af1ca284f..0000000000 Binary files a/res/img/flags/SM.png and /dev/null differ diff --git a/res/img/flags/SN.png b/res/img/flags/SN.png deleted file mode 100644 index d0b1843561..0000000000 Binary files a/res/img/flags/SN.png and /dev/null differ diff --git a/res/img/flags/SO.png b/res/img/flags/SO.png deleted file mode 100644 index 64e2970b9d..0000000000 Binary files a/res/img/flags/SO.png and /dev/null differ diff --git a/res/img/flags/SR.png b/res/img/flags/SR.png deleted file mode 100644 index b072dda835..0000000000 Binary files a/res/img/flags/SR.png and /dev/null differ diff --git a/res/img/flags/SS.png b/res/img/flags/SS.png deleted file mode 100644 index 83933d4521..0000000000 Binary files a/res/img/flags/SS.png and /dev/null differ diff --git a/res/img/flags/ST.png b/res/img/flags/ST.png deleted file mode 100644 index c102721a86..0000000000 Binary files a/res/img/flags/ST.png and /dev/null differ diff --git a/res/img/flags/SV.png b/res/img/flags/SV.png deleted file mode 100644 index 80de92e556..0000000000 Binary files a/res/img/flags/SV.png and /dev/null differ diff --git a/res/img/flags/SX.png b/res/img/flags/SX.png deleted file mode 100644 index dd52215c5d..0000000000 Binary files a/res/img/flags/SX.png and /dev/null differ diff --git a/res/img/flags/SY.png b/res/img/flags/SY.png deleted file mode 100644 index 78f45b7c0b..0000000000 Binary files a/res/img/flags/SY.png and /dev/null differ diff --git a/res/img/flags/SZ.png b/res/img/flags/SZ.png deleted file mode 100644 index 2182f4ff93..0000000000 Binary files a/res/img/flags/SZ.png and /dev/null differ diff --git a/res/img/flags/TC.png b/res/img/flags/TC.png deleted file mode 100644 index 3e3e19d4b3..0000000000 Binary files a/res/img/flags/TC.png and /dev/null differ diff --git a/res/img/flags/TD.png b/res/img/flags/TD.png deleted file mode 100644 index 753bec22b0..0000000000 Binary files a/res/img/flags/TD.png and /dev/null differ diff --git a/res/img/flags/TF.png b/res/img/flags/TF.png deleted file mode 100644 index 6d50a0f544..0000000000 Binary files a/res/img/flags/TF.png and /dev/null differ diff --git a/res/img/flags/TG.png b/res/img/flags/TG.png deleted file mode 100644 index 8501ada655..0000000000 Binary files a/res/img/flags/TG.png and /dev/null differ diff --git a/res/img/flags/TH.png b/res/img/flags/TH.png deleted file mode 100644 index 0c884c329e..0000000000 Binary files a/res/img/flags/TH.png and /dev/null differ diff --git a/res/img/flags/TJ.png b/res/img/flags/TJ.png deleted file mode 100644 index 3c9026fa0f..0000000000 Binary files a/res/img/flags/TJ.png and /dev/null differ diff --git a/res/img/flags/TK.png b/res/img/flags/TK.png deleted file mode 100644 index fd605749ea..0000000000 Binary files a/res/img/flags/TK.png and /dev/null differ diff --git a/res/img/flags/TL.png b/res/img/flags/TL.png deleted file mode 100644 index b4c834b1d6..0000000000 Binary files a/res/img/flags/TL.png and /dev/null differ diff --git a/res/img/flags/TM.png b/res/img/flags/TM.png deleted file mode 100644 index d18cb939a9..0000000000 Binary files a/res/img/flags/TM.png and /dev/null differ diff --git a/res/img/flags/TN.png b/res/img/flags/TN.png deleted file mode 100644 index 21c4b98be7..0000000000 Binary files a/res/img/flags/TN.png and /dev/null differ diff --git a/res/img/flags/TO.png b/res/img/flags/TO.png deleted file mode 100644 index c828206e35..0000000000 Binary files a/res/img/flags/TO.png and /dev/null differ diff --git a/res/img/flags/TR.png b/res/img/flags/TR.png deleted file mode 100644 index f2a5bd22c8..0000000000 Binary files a/res/img/flags/TR.png and /dev/null differ diff --git a/res/img/flags/TT.png b/res/img/flags/TT.png deleted file mode 100644 index 66d698334b..0000000000 Binary files a/res/img/flags/TT.png and /dev/null differ diff --git a/res/img/flags/TV.png b/res/img/flags/TV.png deleted file mode 100644 index 7a127f51ae..0000000000 Binary files a/res/img/flags/TV.png and /dev/null differ diff --git a/res/img/flags/TW.png b/res/img/flags/TW.png deleted file mode 100644 index 2353ba1b0a..0000000000 Binary files a/res/img/flags/TW.png and /dev/null differ diff --git a/res/img/flags/TZ.png b/res/img/flags/TZ.png deleted file mode 100644 index 7949f65d8a..0000000000 Binary files a/res/img/flags/TZ.png and /dev/null differ diff --git a/res/img/flags/UA.png b/res/img/flags/UA.png deleted file mode 100644 index 687e305294..0000000000 Binary files a/res/img/flags/UA.png and /dev/null differ diff --git a/res/img/flags/UG.png b/res/img/flags/UG.png deleted file mode 100644 index 0a21ad15c3..0000000000 Binary files a/res/img/flags/UG.png and /dev/null differ diff --git a/res/img/flags/US.png b/res/img/flags/US.png deleted file mode 100644 index c3a245b767..0000000000 Binary files a/res/img/flags/US.png and /dev/null differ diff --git a/res/img/flags/UY.png b/res/img/flags/UY.png deleted file mode 100644 index 21a347c6fc..0000000000 Binary files a/res/img/flags/UY.png and /dev/null differ diff --git a/res/img/flags/UZ.png b/res/img/flags/UZ.png deleted file mode 100644 index 643b6ae0cf..0000000000 Binary files a/res/img/flags/UZ.png and /dev/null differ diff --git a/res/img/flags/VA.png b/res/img/flags/VA.png deleted file mode 100644 index 63a13c0e81..0000000000 Binary files a/res/img/flags/VA.png and /dev/null differ diff --git a/res/img/flags/VC.png b/res/img/flags/VC.png deleted file mode 100644 index da991a9344..0000000000 Binary files a/res/img/flags/VC.png and /dev/null differ diff --git a/res/img/flags/VE.png b/res/img/flags/VE.png deleted file mode 100644 index e75e17c9f0..0000000000 Binary files a/res/img/flags/VE.png and /dev/null differ diff --git a/res/img/flags/VG.png b/res/img/flags/VG.png deleted file mode 100644 index 46f93cad1e..0000000000 Binary files a/res/img/flags/VG.png and /dev/null differ diff --git a/res/img/flags/VI.png b/res/img/flags/VI.png deleted file mode 100644 index 8c849a733e..0000000000 Binary files a/res/img/flags/VI.png and /dev/null differ diff --git a/res/img/flags/VN.png b/res/img/flags/VN.png deleted file mode 100644 index 6ea2122f9d..0000000000 Binary files a/res/img/flags/VN.png and /dev/null differ diff --git a/res/img/flags/VU.png b/res/img/flags/VU.png deleted file mode 100644 index bad3ba4d46..0000000000 Binary files a/res/img/flags/VU.png and /dev/null differ diff --git a/res/img/flags/WF.png b/res/img/flags/WF.png deleted file mode 100644 index d94359dcc4..0000000000 Binary files a/res/img/flags/WF.png and /dev/null differ diff --git a/res/img/flags/WS.png b/res/img/flags/WS.png deleted file mode 100644 index f8b80e5ba9..0000000000 Binary files a/res/img/flags/WS.png and /dev/null differ diff --git a/res/img/flags/YE.png b/res/img/flags/YE.png deleted file mode 100644 index 8b9bbd8942..0000000000 Binary files a/res/img/flags/YE.png and /dev/null differ diff --git a/res/img/flags/YT.png b/res/img/flags/YT.png deleted file mode 100644 index 328879361e..0000000000 Binary files a/res/img/flags/YT.png and /dev/null differ diff --git a/res/img/flags/ZA.png b/res/img/flags/ZA.png deleted file mode 100644 index 7f0a52d3b2..0000000000 Binary files a/res/img/flags/ZA.png and /dev/null differ diff --git a/res/img/flags/ZM.png b/res/img/flags/ZM.png deleted file mode 100644 index 87adc3afaa..0000000000 Binary files a/res/img/flags/ZM.png and /dev/null differ diff --git a/res/img/flags/ZW.png b/res/img/flags/ZW.png deleted file mode 100644 index 742c9f7e71..0000000000 Binary files a/res/img/flags/ZW.png and /dev/null differ diff --git a/res/img/icon_person.svg b/res/img/icon_person.svg deleted file mode 100644 index 4be70df0db..0000000000 --- a/res/img/icon_person.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - 815EF7DE-169A-4322-AE2A-B65CBE91DCED - Created with sketchtool. - - - - - - - - - - - - - - - - - - diff --git a/res/themes/dark-custom/css/dark-custom.scss b/res/themes/dark-custom/css/dark-custom.scss index aff647ce26..03ceef45c6 100644 --- a/res/themes/dark-custom/css/dark-custom.scss +++ b/res/themes/dark-custom/css/dark-custom.scss @@ -1,3 +1,4 @@ +@import "../../../../res/css/_font-sizes.scss"; @import "../../light/css/_paths.scss"; @import "../../light/css/_fonts.scss"; @import "../../light/css/_light.scss"; diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index a3515a9d99..6224c0820f 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -147,6 +147,9 @@ $button-danger-disabled-bg-color: #f5b6bb; // TODO: Verify color $button-link-fg-color: $accent-color; $button-link-bg-color: transparent; +// Toggle switch +$togglesw-off-color: $room-highlight-color; + $visual-bell-bg-color: #800; $room-warning-bg-color: $header-panel-bg-color; @@ -165,6 +168,8 @@ $reaction-row-button-hover-border-color: $header-panel-text-primary-color; $reaction-row-button-selected-bg-color: #1f6954; $reaction-row-button-selected-border-color: $accent-color; +$kbd-border-color: #000000; + $tooltip-timeline-bg-color: $tagpanel-bg-color; $tooltip-timeline-fg-color: #ffffff; @@ -183,7 +188,7 @@ $user-tile-hover-bg-color: $header-panel-bg-color; border: 0px; border-radius: 4px; font-family: $font-family; - font-size: 14px; + font-size: $font-14px; color: $button-fg-color; background-color: $button-bg-color; width: auto; @@ -219,10 +224,6 @@ $user-tile-hover-bg-color: $header-panel-bg-color; filter: invert(1); } -.gm-scrollbar .thumb { - filter: invert(1); -} - // markdown overrides: .mx_EventTile_content .markdown-body pre:hover { border-color: #808080 !important; // inverted due to rules below diff --git a/res/themes/dark/css/dark.scss b/res/themes/dark/css/dark.scss index e7ae7c8cf8..d81db4595f 100644 --- a/res/themes/dark/css/dark.scss +++ b/res/themes/dark/css/dark.scss @@ -1,3 +1,4 @@ +@import "../../../../res/css/_font-sizes.scss"; @import "../../light/css/_paths.scss"; @import "../../light/css/_fonts.scss"; @import "../../light/css/_light.scss"; diff --git a/res/themes/light-custom/css/_custom.scss b/res/themes/light-custom/css/_custom.scss index e4a08277f9..6206496150 100644 --- a/res/themes/light-custom/css/_custom.scss +++ b/res/themes/light-custom/css/_custom.scss @@ -17,6 +17,7 @@ limitations under the License. // // --accent-color $accent-color: var(--accent-color); +$accent-bg-color: var(--accent-color-15pct); $button-bg-color: var(--accent-color); $button-link-fg-color: var(--accent-color); $button-primary-bg-color: var(--accent-color); @@ -52,7 +53,6 @@ $tooltip-timeline-bg-color: var(--sidebar-color); $dialog-backdrop-color: var(--sidebar-color-50pct); // // --roomlist-background-color -$event-selected-color: var(--roomlist-background-color); $header-panel-bg-color: var(--roomlist-background-color); $reaction-row-button-bg-color: var(--roomlist-background-color); $panel-gradient: var(--roomlist-background-color-0pct), var(--roomlist-background-color); @@ -124,3 +124,15 @@ $notice-primary-color: var(--warning-color); $pinned-unread-color: var(--warning-color); $warning-color: var(--warning-color); $button-danger-disabled-bg-color: var(--warning-color-50pct); // still needs alpha at 0.5 + +$username-variant1-color: var(--username-colors_1, $username-variant1-color); +$username-variant2-color: var(--username-colors_2, $username-variant2-color); +$username-variant3-color: var(--username-colors_3, $username-variant3-color); +$username-variant4-color: var(--username-colors_4, $username-variant4-color); +$username-variant5-color: var(--username-colors_5, $username-variant5-color); +$username-variant6-color: var(--username-colors_6, $username-variant6-color); +$username-variant7-color: var(--username-colors_7, $username-variant7-color); +$username-variant8-color: var(--username-colors_8, $username-variant8-color); + +$event-selected-color: var(--timeline-highlights-color); +$event-highlight-bg-color: var(--timeline-highlights-color); diff --git a/res/themes/light-custom/css/light-custom.scss b/res/themes/light-custom/css/light-custom.scss index 278ca5f0b1..4f80647eba 100644 --- a/res/themes/light-custom/css/light-custom.scss +++ b/res/themes/light-custom/css/light-custom.scss @@ -1,3 +1,4 @@ +@import "../../../../res/css/_font-sizes.scss"; @import "../../light/css/_paths.scss"; @import "../../light/css/_fonts.scss"; @import "../../light/css/_light.scss"; diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index c868c81549..f5f3013354 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -5,9 +5,12 @@ Arial empirically gets it right, hence prioritising Arial here. */ /* We fall through to Twemoji for emoji rather than falling through to native Emoji fonts (if any) to ensure cross-browser consistency */ -$font-family: Nunito, Twemoji, 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', Arial, Helvetica, Sans-Serif; +/* Noto Color Emoji contains digits, in fixed-width, therefore causing + digits in flowed text to stand out. + TODO: Consider putting all emoji fonts to the end rather than the front. */ +$font-family: Nunito, Twemoji, 'Apple Color Emoji', 'Segoe UI Emoji', Arial, Helvetica, Sans-Serif, 'Noto Color Emoji'; -$monospace-font-family: Inconsolata, Twemoji, 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', Courier, monospace; +$monospace-font-family: Inconsolata, Twemoji, 'Apple Color Emoji', 'Segoe UI Emoji', Courier, monospace, 'Noto Color Emoji'; // unified palette // try to use these colors when possible @@ -287,6 +290,8 @@ $reaction-row-button-hover-border-color: $focus-bg-color; $reaction-row-button-selected-bg-color: #e9fff9; $reaction-row-button-selected-border-color: $accent-color; +$kbd-border-color: $reaction-row-button-border-color; + $tooltip-timeline-bg-color: $tagpanel-bg-color; $tooltip-timeline-fg-color: #ffffff; @@ -305,7 +310,7 @@ $user-tile-hover-bg-color: $header-panel-bg-color; border: 0px; border-radius: 4px; font-family: $font-family; - font-size: 14px; + font-size: $font-14px; color: $button-fg-color; background-color: $button-bg-color; width: auto; @@ -326,7 +331,7 @@ $user-tile-hover-bg-color: $header-panel-bg-color; @define-mixin mx_DialogButton_small { @mixin mx_DialogButton; - font-size: 15px; + font-size: $font-15px; padding: 0px 1.5em 0px 1.5em; } diff --git a/res/themes/light/css/light.scss b/res/themes/light/css/light.scss index 6acb2d9d94..4f48557648 100644 --- a/res/themes/light/css/light.scss +++ b/res/themes/light/css/light.scss @@ -1,3 +1,4 @@ +@import "../../../../res/css/_font-sizes.scss"; @import "_paths.scss"; @import "_fonts.scss"; @import "_light.scss"; diff --git a/scripts/ci/end-to-end-tests.sh b/scripts/ci/end-to-end-tests.sh index 9bdb512940..1233677db4 100755 --- a/scripts/ci/end-to-end-tests.sh +++ b/scripts/ci/end-to-end-tests.sh @@ -6,22 +6,13 @@ set -ev -upload_logs() { - echo "--- Uploading logs" - buildkite-agent artifact upload "logs/**/*;synapse/installations/consent/homeserver.log" -} - handle_error() { EXIT_CODE=$? - if [ $TESTS_STARTED -eq 1 ]; then - upload_logs - fi exit $EXIT_CODE } trap 'handle_error' ERR - echo "--- Building Riot" scripts/ci/layered-riot-web.sh cd ../riot-web diff --git a/scripts/gen-i18n.js b/scripts/gen-i18n.js index 3d3d5af116..a1823cdf50 100755 --- a/scripts/gen-i18n.js +++ b/scripts/gen-i18n.js @@ -237,7 +237,7 @@ const walkOpts = { const fullPath = path.join(root, fileStats.name); let trs; - if (fileStats.name.endsWith('.js')) { + if (fileStats.name.endsWith('.js') || fileStats.name.endsWith('.ts') || fileStats.name.endsWith('.tsx')) { trs = getTranslationsJs(fullPath); } else if (fileStats.name.endsWith('.html')) { trs = getTranslationsOther(fullPath); diff --git a/scripts/generate-eslint-error-ignore-file b/scripts/generate-eslint-error-ignore-file index 3a635f5a7d..54aacfc9fa 100755 --- a/scripts/generate-eslint-error-ignore-file +++ b/scripts/generate-eslint-error-ignore-file @@ -14,8 +14,10 @@ echo "generating $out" # autogenerated file: run scripts/generate-eslint-error-ignore-file to update. EOF - - ./node_modules/.bin/eslint --no-ignore -f json src test | + + ./node_modules/.bin/eslint -f json src test | jq -r '.[] | select((.errorCount + .warningCount) > 0) | .filePath' | sed -e 's/.*matrix-react-sdk\///'; } > "$out" +# also append rules from eslintignore file +cat .eslintignore >> $out diff --git a/scripts/reskindex.js b/scripts/reskindex.js index 81ab111f46..9fb0e1a7c0 100755 --- a/scripts/reskindex.js +++ b/scripts/reskindex.js @@ -8,11 +8,14 @@ var chokidar = require('chokidar'); var componentIndex = path.join('src', 'component-index.js'); var componentIndexTmp = componentIndex+".tmp"; var componentsDir = path.join('src', 'components'); -var componentGlob = '**/*.js'; +var componentJsGlob = '**/*.js'; +var componentTsGlob = '**/*.tsx'; var prevFiles = []; function reskindex() { - var files = glob.sync(componentGlob, {cwd: componentsDir}).sort(); + var jsFiles = glob.sync(componentJsGlob, {cwd: componentsDir}).sort(); + var tsFiles = glob.sync(componentTsGlob, {cwd: componentsDir}).sort(); + var files = [...tsFiles, ...jsFiles]; if (!filesHaveChanged(files, prevFiles)) { return; } @@ -36,7 +39,7 @@ function reskindex() { strm.write("let components = {};\n"); for (var i = 0; i < files.length; ++i) { - var file = files[i].replace('.js', ''); + var file = files[i].replace('.js', '').replace('.tsx', ''); var moduleName = (file.replace(/\//g, '.')); var importName = moduleName.replace(/\./g, "$"); @@ -79,7 +82,7 @@ if (!args.w) { } var watchDebouncer = null; -chokidar.watch(path.join(componentsDir, componentGlob)).on('all', (event, path) => { +chokidar.watch(path.join(componentsDir, componentJsGlob)).on('all', (event, path) => { if (path === componentIndex) return; if (watchDebouncer) clearTimeout(watchDebouncer); watchDebouncer = setTimeout(reskindex, 1000); diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts new file mode 100644 index 0000000000..e6e339d067 --- /dev/null +++ b/src/@types/global.d.ts @@ -0,0 +1,53 @@ +/* +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. +*/ + +import * as ModernizrStatic from "modernizr"; + +declare global { + interface Window { + Modernizr: ModernizrStatic; + Olm: { + init: () => Promise; + }; + } + + // workaround for https://github.com/microsoft/TypeScript/issues/30933 + interface ObjectConstructor { + fromEntries?(xs: [string|number|symbol, any][]): object + } + + interface Document { + // https://developer.mozilla.org/en-US/docs/Web/API/Document/hasStorageAccess + hasStorageAccess?: () => Promise; + } + + interface StorageEstimate { + usageDetails?: {[key: string]: number}; + } + + export interface ISettledFulfilled { + status: "fulfilled"; + value: T; + } + export interface ISettledRejected { + status: "rejected"; + reason: any; + } + + interface PromiseConstructor { + allSettled(promises: Promise[]): Promise | ISettledRejected>>; + } +} diff --git a/src/AddThreepid.js b/src/AddThreepid.js index 7a3250d0ca..f06f7c187d 100644 --- a/src/AddThreepid.js +++ b/src/AddThreepid.js @@ -21,6 +21,7 @@ import * as sdk from './index'; import Modal from './Modal'; import { _t } from './languageHandler'; import IdentityAuthClient from './IdentityAuthClient'; +import {SSOAuthEntry} from "./components/views/auth/InteractiveAuthEntryComponents"; function getIdServerDomain() { return MatrixClientPeg.get().idBaseUrl.split("://")[1]; @@ -188,11 +189,31 @@ export default class AddThreepid { // pop up an interactive auth dialog const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog"); + + const dialogAesthetics = { + [SSOAuthEntry.PHASE_PREAUTH]: { + title: _t("Use Single Sign On to continue"), + body: _t("Confirm adding this email address by using " + + "Single Sign On to prove your identity."), + continueText: _t("Single Sign On"), + continueKind: "primary", + }, + [SSOAuthEntry.PHASE_POSTAUTH]: { + title: _t("Confirm adding email"), + body: _t("Click the button below to confirm adding this email address."), + continueText: _t("Confirm"), + continueKind: "primary", + }, + }; const { finished } = Modal.createTrackedDialog('Add Email', '', InteractiveAuthDialog, { title: _t("Add Email Address"), matrixClient: MatrixClientPeg.get(), authData: e.data, makeRequest: this._makeAddThreepidOnlyRequest, + aestheticsForStagePhases: { + [SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics, + [SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics, + }, }); return finished; } @@ -285,11 +306,30 @@ export default class AddThreepid { // pop up an interactive auth dialog const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog"); + const dialogAesthetics = { + [SSOAuthEntry.PHASE_PREAUTH]: { + title: _t("Use Single Sign On to continue"), + body: _t("Confirm adding this phone number by using " + + "Single Sign On to prove your identity."), + continueText: _t("Single Sign On"), + continueKind: "primary", + }, + [SSOAuthEntry.PHASE_POSTAUTH]: { + title: _t("Confirm adding phone number"), + body: _t("Click the button below to confirm adding this phone number."), + continueText: _t("Confirm"), + continueKind: "primary", + }, + }; const { finished } = Modal.createTrackedDialog('Add MSISDN', '', InteractiveAuthDialog, { title: _t("Add Phone Number"), matrixClient: MatrixClientPeg.get(), authData: e.data, makeRequest: this._makeAddThreepidOnlyRequest, + aestheticsForStagePhases: { + [SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics, + [SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics, + }, }); return finished; } diff --git a/src/Analytics.js b/src/Analytics.js index 8eea47ea89..e55612c4f1 100644 --- a/src/Analytics.js +++ b/src/Analytics.js @@ -123,8 +123,8 @@ const LAST_VISIT_TS_KEY = "mx_Riot_Analytics_lvts"; function getUid() { try { - let data = localStorage.getItem(UID_KEY); - if (!data) { + let data = localStorage && localStorage.getItem(UID_KEY); + if (!data && localStorage) { localStorage.setItem(UID_KEY, data = [...Array(16)].map(() => Math.random().toString(16)[2]).join('')); } return data; @@ -145,14 +145,16 @@ class Analytics { this.firstPage = true; this._heartbeatIntervalID = null; - this.creationTs = localStorage.getItem(CREATION_TS_KEY); - if (!this.creationTs) { + this.creationTs = localStorage && localStorage.getItem(CREATION_TS_KEY); + if (!this.creationTs && localStorage) { localStorage.setItem(CREATION_TS_KEY, this.creationTs = new Date().getTime()); } - this.lastVisitTs = localStorage.getItem(LAST_VISIT_TS_KEY); - this.visitCount = localStorage.getItem(VISIT_COUNT_KEY) || 0; - localStorage.setItem(VISIT_COUNT_KEY, parseInt(this.visitCount, 10) + 1); + this.lastVisitTs = localStorage && localStorage.getItem(LAST_VISIT_TS_KEY); + this.visitCount = localStorage && localStorage.getItem(VISIT_COUNT_KEY) || 0; + if (localStorage) { + localStorage.setItem(VISIT_COUNT_KEY, parseInt(this.visitCount, 10) + 1); + } } get disabled() { @@ -260,7 +262,6 @@ class Analytics { }); } catch (e) { console.error("Analytics error: ", e); - window.err = e; } } diff --git a/src/AsyncWrapper.js b/src/AsyncWrapper.js index b7b81688e1..05054cf63a 100644 --- a/src/AsyncWrapper.js +++ b/src/AsyncWrapper.js @@ -38,7 +38,7 @@ export default createReactClass({ }; }, - componentWillMount: function() { + componentDidMount: function() { this._unmounted = false; // XXX: temporary logging to try to diagnose // https://github.com/vector-im/riot-web/issues/3148 diff --git a/src/Avatar.js b/src/Avatar.js index 5a330c31e9..8393ce02b2 100644 --- a/src/Avatar.js +++ b/src/Avatar.js @@ -53,13 +53,56 @@ export function avatarUrlForUser(user, width, height, resizeMethod) { return url; } +function isValidHexColor(color) { + return typeof color === "string" && + (color.length === 7 || color.lengh === 9) && + color.charAt(0) === "#" && + !color.substr(1).split("").some(c => isNaN(parseInt(c, 16))); +} + +function urlForColor(color) { + const size = 40; + const canvas = document.createElement("canvas"); + canvas.width = size; + canvas.height = size; + const ctx = canvas.getContext("2d"); + // bail out when using jsdom in unit tests + if (!ctx) { + return ""; + } + ctx.fillStyle = color; + ctx.fillRect(0, 0, size, size); + return canvas.toDataURL(); +} + +// XXX: Ideally we'd clear this cache when the theme changes +// but since this function is at global scope, it's a bit +// hard to install a listener here, even if there were a clear event to listen to +const colorToDataURLCache = new Map(); + export function defaultAvatarUrlForString(s) { - const images = ['03b381', '368bd6', 'ac3ba8']; + const defaultColors = ['#03b381', '#368bd6', '#ac3ba8']; let total = 0; for (let i = 0; i < s.length; ++i) { total += s.charCodeAt(i); } - return require('../res/img/' + images[total % images.length] + '.png'); + const colorIndex = total % defaultColors.length; + // overwritten color value in custom themes + const cssVariable = `--avatar-background-colors_${colorIndex}`; + const cssValue = document.body.style.getPropertyValue(cssVariable); + const color = cssValue || defaultColors[colorIndex]; + let dataUrl = colorToDataURLCache.get(color); + if (!dataUrl) { + // validate color as this can come from account_data + // with custom theming + if (isValidHexColor(color)) { + dataUrl = urlForColor(color); + colorToDataURLCache.set(color, dataUrl); + } else { + dataUrl = ""; + } + } + return dataUrl; } /** @@ -102,6 +145,8 @@ export function getInitialLetter(name) { } export function avatarUrlForRoom(room, width, height, resizeMethod) { + if (!room) return null; // null-guard + const explicitRoomAvatar = room.getAvatarUrl( MatrixClientPeg.get().getHomeserverUrl(), width, diff --git a/src/BasePlatform.js b/src/BasePlatform.js index 14e34a1f40..8a950dc2e3 100644 --- a/src/BasePlatform.js +++ b/src/BasePlatform.js @@ -4,6 +4,7 @@ Copyright 2016 Aviral Dasgupta Copyright 2016 OpenMarket Ltd Copyright 2018 New Vector Ltd +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. @@ -18,6 +19,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import {MatrixClient} from "matrix-js-sdk"; import dis from './dispatcher'; import BaseEventIndexManager from './indexing/BaseEventIndexManager'; @@ -162,4 +164,30 @@ export default class BasePlatform { getEventIndexingManager(): BaseEventIndexManager | null { return null; } + + setLanguage(preferredLangs: string[]) {} + + getSSOCallbackUrl(hsUrl: string, isUrl: string, fragmentAfterLogin: string): URL { + const url = new URL(window.location.href); + url.hash = fragmentAfterLogin || ""; + url.searchParams.set("homeserver", hsUrl); + url.searchParams.set("identityServer", isUrl); + return url; + } + + /** + * Begin Single Sign On flows. + * @param {MatrixClient} mxClient the matrix client using which we should start the flow + * @param {"sso"|"cas"} loginType the type of SSO it is, CAS/SSO. + * @param {string} fragmentAfterLogin the hash to pass to the app during sso callback. + */ + startSingleSignOn(mxClient: MatrixClient, loginType: "sso" | "cas", fragmentAfterLogin: string) { + const callbackUrl = this.getSSOCallbackUrl(mxClient.getHomeserverUrl(), mxClient.getIdentityServerUrl(), + fragmentAfterLogin); + window.location.href = mxClient.getSsoLoginUrl(callbackUrl.toString(), loginType); // redirect to SSO + } + + onKeyDown(ev: KeyboardEvent): boolean { + return false; // no shortcuts implemented + } } diff --git a/src/CallHandler.js b/src/CallHandler.js index 1551b57313..2bfe10850a 100644 --- a/src/CallHandler.js +++ b/src/CallHandler.js @@ -60,12 +60,13 @@ import * as sdk from './index'; import { _t } from './languageHandler'; import Matrix from 'matrix-js-sdk'; import dis from './dispatcher'; -import SdkConfig from './SdkConfig'; import { showUnknownDeviceDialogForCalls } from './cryptodevices'; import WidgetUtils from './utils/WidgetUtils'; import WidgetEchoStore from './stores/WidgetEchoStore'; -import {IntegrationManagers} from "./integrations/IntegrationManagers"; import SettingsStore, { SettingLevel } from './settings/SettingsStore'; +import {generateHumanReadableId} from "./utils/NamingUtils"; +import {Jitsi} from "./widgets/Jitsi"; +import {WidgetType} from "./widgets/WidgetType"; global.mxCalls = { //room_id: MatrixCall @@ -143,7 +144,7 @@ function _setCallListeners(call) { "if you proceed without verifying them, it will be "+ "possible for someone to eavesdrop on your call.", ), - button: _t('Review Devices'), + button: _t('Review Sessions'), onFinished: function(confirmed) { if (confirmed) { const room = MatrixClientPeg.get().getRoom(call.roomId); @@ -395,41 +396,15 @@ function _onAction(payload) { } async function _startCallApp(roomId, type) { - // check for a working integration manager. Technically we could put - // the state event in anyway, but the resulting widget would then not - // work for us. Better that the user knows before everyone else in the - // room sees it. - const managers = IntegrationManagers.sharedInstance(); - let haveScalar = false; - if (managers.hasManager()) { - try { - const scalarClient = managers.getPrimaryManager().getScalarClient(); - await scalarClient.connect(); - haveScalar = scalarClient.hasCredentials(); - } catch (e) { - // ignore - } - } - - if (!haveScalar) { - const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); - - Modal.createTrackedDialog('Could not connect to the integration server', '', ErrorDialog, { - title: _t('Could not connect to the integration server'), - description: _t('A conference call could not be started because the integrations server is not available'), - }); - return; - } - dis.dispatch({ action: 'appsDrawer', show: true, }); const room = MatrixClientPeg.get().getRoom(roomId); - const currentRoomWidgets = WidgetUtils.getRoomWidgets(room); + const currentJitsiWidgets = WidgetUtils.getRoomWidgetsOfType(room, WidgetType.JITSI); - if (WidgetEchoStore.roomHasPendingWidgetsOfType(roomId, currentRoomWidgets, 'jitsi')) { + if (WidgetEchoStore.roomHasPendingWidgetsOfType(roomId, currentJitsiWidgets, WidgetType.JITSI)) { const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog('Call already in progress', '', ErrorDialog, { @@ -439,9 +414,6 @@ async function _startCallApp(roomId, type) { return; } - const currentJitsiWidgets = currentRoomWidgets.filter((ev) => { - return ev.getContent().type === 'jitsi'; - }); if (currentJitsiWidgets.length > 0) { console.warn( "Refusing to start conference call widget in " + roomId + @@ -456,31 +428,22 @@ async function _startCallApp(roomId, type) { return; } - // This inherits its poor naming from the field of the same name that goes into - // the event. It's just a random string to make the Jitsi URLs unique. - const widgetSessionId = Math.random().toString(36).substring(2); - const confId = room.roomId.replace(/[^A-Za-z0-9]/g, '') + widgetSessionId; - // NB. we can't just encodeURICompoent all of these because the $ signs need to be there - // (but currently the only thing that needs encoding is the confId) - const queryString = [ - 'confId='+encodeURIComponent(confId), - 'isAudioConf='+(type === 'voice' ? 'true' : 'false'), - 'displayName=$matrix_display_name', - 'avatarUrl=$matrix_avatar_url', - 'email=$matrix_user_id', - ].join('&'); + const confId = `JitsiConference${generateHumanReadableId()}`; + const jitsiDomain = Jitsi.getInstance().preferredDomain; - let widgetUrl; - if (SdkConfig.get().integrations_jitsi_widget_url) { - // Try this config key. This probably isn't ideal as a way of discovering this - // URL, but this will at least allow the integration manager to not be hardcoded. - widgetUrl = SdkConfig.get().integrations_jitsi_widget_url + '?' + queryString; - } else { - const apiUrl = IntegrationManagers.sharedInstance().getPrimaryManager().apiUrl; - widgetUrl = apiUrl + '/widgets/jitsi.html?' + queryString; - } + let widgetUrl = WidgetUtils.getLocalJitsiWrapperUrl(); - const widgetData = { widgetSessionId }; + // TODO: Remove URL hacks when the mobile clients eventually support v2 widgets + const parsedUrl = new URL(widgetUrl); + parsedUrl.search = ''; // set to empty string to make the URL class use searchParams instead + parsedUrl.searchParams.set('confId', confId); + widgetUrl = parsedUrl.toString(); + + const widgetData = { + conferenceId: confId, + isAudioOnly: type === 'voice', + domain: jitsiDomain, + }; const widgetId = ( 'jitsi_' + @@ -489,7 +452,7 @@ async function _startCallApp(roomId, type) { Date.now() ); - WidgetUtils.setRoomWidget(roomId, widgetId, 'jitsi', widgetUrl, 'Jitsi', widgetData).then(() => { + WidgetUtils.setRoomWidget(roomId, widgetId, WidgetType.JITSI, widgetUrl, 'Jitsi', widgetData).then(() => { console.log('Jitsi widget added'); }).catch((e) => { if (e.errcode === 'M_FORBIDDEN') { diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js index f19be03574..c37d0f8bf5 100644 --- a/src/CrossSigningManager.js +++ b/src/CrossSigningManager.js @@ -21,6 +21,7 @@ import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase'; import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey'; import { _t } from './languageHandler'; import SettingsStore from './settings/SettingsStore'; +import {encodeBase64} from "matrix-js-sdk/src/crypto/olmlib"; // This stores the secret storage private keys in memory for the JS SDK. This is // only meant to act as a cache to avoid prompting the user multiple times @@ -50,7 +51,7 @@ async function confirmToDismiss(name) { } else if (name === "m.cross_signing.self_signing") { description = _t("If you cancel now, you won't complete verifying your other session."); } else { - description = _t("If you cancel now, you won't complete your secret storage operation."); + description = _t("If you cancel now, you won't complete your operation."); } const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); @@ -96,7 +97,7 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) { keyInfo: info, checkPrivateKey: async (input) => { const key = await inputToKey(input); - return MatrixClientPeg.get().checkSecretStoragePrivateKey(key, info.pubkey); + return await MatrixClientPeg.get().checkSecretStorageKey(key, info); }, }, /* className= */ null, @@ -125,10 +126,74 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) { return [name, key]; } +const onSecretRequested = async function({ + user_id: userId, + device_id: deviceId, + request_id: requestId, + name, + device_trust: deviceTrust, +}) { + console.log("onSecretRequested", userId, deviceId, requestId, name, deviceTrust); + const client = MatrixClientPeg.get(); + if (userId !== client.getUserId()) { + return; + } + if (!deviceTrust || !deviceTrust.isVerified()) { + console.log(`CrossSigningManager: Ignoring request from untrusted device ${deviceId}`); + return; + } + if (name.startsWith("m.cross_signing")) { + const callbacks = client.getCrossSigningCacheCallbacks(); + if (!callbacks.getCrossSigningKeyCache) return; + /* Explicit enumeration here is deliberate – never share the master key! */ + if (name === "m.cross_signing.self_signing") { + const key = await callbacks.getCrossSigningKeyCache("self_signing"); + if (!key) { + console.log( + `self_signing requested by ${deviceId}, but not found in cache`, + ); + } + return key && encodeBase64(key); + } else if (name === "m.cross_signing.user_signing") { + const key = await callbacks.getCrossSigningKeyCache("user_signing"); + if (!key) { + console.log( + `user_signing requested by ${deviceId}, but not found in cache`, + ); + } + return key && encodeBase64(key); + } + } else if (name === "m.megolm_backup.v1") { + const key = await client._crypto.getSessionBackupPrivateKey(); + if (!key) { + console.log( + `session backup key requested by ${deviceId}, but not found in cache`, + ); + } + return key && encodeBase64(key); + } + console.warn("onSecretRequested didn't recognise the secret named ", name); +}; + export const crossSigningCallbacks = { getSecretStorageKey, + onSecretRequested, }; +export async function promptForBackupPassphrase() { + let key; + + const RestoreKeyBackupDialog = sdk.getComponent('dialogs.keybackup.RestoreKeyBackupDialog'); + const { finished } = Modal.createTrackedDialog('Restore Backup', '', RestoreKeyBackupDialog, { + showSummary: false, keyCallback: k => key = k, + }, null, /* priority = */ false, /* static = */ true); + + const success = await finished; + if (!success) throw new Error("Key backup prompt cancelled"); + + return key; +} + /** * This helper should be used whenever you need to access secret storage. It * ensures that secret storage (and also cross-signing since they each depend on @@ -148,19 +213,19 @@ export const crossSigningCallbacks = { * * @param {Function} [func] An operation to perform once secret storage has been * bootstrapped. Optional. - * @param {bool} [force] Reset secret storage even if it's already set up + * @param {bool} [forceReset] Reset secret storage even if it's already set up */ -export async function accessSecretStorage(func = async () => { }, force = false) { +export async function accessSecretStorage(func = async () => { }, forceReset = false) { const cli = MatrixClientPeg.get(); secretStorageBeingAccessed = true; try { - if (!await cli.hasSecretStorageKey() || force) { + if (!await cli.hasSecretStorageKey() || forceReset) { // This dialog calls bootstrap itself after guiding the user through // passphrase creation. const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '', import("./async-components/views/dialogs/secretstorage/CreateSecretStorageDialog"), { - force, + force: forceReset, }, null, /* priority = */ false, /* static = */ true, ); @@ -185,6 +250,7 @@ export async function accessSecretStorage(func = async () => { }, force = false) throw new Error("Cross-signing key upload auth canceled"); } }, + getBackupPassphrase: promptForBackupPassphrase, }); } diff --git a/src/DeviceListener.js b/src/DeviceListener.js index 4e7bc8470d..27caba971e 100644 --- a/src/DeviceListener.js +++ b/src/DeviceListener.js @@ -20,12 +20,13 @@ import * as sdk from './index'; import { _t } from './languageHandler'; import ToastStore from './stores/ToastStore'; -function toastKey(deviceId) { - return 'unverified_session_' + deviceId; -} - const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000; const THIS_DEVICE_TOAST_KEY = 'setupencryption'; +const OTHER_DEVICES_TOAST_KEY = 'reviewsessions'; + +function toastKey(deviceId) { + return "unverified_session_" + deviceId; +} export default class DeviceListener { static sharedInstance() { @@ -34,8 +35,6 @@ export default class DeviceListener { } constructor() { - // set of device IDs we're currently showing toasts for - this._activeNagToasts = new Set(); // device IDs for which the user has dismissed the verify toast ('Later') this._dismissed = new Set(); // has the user dismissed any of the various nag toasts to setup encryption on this device? @@ -44,26 +43,55 @@ export default class DeviceListener { // cache of the key backup info this._keyBackupInfo = null; this._keyBackupFetchedAt = null; + + // We keep a list of our own device IDs so we can batch ones that were already + // there the last time the app launched into a single toast, but display new + // ones in their own toasts. + this._ourDeviceIdsAtStart = null; + + // The set of device IDs we're currently displaying toasts for + this._displayingToastsForDeviceIds = new Set(); } start() { + MatrixClientPeg.get().on('crypto.willUpdateDevices', this._onWillUpdateDevices); MatrixClientPeg.get().on('crypto.devicesUpdated', this._onDevicesUpdated); MatrixClientPeg.get().on('deviceVerificationChanged', this._onDeviceVerificationChanged); MatrixClientPeg.get().on('userTrustStatusChanged', this._onUserTrustStatusChanged); + MatrixClientPeg.get().on('crossSigning.keysChanged', this._onCrossSingingKeysChanged); + MatrixClientPeg.get().on('accountData', this._onAccountData); + MatrixClientPeg.get().on('sync', this._onSync); this._recheck(); } stop() { if (MatrixClientPeg.get()) { + MatrixClientPeg.get().removeListener('crypto.willUpdateDevices', this._onWillUpdateDevices); MatrixClientPeg.get().removeListener('crypto.devicesUpdated', this._onDevicesUpdated); MatrixClientPeg.get().removeListener('deviceVerificationChanged', this._onDeviceVerificationChanged); MatrixClientPeg.get().removeListener('userTrustStatusChanged', this._onUserTrustStatusChanged); + MatrixClientPeg.get().removeListener('crossSigning.keysChanged', this._onCrossSingingKeysChanged); + MatrixClientPeg.get().removeListener('accountData', this._onAccountData); + MatrixClientPeg.get().removeListener('sync', this._onSync); } this._dismissed.clear(); + this._dismissedThisDeviceToast = false; + this._keyBackupInfo = null; + this._keyBackupFetchedAt = null; + this._ourDeviceIdsAtStart = null; + this._displayingToastsForDeviceIds = new Set(); } - dismissVerification(deviceId) { - this._dismissed.add(deviceId); + /** + * Dismiss notifications about our own unverified devices + * + * @param {String[]} deviceIds List of device IDs to dismiss notifications for + */ + async dismissUnverifiedSessions(deviceIds) { + for (const d of deviceIds) { + this._dismissed.add(d); + } + this._recheck(); } @@ -72,6 +100,28 @@ export default class DeviceListener { this._recheck(); } + _ensureDeviceIdsAtStartPopulated() { + if (this._ourDeviceIdsAtStart === null) { + const cli = MatrixClientPeg.get(); + this._ourDeviceIdsAtStart = new Set( + cli.getStoredDevicesForUser(cli.getUserId()).map(d => d.deviceId), + ); + } + } + + _onWillUpdateDevices = async (users, initialFetch) => { + // If we didn't know about *any* devices before (ie. it's fresh login), + // then they are all pre-existing devices, so ignore this and set the + // devicesAtStart list to the devices that we see after the fetch. + if (initialFetch) return; + + const myUserId = MatrixClientPeg.get().getUserId(); + if (users.includes(myUserId)) this._ensureDeviceIdsAtStartPopulated(); + + // No need to do a recheck here: we just need to get a snapshot of our devices + // before we download any new ones. + } + _onDevicesUpdated = (users) => { if (!users.includes(MatrixClientPeg.get().getUserId())) return; this._recheck(); @@ -87,6 +137,28 @@ export default class DeviceListener { this._recheck(); } + _onCrossSingingKeysChanged = () => { + this._recheck(); + } + + _onAccountData = (ev) => { + // User may have: + // * migrated SSSS to symmetric + // * uploaded keys to secret storage + // * completed secret storage creation + // which result in account data changes affecting checks below. + if ( + ev.getType().startsWith('m.secret_storage.') || + ev.getType().startsWith('m.cross_signing.') + ) { + this._recheck(); + } + } + + _onSync = (state, prevState) => { + if (state === 'PREPARED' && prevState === null) this._recheck(); + } + // The server doesn't tell us when key backup is set up, so we poll // & cache the result async _getKeyBackupInfo() { @@ -99,80 +171,130 @@ export default class DeviceListener { } async _recheck() { - if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) return; const cli = MatrixClientPeg.get(); - if (!cli.isCryptoEnabled()) return; - if (!cli.getCrossSigningId()) { - if (this._dismissedThisDeviceToast) { - ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY); - return; - } + if ( + !SettingsStore.getValue("feature_cross_signing") || + !await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing") + ) return; - // cross signing isn't enabled - nag to enable it - // There are 3 different toasts for: - if (cli.getStoredCrossSigningForUser(cli.getUserId())) { - // Cross-signing on account but this device doesn't trust the master key (verify this session) - ToastStore.sharedInstance().addOrReplaceToast({ - key: THIS_DEVICE_TOAST_KEY, - title: _t("Verify this session"), - icon: "verification_warning", - props: {kind: 'verify_this_session'}, - component: sdk.getComponent("toasts.SetupEncryptionToast"), - }); - } else { - const backupInfo = await this._getKeyBackupInfo(); - if (backupInfo) { - // No cross-signing on account but key backup available (upgrade encryption) + if (!cli.isCryptoEnabled()) return; + // don't recheck until the initial sync is complete: lots of account data events will fire + // while the initial sync is processing and we don't need to recheck on each one of them + // (we add a listener on sync to do once check after the initial sync is done) + if (!cli.isInitialSyncComplete()) return; + + const crossSigningReady = await cli.isCrossSigningReady(); + + if (this._dismissedThisDeviceToast) { + ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY); + } else { + if (!crossSigningReady) { + // make sure our keys are finished downlaoding + await cli.downloadKeys([cli.getUserId()]); + // cross signing isn't enabled - nag to enable it + // There are 3 different toasts for: + if (cli.getStoredCrossSigningForUser(cli.getUserId())) { + // Cross-signing on account but this device doesn't trust the master key (verify this session) ToastStore.sharedInstance().addOrReplaceToast({ key: THIS_DEVICE_TOAST_KEY, - title: _t("Encryption upgrade available"), + title: _t("Verify this session"), icon: "verification_warning", - props: {kind: 'upgrade_encryption'}, + props: {kind: 'verify_this_session'}, component: sdk.getComponent("toasts.SetupEncryptionToast"), }); } else { - // No cross-signing or key backup on account (set up encryption) - ToastStore.sharedInstance().addOrReplaceToast({ - key: THIS_DEVICE_TOAST_KEY, - title: _t("Set up encryption"), - icon: "verification_warning", - props: {kind: 'set_up_encryption'}, - component: sdk.getComponent("toasts.SetupEncryptionToast"), - }); + const backupInfo = await this._getKeyBackupInfo(); + if (backupInfo) { + // No cross-signing on account but key backup available (upgrade encryption) + ToastStore.sharedInstance().addOrReplaceToast({ + key: THIS_DEVICE_TOAST_KEY, + title: _t("Encryption upgrade available"), + icon: "verification_warning", + props: {kind: 'upgrade_encryption'}, + component: sdk.getComponent("toasts.SetupEncryptionToast"), + }); + } else { + // No cross-signing or key backup on account (set up encryption) + ToastStore.sharedInstance().addOrReplaceToast({ + key: THIS_DEVICE_TOAST_KEY, + title: _t("Set up encryption"), + icon: "verification_warning", + props: {kind: 'set_up_encryption'}, + component: sdk.getComponent("toasts.SetupEncryptionToast"), + }); + } + } + } else { + // cross-signing is ready, and we don't need to upgrade encryption + ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY); + } + } + + // This needs to be done after awaiting on downloadKeys() above, so + // we make sure we get the devices after the fetch is done. + this._ensureDeviceIdsAtStartPopulated(); + + // Unverified devices that were there last time the app ran + // (technically could just be a boolean: we don't actually + // need to remember the device IDs, but for the sake of + // symmetry...). + const oldUnverifiedDeviceIds = new Set(); + // Unverified devices that have appeared since then + const newUnverifiedDeviceIds = new Set(); + + // as long as cross-signing isn't ready, + // you can't see or dismiss any device toasts + if (crossSigningReady) { + const devices = cli.getStoredDevicesForUser(cli.getUserId()); + for (const device of devices) { + if (device.deviceId == cli.deviceId) continue; + + const deviceTrust = await cli.checkDeviceTrust(cli.getUserId(), device.deviceId); + if (!deviceTrust.isCrossSigningVerified() && !this._dismissed.has(device.deviceId)) { + if (this._ourDeviceIdsAtStart.has(device.deviceId)) { + oldUnverifiedDeviceIds.add(device.deviceId); + } else { + newUnverifiedDeviceIds.add(device.deviceId); + } } } - return; - } else { - ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY); } - const newActiveToasts = new Set(); + // Display or hide the batch toast for old unverified sessions + if (oldUnverifiedDeviceIds.size > 0) { + ToastStore.sharedInstance().addOrReplaceToast({ + key: OTHER_DEVICES_TOAST_KEY, + title: _t("Review where you’re logged in"), + icon: "verification_warning", + priority: ToastStore.PRIORITY_LOW, + props: { + deviceIds: oldUnverifiedDeviceIds, + }, + component: sdk.getComponent("toasts.BulkUnverifiedSessionsToast"), + }); + } else { + ToastStore.sharedInstance().dismissToast(OTHER_DEVICES_TOAST_KEY); + } - const devices = await cli.getStoredDevicesForUser(cli.getUserId()); - for (const device of devices) { - if (device.deviceId == cli.deviceId) continue; + // Show toasts for new unverified devices if they aren't already there + for (const deviceId of newUnverifiedDeviceIds) { + ToastStore.sharedInstance().addOrReplaceToast({ + key: toastKey(deviceId), + title: _t("New login. Was this you?"), + icon: "verification_warning", + props: { deviceId }, + component: sdk.getComponent("toasts.UnverifiedSessionToast"), + }); + } - const deviceTrust = await cli.checkDeviceTrust(cli.getUserId(), device.deviceId); - if (deviceTrust.isCrossSigningVerified() || this._dismissed.has(device.deviceId)) { - ToastStore.sharedInstance().dismissToast(toastKey(device.deviceId)); - } else { - this._activeNagToasts.add(device.deviceId); - ToastStore.sharedInstance().addOrReplaceToast({ - key: toastKey(device.deviceId), - title: _t("Unverified session"), - icon: "verification_warning", - props: { device }, - component: sdk.getComponent("toasts.UnverifiedSessionToast"), - }); - newActiveToasts.add(device.deviceId); + // ...and hide any we don't need any more + for (const deviceId of this._displayingToastsForDeviceIds) { + if (!newUnverifiedDeviceIds.has(deviceId)) { + ToastStore.sharedInstance().dismissToast(toastKey(deviceId)); } } - // clear any other outstanding toasts (eg. logged out devices) - for (const deviceId of this._activeNagToasts) { - if (!newActiveToasts.has(deviceId)) ToastStore.sharedInstance().dismissToast(toastKey(deviceId)); - } - this._activeNagToasts = newActiveToasts; + this._displayingToastsForDeviceIds = newUnverifiedDeviceIds; } } diff --git a/src/FromWidgetPostMessageApi.js b/src/FromWidgetPostMessageApi.js index 64caba0fdf..c9793d40f7 100644 --- a/src/FromWidgetPostMessageApi.js +++ b/src/FromWidgetPostMessageApi.js @@ -24,6 +24,7 @@ import {MatrixClientPeg} from "./MatrixClientPeg"; import RoomViewStore from "./stores/RoomViewStore"; import {IntegrationManagers} from "./integrations/IntegrationManagers"; import SettingsStore from "./settings/SettingsStore"; +import {Capability} from "./widgets/WidgetApi"; const WIDGET_API_VERSION = '0.0.2'; // Current API version const SUPPORTED_WIDGET_API_VERSIONS = [ @@ -99,7 +100,7 @@ export default class FromWidgetPostMessageApi { console.warn('Add FromWidgetPostMessageApi - Endpoint already registered'); return; } else { - console.warn(`Adding fromWidget messaging endpoint for ${widgetId}`, endpoint); + console.log(`Adding fromWidget messaging endpoint for ${widgetId}`, endpoint); this.widgetMessagingEndpoints.push(endpoint); } } @@ -164,7 +165,7 @@ export default class FromWidgetPostMessageApi { const action = event.data.action; const widgetId = event.data.widgetId; if (action === 'content_loaded') { - console.warn('Widget reported content loaded for', widgetId); + console.log('Widget reported content loaded for', widgetId); dis.dispatch({ action: 'widget_content_loaded', widgetId: widgetId, @@ -213,7 +214,7 @@ export default class FromWidgetPostMessageApi { const data = event.data.data; const val = data.value; - if (ActiveWidgetStore.widgetHasCapability(widgetId, 'm.always_on_screen')) { + if (ActiveWidgetStore.widgetHasCapability(widgetId, Capability.AlwaysOnScreen)) { ActiveWidgetStore.setWidgetPersistence(widgetId, val); } } else if (action === 'get_openid') { diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index 236aa0157e..34e9e55d25 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -23,7 +23,6 @@ import ReplyThread from "./components/views/elements/ReplyThread"; import React from 'react'; import sanitizeHtml from 'sanitize-html'; -import highlight from 'highlight.js'; import * as linkify from 'linkifyjs'; import linkifyMatrix from './linkify-matrix'; import _linkifyElement from 'linkifyjs/element'; @@ -160,7 +159,7 @@ const transformTags = { // custom to matrix delete attribs.target; } } - attribs.rel = 'noopener'; // https://mathiasbynens.github.io/rel-noopener/ + attribs.rel = 'noreferrer noopener'; // https://mathiasbynens.github.io/rel-noopener/ return { tagName, attribs }; }, 'img': function(tagName, attribs) { @@ -447,7 +446,8 @@ export function bodyToHtml(content, highlights, opts={}) { // their username. Permalinks (links in pills) can be any URL // now, so we just check for an HTTP-looking thing. ( - content.formatted_body == undefined || + strippedBody === safeBody || // replies have the html fallbacks, account for that here + content.formatted_body === undefined || (!content.formatted_body.includes("http:") && !content.formatted_body.includes("https:")) ); @@ -467,11 +467,12 @@ export function bodyToHtml(content, highlights, opts={}) { /** * Linkifies the given string. This is a wrapper around 'linkifyjs/string'. * - * @param {string} str - * @returns {string} + * @param {string} str string to linkify + * @param {object} [options] Options for linkifyString. Default: linkifyMatrix.options + * @returns {string} Linkified string */ -export function linkifyString(str) { - return _linkifyString(str); +export function linkifyString(str, options = linkifyMatrix.options) { + return _linkifyString(str, options); } /** @@ -489,10 +490,11 @@ export function linkifyElement(element, options = linkifyMatrix.options) { * Linkify the given string and sanitize the HTML afterwards. * * @param {string} dirtyHtml The HTML string to sanitize and linkify + * @param {object} [options] Options for linkifyString. Default: linkifyMatrix.options * @returns {string} */ -export function linkifyAndSanitizeHtml(dirtyHtml) { - return sanitizeHtml(linkifyString(dirtyHtml), sanitizeHtmlParams); +export function linkifyAndSanitizeHtml(dirtyHtml, options = linkifyMatrix.options) { + return sanitizeHtml(linkifyString(dirtyHtml, options), sanitizeHtmlParams); } /** diff --git a/src/IdentityAuthClient.js b/src/IdentityAuthClient.js index 72432b9a44..4a830d6506 100644 --- a/src/IdentityAuthClient.js +++ b/src/IdentityAuthClient.js @@ -181,24 +181,12 @@ export default class IdentityAuthClient { } async registerForToken(check=true) { - try { - const hsOpenIdToken = await MatrixClientPeg.get().getOpenIdToken(); - // XXX: The spec is `token`, but we used `access_token` for a Sydent release. - const { access_token: accessToken, token } = - await this._matrixClient.registerWithIdentityServer(hsOpenIdToken); - const identityAccessToken = token ? token : accessToken; - if (check) await this._checkToken(identityAccessToken); - return identityAccessToken; - } catch (e) { - if (e.cors === "rejected" || e.httpStatus === 404) { - // Assume IS only supports deprecated v1 API for now - // TODO: Remove this path once v2 is only supported version - // See https://github.com/vector-im/riot-web/issues/10443 - console.warn("IS doesn't support v2 auth"); - this.authEnabled = false; - return; - } - throw e; - } + const hsOpenIdToken = await MatrixClientPeg.get().getOpenIdToken(); + // XXX: The spec is `token`, but we used `access_token` for a Sydent release. + const { access_token: accessToken, token } = + await this._matrixClient.registerWithIdentityServer(hsOpenIdToken); + const identityAccessToken = token ? token : accessToken; + if (check) await this._checkToken(identityAccessToken); + return identityAccessToken; } } diff --git a/src/KeyRequestHandler.js b/src/KeyRequestHandler.js index 30f3b7d50e..ceaff0c54d 100644 --- a/src/KeyRequestHandler.js +++ b/src/KeyRequestHandler.js @@ -35,7 +35,7 @@ export default class KeyRequestHandler { handleKeyRequest(keyRequest) { // Ignore own device key requests if cross-signing lab enabled - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { return; } @@ -70,7 +70,7 @@ export default class KeyRequestHandler { handleKeyRequestCancellation(cancellation) { // Ignore own device key requests if cross-signing lab enabled - if (SettingsStore.isFeatureEnabled("feature_cross_signing")) { + if (SettingsStore.getValue("feature_cross_signing")) { return; } diff --git a/src/Keyboard.js b/src/Keyboard.ts similarity index 90% rename from src/Keyboard.js rename to src/Keyboard.ts index 478d75acc1..7040898872 100644 --- a/src/Keyboard.js +++ b/src/Keyboard.ts @@ -22,6 +22,7 @@ export const Key = { PAGE_UP: "PageUp", PAGE_DOWN: "PageDown", BACKSPACE: "Backspace", + DELETE: "Delete", ARROW_UP: "ArrowUp", ARROW_DOWN: "ArrowDown", ARROW_LEFT: "ArrowLeft", @@ -36,10 +37,14 @@ export const Key = { CONTEXT_MENU: "ContextMenu", COMMA: ",", + PERIOD: ".", LESS_THAN: "<", GREATER_THAN: ">", BACKTICK: "`", SPACE: " ", + SLASH: "/", + SQUARE_BRACKET_LEFT: "[", + SQUARE_BRACKET_RIGHT: "]", A: "a", B: "b", C: "c", @@ -68,8 +73,9 @@ export const Key = { Z: "z", }; +export const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; + export function isOnlyCtrlOrCmdKeyEvent(ev) { - const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; if (isMac) { return ev.metaKey && !ev.altKey && !ev.ctrlKey && !ev.shiftKey; } else { @@ -78,7 +84,6 @@ export function isOnlyCtrlOrCmdKeyEvent(ev) { } export function isOnlyCtrlOrCmdIgnoreShiftKeyEvent(ev) { - const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; if (isMac) { return ev.metaKey && !ev.altKey && !ev.ctrlKey; } else { diff --git a/src/Lifecycle.js b/src/Lifecycle.js index 72cd84bfd9..1baa6c8e0c 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -40,6 +40,7 @@ import ToastStore from "./stores/ToastStore"; import {IntegrationManagers} from "./integrations/IntegrationManagers"; import {Mjolnir} from "./mjolnir/Mjolnir"; import DeviceListener from "./DeviceListener"; +import {Jitsi} from "./widgets/Jitsi"; /** * Called at startup, to attempt to build a logged-in Matrix session. It tries @@ -313,7 +314,7 @@ async function _restoreFromLocalStorage(opts) { } } -function _handleLoadSessionFailure(e) { +async function _handleLoadSessionFailure(e) { console.error("Unable to load session", e); const SessionRestoreErrorDialog = @@ -323,16 +324,15 @@ function _handleLoadSessionFailure(e) { error: e.message, }); - return modal.finished.then(([success]) => { - if (success) { - // user clicked continue. - _clearStorage(); - return false; - } + const [success] = await modal.finished; + if (success) { + // user clicked continue. + await _clearStorage(); + return false; + } - // try, try again - return loadSession(); - }); + // try, try again + return loadSession(); } /** @@ -579,9 +579,6 @@ async function startMatrixClient(startSyncing=true) { UserActivity.sharedInstance().start(); TypingStore.sharedInstance().reset(); // just in case ToastStore.sharedInstance().reset(); - if (!SettingsStore.getValue("lowBandwidth")) { - Presence.start(); - } DMRoomMap.makeShared().start(); IntegrationManagers.sharedInstance().startWatching(); ActiveWidgetStore.start(); @@ -604,6 +601,14 @@ async function startMatrixClient(startSyncing=true) { // This needs to be started after crypto is set up DeviceListener.sharedInstance().start(); + // Similarly, don't start sending presence updates until we've started + // the client + if (!SettingsStore.getValue("lowBandwidth")) { + Presence.start(); + } + + // Now that we have a MatrixClientPeg, update the Jitsi info + await Jitsi.getInstance().update(); // dispatch that we finished starting up to wire up any other bits // of the matrix client that cannot be set prior to starting up. @@ -638,6 +643,10 @@ async function _clearStorage() { window.localStorage.clear(); } + if (window.sessionStorage) { + window.sessionStorage.clear(); + } + // create a temporary client to clear out the persistent stores. const cli = createMatrixClient({ // we'll never make any requests, so can pass a bogus HS URL diff --git a/src/Login.js b/src/Login.js index d9ce8adaaa..1590e5ac28 100644 --- a/src/Login.js +++ b/src/Login.js @@ -3,6 +3,7 @@ Copyright 2015, 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd Copyright 2018 New Vector Ltd Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> +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. @@ -19,8 +20,6 @@ limitations under the License. import Matrix from "matrix-js-sdk"; -import url from 'url'; - export default class Login { constructor(hsUrl, isUrl, fallbackHsUrl, opts) { this._hsUrl = hsUrl; @@ -29,6 +28,7 @@ export default class Login { this._currentFlowIndex = 0; this._flows = []; this._defaultDeviceDisplayName = opts.defaultDeviceDisplayName; + this._tempClient = null; // memoize } getHomeserverUrl() { @@ -40,10 +40,12 @@ export default class Login { } setHomeserverUrl(hsUrl) { + this._tempClient = null; // clear memoization this._hsUrl = hsUrl; } setIdentityServerUrl(isUrl) { + this._tempClient = null; // clear memoization this._isUrl = isUrl; } @@ -52,8 +54,9 @@ export default class Login { * requests. * @returns {MatrixClient} */ - _createTemporaryClient() { - return Matrix.createClient({ + createTemporaryClient() { + if (this._tempClient) return this._tempClient; // use memoization + return this._tempClient = Matrix.createClient({ baseUrl: this._hsUrl, idBaseUrl: this._isUrl, }); @@ -61,7 +64,7 @@ export default class Login { getFlows() { const self = this; - const client = this._createTemporaryClient(); + const client = this.createTemporaryClient(); return client.loginFlows().then(function(result) { self._flows = result.flows; self._currentFlowIndex = 0; @@ -139,21 +142,6 @@ export default class Login { throw error; }); } - - getSsoLoginUrl(loginType) { - const client = this._createTemporaryClient(); - const parsedUrl = url.parse(window.location.href, true); - - // XXX: at this point, the fragment will always be #/login, which is no - // use to anyone. Ideally, we would get the intended fragment from - // MatrixChat.screenAfterLogin so that you could follow #/room links etc - // through an SSO login. - parsedUrl.hash = ""; - - parsedUrl.query["homeserver"] = client.getHomeserverUrl(); - parsedUrl.query["identityServer"] = client.getIdentityServerUrl(); - return client.getSsoLoginUrl(url.format(parsedUrl), loginType); - } } diff --git a/src/Markdown.js b/src/Markdown.js index 437ceec88b..fb1f8bf0ea 100644 --- a/src/Markdown.js +++ b/src/Markdown.js @@ -136,7 +136,7 @@ export default class Markdown { // thus opening in a new tab. if (externalLinks) { attrs.push(['target', '_blank']); - attrs.push(['rel', 'noopener']); + attrs.push(['rel', 'noreferrer noopener']); } this.tag('a', attrs); } else { diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index 448c6d9e9b..21f05b9759 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -32,7 +32,7 @@ import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientB import * as StorageManager from './utils/StorageManager'; import IdentityAuthClient from './IdentityAuthClient'; import { crossSigningCallbacks } from './CrossSigningManager'; -import {SCAN_QR_CODE_METHOD, SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode"; +import {SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode"; interface MatrixClientCreds { homeserverUrl: string, @@ -148,6 +148,9 @@ class _MatrixClientPeg { // check that we have a version of the js-sdk which includes initCrypto if (!SettingsStore.getValue("lowBandwidth") && this.matrixClient.initCrypto) { await this.matrixClient.initCrypto(); + this.matrixClient.setCryptoTrustCrossSignedDevices( + !SettingsStore.getValue('e2ee.manuallyVerifyAllSessions'), + ); StorageManager.setCryptoInitialised(true); } } catch (e) { @@ -221,7 +224,6 @@ class _MatrixClientPeg { verificationMethods: [ verificationMethods.SAS, SHOW_QR_CODE_METHOD, - SCAN_QR_CODE_METHOD, // XXX: We don't actually support scanning yet! verificationMethods.RECIPROCATE_QR_CODE, ], unstableClientRelationAggregation: true, diff --git a/src/Notifier.js b/src/Notifier.js index 36a6f13bb6..ec92840998 100644 --- a/src/Notifier.js +++ b/src/Notifier.js @@ -37,6 +37,18 @@ import SettingsStore, {SettingLevel} from "./settings/SettingsStore"; const MAX_PENDING_ENCRYPTED = 20; +/* +Override both the content body and the TextForEvent handler for specific msgtypes, in notifications. +This is useful when the content body contains fallback text that would explain that the client can't handle a particular +type of tile. +*/ +const typehandlers = { + "m.key.verification.request": (event) => { + const name = (event.sender || {}).name; + return _t("%(name)s is requesting verification", { name }); + }, +}; + const Notifier = { notifsByRoom: {}, @@ -46,6 +58,9 @@ const Notifier = { pendingEncryptedEventIds: [], notificationMessageForEvent: function(ev) { + if (typehandlers.hasOwnProperty(ev.getContent().msgtype)) { + return typehandlers[ev.getContent().msgtype](ev); + } return TextForEvent.textForEvent(ev); }, @@ -69,7 +84,9 @@ const Notifier = { title = room.name; // notificationMessageForEvent includes sender, // but we already have the sender here - if (ev.getContent().body) msg = ev.getContent().body; + if (ev.getContent().body && !typehandlers.hasOwnProperty(ev.getContent().msgtype)) { + msg = ev.getContent().body; + } } else if (ev.getType() === 'm.room.member') { // context is all in the message here, we don't need // to display sender info @@ -78,7 +95,9 @@ const Notifier = { title = ev.sender.name + " (" + room.name + ")"; // notificationMessageForEvent includes sender, // but we've just out sender in the title - if (ev.getContent().body) msg = ev.getContent().body; + if (ev.getContent().body && !typehandlers.hasOwnProperty(ev.getContent().msgtype)) { + msg = ev.getContent().body; + } } if (!this.isBodyEnabled()) { diff --git a/src/Registration.js b/src/Registration.js index ac8baa3cca..ca162bac03 100644 --- a/src/Registration.js +++ b/src/Registration.js @@ -39,6 +39,8 @@ export const SAFE_LOCALPART_REGEX = /^[a-z0-9=_\-./]+$/; * If true, goes to the home page if the user cancels the action * @param {bool} options.go_welcome_on_cancel * If true, goes to the welcome page if the user cancels the action + * @param {bool} options.screen_after + * If present the screen to redirect to after a successful login or register. */ export async function startAnyRegistrationFlow(options) { if (options === undefined) options = {}; @@ -66,13 +68,21 @@ export async function startAnyRegistrationFlow(options) { // }); //} else { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); - Modal.createTrackedDialog('Registration required', '', QuestionDialog, { - title: _t("Registration Required"), - description: _t("You need to register to do this. Would you like to register now?"), - button: _t("Register"), + const modal = Modal.createTrackedDialog('Registration required', '', QuestionDialog, { + hasCancelButton: true, + quitOnly: true, + title: _t("Sign In or Create Account"), + description: _t("Use your account or create a new one to continue."), + button: _t("Create Account"), + extraButtons: [ + , + ], onFinished: (proceed) => { if (proceed) { - dis.dispatch({action: 'start_registration'}); + dis.dispatch({action: 'start_registration', screenAfterLogin: options.screen_after}); } else if (options.go_home_on_cancel) { dis.dispatch({action: 'view_home_page'}); } else if (options.go_welcome_on_cancel) { @@ -101,4 +111,3 @@ export async function startAnyRegistrationFlow(options) { // } // throw new Error("Register request succeeded when it should have returned 401!"); // } - diff --git a/src/Rooms.js b/src/Rooms.js index f65e0ff218..218e970f35 100644 --- a/src/Rooms.js +++ b/src/Rooms.js @@ -23,7 +23,7 @@ import {MatrixClientPeg} from './MatrixClientPeg'; * of aliases. Otherwise return null; */ export function getDisplayAliasForRoom(room) { - return room.getCanonicalAlias() || room.getAliases()[0]; + return room.getCanonicalAlias() || room.getAltAliases()[0]; } /** diff --git a/src/ScalarAuthClient.js b/src/ScalarAuthClient.js index 819fe3c998..1ea9d39e2f 100644 --- a/src/ScalarAuthClient.js +++ b/src/ScalarAuthClient.js @@ -23,10 +23,13 @@ import request from "browser-request"; import * as Matrix from 'matrix-js-sdk'; import SdkConfig from "./SdkConfig"; +import {WidgetType} from "./widgets/WidgetType"; // The version of the integration manager API we're intending to work with const imApiVersion = "1.1"; +// TODO: Generify the name of this class and all components within - it's not just for Scalar. + export default class ScalarAuthClient { constructor(apiUrl, uiUrl) { this.apiUrl = apiUrl; @@ -233,20 +236,20 @@ export default class ScalarAuthClient { * Mark all assets associated with the specified widget as "disabled" in the * integration manager database. * This can be useful to temporarily prevent purchased assets from being displayed. - * @param {string} widgetType [description] - * @param {string} widgetId [description] + * @param {WidgetType} widgetType The Widget Type to disable assets for + * @param {string} widgetId The widget ID to disable assets for * @return {Promise} Resolves on completion */ - disableWidgetAssets(widgetType, widgetId) { + disableWidgetAssets(widgetType: WidgetType, widgetId) { let url = this.apiUrl + '/widgets/set_assets_state'; url = this.getStarterLink(url); return new Promise((resolve, reject) => { request({ - method: 'GET', + method: 'GET', // XXX: Actions shouldn't be GET requests uri: url, json: true, qs: { - 'widget_type': widgetType, + 'widget_type': widgetType.preferred, 'widget_id': widgetId, 'state': 'disable', }, diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 2211e513c3..9731e42825 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -16,6 +16,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// TODO: Generify the name of this and all components within - it's not just for scalar. + /* Listens for incoming postMessage requests from the integrations UI URL. The following API is exposed: { @@ -172,6 +174,7 @@ Request: Response: [ { + // TODO: Enable support for m.widget event type (https://github.com/vector-im/riot-web/issues/13111) type: "im.vector.modular.widgets", state_key: "wid1", content: { @@ -190,6 +193,7 @@ Example: room_id: "!foo:bar", response: [ { + // TODO: Enable support for m.widget event type (https://github.com/vector-im/riot-web/issues/13111) type: "im.vector.modular.widgets", state_key: "wid1", content: { @@ -239,6 +243,7 @@ import WidgetUtils from './utils/WidgetUtils'; import RoomViewStore from './stores/RoomViewStore'; import { _t } from './languageHandler'; import {IntegrationManagers} from "./integrations/IntegrationManagers"; +import {WidgetType} from "./widgets/WidgetType"; function sendResponse(event, res) { const data = JSON.parse(JSON.stringify(event.data)); @@ -290,7 +295,7 @@ function inviteUser(event, roomId, userId) { function setWidget(event, roomId) { const widgetId = event.data.widget_id; - const widgetType = event.data.type; + let widgetType = event.data.type; const widgetUrl = event.data.url; const widgetName = event.data.name; // optional const widgetData = event.data.data; // optional @@ -322,6 +327,9 @@ function setWidget(event, roomId) { } } + // convert the widget type to a known widget type + widgetType = WidgetType.fromString(widgetType); + if (userWidget) { WidgetUtils.setUserWidget(widgetId, widgetType, widgetUrl, widgetName, widgetData).then(() => { sendResponse(event, { diff --git a/src/SdkConfig.ts b/src/SdkConfig.ts index 8177a6c5b8..400d29a20f 100644 --- a/src/SdkConfig.ts +++ b/src/SdkConfig.ts @@ -26,6 +26,11 @@ export const DEFAULTS: ConfigOptions = { integrations_rest_url: "https://scalar.vector.im/api", // Where to send bug reports. If not specified, bugs cannot be sent. bug_report_endpoint_url: null, + // Jitsi conference options + jitsi: { + // Default conference domain + preferredDomain: "jitsi.riot.im", + }, }; export default class SdkConfig { diff --git a/src/Searching.js b/src/Searching.js index a5d945f64b..663328fe41 100644 --- a/src/Searching.js +++ b/src/Searching.js @@ -87,6 +87,13 @@ async function localSearch(searchTerm, roomId = undefined) { searchArgs.room_id = roomId; } + const emptyResult = { + results: [], + highlights: [], + }; + + if (searchTerm === "") return emptyResult; + const eventIndex = EventIndexPeg.get(); const localResult = await eventIndex.search(searchArgs); @@ -97,11 +104,6 @@ async function localSearch(searchTerm, roomId = undefined) { }, }; - const emptyResult = { - results: [], - highlights: [], - }; - const result = MatrixClientPeg.get()._processRoomEventsSearch( emptyResult, response); diff --git a/src/SlashCommands.js b/src/SlashCommands.tsx similarity index 77% rename from src/SlashCommands.js rename to src/SlashCommands.tsx index b39b8fb9ac..fbb9e2eb0e 100644 --- a/src/SlashCommands.js +++ b/src/SlashCommands.tsx @@ -2,6 +2,7 @@ Copyright 2015, 2016 OpenMarket Ltd Copyright 2018 New Vector Ltd Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> +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. @@ -17,7 +18,8 @@ limitations under the License. */ -import React from 'react'; +import * as React from 'react'; + import {MatrixClientPeg} from './MatrixClientPeg'; import dis from './dispatcher'; import * as sdk from './index'; @@ -33,12 +35,23 @@ import { abbreviateUrl } from './utils/UrlUtils'; import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from './utils/IdentityServerUtils'; import {isPermalinkHost, parsePermalink} from "./utils/permalinks/Permalinks"; import {inviteUsersToRoom} from "./RoomInvite"; +import { WidgetType } from "./widgets/WidgetType"; +import { Jitsi } from "./widgets/Jitsi"; +import { parseFragment as parseHtml } from "parse5"; +import sendBugReport from "./rageshake/submit-rageshake"; +import SdkConfig from "./SdkConfig"; +import { ensureDMExists } from "./createRoom"; -const singleMxcUpload = async () => { +// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816 +interface HTMLInputEvent extends Event { + target: HTMLInputElement & EventTarget; +} + +const singleMxcUpload = async (): Promise => { return new Promise((resolve) => { const fileSelector = document.createElement('input'); fileSelector.setAttribute('type', 'file'); - fileSelector.onchange = (ev) => { + fileSelector.onchange = (ev: HTMLInputEvent) => { const file = ev.target.files[0]; const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog"); @@ -62,28 +75,49 @@ export const CommandCategories = { "other": _td("Other"), }; -class Command { - constructor({name, args='', description, runFn, category=CommandCategories.other, hideCompletionAfterSpace=false}) { - this.command = '/' + name; - this.args = args; - this.description = description; - this.runFn = runFn; - this.category = category; - this.hideCompletionAfterSpace = hideCompletionAfterSpace; +type RunFn = ((roomId: string, args: string, cmd: string) => {error: any} | {promise: Promise}); + +interface ICommandOpts { + command: string; + aliases?: string[]; + args?: string; + description: string; + runFn?: RunFn; + category: string; + hideCompletionAfterSpace?: boolean; +} + +export class Command { + command: string; + aliases: string[]; + args: undefined | string; + description: string; + runFn: undefined | RunFn; + category: string; + hideCompletionAfterSpace: boolean; + + constructor(opts: ICommandOpts) { + this.command = opts.command; + this.aliases = opts.aliases || []; + this.args = opts.args || ""; + this.description = opts.description; + this.runFn = opts.runFn; + this.category = opts.category || CommandCategories.other; + this.hideCompletionAfterSpace = opts.hideCompletionAfterSpace || false; } getCommand() { - return this.command; + return `/${this.command}`; } getCommandWithArgs() { return this.getCommand() + " " + this.args; } - run(roomId, args) { + run(roomId: string, args: string, cmd: string) { // if it has no runFn then its an ignored/nop command (autocomplete only) e.g `/me` if (!this.runFn) return; - return this.runFn.bind(this)(roomId, args); + return this.runFn.bind(this)(roomId, args, cmd); } getUsage() { @@ -95,7 +129,7 @@ function reject(error) { return {error}; } -function success(promise) { +function success(promise?: Promise) { return {promise}; } @@ -103,11 +137,9 @@ function success(promise) { * functions are called with `this` bound to the Command instance. */ -/* eslint-disable babel/no-invalid-this */ - -export const CommandMap = { - shrug: new Command({ - name: 'shrug', +export const Commands = [ + new Command({ + command: 'shrug', args: '', description: _td('Prepends ¯\\_(ツ)_/¯ to a plain-text message'), runFn: function(roomId, args) { @@ -119,8 +151,8 @@ export const CommandMap = { }, category: CommandCategories.messages, }), - plain: new Command({ - name: 'plain', + new Command({ + command: 'plain', args: '', description: _td('Sends a message as plain text, without interpreting it as markdown'), runFn: function(roomId, messages) { @@ -128,11 +160,20 @@ export const CommandMap = { }, category: CommandCategories.messages, }), - ddg: new Command({ - name: 'ddg', + new Command({ + command: 'html', + args: '', + description: _td('Sends a message as html, without interpreting it as markdown'), + runFn: function(roomId, messages) { + return success(MatrixClientPeg.get().sendHtmlMessage(roomId, messages, messages)); + }, + category: CommandCategories.messages, + }), + new Command({ + command: 'ddg', args: '', description: _td('Searches DuckDuckGo for results'), - runFn: function(roomId, args) { + runFn: function() { const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog'); // TODO Don't explain this away, actually show a search UI here. Modal.createTrackedDialog('Slash Commands', '/ddg is not a command', ErrorDialog, { @@ -144,9 +185,8 @@ export const CommandMap = { category: CommandCategories.actions, hideCompletionAfterSpace: true, }), - - upgraderoom: new Command({ - name: 'upgraderoom', + new Command({ + command: 'upgraderoom', args: '', description: _td('Upgrades a room to a new version'), runFn: function(roomId, args) { @@ -215,9 +255,8 @@ export const CommandMap = { }, category: CommandCategories.admin, }), - - nick: new Command({ - name: 'nick', + new Command({ + command: 'nick', args: '', description: _td('Changes your display nickname'), runFn: function(roomId, args) { @@ -228,9 +267,9 @@ export const CommandMap = { }, category: CommandCategories.actions, }), - - myroomnick: new Command({ - name: 'myroomnick', + new Command({ + command: 'myroomnick', + aliases: ['roomnick'], args: '', description: _td('Changes your display nickname in the current room only'), runFn: function(roomId, args) { @@ -247,9 +286,8 @@ export const CommandMap = { }, category: CommandCategories.actions, }), - - roomavatar: new Command({ - name: 'roomavatar', + new Command({ + command: 'roomavatar', args: '[]', description: _td('Changes the avatar of the current room'), runFn: function(roomId, args) { @@ -265,9 +303,8 @@ export const CommandMap = { }, category: CommandCategories.actions, }), - - myroomavatar: new Command({ - name: 'myroomavatar', + new Command({ + command: 'myroomavatar', args: '[]', description: _td('Changes your avatar in this current room only'), runFn: function(roomId, args) { @@ -292,9 +329,8 @@ export const CommandMap = { }, category: CommandCategories.actions, }), - - myavatar: new Command({ - name: 'myavatar', + new Command({ + command: 'myavatar', args: '[]', description: _td('Changes your avatar in all rooms'), runFn: function(roomId, args) { @@ -310,9 +346,8 @@ export const CommandMap = { }, category: CommandCategories.actions, }), - - topic: new Command({ - name: 'topic', + new Command({ + command: 'topic', args: '[]', description: _td('Gets or sets the room topic'), runFn: function(roomId, args) { @@ -321,7 +356,7 @@ export const CommandMap = { return success(cli.setRoomTopic(roomId, args)); } const room = cli.getRoom(roomId); - if (!room) return reject('Bad room ID: ' + roomId); + if (!room) return reject(_t("Failed to set topic")); const topicEvents = room.currentState.getStateEvents('m.room.topic', ''); const topic = topicEvents && topicEvents.getContent().topic; @@ -331,14 +366,14 @@ export const CommandMap = { Modal.createTrackedDialog('Slash Commands', 'Topic', InfoDialog, { title: room.name, description:
, + hasCloseButton: true, }); return success(); }, category: CommandCategories.admin, }), - - roomname: new Command({ - name: 'roomname', + new Command({ + command: 'roomname', args: '', description: _td('Sets the room name'), runFn: function(roomId, args) { @@ -349,9 +384,8 @@ export const CommandMap = { }, category: CommandCategories.admin, }), - - invite: new Command({ - name: 'invite', + new Command({ + command: 'invite', args: '', description: _td('Invites user with given id to current room'), runFn: function(roomId, args) { @@ -385,17 +419,20 @@ export const CommandMap = { button: _t("Continue"), }, )); + + finished = finished.then(([useDefault]: any) => { + if (useDefault) { + useDefaultIdentityServer(); + return; + } + throw new Error(_t("Use an identity server to invite by email. Manage in Settings.")); + }); } else { return reject(_t("Use an identity server to invite by email. Manage in Settings.")); } } const inviter = new MultiInviter(roomId); - return success(finished.then(([useDefault] = []) => { - if (useDefault) { - useDefaultIdentityServer(); - } else if (useDefault === false) { - throw new Error(_t("Use an identity server to invite by email. Manage in Settings.")); - } + return success(finished.then(() => { return inviter.invite([address]); }).then(() => { if (inviter.getCompletionState(address) !== "invited") { @@ -408,12 +445,12 @@ export const CommandMap = { }, category: CommandCategories.actions, }), - - join: new Command({ - name: 'join', + new Command({ + command: 'join', + aliases: ['j', 'goto'], args: '', description: _td('Joins room with given alias'), - runFn: function(roomId, args) { + runFn: function(_, args) { if (args) { // Note: we support 2 versions of this command. The first is // the public-facing one for most users and the other is a @@ -521,9 +558,8 @@ export const CommandMap = { }, category: CommandCategories.actions, }), - - part: new Command({ - name: 'part', + new Command({ + command: 'part', args: '[]', description: _td('Leave room'), runFn: function(roomId, args) { @@ -569,9 +605,8 @@ export const CommandMap = { }, category: CommandCategories.actions, }), - - kick: new Command({ - name: 'kick', + new Command({ + command: 'kick', args: ' [reason]', description: _td('Kicks user with given id'), runFn: function(roomId, args) { @@ -585,10 +620,8 @@ export const CommandMap = { }, category: CommandCategories.admin, }), - - // Ban a user from the room with an optional reason - ban: new Command({ - name: 'ban', + new Command({ + command: 'ban', args: ' [reason]', description: _td('Bans user with given id'), runFn: function(roomId, args) { @@ -602,10 +635,8 @@ export const CommandMap = { }, category: CommandCategories.admin, }), - - // Unban a user from ythe room - unban: new Command({ - name: 'unban', + new Command({ + command: 'unban', args: '', description: _td('Unbans user with given ID'), runFn: function(roomId, args) { @@ -620,9 +651,8 @@ export const CommandMap = { }, category: CommandCategories.admin, }), - - ignore: new Command({ - name: 'ignore', + new Command({ + command: 'ignore', args: '', description: _td('Ignores a user, hiding their messages from you'), runFn: function(roomId, args) { @@ -651,9 +681,8 @@ export const CommandMap = { }, category: CommandCategories.actions, }), - - unignore: new Command({ - name: 'unignore', + new Command({ + command: 'unignore', args: '', description: _td('Stops ignoring a user, showing their messages going forward'), runFn: function(roomId, args) { @@ -683,10 +712,8 @@ export const CommandMap = { }, category: CommandCategories.actions, }), - - // Define the power level of a user - op: new Command({ - name: 'op', + new Command({ + command: 'op', args: ' []', description: _td('Define the power level of a user'), runFn: function(roomId, args) { @@ -696,14 +723,15 @@ export const CommandMap = { if (matches) { const userId = matches[1]; if (matches.length === 4 && undefined !== matches[3]) { - powerLevel = parseInt(matches[3]); + powerLevel = parseInt(matches[3], 10); } if (!isNaN(powerLevel)) { const cli = MatrixClientPeg.get(); const room = cli.getRoom(roomId); - if (!room) return reject('Bad room ID: ' + roomId); + if (!room) return reject(_t("Command failed")); const powerLevelEvent = room.currentState.getStateEvents('m.room.power_levels', ''); + if (!powerLevelEvent.getContent().users[args]) return reject(_t("Could not find user in room")); return success(cli.setPowerLevel(roomId, userId, powerLevel, powerLevelEvent)); } } @@ -712,10 +740,8 @@ export const CommandMap = { }, category: CommandCategories.admin, }), - - // Reset the power level of a user - deop: new Command({ - name: 'deop', + new Command({ + command: 'deop', args: '', description: _td('Deops user with given id'), runFn: function(roomId, args) { @@ -724,9 +750,10 @@ export const CommandMap = { if (matches) { const cli = MatrixClientPeg.get(); const room = cli.getRoom(roomId); - if (!room) return reject('Bad room ID: ' + roomId); + if (!room) return reject(_t("Command failed")); const powerLevelEvent = room.currentState.getStateEvents('m.room.power_levels', ''); + if (!powerLevelEvent.getContent().users[args]) return reject(_t("Could not find user in room")); return success(cli.setPowerLevel(roomId, args, undefined, powerLevelEvent)); } } @@ -734,9 +761,8 @@ export const CommandMap = { }, category: CommandCategories.admin, }), - - devtools: new Command({ - name: 'devtools', + new Command({ + command: 'devtools', description: _td('Opens the Developer Tools dialog'), runFn: function(roomId) { const DevtoolsDialog = sdk.getComponent('dialogs.DevtoolsDialog'); @@ -745,31 +771,60 @@ export const CommandMap = { }, category: CommandCategories.advanced, }), - - addwidget: new Command({ - name: 'addwidget', - args: '', + new Command({ + command: 'addwidget', + args: '', description: _td('Adds a custom widget by URL to the room'), - runFn: function(roomId, args) { - if (!args || (!args.startsWith("https://") && !args.startsWith("http://"))) { + runFn: function(roomId, widgetUrl) { + if (!widgetUrl) { + return reject(_t("Please supply a widget URL or embed code")); + } + + // Try and parse out a widget URL from iframes + if (widgetUrl.toLowerCase().startsWith("