Merge pull request #1121 from buster-so/nate/streaming-alert

version update should trigger full page refresh
This commit is contained in:
Nate Kelley 2025-09-24 13:53:06 -06:00 committed by GitHub
commit cf289689e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 115 additions and 26 deletions

View File

@ -3,7 +3,7 @@ import type React from 'react';
import { useMemo, useState } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { Button } from '@/components/ui/buttons';
import { Paragraph, Text, Title } from '@/components/ui/typography';
import { Paragraph, Title } from '@/components/ui/typography';
import { useIsVersionChanged } from '@/context/AppVersion/useAppVersion';
import { useMount } from '@/hooks/useMount';
import { cn } from '@/lib/utils';

View File

@ -2,3 +2,4 @@ export const BUSTER_HOME_PAGE = 'https://buster.so';
export const BUSTER_DOCS_URL = 'https://docs.buster.so';
export const BUSTER_GETTING_STARTED_URL = 'https://www.buster.so/get-started';
export const BUSTER_DOCS_QUICKSTART = 'https://docs.buster.so/docs/getting-started/quickstart';
export const BUSTER_SIGN_UP_URL = 'https://buster.so/sign-up';

View File

@ -18,6 +18,7 @@ export const useAppVersion = () => {
...versionGetAppVersion,
refetchOnReconnect: true,
refetchOnMount: true,
notifyOnChangeProps: ['data'],
});
const isChanged = checkNewVersion(data?.buildId);
@ -64,6 +65,7 @@ export const useIsVersionChanged = () => {
const { data = false } = useQuery({
...versionGetAppVersion,
select: useCallback((data: { buildId: string }) => checkNewVersion(data.buildId), []),
notifyOnChangeProps: ['data'],
});
return data;
};

View File

@ -61,7 +61,6 @@ const PosthogWrapper: React.FC<PropsWithChildren> = ({ children }) => {
import('posthog-js'),
import('posthog-js/react'),
]);
console.log('posthog', posthog);
setPosthogModules({ posthog, PostHogProvider });
} catch (error) {

View File

@ -2,6 +2,7 @@ import { useLocation, useNavigate } from '@tanstack/react-router';
import { useEffect, useLayoutEffect, useRef } from 'react';
import type { BusterChatResponseMessage_file } from '@/api/asset_interfaces/chat';
import { useGetChatMessageMemoized } from '@/api/buster_rest/chats';
import { useIsVersionChanged } from '@/context/AppVersion/useAppVersion';
import { useHasLoadedChat } from '@/context/Chats/useGetChat';
import {
useGetChatMessageCompleted,
@ -20,17 +21,15 @@ export const useAutoRedirectStreaming = ({
}) => {
const navigate = useNavigate();
const getChatMessageMemoized = useGetChatMessageMemoized();
const versionChanged = useIsVersionChanged();
const isStreamFinished = useGetChatMessageCompleted({ messageId: lastMessageId });
const lastReasoningMessageId = useGetChatMessageLastReasoningMessageId({
messageId: lastMessageId,
});
const isFinishedReasoning = useGetChatMessageIsFinishedReasoning({ messageId: lastMessageId });
const hasResponseFile = useGetChatMessageHasResponseFile({ messageId: lastMessageId });
const previousIsCompletedStream = useRef<boolean>(isStreamFinished);
const hasLoadedChat = useHasLoadedChat({ chatId: chatId || '' });
const hasReasoning = !!lastReasoningMessageId;
useLayoutEffect(() => {
@ -63,7 +62,7 @@ export const useAutoRedirectStreaming = ({
versionNumber: firstFile.version_number,
});
navigate({ ...linkProps, replace: true });
navigate({ ...linkProps, replace: true, reloadDocument: versionChanged });
}
}
@ -76,6 +75,7 @@ export const useAutoRedirectStreaming = ({
messageId: lastMessageId,
},
replace: true,
reloadDocument: versionChanged,
});
}
@ -94,7 +94,14 @@ export const useAutoRedirectStreaming = ({
chatId,
},
replace: true,
reloadDocument: versionChanged,
});
}
}, [isStreamFinished, hasReasoning, hasResponseFile, chatId, lastMessageId, isFinishedReasoning]); //only use these values to trigger the useEffect
useEffect(() => {
if (!isStreamFinished && versionChanged) {
window.location.reload();
}
}, [isStreamFinished, versionChanged]);
};

