diff --git a/apps/desktop/src/auth/context.tsx b/apps/desktop/src/auth/context.tsx index 4771086208..47cda481f9 100644 --- a/apps/desktop/src/auth/context.tsx +++ b/apps/desktop/src/auth/context.tsx @@ -9,6 +9,7 @@ import { useMutation } from "@tanstack/react-query"; import { getVersion } from "@tauri-apps/api/app"; import { getCurrentWindow } from "@tauri-apps/api/window"; import { version as osVersion, platform } from "@tauri-apps/plugin-os"; +import posthog from "posthog-js"; import { createContext, useCallback, @@ -129,6 +130,8 @@ async function trackAuthEvent( }, }); + posthog.identify(session.user.id); + if (event === "SIGNED_IN") { void analyticsCommands.event({ event: "user_signed_in" }); } @@ -136,6 +139,7 @@ async function trackAuthEvent( if (event === "SIGNED_OUT") { trackedUserId = null; + posthog.reset(); } } diff --git a/apps/desktop/src/main.tsx b/apps/desktop/src/main.tsx index 1156af09b6..59928316b7 100644 --- a/apps/desktop/src/main.tsx +++ b/apps/desktop/src/main.tsx @@ -1,4 +1,5 @@ import "./styles/globals.css"; +import "./providers/posthog"; import * as Sentry from "@sentry/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; @@ -18,6 +19,7 @@ import "@hypr/ui/globals.css"; import { createToolRegistry } from "./contexts/tool-registry/core"; import { env } from "./env"; import { initPluginGlobals } from "./plugins/globals"; +import { SessionReplay } from "./providers/session-replay"; import { routeTree } from "./routeTree.gen"; import { TaskManager } from "./services/task-manager"; import { ErrorComponent, NotFoundComponent } from "./shared/control"; @@ -114,6 +116,7 @@ function AppWithTiny() { + diff --git a/apps/desktop/src/providers/posthog.ts b/apps/desktop/src/providers/posthog.ts new file mode 100644 index 0000000000..27a0fe0550 --- /dev/null +++ b/apps/desktop/src/providers/posthog.ts @@ -0,0 +1,22 @@ +import posthog from "posthog-js"; + +import { env } from "~/env"; + +const key = env.VITE_POSTHOG_API_KEY; + +if (key) { + posthog.init(key, { + api_host: env.VITE_POSTHOG_HOST, + + autocapture: false, + capture_pageview: false, + capture_pageleave: false, + + disable_session_recording: true, + + session_recording: { + maskAllInputs: true, + maskTextSelector: "*", + }, + }); +} diff --git a/apps/desktop/src/providers/session-replay.tsx b/apps/desktop/src/providers/session-replay.tsx new file mode 100644 index 0000000000..4545fb5497 --- /dev/null +++ b/apps/desktop/src/providers/session-replay.tsx @@ -0,0 +1,26 @@ +import posthog from "posthog-js"; +import { useEffect } from "react"; + +import { useConfigValue } from "~/shared/config"; +import { useTabs } from "~/store/zustand/tabs"; + +const RECORDED_TAB_TYPES = new Set(["settings", "ai", "onboarding"]); + +export function SessionReplay() { + const telemetryConsent = useConfigValue("telemetry_consent"); + const tabType = useTabs((state) => state.currentTab?.type); + + const shouldRecord = + telemetryConsent && !!tabType && RECORDED_TAB_TYPES.has(tabType); + + useEffect(() => { + if (shouldRecord) { + posthog.startSessionRecording(); + return () => posthog.stopSessionRecording(); + } else { + posthog.stopSessionRecording(); + } + }, [shouldRecord]); + + return null; +}