Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
475d27baa0 |
No files matched your search
@@ -21,6 +21,13 @@ import type { AppRouter } from "@homarr/api";
|
|||||||
import { clientApi } from "@homarr/api/client";
|
import { clientApi } from "@homarr/api/client";
|
||||||
import { createHeadersCallbackForSource, getTrpcUrl } from "@homarr/api/shared";
|
import { createHeadersCallbackForSource, getTrpcUrl } from "@homarr/api/shared";
|
||||||
import { env } from "@homarr/common/env";
|
import { env } from "@homarr/common/env";
|
||||||
|
import { atom, useSetAtom } from "jotai";
|
||||||
|
|
||||||
|
interface WebSocketConnection {
|
||||||
|
state: 'connecting' | 'connected' | 'error' | 'closed'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const webSocketConnectionAtom = atom<WebSocketConnection>({ state: 'connecting' });
|
||||||
|
|
||||||
const getWebSocketProtocol = () => {
|
const getWebSocketProtocol = () => {
|
||||||
// window is not defined on server side
|
// window is not defined on server side
|
||||||
@@ -44,9 +51,27 @@ const constructWebsocketUrl = () => {
|
|||||||
return `${getWebSocketProtocol()}://${window.location.hostname}:${window.location.port}/websockets`;
|
return `${getWebSocketProtocol()}://${window.location.hostname}:${window.location.port}/websockets`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const wsClient = createWSClient({
|
let wsClient: WsClient | null;
|
||||||
url: constructWebsocketUrl(),
|
|
||||||
});
|
const createWsClientOrDefault = (setState: (connection: WebSocketConnection) => void) => {
|
||||||
|
if (wsClient) {
|
||||||
|
return wsClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsClient = createWSClient({
|
||||||
|
url: constructWebsocketUrl(),
|
||||||
|
onOpen() {
|
||||||
|
setState({ state: "connected" });
|
||||||
|
},
|
||||||
|
onClose() {
|
||||||
|
setState({ state: "closed" });
|
||||||
|
},
|
||||||
|
onError() {
|
||||||
|
setState({ state: "error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return wsClient;
|
||||||
|
}
|
||||||
|
|
||||||
export function TRPCReactProvider(props: PropsWithChildren) {
|
export function TRPCReactProvider(props: PropsWithChildren) {
|
||||||
const [queryClient] = useState(
|
const [queryClient] = useState(
|
||||||
@@ -60,6 +85,8 @@ export function TRPCReactProvider(props: PropsWithChildren) {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const setWebSocketConnection = useSetAtom(webSocketConnectionAtom);
|
||||||
|
|
||||||
const [trpcClient] = useState(() => {
|
const [trpcClient] = useState(() => {
|
||||||
return clientApi.createClient({
|
return clientApi.createClient({
|
||||||
links: [
|
links: [
|
||||||
@@ -70,7 +97,7 @@ export function TRPCReactProvider(props: PropsWithChildren) {
|
|||||||
splitLink({
|
splitLink({
|
||||||
condition: ({ type }) => type === "subscription",
|
condition: ({ type }) => type === "subscription",
|
||||||
true: wsLink<AppRouter>({
|
true: wsLink<AppRouter>({
|
||||||
client: wsClient,
|
client: createWsClientOrDefault((state) => setWebSocketConnection(state)),
|
||||||
transformer: superjson,
|
transformer: superjson,
|
||||||
}),
|
}),
|
||||||
false: splitLink({
|
false: splitLink({
|
||||||
@@ -106,7 +133,7 @@ export function TRPCReactProvider(props: PropsWithChildren) {
|
|||||||
<clientApi.Provider client={trpcClient} queryClient={queryClient}>
|
<clientApi.Provider client={trpcClient} queryClient={queryClient}>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<ReactQueryStreamedHydration transformer={superjson}>{props.children}</ReactQueryStreamedHydration>
|
<ReactQueryStreamedHydration transformer={superjson}>{props.children}</ReactQueryStreamedHydration>
|
||||||
<ReactQueryDevtools initialIsOpen={false} />
|
<ReactQueryDevtools initialIsOpen={false}/>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</clientApi.Provider>
|
</clientApi.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useAtomValue } from "jotai";
|
||||||
|
import { webSocketConnectionAtom } from "~/app/[locale]/_client-providers/trpc";
|
||||||
|
|
||||||
|
export const WebSocketConnectionBanner = () => {
|
||||||
|
const value = useAtomValue(webSocketConnectionAtom);
|
||||||
|
|
||||||
|
console.log('socket connection', value)
|
||||||
|
return <div>dfheuihjfieufheuhfuefhuehfu</div>
|
||||||
|
};
|
||||||
@@ -6,6 +6,7 @@ import { useAtomValue } from "jotai";
|
|||||||
|
|
||||||
import { useOptionalBackgroundProps } from "./background";
|
import { useOptionalBackgroundProps } from "./background";
|
||||||
import { navigationCollapsedAtom } from "./header/burger";
|
import { navigationCollapsedAtom } from "./header/burger";
|
||||||
|
import { webSocketConnectionAtom } from "~/app/[locale]/_client-providers/trpc";
|
||||||
|
|
||||||
interface ClientShellProps {
|
interface ClientShellProps {
|
||||||
hasHeader?: boolean;
|
hasHeader?: boolean;
|
||||||
@@ -18,12 +19,14 @@ export const ClientShell = ({
|
|||||||
children,
|
children,
|
||||||
}: PropsWithChildren<ClientShellProps>) => {
|
}: PropsWithChildren<ClientShellProps>) => {
|
||||||
const collapsed = useAtomValue(navigationCollapsedAtom);
|
const collapsed = useAtomValue(navigationCollapsedAtom);
|
||||||
const backgroundProps = useOptionalBackgroundProps();
|
const backgroundProps = useOptionalBackgroundProps()
|
||||||
|
|
||||||
|
const value = useAtomValue(webSocketConnectionAtom);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppShell
|
<AppShell
|
||||||
{...backgroundProps}
|
{...backgroundProps}
|
||||||
header={hasHeader ? { height: 60 } : undefined}
|
header={hasHeader ? { height: 60 + (value === 'closed' ? 20 : 0) } : undefined}
|
||||||
navbar={
|
navbar={
|
||||||
hasNavigation
|
hasNavigation
|
||||||
? {
|
? {
|
||||||
|
|||||||
Reference in new issue
Block a user