From d7b91e1a204051b4fbd42dd730df49f639263bc5 Mon Sep 17 00:00:00 2001 From: Prakash Maheshwaran <73785492+Prakashmaheshwaran@users.noreply.github.com> Date: Fri, 4 Jul 2025 17:11:26 -0400 Subject: [PATCH] add .cursor/rules to gitignore (#2883) --- .../panels/WorkflowNodeLibraryPanel.tsx | 40 +----------- ...seOptimisticallyRequestBrowserSessionId.ts | 65 +++++++++++++++++++ 2 files changed, 66 insertions(+), 39 deletions(-) create mode 100644 skyvern-frontend/src/store/useOptimisticallyRequestBrowserSessionId.ts diff --git a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowNodeLibraryPanel.tsx b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowNodeLibraryPanel.tsx index b3fe47e6..0aa02f18 100644 --- a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowNodeLibraryPanel.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowNodeLibraryPanel.tsx @@ -1,6 +1,6 @@ import { ScrollArea, ScrollAreaViewport } from "@/components/ui/scroll-area"; import { useWorkflowPanelStore } from "@/store/WorkflowPanelStore"; -import { useState, useRef, useEffect } from "react"; +import { useState } from "react"; import { Cross2Icon, PlusIcon, @@ -232,45 +232,10 @@ function WorkflowNodeLibraryPanel({ onNodeClick, first }: Props) { const workflowPanelData = useWorkflowPanelStore( (state) => state.workflowPanelState.data, ); - const workflowPanelActive = useWorkflowPanelStore( - (state) => state.workflowPanelState.active, - ); const closeWorkflowPanel = useWorkflowPanelStore( (state) => state.closeWorkflowPanel, ); const [search, setSearch] = useState(""); - const inputRef = useRef(null); - - useEffect(() => { - // Focus the input when the panel becomes active - if (workflowPanelActive && inputRef.current) { - // Use multiple approaches to ensure focus works - const focusInput = () => { - if (inputRef.current) { - inputRef.current.focus(); - inputRef.current.select(); // Also select any existing text - } - }; - - // Try immediate focus - focusInput(); - - // Also try with a small delay for animations/transitions - const timeoutId = setTimeout(() => { - focusInput(); - }, 100); - - // And try with a longer delay as backup - const backupTimeoutId = setTimeout(() => { - focusInput(); - }, 300); - - return () => { - clearTimeout(timeoutId); - clearTimeout(backupTimeoutId); - }; - } - }, [workflowPanelActive]); const filteredItems = nodeLibraryItems.filter((item) => { if (workflowPanelData?.disableLoop && item.nodeType === "loop") { @@ -323,9 +288,6 @@ function WorkflowNodeLibraryPanel({ onNodeClick, first }: Props) { }} placeholder="Search blocks..." className="pl-9" - ref={inputRef} - autoFocus - tabIndex={0} /> diff --git a/skyvern-frontend/src/store/useOptimisticallyRequestBrowserSessionId.ts b/skyvern-frontend/src/store/useOptimisticallyRequestBrowserSessionId.ts new file mode 100644 index 00000000..cf9bed0f --- /dev/null +++ b/skyvern-frontend/src/store/useOptimisticallyRequestBrowserSessionId.ts @@ -0,0 +1,65 @@ +import { create } from "zustand"; +import { AxiosInstance } from "axios"; + +export interface BrowserSessionData { + browser_session_id: string | null; + expires_at: number | null; // seconds since epoch +} + +interface OptimisticBrowserSessionIdState extends BrowserSessionData { + run: (client: AxiosInstance) => Promise; +} + +const SESSION_KEY = "skyvern.optimisticBrowserSession"; +const SESSION_TIMEOUT_MINUTES = 60; + +export const useOptimisticallyRequestBrowserSessionId = + create((set) => ({ + browser_session_id: null, + expires_at: null, + run: async (client) => { + const stored = localStorage.getItem(SESSION_KEY); + if (stored) { + try { + const parsed = JSON.parse(stored); + const { browser_session_id, expires_at } = parsed; + const now = Math.floor(Date.now() / 1000); // seconds since epoch + + if ( + browser_session_id && + typeof browser_session_id === "string" && + expires_at && + typeof expires_at === "number" && + now < expires_at + ) { + set({ browser_session_id, expires_at }); + return { browser_session_id, expires_at }; + } + } catch (e) { + // pass + } + } + + const resp = await client.post("/browser_sessions", { + timeout: SESSION_TIMEOUT_MINUTES * 60, // accepts seconds, so have to mult + }); + const { browser_session_id: newBrowserSessionId, timeout } = resp.data; + const newExpiresAt = Math.floor(Date.now() / 1000) + timeout * 0.9; + set({ + browser_session_id: newBrowserSessionId, + expires_at: newExpiresAt, + }); + localStorage.setItem( + SESSION_KEY, + JSON.stringify({ + browser_session_id: newBrowserSessionId, + expires_at: newExpiresAt, + }), + ); + + return { + browser_session_id: newBrowserSessionId, + expires_at: newExpiresAt, + }; + }, + }));