mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-21 17:09:09 +01:00
Clean up model fetching and loading states
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import type { WorkspaceMeta } from '@yaakapp-internal/models';
|
||||
import { useState } from 'react';
|
||||
import { upsertWorkspace } from '../commands/upsertWorkspace';
|
||||
import { upsertWorkspaceMeta } from '../commands/upsertWorkspaceMeta';
|
||||
import { router } from '../lib/router';
|
||||
import { getWorkspaceMeta } from '../lib/store';
|
||||
import { invokeCmd } from '../lib/tauri';
|
||||
import { Button } from './core/Button';
|
||||
import { PlainInput } from './core/PlainInput';
|
||||
import { VStack } from './core/Stacks';
|
||||
@@ -29,7 +30,9 @@ export function CreateWorkspaceDialog({ hide }: Props) {
|
||||
|
||||
// Do getWorkspaceMeta instead of naively creating one because it might have
|
||||
// been created already when the store refreshes the workspace meta after
|
||||
const workspaceMeta = await getWorkspaceMeta(workspace.id);
|
||||
const workspaceMeta = await invokeCmd<WorkspaceMeta>('cmd_get_workspace_meta', {
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
upsertWorkspaceMeta.mutate({ ...workspaceMeta, settingSyncDir });
|
||||
|
||||
// Navigate to workspace
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { GrpcEvent, GrpcRequest } from '@yaakapp-internal/models';
|
||||
import classNames from 'classnames';
|
||||
import { format } from 'date-fns';
|
||||
import type { CSSProperties } from 'react';
|
||||
@@ -5,8 +6,6 @@ import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useGrpcEvents } from '../hooks/useGrpcEvents';
|
||||
import { usePinnedGrpcConnection } from '../hooks/usePinnedGrpcConnection';
|
||||
import { useStateWithDeps } from '../hooks/useStateWithDeps';
|
||||
import type { GrpcEvent, GrpcRequest } from '@yaakapp-internal/models';
|
||||
import { isResponseLoading } from '../lib/model_util';
|
||||
import { Banner } from './core/Banner';
|
||||
import { Button } from './core/Button';
|
||||
import { Icon } from './core/Icon';
|
||||
@@ -66,7 +65,7 @@ export function GrpcConnectionMessagesPane({ style, methodType, activeRequest }:
|
||||
<HStack className="pl-3 mb-1 font-mono text-sm">
|
||||
<HStack space={2}>
|
||||
<span>{events.length} Messages</span>
|
||||
{isResponseLoading(activeConnection) && (
|
||||
{activeConnection.state !== 'closed' && (
|
||||
<Icon icon="refresh" size="sm" spin className="text-text-subtlest" />
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
@@ -12,7 +12,6 @@ import { useHttpAuthentication } from '../hooks/useHttpAuthentication';
|
||||
import { httpRequestsAtom } from '../hooks/useHttpRequests';
|
||||
import { useImportCurl } from '../hooks/useImportCurl';
|
||||
import { useImportQuerystring } from '../hooks/useImportQuerystring';
|
||||
import { useIsResponseLoading } from '../hooks/useIsResponseLoading';
|
||||
import { usePinnedHttpResponse } from '../hooks/usePinnedHttpResponse';
|
||||
import { useRequestEditor, useRequestEditorEvent } from '../hooks/useRequestEditor';
|
||||
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
|
||||
@@ -277,7 +276,6 @@ export const RequestPane = memo(function RequestPane({
|
||||
],
|
||||
);
|
||||
|
||||
const isLoading = useIsResponseLoading(activeRequestId);
|
||||
const { mutate: sendRequest } = useSendAnyHttpRequest();
|
||||
const { activeResponse } = usePinnedHttpResponse(activeRequestId);
|
||||
const { mutate: cancelResponse } = useCancelHttpResponse(activeResponse?.id ?? null);
|
||||
@@ -370,7 +368,7 @@ export const RequestPane = memo(function RequestPane({
|
||||
onMethodChange={handleMethodChange}
|
||||
onUrlChange={handleUrlChange}
|
||||
forceUpdateKey={updateKey}
|
||||
isLoading={isLoading}
|
||||
isLoading={activeResponse?.state !== 'closed'}
|
||||
/>
|
||||
<Tabs
|
||||
key={activeRequest.id} // Freshen tabs on request change
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useLocalStorage } from 'react-use';
|
||||
import { useContentTypeFromHeaders } from '../hooks/useContentTypeFromHeaders';
|
||||
import { usePinnedHttpResponse } from '../hooks/usePinnedHttpResponse';
|
||||
import { useResponseViewMode } from '../hooks/useResponseViewMode';
|
||||
import { isResponseLoading } from '../lib/model_util';
|
||||
import { ConfirmLargeResponse } from './ConfirmLargeResponse';
|
||||
import { Banner } from './core/Banner';
|
||||
import { CountBadge } from './core/CountBadge';
|
||||
import { DurationTag } from './core/DurationTag';
|
||||
@@ -29,7 +29,6 @@ import { ImageViewer } from './responseViewers/ImageViewer';
|
||||
import { PdfViewer } from './responseViewers/PdfViewer';
|
||||
import { SvgViewer } from './responseViewers/SvgViewer';
|
||||
import { VideoViewer } from './responseViewers/VideoViewer';
|
||||
import { ConfirmLargeResponse } from './ConfirmLargeResponse';
|
||||
|
||||
interface Props {
|
||||
style?: CSSProperties;
|
||||
@@ -92,8 +91,6 @@ export const ResponsePane = memo(function ResponsePane({
|
||||
[activeRequestId, setActiveTabs],
|
||||
);
|
||||
|
||||
const isLoading = isResponseLoading(activeResponse);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={style}
|
||||
@@ -127,7 +124,7 @@ export const ResponsePane = memo(function ResponsePane({
|
||||
'whitespace-nowrap w-full pl-3 overflow-x-auto font-mono text-sm',
|
||||
)}
|
||||
>
|
||||
{isLoading && <Icon size="sm" icon="refresh" spin />}
|
||||
{activeResponse.state !== 'closed' && <Icon size="sm" icon="refresh" spin />}
|
||||
<StatusTag showReason response={activeResponse} />
|
||||
<span>•</span>
|
||||
<DurationTag
|
||||
@@ -164,7 +161,11 @@ export const ResponsePane = memo(function ResponsePane({
|
||||
>
|
||||
<TabContent value={TAB_BODY}>
|
||||
<ConfirmLargeResponse response={activeResponse}>
|
||||
{!activeResponse.contentLength ? (
|
||||
{activeResponse.state === 'initialized' ? (
|
||||
<EmptyStateText>
|
||||
<Icon size="xl" spin icon="refresh" className="text-text-subtlest" />
|
||||
</EmptyStateText>
|
||||
) : activeResponse.state === 'closed' && activeResponse.contentLength === 0 ? (
|
||||
<div className="pb-2 h-full">
|
||||
<EmptyStateText>Empty Body</EmptyStateText>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,6 @@ import { useSidebarItemCollapsed } from '../hooks/useSidebarItemCollapsed';
|
||||
import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest';
|
||||
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
|
||||
import { jotaiStore } from '../lib/jotai';
|
||||
import { isResponseLoading } from '../lib/model_util';
|
||||
import { HttpMethodTag } from './core/HttpMethodTag';
|
||||
import { Icon } from './core/Icon';
|
||||
import { StatusTag } from './core/StatusTag';
|
||||
@@ -277,13 +276,13 @@ export const SidebarItem = memo(function SidebarItem({
|
||||
</div>
|
||||
{latestGrpcConnection ? (
|
||||
<div className="ml-auto">
|
||||
{isResponseLoading(latestGrpcConnection) && (
|
||||
{latestGrpcConnection.state !== 'closed' && (
|
||||
<Icon spin size="sm" icon="update" className="text-text-subtlest" />
|
||||
)}
|
||||
</div>
|
||||
) : latestHttpResponse ? (
|
||||
<div className="ml-auto">
|
||||
{isResponseLoading(latestHttpResponse) ? (
|
||||
{latestHttpResponse.state !== 'closed' ? (
|
||||
<Icon spin size="sm" icon="refresh" className="text-text-subtlest" />
|
||||
) : (
|
||||
<StatusTag className="text-xs" response={latestHttpResponse} />
|
||||
|
||||
@@ -13,12 +13,12 @@ import { useSendManyRequests } from '../hooks/useSendManyRequests';
|
||||
import { useWorkspaces } from '../hooks/useWorkspaces';
|
||||
|
||||
import { showDialog } from '../lib/dialog';
|
||||
import { getHttpRequest } from '../lib/store';
|
||||
import type { DropdownItem } from './core/Dropdown';
|
||||
import { ContextMenu } from './core/Dropdown';
|
||||
import { Icon } from './core/Icon';
|
||||
import { FolderSettingsDialog } from './FolderSettingsDialog';
|
||||
import type { SidebarTreeNode } from './Sidebar';
|
||||
import { getHttpRequest } from '../hooks/useHttpRequests';
|
||||
|
||||
interface Props {
|
||||
child: SidebarTreeNode;
|
||||
@@ -97,7 +97,7 @@ export function SidebarItemContextMenu({ child, show, close }: Props) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
leftSlot: <Icon icon={(a.icon as any) ?? 'empty'} />,
|
||||
onSelect: async () => {
|
||||
const request = await getHttpRequest(child.id);
|
||||
const request = getHttpRequest(child.id);
|
||||
if (request != null) await a.call(request);
|
||||
},
|
||||
})),
|
||||
|
||||
@@ -8,11 +8,10 @@ import { useCreateWorkspace } from '../hooks/useCreateWorkspace';
|
||||
import { useDeleteSendHistory } from '../hooks/useDeleteSendHistory';
|
||||
import { settingsAtom } from '../hooks/useSettings';
|
||||
import { useWorkspaceMeta } from '../hooks/useWorkspaceMeta';
|
||||
import { useWorkspaces } from '../hooks/useWorkspaces';
|
||||
import { getWorkspace, useWorkspaces } from '../hooks/useWorkspaces';
|
||||
import { showDialog } from '../lib/dialog';
|
||||
import { jotaiStore } from '../lib/jotai';
|
||||
import { revealInFinderText } from '../lib/reveal';
|
||||
import { getWorkspace } from '../lib/store';
|
||||
import type { ButtonProps } from './core/Button';
|
||||
import { Button } from './core/Button';
|
||||
import type { DropdownItem } from './core/Dropdown';
|
||||
@@ -106,7 +105,7 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
||||
return;
|
||||
}
|
||||
|
||||
const workspace = await getWorkspace(workspaceId);
|
||||
const workspace = getWorkspace(workspaceId);
|
||||
if (workspace == null) return;
|
||||
|
||||
showDialog({
|
||||
|
||||
@@ -94,7 +94,7 @@ const icons = {
|
||||
export interface IconProps {
|
||||
icon: keyof typeof icons;
|
||||
className?: string;
|
||||
size?: '2xs' | 'xs' | 'sm' | 'md' | 'lg';
|
||||
size?: '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
spin?: boolean;
|
||||
title?: string;
|
||||
}
|
||||
@@ -107,6 +107,7 @@ export const Icon = memo(function Icon({ icon, spin, size = 'md', className, tit
|
||||
className={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',
|
||||
|
||||
@@ -16,7 +16,7 @@ export function BinaryViewer({ response }: Props) {
|
||||
const contentType = getContentTypeHeader(response.headers) ?? 'unknown';
|
||||
|
||||
// Wait until the response has been fully-downloaded
|
||||
if (response.state !== 'closed') {
|
||||
if (response.state === 'closed') {
|
||||
return (
|
||||
<EmptyStateText>
|
||||
<Icon icon="refresh" spin />
|
||||
|
||||
@@ -19,10 +19,11 @@ export function HTMLOrTextViewer({ response, pretty, textViewerClassName }: Prop
|
||||
rawTextBody.data ?? '',
|
||||
);
|
||||
|
||||
if (rawTextBody.isLoading) {
|
||||
if (rawTextBody.isLoading || response.state === 'initialized') {
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log("HELLO", rawTextBody.data, response);
|
||||
// Wasn't able to decode as text, so it must be binary
|
||||
if (rawTextBody.data == null) {
|
||||
return <BinaryViewer response={response} />;
|
||||
|
||||
Reference in New Issue
Block a user