Remove analytics and add more update headers

This commit is contained in:
Gregory Schier
2025-02-24 06:31:49 -08:00
parent af7782c93b
commit 05ac836265
62 changed files with 146 additions and 519 deletions

View File

@@ -5,7 +5,6 @@ import { InlineCode } from '../components/core/InlineCode';
import { VStack } from '../components/core/Stacks';
import { getActiveWorkspaceId } from '../hooks/useActiveWorkspace';
import { createFastMutation } from '../hooks/useFastMutation';
import { trackEvent } from '../lib/analytics';
import { showConfirm } from '../lib/confirm';
import { resolvedModelNameWithFolders } from '../lib/resolvedModelName';
import { pluralizeCount } from '../lib/pluralize';
@@ -42,7 +41,6 @@ export const createFolder = createFastMutation<
patch.sortPriority = patch.sortPriority || -Date.now();
return invokeCmd<Folder>('cmd_update_folder', { folder: { workspaceId, ...patch } });
},
onSettled: () => trackEvent('folder', 'create'),
});
export const syncWorkspace = createFastMutation<

View File

@@ -1,14 +1,10 @@
import type { WebsocketConnection } from '@yaakapp-internal/models';
import { deleteWebsocketConnection as cmdDeleteWebsocketConnection } from '@yaakapp-internal/ws';
import { createFastMutation } from '../hooks/useFastMutation';
import { trackEvent } from '../lib/analytics';
export const deleteWebsocketConnection = createFastMutation({
mutationKey: ['delete_websocket_connection'],
mutationFn: async function (connection: WebsocketConnection) {
return cmdDeleteWebsocketConnection(connection.id);
},
onSuccess: async () => {
trackEvent('websocket_connection', 'delete');
},
});

View File

@@ -1,14 +1,10 @@
import type { WebsocketRequest } from '@yaakapp-internal/models';
import { deleteWebsocketConnections as cmdDeleteWebsocketConnections } from '@yaakapp-internal/ws';
import { createFastMutation } from '../hooks/useFastMutation';
import { trackEvent } from '../lib/analytics';
export const deleteWebsocketConnections = createFastMutation({
mutationKey: ['delete_websocket_connections'],
mutationFn: async function (request: WebsocketRequest) {
return cmdDeleteWebsocketConnections(request.id);
},
onSuccess: async () => {
trackEvent('websocket_connection', 'delete_many');
},
});

View File

@@ -2,7 +2,6 @@ import type { WebsocketRequest } from '@yaakapp-internal/models';
import { deleteWebsocketRequest as cmdDeleteWebsocketRequest } from '@yaakapp-internal/ws';
import { InlineCode } from '../components/core/InlineCode';
import { createFastMutation } from '../hooks/useFastMutation';
import { trackEvent } from '../lib/analytics';
import { showConfirmDelete } from '../lib/confirm';
import { resolvedModelName } from '../lib/resolvedModelName';
@@ -24,7 +23,4 @@ export const deleteWebsocketRequest = createFastMutation({
return cmdDeleteWebsocketRequest(request.id);
},
onSuccess: async () => {
trackEvent('websocket_request', 'delete');
},
});

View File

