From 4b9429bb56e345fbe278e32bceabf9fd8f00a332 Mon Sep 17 00:00:00 2001 From: bymyself Date: Tue, 20 Jan 2026 14:36:15 -0800 Subject: [PATCH] feat: integrate nightly survey system into app --- src/components/sidebar/SideToolbar.vue | 2 + .../surveys/NightlySurveyController.vue | 21 +++++++ .../surveys/useSurveyFeatureTracking.test.ts | 61 +++++++++++++++++++ .../surveys/useSurveyFeatureTracking.ts | 30 +++++++++ 4 files changed, 114 insertions(+) create mode 100644 src/platform/surveys/NightlySurveyController.vue create mode 100644 src/platform/surveys/useSurveyFeatureTracking.test.ts create mode 100644 src/platform/surveys/useSurveyFeatureTracking.ts diff --git a/src/components/sidebar/SideToolbar.vue b/src/components/sidebar/SideToolbar.vue index 44dff5fc2..d79de919f 100644 --- a/src/components/sidebar/SideToolbar.vue +++ b/src/components/sidebar/SideToolbar.vue @@ -50,6 +50,7 @@ + @@ -66,6 +67,7 @@ import SidebarSettingsButton from '@/components/sidebar/SidebarSettingsButton.vu import SidebarShortcutsToggleButton from '@/components/sidebar/SidebarShortcutsToggleButton.vue' import { useFeatureFlags } from '@/composables/useFeatureFlags' import { useSettingStore } from '@/platform/settings/settingStore' +import NightlySurveyController from '@/platform/surveys/NightlySurveyController.vue' import { useTelemetry } from '@/platform/telemetry' import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' import { useCommandStore } from '@/stores/commandStore' diff --git a/src/platform/surveys/NightlySurveyController.vue b/src/platform/surveys/NightlySurveyController.vue new file mode 100644 index 000000000..d42ed89f4 --- /dev/null +++ b/src/platform/surveys/NightlySurveyController.vue @@ -0,0 +1,21 @@ + + + diff --git a/src/platform/surveys/useSurveyFeatureTracking.test.ts b/src/platform/surveys/useSurveyFeatureTracking.test.ts new file mode 100644 index 000000000..a0c2c3b81 --- /dev/null +++ b/src/platform/surveys/useSurveyFeatureTracking.test.ts @@ -0,0 +1,61 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' + +const mockSurveyConfigs: Record = {} + +vi.mock('./surveyRegistry', () => ({ + getSurveyConfig: (featureId: string) => mockSurveyConfigs[featureId] +})) + +describe('useSurveyFeatureTracking', () => { + beforeEach(() => { + localStorage.clear() + vi.resetModules() + Object.keys(mockSurveyConfigs).forEach( + (key) => delete mockSurveyConfigs[key] + ) + }) + + afterEach(() => { + localStorage.clear() + }) + + it('tracks usage when config is enabled', async () => { + mockSurveyConfigs['test-feature'] = { enabled: true } + + const { useSurveyFeatureTracking } = + await import('./useSurveyFeatureTracking') + const { trackFeatureUsed, useCount } = + useSurveyFeatureTracking('test-feature') + + expect(useCount.value).toBe(0) + + trackFeatureUsed() + + expect(useCount.value).toBe(1) + }) + + it('does not track when config is disabled', async () => { + mockSurveyConfigs['disabled-feature'] = { enabled: false } + + const { useSurveyFeatureTracking } = + await import('./useSurveyFeatureTracking') + const { trackFeatureUsed, useCount } = + useSurveyFeatureTracking('disabled-feature') + + trackFeatureUsed() + + expect(useCount.value).toBe(0) + }) + + it('does not track when config does not exist', async () => { + const { useSurveyFeatureTracking } = + await import('./useSurveyFeatureTracking') + const { trackFeatureUsed, useCount } = useSurveyFeatureTracking( + 'nonexistent-feature' + ) + + trackFeatureUsed() + + expect(useCount.value).toBe(0) + }) +}) diff --git a/src/platform/surveys/useSurveyFeatureTracking.ts b/src/platform/surveys/useSurveyFeatureTracking.ts new file mode 100644 index 000000000..72ac47edc --- /dev/null +++ b/src/platform/surveys/useSurveyFeatureTracking.ts @@ -0,0 +1,30 @@ +import { getSurveyConfig } from './surveyRegistry' +import { useFeatureUsageTracker } from './useFeatureUsageTracker' + +/** + * Convenience composable for tracking feature usage for surveys. + * Use this at the feature site to track when a feature is used. + * + * @example + * ```typescript + * const { trackFeatureUsed } = useSurveyFeatureTracking('simple-mode') + * + * function onFeatureAction() { + * trackFeatureUsed() + * } + * ``` + */ +export function useSurveyFeatureTracking(featureId: string) { + const config = getSurveyConfig(featureId) + const { trackUsage, useCount } = useFeatureUsageTracker(featureId) + + function trackFeatureUsed() { + if (!config?.enabled) return + trackUsage() + } + + return { + trackFeatureUsed, + useCount + } +}