+ The desktop site does + not work on mobile, please download the app. +
+diff --git a/docs/config.md b/docs/config.md index 4f4724ad403..b9e6f0f13a7 100644 --- a/docs/config.md +++ b/docs/config.md @@ -130,32 +130,37 @@ complete re-branding/private labeling, a more personalised experience can be ach 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 +8. `mobile_guide_app_variant`: Optional. The mobile app that the user is prompted to download from the `/mobile_guide` page. When omitted + the mobile guide will be configured for the new Element X apps. Allowed values are as follows: + 1. `classic`: Element Android/iOS. + 2. `x`: Element X Android/iOS. + 3. `pro`: Element Pro Android/iOS. +9. `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`: **DEPRECATED** 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 +10. `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. +11. `welcome_user_id`: **DEPRECATED** An optional user ID to start a DM with after creating an account. Defaults to nothing (no DM created). +12. `custom_translations_url`: An optional URL to allow overriding of translatable strings. The JSON file must be in a format of `{"affected|translation|key": {"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 +13. `branding`: Options for configuring various assets used within the app. Described in more detail down below. +14. `embedded_pages`: Further optional URLs for various assets used within the app. Described in more detail down below. +15. `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` +16. `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 +17. `disable_guests`: When `false` (default), **enable** guest-related functionality (peeking/previewing rooms, etc) for unregistered users. Set to `true` to disable this functionality. -17. `user_notice`: Optional notice to show to the user, e.g. for sunsetting a deployment and pushing users to move in their own time. +18. `user_notice`: Optional notice to show to the user, e.g. for sunsetting a deployment and pushing users to move in their own time. Takes a configuration object as below: 1. `title`: Required. Title to show at the top of the notice. 2. `description`: Required. The description to use for the notice. 3. `show_once`: Optional. If true then the notice will only be shown once per device. -18. `help_url`: The URL to point users to for help with the app, defaults to `https://element.io/help`. -19. `help_encryption_url`: The URL to point users to for help with encryption, defaults to `https://element.io/help#encryption`. -20. `force_verification`: If true, users must verify new logins (eg. with another device / their recovery key) +19. `help_url`: The URL to point users to for help with the app, defaults to `https://element.io/help`. +20. `help_encryption_url`: The URL to point users to for help with encryption, defaults to `https://element.io/help#encryption`. +21. `force_verification`: If true, users must verify new logins (eg. with another device / their recovery key) ### `desktop_builds` and `mobile_builds` diff --git a/playwright/e2e/mobile-guide/mobile-guide.spec.ts b/playwright/e2e/mobile-guide/mobile-guide.spec.ts new file mode 100644 index 00000000000..ff2ad69bf87 --- /dev/null +++ b/playwright/e2e/mobile-guide/mobile-guide.spec.ts @@ -0,0 +1,36 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import { test, expect } from "../../element-web-test"; +import { MobileAppVariant } from "../../../src/vector/mobile_guide/mobile-apps"; + +const variants = [MobileAppVariant.Classic, MobileAppVariant.X, MobileAppVariant.Pro]; + +test.describe("Mobile Guide Screenshots", { tag: "@screenshot" }, () => { + for (const variant of variants) { + test.describe(`for variant ${variant}`, () => { + test.use({ + config: { + default_server_config: { + "m.homeserver": { + base_url: "https://matrix.server.invalid", + server_name: "server.invalid", + }, + }, + mobile_guide_app_variant: variant, + }, + viewport: { width: 390, height: 844 }, // iPhone 16e + }); + + test("should match the mobile_guide screenshot", async ({ page, axe }) => { + await page.goto("/mobile_guide/"); + await expect(page).toMatchScreenshot(`mobile-guide-${variant}.png`); + await expect(axe).toHaveNoViolations(); + }); + }); + } +}); diff --git a/playwright/snapshots/mobile-guide/mobile-guide.spec.ts/mobile-guide-classic-linux.png b/playwright/snapshots/mobile-guide/mobile-guide.spec.ts/mobile-guide-classic-linux.png new file mode 100644 index 00000000000..f091eeed74f Binary files /dev/null and b/playwright/snapshots/mobile-guide/mobile-guide.spec.ts/mobile-guide-classic-linux.png differ diff --git a/playwright/snapshots/mobile-guide/mobile-guide.spec.ts/mobile-guide-pro-linux.png b/playwright/snapshots/mobile-guide/mobile-guide.spec.ts/mobile-guide-pro-linux.png new file mode 100644 index 00000000000..ff1bb69a4f8 Binary files /dev/null and b/playwright/snapshots/mobile-guide/mobile-guide.spec.ts/mobile-guide-pro-linux.png differ diff --git a/playwright/snapshots/mobile-guide/mobile-guide.spec.ts/mobile-guide-x-linux.png b/playwright/snapshots/mobile-guide/mobile-guide.spec.ts/mobile-guide-x-linux.png new file mode 100644 index 00000000000..9c32731ab79 Binary files /dev/null and b/playwright/snapshots/mobile-guide/mobile-guide.spec.ts/mobile-guide-x-linux.png differ diff --git a/sonar-project.properties b/sonar-project.properties index 2d87d32efcd..d95f46460bd 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -19,5 +19,6 @@ sonar.coverage.exclusions=\ src/vector/modernizr.js,\ src/components/views/dialogs/devtools/**/*,\ src/utils/SessionLock.ts,\ - src/**/*.d.ts + src/**/*.d.ts,\ + src/vector/mobile_guide/**/* sonar.testExecutionReportPaths=coverage/jest-sonar-report.xml diff --git a/src/IConfigOptions.ts b/src/IConfigOptions.ts index 8b88a18075c..2e129f11869 100644 --- a/src/IConfigOptions.ts +++ b/src/IConfigOptions.ts @@ -81,6 +81,7 @@ export interface IConfigOptions { }; mobile_guide_toast?: boolean; + mobile_guide_app_variant?: "classic" | "x" | "pro"; default_theme?: "light" | "dark" | string; // custom themes are strings default_country_code?: string; // ISO 3166 alpha2 country code diff --git a/src/vector/mobile_guide/assets/app-store-badge.svg b/src/vector/mobile_guide/assets/app-store-badge.svg new file mode 100755 index 00000000000..072b425a1ab --- /dev/null +++ b/src/vector/mobile_guide/assets/app-store-badge.svg @@ -0,0 +1,46 @@ + diff --git a/src/vector/mobile_guide/assets/bottom-gradient.svg b/src/vector/mobile_guide/assets/bottom-gradient.svg new file mode 100644 index 00000000000..07404409466 --- /dev/null +++ b/src/vector/mobile_guide/assets/bottom-gradient.svg @@ -0,0 +1,53 @@ + diff --git a/src/vector/mobile_guide/assets/element-logo.svg b/src/vector/mobile_guide/assets/element-logo.svg new file mode 100644 index 00000000000..d2cb52e498f --- /dev/null +++ b/src/vector/mobile_guide/assets/element-logo.svg @@ -0,0 +1,8 @@ + diff --git a/src/vector/mobile_guide/assets/google-play-badge.svg b/src/vector/mobile_guide/assets/google-play-badge.svg new file mode 100644 index 00000000000..fac62d70ed3 --- /dev/null +++ b/src/vector/mobile_guide/assets/google-play-badge.svg @@ -0,0 +1,23 @@ + + + diff --git a/src/vector/mobile_guide/index.css b/src/vector/mobile_guide/index.css new file mode 100644 index 00000000000..cb51c3fb24e --- /dev/null +++ b/src/vector/mobile_guide/index.css @@ -0,0 +1,183 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +@import url("@vector-im/compound-design-tokens/assets/web/css/compound-design-tokens.css"); + +html { + min-height: 100%; + position: relative; +} + +body { + background: var(--cpd-color-bg-canvas-default); + max-width: 680px; + margin: var(--cpd-space-0x) auto; + padding-bottom: 178px; /* Match the height of mx_BottomGradient */ + font-family: var(--cpd-font-family-sans); + font-size: var(--cpd-font-size-body-lg); /* Design says 16px, this is 17px */ + color: var(--cpd-color-text-primary); +} + +hr { + border: none; + height: var(--cpd-border-width-1); + background-color: var( + --cpd-color-bg-subtle-primary /* Design uses Border token from "Compound Marketing" set, but this matches. */ + ); + color: var( + --cpd-color-bg-subtle-primary /* Design uses Border token from "Compound Marketing" set, but this matches. */ + ); + margin: 0; +} + +p { + margin: var(--cpd-space-1x) var(--cpd-space-0x); + padding: var(--cpd-space-0x); +} + +.mx_Button { + border: 0; + border-radius: 100px; + min-width: 80px; + background-color: var(--cpd-color-bg-action-primary-rest); + color: var(--cpd-color-text-on-solid-primary); + cursor: pointer; + padding: 12px 22px; + word-break: break-word; + text-decoration: none; +} + +#deep_link_button { + margin-top: 12px; + display: inline-block; + width: auto; + box-sizing: border-box; +} + +.mx_StoreLinks { + margin: 15px 0 12px 0; +} + +.mx_StoreBadge { + text-decoration: none !important; + margin: 16px 16px 16px 0px; +} + +#f_droid_link { + color: var(--cpd-color-text-action-accent); + font-weight: bold; + text-decoration: none; +} + +#f_droid_link:visited { + color: var(--cpd-color-text-action-accent); +} + +.mx_HomePage_header { + color: var(--cpd-color-text-secondary); + align-items: center; + justify-content: center; + text-align: center; + padding-top: 48px; + padding-bottom: 48px; +} + +.mx_HomePage_header #header_title { + margin-top: 8px; + margin-bottom: 0px; +} + +.mx_HomePage h3 { + margin-top: 30px; +} + +.mx_HomePage_col { + display: flex; + flex-direction: row; +} + +.mx_HomePage_row { + flex: 1 1 0; + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: flex-start; +} + +.mx_HomePage_container { + margin: 10px 20px; +} + +.mx_HomePage_errorContainer { + display: none; /* shown in JS if needed */ + margin: 20px; + border: var(--cpd-border-width-1) solid var(--cpd-color-border-critical-primary); + background-color: var(--cpd-color-bg-critical-subtle); + padding: 5px; +} + +.mx_HomePage_container h1, +.mx_HomePage_container h2, +.mx_HomePage_container h3, +.mx_HomePage_container h4 { + font-weight: var(--cpd-font-weight-semibold); + font-size: var(--cpd-font-size-body-lg); /* Design says 16px, this is 17px */ + margin-bottom: 8px; + margin-top: 4px; +} + +.mx_Spacer { + margin-top: 48px; +} + +.mx_DesktopLink { + color: var(--cpd-color-text-action-accent); + font-weight: var(--cpd-font-weight-semibold); + text-decoration: none; +} + +/* + * The bottom gradient is a full-width background image that stretches horizontally across the page. + * It is positioned pinned to the bottom of the viewport unless the content is taller than the viewport, + * in which case it will be pinned to the bottom of the content. + */ +.mx_BottomGradient { + position: absolute; + bottom: 0; + left: 0; + right: 0; + width: 100vw; + height: 178px; /* Match the height of assets/bottom-gradient.svg so the gradient only stretches horizontally */ + background-image: url("./assets/bottom-gradient.svg"); + background-size: 100% 100%; + background-repeat: no-repeat; + z-index: -1; + margin-left: calc(50% - 50vw); /* Center the gradient regardless of body width */ +} + +.mx_HomePage_step_number { + display: flex; + align-items: flex-start; + margin-right: 8px; +} + +.mx_HomePage_step_number span { + display: flex; + align-items: center; + justify-content: center; + width: var(--cpd-space-6x); + height: var(--cpd-space-6x); + border-radius: 50%; + border: var(--cpd-border-width-1) solid var(--cpd-color-bg-subtle-primary); /* Not a border token, but matches the Design (Border token from the "Compound Marketing" set). */ + background-color: transparent; + color: var(--cpd-color-text-secondary); + font-size: var(--cpd-font-size-body-md); /* Design says 14px, this is 15px */ +} + +#step2_description { + color: var(--cpd-color-text-secondary); +} diff --git a/src/vector/mobile_guide/index.html b/src/vector/mobile_guide/index.html index d58842d6a64..34c3c4cc4a2 100644 --- a/src/vector/mobile_guide/index.html +++ b/src/vector/mobile_guide/index.html @@ -1,141 +1,13 @@ +
Set up Element on iOS or Android
-
- Go to Desktop Site
-
- Please note the Desktop site does not work on mobile.
-