@@ -1,7 +1,6 @@
import type { WebsocketRequest } from '@yaakapp-internal/models';
import { duplicateWebsocketRequest as cmdDuplicateWebsocketRequest } from '@yaakapp-internal/ws';
import { createFastMutation } from '../hooks/useFastMutation';
import { trackEvent } from '../lib/analytics';
import { router } from '../lib/router';
export const duplicateWebsocketRequest = createFastMutation({
@@ -10,7 +9,6 @@ export const duplicateWebsocketRequest = createFastMutation({
return cmdDuplicateWebsocketRequest(request.id);
},
onSuccess: async (request) => {
trackEvent('websocket_request', 'duplicate');
await router.navigate({
to: '/workspaces/$workspaceId',
params: { workspaceId: request.workspaceId },

View File

@@ -1,7 +1,6 @@
import { SettingsTab } from '../components/Settings/SettingsTab';
import { getActiveWorkspaceId } from '../hooks/useActiveWorkspace';
import { createFastMutation } from '../hooks/useFastMutation';
import { trackEvent } from '../lib/analytics';
import { router } from '../lib/router';
import { invokeCmd } from '../lib/tauri';
@@ -11,7 +10,6 @@ export const openSettings = createFastMutation<void, string, SettingsTab | null>
const workspaceId = getActiveWorkspaceId();
if (workspaceId == null) return;
trackEvent('dialog', 'show', { id: 'settings', tab: `${tab}` });
const location = router.buildLocation({
to: '/workspaces/$workspaceId/settings',
params: { workspaceId },

View File

@@ -2,7 +2,6 @@ import type { WebsocketRequest } from '@yaakapp-internal/models';
import { upsertWebsocketRequest as cmdUpsertWebsocketRequest } from '@yaakapp-internal/ws';
import { differenceInMilliseconds } from 'date-fns';
import { createFastMutation } from '../hooks/useFastMutation';
import { trackEvent } from '../lib/analytics';
import { router } from '../lib/router';
export const upsertWebsocketRequest = createFastMutation<
@@ -16,12 +15,11 @@ export const upsertWebsocketRequest = createFastMutation<
const isNew = differenceInMilliseconds(new Date(), request.createdAt + 'Z') < 100;
if (isNew) {
trackEvent('websocket_request', 'create');
await router.navigate({
to: '/workspaces/$workspaceId',
params: { workspaceId: request.workspaceId },
search: (prev) => ({ ...prev, request_id: request.id }),
});
} else trackEvent('websocket_request', 'update');
}
},
});

View File

@@ -1,7 +1,5 @@
import type { Workspace } from '@yaakapp-internal/models';
import { differenceInMilliseconds } from 'date-fns';
import { createFastMutation } from '../hooks/useFastMutation';
import { trackEvent } from '../lib/analytics';
import { invokeCmd } from '../lib/tauri';
export const upsertWorkspace = createFastMutation<
@@ -11,10 +9,4 @@ export const upsertWorkspace = createFastMutation<
>({
mutationKey: ['upsert_workspace'],
mutationFn: (workspace) => invokeCmd<Workspace>('cmd_update_workspace', { workspace }),
onSuccess: async (workspace) => {
const isNew = differenceInMilliseconds(new Date(), workspace.createdAt + 'Z') < 100;
if (isNew) trackEvent('workspace', 'create');
else trackEvent('workspace', 'update');
},
});

View File

@@ -60,6 +60,7 @@ export function LicenseBadge() {
size="2xs"
variant="border"
className="!rounded-full mx-1"
color={detail.color}
onClick={async () => {
if (check.data.type === 'trialing') {
await setLicenseDetails((v) => ({
@@ -69,8 +70,6 @@ export function LicenseBadge() {
}
openSettings.mutate(SettingsTab.License);
}}
color={detail.color}
event={{ id: 'license-badge', status: check.data.type }}
>
{detail.label}
</Button>

View File

@@ -66,18 +66,8 @@ export function MarkdownEditor({
onChange={setViewMode}
value={viewMode}
options={[
{
event: { id: 'md_mode', mode: 'preview' },
icon: 'eye',
label: 'Preview mode',
value: 'preview',
},
{
event: { id: 'md_mode', mode: 'edit' },
icon: 'pencil',
label: 'Edit mode',
value: 'edit',
},
{ icon: 'eye', label: 'Preview mode', value: 'preview' },
{ icon: 'pencil', label: 'Edit mode', value: 'edit' },
]}
/>
</div>

View File

@@ -96,7 +96,6 @@ export function SettingsAppearance() {
value={`${settings.interfaceFontSize}`}
options={fontSizeOptions}
onChange={(v) => updateSettings.mutate({ interfaceFontSize: parseInt(v) })}
event="ui-font-size"
/>
<Select
size="sm"
@@ -106,7 +105,6 @@ export function SettingsAppearance() {
value={`${settings.editorFontSize}`}
options={fontSizeOptions}
onChange={(v) => updateSettings.mutate({ editorFontSize: clamp(parseInt(v) || 14, 8, 30) })}
event="editor-font-size"
/>
<Select
size="sm"
@@ -116,13 +114,11 @@ export function SettingsAppearance() {
value={`${settings.editorKeymap}`}
options={keymaps}
onChange={(v) => updateSettings.mutate({ editorKeymap: v })}
event="editor-keymap"
/>
<Checkbox
checked={settings.editorSoftWrap}
title="Wrap Editor Lines"
onChange={(editorSoftWrap) => updateSettings.mutate({ editorSoftWrap })}
event="editor-wrap-lines"
/>
<Separator className="my-4" />
@@ -134,7 +130,6 @@ export function SettingsAppearance() {
size="sm"
value={settings.appearance}
onChange={(appearance) => updateSettings.mutate({ appearance })}
event="appearance"
options={[
{ label: 'Automatic', value: 'system' },
{ label: 'Light', value: 'light' },
@@ -152,7 +147,6 @@ export function SettingsAppearance() {
className="flex-1"
value={activeTheme.light.id}
options={lightThemes}
event="theme.light"
onChange={(themeLight) => updateSettings.mutate({ ...settings, themeLight })}
/>
)}
@@ -166,7 +160,6 @@ export function SettingsAppearance() {
size="sm"
value={activeTheme.dark.id}
options={darkThemes}
event="theme.dark"
onChange={(themeDark) => updateSettings.mutate({ ...settings, themeDark })}
/>
)}

View File

@@ -38,7 +38,6 @@ export function SettingsGeneral() {
size="sm"
value={settings.updateChannel}
onChange={(updateChannel) => updateSettings.mutate({ updateChannel })}
event="update-channel"
options={[
{ label: 'Stable (less frequent)', value: 'stable' },
{ label: 'Beta (more frequent)', value: 'beta' },
@@ -59,7 +58,6 @@ export function SettingsGeneral() {
labelPosition="left"
labelClassName="w-[14rem]"
size="sm"
event="workspace-switch-behavior"
value={
settings.openWorkspaceNewWindow === true
? 'new'
@@ -81,9 +79,9 @@ export function SettingsGeneral() {
<Checkbox
className="mt-3"
checked={settings.telemetry}
title="Send Usage Statistics"
event="usage-statistics"
checked={false}
title="Send Usage Statistics (all tracking was removed in 2025.1.2)"
disabled
onChange={(telemetry) => updateSettings.mutate({ telemetry })}
/>
@@ -115,7 +113,6 @@ export function SettingsGeneral() {
<Checkbox
checked={workspace.settingValidateCertificates}
title="Validate TLS Certificates"
event="validate-certs"
onChange={(settingValidateCertificates) =>
upsertWorkspace.mutate({ ...workspace, settingValidateCertificates })
}
@@ -124,7 +121,6 @@ export function SettingsGeneral() {
<Checkbox
checked={workspace.settingFollowRedirects}
title="Follow Redirects"
event="follow-redirects"
onChange={(settingFollowRedirects) =>
upsertWorkspace.mutate({
...workspace,

View File

@@ -81,7 +81,6 @@ export function SettingsLicense() {
color="secondary"
size="sm"
onClick={toggleActivateFormVisible}
event="license.another"
>
Activate Another License
</Button>
@@ -90,7 +89,6 @@ export function SettingsLicense() {
size="sm"
onClick={() => openUrl('https://yaak.app/dashboard')}
rightSlot={<Icon icon="external_link" />}
event="license.support"
>
Direct Support
</Button>
@@ -101,7 +99,6 @@ export function SettingsLicense() {
color="primary"
size="sm"
onClick={toggleActivateFormVisible}
event="license.activate"
>
Activate
</Button>
@@ -110,7 +107,6 @@ export function SettingsLicense() {
size="sm"
onClick={() => openUrl('https://yaak.app/pricing?ref=app.yaak.desktop')}
rightSlot={<Icon icon="external_link" />}
event="license.purchase"
>
Purchase
</Button>
@@ -140,7 +136,6 @@ export function SettingsLicense() {
color="primary"
size="sm"
isLoading={activate.isPending}
event="license.submit"
>
Submit
</Button>

View File

@@ -66,7 +66,6 @@ export function SettingsPlugins() {
type="submit"
color="primary"
className="ml-auto"
event="plugin.add"
>
Add Plugin
</Button>
@@ -76,14 +75,12 @@ export function SettingsPlugins() {
icon="refresh"
title="Reload plugins"
spin={refreshPlugins.isPending}
event="plugin.reload"
onClick={() => refreshPlugins.mutate()}
/>
<IconButton
size="sm"
icon="help"
title="View documentation"
event="plugin.docs"
onClick={() => openUrl('https://feedback.yaak.app/help/articles/6911763-quick-start')}
/>
</HStack>
@@ -107,7 +104,6 @@ function PluginInfo({ plugin }: { plugin: Plugin }) {
size="sm"
icon="trash"
title="Uninstall plugin"
event="plugin.delete"
onClick={() => deletePlugin.mutate()}
/>
</td>

View File

@@ -19,7 +19,6 @@ export function SettingsProxy() {
hideLabel
size="sm"
value={settings.proxy?.type ?? 'automatic'}
event="proxy"
onChange={(v) => {
if (v === 'automatic') {
updateSettings.mutate({ proxy: undefined });

View File

@@ -18,7 +18,6 @@ import { requestsAtom } from '../hooks/useRequests';
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
import { useLatestWebsocketConnection } from '../hooks/useWebsocketConnections';
import { trackEvent } from '../lib/analytics';
import { deepEqualAtom } from '../lib/atoms';
import { languageFromContentType } from '../lib/contentType';
import { generateId } from '../lib/generateId';
@@ -190,7 +189,6 @@ export function WebsocketRequestPane({ style, fullHeight, className, activeReque
environmentId: getActiveEnvironment()?.id ?? null,
cookieJarId: getActiveCookieJar()?.id ?? null,
});
trackEvent('websocket_request', 'send');
}, [activeRequest.id]);
const handleSend = useCallback(async () => {
@@ -199,13 +197,11 @@ export function WebsocketRequestPane({ style, fullHeight, className, activeReque
connectionId: connection?.id,
environmentId: getActiveEnvironment()?.id ?? null,
});
trackEvent('websocket_connection', 'send');
}, [connection]);
const handleCancel = useCallback(async () => {
if (connection == null) return;
await closeWebsocket({ connectionId: connection?.id });
trackEvent('websocket_connection', 'cancel');
}, [connection]);
const handleUrlChange = useCallback(

View File

@@ -46,7 +46,6 @@ export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Prop
icon="search"
title="Search or execute a command"
size="sm"
event="search"
iconColor="secondary"
onClick={togglePalette}
/>

View File

@@ -4,7 +4,6 @@ import type { HTMLAttributes, ReactNode } from 'react';
import { forwardRef, useImperativeHandle, useRef } from 'react';
import type { HotkeyAction } from '../../hooks/useHotKey';
import { useFormattedHotkey, useHotKey } from '../../hooks/useHotKey';
import { trackEvent } from '../../lib/analytics';
import { Icon } from './Icon';
import { LoadingIcon } from './LoadingIcon';
@@ -22,7 +21,6 @@ export type ButtonProps = Omit<HTMLAttributes<HTMLButtonElement>, 'color' | 'onC
leftSlot?: ReactNode;
rightSlot?: ReactNode;
hotkeyAction?: HotkeyAction;
event?: string | { id: string; [attr: string]: number | string };
};
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
@@ -43,7 +41,6 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button
hotkeyAction,
title,
onClick,
event,
...props
}: ButtonProps,
ref,
@@ -107,12 +104,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button
type={type}
className={classes}
disabled={disabled}
onClick={(e) => {
onClick?.(e);
if (event != null) {
trackEvent('button', 'click', typeof event === 'string' ? { id: event } : event);
}
}}
onClick={onClick}
onDoubleClick={(e) => {
// Kind of a hack? This prevents double-clicks from going through buttons. For example, when
// double-clicking the workspace header to toggle window maximization

View File

@@ -1,6 +1,5 @@
import classNames from 'classnames';
import { type ReactNode } from 'react';
import { trackEvent } from '../../lib/analytics';
import { Icon } from './Icon';
import { HStack } from './Stacks';
@@ -13,7 +12,6 @@ export interface CheckboxProps {
inputWrapperClassName?: string;
hideLabel?: boolean;
fullWidth?: boolean;
event?: string;
}
export function Checkbox({
@@ -25,7 +23,6 @@ export function Checkbox({
title,
hideLabel,
fullWidth,
event,
}: CheckboxProps) {
return (
<HStack as="label" space={2} className={classNames(className, 'text-text mr-auto')}>
@@ -42,9 +39,6 @@ export function Checkbox({
disabled={disabled}
onChange={() => {
onChange(checked === 'indeterminate' ? true : !checked);
if (event != null) {
trackEvent('button', 'click', { id: event, checked: checked ? 'on' : 'off' });
}
}}
/>
<div className="absolute inset-0 flex items-center justify-center">

View File

@@ -1,15 +1,13 @@
import { Link as RouterLink } from '@tanstack/react-router';
import classNames from 'classnames';
import type { HTMLAttributes } from 'react';
import { Link as RouterLink } from '@tanstack/react-router';
import { trackEvent } from '../../lib/analytics';
import { Icon } from './Icon';
interface Props extends HTMLAttributes<HTMLAnchorElement> {
href: string;
event?: string;
}
export function Link({ href, children, className, event, ...other }: Props) {
export function Link({ href, children, className, ...other }: Props) {
const isExternal = href.match(/^https?:\/\//);
className = classNames(className, 'relative underline hover:text-violet-600');
@@ -23,9 +21,6 @@ export function Link({ href, children, className, event, ...other }: Props) {
className={classNames(className, 'pr-4 inline-flex items-center')}
onClick={(e) => {
e.preventDefault();
if (event != null) {
trackEvent('link', 'click', { id: event });
}
}}
{...other}
>

View File

@@ -261,7 +261,6 @@ export const PairEditor = forwardRef<PairEditorRef, PairEditorProps>(function Pa
variant="border"
className="m-2"
size="xs"
event="pairs.reveal-more"
>
Show {pairs.length - MAX_INITIAL_PAIRS} More
</Button>

View File

@@ -2,18 +2,17 @@ import classNames from 'classnames';
import { useRef } from 'react';
import { useStateWithDeps } from '../../hooks/useStateWithDeps';
import type { IconProps } from './Icon';
import type { IconButtonProps } from './IconButton';
import { IconButton } from './IconButton';
import { HStack } from './Stacks';
interface Props<T extends string> {
options: { value: T; label: string; icon: IconProps['icon']; event?: IconButtonProps['event'] }[];
options: { value: T; label: string; icon: IconProps['icon'] }[];
onChange: (value: T) => void;
value: T;
name: string;
}
export function SegmentedControl<T extends string>({ value, onChange, options, name }: Props<T>) {
export function SegmentedControl<T extends string>({ value, onChange, options }: Props<T>) {
const [selectedValue, setSelectedValue] = useStateWithDeps<T>(value, [value]);
const containerRef = useRef<HTMLDivElement>(null);
return (
@@ -45,14 +44,13 @@ export function SegmentedControl<T extends string>({ value, onChange, options, n
<IconButton
size="xs"
variant="solid"
color={isActive ? "secondary" : undefined}
color={isActive ? 'secondary' : undefined}
role="radio"
event={{ id: name, value: String(o.value) }}
tabIndex={isSelected ? 0 : -1}
className={classNames(
isActive && '!text-text',
'!px-1.5 !w-auto',
'focus:ring-border-focus',
isActive && '!text-text',
'!px-1.5 !w-auto',
'focus:ring-border-focus',
)}
key={i}
title={o.label}

View File

@@ -2,7 +2,6 @@ import classNames from 'classnames';
import type { CSSProperties, ReactNode } from 'react';
import { useState } from 'react';
import { useOsInfo } from '../../hooks/useOsInfo';
import { trackEvent } from '../../lib/analytics';
import type { ButtonProps } from './Button';
import { Button } from './Button';
import { Label } from './Label';
@@ -22,7 +21,6 @@ export interface SelectProps<T extends string> {
onChange: (value: T) => void;
size?: ButtonProps['size'];
className?: string;
event?: string;
disabled?: boolean;
}
@@ -38,7 +36,6 @@ export function Select<T extends string>({
leftSlot,
onChange,
className,
event,
size = 'md',
}: SelectProps<T>) {
const osInfo = useOsInfo();
@@ -48,9 +45,6 @@ export function Select<T extends string>({
const handleChange = (value: T) => {
onChange?.(value);
if (event != null) {
trackEvent('select', 'click', { id: event, value });
}
};
return (

View File

@@ -1,7 +1,6 @@
import classNames from 'classnames';
import type { ReactNode } from 'react';
import { memo, useEffect, useRef } from 'react';
import { trackEvent } from '../../../lib/analytics';
import { Icon } from '../Icon';
import type { RadioDropdownProps } from '../RadioDropdown';
import { RadioDropdown } from '../RadioDropdown';
@@ -104,14 +103,7 @@ export function Tabs({
onChange={t.options.onChange}
>
<button
onClick={
isActive
? undefined
: () => {
trackEvent('tab', 'click', { label, tab: t.value });
onChangeValue(t.value);
}
}
onClick={isActive ? undefined : () => onChangeValue(t.value)}
className={btnClassName}
>
{option && 'shortLabel' in option && option.shortLabel
@@ -133,14 +125,7 @@ export function Tabs({
return (
<button
key={t.value}
onClick={
isActive
? undefined
: () => {
trackEvent('tab', 'click', { label, tab: t.value });
onChangeValue(t.value);
}
}
onClick={isActive ? undefined : () => onChangeValue(t.value)}
className={btnClassName}
>
{t.label}

View File

@@ -2,7 +2,6 @@ import { useMemo } from 'react';
import { useFloatingSidebarHidden } from '../../hooks/useFloatingSidebarHidden';
import { useShouldFloatSidebar } from '../../hooks/useShouldFloatSidebar';
import { useSidebarHidden } from '../../hooks/useSidebarHidden';
import { trackEvent } from '../../lib/analytics';
import { IconButton } from '../core/IconButton';
import { HStack } from '../core/Stacks';
import { CreateDropdown } from '../CreateDropdown';
@@ -22,8 +21,6 @@ export function SidebarActions() {
<HStack className="h-full">
<IconButton
onClick={async () => {
trackEvent('sidebar', 'toggle');
// NOTE: We're not using the (h) => !h pattern here because the data
// might be different if another window changed it (out of sync)
await setHidden(!hidden);

View File

@@ -1,11 +1,9 @@
import { useFastMutation } from './useFastMutation';
import { event } from '@tauri-apps/api';
import { trackEvent } from '../lib/analytics';
export function useCancelHttpResponse(id: string | null) {
return useFastMutation<void>({
mutationKey: ['cancel_http_response', id],
mutationFn: () => event.emit(`cancel_http_response_${id}`),
onSettled: () => trackEvent('http_response', 'cancel'),
});
}

View File

@@ -1,5 +1,4 @@
import type { CookieJar } from '@yaakapp-internal/models';
import { trackEvent } from '../lib/analytics';
import { showPrompt } from '../lib/prompt';
import { invokeCmd } from '../lib/tauri';
import { getActiveWorkspaceId } from './useActiveWorkspace';
@@ -25,6 +24,5 @@ export function useCreateCookieJar() {
return invokeCmd('cmd_create_cookie_jar', { workspaceId, name });
},
onSettled: () => trackEvent('cookie_jar', 'create'),
});
}

View File

@@ -1,5 +1,4 @@
import type { Environment } from '@yaakapp-internal/models';
import { trackEvent } from '../lib/analytics';
import { showPrompt } from '../lib/prompt';
import { setWorkspaceSearchParams } from '../lib/setWorkspaceSearchParams';
import { invokeCmd } from '../lib/tauri';
@@ -33,7 +32,6 @@ export function useCreateEnvironment() {
environmentId: baseEnvironment.id,
});
},
onSettled: () => trackEvent('environment', 'create'),
onSuccess: async (environment) => {
if (environment == null) return;
setWorkspaceSearchParams({ environment_id: environment.id });

View File

@@ -1,5 +1,4 @@
import type { GrpcRequest } from '@yaakapp-internal/models';
import { trackEvent } from '../lib/analytics';
import { jotaiStore } from '../lib/jotai';
import { invokeCmd } from '../lib/tauri';
import { getActiveRequest } from './useActiveRequest';
@@ -36,7 +35,6 @@ export function useCreateGrpcRequest() {
...patch,
});
},
onSettled: () => trackEvent('grpc_request', 'create'),
onSuccess: async (request) => {
await router.navigate({
to: '/workspaces/$workspaceId',

View File

@@ -1,5 +1,4 @@
import type { HttpRequest } from '@yaakapp-internal/models';
import { trackEvent } from '../lib/analytics';
import { router } from '../lib/router';
import { invokeCmd } from '../lib/tauri';
import { getActiveRequest } from './useActiveRequest';
@@ -30,7 +29,6 @@ export function useCreateHttpRequest() {
request: { workspaceId, ...patch },
});
},
onSettled: () => trackEvent('http_request', 'create'),
onSuccess: async (request) => {
await router.navigate({
to: '/workspaces/$workspaceId',

View File

@@ -1,6 +1,5 @@
import type { Workspace } from '@yaakapp-internal/models';
import { InlineCode } from '../components/core/InlineCode';
import { trackEvent } from '../lib/analytics';
import { showConfirmDelete } from '../lib/confirm';
import { router } from '../lib/router';
import { invokeCmd } from '../lib/tauri';
@@ -24,7 +23,6 @@ export function useDeleteActiveWorkspace() {
if (!confirmed) return null;
return invokeCmd('cmd_delete_workspace', { workspaceId: workspace?.id });
},
onSettled: () => trackEvent('workspace', 'delete'),
onSuccess: async (workspace) => {
if (workspace === null) return;
await router.navigate({ to: '/workspaces' });

View File

@@ -1,6 +1,5 @@
import type { GrpcRequest } from '@yaakapp-internal/models';
import { InlineCode } from '../components/core/InlineCode';
import { trackEvent } from '../lib/analytics';
import { showConfirmDelete } from '../lib/confirm';
import { resolvedModelName } from '../lib/resolvedModelName';
import { invokeCmd } from '../lib/tauri';
@@ -24,6 +23,5 @@ export function useDeleteAnyGrpcRequest() {
}
return invokeCmd('cmd_delete_grpc_request', { requestId: request.id });
},
onSuccess: () => trackEvent('grpc_request', 'delete'),
});
}

View File

@@ -1,6 +1,5 @@
import type { HttpRequest } from '@yaakapp-internal/models';
import { InlineCode } from '../components/core/InlineCode';
import { trackEvent } from '../lib/analytics';
import { showConfirmDelete } from '../lib/confirm';
import { resolvedModelName } from '../lib/resolvedModelName';
import { invokeCmd } from '../lib/tauri';
@@ -24,6 +23,5 @@ export function useDeleteAnyHttpRequest() {
}
return invokeCmd<HttpRequest>('cmd_delete_http_request', { requestId: request.id });
},
onSuccess: () => trackEvent('http_request', 'delete'),
});
}

View File

@@ -1,7 +1,6 @@
import type { CookieJar } from '@yaakapp-internal/models';
import { useSetAtom } from 'jotai';
import { InlineCode } from '../components/core/InlineCode';
import { trackEvent } from '../lib/analytics';
import { showConfirmDelete } from '../lib/confirm';
import { invokeCmd } from '../lib/tauri';
import { cookieJarsAtom } from './useCookieJars';
@@ -26,7 +25,6 @@ export function useDeleteCookieJar(cookieJar: CookieJar | null) {
if (!confirmed) return null;
return invokeCmd('cmd_delete_cookie_jar', { cookieJarId: cookieJar?.id });
},
onSettled: () => trackEvent('cookie_jar', 'delete'),
onSuccess: (cookieJar) => {
if (cookieJar == null) return;

View File

@@ -1,7 +1,6 @@
import type { Environment } from '@yaakapp-internal/models';
import { useSetAtom } from 'jotai';
import { InlineCode } from '../components/core/InlineCode';
import { trackEvent } from '../lib/analytics';
import { showConfirmDelete } from '../lib/confirm';
import { invokeCmd } from '../lib/tauri';
import { environmentsAtom } from './useEnvironments';
@@ -26,7 +25,6 @@ export function useDeleteEnvironment(environment: Environment | null) {
if (!confirmed) return null;
return invokeCmd('cmd_delete_environment', { environmentId: environment?.id });
},
onSettled: () => trackEvent('environment', 'delete'),
onSuccess: (environment) => {
if (environment == null) return;

View File

@@ -1,7 +1,6 @@
import type { Folder } from '@yaakapp-internal/models';
import { useSetAtom } from 'jotai';
import { InlineCode } from '../components/core/InlineCode';
import { trackEvent } from '../lib/analytics';
import { showConfirmDelete } from '../lib/confirm';
import { invokeCmd } from '../lib/tauri';
import { useFastMutation } from './useFastMutation';
@@ -27,7 +26,6 @@ export function useDeleteFolder(id: string | null) {
if (!confirmed) return null;
return invokeCmd('cmd_delete_folder', { folderId: id });
},
onSettled: () => trackEvent('folder', 'delete'),
onSuccess: (folder) => {
if (folder == null) return;

View File

@@ -1,7 +1,6 @@
import { useFastMutation } from './useFastMutation';
import type { GrpcConnection } from '@yaakapp-internal/models';
import {useSetAtom} from "jotai";
import { trackEvent } from '../lib/analytics';
import { invokeCmd } from '../lib/tauri';
import {grpcConnectionsAtom} from "./useGrpcConnections";
import {removeModelById} from "./useSyncModelStores";
@@ -13,7 +12,6 @@ export function useDeleteGrpcConnection(id: string | null) {
mutationFn: async () => {
return await invokeCmd('cmd_delete_grpc_connection', { id: id });
},
onSettled: () => trackEvent('grpc_connection', 'delete'),
onSuccess: (connection) => {
if (connection == null) return;

View File

@@ -1,6 +1,5 @@
import { useFastMutation } from './useFastMutation';
import { useSetAtom } from 'jotai';
import { trackEvent } from '../lib/analytics';
import { invokeCmd } from '../lib/tauri';
import { grpcConnectionsAtom } from './useGrpcConnections';
@@ -12,7 +11,6 @@ export function useDeleteGrpcConnections(requestId?: string) {
if (requestId === undefined) return;
await invokeCmd('cmd_delete_all_grpc_connections', { requestId });
},
onSettled: () => trackEvent('grpc_connection', 'delete_many'),
onSuccess: () => {
setGrpcConnections((all) => all.filter((r) => r.requestId !== requestId));
},

View File

@@ -1,7 +1,6 @@
import { useFastMutation } from './useFastMutation';
import type { HttpResponse } from '@yaakapp-internal/models';
import {useSetAtom} from "jotai";
import { trackEvent } from '../lib/analytics';
import { invokeCmd } from '../lib/tauri';
import {httpResponsesAtom} from "./useHttpResponses";
import {removeModelById} from "./useSyncModelStores";
@@ -13,7 +12,6 @@ export function useDeleteHttpResponse(id: string | null) {
mutationFn: async () => {
return await invokeCmd('cmd_delete_http_response', { id: id });
},
onSettled: () => trackEvent('http_response', 'delete'),
onSuccess: (response) => {
setHttpResponses(removeModelById(response));
}

View File

@@ -1,6 +1,5 @@
import { useFastMutation } from './useFastMutation';
import { useSetAtom } from 'jotai';
import { trackEvent } from '../lib/analytics';
import { invokeCmd } from '../lib/tauri';
import { httpResponsesAtom } from './useHttpResponses';
@@ -15,6 +14,5 @@ export function useDeleteHttpResponses(requestId?: string) {
onSuccess: () => {
setHttpResponses((all) => all.filter((r) => r.requestId !== requestId));
},
onSettled: () => trackEvent('http_response', 'delete_many'),
});
}

View File

@@ -1,11 +1,9 @@
import { useFastMutation } from './useFastMutation';
import { trackEvent } from '../lib/analytics';
import { invokeCmd } from '../lib/tauri';
export function useDuplicateFolder(id: string) {
return useFastMutation<void, string>({
mutationKey: ['duplicate_folder', id],
mutationFn: () => invokeCmd('cmd_duplicate_folder', { id }),
onSettled: () => trackEvent('folder', 'duplicate'),
});
}

View File

@@ -1,5 +1,4 @@
import type { GrpcRequest } from '@yaakapp-internal/models';
import { trackEvent } from '../lib/analytics';
import { router } from '../lib/router';
import { invokeCmd } from '../lib/tauri';
import { useFastMutation } from './useFastMutation';
@@ -18,7 +17,6 @@ export function useDuplicateGrpcRequest({
if (id === null) throw new Error("Can't duplicate a null grpc request");
return invokeCmd('cmd_duplicate_grpc_request', { id });
},
onSettled: () => trackEvent('grpc_request', 'duplicate'),
onSuccess: async (request) => {
if (id == null) return;

View File

@@ -1,5 +1,4 @@
import type { HttpRequest } from '@yaakapp-internal/models';
import { trackEvent } from '../lib/analytics';
import { router } from '../lib/router';
import { invokeCmd } from '../lib/tauri';
import { useFastMutation } from './useFastMutation';
@@ -17,7 +16,6 @@ export function useDuplicateHttpRequest({
if (id === null) throw new Error("Can't duplicate a null request");
return invokeCmd('cmd_duplicate_http_request', { id });
},
onSettled: () => trackEvent('http_request', 'duplicate'),
onSuccess: async (request) => {
if (navigateAfter) {
await router.navigate({

View File

@@ -1,7 +1,6 @@
import type { MutationKey } from '@tanstack/react-query';
import { useMemo } from 'react';
import { showToast } from '../lib/toast';
import { trackEvent } from '../lib/analytics';
interface MutationOptions<TData, TError, TVariables> {
mutationKey: MutationKey;
@@ -36,7 +35,6 @@ export function createFastMutation<TData = unknown, TError = unknown, TVariables
const stringKey = mutationKey.join('.');
const e = err as TError;
console.log('mutation error', stringKey, e);
trackEvent('mutation', 'error', { key: stringKey });
if (!disableToastError) {
showToast({
id: stringKey,

View File

@@ -1,7 +1,6 @@
import { useMutation, useQuery } from '@tanstack/react-query';
import { emit } from '@tauri-apps/api/event';
import type { GrpcConnection, GrpcRequest } from '@yaakapp-internal/models';
import { trackEvent } from '../lib/analytics';
import { minPromiseMillis } from '../lib/minPromiseMillis';
import { invokeCmd } from '../lib/tauri';
import { useActiveEnvironment } from './useActiveEnvironment';
@@ -24,26 +23,22 @@ export function useGrpc(
mutationKey: ['grpc_go', conn?.id],
mutationFn: () =>
invokeCmd<void>('cmd_grpc_go', { requestId, environmentId: environment?.id, protoFiles }),
onSettled: () => trackEvent('grpc_request', 'send'),
});
const send = useMutation({
mutationKey: ['grpc_send', conn?.id],
mutationFn: ({ message }: { message: string }) =>
emit(`grpc_client_msg_${conn?.id ?? 'none'}`, { Message: message }),
onSettled: () => trackEvent('grpc_connection', 'send'),
});
const cancel = useMutation({
mutationKey: ['grpc_cancel', conn?.id ?? 'n/a'],
mutationFn: () => emit(`grpc_client_msg_${conn?.id ?? 'none'}`, 'Cancel'),
onSettled: () => trackEvent('grpc_connection', 'cancel'),
});
const commit = useMutation({
mutationKey: ['grpc_commit', conn?.id ?? 'n/a'],
mutationFn: () => emit(`grpc_client_msg_${conn?.id ?? 'none'}`, 'Commit'),
onSettled: () => trackEvent('grpc_connection', 'commit'),
});
const debouncedUrl = useDebouncedValue<string>(req?.url ?? '', 1000);

View File

@@ -1,5 +1,4 @@
import { useFastMutation } from './useFastMutation';
import { trackEvent } from '../lib/analytics';
import { invokeCmd } from '../lib/tauri';
export function useInstallPlugin() {
@@ -8,6 +7,5 @@ export function useInstallPlugin() {
mutationFn: async (directory: string) => {
await invokeCmd('cmd_install_plugin', { directory });
},
onSettled: () => trackEvent('plugin', 'create'),
});
}

View File

@@ -1,5 +1,4 @@
import type { HttpResponse } from '@yaakapp-internal/models';
import { trackEvent } from '../lib/analytics';
import { invokeCmd } from '../lib/tauri';
import { getActiveCookieJar } from './useActiveCookieJar';
import { getActiveEnvironment } from './useActiveEnvironment';
@@ -21,6 +20,5 @@ export function useSendAnyHttpRequest() {
cookieJarId: getActiveCookieJar()?.id,
});
},
onSettled: () => trackEvent('http_request', 'send'),
});
}

View File

@@ -1,6 +1,5 @@
import { useFastMutation } from './useFastMutation';
import type { Plugin } from '@yaakapp-internal/models';
import { trackEvent } from '../lib/analytics';
import { invokeCmd } from '../lib/tauri';
export function useUninstallPlugin(pluginId: string) {
@@ -9,6 +8,5 @@ export function useUninstallPlugin(pluginId: string) {
mutationFn: async () => {
return invokeCmd('cmd_uninstall_plugin', { pluginId });
},
onSettled: () => trackEvent('plugin', 'delete'),
});
}

View File

@@ -1,14 +0,0 @@
import type { AnalyticsAction, AnalyticsResource } from '../../src-tauri/bindings/analytics';
import { invokeCmd } from './tauri';
export function trackEvent(
resource: AnalyticsResource,
action: AnalyticsAction,
attributes: Record<string, string | number> = {},
) {
invokeCmd('cmd_track_event', {
resource: resource,
action,
attributes,
}).catch(console.error);
}

View File

@@ -1,12 +1,10 @@
import { atom } from 'jotai/index';
import type { DialogInstance } from '../components/Dialogs';
import { trackEvent } from './analytics';
import { jotaiStore } from './jotai';
export const dialogsAtom = atom<DialogInstance[]>([]);
export function showDialog({ id, ...props }: DialogInstance) {
trackEvent('dialog', 'show', { id });
jotaiStore.set(dialogsAtom, (a) => [...a.filter((d) => d.id !== id), { id, ...props }]);
}

View File

@@ -70,7 +70,6 @@ type TauriCmd =
| 'cmd_set_update_mode'
| 'cmd_template_functions'
| 'cmd_template_tokens_to_string'
| 'cmd_track_event'
| 'cmd_uninstall_plugin'
| 'cmd_update_cookie_jar'
| 'cmd_update_environment'