"use client"; import type { PropsWithChildren } from "react"; import { Center, Flex, Loader, Stack, Text, Tooltip, UnstyledButton, } from "@mantine/core"; import { IconDeviceDesktopX } from "@tabler/icons-react"; import { clientApi } from "@homarr/api/client"; import { useRegisterSpotlightActions } from "@homarr/spotlight"; import { useScopedI18n } from "@homarr/translation/client"; import type { WidgetComponentProps } from "../definition"; import classes from "./app.module.css"; export default function AppWidget({ options, serverData, isEditMode, width, height, }: WidgetComponentProps<"app">) { const t = useScopedI18n("widget.app"); const isQueryEnabled = Boolean(options.appId); const { data: app, isPending, isError, } = clientApi.app.byId.useQuery( { id: options.appId, }, { initialData: // We need to check if the id's match because otherwise the same initialData for a changed id will be used serverData?.app?.id === options.appId ? serverData?.app : undefined, refetchOnMount: false, refetchOnWindowFocus: false, refetchOnReconnect: false, enabled: isQueryEnabled, }, ); useRegisterSpotlightActions( `app-${options.appId}`, app?.href ? [ { id: `app-${options.appId}`, title: app?.name, description: app?.description ?? "", icon: app?.iconUrl, group: "app", type: "link", href: app?.href, openInNewTab: options.openInNewTab, }, ] : [], [app, options.appId, options.openInNewTab], ); if (isPending && isQueryEnabled) { return (
); } if (isError || !isQueryEnabled) { return ( = 96 ? "2rem" : "1.5rem"} /> {width >= 96 && ( {t("error.notFound.label")} )} ); } return ( {height >= 96 && ( {app?.name} )} {app?.name} ); } interface AppLinkProps { href: string; openInNewTab: boolean; enabled: boolean; } const AppLink = ({ href, openInNewTab, enabled, children, }: PropsWithChildren) => enabled ? ( {children} ) : ( children );