feat: display error if app is not installed (#16980)

Fixes: https://github.com/coder/coder/issues/13937
This commit is contained in:
Marcin Tojek
2025-03-18 14:24:02 +01:00
committed by GitHub
parent 13a3ddd964
commit 13d0dac795
2 changed files with 30 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ import {
MockWorkspaceApp,
MockWorkspaceProxies,
} from "testHelpers/entities";
import { withGlobalSnackbar } from "testHelpers/storybook";
import { AppLink } from "./AppLink";
const meta: Meta<typeof AppLink> = {
@@ -72,6 +73,19 @@ export const ExternalApp: Story = {
},
};
export const ExternalAppNotInstalled: Story = {
decorators: [withGlobalSnackbar],
args: {
workspace: MockWorkspace,
app: {
...MockWorkspaceApp,
external: true,
url: "foobar-foobaz://open-me",
},
agent: MockWorkspaceAgent,
},
};
export const SharingLevelOwner: Story = {
args: {
workspace: MockWorkspace,

View File

@@ -5,7 +5,9 @@ import Link from "@mui/material/Link";
import Tooltip from "@mui/material/Tooltip";
import { API } from "api/api";
import type * as TypesGen from "api/typesGenerated";
import { displayError } from "components/GlobalSnackbar/utils";
import { useProxy } from "contexts/ProxyContext";
import { useEffect } from "react";
import { type FC, type MouseEvent, useState } from "react";
import { createAppLinkHref } from "utils/apps";
import { generateRandomString } from "utils/random";
@@ -152,6 +154,20 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
url = href.replaceAll(magicTokenString, key.key);
setFetchingSessionToken(false);
}
// When browser recognizes the protocol and is able to navigate to the app,
// it will blur away, and will stop the timer. Otherwise,
// an error message will be displayed.
const openAppExternallyFailedTimeout = 500;
const openAppExternallyFailed = setTimeout(() => {
displayError(
`${app.display_name !== "" ? app.display_name : app.slug} must be installed first.`,
);
}, openAppExternallyFailedTimeout);
window.addEventListener("blur", () => {
clearTimeout(openAppExternallyFailed);
});
window.location.href = url;
return;
}