Remove useToast everywhere

This commit is contained in:
Gregory Schier
2025-01-06 12:21:21 -08:00
parent ab55c2e0ce
commit 806a8eb801
14 changed files with 58 additions and 84 deletions

View File

@@ -29,8 +29,8 @@ import { useSyncWorkspaceChildModels } from '../hooks/useSyncWorkspaceChildModel
import { useSyncWorkspaceRequestTitle } from '../hooks/useSyncWorkspaceRequestTitle';
import { useSyncZoomSetting } from '../hooks/useSyncZoomSetting';
import { useSubscribeTemplateFunctions } from '../hooks/useTemplateFunctions';
import {useToast} from "../hooks/useToast";
import { useToggleCommandPalette } from '../hooks/useToggleCommandPalette';
import { showToast } from '../lib/toast';
export function GlobalHooks() {
useSyncModelStores();
@@ -58,9 +58,8 @@ export function GlobalHooks() {
useEnsureActiveCookieJar();
// Listen for toasts
const toast = useToast();
useListenToTauriEvent<ShowToastRequest>('show_toast', (event) => {
toast.show({ ...event.payload });
showToast({ ...event.payload });
});
// Trigger workspace sync operation when workspace files change

View File

@@ -1,11 +1,11 @@
import { useNavigate } from '@tanstack/react-router';
import type { GrpcRequest, HttpRequest } from '@yaakapp-internal/models';
import React, { useState } from 'react';
import { useToast } from '../hooks/useToast';
import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest';
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
import { useWorkspaces } from '../hooks/useWorkspaces';
import { fallbackRequestName } from '../lib/fallbackRequestName';
import {showToast} from "../lib/toast";
import { Button } from './core/Button';
import { InlineCode } from './core/InlineCode';
import { Select } from './core/Select';
@@ -21,7 +21,6 @@ export function MoveToWorkspaceDialog({ onDone, request, activeWorkspaceId }: Pr
const workspaces = useWorkspaces();
const updateHttpRequest = useUpdateAnyHttpRequest();
const updateGrpcRequest = useUpdateAnyGrpcRequest();
const toast = useToast();
const navigate = useNavigate();
const [selectedWorkspaceId, setSelectedWorkspaceId] = useState<string>(activeWorkspaceId);
@@ -54,7 +53,7 @@ export function MoveToWorkspaceDialog({ onDone, request, activeWorkspaceId }: Pr
// Hide after a moment, to give time for request to disappear
setTimeout(onDone, 100);
toast.show({
showToast({
id: 'workspace-moved',
message: (
<>

View File

@@ -16,7 +16,6 @@ import { usePinnedHttpResponse } from '../hooks/usePinnedHttpResponse';
import { useRequestEditor, useRequestEditorEvent } from '../hooks/useRequestEditor';
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest';
import { useToast } from '../hooks/useToast';
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
import { deepEqualAtom } from '../lib/atoms';
import { languageFromContentType } from '../lib/contentType';
@@ -35,6 +34,7 @@ import {
BODY_TYPE_OTHER,
BODY_TYPE_XML,
} from '../lib/model_util';
import { showToast } from '../lib/toast';
import { BasicAuth } from './BasicAuth';
import { BearerAuth } from './BearerAuth';
import { BinaryFileEditor } from './BinaryFileEditor';
@@ -123,8 +123,6 @@ export const RequestPane = memo(function RequestPane({
[activeRequest, updateRequestAsync],
);
const toast = useToast();
const { urlParameterPairs, urlParametersKey } = useMemo(() => {
const placeholderNames = Array.from(activeRequest.url.matchAll(/\/(:[^/]+)/g)).map(
(m) => m[1] ?? '',
@@ -182,7 +180,7 @@ export const RequestPane = memo(function RequestPane({
const showMethodToast = (newMethod: string) => {
if (activeRequest.method.toLowerCase() === newMethod.toLowerCase()) return;
toast.show({
showToast({
id: 'switched-method',
message: (
<>
@@ -276,7 +274,6 @@ export const RequestPane = memo(function RequestPane({
activeRequestId,
handleContentTypeChange,
numParams,
toast,
updateRequest,
updateRequestAsync,
urlParameterPairs.length,

View File

@@ -1,7 +1,7 @@
import { AnimatePresence } from 'framer-motion';
import { useAtomValue } from 'jotai';
import React, { type ReactNode } from 'react';
import { toastsAtom, useToast } from '../hooks/useToast';
import { hideToast, toastsAtom } from '../lib/toast';
import { Toast, type ToastProps } from './core/Toast';
import { Portal } from './Portal';
@@ -18,7 +18,6 @@ export type PrivateToastEntry = ToastEntry & {
};
function ToastInstance({ id, message, timeout, ...props }: PrivateToastEntry) {
const toast = useToast();
return (
<Toast
open
@@ -26,7 +25,7 @@ function ToastInstance({ id, message, timeout, ...props }: PrivateToastEntry) {
{...props}
// We call onClose inside actions.hide instead of passing to toast so that
// it gets called from external close calls as well
onClose={() => toast.hide(id)}
onClose={() => hideToast(id)}
>
{message}
</Toast>

View File

@@ -1,10 +1,9 @@
import { useEffect, useState } from 'react';
import { InlineCode } from '../components/core/InlineCode';
import { useActiveWorkspace } from './useActiveWorkspace';
import { useToast } from './useToast';
import { showToast } from '../lib/toast';
export function useActiveWorkspaceChangedToast() {
const toast = useToast();
const activeWorkspace = useActiveWorkspace();
const [id, setId] = useState<string | null>(activeWorkspace?.id ?? null);
@@ -17,7 +16,7 @@ export function useActiveWorkspaceChangedToast() {
// Don't notify on the first load
if (id === null) return;
toast.show({
showToast({
id: `workspace-changed-${activeWorkspace.id}`,
timeout: 3000,
message: (
@@ -27,5 +26,5 @@ export function useActiveWorkspaceChangedToast() {
</>
),
});
}, [activeWorkspace, id, toast]);
}, [activeWorkspace, id]);
}

View File

@@ -6,7 +6,6 @@ import { invokeCmd } from '../lib/tauri';
import { getActiveWorkspaceId } from './useActiveWorkspace';
import { createFastMutation } from './useFastMutation';
import { usePrompt } from './usePrompt';
import { useToast } from './useToast';
function makeCommands({
navigate,
@@ -14,7 +13,6 @@ function makeCommands({
}: {
navigate: ReturnType<typeof useNavigate>;
prompt: ReturnType<typeof usePrompt>;
toast: ReturnType<typeof useToast>;
}) {
return {
createWorkspace: createFastMutation<Workspace, void, Partial<Workspace>>({
@@ -65,7 +63,6 @@ function makeCommands({
export function useCommands() {
const navigate = useNavigate();
const toast = useToast();
const prompt = usePrompt();
return useMemo(() => makeCommands({ navigate, toast, prompt }), [navigate, prompt, toast]);
return useMemo(() => makeCommands({ navigate, prompt }), [navigate, prompt]);
}

View File

@@ -1,10 +1,8 @@
import { clear, writeText } from '@tauri-apps/plugin-clipboard-manager';
import { useCallback } from 'react';
import { useToast } from './useToast';
import { showToast } from '../lib/toast';
export function useCopy({ disableToast }: { disableToast?: boolean } = {}) {
const toast = useToast();
const copy = useCallback(
(text: string | null) => {
if (text == null) {
@@ -13,7 +11,7 @@ export function useCopy({ disableToast }: { disableToast?: boolean } = {}) {
writeText(text).catch(console.error);
}
if (text != '' && !disableToast) {
toast.show({
showToast({
id: 'copied',
color: 'secondary',
icon: 'copy',
@@ -21,7 +19,7 @@ export function useCopy({ disableToast }: { disableToast?: boolean } = {}) {
});
}
},
[disableToast, toast],
[disableToast],
);
return copy;

View File

@@ -4,13 +4,12 @@ import { getActiveWorkspace } from './useActiveWorkspace';
import { useAlert } from './useAlert';
import { useDialog } from './useDialog';
import { useFastMutation } from './useFastMutation';
import { useToast } from './useToast';
import { showToast } from '../lib/toast';
import { workspacesAtom } from './useWorkspaces';
export function useExportData() {
const alert = useAlert();
const dialog = useDialog();
const toast = useToast();
return useFastMutation({
mutationKey: ['export_data'],
@@ -32,7 +31,7 @@ export function useExportData() {
<ExportDataDialog
onHide={hide}
onSuccess={() => {
toast.show({
showToast({
color: 'success',
message: 'Data export successful',
});

View File

@@ -4,14 +4,13 @@ import { getActiveWorkspaceId } from './useActiveWorkspace';
import { useCreateHttpRequest } from './useCreateHttpRequest';
import { useFastMutation } from './useFastMutation';
import { useRequestUpdateKey } from './useRequestUpdateKey';
import { useToast } from './useToast';
import { showToast } from '../lib/toast';
import { useUpdateAnyHttpRequest } from './useUpdateAnyHttpRequest';
export function useImportCurl() {
const updateRequest = useUpdateAnyHttpRequest();
const createRequest = useCreateHttpRequest();
const { wasUpdatedExternally } = useRequestUpdateKey(null);
const toast = useToast();
return useFastMutation({
mutationKey: ['import_curl'],
@@ -50,7 +49,7 @@ export function useImportCurl() {
setTimeout(() => wasUpdatedExternally(overwriteRequestId), 100);
}
toast.show({
showToast({
color: 'success',
message: `${verb} request from Curl`,
});

View File

@@ -1,15 +1,14 @@
import {generateId} from "../lib/generateId";
import { useFastMutation } from './useFastMutation';
import type { HttpUrlParameter } from '@yaakapp-internal/models';
import { useToast } from './useToast';
import { generateId } from '../lib/generateId';
import { pluralize } from '../lib/pluralize';
import { getHttpRequest } from '../lib/store';
import { useFastMutation } from './useFastMutation';
import { useRequestEditor } from './useRequestEditor';
import { showToast } from '../lib/toast';
import { useUpdateAnyHttpRequest } from './useUpdateAnyHttpRequest';
export function useImportQuerystring(requestId: string) {
const updateRequest = useUpdateAnyHttpRequest();
const toast = useToast();
const [, { focusParamsTab, forceParamsRefresh, forceUrlRefresh }] = useRequestEditor();
return useFastMutation({
@@ -40,7 +39,7 @@ export function useImportQuerystring(requestId: string) {
});
if (urlParameters.length > 0) {
toast.show({
showToast({
id: 'querystring-imported',
color: 'info',
message: `Extracted ${urlParameters.length} ${pluralize('parameter', urlParameters.length)} from URL`,

View File

@@ -2,11 +2,9 @@ import { openUrl } from '@tauri-apps/plugin-opener';
import { Button } from '../components/core/Button';
import { invokeCmd } from '../lib/tauri';
import { useListenToTauriEvent } from './useListenToTauriEvent';
import { useToast } from './useToast';
import { showToast } from '../lib/toast';
export function useNotificationToast() {
const toast = useToast();
const markRead = (id: string) => {
invokeCmd('cmd_dismiss_notification', { notificationId: id }).catch(console.error);
};
@@ -23,7 +21,7 @@ export function useNotificationToast() {
console.log('Got notification event', payload);
const actionUrl = payload.action?.url;
const actionLabel = payload.action?.label;
toast.show({
showToast({
id: payload.id,
timeout: null,
message: payload.message,

View File

@@ -1,17 +1,15 @@
import { useFastMutation } from './useFastMutation';
import { save } from '@tauri-apps/plugin-dialog';
import type { HttpResponse } from '@yaakapp-internal/models';
import mime from 'mime';
import slugify from 'slugify';
import { InlineCode } from '../components/core/InlineCode';
import { useToast } from './useToast';
import type { HttpResponse } from '@yaakapp-internal/models';
import { getContentTypeHeader } from '../lib/model_util';
import { getHttpRequest } from '../lib/store';
import { invokeCmd } from '../lib/tauri';
import { useFastMutation } from './useFastMutation';
import { showToast } from '../lib/toast';
export function useSaveResponse(response: HttpResponse) {
const toast = useToast();
return useFastMutation({
mutationKey: ['save_response', response.id],
mutationFn: async () => {
@@ -26,7 +24,7 @@ export function useSaveResponse(response: HttpResponse) {
title: 'Save Response',
});
await invokeCmd('cmd_save_response', { responseId: response.id, filepath });
toast.show({
showToast({
message: (
<>
Response saved to <InlineCode>{filepath}</InlineCode>

View File

@@ -1,36 +0,0 @@
import { atom } from 'jotai/index';
import { useMemo } from 'react';
import type { PrivateToastEntry, ToastEntry } from '../components/Toasts';
import { generateId } from '../lib/generateId';
import { jotaiStore } from '../lib/jotai';
export const toastsAtom = atom<PrivateToastEntry[]>([]);
export function useToast() {
return useMemo(
() => ({
show({ id, timeout = 5000, ...props }: ToastEntry) {
id = id ?? generateId();
if (timeout != null) {
setTimeout(() => this.hide(id), timeout);
}
jotaiStore.set(toastsAtom, (a) => {
if (a.some((v) => v.id === id)) {
// It's already visible with this id
return a;
}
return [...a, { id, timeout, ...props }];
});
return id;
},
hide: (id: string) => {
jotaiStore.set(toastsAtom, (all) => {
const t = all.find((t) => t.id === id);
t?.onClose?.();
return all.filter((t) => t.id !== id);
});
},
}),
[],
);
}

29
src-web/lib/toast.ts Normal file
View File

@@ -0,0 +1,29 @@
import { atom } from 'jotai/index';
import type { PrivateToastEntry, ToastEntry } from '../components/Toasts';
import { generateId } from './generateId';
import { jotaiStore } from './jotai';
export const toastsAtom = atom<PrivateToastEntry[]>([]);
export function showToast({ id, timeout = 5000, ...props }: ToastEntry) {
id = id ?? generateId();
if (timeout != null) {
setTimeout(() => hideToast(id), timeout);
}
jotaiStore.set(toastsAtom, (a) => {
if (a.some((v) => v.id === id)) {
// It's already visible with this id
return a;
}
return [...a, { id, timeout, ...props }];
});
return id;
}
export function hideToast(id: string) {
jotaiStore.set(toastsAtom, (all) => {
const t = all.find((t) => t.id === id);
t?.onClose?.();
return all.filter((t) => t.id !== id);
});
}