Avoid rendering app download buttons if disabled in config (#11741)

* Add default desktop_builds and mobile_builds into SdkConfig.DEFAULTS

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Avoid rendering app download buttons if config sets to `null`

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Disable app download onboarding task if config has no apps to download

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add tests and update types

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix types

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2023-10-13 10:43:39 +01:00 committed by GitHub
parent e22fa2efc1
commit bdf2ebd301
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 723 additions and 70 deletions

View file

@ -44,7 +44,7 @@ import PosthogTrackers from "../../PosthogTrackers";
import { DecryptionFailureTracker } from "../../DecryptionFailureTracker";
import { IMatrixClientCreds, MatrixClientPeg } from "../../MatrixClientPeg";
import PlatformPeg from "../../PlatformPeg";
import SdkConfig from "../../SdkConfig";
import SdkConfig, { ConfigOptions } from "../../SdkConfig";
import dis from "../../dispatcher/dispatcher";
import Notifier from "../../Notifier";
import Modal from "../../Modal";
@ -122,7 +122,6 @@ import { ViewHomePagePayload } from "../../dispatcher/payloads/ViewHomePagePaylo
import { AfterLeaveRoomPayload } from "../../dispatcher/payloads/AfterLeaveRoomPayload";
import { DoAfterSyncPreparedPayload } from "../../dispatcher/payloads/DoAfterSyncPreparedPayload";
import { ViewStartChatOrReusePayload } from "../../dispatcher/payloads/ViewStartChatOrReusePayload";
import { IConfigOptions } from "../../IConfigOptions";
import { SnakedObject } from "../../utils/SnakedObject";
import { leaveRoomBehaviour } from "../../utils/leave-behaviour";
import { CallStore } from "../../stores/CallStore";
@ -165,7 +164,7 @@ interface IScreen {
}
interface IProps {
config: IConfigOptions;
config: ConfigOptions;
onNewScreen: (screen: string, replaceLast: boolean) => void;
enableGuest?: boolean;
// the queryParams extracted from the [real] query-string of the URI
@ -1138,7 +1137,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
}
private chatCreateOrReuse(userId: string): void {
const snakedConfig = new SnakedObject<IConfigOptions>(this.props.config);
const snakedConfig = new SnakedObject(this.props.config);
// Use a deferred action to reshow the dialog once the user has registered
if (MatrixClientPeg.safeGet().isGuest()) {
// No point in making 2 DMs with welcome bot. This assumes view_set_mxid will
@ -1295,7 +1294,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
* @returns {string} The room ID of the new room, or null if no room was created
*/
private async startWelcomeUserChat(): Promise<string | null> {
const snakedConfig = new SnakedObject<IConfigOptions>(this.props.config);
const snakedConfig = new SnakedObject(this.props.config);
const welcomeUserId = snakedConfig.get("welcome_user_id");
if (!welcomeUserId) return null;
@ -1390,7 +1389,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} else if (MatrixClientPeg.currentUserIsJustRegistered()) {
MatrixClientPeg.setJustRegisteredUserId(null);
const snakedConfig = new SnakedObject<IConfigOptions>(this.props.config);
const snakedConfig = new SnakedObject(this.props.config);
if (snakedConfig.get("welcome_user_id") && getCurrentLanguage().startsWith("en")) {
const welcomeUserRoom = await this.startWelcomeUserChat();
if (welcomeUserRoom === null) {

View file

@ -26,24 +26,32 @@ import QRCode from "../elements/QRCode";
import Heading from "../typography/Heading";
import BaseDialog from "./BaseDialog";
const fallbackAppStore = "https://apps.apple.com/app/vector/id1083446067";
const fallbackGooglePlay = "https://play.google.com/store/apps/details?id=im.vector.app";
const fallbackFDroid = "https://f-droid.org/repository/browse/?fdid=im.vector.app";
interface Props {
onFinished(): void;
}
export const showAppDownloadDialogPrompt = (): boolean => {
const desktopBuilds = SdkConfig.getObject("desktop_builds");
const mobileBuilds = SdkConfig.getObject("mobile_builds");
return (
!!desktopBuilds?.get("available") ||
!!mobileBuilds?.get("ios") ||
!!mobileBuilds?.get("android") ||
!!mobileBuilds?.get("fdroid")
);
};
export const AppDownloadDialog: FC<Props> = ({ onFinished }) => {
const brand = SdkConfig.get("brand");
const desktopBuilds = SdkConfig.getObject("desktop_builds");
const mobileBuilds = SdkConfig.getObject("mobile_builds");
const urlAppStore = mobileBuilds?.get("ios") ?? fallbackAppStore;
const urlAppStore = mobileBuilds?.get("ios");
const urlAndroid = mobileBuilds?.get("android") ?? mobileBuilds?.get("fdroid") ?? fallbackGooglePlay;
const urlGooglePlay = mobileBuilds?.get("android") ?? fallbackGooglePlay;
const urlFDroid = mobileBuilds?.get("fdroid") ?? fallbackFDroid;
const urlGooglePlay = mobileBuilds?.get("android");
const urlFDroid = mobileBuilds?.get("fdroid");
const urlAndroid = urlGooglePlay ?? urlFDroid;
return (
<BaseDialog
@ -67,57 +75,65 @@ export const AppDownloadDialog: FC<Props> = ({ onFinished }) => {
</div>
)}
<div className="mx_AppDownloadDialog_mobile">
<div className="mx_AppDownloadDialog_app">
<Heading size="3">{_t("common|ios")}</Heading>
<QRCode data={urlAppStore} margin={0} width={172} />
<div className="mx_AppDownloadDialog_info">
{_t("onboarding|qr_or_app_links", {
appLinks: "",
qrCode: "",
})}
{urlAppStore && (
<div className="mx_AppDownloadDialog_app">
<Heading size="3">{_t("common|ios")}</Heading>
<QRCode data={urlAppStore} margin={0} width={172} />
<div className="mx_AppDownloadDialog_info">
{_t("onboarding|qr_or_app_links", {
appLinks: "",
qrCode: "",
})}
</div>
<div className="mx_AppDownloadDialog_links">
<AccessibleButton
element="a"
href={urlAppStore}
target="_blank"
aria-label={_t("onboarding|download_app_store")}
onClick={() => {}}
>
<IOSBadge />
</AccessibleButton>
</div>
</div>
<div className="mx_AppDownloadDialog_links">
<AccessibleButton
element="a"
href={urlAppStore}
target="_blank"
aria-label={_t("onboarding|download_app_store")}
onClick={() => {}}
>
<IOSBadge />
</AccessibleButton>
)}
{urlAndroid && (
<div className="mx_AppDownloadDialog_app">
<Heading size="3">{_t("common|android")}</Heading>
<QRCode data={urlAndroid} margin={0} width={172} />
<div className="mx_AppDownloadDialog_info">
{_t("onboarding|qr_or_app_links", {
appLinks: "",
qrCode: "",
})}
</div>
<div className="mx_AppDownloadDialog_links">
{urlGooglePlay && (
<AccessibleButton
element="a"
href={urlGooglePlay}
target="_blank"
aria-label={_t("onboarding|download_google_play")}
onClick={() => {}}
>
<GooglePlayBadge />
</AccessibleButton>
)}
{urlFDroid && (
<AccessibleButton
element="a"
href={urlFDroid}
target="_blank"
aria-label={_t("onboarding|download_f_droid")}
onClick={() => {}}
>
<FDroidBadge />
</AccessibleButton>
)}
</div>
</div>
</div>
<div className="mx_AppDownloadDialog_app">
<Heading size="3">{_t("common|android")}</Heading>
<QRCode data={urlAndroid} margin={0} width={172} />
<div className="mx_AppDownloadDialog_info">
{_t("onboarding|qr_or_app_links", {
appLinks: "",
qrCode: "",
})}
</div>
<div className="mx_AppDownloadDialog_links">
<AccessibleButton
element="a"
href={urlGooglePlay}
target="_blank"
aria-label={_t("onboarding|download_google_play")}
onClick={() => {}}
>
<GooglePlayBadge />
</AccessibleButton>
<AccessibleButton
element="a"
href={urlFDroid}
target="_blank"
aria-label={_t("onboarding|download_f_droid")}
onClick={() => {}}
>
<FDroidBadge />
</AccessibleButton>
</div>
</div>
)}
</div>
<div className="mx_AppDownloadDialog_legal">
<p>{_t("onboarding|apple_trademarks")}</p>