Show a loading bar when checkout is happening (#249)

This commit is contained in:
Will Chen
2025-05-26 11:51:00 -07:00
committed by GitHub
parent 2bb8902b08
commit cdf2f5d772
5 changed files with 65 additions and 2 deletions

View File

@@ -26,6 +26,8 @@ import { useStreamChat } from "@/hooks/useStreamChat";
import { useCurrentBranch } from "@/hooks/useCurrentBranch";
import { useCheckoutVersion } from "@/hooks/useCheckoutVersion";
import { useRenameBranch } from "@/hooks/useRenameBranch";
import { isAnyCheckoutVersionInProgressAtom } from "@/store/appAtoms";
import { LoadingBar } from "../ui/LoadingBar";
interface ChatHeaderProps {
isVersionPaneOpen: boolean;
@@ -46,6 +48,9 @@ export function ChatHeader({
const [selectedChatId, setSelectedChatId] = useAtom(selectedChatIdAtom);
const { refreshChats } = useChats(appId);
const { isStreaming } = useStreamChat();
const isAnyCheckoutVersionInProgress = useAtomValue(
isAnyCheckoutVersionInProgressAtom,
);
const {
branchInfo,
@@ -102,6 +107,7 @@ export function ChatHeader({
return (
<div className="flex flex-col w-full @container">
<LoadingBar isVisible={isAnyCheckoutVersionInProgress} />
{/* If the version pane is open, it's expected to not always be on the main branch. */}
{isNotMainBranch && !isVersionPaneOpen && (
<div className="flex flex-col @sm:flex-row items-center justify-between px-4 py-2 bg-amber-100 dark:bg-amber-900 text-amber-800 dark:text-amber-200">
@@ -161,7 +167,8 @@ export function ChatHeader({
</div>
)}
<div className="@container flex items-center justify-between py-1.5">
{/* Why is this pt-0.5? Because the loading bar is h-1 (it always takes space) and we want the vertical spacing to be consistent.*/}
<div className="@container flex items-center justify-between pb-1.5 pt-0.5">
<div className="flex items-center space-x-2">
<Button
onClick={handleNewChat}

View File

@@ -0,0 +1,20 @@
import { cn } from "@/lib/utils";
import React from "react";
export const LoadingBar: React.FC<{ isVisible: boolean }> = ({ isVisible }) => {
return (
<div
key="loading-bar"
className={cn(
"relative w-full h-1 bg-primary/20 overflow-hidden",
isVisible ? "" : "invisible",
)}
>
<div
className={cn(
"absolute top-0 left-0 h-full w-1/2 bg-primary animate-marquee",
)}
/>
</div>
);
};

View File

@@ -1,5 +1,7 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { IpcClient } from "@/ipc/ipc_client";
import { useSetAtom } from "jotai";
import { activeCheckoutCounterAtom } from "@/store/appAtoms";
interface CheckoutVersionVariables {
appId: number;
@@ -8,6 +10,7 @@ interface CheckoutVersionVariables {
export function useCheckoutVersion() {
const queryClient = useQueryClient();
const setActiveCheckouts = useSetAtom(activeCheckoutCounterAtom);
const { isPending: isCheckingOutVersion, mutateAsync: checkoutVersion } =
useMutation<void, Error, CheckoutVersionVariables>({
@@ -17,7 +20,12 @@ export function useCheckoutVersion() {
throw new Error("App ID is null, cannot checkout version.");
}
const ipcClient = IpcClient.getInstance();
setActiveCheckouts((prev) => prev + 1); // Increment counter
try {
await ipcClient.checkoutVersion({ appId, versionId });
} finally {
setActiveCheckouts((prev) => prev - 1); // Decrement counter
}
},
onSuccess: (_, variables) => {
// Invalidate queries that depend on the current version/branch

15
src/store/appAtoms.ts Normal file
View File

@@ -0,0 +1,15 @@
import { atom } from "jotai";
/**
* Atom to store the number of active checkoutVersion mutations.
* This is a "primitive" atom that you will update directly.
*/
export const activeCheckoutCounterAtom = atom(0);
/**
* Derived atom that is true if any checkoutVersion mutation is in progress.
* This atom is read-only and derives its state from activeCheckoutCounterAtom.
*/
export const isAnyCheckoutVersionInProgressAtom = atom(
(get) => get(activeCheckoutCounterAtom) > 0,
);

View File

@@ -280,3 +280,16 @@
width: 0;
}
}
@keyframes marquee {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(200%);
}
}
.animate-marquee {
animation: marquee 2s linear infinite;
}