View File

@ -22,6 +22,7 @@ import { Route as InfoGettingStartedRouteImport } from './routes/info/getting-st
import { Route as AuthResetPasswordRouteImport } from './routes/auth.reset-password'
import { Route as AuthLogoutRouteImport } from './routes/auth.logout'
import { Route as AuthLoginRouteImport } from './routes/auth.login'
import { Route as AppThrow2RouteImport } from './routes/app.throw2'
import { Route as AppThrowRouteImport } from './routes/app.throw'
import { Route as AppSettingsRouteImport } from './routes/app/_settings'
import { Route as AppAppRouteImport } from './routes/app/_app'
@ -213,6 +214,11 @@ const AuthLoginRoute = AuthLoginRouteImport.update({
path: '/login',
getParentRoute: () => AuthRoute,
} as any)
const AppThrow2Route = AppThrow2RouteImport.update({
id: '/throw2',
path: '/throw2',
getParentRoute: () => AppRoute,
} as any)
const AppThrowRoute = AppThrowRouteImport.update({
id: '/throw',
path: '/throw',
@ -946,6 +952,7 @@ export interface FileRoutesByFullPath {
'/embed': typeof EmbedRouteWithChildren
'/healthcheck': typeof HealthcheckRoute
'/app/throw': typeof AppThrowRoute
'/app/throw2': typeof AppThrow2Route
'/auth/login': typeof AuthLoginRoute
'/auth/logout': typeof AuthLogoutRoute
'/auth/reset-password': typeof AuthResetPasswordRoute
@ -1056,6 +1063,7 @@ export interface FileRoutesByTo {
'/healthcheck': typeof HealthcheckRoute
'/app': typeof AppSettingsRestricted_layoutAdmin_onlyRouteWithChildren
'/app/throw': typeof AppThrowRoute
'/app/throw2': typeof AppThrow2Route
'/auth/login': typeof AuthLoginRoute
'/auth/logout': typeof AuthLogoutRoute
'/auth/reset-password': typeof AuthResetPasswordRoute
@ -1151,6 +1159,7 @@ export interface FileRoutesById {
'/app/_app': typeof AppAppRouteWithChildren
'/app/_settings': typeof AppSettingsRouteWithChildren
'/app/throw': typeof AppThrowRoute
'/app/throw2': typeof AppThrow2Route
'/auth/login': typeof AuthLoginRoute
'/auth/logout': typeof AuthLogoutRoute
'/auth/reset-password': typeof AuthResetPasswordRoute
@ -1277,6 +1286,7 @@ export interface FileRouteTypes {
| '/embed'
| '/healthcheck'
| '/app/throw'
| '/app/throw2'
| '/auth/login'
| '/auth/logout'
| '/auth/reset-password'
@ -1387,6 +1397,7 @@ export interface FileRouteTypes {
| '/healthcheck'
| '/app'
| '/app/throw'
| '/app/throw2'
| '/auth/login'
| '/auth/logout'
| '/auth/reset-password'
@ -1481,6 +1492,7 @@ export interface FileRouteTypes {
| '/app/_app'
| '/app/_settings'
| '/app/throw'
| '/app/throw2'
| '/auth/login'
| '/auth/logout'
| '/auth/reset-password'
@ -1701,6 +1713,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthLoginRouteImport
parentRoute: typeof AuthRoute
}
'/app/throw2': {
id: '/app/throw2'
path: '/throw2'
fullPath: '/app/throw2'
preLoaderRoute: typeof AppThrow2RouteImport
parentRoute: typeof AppRoute
}
'/app/throw': {
id: '/app/throw'
path: '/throw'
@ -3235,6 +3254,7 @@ interface AppRouteChildren {
AppAppRoute: typeof AppAppRouteWithChildren
AppSettingsRoute: typeof AppSettingsRouteWithChildren
AppThrowRoute: typeof AppThrowRoute
AppThrow2Route: typeof AppThrow2Route
AppIndexRoute: typeof AppIndexRoute
}
@ -3242,6 +3262,7 @@ const AppRouteChildren: AppRouteChildren = {
AppAppRoute: AppAppRouteWithChildren,
AppSettingsRoute: AppSettingsRouteWithChildren,
AppThrowRoute: AppThrowRoute,
AppThrow2Route: AppThrow2Route,
AppIndexRoute: AppIndexRoute,
}

View File

@ -1,23 +1,42 @@
import { createFileRoute } from '@tanstack/react-router';
import { useState } from 'react';
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { z } from 'zod';
import { useMount } from '../hooks/useMount';
export const Route = createFileRoute('/app/throw')({
validateSearch: z.object({
iterations: z.number().optional(),
}),
component: RouteComponent,
beforeLoad: ({ search }) => {
return {
iterations: search.iterations,
};
},
loader: async ({ context }) => {
return {
iterations: context.iterations,
};
},
head: ({ loaderData }) => {
return {
meta: [
{
title: `Throw ${loaderData?.iterations}`,
},
],
};
},
});
function RouteComponent() {
const [throwError, setThrowError] = useState(false);
const navigate = useNavigate();
const { iterations } = Route.useSearch();
useMount(() => {
setTimeout(() => {
setThrowError(true);
navigate({ to: '/app/throw2', replace: true, search: { iterations: (iterations ?? 0) + 1 } });
}, 1000);
});
if (throwError) {
throw new Error('Nate is testing this error');
}
return <div>Hello "/app/throw"! {throwError ? 'Throwing error' : 'Not throwing error'}</div>;
return <div className="bg-red-100">Hello "/app/throw"! </div>;
}

View File

@ -0,0 +1,43 @@
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { z } from 'zod';
import { useMount } from '@/hooks/useMount';
const searchParamsSchema = z.object({
iterations: z.number().optional(),
});
export const Route = createFileRoute('/app/throw2')({
validateSearch: searchParamsSchema,
component: RouteComponent,
beforeLoad: ({ search }) => {
return {
iterations: search.iterations,
};
},
loader: async ({ context }) => {
return {
iterations: context.iterations,
};
},
head: ({ loaderData }) => {
return {
meta: [
{
title: `Throw ${loaderData?.iterations}`,
},
],
};
},
});
function RouteComponent() {
const navigate = useNavigate();
const { iterations } = Route.useSearch();
useMount(() => {
setTimeout(() => {
navigate({ to: '/app/throw', replace: true, search: { iterations: (iterations ?? 0) + 1 } });
}, 1000);
});
return <div className="bg-blue-100">Hello "/app/throw2"!</div>;
}

View File

@ -3,6 +3,7 @@ import { prefetchGetMyUserInfo } from '@/api/buster_rest/users/queryRequests';
import { getAppLayout } from '@/api/server-functions/getAppLayout';
import { AppProviders } from '@/context/Providers';
import { getSupabaseSession } from '@/integrations/supabase/getSupabaseUserClient';
import { BUSTER_SIGN_UP_URL } from '../config/externalRoutes';
export const Route = createFileRoute('/app')({
context: ({ context }) => ({ ...context, getAppLayout }),
@ -27,7 +28,7 @@ export const Route = createFileRoute('/app')({
try {
const [user] = await Promise.all([prefetchGetMyUserInfo(queryClient)]);
if (!user || !user.organizations || user.organizations.length === 0) {
throw redirect({ href: 'https://buster.so/sign-up', replace: true, statusCode: 307 });
throw redirect({ href: BUSTER_SIGN_UP_URL, replace: true, statusCode: 307 });
}
return {
supabaseSession,

View File

@ -1,13 +1,9 @@
import { createFileRoute } from '@tanstack/react-router';
import { useEffect } from 'react';
import { createFileRoute, redirect } from '@tanstack/react-router';
import { BUSTER_SIGN_UP_URL } from '../../config/externalRoutes';
export const Route = createFileRoute('/info/getting-started')({
component: GettingStartedPage,
component: () => null,
beforeLoad: () => {
throw redirect({ href: BUSTER_SIGN_UP_URL, replace: true, statusCode: 307 });
},
});
export default function GettingStartedPage() {
useEffect(() => {
window.location.replace('https://buster.so/sign-up');
}, []);
return null;
}