mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-27 11:51:13 +01:00
A bunch of changes, including moving prompt/confirm out of context
This commit is contained in:
@@ -5,7 +5,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useActiveCookieJar } from '../hooks/useActiveCookieJar';
|
||||
import { useActiveEnvironment } from '../hooks/useActiveEnvironment';
|
||||
import { useActiveRequest } from '../hooks/useActiveRequest';
|
||||
import { useCommands } from '../hooks/useCommands';
|
||||
import { useCreateEnvironment } from '../hooks/useCreateEnvironment';
|
||||
import { useCreateGrpcRequest } from '../hooks/useCreateGrpcRequest';
|
||||
import { useCreateHttpRequest } from '../hooks/useCreateHttpRequest';
|
||||
@@ -27,6 +26,7 @@ import { useScrollIntoView } from '../hooks/useScrollIntoView';
|
||||
import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest';
|
||||
import { useSidebarHidden } from '../hooks/useSidebarHidden';
|
||||
import { useWorkspaces } from '../hooks/useWorkspaces';
|
||||
import { createFolder } from '../lib/commands';
|
||||
import { showDialog, toggleDialog } from '../lib/dialog';
|
||||
import { fallbackRequestName } from '../lib/fallbackRequestName';
|
||||
import { router } from '../lib/router';
|
||||
@@ -69,7 +69,6 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
|
||||
const [recentRequests] = useRecentRequests();
|
||||
const openWorkspace = useOpenWorkspace();
|
||||
const createHttpRequest = useCreateHttpRequest();
|
||||
const { createFolder } = useCommands();
|
||||
const activeCookieJar = useActiveCookieJar();
|
||||
const createGrpcRequest = useCreateGrpcRequest();
|
||||
const createEnvironment = useCreateEnvironment();
|
||||
@@ -188,7 +187,6 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
|
||||
activeRequest,
|
||||
baseEnvironment,
|
||||
createEnvironment,
|
||||
createFolder,
|
||||
createGrpcRequest,
|
||||
createHttpRequest,
|
||||
createWorkspace,
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { setActiveCookieJar, useActiveCookieJar } from '../hooks/useActiveCookieJar';
|
||||
import { useActiveCookieJar } from '../hooks/useActiveCookieJar';
|
||||
import { cookieJarsAtom } from '../hooks/useCookieJars';
|
||||
import { useCreateCookieJar } from '../hooks/useCreateCookieJar';
|
||||
import { useDeleteCookieJar } from '../hooks/useDeleteCookieJar';
|
||||
import { usePrompt } from '../hooks/usePrompt';
|
||||
import { useUpdateCookieJar } from '../hooks/useUpdateCookieJar';
|
||||
import { showDialog } from '../lib/dialog';
|
||||
import { jotaiStore } from '../lib/jotai';
|
||||
import { showPrompt } from '../lib/prompt';
|
||||
import {setWorkspaceSearchParams} from "../lib/setWorkspaceSearchParams";
|
||||
import { CookieDialog } from './CookieDialog';
|
||||
import { Dropdown, type DropdownItem } from './core/Dropdown';
|
||||
import { Icon } from './core/Icon';
|
||||
@@ -18,18 +19,19 @@ export const CookieDropdown = memo(function CookieDropdown() {
|
||||
const updateCookieJar = useUpdateCookieJar(activeCookieJar?.id ?? null);
|
||||
const deleteCookieJar = useDeleteCookieJar(activeCookieJar ?? null);
|
||||
const createCookieJar = useCreateCookieJar();
|
||||
const prompt = usePrompt();
|
||||
const cookieJars = useAtomValue(cookieJarsAtom);
|
||||
|
||||
const items = useMemo((): DropdownItem[] => {
|
||||
const cookieJars = jotaiStore.get(cookieJarsAtom) ?? [];
|
||||
return [
|
||||
...cookieJars.map((j) => ({
|
||||
...(cookieJars ?? []).map((j) => ({
|
||||
key: j.id,
|
||||
label: j.name,
|
||||
leftSlot: <Icon icon={j.id === activeCookieJar?.id ? 'check' : 'empty'} />,
|
||||
onSelect: () => setActiveCookieJar(j),
|
||||
onSelect: () => {
|
||||
setWorkspaceSearchParams({ cookie_jar_id: j.id });
|
||||
},
|
||||
})),
|
||||
...((cookieJars.length > 0 && activeCookieJar != null
|
||||
...(((cookieJars ?? []).length > 0 && activeCookieJar != null
|
||||
? [
|
||||
{ type: 'separator', label: activeCookieJar.name },
|
||||
{
|
||||
@@ -51,7 +53,7 @@ export const CookieDropdown = memo(function CookieDropdown() {
|
||||
label: 'Rename',
|
||||
leftSlot: <Icon icon="pencil" />,
|
||||
onSelect: async () => {
|
||||
const name = await prompt({
|
||||
const name = await showPrompt({
|
||||
id: 'rename-cookie-jar',
|
||||
title: 'Rename Cookie Jar',
|
||||
description: (
|
||||
@@ -68,7 +70,7 @@ export const CookieDropdown = memo(function CookieDropdown() {
|
||||
updateCookieJar.mutate({ name });
|
||||
},
|
||||
},
|
||||
...((cookieJars.length > 1 // Never delete the last one
|
||||
...(((cookieJars ?? []).length > 1 // Never delete the last one
|
||||
? [
|
||||
{
|
||||
key: 'delete',
|
||||
@@ -89,7 +91,7 @@ export const CookieDropdown = memo(function CookieDropdown() {
|
||||
onSelect: () => createCookieJar.mutate(),
|
||||
},
|
||||
];
|
||||
}, [activeCookieJar, createCookieJar, deleteCookieJar, prompt, updateCookieJar]);
|
||||
}, [activeCookieJar, cookieJars, createCookieJar, deleteCookieJar, updateCookieJar]);
|
||||
|
||||
return (
|
||||
<Dropdown items={items}>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { useCommands } from '../hooks/useCommands';
|
||||
import {createWorkspace} from "../lib/commands";
|
||||
import { Button } from './core/Button';
|
||||
import { PlainInput } from './core/PlainInput';
|
||||
import { VStack } from './core/Stacks';
|
||||
@@ -14,7 +14,6 @@ export function CreateWorkspaceDialog({ hide }: Props) {
|
||||
const [name, setName] = useState<string>('');
|
||||
const [description, setDescription] = useState<string>('');
|
||||
const [settingSyncDir, setSettingSyncDir] = useState<string | null>(null);
|
||||
const { createWorkspace } = useCommands();
|
||||
|
||||
return (
|
||||
<VStack
|
||||
|
||||
@@ -12,19 +12,26 @@ export function Dialogs() {
|
||||
const dialogs = useAtomValue(dialogsAtom);
|
||||
return (
|
||||
<>
|
||||
{dialogs.map(({ render, onClose, id, ...props }: DialogInstance) => (
|
||||
<Dialog
|
||||
open
|
||||
key={id}
|
||||
onClose={() => {
|
||||
onClose?.();
|
||||
hideDialog(id);
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{render({ hide: () => hideDialog(id) })}
|
||||
</Dialog>
|
||||
{dialogs.map(({ id, ...props }) => (
|
||||
<DialogInstance key={id} id={id} {...props} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function DialogInstance({ render, onClose, id, ...props }: DialogInstance) {
|
||||
const children = render({ hide: () => hideDialog(id) });
|
||||
return (
|
||||
<Dialog
|
||||
open
|
||||
key={id}
|
||||
onClose={() => {
|
||||
onClose?.();
|
||||
hideDialog(id);
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import { useCreateEnvironment } from '../hooks/useCreateEnvironment';
|
||||
import { useDeleteEnvironment } from '../hooks/useDeleteEnvironment';
|
||||
import { useEnvironments } from '../hooks/useEnvironments';
|
||||
import { useKeyValue } from '../hooks/useKeyValue';
|
||||
import { usePrompt } from '../hooks/usePrompt';
|
||||
import { useUpdateEnvironment } from '../hooks/useUpdateEnvironment';
|
||||
import { showPrompt } from '../lib/prompt';
|
||||
import { Banner } from './core/Banner';
|
||||
import { Button } from './core/Button';
|
||||
import { ContextMenu } from './core/Dropdown';
|
||||
@@ -212,7 +212,6 @@ function SidebarButton({
|
||||
rightSlot?: ReactNode;
|
||||
environment: Environment | null;
|
||||
}) {
|
||||
const prompt = usePrompt();
|
||||
const updateEnvironment = useUpdateEnvironment(environment?.id ?? null);
|
||||
const deleteEnvironment = useDeleteEnvironment(environment);
|
||||
const [showContextMenu, setShowContextMenu] = useState<{
|
||||
@@ -260,7 +259,7 @@ function SidebarButton({
|
||||
label: 'Rename',
|
||||
leftSlot: <Icon icon="pencil" size="sm" />,
|
||||
onSelect: async () => {
|
||||
const name = await prompt({
|
||||
const name = await showPrompt({
|
||||
id: 'rename-environment',
|
||||
title: 'Rename Environment',
|
||||
description: (
|
||||
|
||||
@@ -2,34 +2,18 @@ import { emit } from '@tauri-apps/api/event';
|
||||
import type { PromptTextRequest, PromptTextResponse } from '@yaakapp-internal/plugins';
|
||||
import { useWatchWorkspace } from '@yaakapp-internal/sync';
|
||||
import type { ShowToastRequest } from '@yaakapp/api';
|
||||
import {
|
||||
useEnsureActiveCookieJar,
|
||||
useSubscribeActiveCookieJarId,
|
||||
} from '../hooks/useActiveCookieJar';
|
||||
import { useSubscribeActiveEnvironmentId } from '../hooks/useActiveEnvironment';
|
||||
import { getActiveRequest, useActiveRequest } from '../hooks/useActiveRequest';
|
||||
import { useSubscribeActiveRequestId } from '../hooks/useActiveRequestId';
|
||||
import { useActiveWorkspace, useSubscribeActiveWorkspaceId } from '../hooks/useActiveWorkspace';
|
||||
import { useActiveWorkspaceChangedToast } from '../hooks/useActiveWorkspaceChangedToast';
|
||||
import { useDuplicateGrpcRequest } from '../hooks/useDuplicateGrpcRequest';
|
||||
import { useDuplicateHttpRequest } from '../hooks/useDuplicateHttpRequest';
|
||||
import { useGenerateThemeCss } from '../hooks/useGenerateThemeCss';
|
||||
import { useHotKey } from '../hooks/useHotKey';
|
||||
import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
|
||||
import { useNotificationToast } from '../hooks/useNotificationToast';
|
||||
import { usePrompt } from '../hooks/usePrompt';
|
||||
import { useSubscribeRecentCookieJars } from '../hooks/useRecentCookieJars';
|
||||
import { useSubscribeRecentEnvironments } from '../hooks/useRecentEnvironments';
|
||||
import { useSubscribeRecentRequests } from '../hooks/useRecentRequests';
|
||||
import { useSubscribeRecentWorkspaces } from '../hooks/useRecentWorkspaces';
|
||||
import { useSyncFontSizeSetting } from '../hooks/useSyncFontSizeSetting';
|
||||
import { useSyncModelStores } from '../hooks/useSyncModelStores';
|
||||
import { useSyncWorkspace } from '../hooks/useSyncWorkspace';
|
||||
import { useSyncWorkspaceChildModels } from '../hooks/useSyncWorkspaceChildModels';
|
||||
import { useSyncWorkspaceRequestTitle } from '../hooks/useSyncWorkspaceRequestTitle';
|
||||
import { useSyncZoomSetting } from '../hooks/useSyncZoomSetting';
|
||||
import { useSubscribeTemplateFunctions } from '../hooks/useTemplateFunctions';
|
||||
import { useToggleCommandPalette } from '../hooks/useToggleCommandPalette';
|
||||
import { showPrompt } from '../lib/prompt';
|
||||
import { showToast } from '../lib/toast';
|
||||
|
||||
export function GlobalHooks() {
|
||||
@@ -37,17 +21,8 @@ export function GlobalHooks() {
|
||||
useSyncZoomSetting();
|
||||
useSyncFontSizeSetting();
|
||||
useGenerateThemeCss();
|
||||
useSyncWorkspaceRequestTitle();
|
||||
|
||||
useSubscribeActiveWorkspaceId();
|
||||
useSubscribeActiveRequestId();
|
||||
useSubscribeActiveEnvironmentId();
|
||||
useSubscribeActiveCookieJarId();
|
||||
|
||||
useSubscribeRecentRequests();
|
||||
useSubscribeRecentWorkspaces();
|
||||
useSubscribeRecentEnvironments();
|
||||
useSubscribeRecentCookieJars();
|
||||
|
||||
useSyncWorkspaceChildModels();
|
||||
useSubscribeTemplateFunctions();
|
||||
@@ -55,7 +30,6 @@ export function GlobalHooks() {
|
||||
// Other useful things
|
||||
useNotificationToast();
|
||||
useActiveWorkspaceChangedToast();
|
||||
useEnsureActiveCookieJar();
|
||||
|
||||
// Listen for toasts
|
||||
useListenToTauriEvent<ShowToastRequest>('show_toast', (event) => {
|
||||
@@ -68,32 +42,10 @@ export function GlobalHooks() {
|
||||
useListenToTauriEvent('upserted_model', debouncedSync);
|
||||
useWatchWorkspace(activeWorkspace, debouncedSync);
|
||||
|
||||
const activeRequest = useActiveRequest();
|
||||
const duplicateHttpRequest = useDuplicateHttpRequest({
|
||||
id: activeRequest?.id ?? null,
|
||||
navigateAfter: true,
|
||||
});
|
||||
const duplicateGrpcRequest = useDuplicateGrpcRequest({
|
||||
id: activeRequest?.id ?? null,
|
||||
navigateAfter: true,
|
||||
});
|
||||
useHotKey('http_request.duplicate', async () => {
|
||||
const activeRequest = getActiveRequest();
|
||||
if (activeRequest?.model === 'http_request') {
|
||||
await duplicateHttpRequest.mutateAsync();
|
||||
} else {
|
||||
await duplicateGrpcRequest.mutateAsync();
|
||||
}
|
||||
});
|
||||
|
||||
const toggleCommandPalette = useToggleCommandPalette();
|
||||
useHotKey('command_palette.toggle', toggleCommandPalette);
|
||||
|
||||
const prompt = usePrompt();
|
||||
useListenToTauriEvent<{ replyId: string; args: PromptTextRequest }>(
|
||||
'show_prompt',
|
||||
async (event) => {
|
||||
const value = await prompt(event.payload.args);
|
||||
const value = await showPrompt(event.payload.args);
|
||||
const result: PromptTextResponse = { value };
|
||||
await emit(event.payload.replyId, result);
|
||||
},
|
||||
|
||||
@@ -42,7 +42,7 @@ export function MarkdownEditor({ className, defaultValue, onChange, name, ...edi
|
||||
<Editor
|
||||
hideGutter
|
||||
wrapLines
|
||||
className="max-w-2xl max-h-full"
|
||||
className="max-w-2xl max-h-full"
|
||||
language="markdown"
|
||||
defaultValue={defaultValue}
|
||||
onChange={onChange}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import classNames from 'classnames';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { usePrompt } from '../hooks/usePrompt';
|
||||
import { showPrompt } from '../lib/prompt';
|
||||
import { Button } from './core/Button';
|
||||
import type { DropdownItem } from './core/Dropdown';
|
||||
import { Icon } from './core/Icon';
|
||||
@@ -32,7 +32,6 @@ export const RequestMethodDropdown = memo(function RequestMethodDropdown({
|
||||
onChange,
|
||||
className,
|
||||
}: Props) {
|
||||
const prompt = usePrompt();
|
||||
const extraItems = useMemo<DropdownItem[]>(
|
||||
() => [
|
||||
{
|
||||
@@ -40,7 +39,7 @@ export const RequestMethodDropdown = memo(function RequestMethodDropdown({
|
||||
label: 'CUSTOM',
|
||||
leftSlot: <Icon icon="sparkles" />,
|
||||
onSelect: async () => {
|
||||
const newMethod = await prompt({
|
||||
const newMethod = await showPrompt({
|
||||
id: 'custom-method',
|
||||
label: 'Http Method',
|
||||
defaultValue: '',
|
||||
@@ -54,7 +53,7 @@ export const RequestMethodDropdown = memo(function RequestMethodDropdown({
|
||||
},
|
||||
},
|
||||
],
|
||||
[onChange, prompt],
|
||||
[onChange],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -298,7 +298,6 @@ export const RequestPane = memo(function RequestPane({
|
||||
);
|
||||
|
||||
const activeTab = activeTabs?.[activeRequestId];
|
||||
console.log('ACTIVE TAB', activeTab);
|
||||
const setActiveTab = useCallback(
|
||||
(tab: string) => {
|
||||
setActiveTabs((r) => ({ ...r, [activeRequest.id]: tab }));
|
||||
|
||||
@@ -15,6 +15,7 @@ import { useUpdateAnyFolder } from '../hooks/useUpdateAnyFolder';
|
||||
import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest';
|
||||
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
|
||||
import { router } from '../lib/router';
|
||||
import { setWorkspaceSearchParams } from '../lib/setWorkspaceSearchParams';
|
||||
import { ContextMenu } from './core/Dropdown';
|
||||
import { sidebarSelectedIdAtom, sidebarTreeAtom } from './SidebarAtoms';
|
||||
import type { SidebarItemProps } from './SidebarItem';
|
||||
@@ -151,11 +152,7 @@ export function Sidebar({ className }: Props) {
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
await router.navigate({
|
||||
to: '/workspaces/$workspaceId',
|
||||
params: { workspaceId: activeWorkspace?.id ?? null },
|
||||
search: (prev) => ({ ...prev, request_id: selected.id }),
|
||||
});
|
||||
setWorkspaceSearchParams({ request_id: selected.id });
|
||||
});
|
||||
|
||||
useKey(
|
||||
|
||||
@@ -2,13 +2,25 @@ import classNames from 'classnames';
|
||||
import { motion } from 'framer-motion';
|
||||
import type { CSSProperties, MouseEvent as ReactMouseEvent } from 'react';
|
||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { useActiveRequest } from '../hooks/useActiveRequest';
|
||||
import {useEnsureActiveCookieJar, useSubscribeActiveCookieJarId} from "../hooks/useActiveCookieJar";
|
||||
import {useSubscribeActiveEnvironmentId} from "../hooks/useActiveEnvironment";
|
||||
import {getActiveRequest, useActiveRequest} from '../hooks/useActiveRequest';
|
||||
import {useSubscribeActiveRequestId} from "../hooks/useActiveRequestId";
|
||||
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
|
||||
import {useDuplicateGrpcRequest} from "../hooks/useDuplicateGrpcRequest";
|
||||
import {useDuplicateHttpRequest} from "../hooks/useDuplicateHttpRequest";
|
||||
import { useFloatingSidebarHidden } from '../hooks/useFloatingSidebarHidden';
|
||||
import {useHotKey} from "../hooks/useHotKey";
|
||||
import { useImportData } from '../hooks/useImportData';
|
||||
import {useSubscribeRecentCookieJars} from "../hooks/useRecentCookieJars";
|
||||
import {useSubscribeRecentEnvironments} from "../hooks/useRecentEnvironments";
|
||||
import {useSubscribeRecentRequests} from "../hooks/useRecentRequests";
|
||||
import {useSubscribeRecentWorkspaces} from "../hooks/useRecentWorkspaces";
|
||||
import { useShouldFloatSidebar } from '../hooks/useShouldFloatSidebar';
|
||||
import { useSidebarHidden } from '../hooks/useSidebarHidden';
|
||||
import { useSidebarWidth } from '../hooks/useSidebarWidth';
|
||||
import {useSyncWorkspaceRequestTitle} from "../hooks/useSyncWorkspaceRequestTitle";
|
||||
import {useToggleCommandPalette} from "../hooks/useToggleCommandPalette";
|
||||
import { useWorkspaces } from '../hooks/useWorkspaces';
|
||||
import { Banner } from './core/Banner';
|
||||
import { Button } from './core/Button';
|
||||
@@ -31,6 +43,9 @@ const body = { gridArea: 'body' };
|
||||
const drag = { gridArea: 'drag' };
|
||||
|
||||
export function Workspace() {
|
||||
// First, subscribe to some things applicable to workspaces
|
||||
useGlobalWorkspaceHooks();
|
||||
|
||||
const workspaces = useWorkspaces();
|
||||
const { setWidth, width, resetWidth } = useSidebarWidth();
|
||||
const [sidebarHidden, setSidebarHidden] = useSidebarHidden();
|
||||
@@ -202,3 +217,40 @@ function WorkspaceBody() {
|
||||
|
||||
return <HttpRequestLayout activeRequest={activeRequest} style={body} />;
|
||||
}
|
||||
|
||||
function useGlobalWorkspaceHooks() {
|
||||
useEnsureActiveCookieJar();
|
||||
|
||||
useSubscribeActiveRequestId();
|
||||
useSubscribeActiveEnvironmentId();
|
||||
useSubscribeActiveCookieJarId();
|
||||
|
||||
useSubscribeRecentRequests();
|
||||
useSubscribeRecentWorkspaces();
|
||||
useSubscribeRecentEnvironments();
|
||||
useSubscribeRecentCookieJars();
|
||||
|
||||
useSyncWorkspaceRequestTitle();
|
||||
|
||||
const toggleCommandPalette = useToggleCommandPalette();
|
||||
useHotKey('command_palette.toggle', toggleCommandPalette);
|
||||
|
||||
const activeRequest = useActiveRequest();
|
||||
const duplicateHttpRequest = useDuplicateHttpRequest({
|
||||
id: activeRequest?.id ?? null,
|
||||
navigateAfter: true,
|
||||
});
|
||||
const duplicateGrpcRequest = useDuplicateGrpcRequest({
|
||||
id: activeRequest?.id ?? null,
|
||||
navigateAfter: true,
|
||||
});
|
||||
|
||||
useHotKey('http_request.duplicate', async () => {
|
||||
const activeRequest = getActiveRequest();
|
||||
if (activeRequest?.model === 'http_request') {
|
||||
await duplicateHttpRequest.mutateAsync();
|
||||
} else {
|
||||
await duplicateGrpcRequest.mutateAsync();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useCreateWorkspace } from '../hooks/useCreateWorkspace';
|
||||
import { useDeleteSendHistory } from '../hooks/useDeleteSendHistory';
|
||||
import { useOpenWorkspace } from '../hooks/useOpenWorkspace';
|
||||
import { useSettings } from '../hooks/useSettings';
|
||||
import { useSyncWorkspace } from '../hooks/useSyncWorkspace';
|
||||
import { useWorkspaces } from '../hooks/useWorkspaces';
|
||||
import { showDialog } from '../lib/dialog';
|
||||
import { getWorkspace } from '../lib/store';
|
||||
@@ -31,7 +30,6 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
||||
const settings = useSettings();
|
||||
const openWorkspace = useOpenWorkspace();
|
||||
const openWorkspaceNewWindow = settings?.openWorkspaceNewWindow ?? null;
|
||||
const { sync } = useSyncWorkspace(activeWorkspace);
|
||||
|
||||
const orderedWorkspaces = useMemo(
|
||||
() => [...workspaces].sort((a, b) => (a.name.localeCompare(b.name) > 0 ? 1 : -1)),
|
||||
@@ -66,13 +64,6 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'sync',
|
||||
label: 'Sync Workspace',
|
||||
leftSlot: <Icon icon="folder_sync" />,
|
||||
hidden: !activeWorkspace?.settingSyncDir,
|
||||
onSelect: sync,
|
||||
},
|
||||
{
|
||||
key: 'delete-responses',
|
||||
label: 'Clear Send History',
|
||||
@@ -89,14 +80,7 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
||||
];
|
||||
|
||||
return { workspaceItems, extraItems };
|
||||
}, [
|
||||
orderedWorkspaces,
|
||||
activeWorkspace?.settingSyncDir,
|
||||
activeWorkspace?.id,
|
||||
sync,
|
||||
deleteSendHistory,
|
||||
createWorkspace,
|
||||
]);
|
||||
}, [orderedWorkspaces, activeWorkspace?.id, deleteSendHistory, createWorkspace]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
async (workspaceId: string | null) => {
|
||||
|
||||
21
src-web/components/core/Alert.tsx
Normal file
21
src-web/components/core/Alert.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { Button } from './Button';
|
||||
import { HStack, VStack } from './Stacks';
|
||||
|
||||
export interface AlertProps {
|
||||
onHide: () => void;
|
||||
body: ReactNode;
|
||||
}
|
||||
|
||||
export function Alert({ onHide, body }: AlertProps) {
|
||||
return (
|
||||
<VStack space={3} className="pb-4">
|
||||
<div>{body}</div>
|
||||
<HStack space={2} justifyContent="end">
|
||||
<Button className="focus" color="primary" onClick={onHide}>
|
||||
Okay
|
||||
</Button>
|
||||
</HStack>
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
43
src-web/components/core/Confirm.tsx
Normal file
43
src-web/components/core/Confirm.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { ButtonProps } from './Button';
|
||||
import { Button } from './Button';
|
||||
import { HStack } from './Stacks';
|
||||
|
||||
export interface ConfirmProps {
|
||||
onHide: () => void;
|
||||
onResult: (result: boolean) => void;
|
||||
variant?: 'delete' | 'confirm';
|
||||
confirmText?: string;
|
||||
}
|
||||
|
||||
const colors: Record<NonNullable<ConfirmProps['variant']>, ButtonProps['color']> = {
|
||||
delete: 'danger',
|
||||
confirm: 'primary',
|
||||
};
|
||||
|
||||
const confirmButtonTexts: Record<NonNullable<ConfirmProps['variant']>, string> = {
|
||||
delete: 'Delete',
|
||||
confirm: 'Confirm',
|
||||
};
|
||||
|
||||
export function Confirm({ onHide, onResult, confirmText, variant = 'confirm' }: ConfirmProps) {
|
||||
const handleHide = () => {
|
||||
onResult(false);
|
||||
onHide();
|
||||
};
|
||||
|
||||
const handleSuccess = () => {
|
||||
onResult(true);
|
||||
onHide();
|
||||
};
|
||||
|
||||
return (
|
||||
<HStack space={2} justifyContent="start" className="mt-2 mb-4 flex-row-reverse">
|
||||
<Button color={colors[variant]} onClick={handleSuccess}>
|
||||
{confirmText ?? confirmButtonTexts[variant]}
|
||||
</Button>
|
||||
<Button onClick={handleHide} variant="border">
|
||||
Cancel
|
||||
</Button>
|
||||
</HStack>
|
||||
);
|
||||
}
|
||||
@@ -12,9 +12,9 @@ import {
|
||||
} from 'react';
|
||||
import type { XYCoord } from 'react-dnd';
|
||||
import { useDrag, useDrop } from 'react-dnd';
|
||||
import { usePrompt } from '../../hooks/usePrompt';
|
||||
import { useToggle } from '../../hooks/useToggle';
|
||||
import { generateId } from '../../lib/generateId';
|
||||
import { showPrompt } from '../../lib/prompt';
|
||||
import { DropMarker } from '../DropMarker';
|
||||
import { SelectFile } from '../SelectFile';
|
||||
import { Button } from './Button';
|
||||
@@ -556,7 +556,6 @@ function FileActionsDropdown({
|
||||
onChangeContentType: (contentType: string) => void;
|
||||
onDelete: () => void;
|
||||
}) {
|
||||
const prompt = usePrompt();
|
||||
const onChange = useCallback(
|
||||
(v: string) => {
|
||||
if (v === 'file') onChangeFile({ filePath: '' });
|
||||
@@ -573,7 +572,7 @@ function FileActionsDropdown({
|
||||
leftSlot: <Icon icon="pencil" />,
|
||||
hidden: !pair.isFile,
|
||||
onSelect: async () => {
|
||||
const contentType = await prompt({
|
||||
const contentType = await showPrompt({
|
||||
id: 'content-type',
|
||||
require: false,
|
||||
title: 'Override Content-Type',
|
||||
@@ -604,7 +603,7 @@ function FileActionsDropdown({
|
||||
leftSlot: <Icon icon="trash" />,
|
||||
},
|
||||
],
|
||||
[onChangeContentType, onChangeFile, onDelete, pair.contentType, pair.isFile, prompt],
|
||||
[onChangeContentType, onChangeFile, onDelete, pair.contentType, pair.isFile],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
57
src-web/components/core/Prompt.tsx
Normal file
57
src-web/components/core/Prompt.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { PromptTextRequest } from '@yaakapp-internal/plugins';
|
||||
import type { FormEvent, ReactNode } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
import {PlainInput} from "./PlainInput";
|
||||
import { HStack } from './Stacks';
|
||||
import { Button } from './Button';
|
||||
|
||||
export type PromptProps = Omit<PromptTextRequest, 'id' | 'title' | 'description'> & {
|
||||
description?: ReactNode;
|
||||
onCancel: () => void;
|
||||
onResult: (value: string | null) => void;
|
||||
};
|
||||
|
||||
export function Prompt({
|
||||
onCancel,
|
||||
label,
|
||||
defaultValue,
|
||||
placeholder,
|
||||
onResult,
|
||||
require,
|
||||
confirmText,
|
||||
cancelText,
|
||||
}: PromptProps) {
|
||||
const [value, setValue] = useState<string>(defaultValue ?? '');
|
||||
const handleSubmit = useCallback(
|
||||
(e: FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
onResult(value);
|
||||
},
|
||||
[onResult, value],
|
||||
);
|
||||
|
||||
return (
|
||||
<form
|
||||
className="grid grid-rows-[auto_auto] grid-cols-[minmax(0,1fr)] gap-4 mb-4"
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<PlainInput
|
||||
hideLabel
|
||||
autoSelect
|
||||
require={require}
|
||||
placeholder={placeholder ?? 'Enter text'}
|
||||
label={label}
|
||||
defaultValue={defaultValue}
|
||||
onChange={setValue}
|
||||
/>
|
||||
<HStack space={2} justifyContent="end">
|
||||
<Button onClick={onCancel} variant="border" color="secondary">
|
||||
{cancelText || 'Cancel'}
|
||||
</Button>
|
||||
<Button type="submit" color="primary">
|
||||
{confirmText || 'Done'}
|
||||
</Button>
|
||||
</HStack>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user