More analytics, and cancel requests

This commit is contained in:
Gregory Schier
2024-02-24 11:30:07 -08:00
parent 0857ef9afd
commit fd044005a6
43 changed files with 565 additions and 541 deletions

View File

@@ -0,0 +1,10 @@
import { useMutation } from '@tanstack/react-query';
import { event } from '@tauri-apps/api';
import { trackEvent } from '../lib/analytics';
export function useCancelHttpResponse(id: string | null) {
return useMutation<void>({
mutationFn: () => event.emit(`cancel_http_response_${id}`),
onSettled: () => trackEvent('http_response', 'cancel'),
});
}

View File

@@ -0,0 +1,20 @@
import { useMutation } from '@tanstack/react-query';
import { invoke } from '@tauri-apps/api';
import { minPromiseMillis } from '../lib/minPromiseMillis';
import { useAlert } from './useAlert';
export function useCheckForUpdates() {
const alert = useAlert();
return useMutation({
mutationFn: async () => {
const hasUpdate: boolean = await minPromiseMillis(invoke('cmd_check_for_updates'), 500);
if (!hasUpdate) {
alert({
id: 'no-updates',
title: 'No Updates',
body: 'You are currently up to date',
});
}
},
});
}

View File

@@ -26,7 +26,7 @@ export function useCreateCookieJar() {
});
return invoke('cmd_create_cookie_jar', { workspaceId, name });
},
onSettled: () => trackEvent('CookieJar', 'Create'),
onSettled: () => trackEvent('cookie_jar', 'create'),
onSuccess: async (cookieJar) => {
queryClient.setQueryData<CookieJar[]>(
cookieJarsQueryKey({ workspaceId: cookieJar.workspaceId }),

View File

@@ -26,7 +26,7 @@ export function useCreateEnvironment() {
});
return invoke('cmd_create_environment', { name, variables: [], workspaceId });
},
onSettled: () => trackEvent('Environment', 'Create'),
onSettled: () => trackEvent('environment', 'create'),
onSuccess: async (environment) => {
if (workspaceId == null) return;
routes.setEnvironment(environment);

View File

@@ -18,7 +18,7 @@ export function useCreateFolder() {
patch.sortPriority = patch.sortPriority || -Date.now();
return invoke('cmd_create_folder', { workspaceId, ...patch });
},
onSettled: () => trackEvent('Folder', 'Create'),
onSettled: () => trackEvent('folder', 'create'),
onSuccess: async (request) => {
await queryClient.invalidateQueries(foldersQueryKey({ workspaceId: request.workspaceId }));
},

View File

@@ -33,7 +33,7 @@ export function useCreateGrpcRequest() {
// patch.folderId = patch.folderId; // TODO: || activeRequest?.folderId;
return invoke('cmd_create_grpc_request', { workspaceId, name: '', ...patch });
},
onSettled: () => trackEvent('GrpcRequest', 'Create'),
onSettled: () => trackEvent('grpc_request', 'create'),
onSuccess: async (request) => {
routes.navigate('request', {
workspaceId: request.workspaceId,

View File

@@ -34,7 +34,7 @@ export function useCreateHttpRequest() {
patch.folderId = patch.folderId || activeRequest?.folderId;
return invoke('cmd_create_http_request', { workspaceId, name: '', ...patch });
},
onSettled: () => trackEvent('HttpRequest', 'Create'),
onSettled: () => trackEvent('http_request', 'create'),
onSuccess: async (request) => {
routes.navigate('request', {
workspaceId: request.workspaceId,

View File

@@ -10,7 +10,7 @@ export function useCreateWorkspace({ navigateAfter }: { navigateAfter: boolean }
mutationFn: (patch) => {
return invoke('cmd_create_workspace', patch);
},
onSettled: () => trackEvent('Workspace', 'Create'),
onSettled: () => trackEvent('workspace', 'create'),
onSuccess: async (workspace) => {
if (navigateAfter) {
routes.navigate('workspace', { workspaceId: workspace.id });

View File

@@ -30,7 +30,7 @@ export function useDeleteAnyGrpcRequest() {
if (!confirmed) return null;
return invoke('cmd_delete_grpc_request', { requestId: id });
},
onSettled: () => trackEvent('GrpcRequest', 'Delete'),
onSettled: () => trackEvent('grpc_request', 'delete'),
onSuccess: async (request) => {
if (request === null) return;

View File

@@ -31,7 +31,7 @@ export function useDeleteAnyHttpRequest() {
if (!confirmed) return null;
return invoke('cmd_delete_http_request', { requestId: id });
},
onSettled: () => trackEvent('HttpRequest', 'Delete'),
onSettled: () => trackEvent('http_request', 'delete'),
onSuccess: async (request) => {
// Was it cancelled?
if (request === null) return;

View File

@@ -25,7 +25,7 @@ export function useDeleteCookieJar(cookieJar: CookieJar | null) {
if (!confirmed) return null;
return invoke('cmd_delete_cookie_jar', { cookieJarId: cookieJar?.id });
},
onSettled: () => trackEvent('CookieJar', 'Delete'),
onSettled: () => trackEvent('cookie_jar', 'delete'),
onSuccess: async (cookieJar) => {
if (cookieJar === null) return;

View File

@@ -25,7 +25,7 @@ export function useDeleteEnvironment(environment: Environment | null) {
if (!confirmed) return null;
return invoke('cmd_delete_environment', { environmentId: environment?.id });
},
onSettled: () => trackEvent('Environment', 'Delete'),
onSettled: () => trackEvent('environment', 'delete'),
onSuccess: async (environment) => {
if (environment === null) return;

View File

@@ -28,7 +28,7 @@ export function useDeleteFolder(id: string | null) {
if (!confirmed) return null;
return invoke('cmd_delete_folder', { folderId: id });
},
onSettled: () => trackEvent('Folder', 'Delete'),
onSettled: () => trackEvent('folder', 'delete'),
onSuccess: async (folder) => {
// Was it cancelled?
if (folder === null) return;

View File

@@ -10,7 +10,7 @@ export function useDeleteGrpcConnection(id: string | null) {
mutationFn: async () => {
return await invoke('cmd_delete_grpc_connection', { id: id });
},
onSettled: () => trackEvent('GrpcConnection', 'Delete'),
onSettled: () => trackEvent('grpc_connection', 'delete'),
onSuccess: ({ requestId, id: connectionId }) => {
queryClient.setQueryData<GrpcConnection[]>(
grpcConnectionsQueryKey({ requestId }),

View File

@@ -10,7 +10,7 @@ export function useDeleteGrpcConnections(requestId?: string) {
if (requestId === undefined) return;
await invoke('cmd_delete_all_grpc_connections', { requestId });
},
onSettled: () => trackEvent('GrpcConnection', 'DeleteMany'),
onSettled: () => trackEvent('grpc_connection', 'delete_many'),
onSuccess: async () => {
if (requestId === undefined) return;
queryClient.setQueryData(grpcConnectionsQueryKey({ requestId }), []);

View File

@@ -10,7 +10,7 @@ export function useDeleteHttpResponse(id: string | null) {
mutationFn: async () => {
return await invoke('cmd_delete_http_response', { id: id });
},
onSettled: () => trackEvent('HttpResponse', 'Delete'),
onSettled: () => trackEvent('http_response', 'delete'),
onSuccess: ({ requestId, id: responseId }) => {
queryClient.setQueryData<HttpResponse[]>(httpResponsesQueryKey({ requestId }), (responses) =>
(responses ?? []).filter((response) => response.id !== responseId),

View File

@@ -10,7 +10,7 @@ export function useDeleteHttpResponses(requestId?: string) {
if (requestId === undefined) return;
await invoke('cmd_delete_all_http_responses', { requestId });
},
onSettled: () => trackEvent('HttpResponse', 'DeleteMany'),
onSettled: () => trackEvent('http_response', 'delete_many'),
onSuccess: async () => {
if (requestId === undefined) return;
queryClient.setQueryData(httpResponsesQueryKey({ requestId }), []);

View File

@@ -30,7 +30,7 @@ export function useDeleteWorkspace(workspace: Workspace | null) {
if (!confirmed) return null;
return invoke('cmd_delete_workspace', { workspaceId: workspace?.id });
},
onSettled: () => trackEvent('Workspace', 'Delete'),
onSettled: () => trackEvent('workspace', 'delete'),
onSuccess: async (workspace) => {
if (workspace === null) return;

View File

@@ -21,7 +21,7 @@ export function useDuplicateGrpcRequest({
if (id === null) throw new Error("Can't duplicate a null grpc request");
return invoke('cmd_duplicate_grpc_request', { id });
},
onSettled: () => trackEvent('GrpcRequest', 'Duplicate'),
onSettled: () => trackEvent('grpc_request', 'duplicate'),
onSuccess: async (request) => {
if (navigateAfter && activeWorkspaceId !== null) {
routes.navigate('request', {

View File

@@ -21,7 +21,7 @@ export function useDuplicateHttpRequest({
if (id === null) throw new Error("Can't duplicate a null request");
return invoke('cmd_duplicate_http_request', { id });
},
onSettled: () => trackEvent('HttpRequest', 'Duplicate'),
onSettled: () => trackEvent('http_request', 'duplicate'),
onSuccess: async (request) => {
if (navigateAfter && activeWorkspaceId !== null) {
routes.navigate('request', {

View File

@@ -0,0 +1,28 @@
import { useCallback, useEffect } from 'react';
import { createGlobalState } from 'react-use';
import type { HttpRequest, HttpResponse } from '../lib/models';
import { useHttpResponses } from './useHttpResponses';
import { useLatestHttpResponse } from './useLatestHttpResponse';
const usePinnedResponseIdState = createGlobalState<string | null>(null);
export function usePinnedHttpResponse(activeRequest: HttpRequest) {
const [pinnedResponseId, setPinnedResponseId] = usePinnedResponseIdState();
const latestResponse = useLatestHttpResponse(activeRequest.id);
const responses = useHttpResponses(activeRequest.id);
const activeResponse: HttpResponse | null = pinnedResponseId
? responses.find((r) => r.id === pinnedResponseId) ?? null
: latestResponse ?? null;
// Unset pinned response when a new one comes in
useEffect(() => setPinnedResponseId(null), [responses.length, setPinnedResponseId]);
const setPinnedResponse = useCallback(
(r: HttpResponse) => {
setPinnedResponseId(r.id);
},
[setPinnedResponseId],
);
return { activeResponse, setPinnedResponse, pinnedResponseId, responses } as const;
}

View File

@@ -38,7 +38,7 @@ export function useSendAnyRequest(options: { download?: boolean } = {}) {
cookieJarId: activeCookieJar?.id,
});
},
onSettled: () => trackEvent('HttpRequest', 'Send'),
onSettled: () => trackEvent('http_request', 'send'),
onError: (err) => alert({ id: 'send-failed', title: 'Send Failed', body: err }),
});
}