+12








fcd7c979df
Co-authored-by: Artur <145776561+arturict@users.noreply.github.com> Co-authored-by: arturict <arturict@users.noreply.github.com> Co-authored-by: Thomas <thomas@ajnart.fr> Co-authored-by: Afonso Jorge Ramos <afonsojorgeramos@gmail.com> Co-authored-by: Danura30082 <danura30082+github@gmail.com> Co-authored-by: Kushie <122986913+kushiemoon-dev@users.noreply.github.com> Co-authored-by: ajnart <thomas@ajnart.fr> Co-authored-by: ajnart <thomas@ajnart.dev> Co-authored-by: chenjun <chenjun@foxmail.com> Co-authored-by: Wikibear <wikibear@users.noreply.github.com> Co-authored-by: Bergasha <bergasha@gmail.com> Co-authored-by: leafyelin <43306196+leafyelin@users.noreply.github.com> Co-authored-by: Lucas Araujo <lucas.lra@gmail.com> Co-authored-by: GreenMonito <86085570+GreenMonito@users.noreply.github.com> Co-authored-by: Nerdy-Technician <roffo@nerdy-technician.social> Co-authored-by: Jun <34545896+jcstrong@users.noreply.github.com> Co-authored-by: Edmond Abraham <54119952+gitedmond@users.noreply.github.com> Co-authored-by: thrawnx <tight.bulb9384@fastmail.com> Co-authored-by: Chris <58918656+nordada@users.noreply.github.com> Co-authored-by: yi111 <153097222+Yi-111-a@users.noreply.github.com> Co-authored-by: Yanis <naamaneyanis@gmail.com> Co-authored-by: Wikibear <me@sej.de> Co-authored-by: alessiottavo <93441886+alessiottavo@users.noreply.github.com>
82 lines
2.9 KiB
TypeScript
82 lines
2.9 KiB
TypeScript
"use client";
|
|
|
|
import type { PropsWithChildren } from "react";
|
|
import { useMemo } from "react";
|
|
import dynamic from "next/dynamic";
|
|
|
|
import { useI18n } from "@homarr/translation/client";
|
|
import { AssistantWidgetRendererProvider } from "@homarr/widgets/assistant/context";
|
|
|
|
import { AssistantContext } from "./assistant-context";
|
|
import { AssistantBoardWidgetLazy } from "./assistant-widget-lazy";
|
|
import { useRegisterAssistantSpotlightPlaceholder } from "./assistant-spotlight-placeholder";
|
|
|
|
/**
|
|
* The enabled runtime is the expensive half of the assistant (assistant-ui, Lexical, Markdown,
|
|
* Mermaid). Loading it through `next/dynamic` puts it in its own chunk that is only requested when
|
|
* this component actually renders. Availability is resolved alongside other root-layout reads on
|
|
* the server, so enabled instances render children in their final provider from the initial HTML
|
|
* without remounting the board after hydration.
|
|
*/
|
|
const EnabledAssistantRoot = dynamic(() =>
|
|
import("./assistant-provider").then((module) => ({ default: module.EnabledAssistantRoot })),
|
|
);
|
|
|
|
const DisabledAssistant = ({ children, description }: PropsWithChildren<{ description: string }>) => {
|
|
useRegisterAssistantSpotlightPlaceholder(description);
|
|
const value = useMemo(
|
|
() => ({
|
|
enabled: false,
|
|
unavailableDescription: description,
|
|
opened: false,
|
|
isRunning: false,
|
|
isRefreshing: false,
|
|
unreadCount: 0,
|
|
hasVisibleWidget: false,
|
|
activeWidgetId: null,
|
|
open: () => undefined,
|
|
close: () => undefined,
|
|
toggle: () => undefined,
|
|
sendPrompt: () => false,
|
|
refreshCurrentView: () => Promise.resolve(),
|
|
setWidgetVisible: () => undefined,
|
|
activateWidget: () => undefined,
|
|
}),
|
|
[description],
|
|
);
|
|
|
|
return (
|
|
<AssistantContext.Provider value={value}>
|
|
<AssistantWidgetRendererProvider renderer={AssistantBoardWidgetLazy}>{children}</AssistantWidgetRendererProvider>
|
|
</AssistantContext.Provider>
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Why the assistant is or is not usable, resolved alongside root-layout data.
|
|
*
|
|
* `unauthenticated` is kept apart from `unconfigured` because the server cannot check availability
|
|
* for a signed-out visitor, and telling them the instance is unconfigured would be a guess.
|
|
*/
|
|
export type AssistantAvailability = "enabled" | "unconfigured" | "unauthenticated" | "error";
|
|
|
|
interface AssistantGateProps extends PropsWithChildren {
|
|
availability: AssistantAvailability;
|
|
}
|
|
|
|
const unavailableMessageKeys = {
|
|
unauthenticated: "unavailable.signIn",
|
|
unconfigured: "unavailable.notConfigured",
|
|
error: "unavailable.error",
|
|
} as const;
|
|
|
|
export const AssistantGate = ({ availability, children }: AssistantGateProps) => {
|
|
const t = useI18n("assistant");
|
|
|
|
if (availability === "enabled") {
|
|
return <EnabledAssistantRoot>{children}</EnabledAssistantRoot>;
|
|
}
|
|
|
|
return <DisabledAssistant description={t(unavailableMessageKeys[availability])}>{children}</DisabledAssistant>;
|
|
};
|