Sidebar methods and fix model hooks

This commit is contained in:
Gregory Schier
2024-02-09 16:09:24 -08:00
parent 017de296a0
commit 7a960574a5
7 changed files with 84 additions and 50 deletions

View File

@@ -1564,7 +1564,7 @@ fn main() {
"App Config Dir: {}",
app_config_dir.as_path().to_string_lossy(),
);
info!("App Data Dir: {}", app_data_dir.as_path().to_string_lossy(),);
info!("App Data Dir: {}", app_data_dir.as_path().to_string_lossy());
let dir = match is_dev() {
true => current_dir().unwrap(),
false => app_data_dir,

View File

@@ -46,8 +46,6 @@ export function GlobalHooks() {
}, [location.pathname]);
useListenToTauriEvent<Model>('upserted_model', ({ payload, windowLabel }) => {
if (shouldIgnoreEvent(payload, windowLabel)) return;
const queryKey =
payload.model === 'http_request'
? httpRequestsQueryKey(payload)
@@ -74,7 +72,7 @@ export function GlobalHooks() {
return;
}
if (payload.model === 'http_request') {
if (payload.model === 'http_request' && windowLabel !== appWindow.label) {
wasUpdatedExternally(payload.id);
}
@@ -82,21 +80,19 @@ export function GlobalHooks() {
payload.model,
);
if (!shouldIgnoreModel(payload)) {
queryClient.setQueryData<Model[]>(queryKey, (values = []) => {
const index = values.findIndex((v) => modelsEq(v, payload)) ?? -1;
if (index >= 0) {
return [...values.slice(0, index), payload, ...values.slice(index + 1)];
} else {
return pushToFront ? [payload, ...(values ?? [])] : [...(values ?? []), payload];
}
});
}
if (shouldIgnoreModel(payload)) return;
queryClient.setQueryData<Model[]>(queryKey, (values = []) => {
const index = values.findIndex((v) => modelsEq(v, payload)) ?? -1;
if (index >= 0) {
return [...values.slice(0, index), payload, ...values.slice(index + 1)];
} else {
return pushToFront ? [payload, ...(values ?? [])] : [...(values ?? []), payload];
}
});
});
useListenToTauriEvent<Model>('deleted_model', ({ payload, windowLabel }) => {
if (shouldIgnoreEvent(payload, windowLabel)) return;
if (shouldIgnoreModel(payload)) return;
if (payload.model === 'workspace') {
@@ -142,9 +138,6 @@ function removeById<T extends { id: string }>(model: T) {
return (entries: T[] | undefined) => entries?.filter((e) => e.id !== model.id);
}
const shouldIgnoreEvent = (payload: Model, windowLabel: string) =>
windowLabel === appWindow.label && payload.model !== 'http_response';
const shouldIgnoreModel = (payload: Model) => {
if (payload.model === 'key_value') {
return payload.namespace === NAMESPACE_NO_SYNC;

View File

@@ -5,6 +5,7 @@ import { useActiveEnvironmentId } from '../hooks/useActiveEnvironmentId';
import { useActiveRequest } from '../hooks/useActiveRequest';
import { useActiveWorkspaceId } from '../hooks/useActiveWorkspaceId';
import { useAppRoutes } from '../hooks/useAppRoutes';
import { useGrpcRequests } from '../hooks/useGrpcRequests';
import { useHotKey } from '../hooks/useHotKey';
import { useRecentRequests } from '../hooks/useRecentRequests';
import { useHttpRequests } from '../hooks/useHttpRequests';
@@ -19,10 +20,12 @@ export function RecentRequestsDropdown({ className }: Pick<ButtonProps, 'classNa
const activeRequest = useActiveRequest();
const activeWorkspaceId = useActiveWorkspaceId();
const activeEnvironmentId = useActiveEnvironmentId();
const requests = useHttpRequests();
const httpRequests = useHttpRequests();
const grpcRequests = useGrpcRequests();
const routes = useAppRoutes();
const allRecentRequestIds = useRecentRequests();
const recentRequestIds = useMemo(() => allRecentRequestIds.slice(1), [allRecentRequestIds]);
const requests = useMemo(() => [...httpRequests, ...grpcRequests], [httpRequests, grpcRequests]);
// Toggle the menu on Cmd+k
useKey('k', (e) => {

View File

@@ -39,6 +39,7 @@ import type { Folder, GrpcRequest, HttpRequest, Workspace } from '../lib/models'
import { isResponseLoading } from '../lib/models';
import type { DropdownItem } from './core/Dropdown';
import { ContextMenu } from './core/Dropdown';
import { HttpMethodTag } from './core/HttpMethodTag';
import { Icon } from './core/Icon';
import { InlineCode } from './core/InlineCode';
import { VStack } from './core/Stacks';
@@ -488,6 +489,13 @@ function SidebarItems({
: 'New Folder'
}
itemModel={child.item.model}
itemPrefix={
child.item.model === 'http_request' ? (
<HttpMethodTag className="opacity-50">{child.item.method}</HttpMethodTag>
) : child.item.model === 'grpc_request' ? (
<HttpMethodTag className="opacity-50">gRPC</HttpMethodTag>
) : null
}
onMove={handleMove}
onEnd={handleEnd}
onSelect={onSelect}
@@ -531,6 +539,7 @@ type SidebarItemProps = {
itemName: string;
itemFallbackName: string;
itemModel: string;
itemPrefix: ReactNode;
useProminentStyles?: boolean;
selected?: boolean;
draggable?: boolean;
@@ -546,6 +555,7 @@ const SidebarItem = forwardRef(function SidebarItem(
itemFallbackName,
itemId,
itemModel,
itemPrefix,
useProminentStyles,
selected,
onSelect,
@@ -733,7 +743,7 @@ const SidebarItem = forwardRef(function SidebarItem(
data-active={isActive}
data-selected={selected}
className={classNames(
'w-full flex items-center text-sm h-xs px-2 rounded-md transition-colors',
'w-full flex gap-2 items-center text-sm h-xs pl-2 rounded-md transition-colors',
editing && 'ring-1 focus-within:ring-focus',
isActive && 'bg-highlightSecondary text-gray-800',
!isActive &&
@@ -746,37 +756,40 @@ const SidebarItem = forwardRef(function SidebarItem(
size="sm"
icon="chevronRight"
className={classNames(
'-ml-0.5 mr-2 transition-transform',
'-ml-0.5 transition-transform opacity-50',
!isCollapsed(itemId) && 'transform rotate-90',
)}
/>
)}
{editing ? (
<input
ref={handleFocus}
defaultValue={itemName}
className="bg-transparent outline-none w-full"
onBlur={handleBlur}
onKeyDown={handleInputKeyDown}
/>
) : (
<span className="truncate">{itemName || itemFallbackName}</span>
)}
{latestGrpcConnection ? (
<div className="ml-auto">
{latestGrpcConnection.elapsed === 0 && (
<Icon spin size="sm" icon="update" className="text-gray-400" />
)}
</div>
) : latestHttpResponse ? (
<div className="ml-auto">
{isResponseLoading(latestHttpResponse) ? (
<Icon spin size="sm" icon="update" className="text-gray-400" />
) : (
<StatusTag className="text-2xs dark:opacity-80" response={latestHttpResponse} />
)}
</div>
) : null}
<div className="flex items-end gap-2 min-w-0">
{itemPrefix}
{editing ? (
<input
ref={handleFocus}
defaultValue={itemName}
className="bg-transparent outline-none w-full"
onBlur={handleBlur}
onKeyDown={handleInputKeyDown}
/>
) : (
<span className="truncate">{itemName || itemFallbackName}</span>
)}
{latestGrpcConnection ? (
<div className="ml-auto">
{latestGrpcConnection.elapsed === 0 && (
<Icon spin size="sm" icon="update" className="text-gray-400" />
)}
</div>
) : latestHttpResponse ? (
<div className="ml-auto">
{isResponseLoading(latestHttpResponse) ? (
<Icon spin size="sm" icon="update" className="text-gray-400" />
) : (
<StatusTag className="text-2xs dark:opacity-80" response={latestHttpResponse} />
)}
</div>
) : null}
</div>
</button>
</div>
{children}

View File

@@ -0,0 +1,26 @@
import classNames from 'classnames';
interface Props {
children: string;
className?: string;
}
const methodMap: Record<string, string> = {
get: 'GET',
put: 'PUT',
post: 'POST',
patch: 'PATCH',
delete: 'DELETE',
options: 'OPTIONS',
head: 'HEAD',
grpc: 'gRPC',
};
export function HttpMethodTag({ children: method, className }: Props) {
const m = method.toLowerCase();
return (
<span className={classNames(className, 'text-2xs font-mono')}>
{methodMap[m] ?? m.slice(0, 3).toUpperCase()}
</span>
);
}

View File

@@ -57,7 +57,6 @@ export function useGrpc(req: GrpcRequest | null, conn: GrpcConnection | null) {
queryKey: ['grpc_reflect', req?.id ?? 'n/a', debouncedUrl],
refetchOnWindowFocus: false,
queryFn: async () => {
console.log('useGrpc.reflect', { requestId });
return (await minPromiseMillis(
invoke('cmd_grpc_reflect', { requestId }),
300,

View File

@@ -71,11 +71,11 @@ module.exports = {
red: color('red'),
orange: color('orange'),
yellow: color('yellow'),
gray: color('gray'),
blue: color('blue'),
green: color('green'),
pink: color('pink'),
violet: color('violet'),
gray: color('gray'),
},
},
plugins: [