diff --git a/package-lock.json b/package-lock.json index dd2464cc..406f630b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8873,12 +8873,12 @@ } }, "node_modules/lucide-react": { - "version": "0.439.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.439.0.tgz", - "integrity": "sha512-PafSWvDTpxdtNEndS2HIHxcNAbd54OaqSYJO90/b63rab2HWYqDbH194j0i82ZFdWOAcf0AHinRykXRRK2PJbw==", + "version": "0.474.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.474.0.tgz", + "integrity": "sha512-CmghgHkh0OJNmxGKWc0qfPJCYHASPMVSyGY8fj3xgk4v84ItqDg64JNKFZn5hC6E0vHi6gxnbCgwhyVB09wQtA==", "license": "ISC", "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/make-cancellable-promise": { @@ -15491,7 +15491,7 @@ }, "packages/plugin-runtime-types": { "name": "@yaakapp/api", - "version": "0.4.0", + "version": "0.4.1", "dependencies": { "@types/node": "^22.5.4" }, @@ -15657,7 +15657,7 @@ "history": "^5.3.0", "jotai": "^2.9.3", "js-md5": "^0.8.3", - "lucide-react": "^0.439.0", + "lucide-react": "^0.474.0", "mime": "^4.0.4", "nanoid": "^5.0.9", "papaparse": "^5.4.1", diff --git a/src-web/components/GrpcConnectionMessagesPane.tsx b/src-web/components/GrpcConnectionMessagesPane.tsx index 643bd76e..8843fc1f 100644 --- a/src-web/components/GrpcConnectionMessagesPane.tsx +++ b/src-web/components/GrpcConnectionMessagesPane.tsx @@ -14,6 +14,7 @@ import { Icon } from './core/Icon'; import { IconButton } from './core/IconButton'; import { JsonAttributeTree } from './core/JsonAttributeTree'; import { KeyValueRow, KeyValueRows } from './core/KeyValueRow'; +import { LoadingIcon } from './core/LoadingIcon'; import { Separator } from './core/Separator'; import { SplitLayout } from './core/SplitLayout'; import { HStack, VStack } from './core/Stacks'; @@ -70,7 +71,7 @@ export function GrpcConnectionMessagesPane({ style, methodType, activeRequest }: {events.length} Messages {activeConnection.state !== 'closed' && ( - + )}
diff --git a/src-web/components/HttpResponsePane.tsx b/src-web/components/HttpResponsePane.tsx index 38688ea3..217b7244 100644 --- a/src-web/components/HttpResponsePane.tsx +++ b/src-web/components/HttpResponsePane.tsx @@ -11,7 +11,7 @@ import { Banner } from './core/Banner'; import { CountBadge } from './core/CountBadge'; import { DurationTag } from './core/DurationTag'; import { HotKeyList } from './core/HotKeyList'; -import { Icon } from './core/Icon'; +import { LoadingIcon } from './core/LoadingIcon'; import { SizeTag } from './core/SizeTag'; import { HStack } from './core/Stacks'; import { StatusTag } from './core/StatusTag'; @@ -120,7 +120,7 @@ export function HttpResponsePane({ style, className, activeRequestId }: Props) { 'whitespace-nowrap w-full pl-3 overflow-x-auto font-mono text-sm', )} > - {activeResponse.state !== 'closed' && } + {activeResponse.state !== 'closed' && } {activeResponse.state === 'initialized' ? ( - + ) : activeResponse.state === 'closed' && activeResponse.contentLength === 0 ? ( Empty @@ -217,7 +217,7 @@ function EnsureCompleteResponse({ if (response.state !== 'closed') { return ( - + ); } diff --git a/src-web/components/WebsocketResponsePane.tsx b/src-web/components/WebsocketResponsePane.tsx index 9f89efdf..0c2b2a85 100644 --- a/src-web/components/WebsocketResponsePane.tsx +++ b/src-web/components/WebsocketResponsePane.tsx @@ -15,6 +15,7 @@ import { Button } from './core/Button'; import { Editor } from './core/Editor/Editor'; import { Icon } from './core/Icon'; import { IconButton } from './core/IconButton'; +import { LoadingIcon } from './core/LoadingIcon'; import { Separator } from './core/Separator'; import { SplitLayout } from './core/SplitLayout'; import { HStack, VStack } from './core/Stacks'; @@ -71,7 +72,7 @@ export function WebsocketResponsePane({ activeRequest }: Props) { {activeConnection.state !== 'closed' && ( - + )} diff --git a/src-web/components/core/Button.tsx b/src-web/components/core/Button.tsx index ffb79982..14564426 100644 --- a/src-web/components/core/Button.tsx +++ b/src-web/components/core/Button.tsx @@ -5,6 +5,7 @@ import type { HotkeyAction } from '../../hooks/useHotKey'; import { useFormattedHotkey, useHotKey } from '../../hooks/useHotKey'; import { trackEvent } from '../../lib/analytics'; import { Icon } from './Icon'; +import { LoadingIcon } from './LoadingIcon'; export type ButtonProps = Omit, 'color' | 'onChange'> & { innerClassName?: string; @@ -125,7 +126,7 @@ export const Button = forwardRef(function Button {...props} > {isLoading ? ( - + ) : leftSlot ? (
{leftSlot}
) : null} diff --git a/src-web/components/core/LoadingIcon.tsx b/src-web/components/core/LoadingIcon.tsx new file mode 100644 index 00000000..0353baa8 --- /dev/null +++ b/src-web/components/core/LoadingIcon.tsx @@ -0,0 +1,35 @@ +import classNames from 'classnames'; + +interface Props { + size?: '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; + className?: string; +} + +export function LoadingIcon({ size = 'md', className }: Props) { + const classes = classNames( + className, + 'text-inherit flex-shrink-0', + size === 'xl' && 'h-6 w-6', + size === 'lg' && 'h-5 w-5', + size === 'md' && 'h-4 w-4', + size === 'sm' && 'h-3.5 w-3.5', + size === 'xs' && 'h-3 w-3', + size === '2xs' && 'h-2.5 w-2.5', + 'animate-spin', + ); + + return ( +
+ ); +} diff --git a/src-web/components/responseViewers/BinaryViewer.tsx b/src-web/components/responseViewers/BinaryViewer.tsx index fcadcdbe..50cf269a 100644 --- a/src-web/components/responseViewers/BinaryViewer.tsx +++ b/src-web/components/responseViewers/BinaryViewer.tsx @@ -1,10 +1,10 @@ -import { useSaveResponse } from '../../hooks/useSaveResponse'; import type { HttpResponse } from '@yaakapp-internal/models'; +import { useSaveResponse } from '../../hooks/useSaveResponse'; import { getContentTypeHeader } from '../../lib/model_util'; import { Banner } from '../core/Banner'; import { Button } from '../core/Button'; -import { Icon } from '../core/Icon'; import { InlineCode } from '../core/InlineCode'; +import { LoadingIcon } from '../core/LoadingIcon'; import { EmptyStateText } from '../EmptyStateText'; interface Props { @@ -19,7 +19,7 @@ export function BinaryViewer({ response }: Props) { if (response.state === 'closed') { return ( - + ); } diff --git a/src-web/components/sidebar/Sidebar.tsx b/src-web/components/sidebar/Sidebar.tsx index 51658d8b..9a589970 100644 --- a/src-web/components/sidebar/Sidebar.tsx +++ b/src-web/components/sidebar/Sidebar.tsx @@ -14,9 +14,7 @@ import { getActiveRequest } from '../../hooks/useActiveRequest'; import { useActiveWorkspace } from '../../hooks/useActiveWorkspace'; import { useCreateDropdownItems } from '../../hooks/useCreateDropdownItems'; import { useDeleteAnyRequest } from '../../hooks/useDeleteAnyRequest'; -import { useGrpcConnections } from '../../hooks/useGrpcConnections'; import { useHotKey } from '../../hooks/useHotKey'; -import { useHttpResponses } from '../../hooks/useHttpResponses'; import { useSidebarHidden } from '../../hooks/useSidebarHidden'; import { getSidebarCollapsedMap } from '../../hooks/useSidebarItemCollapsed'; import { useUpdateAnyFolder } from '../../hooks/useUpdateAnyFolder'; @@ -51,8 +49,6 @@ export function Sidebar({ className }: Props) { const [hidden, setHidden] = useSidebarHidden(); const sidebarRef = useRef(null); const activeWorkspace = useActiveWorkspace(); - const httpResponses = useHttpResponses(); - const grpcConnections = useGrpcConnections(); const [hasFocus, setHasFocus] = useState(false); const [selectedId, setSelectedId] = useAtom(sidebarSelectedIdAtom); const [selectedTree, setSelectedTree] = useState(null); @@ -372,8 +368,6 @@ export function Sidebar({ className }: Props) { ; type DragItem = { @@ -58,6 +65,7 @@ export const SidebarItem = memo(function SidebarItem({ className, latestHttpResponse, latestGrpcConnection, + latestWebsocketConnection, children, }: SidebarItemProps) { const ref = useRef(null); @@ -283,13 +291,19 @@ export const SidebarItem = memo(function SidebarItem({ {latestGrpcConnection ? (
{latestGrpcConnection.state !== 'closed' && ( - + + )} +
+ ) : latestWebsocketConnection ? ( +
+ {latestWebsocketConnection.state !== 'closed' && ( + )}
) : latestHttpResponse ? (
{latestHttpResponse.state !== 'closed' ? ( - + ) : ( )} diff --git a/src-web/components/sidebar/SidebarItems.tsx b/src-web/components/sidebar/SidebarItems.tsx index 0722ca41..7099278f 100644 --- a/src-web/components/sidebar/SidebarItems.tsx +++ b/src-web/components/sidebar/SidebarItems.tsx @@ -1,6 +1,8 @@ -import type { GrpcConnection, HttpResponse } from '@yaakapp-internal/models'; import classNames from 'classnames'; import React, { Fragment, memo } from 'react'; +import { useGrpcConnections } from '../../hooks/useGrpcConnections'; +import { useHttpResponses } from '../../hooks/useHttpResponses'; +import { useWebsocketConnections } from '../../hooks/useWebsocketConnections'; import { VStack } from '../core/Stacks'; import { DropMarker } from '../DropMarker'; import type { SidebarTreeNode } from './Sidebar'; @@ -17,8 +19,6 @@ export interface SidebarItemsProps { handleEnd: (id: string) => void; handleDragStart: (id: string) => void; onSelect: (requestId: string) => void; - httpResponses: HttpResponse[]; - grpcConnections: GrpcConnection[]; } export const SidebarItems = memo(function SidebarItems({ @@ -32,9 +32,11 @@ export const SidebarItems = memo(function SidebarItems({ handleEnd, handleMove, handleDragStart, - httpResponses, - grpcConnections, }: SidebarItemsProps) { + const httpResponses = useHttpResponses(); + const grpcConnections = useGrpcConnections(); + const websocketConnections = useWebsocketConnections(); + return ( r.requestId === child.id) ?? null} latestGrpcConnection={grpcConnections.find((c) => c.requestId === child.id) ?? null} + latestWebsocketConnection={ + websocketConnections.find((c) => c.requestId === child.id) ?? null + } onMove={handleMove} onEnd={handleEnd} onSelect={onSelect} @@ -71,8 +76,6 @@ export const SidebarItems = memo(function SidebarItems({ handleMove={handleMove} hoveredIndex={hoveredIndex} hoveredTree={hoveredTree} - httpResponses={httpResponses} - grpcConnections={grpcConnections} onSelect={onSelect} selectedTree={selectedTree} tree={child} diff --git a/src-web/package.json b/src-web/package.json index b32bfe9a..c54ff187 100644 --- a/src-web/package.json +++ b/src-web/package.json @@ -49,7 +49,7 @@ "history": "^5.3.0", "jotai": "^2.9.3", "js-md5": "^0.8.3", - "lucide-react": "^0.439.0", + "lucide-react": "^0.474.0", "mime": "^4.0.4", "nanoid": "^5.0.9", "papaparse": "^5.4.1",