1- import { useEffect , useState } from 'react'
2- import { HashRouter , Routes , Route , Navigate } from 'react-router-dom'
1+ import { useEffect , useRef , useState } from 'react'
2+ import { HashRouter , Routes , Route , Navigate , useLocation } from 'react-router-dom'
33import { useQueryClient } from '@tanstack/react-query'
44import { listen , invoke } from '@/mainview/lib/native'
55import { useTranslation } from 'react-i18next'
6+ import {
7+ captureTelemetry ,
8+ identifyTelemetry ,
9+ setTelemetryEnabled ,
10+ } from '@/mainview/lib/telemetry'
611import Layout from './components/Layout'
712import Dashboard from './pages/Dashboard'
813import SkillsManager from './pages/SkillsManager'
@@ -22,8 +27,11 @@ const STAR_PROMPT_RESHOW_MS = 3 * 24 * 60 * 60 * 1000
2227
2328function AppInner ( ) {
2429 const queryClient = useQueryClient ( )
30+ const location = useLocation ( )
2531 const { i18n } = useTranslation ( )
2632 useTheme ( )
33+ const appOpenedTrackedRef = useRef ( false )
34+ const [ telemetryReady , setTelemetryReady ] = useState ( false )
2735 const [ closeDialogOpen , setCloseDialogOpen ] = useState ( false )
2836 const [ showGithubStarPrompt , setShowGithubStarPrompt ] = useState ( false )
2937 // Onboarding shows on very first launch (or when user explicitly replays it
@@ -37,6 +45,25 @@ function AppInner() {
3745 }
3846 } )
3947
48+ useEffect ( ( ) => {
49+ if ( ! telemetryReady || appOpenedTrackedRef . current ) return
50+ appOpenedTrackedRef . current = true
51+ captureTelemetry ( 'app_opened' )
52+ void invoke ( 'get_app_version' )
53+ . then ( ( version ) => {
54+ identifyTelemetry ( `desktop:${ version } ` , { app_version : version } )
55+ } )
56+ . catch ( ( ) => { } )
57+ } , [ telemetryReady ] )
58+
59+ useEffect ( ( ) => {
60+ if ( ! telemetryReady ) return
61+ captureTelemetry ( 'page_view' , {
62+ path : location . pathname ,
63+ search : location . search ,
64+ } )
65+ } , [ location . pathname , location . search , telemetryReady ] )
66+
4067 useEffect ( ( ) => {
4168 const handler = ( event : Event ) => {
4269 const detail = ( event as CustomEvent < { force ?: boolean } > ) . detail
@@ -96,8 +123,12 @@ function AppInner() {
96123 if ( lang && lang !== i18n . language ) {
97124 void i18n . changeLanguage ( lang )
98125 }
126+ setTelemetryEnabled ( settings . analytics_enabled !== false )
127+ setTelemetryReady ( true )
128+ } )
129+ . catch ( ( ) => {
130+ setTelemetryReady ( true )
99131 } )
100- . catch ( ( ) => { } )
101132 } , [ ] ) // eslint-disable-line react-hooks/exhaustive-deps
102133
103134 // Ask for a GitHub star once after meaningful usage cadence.
@@ -161,6 +192,7 @@ function AppInner() {
161192
162193 const handleGithubStarDismiss = ( ) => {
163194 setShowGithubStarPrompt ( false )
195+ captureTelemetry ( 'github_star_prompt_dismissed' )
164196 void invoke ( 'read_settings' )
165197 . then ( ( settings ) => {
166198 const existing = settings . github_star_prompt ?? { }
@@ -182,6 +214,7 @@ function AppInner() {
182214
183215 const handleGithubStarClick = ( ) => {
184216 setShowGithubStarPrompt ( false )
217+ captureTelemetry ( 'github_star_prompt_clicked' )
185218 void invoke ( 'open_external' , { url : GITHUB_REPO_URL } )
186219 void invoke ( 'read_settings' )
187220 . then ( ( settings ) =>
@@ -198,6 +231,12 @@ function AppInner() {
198231 . catch ( ( ) => { } )
199232 }
200233
234+ useEffect ( ( ) => {
235+ if ( showGithubStarPrompt ) {
236+ captureTelemetry ( 'github_star_prompt_shown' )
237+ }
238+ } , [ showGithubStarPrompt ] )
239+
201240 useEffect ( ( ) => {
202241 let cancelled = false
203242 let unlisten : ( ( ) => void ) | undefined
0 commit comments