diff --git a/.eslintrc.js b/.eslintrc.js index bb3a06d3552..3e1892b2d65 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -12,6 +12,11 @@ module.exports = { // Things we do that break the ideal style "quotes": "off", }, + settings: { + react: { + version: 'detect' + } + }, overrides: [{ files: ["src/**/*.{ts,tsx}"], extends: [ diff --git a/.github/ISSUE_TEMPLATE/config.ylm b/.github/ISSUE_TEMPLATE/config.yml similarity index 50% rename from .github/ISSUE_TEMPLATE/config.ylm rename to .github/ISSUE_TEMPLATE/config.yml index f7ca654fad4..cbda0e66350 100644 --- a/.github/ISSUE_TEMPLATE/config.ylm +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,5 @@ blank_issues_enabled: false contact_links: - - name: Report a security vulnerability - url: https://github.com/vector-im/element-web/security/policy - about: Please review our security policy for more details - name: Questions & support url: https://matrix.to/#/#element-web:matrix.org about: Please ask and answer questions here. diff --git a/CHANGELOG.md b/CHANGELOG.md index 5aa75a5bcf2..057060976a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,49 @@ +Changes in [1.10.8-rc.1](https://github.com/vector-im/element-web/releases/tag/v1.10.8-rc.1) (2022-03-22) +========================================================================================================= + +## ✨ Features + * Live location sharing: live share warning in room ([\#8100](https://github.com/matrix-org/matrix-react-sdk/pull/8100)). + * Add simple live share warning ([\#8066](https://github.com/matrix-org/matrix-react-sdk/pull/8066)). + * extract reusable styled live beacon icon ([\#8103](https://github.com/matrix-org/matrix-react-sdk/pull/8103)). + * Don't restore MemberInfo from RightPanel history when viewing a room ([\#8090](https://github.com/matrix-org/matrix-react-sdk/pull/8090)). Fixes #21487. + * Allow sending files as replies as per MSC3676 ([\#8020](https://github.com/matrix-org/matrix-react-sdk/pull/8020)). Fixes #7156. + * kill beacons on expiry ([\#8075](https://github.com/matrix-org/matrix-react-sdk/pull/8075)). + * enable geolocation behaviour in location picker for live share type ([\#8068](https://github.com/matrix-org/matrix-react-sdk/pull/8068)). + * Improve formatting features in the editor ([\#7104](https://github.com/matrix-org/matrix-react-sdk/pull/7104)). Fixes #19501. Contributed by @alexanderstephan. + * Support MSC3026 busy presence ([\#8043](https://github.com/matrix-org/matrix-react-sdk/pull/8043)). + * Show displayname in non-narrow thread summeries ([\#8036](https://github.com/matrix-org/matrix-react-sdk/pull/8036)). Fixes #19646. + * Tweak search dialog based on new designs ([\#7980](https://github.com/matrix-org/matrix-react-sdk/pull/7980)). Fixes #21285 and #21289. + * fallback to event text in location body when map unavailable ([\#7982](https://github.com/matrix-org/matrix-react-sdk/pull/7982)). Fixes #20655. + * Send pin drop location share events ([\#7967](https://github.com/matrix-org/matrix-react-sdk/pull/7967)). + +## 🐛 Bug Fixes + * fix quicktime video thumbnailing ([\#8108](https://github.com/matrix-org/matrix-react-sdk/pull/8108)). Fixes #21505. + * Fix scroll behaviour in space panel ([\#8111](https://github.com/matrix-org/matrix-react-sdk/pull/8111)). Fixes #21467. + * Fix emoting with emoji or pills ([\#8105](https://github.com/matrix-org/matrix-react-sdk/pull/8105)). Fixes #21497. + * Remove padding of InviteDialog & fix visual regression ([\#8076](https://github.com/matrix-org/matrix-react-sdk/pull/8076)). Fixes #20631. Contributed by @luixxiul. + * Fixes mx_MLocationBody_markerBorder ([\#8069](https://github.com/matrix-org/matrix-react-sdk/pull/8069)). Fixes #21444. Contributed by @luixxiul. + * Make margin and padding of mx_InviteDialog_other consistent ([\#8063](https://github.com/matrix-org/matrix-react-sdk/pull/8063)). Fixes #20631. Contributed by @luixxiul. + * Fix freeze/crash when 1:1 calling ([\#8057](https://github.com/matrix-org/matrix-react-sdk/pull/8057)). Fixes #21181. + * Don't assume that widget IDs are unique ([\#8052](https://github.com/matrix-org/matrix-react-sdk/pull/8052)). Fixes #21399. + * Fix the header of Space landing page ([\#8048](https://github.com/matrix-org/matrix-react-sdk/pull/8048)). Fixes #21402. Contributed by @luixxiul. + * Fix buttons alignment of Space list header ([\#8047](https://github.com/matrix-org/matrix-react-sdk/pull/8047)). Fixes #21401. Contributed by @luixxiul. + * Fix null-guarding regression around reply_to_event dispatch ([\#8039](https://github.com/matrix-org/matrix-react-sdk/pull/8039)). + * Fix clicking on copy link to thread wrongly opening thread ([\#8038](https://github.com/matrix-org/matrix-react-sdk/pull/8038)). Fixes #20653. + * Fix regression around replying to search results ([\#8035](https://github.com/matrix-org/matrix-react-sdk/pull/8035)). Fixes #21389. + * Share shared history keys in the background ([\#8031](https://github.com/matrix-org/matrix-react-sdk/pull/8031)). Fixes #21192. + * Paginate responses to pinned polls ([\#8025](https://github.com/matrix-org/matrix-react-sdk/pull/8025)). Fixes #21382. + * Fix incorrect usage of unstable variant of `is_falling_back` ([\#8016](https://github.com/matrix-org/matrix-react-sdk/pull/8016)). + * Fix issues with ThreadSummary in msc-enabled mode ([\#8018](https://github.com/matrix-org/matrix-react-sdk/pull/8018)). Fixes matrix-org/element-web-rageshakes#11401 and matrix-org/element-web-rageshakes#11400. + * Fix alignment of polls within threads ([\#8017](https://github.com/matrix-org/matrix-react-sdk/pull/8017)). Fixes #21235. + * Fix issues with thread summaries being wrong or stale ([\#8015](https://github.com/matrix-org/matrix-react-sdk/pull/8015)). Fixes #21363 and #21204. + * Fix button border color of LeaveSpaceDialog ([\#8010](https://github.com/matrix-org/matrix-react-sdk/pull/8010)). Fixes #21365. Contributed by @luixxiul. + * Fix room list scroll jumps ([\#7991](https://github.com/matrix-org/matrix-react-sdk/pull/7991)). Fixes #19322. + * Fix a variety of issues with HTML → Markdown conversion ([\#8004](https://github.com/matrix-org/matrix-react-sdk/pull/8004)). Fixes #10648, #20718, #10722, #10389, #17610 #9984 and #20140. + * Wrap EventTile rather than its children in an error boundary ([\#7945](https://github.com/matrix-org/matrix-react-sdk/pull/7945)). + * Normalized shortcut formatting for quote expansion control ([\#7995](https://github.com/matrix-org/matrix-react-sdk/pull/7995)). Fixes #19685. Contributed by @Sinharitik589. + * Fix buttons and text layout on Security Key dialog ([\#7996](https://github.com/matrix-org/matrix-react-sdk/pull/7996)). Fixes #21330. Contributed by @luixxiul. + * Fix formatting not being applied after links ([\#7990](https://github.com/matrix-org/matrix-react-sdk/pull/7990)). Fixes #20091. + Changes in [1.10.7](https://github.com/vector-im/element-web/releases/tag/v1.10.7) (2022-03-15) =============================================================================================== diff --git a/README.md b/README.md index ebb70dbc70b..e2a2c663474 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ 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://classic.yarnpkg.com/en/docs/install) if you do not have it already. -1. Install or update `node.js` so that your `node` is at least v14.x. +1. Install or update `node.js` so that your `node` is at least the current recommended LTS. 1. Install `yarn` if not present already. 1. Clone the repo: `git clone https://github.com/vector-im/element-web.git`. 1. Switch to the element-web directory: `cd element-web`. diff --git a/config.sample.json b/config.sample.json index 1ddc14a154f..56d62652cfe 100644 --- a/config.sample.json +++ b/config.sample.json @@ -24,9 +24,10 @@ ], "defaultCountryCode": "GB", "showLabsSettings": true, + "features": { }, "default_federate": true, "default_theme": "light", - "roomDirectory": { + "room_directory": { "servers": [ "matrix.org" ] @@ -35,11 +36,11 @@ "https://matrix.org": false, "https://matrix-client.matrix.org": false }, - "settingDefaults": { + "setting_defaults": { "breadcrumbs": true }, "jitsi": { - "preferredDomain": "meet.jit.si" + "preferred_domain": "meet.jit.si" }, "map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx" } diff --git a/docs/config.md b/docs/config.md index 79055774ec6..d508a630afc 100644 --- a/docs/config.md +++ b/docs/config.md @@ -1,213 +1,468 @@ -Configuration -============= - -You can configure the app by copying `config.sample.json` to -`config.json` and customising it: - -For a good example, see https://develop.element.io/config.json. - -1. `default_server_config` sets the default homeserver and identity server URL for - Element to use. The object is the same as returned by [https:///.well-known/matrix/client](https://matrix.org/docs/spec/client_server/latest.html#get-well-known-matrix-client), - with added support for a `server_name` under the `m.homeserver` section to display - a custom homeserver name. Alternatively, the config can contain a `default_server_name` - instead which is where Element will go to get that same object, although this option is - deprecated - see the `.well-known` link above for more information on using this option. - Note that the `default_server_name` is used to get a complete server configuration - whereas the `server_name` in the `default_server_config` is for display purposes only. - * *Note*: The URLs can also be individually specified as `default_hs_url` and - `default_is_url`, however these are deprecated. They are maintained for backwards - compatibility with older configurations. `default_is_url` is respected only - if `default_hs_url` is used. - * Element will fail to load if a mix of `default_server_config`, `default_server_name`, or - `default_hs_url` is specified. When multiple sources are specified, it is unclear - which should take priority and therefore the application cannot continue. - * As of Element 1.4.0, identity servers are optional. See [Identity servers](#identity-servers) below. -1. `sso_redirect_options`: Optionally defines how Element will behave with a server which supports - Single Sign On (SSO). By default, Element will do nothing special and simply show a button where - needed for the user to click to navigate to the SSO system. This behaviour can be tuned with the - config options below (as properties of the `sso_redirect_options` object). None of the options apply - if Element thinks the user is already logged in, and similarly Element will assume the default server - supports SSO if these redirect options are used. - * `immediate`: When `true` (default `false`), Element will automatically redirect all unauthenticated - users to the SSO system to log in regardless of how they reached the app. This overrides the use of - other redirect options. - * `on_welcome_page`: When `true` (default `false`), Element will automatically redirect all unauthenticated - users to the SSO to log in if the user lands on the welcome page or no specific page. For example, - https://app.element.io/#/welcome and https://app.element.io would redirect if set up to use this option. - This can be useful to maintain guest experience until an account is needed. -1. `logout_redirect_url`: After Element has cleared the user's storage, the user will be redirected to this URL. - Typically most useful in environments where the account users will be logging into is managed for them, such - as in cases of some SSO deployments. For example: this page might log the user out of the SSO system too. -1. `features`: Lookup of optional features that may be force-enabled (`true`) or force-disabled (`false`). - When features are not listed here, their defaults will be used, and users can turn them on/off if `showLabsSettings` - allows them to. The available optional experimental features vary from release to release and are - [documented](labs.md). The feature flag process is [documented](feature-flags.md) as well. -1. `showLabsSettings`: Shows the "labs" tab of user settings. Useful to allow users to turn on experimental features - they might not otherwise have access to. -1. `brand`: String to pass to your homeserver when configuring email notifications, to let the - homeserver know what email template to use when talking to you. -1. `branding`: Configures various branding and logo details, such as: - 1. `welcomeBackgroundUrl`: An image to use as a wallpaper outside the app - during authentication flows. If an array is passed, an image is chosen randomly for each visit. - 1. `authHeaderLogoUrl`: An logo image that is shown in the header during - authentication flows - 1. `authFooterLinks`: a list of links to show in the authentication page footer: - `[{"text": "Link text", "url": "https://link.target"}, {"text": "Other link", ...}]` -1. `reportEvent`: Configures the dialog for reporting content to the homeserver - admin. - 1. `adminMessageMD`: An extra message to show on the reporting dialog to - mention homeserver-specific policies. Accepts Markdown. -1. `integrations_ui_url`: URL to the web interface for the integrations server. The integrations - server is not Element and normally not your homeserver either. The integration server settings - may be left blank to disable integrations. -1. `integrations_rest_url`: URL to the REST interface for the integrations server. -1. `integrations_widgets_urls`: list of URLs to the REST interface for the widget integrations server. -1. `bug_report_endpoint_url`: endpoint to send bug reports to (must be running a - https://github.com/matrix-org/rageshake server). Bug reports are sent when a user clicks - "Send Logs" within the application. Bug reports can be disabled/hidden by leaving the - `bug_report_endpoint_url` out of your config file. -1. `uisi_autorageshake_app`: If users enable the Labs flag - "Automatically send debug logs on decryption errors", rageshakes - submitted by that feature can be given a custom app name so that - the rageshake server can file them in a separate issue tracker. If - this field is absent from the config, the app name for decryption - error rageshakes will be `"element-web"` just like for - manually-submitted rageshakes. - - If `bug_report_endpoint_url` is set to Element's rageshake server, - then this field should be set to `"element-auto-uisi"` as in - `config.sample.json`. If `bug_report_endpoint_url` is left out, - this field has no effect and can be left out as well. If you are - using your own rageshake server, set this field in accordance with - your rageshake server configuration. -1. `roomDirectory`: config for the public room directory. This section is optional. -1. `roomDirectory.servers`: List of other homeservers' directories to include in the drop - down list. Optional. +# Configuration + +You can configure the app by copying `config.sample.json` to `config.json` and customising it. The possible options are +described here. If you run into issues, please visit [#element-web:matrix.org](https://matrix.to/#/#element-web:matrix.org) +on Matrix. + +For a good example of a production-tuned config, see https://app.element.io/config.json + +For an example of a development/beta-tuned config, see https://develop.element.io/config.json + +After changing the config, the app will need to be reloaded. For web browsers this is a simple page refresh, however +for the desktop app the application will need to be exited fully (including via the task tray) and re-started. + +## Homeserver configuration + +In order for Element to even start you will need to tell it what homeserver to connect to *by default*. Users will be +able to use a different homeserver if they like, though this can be disabled with `"disable_custom_urls": false` in your +config. + +One of the following options **must** be supplied: + +1. `default_server_config`: The preferred method of setting the homeserver connection information. Simply copy/paste + your [`/.well-known/matrix/client`](https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixclient) + into this field. For example: + ```json + { + "default_server_config": { + "m.homeserver": { + "base_url": "https://matrix-client.matrix.org" + }, + "m.identity_server": { + "base_url": "https://vector.im" + } + } + } + ``` +2. `default_server_name`: A different method of connecting to the homeserver by looking up the connection information + using `.well-known`. When using this option, simply use your server's domain name (the part at the end of user IDs): + `"default_server_name": "matrix.org"` +3. `default_hs_url` and (optionally) `default_is_url`: A very deprecated method of defining the connection + information. These are the same values seen as `base_url` in the `default_server_config` example, with `default_is_url` + being optional. + +If a combination of these three methods is used then Element will fail to load. This is because it is unclear which +should be considered "first". + +## Labs flags + +Labs flags are optional, typically beta or in-development, features that can be turned on or off. The full range of +labs flags and their development status are documented [here](./labs.md). If interested, the feature flag process is +documented [here](./feature-flags.md). + +To force a labs flag on or off, use the following: + +```json +{ + "features": { + "feature_you_want_to_turn_on": true, + "feature_you_want_to_keep_off": false + } +} +``` + +If you'd like the user to be able to self-select which labs flags they can turn on, add `"show_labs_flags": true` to +your config. This will turn on the tab in user settings. + +**Note**: Feature support varies release-by-release. Check the [labs flag documentation](./labs.md) frequently if enabling +the functionality. + +## Default settings + +Some settings additionally support being specified at the config level to affect the user experience of your Element Web +instance. As of writing those settings are not fully documented, however a few are: + +1. `default_federate`: When `true` (default), rooms will be marked as "federatable" during creation. Typically this setting + shouldn't be used as the federation capabilities of a room **cannot** be changed after the room is created. +2. `default_country_code`: An optional ISO 3166 alpha2 country code (eg: `GB`, the default) to use when showing phone number + inputs. +3. `room_directory`: Optionally defines how the room directory component behaves. Currently only a single property, `servers` + is supported to add additional servers to the dropdown. For example: + ```json + { + "room_directory": { + "servers": ["matrix.org", "example.org"] + } + } + ``` +4. `setting_defaults`: Optional configuration for settings which are not described by this document and support the `config` + level. This list is incomplete. For example: + ```json + { + "setting_defaults": { + "MessageComposerInput.showStickersButton": false, + "MessageComposerInput.showPollsButton": false + } + } + ``` + These values will take priority over the hardcoded defaults for the settings. + +## Customisation & branding + + + +Element supports some customisation of the user experience through various branding and theme options. While it doesn't support +complete re-branding/private labeling, a more personalised experience can be achieved for your users. + 1. `default_theme`: name of theme to use by default (can be one of 'light', 'dark' or 'system'), defaults to 'system', set the default light and dark theme via the `light_theme` and `dark_theme` in `settingDefaults` respectively and provide [custom themes](https://github.com/SchildiChat/element-web/blob/sc/docs/theming.md#custom-themes) via `custom_themes` -2. `update_base_url` (electron app only): HTTPS URL to a web server to download - updates from. This should be the path to the directory containing `macos` - and `win32` (for update packages, not installer packages). -1. DEPRECATED: `piwik`: Analytics can be disabled by setting `piwik: false` or by leaving the piwik config - option out of your config file. If you want to enable analytics, set `piwik` to be an object - containing the following properties: - 1. `url`: The URL of the Piwik instance to use for collecting analytics - 2. `whitelistedHSUrls`: a list of HS URLs to not redact from the analytics - 3. `whitelistedISUrls`: a list of IS URLs to not redact from the analytics - 4. `siteId`: The Piwik Site ID to use when sending analytics to the Piwik server configured above -4. `welcomeUserId`: the user ID of a bot to invite whenever users register that can give them a tour -5. `embeddedPages`: Configures the pages displayed in portions of Element that - embed static files, such as: - 1. `welcomeUrl`: Initial content shown on the outside of the app when not - logged in. Defaults to `welcome.html` supplied with Element. - 2. `homeUrl`: Content shown on the inside of the app when a specific room is - not selected. By default, no home page is configured. If one is set, a - button to access it will be shown in the top left menu. - 3. `loginForWelcome`: Overrides `welcomeUrl` to make the welcome page be the - same page as the login page when `true`. This effectively disables the - welcome page. -6. `defaultCountryCode`: The ISO 3166 alpha2 country code to use when showing - country selectors, like the phone number input on the registration page. - Defaults to `GB` if the given code is unknown or not provided. -7. `settingDefaults`: Defaults for settings that support the `config` level, - as an object mapping setting name to value (note that the "theme" setting - is special cased to the `default_theme` in the config file). -8. `disable_custom_urls`: disallow the user to change the - default homeserver when signing up or logging in. -9. `permalinkPrefix`: Used to change the URL that Element generates permalinks with. - By default, this is "https://matrix.to" to generate matrix.to (spec) permalinks. - Set this to your Element instance URL if you run an unfederated server (eg: - "https://element.example.org"). -11. `jitsi`: Used to change the default conference options. Learn more about the - Jitsi options at [jitsi.md](./jitsi.md). - 1. `preferredDomain`: The domain name of the preferred Jitsi instance. Defaults - to `meet.element.io`. This is used whenever a user clicks on the voice/video - call buttons - integration managers may use a different domain. - This setting is ignored if your homeserver provides - `/.well-known/matrix/client` in its well-known location, and the JSON file - at that location has a key `m.vector.riot.jitsi`. In this case, the - configuration found in the well-known location is used instead. -1. `jitsiWidget`: Options to change the built-in Jitsi widget behaviour. `jitsi` controls - how the widget gets created, but not how it behaves. - 1. `skipBuiltInWelcomeScreen`: If you'd like to skip the default "Join Conference" - behaviour, set this to `true`. This will cause the widget to assume that there's - a Jitsi welcome screen set up and point the user towards that. Note that this can - cause the camera/microphone to flicker as "in use" while Jitsi tests the devices. -1. `enable_presence_by_hs_url`: The property key should be the URL of the homeserver - and its value defines whether to enable/disable the presence status display - from that homeserver. If no options are configured, presence is shown for all - homeservers. -13. `disable_guests`: Disables guest access tokens and auto-guest registrations. - Defaults to false (guests are allowed). -14. `disable_login_language_selector`: Disables the login language selector. Defaults - to false (language selector is shown). -15. `disable_3pid_login`: Disables 3rd party identity options on login and registration form - Defaults to false (3rd party identity options are shown). -16. `default_federate`: Default option for room federation when creating a room - Defaults to true (room federation enabled). -17. `desktopBuilds`: Used to alter promotional links to the desktop app. By default - the builds are considered available and accessible from https://element.io. This - config option is typically used in the context of encouraging encrypted message - search capabilities (Seshat). All the options listed below are required if this - option is specified. - 1. `available`: When false, the desktop app will not be promoted to the user. - 2. `logo`: An HTTP URL to the avatar for the desktop build. Should be 24x24, ideally - an SVG. - 3. `url`: An HTTP URL for where to send the user to download the desktop build. -18. `mobileBuilds`: Used to alter promotional links to the mobile app. By default the - builds are considered available and accessible from https://element.io. This config - option is typically used in a context of encouraging the user to try the mobile app - instead of a mobile/incompatible browser. - 1. `ios`: The URL to the iOS build. If `null`, it will be assumed to be not available. - If not set, the default element.io builds will be used. - 2. `android`: The URL to the Android build. If `null`, it will be assumed to be not available. - If not set, the default element.io builds will be used. - 3. `fdroid`: The URL to the FDroid build. If `null`, it will be assumed to be not available. - If not set, the default element.io builds will be used. -19. `mobileGuideToast`: Whether to show a toast a startup which nudges users on - iOS and Android towards the native mobile apps. The toast redirects to the - mobile guide if they accept. Defaults to false. -20. `audioStreamUrl`: If supplied, show an option on Jitsi widgets to stream - audio using Jitsi's live streaming feature. This option is experimental and - may be removed at any time without notice. -21. `voip`: Behaviour related to calls - 1. `obeyAssertedIdentity`: If set, MSC3086 asserted identity messages sent - on VoIP calls will cause the call to appear in the room corresponding to the - asserted identity. This *must* only be set in trusted environments. -1. `posthog`: [Posthog](https://posthog.com/) integration config. If not set, Posthog analytics are disabled. - 1. `projectApiKey`: The Posthog project API key - 2. `apiHost`: The Posthog API host -1. `sentry`: [Sentry](https://sentry.io/) configuration for rageshake data being sent to sentry. - 1. `dsn`: the Sentry [DSN](https://docs.sentry.io/product/sentry-basics/dsn-explainer/) - 2. `environment`: (optional) The [Environment](https://docs.sentry.io/product/sentry-basics/environments/) to pass to sentry -1. `map_style_url`: Map tile server style URL for location sharing. e.g. - 'https://api.maptiler.com/maps/streets/style.json?key=YOUR_KEY_GOES_HERE' - This setting is ignored if your homeserver provides - `/.well-known/matrix/client` in its well-known location, and the JSON file - at that location has a key `m.tile_server` (or the unstable version - `org.matrix.msc3488.tile_server`). In this case, the configuration found in - the well-known location is used instead. -1. `analyticsOwner`: The entity that analytics data is being sent to. Used in copy - when explaining to the user where data is being sent. If not set, defaults to `brand`. -1. `defaultDeviceDisplayName`: The default device display name to use for new logins - and registrations. If not set then a calculated version will be used. -1. `custom_translations_url`: An optional URL to allow overriding of translatable strings. - The JSON file must be in a format of `{"affected string": {"languageCode": "new string"}}`. - See https://github.com/matrix-org/matrix-react-sdk/pull/7886 for details. - -Note that `index.html` also has an og:image meta tag that is set to an image -hosted on riot.im. This is the image used if links to your copy of Element -appear in some websites like Facebook, and indeed Element itself. This has to be -static in the HTML and an absolute URL (and HTTP rather than HTTPS), so it's -not possible for this to be an option in config.json. If you'd like to change -it, you can build Element, but run -`RIOT_OG_IMAGE_URL="http://example.com/logo.png" yarn build`. -Alternatively, you can edit the `og:image` meta tag in `index.html` directly -each time you download a new version of Element. - -Identity servers -================ +2. `default_device_display_name`: Optional public name for devices created by login and registration, instead of the default + templated string. Note that this option does not support templating, currently. +3. `brand`: Optional name for the app. Defaults to `Element`. This is used throughout the application in various strings/locations. +4. `permalink_prefix`: An optional URL pointing to an Element Web deployment. For example, `https://app.element.io`. This will + change all permalinks (via the "Share" menus) to point at the Element Web deployment rather than `matrix.to`. +5. `desktop_builds`: Optional. Where the desktop builds for the application are, if available. This is explained in more detail + down below. +6. `mobile_builds`: Optional. Like `desktop_builds`, except for the mobile apps. Also described in more detail down below. +7. `mobile_guide_toast`: When `true` (default), users accessing the Element Web instance from a mobile device will be prompted to + download the app instead. +8. `update_base_url`: For the desktop app only, the URL where to acquire update packages. If specified, must be a path to a directory + containing `macos` and `win32` directories, with the update packages within. Defaults to `https://packages.element.io/desktop/update/` + in production. +9. `map_style_url`: Map tile server style URL for location sharing. e.g. `https://api.maptiler.com/maps/streets/style.json?key=YOUR_KEY_GOES_HERE` + This setting is ignored if your homeserver provides `/.well-known/matrix/client` in its well-known location, and the JSON file + at that location has a key `m.tile_server` (or the unstable version `org.matrix.msc3488.tile_server`). In this case, the + configuration found in the well-known location is used instead. +10. `welcome_user_id`: An optional user ID to start a DM with after creating an account. Defaults to nothing (no DM created). +11. `custom_translations_url`: An optional URL to allow overriding of translatable strings. The JSON file must be in a format of + `{"affected string": {"languageCode": "new string"}}`. See https://github.com/matrix-org/matrix-react-sdk/pull/7886 for details. +12. `branding`: Options for configuring various assets used within the app. Described in more detail down below. +13. `embedded_pages`: Further optional URLs for various assets used within the app. Described in more detail down below. +14. `disable_3pid_login`: When `false` (default), **enables** the options to log in with email address or phone number. Set to + `true` to hide these options. +15. `disable_login_language_selector`: When `false` (default), **enables** the language selector on the login pages. Set to `true` + to hide this dropdown. +16. `disable_guests`: When `false` (default), **enable** guest-related functionality (peeking/previewing rooms, etc) for unregistered + users. Set to `true` to disable this functionality. + +### `desktop_builds` and `mobile_builds` + +These two options describe the various availability for the application. When the app needs to promote an alternative download, +such as trying to get the user to use an Android app or the desktop app for encrypted search, the config options will be looked +at to see if the link should be to somewhere else. + +Starting with `desktop_builds`, the following subproperties are available: + +1. `available`: Required. When `true`, the desktop app can be downloaded from somewhere. +2. `logo`: Required. A URL to a logo (SVG), intended to be shown at 24x24 pixels. +3. `url`: Required. The download URL for the app. This is used as a hyperlink. + +When `desktop_builds` is not specified at all, the app will assume desktop downloads are available from https://element.io + +For `mobile_builds`, the following subproperties are available: + +1. `ios`: The URL for where to download the iOS app, such as an App Store link. When explicitly `null`, the app will assume the + iOS app cannot be downloaded. When not provided, the default Element app will be assumed available. +2. `android`: The same as `ios`, except for Android instead. +3. `fdroid`: The same as `android`, except for FDroid instead. + +Together, these two options might look like the following in your config: + +```json +{ + "desktop_builds": { + "available": true, + "logo": "https://example.org/assets/logo-small.svg", + "url": "https://example.org/not_element/download" + }, + "mobile_builds": { + "ios": null, + "android": "https://example.org/not_element/android", + "fdroid": "https://example.org/not_element/fdroid" + } +} +``` + +### `branding` and `embedded_pages` + +These two options point at various URLs for changing different internal pages (like the welcome page) and logos within the +application. + +Starting with `branding`, the following subproperties are available: + +1. `welcome_background_url`: When a string, the URL for the full-page image background of the login, registration, and welcome + pages. This property can additionally be an array to have the app choose an image at random from the selections. +2. `auth_header_logo_url`: A URL to the logo used on the login, registration, etc pages. +3. `auth_footer_links`: A list of links to add to the footer during login, registration, etc. Each entry must have a `text` and + `url` property. + +`embedded_pages` can be configured as such: + +1. `welcome_url`: A URL to an HTML page to show as a welcome page (landing on `#/welcome`). When not specified, the default + `welcome.html` that ships with Element will be used instead. +2. `home_url`: A URL to an HTML page to show within the app as the "home" page. When the app doesn't have a room/screen to + show the user, it will use the home page instead. The home page is additionally accessible from the user menu. By default, + no home page is set and therefore a hardcoded landing screen is used. +3. `login_for_welcome`: When `true` (default `false`), the app will use the login form as a welcome page instead of the welcome + page itself. This disables use of `welcome_url` and all welcome page functionality. + +Together, the options might look like this in your config: + +```json +{ + "branding": { + "welcome_background_url": "https://example.org/assets/background.jpg", + "auth_header_logo_url": "https://example.org/assets/logo.svg", + "auth_footer_links": [ + {"text": "FAQ", "url": "https://example.org/faq"}, + {"text": "Donate", "url": "https://example.org/donate"}, + ] + }, + "embedded_pages": { + "welcome_url": "https://example.org/assets/welcome.html", + "home_url": "https://example.org/assets/home.html" + } +} +``` + +Note that `index.html` also has an og:image meta tag that is set to an image hosted on element.io. This is the image used if +links to your copy of Element appear in some websites like Facebook, and indeed Element itself. This has to be static in the HTML +and an absolute URL (and HTTP rather than HTTPS), so it's not possible for this to be an option in config.json. If you'd like to +change it, you can build Element, but run `RIOT_OG_IMAGE_URL="http://example.com/logo.png" yarn build`. Alternatively, you can edit +the `og:image` meta tag in `index.html` directly each time you download a new version of Element. + +## SSO setup + +When Element is deployed alongside a homeserver with SSO-only login, some options to ease the user experience might want to be set: + +1. `logout_redirect_url`: Optional URL to redirect the user to after they have logged out. Some SSO systems support a page that the + user can be sent to in order to log them out of that system too, making logout symmetric between Element and the SSO system. +2. `sso_redirect_options`: Options to define how to handle unauthenticated users. If the object contains `"immediate": true`, then + all unauthenticated users will be automatically redirected to the SSO system to start their login. If instead you'd only like to + have users which land on the welcome page to be redirected, use `"on_welcome_page": true`. As an example: + ```json + { + "sso_redirect_options": { + "immediate": false, + "on_welcome_page": true + } + } + ``` + It is most common to use the `immediate` flag instead of `on_welcome_page`. + +## VoIP / Jitsi calls + +Currently, Element uses Jitsi to offer conference calls in rooms. A set of defaults are applied, pointing at our Jitsi instance, +to ensure conference calling works, however you can point Element at your own Jitsi if you prefer. + +More information about the Jitsi setup can be found [here](./jitsi.md). + +The VoIP and Jitsi options are: + +1. `jitsi`: Optional configuration for how to start Jitsi conferences. Currently can only contain a single `preferred_domain` + value which points at the domain of the Jitsi instance. Defaults to `meet.jit.si`. This is *not* used if the Jitsi widget + was created by an integration manager, or if the homeserver provides Jitsi information in `/.well-known/matrix/client`. For + example: + ```json + { + "jitsi": { + "preferred_domain": "meet.jit.si" + } + } + ``` +2. `jitsi_widget`: Optional configuration for the built-in Jitsi widget. Currently can only contain a single `skip_built_in_welcome_screen` + value, denoting whether the "Join Conference" button should be shown. When `true` (default `false`), Jitsi calls will skip to + the call instead of having a screen with a single button on it. This is most useful if the Jitsi instance being used already + has a landing page for users to test audio and video before joining the call, otherwise users will automatically join the call. + For example: + ```json + { + "jitsi_widget": { + "skip_built_in_welcome_screen": true + } + } + ``` +3. `voip`: Optional configuration for various VoIP features. Currently can only contain a single `obey_asserted_identity` value to + send MSC3086-style asserted identity messages during VoIP calls in the room corresponding to the asserted identity. This *must* + only be set in trusted environments. The option defaults to `false`. For example: + ```json + { + "voip": { + "obey_asserted_identity": false + } + } + ``` +4. `widget_build_url`: Optional URL to have Element make a request to when a user presses the voice/video call buttons in the app, + if a call would normally be started by the action. The URL will be called with a `roomId` query parameter to identify the room + being called in. The URL must respond with a JSON object similar to the following: + ```json + { + "widget_id": "$arbitrary_string", + "widget": { + "creatorUserId": "@user:example.org", + "id": "$the_same_widget_id", + "type": "m.custom", + "waitForIframeLoad": true, + "name": "My Widget Name Here", + "avatar_url": "mxc://example.org/abc123", + "url": "https://example.org/widget.html", + "data": { + "title": "Subtitle goes here" + } + }, + "layout": { + "container": "top", + "index": 0, + "width": 65, + "height": 50 + } + } + ``` + The `widget` is the `content` of a normal widget state event. The `layout` is the layout specifier for the widget being created, + as defined by the `io.element.widgets.layout` state event. +5. `audio_stream_url`: Optional URL to pass to Jitsi to enable live streaming. This option is considered experimental and may be removed + at any time without notice. + +## Bug reporting + +If you run your own rageshake server to collect bug reports, the following options may be of interest: + +1. `bug_report_endpoint_url`: URL for where to submit rageshake logs to. Rageshakes include feedback submissions and bug reports. When + not present in the config, the app will disable all rageshake functionality. Set to `https://element.io/bugreports/submit` to submit + rageshakes to us, or use your own rageshake server. +2. `uisi_autorageshake_app`: If a user has enabled the "automatically send debug logs on decryption errors" flag, this option will be sent + alongside the rageshake so the rageshake server can filter them by app name. By default, this will be `element-web`, as with any other + rageshake submitted by the app. + + If you are using the element.io rageshake server, please set this to `element-auto-uisi` so we can better filter them. + +If you would like to use [Sentry](https://sentry.io/) for rageshake data, add a `sentry` object to your config with the following values: + +1. `dsn`: The Sentry [DSN](https://docs.sentry.io/product/sentry-basics/dsn-explainer/). +2. `environment`: Optional [environment](https://docs.sentry.io/product/sentry-basics/environments/) to pass to Sentry. + +For example: + +```json +{ + "sentry": { + "dsn": "dsn-goes-here", + "environment": "production" + } +} +``` + +## Integration managers + +Integration managers are embedded applications within Element to help the user configure bots, bridges, and widgets. An integration manager +is a separate piece of software not typically available with your homeserver. To disable integrations, leave the options defined here out of +your config. + +1. `integrations_ui_url`: The UI URL for the integration manager. +2. `integrations_rest_url`: The REST interface URL for the integration manager. +3. `integrations_widgets_urls`: A list of URLs the integration manager uses to host widgets. + +If you would like to use Scalar, the integration manager maintained by Element, the following options would apply: + +```json +{ + "integrations_ui_url": "https://scalar.vector.im/", + "integrations_rest_url": "https://scalar.vector.im/api", + "integrations_widgets_urls": [ + "https://scalar.vector.im/_matrix/integrations/v1", + "https://scalar.vector.im/api", + "https://scalar-staging.vector.im/_matrix/integrations/v1", + "https://scalar-staging.vector.im/api", + "https://scalar-staging.riot.im/scalar/api" + ] +} +``` + +## Administrative options + +If you would like to include a custom message when someone is reporting an event, set the following Markdown-capable field: + +```json +{ + "report_event": { + "admin_message_md": "Please be sure to review our [terms of service](https://example.org/terms) before reporting a message." + } +} +``` + +To add additional "terms and conditions" links throughout the app, use the following template: + +```json +{ + "terms_and_conditions_links": [ + { "text": "Code of conduct", "url": "https://example.org/code-of-conduct" } + ] +} +``` + +## Analytics + +Analytics are currently possible with two systems: `posthog` (preferred) and `piwik` (matomo; deprecated). When +these configuration options are not present, analytics are deemed impossible and the user won't be asked to opt-in to the +system. + +To configure [Posthog](https://posthog.com/), add the following under `posthog` in your config: + +1. `api_host`: The hostname of the posthog server. +2. `project_api_key`: The API key from posthog. + +To configure Piwik (***DEPRECATED***), add the following under `piwik` in your config: + +1. `url`: The URL of the piwik server. +2. `site_id`: The site ID to use. +3. `policy_url`: URL to the analytics collection policy. +4. `whitelisted_hs_urls`: A list of homeserver client-server URLs to *not* redact from analytics. + +Additionally, you may set `"piwik": false` to disable piwik configuration too. An `analytics_owner` can also be specified in your +config to replace the company name used in dialogs talking about analytics - this defaults to `brand`, and is useful when the +provider of analytics is different from the provider of the Element instance. + +## Server hosting links + +If you would like to encourage matrix.org users to sign up for a service like [Element Matrix Services](https://element.io/matrix-services/server-hosting), +the following configuration options can be set. Note that if the options are missing from the configuration then the hosting prompts +will not be shown to the user. + +1. `hosting_signup_link`: Optional URL to link the user to when talking about "Upgrading your account". Will contain a query parameter + of `utm_campaign` to denote which link the user clicked on within the app. Only ever applies to matrix.org users specifically. +2. `host_signup`: Optional configuration for an account importer to your hosting platform. The API surface of this is not documented + at the moment, but can be configured with the following subproperties: + 1. `brand`: The brand name to use. + 2. `url`: The iframe URL for the importer. + 3. `domains`: The homeserver domains to show the importer to. + 4. `cookie_policy_url`: The URL to the cookie policy for the importer. + 5. `privacy_policy_url`: The URL to the privacy policy for the importer. + 6. `terms_of_service_url`: The URL to the terms of service for the importer. + +If you're looking to mirror a setup from our production/development environments, the following config should be used: + +```json +{ + "hosting_signup_link": "https://element.io/matrix-services?utm_source=element-web&utm_medium=web", + "host_signup": { + "brand": "Element Home", + "domains": [ "matrix.org" ], + "url": "https://ems.element.io/element-home/in-app-loader", + "cookie_policy_url": "https://element.io/cookie-policy", + "privacy_policy_url": "https://element.io/privacy", + "terms_of_service_url": "https://element.io/terms-of-service" + } +} +``` + +## Miscellaneous + +Element supports other options which don't quite fit into other sections of this document. + +To configure whether presence UI is shown for a given homeserver, set `enable_presence_by_hs_url`. It is recommended to +set this value to the following at a minimum: + +```json +{ + "enable_presence_by_hs_url": { + "https://matrix.org": false, + "https://matrix-client.matrix.org": false + } +} +``` + +## Identity servers The identity server is used for inviting other users to a room via third party identifiers like emails and phone numbers. It is not used to store your password @@ -234,16 +489,14 @@ Currently, the only two public identity servers are https://vector.im and https://matrix.org, however in the future identity servers will be decentralised. -Desktop app configuration -========================= +## Desktop app configuration See https://github.com/vector-im/element-desktop#user-specified-configjson -UI Features -=========== +## UI Features Parts of the UI can be disabled using UI features. These are settings which appear -under `settingDefaults` and can only be `true` (default) or `false`. When `false`, +under `setting_defaults` and can only be `true` (default) or `false`. When `false`, parts of the UI relating to that feature will be disabled regardless of the user's preferences. @@ -279,4 +532,14 @@ Currently, the following UI feature flags are supported: user. * `UIFeature.roomHistorySettings` - Whether or not the room history settings are shown to the user. This should only be used if the room history visibility options are managed by the server. -* `UIFeature.TimelineEnableRelativeDates` - Display relative date separators (eg: 'Today', 'Yesterday') in the timeline for recent messages. When false day dates will be used. +* `UIFeature.TimelineEnableRelativeDates` - Display relative date separators (eg: 'Today', 'Yesterday') in the + timeline for recent messages. When false day dates will be used. + +## Undocumented / developer options + +The following are undocumented or intended for developer use only. + +1. `fallback_hs_url` +2. `sync_timeline_limit` +3. `dangerously_allow_unsafe_and_insecure_passwords` +4. `latex_maths_delims` diff --git a/docs/kubernetes.md b/docs/kubernetes.md index c318b231c43..58fd9d75a51 100644 --- a/docs/kubernetes.md +++ b/docs/kubernetes.md @@ -61,13 +61,11 @@ Then you can deploy it to your cluster with something like `kubectl apply -f my- ], "bug_report_endpoint_url": "https://element.io/bugreports/submit", "defaultCountryCode": "GB", - "showLabsSettings": false, - "features": { - "feature_new_spinner": false - }, + "show_labs_settings": false, + "features": { }, "default_federate": true, "default_theme": "light", - "roomDirectory": { + "room_directory": { "servers": [ "matrix.org" ] @@ -82,11 +80,11 @@ Then you can deploy it to your cluster with something like `kubectl apply -f my- "https://matrix.org": false, "https://matrix-client.matrix.org": false }, - "settingDefaults": { + "setting_defaults": { "breadcrumbs": true }, "jitsi": { - "preferredDomain": "meet.element.io" + "preferred_domain": "meet.element.io" } } diff --git a/docs/theming.md b/docs/theming.md index b911e3d3336..8965a925806 100644 --- a/docs/theming.md +++ b/docs/theming.md @@ -36,7 +36,7 @@ default theme, you would use `default_theme: "custom-Electric Blue"`. eg. in config.json: ``` -"settingDefaults": { +"setting_defaults": { "custom_themes": [ { "name": "Electric Blue", diff --git a/package.json b/package.json index e8283af0903..171c4a55ba7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "element-web", - "version": "1.10.7", + "version": "1.10.8", "description": "A feature-rich client for Matrix.org", "author": "New Vector Ltd.", "repository": { @@ -60,8 +60,8 @@ "gfm.css": "^1.1.2", "jsrsasign": "^10.2.0", "katex": "^0.12.0", - "matrix-js-sdk": "16.0.0", - "matrix-react-sdk": "3.42.0", + "matrix-js-sdk": "16.0.1", + "matrix-react-sdk": "3.42.1", "matrix-widget-api": "^0.1.0-beta.18", "prop-types": "^15.7.2", "react": "17.0.2", diff --git a/src/async-components/structures/CompatibilityView.tsx b/src/async-components/structures/CompatibilityView.tsx index ca9dbdcb32d..4d31e2d6661 100644 --- a/src/async-components/structures/CompatibilityView.tsx +++ b/src/async-components/structures/CompatibilityView.tsx @@ -27,7 +27,8 @@ interface IProps { } const CompatibilityView: React.FC = ({ onAccept }) => { - const { brand, mobileBuilds } = SdkConfig.get(); + const brand = SdkConfig.get("brand"); + const mobileBuilds = SdkConfig.get("mobile_builds"); let ios = null; const iosCustomUrl = mobileBuilds?.ios; diff --git a/src/components/views/auth/VectorAuthFooter.tsx b/src/components/views/auth/VectorAuthFooter.tsx index 79085bc7843..228e7949cae 100644 --- a/src/components/views/auth/VectorAuthFooter.tsx +++ b/src/components/views/auth/VectorAuthFooter.tsx @@ -20,18 +20,14 @@ import SdkConfig from 'matrix-react-sdk/src/SdkConfig'; import { _t } from 'matrix-react-sdk/src/languageHandler'; const VectorAuthFooter = () => { - const brandingConfig = SdkConfig.get().branding; - let links = [ - //{ "text": "Blog", "url": "https://element.io/blog" }, - //{ "text": "Twitter", "url": "https://twitter.com/element_hq" }, + const brandingConfig = SdkConfig.getObject("branding"); + const links = brandingConfig?.get("auth_footer_links") ?? [ + // { "text": "Blog", "url": "https://element.io/blog" }, + // { "text": "Twitter", "url": "https://twitter.com/element_hq" }, { "text": "About", "url": "https://schildi.chat" }, { "text": "GitHub", "url": "https://github.com/SchildiChat/schildichat-desktop" }, ]; - if (brandingConfig && brandingConfig.authFooterLinks) { - links = brandingConfig.authFooterLinks; - } - const authFooterLinks = []; for (const linkEntry of links) { authFooterLinks.push( diff --git a/src/components/views/auth/VectorAuthHeaderLogo.tsx b/src/components/views/auth/VectorAuthHeaderLogo.tsx index 8f6b75ba9b3..d615d92d67b 100644 --- a/src/components/views/auth/VectorAuthHeaderLogo.tsx +++ b/src/components/views/auth/VectorAuthHeaderLogo.tsx @@ -22,11 +22,8 @@ export default class VectorAuthHeaderLogo extends React.PureComponent { static replaces = 'AuthHeaderLogo'; render() { - const brandingConfig = SdkConfig.get().branding; - let logoUrl = "themes/element/img/logos/element-logo.svg"; - if (brandingConfig && brandingConfig.authHeaderLogoUrl) { - logoUrl = brandingConfig.authHeaderLogoUrl; - } + const brandingConfig = SdkConfig.getObject("branding"); + const logoUrl = brandingConfig?.get("auth_header_logo_url") ?? "themes/element/img/logos/element-logo.svg"; return (
diff --git a/src/components/views/auth/VectorAuthPage.tsx b/src/components/views/auth/VectorAuthPage.tsx index 787f6fe32c7..119f309734a 100644 --- a/src/components/views/auth/VectorAuthPage.tsx +++ b/src/components/views/auth/VectorAuthPage.tsx @@ -27,14 +27,16 @@ export default class VectorAuthPage extends React.PureComponent { static getWelcomeBackgroundUrl() { if (VectorAuthPage.welcomeBackgroundUrl) return VectorAuthPage.welcomeBackgroundUrl; - const brandingConfig = SdkConfig.get().branding; + const brandingConfig = SdkConfig.getObject("branding"); VectorAuthPage.welcomeBackgroundUrl = "themes/element/img/backgrounds/ocean.jpg"; - if (brandingConfig && brandingConfig.welcomeBackgroundUrl) { - if (Array.isArray(brandingConfig.welcomeBackgroundUrl)) { - const index = Math.floor(Math.random() * brandingConfig.welcomeBackgroundUrl.length); - VectorAuthPage.welcomeBackgroundUrl = brandingConfig.welcomeBackgroundUrl[index]; + + const configuredUrl = brandingConfig?.get("welcome_background_url"); + if (configuredUrl) { + if (Array.isArray(configuredUrl)) { + const index = Math.floor(Math.random() * configuredUrl.length); + VectorAuthPage.welcomeBackgroundUrl = configuredUrl[index]; } else { - VectorAuthPage.welcomeBackgroundUrl = brandingConfig.welcomeBackgroundUrl; + VectorAuthPage.welcomeBackgroundUrl = configuredUrl; } } diff --git a/src/i18n/strings/bs.json b/src/i18n/strings/bs.json index a423a49f756..530e489943e 100644 --- a/src/i18n/strings/bs.json +++ b/src/i18n/strings/bs.json @@ -31,5 +31,6 @@ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Decentralizirani, šifrirani razgovor & suradnja pokrenuta [matrix]", "Sign In": "Prijavite se", "Create Account": "Otvori račun", - "Explore rooms": "Istražite sobe" + "Explore rooms": "Istražite sobe", + "Use %(brand)s on mobile": "Koristi %(brand)s na mobitelu" } diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index 37512ae3e38..dde11cd0509 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -10,14 +10,14 @@ "Sign In": "サインイン", "Create Account": "アカウントを作成", "Explore rooms": "ルームを探索", - "The message from the parser is: %(message)s": "パーザーのメッセージ:%(message)s", + "The message from the parser is: %(message)s": "パーサーのメッセージ:%(message)s", "Invalid JSON": "不正なJSON", "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "不正な設定:default_server_config、default_server_name、またはdefault_hs_urlのいずれか一つのみを指定できます。", "Please install Chrome, Firefox, or Safari for the best experience.": "最高のユーザー体験を得るためには、ChromeFirefox、もしくはSafariをインストールしてください。", "You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.": "現在のブラウザーを使い続けることもできますが、いくつか(もしくは全ての)機能が動作しなかったり、外観が崩れたりする可能性があります。", "I understand the risks and wish to continue": "リスクを理解して続行", "Missing indexeddb worker script!": "IndexedDBのワーカースクリプトがありません!", - "Unable to load config file: please refresh the page to try again.": "設定ファイルの読み込みに失敗しました:ページを再読み込みしてもう一度お試しください。", + "Unable to load config file: please refresh the page to try again.": "設定ファイルの読み込みに失敗しました:ページを再読み込みして、もう一度やり直してください。", "Download Completed": "ダウンロードが完了しました", "Open": "開く", "Open user settings": "ユーザー設定を開く", diff --git a/src/vector/app.tsx b/src/vector/app.tsx index e92ad90136a..7a3abc0c175 100644 --- a/src/vector/app.tsx +++ b/src/vector/app.tsx @@ -26,73 +26,23 @@ import AutoDiscoveryUtils from 'matrix-react-sdk/src/utils/AutoDiscoveryUtils'; import { AutoDiscovery } from "matrix-js-sdk/src/autodiscovery"; import * as Lifecycle from "matrix-react-sdk/src/Lifecycle"; import SdkConfig, { parseSsoRedirectOptions } from "matrix-react-sdk/src/SdkConfig"; +import { IConfigOptions } from "matrix-react-sdk/src/IConfigOptions"; import { logger } from "matrix-js-sdk/src/logger"; import { createClient } from "matrix-js-sdk/src/matrix"; +import { SnakedObject } from "matrix-react-sdk/src/utils/SnakedObject"; -import type MatrixChatType from "matrix-react-sdk/src/components/structures/MatrixChat"; -import { parseQs, parseQsFromFragment } from './url_utils'; +import { parseQs } from './url_utils'; import VectorBasePlatform from "./platform/VectorBasePlatform"; +import { getScreenFromLocation, init as initRouting, onNewScreen } from "./routing"; // add React and ReactPerf to the global namespace, to make them easier to access via the console // this incidentally means we can forget our React imports in JSX files without penalty. window.React = React; -let lastLocationHashSet: string = null; - logger.log(`Application is running in ${process.env.NODE_ENV} mode`); window.matrixLogger = logger; -// Parse the given window.location and return parameters that can be used when calling -// MatrixChat.showScreen(screen, params) -function getScreenFromLocation(location: Location) { - const fragparts = parseQsFromFragment(location); - return { - screen: fragparts.location.substring(1), - params: fragparts.params, - }; -} - -// Here, we do some crude URL analysis to allow -// deep-linking. -function routeUrl(location: Location) { - if (!window.matrixChat) return; - - logger.log("Routing URL ", location.href); - const s = getScreenFromLocation(location); - (window.matrixChat as MatrixChatType).showScreen(s.screen, s.params); -} - -function onHashChange(ev: HashChangeEvent) { - if (decodeURIComponent(window.location.hash) === lastLocationHashSet) { - // we just set this: no need to route it! - return; - } - routeUrl(window.location); -} - -// This will be called whenever the SDK changes screens, -// so a web page can update the URL bar appropriately. -function onNewScreen(screen: string, replaceLast = false) { - logger.log("newscreen " + screen); - const hash = '#/' + screen; - lastLocationHashSet = hash; - - // if the new hash is a substring of the old one then we are stripping fields e.g `via` so replace history - if (screen.startsWith("room/") && - window.location.hash.includes("/$") === hash.includes("/$") && // only if both did or didn't contain event link - window.location.hash.startsWith(hash) - ) { - replaceLast = true; - } - - if (replaceLast) { - window.location.replace(hash); - } else { - window.location.assign(hash); - } -} - // We use this to work out what URL the SDK should // pass through when registering to allow the user to // click back to the client having registered. @@ -141,8 +91,7 @@ function onTokenLoginCompleted() { } export async function loadApp(fragParams: {}) { - window.addEventListener('hashchange', onHashChange); - + initRouting(); const platform = PlatformPeg.get(); const params = parseQs(window.location); @@ -154,6 +103,7 @@ export async function loadApp(fragParams: {}) { // Don't bother loading the app until the config is verified const config = await verifyServerConfig(); + const snakedConfig = new SnakedObject(config); // Before we continue, let's see if we're supposed to do an SSO redirect const [userId] = await Lifecycle.getStoredSessionOwner(); @@ -169,8 +119,8 @@ export async function loadApp(fragParams: {}) { if (!hasPossibleToken && !isReturningFromSso && autoRedirect) { logger.log("Bypassing app load to redirect to SSO"); const tempCli = createClient({ - baseUrl: config['validated_server_config'].hsUrl, - idBaseUrl: config['validated_server_config'].isUrl, + baseUrl: config.validated_server_config.hsUrl, + idBaseUrl: config.validated_server_config.isUrl, }); PlatformPeg.get().startSingleSignOn(tempCli, "sso", `/${getScreenFromLocation(window.location).screen}`); @@ -180,7 +130,8 @@ export async function loadApp(fragParams: {}) { return; } - const defaultDeviceName = config['defaultDeviceDisplayName'] ?? platform.getDefaultDeviceDisplayName(); + const defaultDeviceName = snakedConfig.get("default_device_display_name") + ?? platform.getDefaultDeviceDisplayName(); const MatrixChat = sdk.getComponent('structures.MatrixChat'); return { if (relativeLocation !== '' && !relativeLocation.endsWith('/')) relativeLocation += '/'; const specificConfigPromise = getConfig(`${relativeLocation}config.${document.domain}.json`); @@ -30,9 +32,9 @@ export async function getVectorConfig(relativeLocation='') { if (Object.keys(configJson).length === 0) { throw new Error(); // throw to enter the catch } - return configJson; + return configJson as IConfigOptions; } catch (e) { - return await generalConfigPromise; + return await generalConfigPromise as IConfigOptions; } } diff --git a/src/vector/init.tsx b/src/vector/init.tsx index ba5dd1a759a..e810d6c8268 100644 --- a/src/vector/init.tsx +++ b/src/vector/init.tsx @@ -63,7 +63,12 @@ export async function loadConfig() { // granular settings are loaded correctly and to avoid duplicating the override logic for the theme. // // Note: this isn't called twice for some wrappers, like the Jitsi wrapper. - SdkConfig.put(await PlatformPeg.get().getConfig() || {}); + const platformConfig = await PlatformPeg.get().getConfig(); + if (platformConfig) { + SdkConfig.put(platformConfig); + } else { + SdkConfig.unset(); // clears the config (sets to empty object) + } } export function loadOlm(): Promise { diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 155501ca31f..c6783d5a6ba 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -23,6 +23,8 @@ import { } from "matrix-widget-api"; import { ElementWidgetActions } from "matrix-react-sdk/src/stores/widgets/ElementWidgetActions"; import { logger } from "matrix-js-sdk/src/logger"; +import { IConfigOptions } from "matrix-react-sdk/src/IConfigOptions"; +import { SnakedObject } from "matrix-react-sdk/src/utils/SnakedObject"; import { getVectorConfig } from "../getconfig"; @@ -118,8 +120,10 @@ let skipOurWelcomeScreen = false; startAudioOnly = qsParam('isAudioOnly', true) === "true"; // We've reached the point where we have to wait for the config, so do that then parse it. - const instanceConfig = await configPromise; - skipOurWelcomeScreen = instanceConfig?.['jitsiWidget']?.['skipBuiltInWelcomeScreen'] || false; + const instanceConfig = new SnakedObject((await configPromise) ?? {}); + const jitsiConfig = instanceConfig.get("jitsi_widget") ?? {}; + skipOurWelcomeScreen = (new SnakedObject(jitsiConfig)) + .get("skip_built_in_welcome_screen") || false; // If we're meant to skip our screen, skip to the part where we show Jitsi instead of us. // We don't set up the call yet though as this might lead to failure without the widget API. diff --git a/src/vector/platform/ElectronPlatform.tsx b/src/vector/platform/ElectronPlatform.tsx index b5f5df79122..92ef511eb2b 100644 --- a/src/vector/platform/ElectronPlatform.tsx +++ b/src/vector/platform/ElectronPlatform.tsx @@ -28,6 +28,7 @@ import BaseEventIndexManager, { import dis from 'matrix-react-sdk/src/dispatcher/dispatcher'; import { _t } from 'matrix-react-sdk/src/languageHandler'; import SdkConfig from 'matrix-react-sdk/src/SdkConfig'; +import { IConfigOptions } from "matrix-react-sdk/src/IConfigOptions"; import * as rageshake from 'matrix-react-sdk/src/rageshake/rageshake'; import { MatrixClient } from "matrix-js-sdk/src/client"; import { Room } from "matrix-js-sdk/src/models/room"; @@ -280,7 +281,7 @@ export default class ElectronPlatform extends VectorBasePlatform { this.ipcCall("startSSOFlow", this.ssoID); } - async getConfig(): Promise<{}> { + async getConfig(): Promise { return this.ipcCall('getConfig'); } diff --git a/src/vector/platform/VectorBasePlatform.ts b/src/vector/platform/VectorBasePlatform.ts index d06fbbb17c8..382fd626040 100644 --- a/src/vector/platform/VectorBasePlatform.ts +++ b/src/vector/platform/VectorBasePlatform.ts @@ -20,6 +20,7 @@ limitations under the License. import BasePlatform from 'matrix-react-sdk/src/BasePlatform'; import { _t } from 'matrix-react-sdk/src/languageHandler'; +import type { IConfigOptions } from "matrix-react-sdk/src/IConfigOptions"; import { getVectorConfig } from "../getconfig"; import Favicon from "../../favicon"; @@ -29,7 +30,7 @@ import Favicon from "../../favicon"; export default abstract class VectorBasePlatform extends BasePlatform { protected _favicon: Favicon; - async getConfig(): Promise<{}> { + async getConfig(): Promise { return getVectorConfig(); } diff --git a/src/vector/platform/WebPlatform.ts b/src/vector/platform/WebPlatform.ts index 52401b5a551..6b1d1798574 100644 --- a/src/vector/platform/WebPlatform.ts +++ b/src/vector/platform/WebPlatform.ts @@ -28,6 +28,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import VectorBasePlatform from './VectorBasePlatform'; import { parseQs } from "../url_utils"; +import { reloadPage } from "../routing"; const POKE_RATE_MS = 10 * 60 * 1000; // 10 min @@ -128,9 +129,11 @@ export default class WebPlatform extends VectorBasePlatform { // // Ideally, loading an old copy would be impossible with the // cache-control: nocache HTTP header set, but Firefox doesn't always obey it :/ + console.log("startUpdater, current version is " + this.getNormalizedAppVersion(process.env.VERSION)); this.pollForUpdate((version: string, newVersion: string) => { const query = parseQs(location); if (query.updated === "1") { + console.log("Update reloaded but still on an old version, stopping"); // We just reloaded already and are still on the old version! // Show the toast rather than reload in a loop. showUpdateToast(version, newVersion); @@ -146,8 +149,7 @@ export default class WebPlatform extends VectorBasePlatform { suffix = "&" + suffix; } - // This line has the effect of loading the page at the new location - window.location.href = window.location.href + suffix; + reloadPage(window.location.href + suffix); }); setInterval(() => this.pollForUpdate(showUpdateToast, hideUpdateToast), POKE_RATE_MS); } @@ -165,10 +167,14 @@ export default class WebPlatform extends VectorBasePlatform { if (currentVersion !== mostRecentVersion) { if (this.shouldShowUpdate(mostRecentVersion)) { + console.log("Update available to " + mostRecentVersion + ", will notify user"); showUpdate(currentVersion, mostRecentVersion); + } else { + console.log("Update available to " + mostRecentVersion + " but won't be shown"); } return { status: UpdateCheckStatus.Ready }; } else { + console.log("No update available, already on " + mostRecentVersion); showNoUpdate?.(); } diff --git a/src/vector/routing.ts b/src/vector/routing.ts new file mode 100644 index 00000000000..07babd6a77f --- /dev/null +++ b/src/vector/routing.ts @@ -0,0 +1,83 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Parse the given window.location and return parameters that can be used when calling +// MatrixChat.showScreen(screen, params) +import { logger } from "matrix-js-sdk/src/logger"; +import MatrixChatType from "matrix-react-sdk/src/components/structures/MatrixChat"; + +import { parseQsFromFragment } from "./url_utils"; + +let lastLocationHashSet: string = null; + +export function getScreenFromLocation(location: Location) { + const fragparts = parseQsFromFragment(location); + return { + screen: fragparts.location.substring(1), + params: fragparts.params, + }; +} + +// Here, we do some crude URL analysis to allow +// deep-linking. +function routeUrl(location: Location) { + if (!window.matrixChat) return; + + logger.log("Routing URL ", location.href); + const s = getScreenFromLocation(location); + (window.matrixChat as MatrixChatType).showScreen(s.screen, s.params); +} + +function onHashChange(ev: HashChangeEvent) { + if (decodeURIComponent(window.location.hash) === lastLocationHashSet) { + // we just set this: no need to route it! + return; + } + routeUrl(window.location); +} + +// This will be called whenever the SDK changes screens, +// so a web page can update the URL bar appropriately. +export function onNewScreen(screen: string, replaceLast = false) { + logger.log("newscreen " + screen); + const hash = '#/' + screen; + lastLocationHashSet = hash; + + // if the new hash is a substring of the old one then we are stripping fields e.g `via` so replace history + if (screen.startsWith("room/") && + window.location.hash.includes("/$") === hash.includes("/$") && // only if both did or didn't contain event link + window.location.hash.startsWith(hash) + ) { + replaceLast = true; + } + + if (replaceLast) { + window.location.replace(hash); + } else { + window.location.assign(hash); + } +} + +// reload the page to a different url +export function reloadPage(newUrl: string) { + console.log("reloadPage to " + newUrl); + window.removeEventListener('hashchange', onHashChange); + window.location.href = newUrl; +} + +export function init() { + window.addEventListener('hashchange', onHashChange); +} diff --git a/test/app-tests/joining-test.tsx b/test/app-tests/joining-test.tsx index 23f956f2d46..1ea411fec1e 100644 --- a/test/app-tests/joining-test.tsx +++ b/test/app-tests/joining-test.tsx @@ -77,7 +77,6 @@ describe('joining a room', function() { const ROOM_ALIAS = '#alias:localhost'; const ROOM_ID = '!id:localhost'; - httpBackend.when('GET', '/capabilities').respond(200, { capabilities : {} }); httpBackend.when('GET', '/pushrules').respond(200, {}); httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' }); diff --git a/test/app-tests/loading-test.tsx b/test/app-tests/loading-test.tsx index e86c83759f1..068164dcee3 100644 --- a/test/app-tests/loading-test.tsx +++ b/test/app-tests/loading-test.tsx @@ -168,15 +168,15 @@ describe('loading:', function() { // returns a promise resolving to the received request async function expectAndAwaitSync(opts?) { let syncRequest = null; + httpBackend.when('GET', '/_matrix/client/versions') + .respond(200, { + "versions": ["r0.3.0"], + "unstable_features": { + "m.lazy_load_members": true + } + }); const isGuest = opts && opts.isGuest; if (!isGuest) { - httpBackend.when('GET', '/_matrix/client/versions') - .respond(200, { - "versions": ["r0.3.0"], - "unstable_features": { - "m.lazy_load_members": true - } - }); // the call to create the LL filter httpBackend.when('POST', '/filter').respond(200, { filter_id: 'llfid' }); } @@ -313,7 +313,6 @@ describe('loading:', function() { }); it('shows the last known room by default', function() { - httpBackend.when('GET', '/capabilities').respond(200, { capabilities: {} }); httpBackend.when('GET', '/pushrules').respond(200, {}); loadApp(); @@ -333,7 +332,6 @@ describe('loading:', function() { it('shows a home page by default if we have no joined rooms', function() { localStorage.removeItem("mx_last_room_id"); - httpBackend.when('GET', '/capabilities').respond(200, { capabilities : {} }); httpBackend.when('GET', '/pushrules').respond(200, {}); loadApp(); @@ -351,7 +349,6 @@ describe('loading:', function() { }); it('shows a room view if we followed a room link', function() { - httpBackend.when('GET', '/capabilities').respond(200, { capabilities : {} }); httpBackend.when('GET', '/pushrules').respond(200, {}); loadApp({ @@ -425,7 +422,6 @@ describe('loading:', function() { describe('Guest auto-registration:', function() { it('shows a welcome page by default', function() { - httpBackend.when('GET', '/capabilities').respond(200, { capabilities: {} }); loadApp(); @@ -457,7 +453,6 @@ describe('loading:', function() { }); it('uses the default homeserver to register with', function() { - httpBackend.when('GET', '/capabilities').respond(200, { capabilities: {} }); loadApp(); @@ -493,7 +488,6 @@ describe('loading:', function() { }); it('shows a room view if we followed a room link', function() { - httpBackend.when('GET', '/capabilities').respond(200, { capabilities: {} }); loadApp({ uriFragment: "#/room/!room:id", @@ -526,7 +520,6 @@ describe('loading:', function() { describe('Login as user', function() { beforeEach(function() { - httpBackend.when('GET', '/capabilities').respond(200, { capabilities: {} }); // first we have to load the homepage loadApp(); @@ -674,7 +667,6 @@ describe('loading:', function() { // Wait for another trip around the event loop for the UI to update return sleep(1); }).then(() => { - httpBackend.when('GET', '/capabilities').respond(200, { capabilities : {} }); httpBackend.when('GET', '/pushrules').respond(200, {}); return expectAndAwaitSync().catch((e) => { throw new Error("Never got /sync after login: did the client start?"); diff --git a/tsconfig.json b/tsconfig.json index 0e02b25bb13..b0a58196f57 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,7 @@ "moduleResolution": "node", "target": "es2016", "noImplicitAny": false, + "noUnusedLocals": true, "sourceMap": false, "outDir": "./lib", "declaration": true, diff --git a/yarn.lock b/yarn.lock index 2d09de48eb5..8c72f754324 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8220,10 +8220,10 @@ matrix-events-sdk@^0.0.1-beta.7: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1-beta.7.tgz#5ffe45eba1f67cc8d7c2377736c728b322524934" integrity sha512-9jl4wtWanUFSy2sr2lCjErN/oC8KTAtaeaozJtrgot1JiQcEI4Rda9OLgQ7nLKaqb4Z/QUx/fR3XpDzm5Jy1JA== -matrix-js-sdk@16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-16.0.0.tgz#0eba446a7d17f0c0bf8880f11e1e46f897408984" - integrity sha512-ZlrRjqo493pY6OwtQto+oNG2tFALbJKHUtIHUbay0eX100jQjbgMzXtWHrrFEU01+/aAccx+UP4ap0/MRcsALQ== +matrix-js-sdk@16.0.1: + version "16.0.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-16.0.1.tgz#9b389ef16677ba648efad2929a7802af6f1dc81f" + integrity sha512-GRYZY7JZRqsVFa2nKO2qJbU4gQail2+1PgX2QDcibWizTL5Gh8YS384twprpIKqzdLHJ3d7H7A0L+uqc562ZsQ== dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" @@ -8245,10 +8245,10 @@ matrix-mock-request@^1.2.3: bluebird "^3.5.0" expect "^1.20.2" -matrix-react-sdk@3.42.0: - version "3.42.0" - resolved "https://registry.yarnpkg.com/matrix-react-sdk/-/matrix-react-sdk-3.42.0.tgz#acdcbc25044fa65525639a68d0af3b857ba39bcb" - integrity sha512-QPFhGzDsy+UcSBpnoTeDSQpkCdtDUCplQ6NPuTRz35jfaaQOk9yPrzcT2EoHNlXnt9EiQ93r9yor1BG0ztq2gA== +matrix-react-sdk@3.42.1: + version "3.42.1" + resolved "https://registry.yarnpkg.com/matrix-react-sdk/-/matrix-react-sdk-3.42.1.tgz#15aec8c01f54cf8badf4423d7b1b8c3dc31d643e" + integrity sha512-XLNgoBkPc5qhJPX9o6kb1azua0Tgg7+NJ9pVyTM3J1lHXsP37oR9aeVLK7fGugnZEDN+fn0Hy9ROguAWNXruAA== dependencies: "@babel/runtime" "^7.12.5" "@sentry/browser" "^6.11.0" @@ -8285,7 +8285,7 @@ matrix-react-sdk@3.42.0: maplibre-gl "^1.15.2" matrix-analytics-events "github:matrix-org/matrix-analytics-events.git#daad3faed54f0b1f1e026a7498b4653e4d01cd90" matrix-events-sdk "^0.0.1-beta.7" - matrix-js-sdk "16.0.0" + matrix-js-sdk "16.0.1" matrix-widget-api "^0.1.0-beta.18" minimist "^1.2.5" opus-recorder "^8.0.3"