fix(frontend): Fix confetti (#11031)

### Changes 🏗️

- Fix not being able to complete `MARKETPLACE_RUN_AGENT` task
- Fix confetti shooting on every refresh
- Fix confetti shooting from top-left corner

### Checklist 📋

#### For code changes:
- [x] I have clearly listed my changes in the PR description
- [x] I have made a test plan
- [x] I have tested my changes according to the test plan:
  - [x] Bugs eradicated
This commit is contained in:
Krzysztof Czerwinski
2025-10-02 12:19:25 +09:00
committed by GitHub
parent 047f011520
commit 18bbd8e572
2 changed files with 31 additions and 24 deletions

View File

@@ -103,8 +103,7 @@ export function AgentRunDraftView({
const [changedPresetAttributes, setChangedPresetAttributes] = useState<
Set<keyof LibraryAgentPresetUpdatable>
>(new Set());
const { state: onboardingState, completeStep: completeOnboardingStep } =
useOnboarding();
const { completeStep: completeOnboardingStep } = useOnboarding();
const [cronScheduleDialogOpen, setCronScheduleDialogOpen] = useState(false);
// Update values if agentPreset parameter is changed
@@ -197,9 +196,7 @@ export function AgentRunDraftView({
.catch(toastOnFail("execute agent preset"));
}
// Mark run agent onboarding step as completed
if (onboardingState?.completedSteps.includes("MARKETPLACE_ADD_AGENT")) {
completeOnboardingStep("MARKETPLACE_RUN_AGENT");
}
completeOnboardingStep("MARKETPLACE_RUN_AGENT");
if (runCount > 0) {
completeOnboardingStep("RE_RUN_AGENT");
}
@@ -210,7 +207,6 @@ export function AgentRunDraftView({
inputCredentials,
onRun,
toastOnFail,
onboardingState,
completeOnboardingStep,
]);
@@ -246,7 +242,6 @@ export function AgentRunDraftView({
onCreatePreset,
toast,
toastOnFail,
onboardingState,
completeOnboardingStep,
]);
@@ -286,7 +281,6 @@ export function AgentRunDraftView({
onUpdatePreset,
toast,
toastOnFail,
onboardingState,
completeOnboardingStep,
]);
@@ -334,7 +328,6 @@ export function AgentRunDraftView({
onCreatePreset,
toast,
toastOnFail,
onboardingState,
completeOnboardingStep,
]);

View File

@@ -171,21 +171,28 @@ export default function Wallet() {
}, [groups]);
// Get total completed count for all groups
const completedCount = useMemo(() => {
return groups.reduce(
const [completedCount, setCompletedCount] = useState<number | null>(null);
// Needed to show confetti when a new step is completed
const [prevCompletedCount, setPrevCompletedCount] = useState<number | null>(
null,
);
const walletRef = useRef<HTMLButtonElement | null>(null);
useEffect(() => {
if (!state) {
return;
}
const completed = groups.reduce(
(acc, group) =>
acc +
group.tasks.filter((task) => state?.completedSteps?.includes(task.id))
.length,
0,
);
setCompletedCount(completed);
}, [groups, state?.completedSteps]);
// Needed to show confetti when a new step is completed
const [stepsLength, setStepsLength] = useState(completedCount);
const walletRef = useRef<HTMLButtonElement | null>(null);
const onWalletOpen = useCallback(async () => {
if (!state?.walletShown) {
updateState({ walletShown: true });
@@ -206,19 +213,25 @@ export default function Wallet() {
// Confetti effect on the wallet button
useEffect(() => {
if (!state?.completedSteps) {
return;
}
// It's enough to check completed count,
// because the order of completed steps is not important
// If the count is the same, we don't need to do anything
if (completedCount === stepsLength) {
if (completedCount === null || completedCount === prevCompletedCount) {
return;
}
// Otherwise, we need to set the new prevCompletedCount
setPrevCompletedCount(completedCount);
// If there was no previous count, we don't show confetti
if (prevCompletedCount === null) {
return;
}
// Otherwise, we need to set the new length
setStepsLength(completedCount);
// And emit confetti
if (walletRef.current) {
// Fix confetti appearing in the top left corner
const rect = walletRef.current.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) {
return;
}
setTimeout(() => {
fetchCredits();
party.confetti(walletRef.current!, {
@@ -236,7 +249,8 @@ export default function Wallet() {
state?.notified,
fadeOut,
fetchCredits,
stepsLength,
completedCount,
prevCompletedCount,
walletRef,
]);
@@ -270,7 +284,7 @@ export default function Wallet() {
<span className="text-sm font-semibold">
{formatCredits(credits)}
</span>
{completedCount < totalCount && (
{completedCount && completedCount < totalCount && (
<span className="absolute right-1 top-1 h-2 w-2 rounded-full bg-violet-600"></span>
)}
<div className="absolute bottom-[-2.5rem] left-1/2 z-50 hidden -translate-x-1/2 transform whitespace-nowrap rounded-small bg-white px-4 py-2 shadow-md group-hover:block">