Update unsupported browser react component to new designs (#27857)

This commit is contained in:
Michael Telatynski 2024-07-30 14:16:19 +01:00 committed by GitHub
parent 31345ddd36
commit 59e526e318
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 564 additions and 466 deletions

View file

@ -1,149 +0,0 @@
/*
Copyright 2020 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ReactNode } from "react";
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
import { _t } from "../../languageHandler";
// directly import the style here as this layer does not support rethemedex at this time so no matrix-react-sdk
// PostCSS variables will be accessible.
import "../../../res/css/structures/ErrorView.pcss";
interface IProps {
onAccept(): void;
}
const CompatibilityView: React.FC<IProps> = ({ onAccept }) => {
const brand = SdkConfig.get("brand");
const mobileBuilds = SdkConfig.get("mobile_builds");
let ios: JSX.Element | undefined;
const iosCustomUrl = mobileBuilds?.ios;
if (iosCustomUrl !== null) {
// could be undefined or a string
ios = (
<>
<p>
<strong>iOS</strong> (iPhone or iPad)
</p>
<a href={iosCustomUrl} target="_blank" rel="noreferrer noopener" className="mx_ClearDecoration">
<img height="48" src="themes/element/img/download/apple.svg" alt="Apple App Store" />
</a>
</>
);
}
let android = [
<p className="mx_Spacer" key="header">
<strong>Android</strong>
</p>,
];
const andCustomUrl = mobileBuilds?.android;
const fdroidCustomUrl = mobileBuilds?.fdroid;
if (andCustomUrl !== null) {
// undefined or string
android.push(
<a
href={andCustomUrl}
target="_blank"
rel="noreferrer noopener"
className="mx_ClearDecoration"
key="android"
>
<img height="48" src="themes/element/img/download/google.svg" alt="Google Play Store" />
</a>,
);
}
if (fdroidCustomUrl !== null) {
// undefined or string
android.push(
<a
href={fdroidCustomUrl}
target="_blank"
rel="noreferrer noopener"
className="mx_ClearDecoration"
key="fdroid"
>
<img height="48" src="themes/element/img/download/fdroid.svg" alt="F-Droid" />
</a>,
);
}
if (android.length === 1) {
// just a header, meaning no links
android = [];
}
let mobileHeader: ReactNode = <h2 id="step2_heading">{_t("use_brand_on_mobile", { brand })}</h2>;
if (!android.length && !ios) {
mobileHeader = null;
}
return (
<div className="mx_ErrorView">
<div className="mx_ErrorView_container">
<div className="mx_HomePage_header">
<span className="mx_HomePage_logo">
<img height="42" src="themes/element/img/logos/element-logo.svg" alt="Element" />
</span>
<h1>{_t("incompatible_browser|title")}</h1>
</div>
<div className="mx_HomePage_col">
<div className="mx_HomePage_row">
<div>
<h2 id="step1_heading">{_t("incompatible_browser|summary", { brand })}</h2>
<p>{_t("incompatible_browser|features", { brand })}</p>
<p>
{_t(
"incompatible_browser|browser_links",
{},
{
chromeLink: (sub) => <a href="https://www.google.com/chrome">{sub}</a>,
firefoxLink: (sub) => <a href="https://firefox.com">{sub}</a>,
safariLink: (sub) => <a href="https://apple.com/safari">{sub}</a>,
},
)}
</p>
<p>{_t("incompatible_browser|feature_warning")}</p>
<button onClick={onAccept}>{_t("incompatible_browser|continue_warning")}</button>
</div>
</div>
</div>
<div className="mx_HomePage_col">
<div className="mx_HomePage_row">
<div>
{mobileHeader}
{ios}
{android}
</div>
</div>
</div>
<div className="mx_HomePage_row mx_Center mx_Spacer">
<p className="mx_Spacer">
<a href="https://element.io" target="_blank" className="mx_FooterLink">
{_t("go_to_element_io")}
</a>
</p>
</div>
</div>
</div>
);
};
export default CompatibilityView;

View file

@ -14,9 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import * as React from "react";
import React, { ReactNode } from "react";
import { Text, Heading, Button, Separator } from "@vector-im/compound-web";
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
import { Flex } from "matrix-react-sdk/src/components/utils/Flex";
import PopOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/pop-out";
import { _t } from "../../languageHandler";
import { Icon as AppleIcon } from "../../../res/themes/element/img/compound/apple.svg";
import { Icon as MicrosoftIcon } from "../../../res/themes/element/img/compound/microsoft.svg";
import { Icon as LinuxIcon } from "../../../res/themes/element/img/compound/linux.svg";
// directly import the style here as this layer does not support rethemedex at this time so no matrix-react-sdk
// PostCSS variables will be accessible.
@ -26,36 +33,184 @@ interface IProps {
// both of these should already be internationalised
title: string;
messages?: string[];
footer?: ReactNode;
}
const ErrorView: React.FC<IProps> = ({ title, messages }) => {
export const ErrorView: React.FC<IProps> = ({ title, messages, footer, children }) => {
return (
<div className="mx_ErrorView">
<div className="mx_ErrorView cpd-theme-light">
<img
className="mx_ErrorView_logo"
height="160"
src="themes/element/img/logos/element-app-logo.png"
alt="Element"
/>
<div className="mx_ErrorView_container">
<div className="mx_HomePage_header">
<span className="mx_HomePage_logo">
<img height="42" src="themes/element/img/logos/element-logo.svg" alt="Element" />
</span>
<h1>{_t("failed_to_start")}</h1>
</div>
<div className="mx_HomePage_col">
<div className="mx_HomePage_row">
<div>
<h2 id="step1_heading">{title}</h2>
{messages && messages.map((msg) => <p key={msg}>{msg}</p>)}
</div>
</div>
</div>
<div className="mx_HomePage_row mx_Center mx_Spacer">
<p className="mx_Spacer">
<a href="https://element.io" target="_blank" className="mx_FooterLink">
{_t("go_to_element_io")}
</a>
</p>
</div>
<Heading size="md" weight="semibold">
{title}
</Heading>
{messages?.map((message) => (
<Text key={message} size="lg">
{message}
</Text>
))}
{children}
</div>
{footer}
</div>
);
};
export default ErrorView;
const MobileAppLinks: React.FC<{
appleAppStoreUrl?: string;
googlePlayUrl?: string;
fdroidUrl?: string;
}> = ({ appleAppStoreUrl, googlePlayUrl, fdroidUrl }) => (
<Flex gap="var(--cpd-space-6x)">
{appleAppStoreUrl && (
<a href={appleAppStoreUrl} target="_blank" rel="noreferrer noopener">
<img height="64" src="themes/element/img/download/apple.svg" alt="Apple App Store" />
</a>
)}
{googlePlayUrl && (
<a href={googlePlayUrl} target="_blank" rel="noreferrer noopener" key="android">
<img height="64" src="themes/element/img/download/google.svg" alt="Google Play Store" />
</a>
)}
{fdroidUrl && (
<a href={fdroidUrl} target="_blank" rel="noreferrer noopener" key="fdroid">
<img height="64" src="themes/element/img/download/fdroid.svg" alt="F-Droid" />
</a>
)}
</Flex>
);
const DesktopAppLinks: React.FC<{
macOsUrl?: string;
win64Url?: string;
win32Url?: string;
linuxUrl?: string;
}> = ({ macOsUrl, win64Url, win32Url, linuxUrl }) => {
return (
<Flex gap="var(--cpd-space-4x)">
{macOsUrl && (
<Button as="a" href={macOsUrl} kind="secondary" Icon={AppleIcon}>
{_t("incompatible_browser|macos")}
</Button>
)}
{win64Url && (
<Button as="a" href={win64Url} kind="secondary" Icon={MicrosoftIcon}>
{_t("incompatible_browser|windows", { bits: "64" })}
</Button>
)}
{win32Url && (
<Button as="a" href={win32Url} kind="secondary" Icon={MicrosoftIcon}>
{_t("incompatible_browser|windows", { bits: "32" })}
</Button>
)}
{linuxUrl && (
<Button as="a" href={linuxUrl} kind="secondary" Icon={LinuxIcon}>
{_t("incompatible_browser|linux")}
</Button>
)}
</Flex>
);
};
const linkFactory =
(link: string) =>
(text: string): JSX.Element => (
<a href={link} target="_blank" rel="noreferrer noopener">
{text}
</a>
);
export const UnsupportedBrowserView: React.FC<{
onAccept?(): void;
}> = ({ onAccept }) => {
const config = SdkConfig.get();
const brand = config.brand ?? "Element";
const hasDesktopBuilds =
config.desktop_builds?.available &&
(config.desktop_builds?.url_macos ||
config.desktop_builds?.url_win64 ||
config.desktop_builds?.url_win32 ||
config.desktop_builds?.url_linux);
const hasMobileBuilds = Boolean(
config.mobile_builds?.ios || config.mobile_builds?.android || config.mobile_builds?.fdroid,
);
return (
<ErrorView
title={_t("incompatible_browser|title", { brand })}
messages={[
_t("incompatible_browser|description", {
brand,
detail: onAccept
? _t("incompatible_browser|detail_can_continue")
: _t("incompatible_browser|detail_no_continue"),
}),
]}
footer={
<>
{/* We render the apps in the footer as they are wider than the 520px container */}
{(hasDesktopBuilds || hasMobileBuilds) && <Separator />}
{hasDesktopBuilds && (
<>
<Heading as="h2" size="sm" weight="semibold">
{_t("incompatible_browser|use_desktop_heading", { brand })}
</Heading>
<DesktopAppLinks
macOsUrl={config.desktop_builds?.url_macos}
win64Url={config.desktop_builds?.url_win64}
win32Url={config.desktop_builds?.url_win32}
linuxUrl={config.desktop_builds?.url_linux}
/>
</>
)}
{hasMobileBuilds && (
<>
<Heading as="h2" size="sm" weight="semibold">
{hasDesktopBuilds
? _t("incompatible_browser|use_mobile_heading_after_desktop")
: _t("incompatible_browser|use_mobile_heading", { brand })}
</Heading>
<MobileAppLinks
appleAppStoreUrl={config.mobile_builds?.ios ?? undefined}
googlePlayUrl={config.mobile_builds?.android ?? undefined}
fdroidUrl={config.mobile_builds?.fdroid ?? undefined}
/>
</>
)}
</>
}
>
<Text size="lg">
{_t(
"incompatible_browser|supported_browsers",
{},
{
Chrome: linkFactory("https://google.com/chrome"),
Firefox: linkFactory("https://firefox.com"),
Edge: linkFactory("https://microsoft.com/edge"),
Safari: linkFactory("https://apple.com/safari"),
},
)}
</Text>
<Flex gap="var(--cpd-space-4x)" className="mx_ErrorView_buttons">
<Button Icon={PopOutIcon} kind="secondary" size="sm">
{_t("incompatible_browser|learn_more")}
</Button>
{onAccept && (
<Button kind="primary" size="sm" onClick={onAccept}>
{_t("incompatible_browser|continue")}
</Button>
)}
</Flex>
</ErrorView>
);
};