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
+2 -3
View File
@@ -29,8 +29,8 @@ import { useSyncWorkspaceChildModels } from '../hooks/useSyncWorkspaceChildModel
import { useSyncWorkspaceRequestTitle } from '../hooks/useSyncWorkspaceRequestTitle'; import { useSyncWorkspaceRequestTitle } from '../hooks/useSyncWorkspaceRequestTitle';
import { useSyncZoomSetting } from '../hooks/useSyncZoomSetting'; import { useSyncZoomSetting } from '../hooks/useSyncZoomSetting';
import { useSubscribeTemplateFunctions } from '../hooks/useTemplateFunctions'; import { useSubscribeTemplateFunctions } from '../hooks/useTemplateFunctions';
import {useToast} from "../hooks/useToast";
import { useToggleCommandPalette } from '../hooks/useToggleCommandPalette'; import { useToggleCommandPalette } from '../hooks/useToggleCommandPalette';
import { showToast } from '../lib/toast';
export function GlobalHooks() { export function GlobalHooks() {
useSyncModelStores(); useSyncModelStores();
@@ -58,9 +58,8 @@ export function GlobalHooks() {
useEnsureActiveCookieJar(); useEnsureActiveCookieJar();
// Listen for toasts // Listen for toasts
const toast = useToast();
useListenToTauriEvent<ShowToastRequest>('show_toast', (event) => { useListenToTauriEvent<ShowToastRequest>('show_toast', (event) => {
toast.show({ ...event.payload }); showToast({ ...event.payload });
}); });
// Trigger workspace sync operation when workspace files change // Trigger workspace sync operation when workspace files change
+2 -3
View File
@@ -1,11 +1,11 @@
import { useNavigate } from '@tanstack/react-router'; import { useNavigate } from '@tanstack/react-router';
import type { GrpcRequest, HttpRequest } from '@yaakapp-internal/models'; import type { GrpcRequest, HttpRequest } from '@yaakapp-internal/models';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useToast } from '../hooks/useToast';
import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest'; import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest';
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest'; import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
import { useWorkspaces } from '../hooks/useWorkspaces'; import { useWorkspaces } from '../hooks/useWorkspaces';
import { fallbackRequestName } from '../lib/fallbackRequestName'; import { fallbackRequestName } from '../lib/fallbackRequestName';
import {showToast} from "../lib/toast";
import { Button } from './core/Button'; import { Button } from './core/Button';
import { InlineCode } from './core/InlineCode'; import { InlineCode } from './core/InlineCode';
import { Select } from './core/Select'; import { Select } from './core/Select';
@@ -21,7 +21,6 @@ export function MoveToWorkspaceDialog({ onDone, request, activeWorkspaceId }: Pr
const workspaces = useWorkspaces(); const workspaces = useWorkspaces();
const updateHttpRequest = useUpdateAnyHttpRequest(); const updateHttpRequest = useUpdateAnyHttpRequest();
const updateGrpcRequest = useUpdateAnyGrpcRequest(); const updateGrpcRequest = useUpdateAnyGrpcRequest();
const toast = useToast();
const navigate = useNavigate(); const navigate = useNavigate();
const [selectedWorkspaceId, setSelectedWorkspaceId] = useState<string>(activeWorkspaceId); 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 // Hide after a moment, to give time for request to disappear
setTimeout(onDone, 100); setTimeout(onDone, 100);
toast.show({ showToast({
id: 'workspace-moved', id: 'workspace-moved',
message: ( message: (
<> <>
+2 -5
View File
@@ -16,7 +16,6 @@ import { usePinnedHttpResponse } from '../hooks/usePinnedHttpResponse';
import { useRequestEditor, useRequestEditorEvent } from '../hooks/useRequestEditor'; import { useRequestEditor, useRequestEditorEvent } from '../hooks/useRequestEditor';
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey'; import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest'; import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest';
import { useToast } from '../hooks/useToast';
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest'; import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
import { deepEqualAtom } from '../lib/atoms'; import { deepEqualAtom } from '../lib/atoms';
import { languageFromContentType } from '../lib/contentType'; import { languageFromContentType } from '../lib/contentType';
@@ -35,6 +34,7 @@ import {
BODY_TYPE_OTHER, BODY_TYPE_OTHER,
BODY_TYPE_XML, BODY_TYPE_XML,
} from '../lib/model_util'; } from '../lib/model_util';
import { showToast } from '../lib/toast';
import { BasicAuth } from './BasicAuth'; import { BasicAuth } from './BasicAuth';
import { BearerAuth } from './BearerAuth'; import { BearerAuth } from './BearerAuth';
import { BinaryFileEditor } from './BinaryFileEditor'; import { BinaryFileEditor } from './BinaryFileEditor';
@@ -123,8 +123,6 @@ export const RequestPane = memo(function RequestPane({
[activeRequest, updateRequestAsync], [activeRequest, updateRequestAsync],
); );
const toast = useToast();
const { urlParameterPairs, urlParametersKey } = useMemo(() => { const { urlParameterPairs, urlParametersKey } = useMemo(() => {
const placeholderNames = Array.from(activeRequest.url.matchAll(/\/(:[^/]+)/g)).map( const placeholderNames = Array.from(activeRequest.url.matchAll(/\/(:[^/]+)/g)).map(
(m) => m[1] ?? '', (m) => m[1] ?? '',
@@ -182,7 +180,7 @@ export const RequestPane = memo(function RequestPane({
const showMethodToast = (newMethod: string) => { const showMethodToast = (newMethod: string) => {
if (activeRequest.method.toLowerCase() === newMethod.toLowerCase()) return; if (activeRequest.method.toLowerCase() === newMethod.toLowerCase()) return;
toast.show({ showToast({
id: 'switched-method', id: 'switched-method',
message: ( message: (
<> <>
@@ -276,7 +274,6 @@ export const RequestPane = memo(function RequestPane({
activeRequestId, activeRequestId,
handleContentTypeChange, handleContentTypeChange,
numParams, numParams,
toast,
updateRequest, updateRequest,
updateRequestAsync, updateRequestAsync,
urlParameterPairs.length, urlParameterPairs.length,
+2 -3
View File
@@ -1,7 +1,7 @@
import { AnimatePresence } from 'framer-motion'; import { AnimatePresence } from 'framer-motion';
import { useAtomValue } from 'jotai'; import { useAtomValue } from 'jotai';
import React, { type ReactNode } from 'react'; 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 { Toast, type ToastProps } from './core/Toast';
import { Portal } from './Portal'; import { Portal } from './Portal';
@@ -18,7 +18,6 @@ export type PrivateToastEntry = ToastEntry & {
}; };
function ToastInstance({ id, message, timeout, ...props }: PrivateToastEntry) { function ToastInstance({ id, message, timeout, ...props }: PrivateToastEntry) {
const toast = useToast();
return ( return (
<Toast <Toast
open open
@@ -26,7 +25,7 @@ function ToastInstance({ id, message, timeout, ...props }: PrivateToastEntry) {
{...props} {...props}
// We call onClose inside actions.hide instead of passing to toast so that // We call onClose inside actions.hide instead of passing to toast so that
// it gets called from external close calls as well // it gets called from external close calls as well
onClose={() => toast.hide(id)} onClose={() => hideToast(id)}
> >
{message} {message}
</Toast> </Toast>
@@ -1,10 +1,9 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { InlineCode } from '../components/core/InlineCode'; import { InlineCode } from '../components/core/InlineCode';
import { useActiveWorkspace } from './useActiveWorkspace'; import { useActiveWorkspace } from './useActiveWorkspace';
import { useToast } from './useToast'; import { showToast } from '../lib/toast';
export function useActiveWorkspaceChangedToast() { export function useActiveWorkspaceChangedToast() {
const toast = useToast();
const activeWorkspace = useActiveWorkspace(); const activeWorkspace = useActiveWorkspace();
const [id, setId] = useState<string | null>(activeWorkspace?.id ?? null); const [id, setId] = useState<string | null>(activeWorkspace?.id ?? null);
@@ -17,7 +16,7 @@ export function useActiveWorkspaceChangedToast() {
// Don't notify on the first load // Don't notify on the first load
if (id === null) return; if (id === null) return;
toast.show({ showToast({
id: `workspace-changed-${activeWorkspace.id}`, id: `workspace-changed-${activeWorkspace.id}`,
timeout: 3000, timeout: 3000,
message: ( message: (
@@ -27,5 +26,5 @@ export function useActiveWorkspaceChangedToast() {
</> </>
), ),
}); });
}, [activeWorkspace, id, toast]); }, [activeWorkspace, id]);
} }
+1 -4
View File
@@ -6,7 +6,6 @@ import { invokeCmd } from '../lib/tauri';
import { getActiveWorkspaceId } from './useActiveWorkspace'; import { getActiveWorkspaceId } from './useActiveWorkspace';
import { createFastMutation } from './useFastMutation'; import { createFastMutation } from './useFastMutation';
import { usePrompt } from './usePrompt'; import { usePrompt } from './usePrompt';
import { useToast } from './useToast';
function makeCommands({ function makeCommands({
navigate, navigate,
@@ -14,7 +13,6 @@ function makeCommands({
}: { }: {
navigate: ReturnType<typeof useNavigate>; navigate: ReturnType<typeof useNavigate>;
prompt: ReturnType<typeof usePrompt>; prompt: ReturnType<typeof usePrompt>;
toast: ReturnType<typeof useToast>;
}) { }) {
return { return {
createWorkspace: createFastMutation<Workspace, void, Partial<Workspace>>({ createWorkspace: createFastMutation<Workspace, void, Partial<Workspace>>({
@@ -65,7 +63,6 @@ function makeCommands({
export function useCommands() { export function useCommands() {
const navigate = useNavigate(); const navigate = useNavigate();
const toast = useToast();
const prompt = usePrompt(); const prompt = usePrompt();
return useMemo(() => makeCommands({ navigate, toast, prompt }), [navigate, prompt, toast]); return useMemo(() => makeCommands({ navigate, prompt }), [navigate, prompt]);
} }
+3 -5
View File
@@ -1,10 +1,8 @@
import { clear, writeText } from '@tauri-apps/plugin-clipboard-manager'; import { clear, writeText } from '@tauri-apps/plugin-clipboard-manager';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useToast } from './useToast'; import { showToast } from '../lib/toast';
export function useCopy({ disableToast }: { disableToast?: boolean } = {}) { export function useCopy({ disableToast }: { disableToast?: boolean } = {}) {
const toast = useToast();
const copy = useCallback( const copy = useCallback(
(text: string | null) => { (text: string | null) => {
if (text == null) { if (text == null) {
@@ -13,7 +11,7 @@ export function useCopy({ disableToast }: { disableToast?: boolean } = {}) {
writeText(text).catch(console.error); writeText(text).catch(console.error);
} }
if (text != '' && !disableToast) { if (text != '' && !disableToast) {
toast.show({ showToast({
id: 'copied', id: 'copied',
color: 'secondary', color: 'secondary',
icon: 'copy', icon: 'copy',
@@ -21,7 +19,7 @@ export function useCopy({ disableToast }: { disableToast?: boolean } = {}) {
}); });
} }
}, },
[disableToast, toast], [disableToast],
); );
return copy; return copy;
+2 -3
View File
@@ -4,13 +4,12 @@ import { getActiveWorkspace } from './useActiveWorkspace';
import { useAlert } from './useAlert'; import { useAlert } from './useAlert';
import { useDialog } from './useDialog'; import { useDialog } from './useDialog';
import { useFastMutation } from './useFastMutation'; import { useFastMutation } from './useFastMutation';
import { useToast } from './useToast'; import { showToast } from '../lib/toast';
import { workspacesAtom } from './useWorkspaces'; import { workspacesAtom } from './useWorkspaces';
export function useExportData() { export function useExportData() {
const alert = useAlert(); const alert = useAlert();
const dialog = useDialog(); const dialog = useDialog();
const toast = useToast();
return useFastMutation({ return useFastMutation({
mutationKey: ['export_data'], mutationKey: ['export_data'],
@@ -32,7 +31,7 @@ export function useExportData() {
<ExportDataDialog <ExportDataDialog
onHide={hide} onHide={hide}
onSuccess={() => { onSuccess={() => {
toast.show({ showToast({
color: 'success', color: 'success',
message: 'Data export successful', message: 'Data export successful',
}); });
+2 -3
View File
@@ -4,14 +4,13 @@ import { getActiveWorkspaceId } from './useActiveWorkspace';
import { useCreateHttpRequest } from './useCreateHttpRequest'; import { useCreateHttpRequest } from './useCreateHttpRequest';
import { useFastMutation } from './useFastMutation'; import { useFastMutation } from './useFastMutation';
import { useRequestUpdateKey } from './useRequestUpdateKey'; import { useRequestUpdateKey } from './useRequestUpdateKey';
import { useToast } from './useToast'; import { showToast } from '../lib/toast';
import { useUpdateAnyHttpRequest } from './useUpdateAnyHttpRequest'; import { useUpdateAnyHttpRequest } from './useUpdateAnyHttpRequest';
export function useImportCurl() { export function useImportCurl() {
const updateRequest = useUpdateAnyHttpRequest(); const updateRequest = useUpdateAnyHttpRequest();
const createRequest = useCreateHttpRequest(); const createRequest = useCreateHttpRequest();
const { wasUpdatedExternally } = useRequestUpdateKey(null); const { wasUpdatedExternally } = useRequestUpdateKey(null);
const toast = useToast();
return useFastMutation({ return useFastMutation({
mutationKey: ['import_curl'], mutationKey: ['import_curl'],
@@ -50,7 +49,7 @@ export function useImportCurl() {
setTimeout(() => wasUpdatedExternally(overwriteRequestId), 100); setTimeout(() => wasUpdatedExternally(overwriteRequestId), 100);
} }
toast.show({ showToast({
color: 'success', color: 'success',
message: `${verb} request from Curl`, message: `${verb} request from Curl`,
}); });
+4 -5
View File
@@ -1,15 +1,14 @@
import {generateId} from "../lib/generateId";
import { useFastMutation } from './useFastMutation';
import type { HttpUrlParameter } from '@yaakapp-internal/models'; import type { HttpUrlParameter } from '@yaakapp-internal/models';
import { useToast } from './useToast'; import { generateId } from '../lib/generateId';
import { pluralize } from '../lib/pluralize'; import { pluralize } from '../lib/pluralize';
import { getHttpRequest } from '../lib/store'; import { getHttpRequest } from '../lib/store';
import { useFastMutation } from './useFastMutation';
import { useRequestEditor } from './useRequestEditor'; import { useRequestEditor } from './useRequestEditor';
import { showToast } from '../lib/toast';
import { useUpdateAnyHttpRequest } from './useUpdateAnyHttpRequest'; import { useUpdateAnyHttpRequest } from './useUpdateAnyHttpRequest';
export function useImportQuerystring(requestId: string) { export function useImportQuerystring(requestId: string) {
const updateRequest = useUpdateAnyHttpRequest(); const updateRequest = useUpdateAnyHttpRequest();
const toast = useToast();
const [, { focusParamsTab, forceParamsRefresh, forceUrlRefresh }] = useRequestEditor(); const [, { focusParamsTab, forceParamsRefresh, forceUrlRefresh }] = useRequestEditor();
return useFastMutation({ return useFastMutation({
@@ -40,7 +39,7 @@ export function useImportQuerystring(requestId: string) {
}); });
if (urlParameters.length > 0) { if (urlParameters.length > 0) {
toast.show({ showToast({
id: 'querystring-imported', id: 'querystring-imported',
color: 'info', color: 'info',
message: `Extracted ${urlParameters.length} ${pluralize('parameter', urlParameters.length)} from URL`, message: `Extracted ${urlParameters.length} ${pluralize('parameter', urlParameters.length)} from URL`,
+2 -4
View File
@@ -2,11 +2,9 @@ import { openUrl } from '@tauri-apps/plugin-opener';
import { Button } from '../components/core/Button'; import { Button } from '../components/core/Button';
import { invokeCmd } from '../lib/tauri'; import { invokeCmd } from '../lib/tauri';
import { useListenToTauriEvent } from './useListenToTauriEvent'; import { useListenToTauriEvent } from './useListenToTauriEvent';
import { useToast } from './useToast'; import { showToast } from '../lib/toast';
export function useNotificationToast() { export function useNotificationToast() {
const toast = useToast();
const markRead = (id: string) => { const markRead = (id: string) => {
invokeCmd('cmd_dismiss_notification', { notificationId: id }).catch(console.error); invokeCmd('cmd_dismiss_notification', { notificationId: id }).catch(console.error);
}; };
@@ -23,7 +21,7 @@ export function useNotificationToast() {
console.log('Got notification event', payload); console.log('Got notification event', payload);
const actionUrl = payload.action?.url; const actionUrl = payload.action?.url;
const actionLabel = payload.action?.label; const actionLabel = payload.action?.label;
toast.show({ showToast({
id: payload.id, id: payload.id,
timeout: null, timeout: null,
message: payload.message, message: payload.message,
+4 -6
View File
@@ -1,17 +1,15 @@
import { useFastMutation } from './useFastMutation';
import { save } from '@tauri-apps/plugin-dialog'; import { save } from '@tauri-apps/plugin-dialog';
import type { HttpResponse } from '@yaakapp-internal/models';
import mime from 'mime'; import mime from 'mime';
import slugify from 'slugify'; import slugify from 'slugify';
import { InlineCode } from '../components/core/InlineCode'; import { InlineCode } from '../components/core/InlineCode';
import { useToast } from './useToast';
import type { HttpResponse } from '@yaakapp-internal/models';
import { getContentTypeHeader } from '../lib/model_util'; import { getContentTypeHeader } from '../lib/model_util';
import { getHttpRequest } from '../lib/store'; import { getHttpRequest } from '../lib/store';
import { invokeCmd } from '../lib/tauri'; import { invokeCmd } from '../lib/tauri';
import { useFastMutation } from './useFastMutation';
import { showToast } from '../lib/toast';
export function useSaveResponse(response: HttpResponse) { export function useSaveResponse(response: HttpResponse) {
const toast = useToast();
return useFastMutation({ return useFastMutation({
mutationKey: ['save_response', response.id], mutationKey: ['save_response', response.id],
mutationFn: async () => { mutationFn: async () => {
@@ -26,7 +24,7 @@ export function useSaveResponse(response: HttpResponse) {
title: 'Save Response', title: 'Save Response',
}); });
await invokeCmd('cmd_save_response', { responseId: response.id, filepath }); await invokeCmd('cmd_save_response', { responseId: response.id, filepath });
toast.show({ showToast({
message: ( message: (
<> <>
Response saved to <InlineCode>{filepath}</InlineCode> Response saved to <InlineCode>{filepath}</InlineCode>
-36
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
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);
});
}