Skip to content

Commit a2d4b99

Browse files
authored
fix: hide app icon if not found (#16684)
Fixes: #14759
1 parent 6bdddd5 commit a2d4b99

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

site/src/modules/resources/AppLink/AppLink.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
3737
const preferredPathBase = proxy.preferredPathAppURL;
3838
const appsHost = proxy.preferredWildcardHostname;
3939
const [fetchingSessionToken, setFetchingSessionToken] = useState(false);
40+
const [iconError, setIconError] = useState(false);
4041

4142
const theme = useTheme();
4243
const username = workspace.owner_name;
@@ -67,7 +68,9 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
6768
// To avoid bugs in the healthcheck code locking users out of apps, we no
6869
// longer block access to apps if they are unhealthy/initializing.
6970
let canClick = true;
70-
let icon = <BaseIcon app={app} />;
71+
let icon = !iconError && (
72+
<BaseIcon app={app} onIconPathError={() => setIconError(true)} />
73+
);
7174

7275
let primaryTooltip = "";
7376
if (app.health === "initializing") {

site/src/modules/resources/AppLink/BaseIcon.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,21 @@ import type { FC } from "react";
44

55
interface BaseIconProps {
66
app: WorkspaceApp;
7+
onIconPathError?: () => void;
78
}
89

9-
export const BaseIcon: FC<BaseIconProps> = ({ app }) => {
10+
export const BaseIcon: FC<BaseIconProps> = ({ app, onIconPathError }) => {
1011
return app.icon ? (
1112
<img
1213
alt={`${app.display_name} Icon`}
1314
src={app.icon}
1415
style={{ pointerEvents: "none" }}
16+
onError={() => {
17+
console.warn(
18+
`Application icon for "${app.id}" has invalid source "${app.icon}".`,
19+
);
20+
onIconPathError?.();
21+
}}
1522
/>
1623
) : (
1724
<ComputerIcon />

site/src/pages/WorkspacePage/Workspace.stories.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,43 @@ export const Running: Story = {
8080
},
8181
};
8282

83+
export const AppIcons: Story = {
84+
args: {
85+
...Running.args,
86+
workspace: {
87+
...Mocks.MockWorkspace,
88+
latest_build: {
89+
...Mocks.MockWorkspace.latest_build,
90+
resources: [
91+
{
92+
...Mocks.MockWorkspaceResource,
93+
agents: [
94+
{
95+
...Mocks.MockWorkspaceAgent,
96+
apps: [
97+
{
98+
...Mocks.MockWorkspaceApp,
99+
id: "test-app-1",
100+
slug: "test-app-1",
101+
display_name: "Default Icon",
102+
},
103+
{
104+
...Mocks.MockWorkspaceApp,
105+
id: "test-app-2",
106+
slug: "test-app-2",
107+
display_name: "Broken Icon",
108+
icon: "/foobar/broken.png",
109+
},
110+
],
111+
},
112+
],
113+
},
114+
],
115+
},
116+
},
117+
},
118+
};
119+
83120
export const Favorite: Story = {
84121
args: {
85122
...Running.args,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy