diff --git a/src-web/components/AppRouter.tsx b/src-web/components/AppRouter.tsx index d65f75b9..3d12fdd8 100644 --- a/src-web/components/AppRouter.tsx +++ b/src-web/components/AppRouter.tsx @@ -1,6 +1,6 @@ import { lazy } from 'react'; import { createBrowserRouter, Navigate, RouterProvider, useParams } from 'react-router-dom'; -import { routePaths, useAppRoutes } from '../hooks/useAppRoutes'; +import { paths, useAppRoutes } from '../hooks/useAppRoutes'; import { DefaultLayout } from './DefaultLayout'; import { RedirectToLatestWorkspace } from './RedirectToLatestWorkspace'; import RouteError from './RouteError'; @@ -19,19 +19,23 @@ const router = createBrowserRouter([ element: , }, { - path: routePaths.workspaces(), + path: paths.workspaces(), element: , }, { - path: routePaths.workspace({ + path: paths.workspace({ workspaceId: ':workspaceId', + environmentId: null, + cookieJarId: null, }), element: , }, { - path: routePaths.request({ + path: paths.request({ workspaceId: ':workspaceId', requestId: ':requestId', + environmentId: null, + cookieJarId: null, }), element: , }, @@ -40,8 +44,10 @@ const router = createBrowserRouter([ element: , }, { - path: routePaths.workspaceSettings({ + path: paths.workspaceSettings({ workspaceId: ':workspaceId', + environmentId: null, + cookieJarId: null, }), element: , }, @@ -64,13 +70,13 @@ function RedirectLegacyEnvironmentURLs() { workspaceId?: string; environmentId?: string; }>(); - const environmentId = rawEnvironmentId === '__default__' ? undefined : rawEnvironmentId; + const environmentId = (rawEnvironmentId === '__default__' ? undefined : rawEnvironmentId) ?? null; let to; if (workspaceId != null && requestId != null) { - to = routes.paths.request({ workspaceId, environmentId, requestId }); + to = routes.paths.request({ workspaceId, environmentId, requestId, cookieJarId: null }); } else if (workspaceId != null) { - to = routes.paths.workspace({ workspaceId, environmentId }); + to = routes.paths.workspace({ workspaceId, environmentId, cookieJarId: null }); } else { to = routes.paths.workspaces(); } diff --git a/src-web/components/CommandPalette.tsx b/src-web/components/CommandPalette.tsx index 3c371203..3079c769 100644 --- a/src-web/components/CommandPalette.tsx +++ b/src-web/components/CommandPalette.tsx @@ -271,7 +271,8 @@ export function CommandPalette({ onClose }: { onClose: () => void }) { return routes.navigate('request', { workspaceId: r.workspaceId, requestId: r.id, - environmentId: activeEnvironment?.id, + environmentId: activeEnvironment?.id ?? null, + cookieJarId: activeCookieJar?.id ?? null, }); }, }); @@ -313,7 +314,8 @@ export function CommandPalette({ onClose }: { onClose: () => void }) { workspaceCommands, sortedRequests, routes, - activeEnvironment, + activeEnvironment?.id, + activeCookieJar?.id, sortedEnvironments, setActiveEnvironmentId, sortedWorkspaces, diff --git a/src-web/components/MoveToWorkspaceDialog.tsx b/src-web/components/MoveToWorkspaceDialog.tsx index bf9ab5ca..72696869 100644 --- a/src-web/components/MoveToWorkspaceDialog.tsx +++ b/src-web/components/MoveToWorkspaceDialog.tsx @@ -71,7 +71,11 @@ export function MoveToWorkspaceDialog({ onDone, request, activeWorkspaceId }: Pr className="mr-auto min-w-[5rem]" onClick={() => { toast.hide('workspace-moved'); - routes.navigate('workspace', { workspaceId: selectedWorkspaceId }); + routes.navigate('workspace', { + workspaceId: selectedWorkspaceId, + cookieJarId: null, + environmentId: null, + }); }} > Switch to Workspace diff --git a/src-web/components/RecentRequestsDropdown.tsx b/src-web/components/RecentRequestsDropdown.tsx index 8cbd9ae5..8250751c 100644 --- a/src-web/components/RecentRequestsDropdown.tsx +++ b/src-web/components/RecentRequestsDropdown.tsx @@ -1,6 +1,7 @@ import classNames from 'classnames'; import { useMemo, useRef } from 'react'; import { useKeyPressEvent } from 'react-use'; +import { useActiveCookieJar } from '../hooks/useActiveCookieJar'; import { useActiveEnvironment } from '../hooks/useActiveEnvironment'; import { useActiveRequest } from '../hooks/useActiveRequest'; import { useActiveWorkspace } from '../hooks/useActiveWorkspace'; @@ -20,6 +21,7 @@ export function RecentRequestsDropdown({ className }: Pick allRecentRequestIds.slice(1), [allRecentRequestIds]); @@ -57,8 +59,9 @@ export function RecentRequestsDropdown({ className }: Pick { routes.navigate('request', { requestId: request.id, - environmentId: activeEnvironment?.id, workspaceId: activeWorkspace.id, + environmentId: activeEnvironment?.id ?? null, + cookieJarId: activeCookieJar?.id ?? null, }); }, }); @@ -76,7 +79,7 @@ export function RecentRequestsDropdown({ className }: Pick diff --git a/src-web/components/RedirectToLatestWorkspace.tsx b/src-web/components/RedirectToLatestWorkspace.tsx index 7b63826c..5c12ced7 100644 --- a/src-web/components/RedirectToLatestWorkspace.tsx +++ b/src-web/components/RedirectToLatestWorkspace.tsx @@ -1,6 +1,7 @@ import { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { useAppRoutes } from '../hooks/useAppRoutes'; +import { getRecentCookieJars } from '../hooks/useRecentCookieJars'; import { getRecentEnvironments } from '../hooks/useRecentEnvironments'; import { getRecentRequests } from '../hooks/useRecentRequests'; import { useRecentWorkspaces } from '../hooks/useRecentWorkspaces'; @@ -20,13 +21,14 @@ export function RedirectToLatestWorkspace() { (async function () { const workspaceId = recentWorkspaces[0] ?? workspaces[0]?.id ?? 'n/a'; - const environmentId = (await getRecentEnvironments(workspaceId))[0]; - const requestId = (await getRecentRequests(workspaceId))[0]; + const environmentId = (await getRecentEnvironments(workspaceId))[0] ?? null; + const cookieJarId = (await getRecentCookieJars(workspaceId))[0] ?? null; + const requestId = (await getRecentRequests(workspaceId))[0] ?? null; if (workspaceId != null && requestId != null) { - navigate(routes.paths.request({ workspaceId, environmentId, requestId })); + navigate(routes.paths.request({ workspaceId, environmentId, requestId, cookieJarId })); } else { - navigate(routes.paths.workspace({ workspaceId, environmentId })); + navigate(routes.paths.workspace({ workspaceId, environmentId, cookieJarId })); } })(); }, [navigate, recentWorkspaces, routes.paths, workspaces, workspaces.length]); diff --git a/src-web/components/Sidebar.tsx b/src-web/components/Sidebar.tsx index 8d425bc5..00f0b964 100644 --- a/src-web/components/Sidebar.tsx +++ b/src-web/components/Sidebar.tsx @@ -13,6 +13,7 @@ import React, { Fragment, useCallback, useMemo, useRef, useState } from 'react'; import type { XYCoord } from 'react-dnd'; import { useDrag, useDrop } from 'react-dnd'; import { useKey, useKeyPressEvent } from 'react-use'; +import { useActiveCookieJar } from '../hooks/useActiveCookieJar'; import { useActiveEnvironment } from '../hooks/useActiveEnvironment'; import { useActiveRequest } from '../hooks/useActiveRequest'; @@ -73,6 +74,7 @@ export function Sidebar({ className }: Props) { const sidebarRef = useRef(null); const activeRequest = useActiveRequest(); const [activeEnvironment] = useActiveEnvironment(); + const [activeCookieJar] = useActiveCookieJar(); const folders = useFolders(); const requests = useRequests(); const activeWorkspace = useActiveWorkspace(); @@ -221,14 +223,22 @@ export function Sidebar({ className }: Props) { routes.navigate('request', { requestId: id, workspaceId: item.workspaceId, - environmentId: activeEnvironment?.id, + environmentId: activeEnvironment?.id ?? null, + cookieJarId: activeCookieJar?.id ?? null, }); setSelectedId(id); setSelectedTree(tree); if (!opts.noFocus) focusActiveRequest({ forced: { id, tree } }); } }, - [treeParentMap, collapsed, routes, activeEnvironment, focusActiveRequest], + [ + treeParentMap, + collapsed, + routes, + activeEnvironment?.id, + activeCookieJar?.id, + focusActiveRequest, + ], ); const handleClearSelected = useCallback(() => { @@ -273,8 +283,9 @@ export function Sidebar({ className }: Props) { e.preventDefault(); routes.navigate('request', { requestId: selected.id, - workspaceId: activeWorkspace?.id, - environmentId: activeEnvironment?.id, + workspaceId: activeWorkspace?.id ?? null, + environmentId: activeEnvironment?.id ?? null, + cookieJarId: activeCookieJar?.id ?? null, }); }); @@ -747,8 +758,8 @@ function SidebarItem({ }, [setEditing, itemModel]); const handleBlur = useCallback( - (e: React.FocusEvent) => { - handleSubmitNameEdit(e.currentTarget); + async (e: React.FocusEvent) => { + await handleSubmitNameEdit(e.currentTarget); }, [handleSubmitNameEdit], ); diff --git a/src-web/hooks/useActiveCookieJar.ts b/src-web/hooks/useActiveCookieJar.ts index 2535e5d3..492f6515 100644 --- a/src-web/hooks/useActiveCookieJar.ts +++ b/src-web/hooks/useActiveCookieJar.ts @@ -18,6 +18,8 @@ export function useActiveCookieJar() { export function useEnsureActiveCookieJar() { const cookieJars = useCookieJars(); const [activeCookieJarId, setActiveCookieJarId] = useActiveCookieJarId(); + + // Set the active cookie jar to the first one, if none set useEffect(() => { if (cookieJars == null) return; // Hasn't loaded yet if (cookieJars.find((j) => j.id === activeCookieJarId)) { diff --git a/src-web/hooks/useActiveRequestId.ts b/src-web/hooks/useActiveRequestId.ts index 34c7e480..ce759748 100644 --- a/src-web/hooks/useActiveRequestId.ts +++ b/src-web/hooks/useActiveRequestId.ts @@ -1,7 +1,6 @@ import { useParams } from 'react-router-dom'; -import type { RouteParamsRequest } from './useAppRoutes'; export function useActiveRequestId(): string | null { - const { requestId } = useParams(); + const { requestId } = useParams(); return requestId ?? null; } diff --git a/src-web/hooks/useActiveWorkspace.ts b/src-web/hooks/useActiveWorkspace.ts index 66d485be..0ec08723 100644 --- a/src-web/hooks/useActiveWorkspace.ts +++ b/src-web/hooks/useActiveWorkspace.ts @@ -1,7 +1,6 @@ import type { Workspace } from '@yaakapp-internal/models'; import { useMemo } from 'react'; import { useParams } from 'react-router-dom'; -import type { RouteParamsWorkspace } from './useAppRoutes'; import { useWorkspaces } from './useWorkspaces'; export function useActiveWorkspace(): Workspace | null { @@ -15,6 +14,6 @@ export function useActiveWorkspace(): Workspace | null { } function useActiveWorkspaceId(): string | null { - const { workspaceId } = useParams(); + const { workspaceId } = useParams(); return workspaceId ?? null; } diff --git a/src-web/hooks/useAppRoutes.tsx b/src-web/hooks/useAppRoutes.tsx index 8e8abdbd..26bb2ce2 100644 --- a/src-web/hooks/useAppRoutes.tsx +++ b/src-web/hooks/useAppRoutes.tsx @@ -1,22 +1,19 @@ -import type { Environment } from '@yaakapp-internal/models'; import { useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; import { QUERY_COOKIE_JAR_ID } from './useActiveCookieJar'; import { QUERY_ENVIRONMENT_ID } from './useActiveEnvironment'; -import { useActiveRequestId } from './useActiveRequestId'; -import { useActiveWorkspace } from './useActiveWorkspace'; export type RouteParamsWorkspace = { workspaceId: string; - environmentId?: string; - cookieJarId?: string; + environmentId: string | null; + cookieJarId: string | null; }; export type RouteParamsRequest = RouteParamsWorkspace & { requestId: string; }; -export const routePaths = { +export const paths = { workspaces() { return '/workspaces'; }, @@ -52,44 +49,21 @@ export const routePaths = { }; export function useAppRoutes() { - const activeWorkspace = useActiveWorkspace(); - const requestId = useActiveRequestId(); const nav = useNavigate(); const navigate = useCallback( - (path: T, ...params: Parameters<(typeof routePaths)[T]>) => { + (path: T, ...params: Parameters<(typeof paths)[T]>) => { // Not sure how to make TS work here, but it's good from the // outside caller perspective. // eslint-disable-next-line @typescript-eslint/no-explicit-any - const resolvedPath = routePaths[path](...(params as any)); + const resolvedPath = paths[path](...(params as any)); nav(resolvedPath); }, [nav], ); - const setEnvironment = useCallback( - (environment: Environment | null) => { - if (activeWorkspace == null) { - navigate('workspaces'); - } else if (requestId == null) { - navigate('workspace', { - workspaceId: activeWorkspace.id, - environmentId: environment == null ? undefined : environment.id, - }); - } else { - navigate('request', { - workspaceId: activeWorkspace.id, - environmentId: environment == null ? undefined : environment.id, - requestId, - }); - } - }, - [navigate, activeWorkspace, requestId], - ); - return { - paths: routePaths, + paths, navigate, - setEnvironment, }; } diff --git a/src-web/hooks/useCreateGrpcRequest.ts b/src-web/hooks/useCreateGrpcRequest.ts index 5571601e..0b0f9580 100644 --- a/src-web/hooks/useCreateGrpcRequest.ts +++ b/src-web/hooks/useCreateGrpcRequest.ts @@ -3,6 +3,7 @@ import type { GrpcRequest } from '@yaakapp-internal/models'; import {useSetAtom} from "jotai"; import { trackEvent } from '../lib/analytics'; import { invokeCmd } from '../lib/tauri'; +import {useActiveCookieJar} from "./useActiveCookieJar"; import { useActiveEnvironment } from './useActiveEnvironment'; import { useActiveRequest } from './useActiveRequest'; import { useActiveWorkspace } from './useActiveWorkspace'; @@ -13,6 +14,7 @@ import {updateModelList} from "./useSyncModelStores"; export function useCreateGrpcRequest() { const workspace = useActiveWorkspace(); const [activeEnvironment] = useActiveEnvironment(); + const [activeCookieJar] = useActiveCookieJar(); const activeRequest = useActiveRequest(); const routes = useAppRoutes(); const setGrpcRequests = useSetAtom(grpcRequestsAtom); @@ -51,7 +53,8 @@ export function useCreateGrpcRequest() { routes.navigate('request', { workspaceId: request.workspaceId, requestId: request.id, - environmentId: activeEnvironment?.id, + environmentId: activeEnvironment?.id ?? null, + cookieJarId: activeCookieJar?.id ?? null, }); }, }); diff --git a/src-web/hooks/useCreateHttpRequest.ts b/src-web/hooks/useCreateHttpRequest.ts index 809fe1c7..0c73b255 100644 --- a/src-web/hooks/useCreateHttpRequest.ts +++ b/src-web/hooks/useCreateHttpRequest.ts @@ -3,6 +3,7 @@ import type { HttpRequest } from '@yaakapp-internal/models'; import { useSetAtom } from 'jotai/index'; import { trackEvent } from '../lib/analytics'; import { invokeCmd } from '../lib/tauri'; +import { useActiveCookieJar } from './useActiveCookieJar'; import { useActiveEnvironment } from './useActiveEnvironment'; import { useActiveRequest } from './useActiveRequest'; import { useActiveWorkspace } from './useActiveWorkspace'; @@ -13,6 +14,7 @@ import { updateModelList } from './useSyncModelStores'; export function useCreateHttpRequest() { const workspace = useActiveWorkspace(); const [activeEnvironment] = useActiveEnvironment(); + const [activeCookieJar] = useActiveCookieJar(); const activeRequest = useActiveRequest(); const routes = useAppRoutes(); const setHttpRequests = useSetAtom(httpRequestsAtom); @@ -25,7 +27,7 @@ export function useCreateHttpRequest() { } if (patch.sortPriority === undefined) { if (activeRequest != null) { - // Place above currently-active request + // Place above currently active request patch.sortPriority = activeRequest.sortPriority - 0.0001; } else { // Place at the very top @@ -45,7 +47,8 @@ export function useCreateHttpRequest() { routes.navigate('request', { workspaceId: request.workspaceId, requestId: request.id, - environmentId: activeEnvironment?.id, + environmentId: activeEnvironment?.id ?? null, + cookieJarId: activeCookieJar?.id ?? null, }); }, }); diff --git a/src-web/hooks/useCreateWorkspace.ts b/src-web/hooks/useCreateWorkspace.ts index 456f6f8a..60cc7c34 100644 --- a/src-web/hooks/useCreateWorkspace.ts +++ b/src-web/hooks/useCreateWorkspace.ts @@ -4,7 +4,7 @@ import { useSetAtom } from 'jotai/index'; import { invokeCmd } from '../lib/tauri'; import { useAppRoutes } from './useAppRoutes'; import { usePrompt } from './usePrompt'; -import {updateModelList} from "./useSyncModelStores"; +import { updateModelList } from './useSyncModelStores'; import { workspacesAtom } from './useWorkspaces'; export function useCreateWorkspace() { @@ -34,7 +34,11 @@ export function useCreateWorkspace() { // Optimistic update setWorkspaces(updateModelList(workspace)); - routes.navigate('workspace', { workspaceId: workspace.id }); + routes.navigate('workspace', { + workspaceId: workspace.id, + environmentId: null, + cookieJarId: null, + }); }, }); } diff --git a/src-web/hooks/useDuplicateGrpcRequest.ts b/src-web/hooks/useDuplicateGrpcRequest.ts index 19a830f7..461f271c 100644 --- a/src-web/hooks/useDuplicateGrpcRequest.ts +++ b/src-web/hooks/useDuplicateGrpcRequest.ts @@ -2,6 +2,7 @@ import { useMutation } from '@tanstack/react-query'; import type { GrpcRequest } from '@yaakapp-internal/models'; import { trackEvent } from '../lib/analytics'; import { invokeCmd } from '../lib/tauri'; +import {useActiveCookieJar} from "./useActiveCookieJar"; import { useActiveEnvironment } from './useActiveEnvironment'; import { useActiveWorkspace } from './useActiveWorkspace'; import { useAppRoutes } from './useAppRoutes'; @@ -16,6 +17,7 @@ export function useDuplicateGrpcRequest({ }) { const activeWorkspace = useActiveWorkspace(); const [activeEnvironment] = useActiveEnvironment(); + const [activeCookieJar] = useActiveCookieJar(); const routes = useAppRoutes(); return useMutation({ @@ -36,7 +38,8 @@ export function useDuplicateGrpcRequest({ routes.navigate('request', { workspaceId: activeWorkspace.id, requestId: request.id, - environmentId: activeEnvironment?.id, + environmentId: activeEnvironment?.id ?? null, + cookieJarId: activeCookieJar?.id ?? null, }); } }, diff --git a/src-web/hooks/useDuplicateHttpRequest.ts b/src-web/hooks/useDuplicateHttpRequest.ts index 916035cd..1032ef18 100644 --- a/src-web/hooks/useDuplicateHttpRequest.ts +++ b/src-web/hooks/useDuplicateHttpRequest.ts @@ -2,6 +2,7 @@ import { useMutation } from '@tanstack/react-query'; import type { HttpRequest } from '@yaakapp-internal/models'; import { trackEvent } from '../lib/analytics'; import { invokeCmd } from '../lib/tauri'; +import {useActiveCookieJar} from "./useActiveCookieJar"; import { useActiveEnvironment } from './useActiveEnvironment'; import { useActiveWorkspace } from './useActiveWorkspace'; import { useAppRoutes } from './useAppRoutes'; @@ -15,6 +16,7 @@ export function useDuplicateHttpRequest({ }) { const activeWorkspace = useActiveWorkspace(); const [activeEnvironment] = useActiveEnvironment(); + const [activeCookieJar] = useActiveCookieJar(); const routes = useAppRoutes(); return useMutation({ mutationKey: ['duplicate_http_request', id], @@ -28,7 +30,8 @@ export function useDuplicateHttpRequest({ routes.navigate('request', { workspaceId: activeWorkspace.id, requestId: request.id, - environmentId: activeEnvironment?.id, + environmentId: activeEnvironment?.id ?? null, + cookieJarId: activeCookieJar?.id ?? null, }); } }, diff --git a/src-web/hooks/useImportData.tsx b/src-web/hooks/useImportData.tsx index c1046181..b1210475 100644 --- a/src-web/hooks/useImportData.tsx +++ b/src-web/hooks/useImportData.tsx @@ -66,7 +66,8 @@ export function useImportData() { if (importedWorkspace != null) { routes.navigate('workspace', { workspaceId: importedWorkspace.id, - environmentId: imported.environments[0]?.id, + environmentId: imported.environments[0]?.id ?? null, + cookieJarId: null, }); } diff --git a/src-web/hooks/useOpenSettings.tsx b/src-web/hooks/useOpenSettings.tsx index 62eb215d..4c2ec4ad 100644 --- a/src-web/hooks/useOpenSettings.tsx +++ b/src-web/hooks/useOpenSettings.tsx @@ -12,7 +12,11 @@ export function useOpenSettings() { if (workspace == null) return; await invokeCmd('cmd_new_child_window', { - url: routes.paths.workspaceSettings({ workspaceId: workspace.id }), + url: routes.paths.workspaceSettings({ + workspaceId: workspace.id, + cookieJarId: null, + environmentId: null, + }), label: 'settings', title: 'Yaak Settings', innerSize: [600, 550], diff --git a/src-web/hooks/useOpenWorkspace.ts b/src-web/hooks/useOpenWorkspace.ts index a0bb7519..8472605a 100644 --- a/src-web/hooks/useOpenWorkspace.ts +++ b/src-web/hooks/useOpenWorkspace.ts @@ -17,9 +17,9 @@ export function useOpenWorkspace() { workspaceId: string; inNewWindow: boolean; }) => { - const environmentId = (await getRecentEnvironments(workspaceId))[0]; - const requestId = (await getRecentRequests(workspaceId))[0]; - const cookieJarId = (await getRecentCookieJars(workspaceId))[0]; + const environmentId = (await getRecentEnvironments(workspaceId))[0] ?? null; + const requestId = (await getRecentRequests(workspaceId))[0] ?? null; + const cookieJarId = (await getRecentCookieJars(workspaceId))[0] ?? null; const baseArgs = { workspaceId, environmentId, cookieJarId } as const; if (inNewWindow) { const path = diff --git a/src-web/hooks/useTemplateFunctions.ts b/src-web/hooks/useTemplateFunctions.ts index 904efbc7..07e44118 100644 --- a/src-web/hooks/useTemplateFunctions.ts +++ b/src-web/hooks/useTemplateFunctions.ts @@ -13,6 +13,7 @@ export function useTemplateFunctions() { // Fetch periodically until functions are returned // NOTE: visibilitychange (refetchOnWindowFocus) does not work on Windows, so we'll rely on this logic // to refetch things until that's working again + // TODO: Update plugin system to wait for plugins to initialize before sending the first event to them refetchInterval: numFns > 0 ? Infinity : 500, refetchOnMount: true, queryFn: async () => {