vibefast-cli 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/2/.claude/agents/architect.md +74 -0
- package/2/.claude/agents/convex-reviewer.md +267 -0
- package/2/.claude/agents/debug-detective.md +62 -0
- package/2/.claude/agents/learner.md +64 -0
- package/2/.claude/agents/perf-optimizer.md +71 -0
- package/2/.claude/agents/security-researcher.md +42 -0
- package/2/.claude/agents/tech-researcher.md +46 -0
- package/2/.claude/agents/ux-designer.md +45 -0
- package/2/.claude/commands/create-app-design.md +279 -0
- package/2/.claude/commands/create-prd-interactive.md +113 -0
- package/2/.claude/commands/create-prd.md +111 -0
- package/2/.claude/commands/create-tech-stack.md +345 -0
- package/2/.claude/commands/update-app-design.md +298 -0
- package/2/.claude/commands/update-project-structure.md +14 -0
- package/2/.claude/commands/update-tech-stack.md +325 -0
- package/2/.claude/docs/CONVEX_FEATURES_PLAN.md +249 -0
- package/2/.claude/docs/app-design-document.md +0 -0
- package/2/.claude/docs/project-status.md +25 -0
- package/2/.claude/docs/project-structure.md +7 -0
- package/2/.claude/docs/tech-stack.md +157 -0
- package/2/.claude/scripts/tree.sh +70 -0
- package/2/.claude/settings.json +30 -0
- package/2/.cursor/commands/code-review-high.md +190 -0
- package/2/.cursorignore +3 -0
- package/2/.github/ISSUE_TEMPLATE.md +13 -0
- package/2/.github/PULL_REQUEST_TEMPLATE.md +23 -0
- package/2/.github/actions/eas-build/action.yml +85 -0
- package/2/.github/actions/setup-jdk-generate-apk/action.yml +48 -0
- package/2/.github/actions/setup-node-pnpm-install/action.yml +29 -0
- package/2/.github/scripts/expo-doctor.sh +26 -0
- package/2/.github/workflows/compress-images.yml +48 -0
- package/2/.github/workflows/e2e-android-eas-build.yml +111 -0
- package/2/.github/workflows/e2e-android-maestro.yml +52 -0
- package/2/.github/workflows/e2e-android.yml +119 -0
- package/2/.github/workflows/eas-build-prod.yml +43 -0
- package/2/.github/workflows/eas-build-qa.yml +47 -0
- package/2/.github/workflows/expo-doctor.yml +61 -0
- package/2/.github/workflows/lint-ts.yml +49 -0
- package/2/.github/workflows/new-app-version.yml +65 -0
- package/2/.github/workflows/new-github-release.yml +34 -0
- package/2/.github/workflows/stale.yml +24 -0
- package/2/.github/workflows/test.yml +50 -0
- package/2/.github/workflows/type-check.yml +54 -0
- package/2/.husky/commit-msg +1 -0
- package/2/.husky/common.sh +8 -0
- package/2/.husky/post-merge +18 -0
- package/2/.husky/pre-commit +24 -0
- package/2/.prettierignore +14 -0
- package/2/.prettierrc.json +10 -0
- package/2/.vibefast/README.md +59 -0
- package/2/.vibefast/config.json +4 -0
- package/2/.vibefast/journal.json +234 -0
- package/2/.vibefast/starter.json +5 -0
- package/2/AGENTS.md +48 -0
- package/2/LICENSE +21 -0
- package/2/README.md +127 -0
- package/2/apps/native/__mocks__/bottom-sheet.js +6 -0
- package/2/apps/native/__mocks__/expo-router.js +16 -0
- package/2/apps/native/__mocks__/react-native-gesture-handler.ts +17 -0
- package/2/apps/native/app-env.d.ts +2 -0
- package/2/apps/native/app.config.ts +167 -0
- package/2/apps/native/assets/adaptive-icon.png +0 -0
- package/2/apps/native/assets/favicon.png +0 -0
- package/2/apps/native/assets/features/image-analyzer/front.jpg +0 -0
- package/2/apps/native/assets/features/image-analyzer/side.jpg +0 -0
- package/2/apps/native/assets/features/image-analyzer/threeQuarter.jpg +0 -0
- package/2/apps/native/assets/fonts/Inter.ttf +0 -0
- package/2/apps/native/assets/fonts/SF-Pro-Display-Bold.otf +0 -0
- package/2/apps/native/assets/fonts/SF-Pro-Display-Medium.otf +0 -0
- package/2/apps/native/assets/fonts/SF-Pro-Display-Regular.otf +0 -0
- package/2/apps/native/assets/fonts/SF-Pro-Display-Semibold.otf +0 -0
- package/2/apps/native/assets/fonts/SpaceMono-Regular.ttf +0 -0
- package/2/apps/native/assets/icon.png +0 -0
- package/2/apps/native/assets/images/cover-image.png +0 -0
- package/2/apps/native/assets/lottie-animations/onboarding-1.json +6504 -0
- package/2/apps/native/assets/lottie-animations/onboarding-2.json +1993 -0
- package/2/apps/native/assets/lottie-animations/onboarding-3.json +50159 -0
- package/2/apps/native/assets/lottie-animations/onboarding-4.json +735 -0
- package/2/apps/native/assets/lottie-animations/onboarding-6.json +2167 -0
- package/2/apps/native/assets/splash-icon.png +0 -0
- package/2/apps/native/babel.config.js +39 -0
- package/2/apps/native/eas.json +75 -0
- package/2/apps/native/env.js +196 -0
- package/2/apps/native/global.css +51 -0
- package/2/apps/native/index.ts +5 -0
- package/2/apps/native/jest-setup.ts +7 -0
- package/2/apps/native/jest.config.js +72 -0
- package/2/apps/native/metro.config.js +85 -0
- package/2/apps/native/nativewind-env.d.ts +1 -0
- package/2/apps/native/package.json +232 -0
- package/2/apps/native/scripts/DRY_RUN_REPORT.md +0 -0
- package/2/apps/native/scripts/QUICK_START.md +76 -0
- package/2/apps/native/scripts/README.md +187 -0
- package/2/apps/native/scripts/convex-setup.js +48 -0
- package/2/apps/native/scripts/download-vosk-model.mjs +121 -0
- package/2/apps/native/scripts/genrate-apk-and-install +39 -0
- package/2/apps/native/scripts/i18next-syntax-validation.js +23 -0
- package/2/apps/native/scripts/starter-setup.mjs +246 -0
- package/2/apps/native/src/api-client/auth.ts +68 -0
- package/2/apps/native/src/api-client/chatbot.ts +83 -0
- package/2/apps/native/src/api-client/client.ts +4 -0
- package/2/apps/native/src/api-client/image-analyzer.ts +62 -0
- package/2/apps/native/src/api-client/image-generator.ts +34 -0
- package/2/apps/native/src/api-client/index.ts +27 -0
- package/2/apps/native/src/api-client/payments.ts +44 -0
- package/2/apps/native/src/api-client/reporting.ts +29 -0
- package/2/apps/native/src/api-client/shared.ts +43 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/_layout.tsx +166 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/index.tsx +174 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/profile.tsx +320 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/settings.tsx +344 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/_layout.tsx +198 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/accordion.tsx +60 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/advanced.tsx +24 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/avatar.tsx +154 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/badge-chips-toggle.tsx +81 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/buttons.tsx +24 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/charts.tsx +3 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/date-picker.tsx +120 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/file-picker.tsx +133 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/gallery-video.tsx +119 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/index.tsx +69 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/inputs-stepper.tsx +78 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/picker-dropdown.tsx +56 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/popover-bottomsheet.tsx +229 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/progress.tsx +38 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/searchbar.tsx +70 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/sliders.tsx +93 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/spinner.tsx +80 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/switch.tsx +47 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/table.tsx +352 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/tabs-timeline.tsx +122 -0
- package/2/apps/native/src/app/(root)/(protected)/_layout.tsx +143 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/_layout.tsx +5 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/analysis-options.tsx +50 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/camera.tsx +2 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/index.tsx +50 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/loading.tsx +50 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/results.tsx +2 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/trait-details.tsx +3 -0
- package/2/apps/native/src/app/(root)/(protected)/audio-recorder/index.tsx +5 -0
- package/2/apps/native/src/app/(root)/(protected)/charts/index.tsx +6 -0
- package/2/apps/native/src/app/(root)/(protected)/chatbot/index.tsx +2 -0
- package/2/apps/native/src/app/(root)/(protected)/image-generator/gallery.tsx +3 -0
- package/2/apps/native/src/app/(root)/(protected)/image-generator/index.tsx +3 -0
- package/2/apps/native/src/app/(root)/(protected)/paywall/index.tsx +74 -0
- package/2/apps/native/src/app/(root)/(protected)/paywall/local.tsx +25 -0
- package/2/apps/native/src/app/(root)/(protected)/paywall/remote.tsx +23 -0
- package/2/apps/native/src/app/(root)/(protected)/quick-actions-demo/index.tsx +32 -0
- package/2/apps/native/src/app/(root)/(protected)/quiz/index.tsx +47 -0
- package/2/apps/native/src/app/(root)/(protected)/test-wake-word.tsx +214 -0
- package/2/apps/native/src/app/(root)/(protected)/tracker-app/index.tsx +1 -0
- package/2/apps/native/src/app/(root)/(protected)/voice-bot/index.tsx +27 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/_layout.tsx +44 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/forgot-password.tsx +185 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/login.tsx +219 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/otp-verification.tsx +369 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/reset-password.tsx +247 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/signup.tsx +207 -0
- package/2/apps/native/src/app/(root)/(public)/_layout.tsx +60 -0
- package/2/apps/native/src/app/(root)/(public)/onboarding/demo-one.tsx +5 -0
- package/2/apps/native/src/app/(root)/(public)/onboarding/demo-two.tsx +52 -0
- package/2/apps/native/src/app/(root)/(public)/onboarding/index.tsx +82 -0
- package/2/apps/native/src/app/(root)/_layout.tsx +30 -0
- package/2/apps/native/src/app/+html.tsx +46 -0
- package/2/apps/native/src/app/[...messing].tsx +24 -0
- package/2/apps/native/src/app/_layout.tsx +56 -0
- package/2/apps/native/src/app/tsconfig.json +3 -0
- package/2/apps/native/src/components/advanced-ui/buttons/demo.tsx +19 -0
- package/2/apps/native/src/components/advanced-ui/buttons/glowing-button.tsx +366 -0
- package/2/apps/native/src/components/advanced-ui/chip/animated-chip.tsx +118 -0
- package/2/apps/native/src/components/advanced-ui/chip/chip.tsx +49 -0
- package/2/apps/native/src/components/advanced-ui/chip/demo.tsx +191 -0
- package/2/apps/native/src/components/advanced-ui/chip/types.ts +21 -0
- package/2/apps/native/src/components/advanced-ui/progress-bars/animated-progress-bar.tsx +182 -0
- package/2/apps/native/src/components/advanced-ui/progress-bars/dropdown-picker-page.tsx +124 -0
- package/2/apps/native/src/components/advanced-ui/progress-bars/progress-circle-page.tsx +111 -0
- package/2/apps/native/src/components/advanced-ui/progress-bars/progress-circle.tsx +223 -0
- package/2/apps/native/src/components/advanced-ui/sliders/swipe-slider-page.tsx +203 -0
- package/2/apps/native/src/components/advanced-ui/sliders/swipe-slider.tsx +266 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/button/stepper-button.tsx +96 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/button/types.ts +16 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/content/stepper-content.tsx +19 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/content/types.ts +6 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/value/stepper-value.tsx +43 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/value/types.ts +25 -0
- package/2/apps/native/src/components/advanced-ui/stepper/context/stepper-context.ts +19 -0
- package/2/apps/native/src/components/advanced-ui/stepper/context/types.ts +9 -0
- package/2/apps/native/src/components/advanced-ui/stepper/demo.tsx +346 -0
- package/2/apps/native/src/components/advanced-ui/stepper/index.ts +4 -0
- package/2/apps/native/src/components/advanced-ui/stepper/stepper.tsx +96 -0
- package/2/apps/native/src/components/advanced-ui/stepper/types.ts +13 -0
- package/2/apps/native/src/components/advanced-ui/switch/animated-switch.tsx +312 -0
- package/2/apps/native/src/components/advanced-ui/switch/demo.tsx +851 -0
- package/2/apps/native/src/components/advanced-ui/switch/types.ts +32 -0
- package/2/apps/native/src/components/advanced-ui/timeline/demo.tsx +444 -0
- package/2/apps/native/src/components/advanced-ui/timeline/timeline-view.tsx +355 -0
- package/2/apps/native/src/components/advanced-ui/timeline/types.ts +31 -0
- package/2/apps/native/src/components/analytics/navigation-tracker.tsx +10 -0
- package/2/apps/native/src/components/demo/advanced-ui-components.tsx +46 -0
- package/2/apps/native/src/components/demo/buttons-demo.tsx +56 -0
- package/2/apps/native/src/components/demo/colors-demo.tsx +52 -0
- package/2/apps/native/src/components/demo/dropdown-picker-demo.tsx +274 -0
- package/2/apps/native/src/components/demo/inputs-demo.tsx +99 -0
- package/2/apps/native/src/components/demo/notification-demo.tsx +434 -0
- package/2/apps/native/src/components/demo/title-demo.tsx +16 -0
- package/2/apps/native/src/components/demo/toast-demo.tsx +81 -0
- package/2/apps/native/src/components/demo/typography-demo.tsx +28 -0
- package/2/apps/native/src/components/performance/render-performance-monitor.tsx +36 -0
- package/2/apps/native/src/components/ui/accordion.tsx +138 -0
- package/2/apps/native/src/components/ui/avatar.tsx +66 -0
- package/2/apps/native/src/components/ui/badge.tsx +68 -0
- package/2/apps/native/src/components/ui/bottom-sheet.tsx +61 -0
- package/2/apps/native/src/components/ui/colors.js +290 -0
- package/2/apps/native/src/components/ui/core/button.tsx +317 -0
- package/2/apps/native/src/components/ui/core/card.tsx +40 -0
- package/2/apps/native/src/components/ui/core/checkbox.tsx +264 -0
- package/2/apps/native/src/components/ui/core/feature-button.tsx +162 -0
- package/2/apps/native/src/components/ui/core/focus-aware-status-bar.tsx +21 -0
- package/2/apps/native/src/components/ui/core/image.tsx +30 -0
- package/2/apps/native/src/components/ui/core/inputs/floating-text-input.tsx +369 -0
- package/2/apps/native/src/components/ui/core/inputs/input-otp.tsx +304 -0
- package/2/apps/native/src/components/ui/core/inputs/input.tsx +373 -0
- package/2/apps/native/src/components/ui/core/list.tsx +60 -0
- package/2/apps/native/src/components/ui/core/navigation/animated-header.tsx +87 -0
- package/2/apps/native/src/components/ui/core/navigation/screen-footer.tsx +67 -0
- package/2/apps/native/src/components/ui/core/overlays/dropdown.tsx +290 -0
- package/2/apps/native/src/components/ui/core/overlays/full-screen-loading.tsx +15 -0
- package/2/apps/native/src/components/ui/core/overlays/modal-keyboard-aware-scroll-view.tsx +46 -0
- package/2/apps/native/src/components/ui/core/overlays/modal.tsx +247 -0
- package/2/apps/native/src/components/ui/core/pagination-dots.tsx +231 -0
- package/2/apps/native/src/components/ui/core/pressable.tsx +48 -0
- package/2/apps/native/src/components/ui/core/progress-bar.tsx +47 -0
- package/2/apps/native/src/components/ui/core/progress.tsx +149 -0
- package/2/apps/native/src/components/ui/core/select.tsx +261 -0
- package/2/apps/native/src/components/ui/core/spinner.tsx +387 -0
- package/2/apps/native/src/components/ui/core/text.tsx +45 -0
- package/2/apps/native/src/components/ui/core/toast.tsx +190 -0
- package/2/apps/native/src/components/ui/custom-switch.tsx +90 -0
- package/2/apps/native/src/components/ui/date-time-picker.tsx +268 -0
- package/2/apps/native/src/components/ui/debug.ts +2 -0
- package/2/apps/native/src/components/ui/extras/debug-credit-tester.tsx +107 -0
- package/2/apps/native/src/components/ui/extras/debug-mmkv-state.tsx +53 -0
- package/2/apps/native/src/components/ui/extras/handle-error.ts +191 -0
- package/2/apps/native/src/components/ui/extras/hello-wave.tsx +70 -0
- package/2/apps/native/src/components/ui/extras/icon.tsx +36 -0
- package/2/apps/native/src/components/ui/extras/network-connectivity-wrapper.tsx +36 -0
- package/2/apps/native/src/components/ui/extras/offline-indicator.tsx +55 -0
- package/2/apps/native/src/components/ui/extras/social-login-buttons.tsx +296 -0
- package/2/apps/native/src/components/ui/file-picker.tsx +177 -0
- package/2/apps/native/src/components/ui/gallery.tsx +79 -0
- package/2/apps/native/src/components/ui/icons/apple.tsx +19 -0
- package/2/apps/native/src/components/ui/icons/arrow-right.tsx +26 -0
- package/2/apps/native/src/components/ui/icons/camera.tsx +26 -0
- package/2/apps/native/src/components/ui/icons/caret-down.tsx +20 -0
- package/2/apps/native/src/components/ui/icons/chevron-up.tsx +21 -0
- package/2/apps/native/src/components/ui/icons/claude.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/copy.tsx +27 -0
- package/2/apps/native/src/components/ui/icons/deepseek.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/download.tsx +32 -0
- package/2/apps/native/src/components/ui/icons/feed.tsx +12 -0
- package/2/apps/native/src/components/ui/icons/gemini.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/github.tsx +30 -0
- package/2/apps/native/src/components/ui/icons/google.tsx +24 -0
- package/2/apps/native/src/components/ui/icons/groq.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/home.tsx +19 -0
- package/2/apps/native/src/components/ui/icons/index.tsx +26 -0
- package/2/apps/native/src/components/ui/icons/language.tsx +33 -0
- package/2/apps/native/src/components/ui/icons/llama.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/microphone.tsx +20 -0
- package/2/apps/native/src/components/ui/icons/mistral.tsx +22 -0
- package/2/apps/native/src/components/ui/icons/nutrition.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/openai.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/perplexity.tsx +22 -0
- package/2/apps/native/src/components/ui/icons/qwen.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/rate.tsx +24 -0
- package/2/apps/native/src/components/ui/icons/report.tsx +20 -0
- package/2/apps/native/src/components/ui/icons/send-horizontal.tsx +26 -0
- package/2/apps/native/src/components/ui/icons/settings.tsx +12 -0
- package/2/apps/native/src/components/ui/icons/share.tsx +16 -0
- package/2/apps/native/src/components/ui/icons/square.tsx +9 -0
- package/2/apps/native/src/components/ui/icons/style.tsx +22 -0
- package/2/apps/native/src/components/ui/icons/support.tsx +27 -0
- package/2/apps/native/src/components/ui/icons/trash2.tsx +42 -0
- package/2/apps/native/src/components/ui/icons/user.tsx +12 -0
- package/2/apps/native/src/components/ui/icons/website.tsx +28 -0
- package/2/apps/native/src/components/ui/icons/wifi-off.tsx +17 -0
- package/2/apps/native/src/components/ui/index.tsx +14 -0
- package/2/apps/native/src/components/ui/nav-item.tsx +42 -0
- package/2/apps/native/src/components/ui/patterns/index.ts +16 -0
- package/2/apps/native/src/components/ui/picker.tsx +244 -0
- package/2/apps/native/src/components/ui/popover.tsx +313 -0
- package/2/apps/native/src/components/ui/primitives/index.ts +38 -0
- package/2/apps/native/src/components/ui/radio-group.tsx +47 -0
- package/2/apps/native/src/components/ui/searchbar.tsx +118 -0
- package/2/apps/native/src/components/ui/sheet.tsx +93 -0
- package/2/apps/native/src/components/ui/switch.tsx +37 -0
- package/2/apps/native/src/components/ui/table.tsx +296 -0
- package/2/apps/native/src/components/ui/tabs.tsx +115 -0
- package/2/apps/native/src/components/ui/toggle.tsx +50 -0
- package/2/apps/native/src/components/ui/utils.tsx +34 -0
- package/2/apps/native/src/components/ui/video.tsx +39 -0
- package/2/apps/native/src/core/analytics/analytics-service.ts +94 -0
- package/2/apps/native/src/core/analytics/index.ts +2 -0
- package/2/apps/native/src/core/analytics/posthog-analytics-adapter.ts +192 -0
- package/2/apps/native/src/core/auth/auth-service.ts +33 -0
- package/2/apps/native/src/core/auth/index.ts +1 -0
- package/2/apps/native/src/core/cache/__tests__/cache-service.test.ts +599 -0
- package/2/apps/native/src/core/cache/cache-service.ts +89 -0
- package/2/apps/native/src/core/cache/index.ts +45 -0
- package/2/apps/native/src/core/config/config.service.ts +153 -0
- package/2/apps/native/src/core/config/index.ts +2 -0
- package/2/apps/native/src/core/config/telemetry.ts +38 -0
- package/2/apps/native/src/core/local-notifications/local-notification-manager.ts +409 -0
- package/2/apps/native/src/core/logging/custom-transports.ts +126 -0
- package/2/apps/native/src/core/logging/index.ts +1 -0
- package/2/apps/native/src/core/logging/logger.ts +182 -0
- package/2/apps/native/src/core/navigation/deep-link-handler.ts +295 -0
- package/2/apps/native/src/core/navigation/navigation-types.ts +53 -0
- package/2/apps/native/src/core/payments/index.ts +1 -0
- package/2/apps/native/src/core/payments/payment-service.ts +32 -0
- package/2/apps/native/src/core/quick-actions/index.ts +2 -0
- package/2/apps/native/src/core/quick-actions/quick-actions-adapter.ts +54 -0
- package/2/apps/native/src/core/quick-actions/types.ts +29 -0
- package/2/apps/native/src/core/storage/index.ts +1 -0
- package/2/apps/native/src/core/storage/mmkv.ts +62 -0
- package/2/apps/native/src/core/storage/notification-storage.ts +312 -0
- package/2/apps/native/src/core/types/common.ts +0 -0
- package/2/apps/native/src/core/utils/convex-http-api.ts +30 -0
- package/2/apps/native/src/features/audio-recorder/components/audio-player.tsx +301 -0
- package/2/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +373 -0
- package/2/apps/native/src/features/audio-recorder/components/audio-waveform.tsx +270 -0
- package/2/apps/native/src/features/audio-recorder/components/index.ts +4 -0
- package/2/apps/native/src/features/audio-recorder/components/recording-list.tsx +89 -0
- package/2/apps/native/src/features/audio-recorder/demo/audio-player-demo.tsx +66 -0
- package/2/apps/native/src/features/audio-recorder/demo/audio-recorder-cloud.tsx +68 -0
- package/2/apps/native/src/features/audio-recorder/demo/audio-recorder-interview.tsx +102 -0
- package/2/apps/native/src/features/audio-recorder/demo/basic.tsx +27 -0
- package/2/apps/native/src/features/audio-recorder/demo/index.ts +5 -0
- package/2/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +82 -0
- package/2/apps/native/src/features/authentication/components/auth-watcher.tsx +115 -0
- package/2/apps/native/src/features/authentication/components/login-form.tsx +85 -0
- package/2/apps/native/src/features/authentication/services/__tests__/convex-auth.adapter.test.ts +399 -0
- package/2/apps/native/src/features/authentication/services/convex-auth.adapter.ts +497 -0
- package/2/apps/native/src/features/authentication/services/index.ts +2 -0
- package/2/apps/native/src/features/charts/README.md +185 -0
- package/2/apps/native/src/features/charts/app/preview.tsx +226 -0
- package/2/apps/native/src/features/charts/components/area-chart.tsx +43 -0
- package/2/apps/native/src/features/charts/components/bar-chart.tsx +146 -0
- package/2/apps/native/src/features/charts/components/candlestick-chart.tsx +199 -0
- package/2/apps/native/src/features/charts/components/chart-card.tsx +68 -0
- package/2/apps/native/src/features/charts/components/column-chart.tsx +146 -0
- package/2/apps/native/src/features/charts/components/doughnut-chart.tsx +260 -0
- package/2/apps/native/src/features/charts/components/index.ts +13 -0
- package/2/apps/native/src/features/charts/components/line-chart.tsx +311 -0
- package/2/apps/native/src/features/charts/components/radar-chart.tsx +183 -0
- package/2/apps/native/src/features/charts/components/radial-bar-chart.tsx +191 -0
- package/2/apps/native/src/features/charts/components/stacked-area-chart.tsx +268 -0
- package/2/apps/native/src/features/charts/components/stacked-bar-chart.tsx +325 -0
- package/2/apps/native/src/features/charts/data/mock-data.ts +186 -0
- package/2/apps/native/src/features/charts/types/index.ts +69 -0
- package/2/apps/native/src/features/chatbot/app/index.tsx +303 -0
- package/2/apps/native/src/features/chatbot/components/chat-header-buttons.tsx +60 -0
- package/2/apps/native/src/features/chatbot/components/chat-input-bar.tsx +470 -0
- package/2/apps/native/src/features/chatbot/components/chat-markdown.tsx +576 -0
- package/2/apps/native/src/features/chatbot/components/chat-message-bubble.tsx +247 -0
- package/2/apps/native/src/features/chatbot/components/chat-settings-modal.tsx +162 -0
- package/2/apps/native/src/features/chatbot/components/image-preview-list.tsx +116 -0
- package/2/apps/native/src/features/chatbot/components/markdown/code-block.tsx +166 -0
- package/2/apps/native/src/features/chatbot/components/markdown/index.ts +11 -0
- package/2/apps/native/src/features/chatbot/components/markdown/table-renderer.tsx +130 -0
- package/2/apps/native/src/features/chatbot/components/message-error-boundary.tsx +79 -0
- package/2/apps/native/src/features/chatbot/components/message-list.tsx +174 -0
- package/2/apps/native/src/features/chatbot/components/model-selector.tsx +284 -0
- package/2/apps/native/src/features/chatbot/components/report-content-modal.tsx +189 -0
- package/2/apps/native/src/features/chatbot/components/suggested-messages.tsx +68 -0
- package/2/apps/native/src/features/chatbot/constants/models.ts +21 -0
- package/2/apps/native/src/features/chatbot/constants/report-reasons.ts +10 -0
- package/2/apps/native/src/features/chatbot/hooks/use-attachment-cache.ts +144 -0
- package/2/apps/native/src/features/chatbot/hooks/use-chat-config.ts +665 -0
- package/2/apps/native/src/features/chatbot/hooks/use-chat-handlers.ts +360 -0
- package/2/apps/native/src/features/chatbot/hooks/use-chatbot-settings.ts +90 -0
- package/2/apps/native/src/features/chatbot/hooks/use-conversation.ts +80 -0
- package/2/apps/native/src/features/chatbot/hooks/use-image-picker.ts +123 -0
- package/2/apps/native/src/features/chatbot/hooks/use-keyboard-coordinator.ts +162 -0
- package/2/apps/native/src/features/chatbot/hooks/use-smart-scroll-manager.ts +214 -0
- package/2/apps/native/src/features/chatbot/models/index.ts +87 -0
- package/2/apps/native/src/features/chatbot/models/models.ts +163 -0
- package/2/apps/native/src/features/chatbot/models/providers.ts +63 -0
- package/2/apps/native/src/features/chatbot/models/types.ts +41 -0
- package/2/apps/native/src/features/chatbot/services/file-uploader.ts +239 -0
- package/2/apps/native/src/features/chatbot/services/message-handler-service.ts +181 -0
- package/2/apps/native/src/features/chatbot/types/index.ts +61 -0
- package/2/apps/native/src/features/chatbot/utils/chat-telemetry.ts +92 -0
- package/2/apps/native/src/features/image-analyzer/app/analysis-options-screen.tsx +304 -0
- package/2/apps/native/src/features/image-analyzer/app/camera.tsx +221 -0
- package/2/apps/native/src/features/image-analyzer/app/image-capture-screen.tsx +333 -0
- package/2/apps/native/src/features/image-analyzer/app/loading-screen.tsx +217 -0
- package/2/apps/native/src/features/image-analyzer/app/loading.tsx +194 -0
- package/2/apps/native/src/features/image-analyzer/app/results.tsx +137 -0
- package/2/apps/native/src/features/image-analyzer/app/trait-details.tsx +172 -0
- package/2/apps/native/src/features/image-analyzer/app/use-analysis-data.ts +143 -0
- package/2/apps/native/src/features/image-analyzer/app/use-results-screen.ts +151 -0
- package/2/apps/native/src/features/image-analyzer/components/results/achievement-badge.tsx +77 -0
- package/2/apps/native/src/features/image-analyzer/components/results/achievement-card.tsx +75 -0
- package/2/apps/native/src/features/image-analyzer/components/results/achievement-unlocked-modal.tsx +162 -0
- package/2/apps/native/src/features/image-analyzer/components/results/achievements-section.tsx +44 -0
- package/2/apps/native/src/features/image-analyzer/components/results/advice-list.tsx +42 -0
- package/2/apps/native/src/features/image-analyzer/components/results/circular-progress.tsx +233 -0
- package/2/apps/native/src/features/image-analyzer/components/results/content-card.tsx +38 -0
- package/2/apps/native/src/features/image-analyzer/components/results/error-state.tsx +42 -0
- package/2/apps/native/src/features/image-analyzer/components/results/index.ts +9 -0
- package/2/apps/native/src/features/image-analyzer/components/results/loading-state.tsx +26 -0
- package/2/apps/native/src/features/image-analyzer/components/results/profile-image.tsx +60 -0
- package/2/apps/native/src/features/image-analyzer/components/results/results-header.tsx +62 -0
- package/2/apps/native/src/features/image-analyzer/components/results/score-display.tsx +54 -0
- package/2/apps/native/src/features/image-analyzer/components/results/share-options-modal.tsx +110 -0
- package/2/apps/native/src/features/image-analyzer/components/results/traits-grid.tsx +74 -0
- package/2/apps/native/src/features/image-analyzer/config/analysis-config.ts +80 -0
- package/2/apps/native/src/features/image-analyzer/config/master-analysis-config.ts +157 -0
- package/2/apps/native/src/features/image-analyzer/hooks/index.ts +1 -0
- package/2/apps/native/src/features/image-analyzer/hooks/use-analysis.ts +37 -0
- package/2/apps/native/src/features/image-analyzer/hooks/use-image-analysis.ts +202 -0
- package/2/apps/native/src/features/image-analyzer/services/analysis-service.ts +262 -0
- package/2/apps/native/src/features/image-analyzer/services/share-service.ts +176 -0
- package/2/apps/native/src/features/image-analyzer/services/trait-details-service.ts +289 -0
- package/2/apps/native/src/features/image-generator/app/_layout.tsx +26 -0
- package/2/apps/native/src/features/image-generator/app/gallery.tsx +217 -0
- package/2/apps/native/src/features/image-generator/app/index.tsx +237 -0
- package/2/apps/native/src/features/image-generator/components/gallery-image.tsx +25 -0
- package/2/apps/native/src/features/image-generator/components/image-detail-modal.tsx +215 -0
- package/2/apps/native/src/features/image-generator/components/image-model-selector.tsx +210 -0
- package/2/apps/native/src/features/image-generator/components/image-placeholder.tsx +26 -0
- package/2/apps/native/src/features/image-generator/hooks/use-image-gallery.ts +71 -0
- package/2/apps/native/src/features/image-generator/hooks/use-image-generator-settings.ts +152 -0
- package/2/apps/native/src/features/image-generator/hooks/use-image-generator.ts +93 -0
- package/2/apps/native/src/features/image-generator/models/models.ts +66 -0
- package/2/apps/native/src/features/image-generator/services/image-gallery-service.ts +98 -0
- package/2/apps/native/src/features/image-generator/services/image-save-service.ts +121 -0
- package/2/apps/native/src/features/onboarding/analytics/index.ts +9 -0
- package/2/apps/native/src/features/onboarding/components/onboarding-with-analytics.tsx +141 -0
- package/2/apps/native/src/features/onboarding/components/onboarding.tsx +173 -0
- package/2/apps/native/src/features/onboarding/config/onboarding-flow-config.ts +189 -0
- package/2/apps/native/src/features/onboarding/demo-one/app/index.tsx +43 -0
- package/2/apps/native/src/features/onboarding/demo-one/data.ts +32 -0
- package/2/apps/native/src/features/onboarding/hooks/use-onboarding-analytics.ts +323 -0
- package/2/apps/native/src/features/onboarding/services/onboarding-analytics.ts +432 -0
- package/2/apps/native/src/features/payments/README.md +200 -0
- package/2/apps/native/src/features/payments/app/local-paywall.tsx +194 -0
- package/2/apps/native/src/features/payments/app/remote-paywall.tsx +79 -0
- package/2/apps/native/src/features/payments/components/payment-initializer.tsx +95 -0
- package/2/apps/native/src/features/payments/components/paywall-error-state.tsx +60 -0
- package/2/apps/native/src/features/payments/components/paywall-local-mode.tsx +116 -0
- package/2/apps/native/src/features/payments/components/paywall-product-card.tsx +133 -0
- package/2/apps/native/src/features/payments/components/paywall-remote-mode.tsx +146 -0
- package/2/apps/native/src/features/payments/hooks/use-entitlement.ts +63 -0
- package/2/apps/native/src/features/payments/index.ts +8 -0
- package/2/apps/native/src/features/payments/services/revenuecat-adapter.ts +407 -0
- package/2/apps/native/src/features/quick-actions/components/quick-actions-demo.tsx +139 -0
- package/2/apps/native/src/features/quick-actions/config/default-actions.ts +83 -0
- package/2/apps/native/src/features/quick-actions/hooks/use-quick-actions.ts +45 -0
- package/2/apps/native/src/features/quick-actions/index.ts +4 -0
- package/2/apps/native/src/features/quick-actions/utils/quick-actions-manager.ts +105 -0
- package/2/apps/native/src/features/quiz/components/question.tsx +67 -0
- package/2/apps/native/src/features/quiz/config.ts +11 -0
- package/2/apps/native/src/features/quiz/index.tsx +133 -0
- package/2/apps/native/src/features/settings/ui/debug-info.tsx +75 -0
- package/2/apps/native/src/features/settings/ui/dev-tools.tsx +1 -0
- package/2/apps/native/src/features/settings/ui/item.tsx +45 -0
- package/2/apps/native/src/features/settings/ui/items-container.tsx +23 -0
- package/2/apps/native/src/features/settings/ui/language-item.tsx +52 -0
- package/2/apps/native/src/features/settings/ui/notification-item.tsx +59 -0
- package/2/apps/native/src/features/settings/ui/theme-item.tsx +45 -0
- package/2/apps/native/src/features/tracker-app/app/index.tsx +108 -0
- package/2/apps/native/src/features/tracker-app/components/animated-number.tsx +102 -0
- package/2/apps/native/src/features/tracker-app/components/calorie-card.tsx +66 -0
- package/2/apps/native/src/features/tracker-app/components/circular-progress.tsx +97 -0
- package/2/apps/native/src/features/tracker-app/components/floating-add-button.tsx +27 -0
- package/2/apps/native/src/features/tracker-app/components/macro-card.tsx +80 -0
- package/2/apps/native/src/features/tracker-app/components/promo-banner.tsx +98 -0
- package/2/apps/native/src/features/tracker-app/components/recently-logged.tsx +64 -0
- package/2/apps/native/src/features/tracker-app/components/week-calendar.tsx +68 -0
- package/2/apps/native/src/features/vibefast-features.ts +42 -0
- package/2/apps/native/src/features/voice-bot/README.md +185 -0
- package/2/apps/native/src/features/voice-bot/components/conversation-status.tsx +76 -0
- package/2/apps/native/src/features/voice-bot/components/index.ts +4 -0
- package/2/apps/native/src/features/voice-bot/components/message-input.tsx +98 -0
- package/2/apps/native/src/features/voice-bot/components/voice-bot-screen.tsx +173 -0
- package/2/apps/native/src/features/voice-bot/components/voice-controls.tsx +73 -0
- package/2/apps/native/src/features/voice-bot/index.ts +3 -0
- package/2/apps/native/src/features/voice-bot/services/index.ts +1 -0
- package/2/apps/native/src/features/voice-bot/services/use-voice-bot.ts +161 -0
- package/2/apps/native/src/features/voice-bot/types.ts +29 -0
- package/2/apps/native/src/features/wake-word/components/index.ts +1 -0
- package/2/apps/native/src/features/wake-word/components/wake-word-indicator.tsx +61 -0
- package/2/apps/native/src/features/wake-word/constants.ts +10 -0
- package/2/apps/native/src/features/wake-word/hooks/use-wake-word.ts +181 -0
- package/2/apps/native/src/features/wake-word/index.ts +22 -0
- package/2/apps/native/src/features/wake-word/services/audio-session.ts +40 -0
- package/2/apps/native/src/features/wake-word/services/event-bus.ts +31 -0
- package/2/apps/native/src/features/wake-word/services/keywords.ts +88 -0
- package/2/apps/native/src/features/wake-word/services/wake-word-manager.ts +249 -0
- package/2/apps/native/src/features/wake-word/types.ts +22 -0
- package/2/apps/native/src/lib/env.js +13 -0
- package/2/apps/native/src/lib/hooks/index.tsx +6 -0
- package/2/apps/native/src/lib/hooks/use-device-identifier.tsx +80 -0
- package/2/apps/native/src/lib/hooks/use-gradual-animation.ts +28 -0
- package/2/apps/native/src/lib/hooks/use-is-first-time.tsx +25 -0
- package/2/apps/native/src/lib/hooks/use-navigation-analytics.ts +44 -0
- package/2/apps/native/src/lib/hooks/use-navigation-options.tsx +87 -0
- package/2/apps/native/src/lib/hooks/use-push-notifications.ts +250 -0
- package/2/apps/native/src/lib/hooks/use-responsive-size.tsx +37 -0
- package/2/apps/native/src/lib/hooks/use-selected-theme.tsx +38 -0
- package/2/apps/native/src/lib/hooks/use-viewport-lazy-loading.tsx +124 -0
- package/2/apps/native/src/lib/i18n/index.tsx +30 -0
- package/2/apps/native/src/lib/i18n/react-i18next.d.ts +9 -0
- package/2/apps/native/src/lib/i18n/resources.ts +25 -0
- package/2/apps/native/src/lib/i18n/types.ts +23 -0
- package/2/apps/native/src/lib/i18n/utils.tsx +112 -0
- package/2/apps/native/src/lib/index.tsx +3 -0
- package/2/apps/native/src/lib/state/auth-client-slice.ts +34 -0
- package/2/apps/native/src/lib/state/index.ts +1 -0
- package/2/apps/native/src/lib/storage.tsx +7 -0
- package/2/apps/native/src/lib/test-utils.tsx +43 -0
- package/2/apps/native/src/lib/use-theme-config.tsx +108 -0
- package/2/apps/native/src/lib/utils.ts +29 -0
- package/2/apps/native/src/polyfills.ts +61 -0
- package/2/apps/native/src/providers/convex-provider.tsx +31 -0
- package/2/apps/native/src/providers/index.tsx +6 -0
- package/2/apps/native/src/providers/notification-provider.tsx +168 -0
- package/2/apps/native/src/providers/posthog-provider.tsx +47 -0
- package/2/apps/native/src/providers/root-providers.tsx +46 -0
- package/2/apps/native/src/providers/sentry-provider.tsx +62 -0
- package/2/apps/native/src/providers/splash-screen-provider.tsx +122 -0
- package/2/apps/native/src/providers/theme-provider.tsx +67 -0
- package/2/apps/native/src/translations/ar.json +394 -0
- package/2/apps/native/src/translations/de.json +394 -0
- package/2/apps/native/src/translations/en.json +394 -0
- package/2/apps/native/src/translations/es.json +394 -0
- package/2/apps/native/src/translations/fr.json +394 -0
- package/2/apps/native/src/types/flash-list.d.ts +3 -0
- package/2/apps/native/src/types/index.ts +3 -0
- package/2/apps/native/src/types/react-native-reanimated.d.ts +5 -0
- package/2/apps/native/tailwind.config.js +57 -0
- package/2/apps/native/targets/widget/AppIntent.swift +46 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/Contents.json +122 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png +0 -0
- package/2/apps/native/targets/widget/CalorieTrackerWidget.swift +424 -0
- package/2/apps/native/targets/widget/HabitTrackerWidget.swift +305 -0
- package/2/apps/native/targets/widget/Info.plist +11 -0
- package/2/apps/native/targets/widget/WidgetLiveActivity.swift +75 -0
- package/2/apps/native/targets/widget/expo-target.config.js +10 -0
- package/2/apps/native/targets/widget/generated.entitlements +5 -0
- package/2/apps/native/targets/widget/index.swift +18 -0
- package/2/apps/native/targets/widget/widgets.swift +96 -0
- package/2/apps/native/tsconfig.json +88 -0
- package/2/apps/native/vitest.config.mts +14 -0
- package/2/apps/web/README.md +36 -0
- package/2/apps/web/app/favicon.ico +0 -0
- package/2/apps/web/app/globals.css +122 -0
- package/2/apps/web/app/layout.tsx +38 -0
- package/2/apps/web/app/page.tsx +35 -0
- package/2/apps/web/app/users/page.tsx +301 -0
- package/2/apps/web/components/AdminDashboard.tsx +336 -0
- package/2/apps/web/components/AppleLogo.tsx +15 -0
- package/2/apps/web/components/GitHubLogo.tsx +11 -0
- package/2/apps/web/components/GoogleLogo.tsx +23 -0
- package/2/apps/web/components/Layout.tsx +77 -0
- package/2/apps/web/components/ThemeToggle.tsx +23 -0
- package/2/apps/web/components/UserMenu.tsx +66 -0
- package/2/apps/web/components/auth/CodeInput.tsx +24 -0
- package/2/apps/web/components/auth/ResetPasswordWithEmailCode.tsx +85 -0
- package/2/apps/web/components/auth/SignInFormEmailCode.tsx +72 -0
- package/2/apps/web/components/auth/SignInFormEmailLink.tsx +81 -0
- package/2/apps/web/components/auth/SignInFormPassword.tsx +17 -0
- package/2/apps/web/components/auth/SignInFormPasswordAndCustomField.tsx +42 -0
- package/2/apps/web/components/auth/SignInFormPasswordAndResetViaCode.tsx +32 -0
- package/2/apps/web/components/auth/SignInFormPasswordAndVerifyViaCode.tsx +86 -0
- package/2/apps/web/components/auth/SignInFormPhoneCode.tsx +89 -0
- package/2/apps/web/components/auth/SignInFormsShowcase.tsx +64 -0
- package/2/apps/web/components/auth/SignInMethodDivider.tsx +17 -0
- package/2/apps/web/components/auth/SignInWithEmailCode.tsx +49 -0
- package/2/apps/web/components/auth/SignInWithOAuth.tsx +16 -0
- package/2/apps/web/components/auth/SignInWithPassword.tsx +100 -0
- package/2/apps/web/components/auth/oauth/SignInWithApple.tsx +27 -0
- package/2/apps/web/components/auth/oauth/SignInWithGitHub.tsx +27 -0
- package/2/apps/web/components/auth/oauth/SignInWithGoogle.tsx +27 -0
- package/2/apps/web/components/ui/button.tsx +60 -0
- package/2/apps/web/components/ui/card.tsx +92 -0
- package/2/apps/web/components/ui/dialog.tsx +143 -0
- package/2/apps/web/components/ui/dropdown-menu.tsx +257 -0
- package/2/apps/web/components/ui/input-otp.tsx +77 -0
- package/2/apps/web/components/ui/input.tsx +21 -0
- package/2/apps/web/components/ui/skeleton.tsx +13 -0
- package/2/apps/web/components/ui/tabs.tsx +66 -0
- package/2/apps/web/components/ui/toast.tsx +130 -0
- package/2/apps/web/components/ui/toaster.tsx +36 -0
- package/2/apps/web/components/ui/toggle-group.tsx +83 -0
- package/2/apps/web/components/ui/toggle.tsx +47 -0
- package/2/apps/web/components/ui/use-toast.ts +192 -0
- package/2/apps/web/components.json +22 -0
- package/2/apps/web/eslint.config.mjs +18 -0
- package/2/apps/web/lib/convex-provider.tsx +18 -0
- package/2/apps/web/lib/utils.ts +6 -0
- package/2/apps/web/next.config.ts +7 -0
- package/2/apps/web/package.json +46 -0
- package/2/apps/web/postcss.config.mjs +7 -0
- package/2/apps/web/public/file.svg +1 -0
- package/2/apps/web/public/globe.svg +1 -0
- package/2/apps/web/public/next.svg +1 -0
- package/2/apps/web/public/vercel.svg +1 -0
- package/2/apps/web/public/window.svg +1 -0
- package/2/apps/web/tsconfig.json +34 -0
- package/2/bts.jsonc +21 -0
- package/2/commitlint.config.js +1 -0
- package/2/eslint.config.mjs +182 -0
- package/2/lint-staged.config.js +16 -0
- package/2/package.json +64 -0
- package/2/packages/backend/.env.example +20 -0
- package/2/packages/backend/convex/README.md +90 -0
- package/2/packages/backend/convex/_generated/api.d.ts +2599 -0
- package/2/packages/backend/convex/_generated/api.js +23 -0
- package/2/packages/backend/convex/_generated/dataModel.d.ts +60 -0
- package/2/packages/backend/convex/_generated/server.d.ts +149 -0
- package/2/packages/backend/convex/_generated/server.js +90 -0
- package/2/packages/backend/convex/agents.ts +116 -0
- package/2/packages/backend/convex/auth.config.ts +8 -0
- package/2/packages/backend/convex/auth.ts +103 -0
- package/2/packages/backend/convex/authCustomEmailOtpProvider.ts +175 -0
- package/2/packages/backend/convex/authOtp.ts +144 -0
- package/2/packages/backend/convex/authPasswordReset.ts +367 -0
- package/2/packages/backend/convex/authPasswordResetActions.ts +150 -0
- package/2/packages/backend/convex/chatbot/index.ts +30 -0
- package/2/packages/backend/convex/chatbotAgent.ts +1085 -0
- package/2/packages/backend/convex/chatbotHistory.ts +307 -0
- package/2/packages/backend/convex/convex.config.ts +13 -0
- package/2/packages/backend/convex/deviceGrants.ts +58 -0
- package/2/packages/backend/convex/grantFunctions.ts +444 -0
- package/2/packages/backend/convex/http.ts +8 -0
- package/2/packages/backend/convex/imageAnalysis/index.ts +18 -0
- package/2/packages/backend/convex/imageAnalysisFunctions.ts +325 -0
- package/2/packages/backend/convex/imageGeneration/index.ts +12 -0
- package/2/packages/backend/convex/imageGeneratorFunctions.ts +290 -0
- package/2/packages/backend/convex/lib/ai/analysisConfigs.ts +257 -0
- package/2/packages/backend/convex/lib/ai/config.ts +71 -0
- package/2/packages/backend/convex/lib/ai/geminiAdapter.ts +43 -0
- package/2/packages/backend/convex/lib/ai/imageAnalysisAdapter.ts +200 -0
- package/2/packages/backend/convex/lib/ai/openaiAdapter.ts +43 -0
- package/2/packages/backend/convex/lib/ai/schemas.ts +79 -0
- package/2/packages/backend/convex/lib/config.ts +111 -0
- package/2/packages/backend/convex/lib/rateLimit.ts +100 -0
- package/2/packages/backend/convex/lib/telemetry.ts +29 -0
- package/2/packages/backend/convex/paymentFunctions.ts +119 -0
- package/2/packages/backend/convex/payments/index.ts +13 -0
- package/2/packages/backend/convex/pushNotificationFunctions.ts +342 -0
- package/2/packages/backend/convex/ragKnowledge.ts +714 -0
- package/2/packages/backend/convex/rateLimit.ts +13 -0
- package/2/packages/backend/convex/recordingFunctions.ts +98 -0
- package/2/packages/backend/convex/reportFunctions.ts +344 -0
- package/2/packages/backend/convex/reporting/index.ts +9 -0
- package/2/packages/backend/convex/router.ts +81 -0
- package/2/packages/backend/convex/schema.ts +237 -0
- package/2/packages/backend/convex/shared/email.ts +172 -0
- package/2/packages/backend/convex/shared/files.ts +96 -0
- package/2/packages/backend/convex/shared/index.ts +17 -0
- package/2/packages/backend/convex/shared/templates/PasswordResetEmail.tsx +72 -0
- package/2/packages/backend/convex/shared/templates/VerificationCodeEmail.tsx +65 -0
- package/2/packages/backend/convex/sharedUsers.ts +48 -0
- package/2/packages/backend/convex/tools/index.ts +18 -0
- package/2/packages/backend/convex/tools/knowledgeRetrieval.ts +92 -0
- package/2/packages/backend/convex/tools/tavilySearch.ts +83 -0
- package/2/packages/backend/convex/tools/userProfile.ts +72 -0
- package/2/packages/backend/convex/tsconfig.json +25 -0
- package/2/packages/backend/convex/users.ts +54 -0
- package/2/packages/backend/index.ts +20 -0
- package/2/packages/backend/package.json +32 -0
- package/2/packages/ui/README.md +63 -0
- package/2/packages/ui/index.ts +1 -0
- package/2/packages/ui/package.json +21 -0
- package/2/packages/ui/src/components/SharedButton.tsx +31 -0
- package/2/packages/ui/src/components/SharedCard.tsx +48 -0
- package/2/packages/ui/src/components/index.ts +2 -0
- package/2/packages/ui/tsconfig.json +10 -0
- package/2/pnpm-lock.yaml +23292 -0
- package/2/pnpm-workspace.yaml +3 -0
- package/2/scripts/i18next-syntax-validation.js +1 -0
- package/2/tsconfig.json +43 -0
- package/2/turbo.json +33 -0
- package/2/vercel.json +6 -0
- package/2/vf-agent/agent-teams/team-vibefast.yaml +14 -0
- package/2/vf-agent/agents/analyst.md +53 -0
- package/2/vf-agent/agents/architect.md +105 -0
- package/2/vf-agent/agents/dev.md +40 -0
- package/2/vf-agent/agents/orchestrator.md +181 -0
- package/2/vf-agent/agents/pm.md +48 -0
- package/2/vf-agent/agents/po.md +38 -0
- package/2/vf-agent/agents/qa.md +30 -0
- package/2/vf-agent/agents/sm.md +38 -0
- package/2/vf-agent/agents/ux-expert.md +33 -0
- package/2/vf-agent/checklists/po-master-checklist.md +73 -0
- package/2/vf-agent/checklists/story-dod-checklist.md +37 -0
- package/2/vf-agent/core-config.yaml +43 -0
- package/2/vf-agent/data/knowledge_base/backend/convex-advanced.md +43 -0
- package/2/vf-agent/data/knowledge_base/backend/convex-database.md +53 -0
- package/2/vf-agent/data/knowledge_base/backend/convex-main.md +65 -0
- package/2/vf-agent/data/knowledge_base/backend/full-guidelines.md +795 -0
- package/2/vf-agent/data/knowledge_base/coding-standards.md +253 -0
- package/2/vf-agent/data/knowledge_base/frontend/full-guidelines.md +254 -0
- package/2/vf-agent/data/knowledge_base/frontend/image-handling.md +48 -0
- package/2/vf-agent/data/knowledge_base/frontend/react-native-main.md +24 -0
- package/2/vf-agent/data/knowledge_base/frontend/ui-and-styling.md +169 -0
- package/2/vf-agent/data/knowledge_base/general-principles.md +26 -0
- package/2/vf-agent/data/knowledge_base/master-rulebook.md +42 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/audio-recorder-reference.md +98 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/authentication-reference.md +155 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/charts-reference.md +149 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/chatbot-reference.md +123 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/feature-reference-index.md +211 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/features-overview.md +221 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/image-analyzer-reference.md +118 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/image-generator-reference.md +110 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/index.md +28 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/onboarding-reference.md +96 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/payments-reference.md +148 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/prd.md +82 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/push-notifications-reference.md +453 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/quick-actions-reference.md +253 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/quiz-reference.md +169 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/settings-reference.md +146 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/tech-stack.md +159 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/tracker-app-reference.md +150 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/unified-project-structure.md +98 -0
- package/2/vf-agent/data/knowledge_base/testing/backend-testing.md +54 -0
- package/2/vf-agent/data/knowledge_base/testing/frontend-testing.md +71 -0
- package/2/vf-agent/data/knowledge_base/testing/testing-strategy.md +31 -0
- package/2/vf-agent/tasks/advanced-elicitation.md +117 -0
- package/2/vf-agent/tasks/brownfield-create-epic.md +160 -0
- package/2/vf-agent/tasks/create-deep-research-prompt.md +278 -0
- package/2/vf-agent/tasks/create-doc.md +42 -0
- package/2/vf-agent/tasks/create-story.md +43 -0
- package/2/vf-agent/tasks/document-project.md +343 -0
- package/2/vf-agent/tasks/facilitate-brainstorming-session.md +136 -0
- package/2/vf-agent/tasks/index-docs.md +173 -0
- package/2/vf-agent/tasks/kb-mode-interaction.md +75 -0
- package/2/vf-agent/tasks/review-story.md +154 -0
- package/2/vf-agent/tasks/shard-doc.md +185 -0
- package/2/vf-agent/tasks/troubleshoot-issue.md +65 -0
- package/2/vf-agent/tasks/validate-next-story.md +47 -0
- package/2/vf-agent/templates/brainstorming-output-tmpl.yaml +156 -0
- package/2/vf-agent/templates/brownfield-architecture-tmpl.yaml +111 -0
- package/2/vf-agent/templates/brownfield-prd-tmpl.yaml +247 -0
- package/2/vf-agent/templates/competitor-analysis-tmpl.yaml +293 -0
- package/2/vf-agent/templates/market-research-tmpl.yaml +252 -0
- package/2/vf-agent/templates/project-brief-tmpl.yaml +221 -0
- package/2/vf-agent/templates/story-tmpl.yaml +143 -0
- package/BEFORE-AFTER.md +327 -0
- package/CHANGELOG.md +73 -0
- package/CLI-ROADMAP.md +415 -0
- package/COMMAND-REFERENCE.md +341 -0
- package/IMPLEMENTATION-STATUS.md +316 -0
- package/MANUAL-TEST-CHECKLIST.md +264 -0
- package/OPTIONS-GLOSSARY.md +308 -0
- package/PHASE-1-2-3-COMPLETE.md +435 -0
- package/PHASE-1-2-IMPLEMENTATION.md +280 -0
- package/PHASE-1-2-SUMMARY.md +183 -0
- package/QUICK-START.md +352 -0
- package/RECIPES-GUIDE.md +325 -0
- package/RELEASE-CHECKLIST.md +269 -0
- package/VF-INIT-FLOW.md +446 -0
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +328 -66
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/checklist.d.ts.map +1 -1
- package/dist/commands/checklist.js +69 -5
- package/dist/commands/checklist.js.map +1 -1
- package/dist/commands/env.d.ts +3 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +130 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/health.d.ts +3 -0
- package/dist/commands/health.d.ts.map +1 -0
- package/dist/commands/health.js +214 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +310 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +36 -16
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +5 -0
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +11 -0
- package/dist/commands/remove.js.map +1 -1
- package/dist/core/__tests__/detect.test.d.ts +2 -0
- package/dist/core/__tests__/detect.test.d.ts.map +1 -0
- package/dist/core/__tests__/detect.test.js +73 -0
- package/dist/core/__tests__/detect.test.js.map +1 -0
- package/dist/core/detect.d.ts +10 -0
- package/dist/core/detect.d.ts.map +1 -0
- package/dist/core/detect.js +58 -0
- package/dist/core/detect.js.map +1 -0
- package/dist/core/env.d.ts +24 -0
- package/dist/core/env.d.ts.map +1 -0
- package/dist/core/env.js +83 -0
- package/dist/core/env.js.map +1 -0
- package/dist/core/errors.d.ts +13 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +111 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/prompt.d.ts +46 -2
- package/dist/core/prompt.d.ts.map +1 -1
- package/dist/core/prompt.js +179 -15
- package/dist/core/prompt.js.map +1 -1
- package/dist/core/prompts.d.ts +23 -0
- package/dist/core/prompts.d.ts.map +1 -0
- package/dist/core/prompts.js +85 -0
- package/dist/core/prompts.js.map +1 -0
- package/dist/core/recipes.d.ts +31 -0
- package/dist/core/recipes.d.ts.map +1 -0
- package/dist/core/recipes.js +138 -0
- package/dist/core/recipes.js.map +1 -0
- package/dist/core/spinner.d.ts +20 -0
- package/dist/core/spinner.d.ts.map +1 -0
- package/dist/core/spinner.js +72 -0
- package/dist/core/spinner.js.map +1 -0
- package/dist/core/vosk.d.ts +7 -0
- package/dist/core/vosk.d.ts.map +1 -0
- package/dist/core/vosk.js +94 -0
- package/dist/core/vosk.js.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
- package/recipes/README.md +156 -0
- package/recipes/image-analysis/recipe.json +61 -0
- package/recipes/image-analysis@latest.zip +0 -0
- package/recipes/image-generator/recipe.json +7 -12
- package/recipes/posthog.json +46 -0
- package/recipes/revenuecat.json +43 -0
- package/recipes/sentry.json +46 -0
- package/recipes/voice-bot/recipe.json +10 -7
- package/recipes/wake-word/apps/native/assets/vosk-model/README.md +103 -0
- package/recipes/wake-word/apps/native/src/app/(root)/(protected)/test-wake-word.tsx +216 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/components/index.ts +1 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/components/wake-word-indicator.tsx +61 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/constants.ts +10 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/hooks/use-wake-word.ts +181 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/index.ts +22 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/services/audio-session.ts +40 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/services/event-bus.ts +31 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/services/keywords.ts +88 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/services/wake-word-manager.ts +249 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/types.ts +22 -0
- package/recipes/wake-word/recipe.json +50 -0
- package/recipes/wake-word/scripts/download-vosk-model.mjs +121 -0
- package/recipes/wake-word@latest.zip +0 -0
- package/scripts/sync-recipes.js +93 -0
- package/src/commands/add.ts +401 -68
- package/src/commands/checklist.ts +81 -6
- package/src/commands/env.ts +163 -0
- package/src/commands/health.ts +225 -0
- package/src/commands/init.ts +390 -0
- package/src/commands/list.ts +42 -16
- package/src/commands/login.ts +6 -0
- package/src/commands/remove.ts +12 -0
- package/src/core/__tests__/detect.test.ts +91 -0
- package/src/core/detect.ts +60 -0
- package/src/core/env.ts +109 -0
- package/src/core/errors.ts +122 -0
- package/src/core/prompt.ts +227 -16
- package/src/core/prompts.ts +115 -0
- package/src/core/recipes.ts +152 -0
- package/src/core/spinner.ts +87 -0
- package/src/core/vosk.ts +111 -0
- package/src/index.ts +50 -0
- package/test-locally.sh +145 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
# Push Notifications Reference
|
|
2
|
+
|
|
3
|
+
> Frontend paths reference the Expo workspace (`apps/native/src/...`); backend paths reference `packages/backend/convex/...` when calling server functions.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The VibeFast starter kit includes a complete, end-to-end push notification system with deep linking, local notifications, and notification history. It allows the app to register for notifications, securely store user tokens on the backend, send targeted notifications from server-side Convex actions, and handle user interactions with notifications.
|
|
8
|
+
|
|
9
|
+
### Core Technologies
|
|
10
|
+
|
|
11
|
+
- **[Expo Push Notifications](https://docs.expo.dev/push-notifications/overview/):** The entire system is built on Expo's push notification service. The frontend uses `expo-notifications` to get a token, and the backend sends messages via Expo's `https://exp.host/--/api/v2/push/send` HTTP endpoint.
|
|
12
|
+
- **[Convex Actions & Mutations](https://docs.convex.dev/functions):** The backend logic for storing tokens and sending messages is encapsulated in Convex functions, ensuring that no sensitive credentials or logic are exposed on the client.
|
|
13
|
+
- **[Expo Router Deep Linking](https://docs.expo.dev/router/reference/linking/):** Notifications can include deep link data to navigate users to specific screens when they tap on a notification.
|
|
14
|
+
- **[AsyncStorage](https://react-native-async-storage.github.io/async-storage/):** Local notification history and preferences are stored securely on the device.
|
|
15
|
+
|
|
16
|
+
## Getting Started
|
|
17
|
+
|
|
18
|
+
The push notification system is ready to use out-of-the-box. It works on physical devices, not simulators. The necessary permissions will be requested from the user automatically when needed.
|
|
19
|
+
|
|
20
|
+
### Setup
|
|
21
|
+
|
|
22
|
+
1. **Add the NotificationProvider to your app root:**
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
// apps/native/src/app/_layout.tsx
|
|
26
|
+
import { NotificationProvider } from '@/providers/notification-provider';
|
|
27
|
+
|
|
28
|
+
export default function RootLayout() {
|
|
29
|
+
return (
|
|
30
|
+
<NotificationProvider>
|
|
31
|
+
{/* Your existing app layout */}
|
|
32
|
+
</NotificationProvider>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The `NotificationProvider` automatically:
|
|
38
|
+
|
|
39
|
+
- Initializes notification listeners
|
|
40
|
+
- Handles deep link navigation when notifications are tapped
|
|
41
|
+
- Stores notification history locally
|
|
42
|
+
- Manages notification permissions
|
|
43
|
+
|
|
44
|
+
### Push Notification Flow
|
|
45
|
+
|
|
46
|
+
1. **Registration (Frontend):**
|
|
47
|
+
- The `usePushNotifications` hook is the central point for frontend logic.
|
|
48
|
+
- Its `registerForPushNotificationsAsync` function is called (e.g., when a user enables notifications in settings).
|
|
49
|
+
- The function requests permission from the user via the OS.
|
|
50
|
+
- If permission is granted, it calls `Notifications.getExpoPushTokenAsync()` to get the unique device token.
|
|
51
|
+
- It then calls the `recordPushToken` Convex mutation, sending the token to the backend to be stored securely.
|
|
52
|
+
2. **Storage (Backend):**
|
|
53
|
+
- The `recordPushToken` mutation receives the token and associates it with the currently authenticated user in the `pushTokens` table.
|
|
54
|
+
- This creates a link between a user in your database and a specific device that can receive notifications.
|
|
55
|
+
3. **Sending (Backend):**
|
|
56
|
+
- A Convex `action` (e.g., `sendPushNotification`) is called with a `userId`, message content, and optional deep link data.
|
|
57
|
+
- The action looks up the user's push token from the `pushTokens` table.
|
|
58
|
+
- It constructs a `POST` request to the Expo Push API with the user's token, message payload, and deep link data.
|
|
59
|
+
- Expo receives the request and delivers the notification to the user's device.
|
|
60
|
+
4. **User Interaction:**
|
|
61
|
+
- When the user taps on a notification, the `NotificationProvider` intercepts it.
|
|
62
|
+
- The `deepLinkHandler` validates and processes the deep link data.
|
|
63
|
+
- The user is navigated to the appropriate screen with the correct parameters.
|
|
64
|
+
- The notification is stored in local history and marked as read.
|
|
65
|
+
|
|
66
|
+
## Key Components & Hooks
|
|
67
|
+
|
|
68
|
+
### Core Hooks
|
|
69
|
+
|
|
70
|
+
- **`usePushNotifications` (`apps/native/src/core/notifications/`):** This is the primary hook for all client-side push notification interactions. It abstracts away the entire registration process and provides simple functions to use in your UI components.
|
|
71
|
+
- `registerForPushNotificationsAsync()`: Handles the full registration flow.
|
|
72
|
+
- `toggleNotifications()`: Allows enabling or disabling notifications by calling the backend `togglePushNotifications` mutation.
|
|
73
|
+
- It also exposes the user's current notification status (`hasToken`, `paused`).
|
|
74
|
+
|
|
75
|
+
### Core Providers
|
|
76
|
+
|
|
77
|
+
- **`NotificationProvider` (`apps/native/src/providers/notification-provider.tsx`):** The central provider that manages all notification functionality. It should wrap your app root and handles:
|
|
78
|
+
- Notification listeners (foreground, background, tap events)
|
|
79
|
+
- Deep link navigation
|
|
80
|
+
- Notification history storage
|
|
81
|
+
- Permission management
|
|
82
|
+
|
|
83
|
+
### Core Managers
|
|
84
|
+
|
|
85
|
+
- **`localNotificationManager` (`apps/native/src/core/local-notifications/local-notification-manager.ts`):** Manages local notifications (scheduled on-device).
|
|
86
|
+
- `scheduleNotification()`: Schedule a notification with full control over timing and content.
|
|
87
|
+
- `scheduleNotificationWithDelay()`: Schedule a notification to fire after a delay (e.g., "in 1 hour").
|
|
88
|
+
- `scheduleNotificationForDate()`: Schedule a notification for a specific date/time.
|
|
89
|
+
- `cancelNotification()`: Cancel a scheduled notification.
|
|
90
|
+
- `cancelAllNotifications()`: Cancel all scheduled notifications.
|
|
91
|
+
- `getScheduledNotifications()`: Get all currently scheduled notifications.
|
|
92
|
+
|
|
93
|
+
- **`deepLinkHandler` (`apps/native/src/core/navigation/deep-link-handler.ts`):** Handles deep link navigation from notifications.
|
|
94
|
+
- `handleNotificationPress()`: Process notification data and navigate to the appropriate screen.
|
|
95
|
+
- `validateDeepLink()`: Validate a deep link URL against allowed patterns.
|
|
96
|
+
- Supports internal navigation, external URLs, and custom actions.
|
|
97
|
+
|
|
98
|
+
- **`notificationStorage` (`apps/native/src/core/storage/notification-storage.ts`):** Manages local notification history.
|
|
99
|
+
- `saveNotification()`: Store a notification in local history.
|
|
100
|
+
- `getAllNotifications()`: Get all stored notifications.
|
|
101
|
+
- `getUnreadCount()`: Get count of unread notifications.
|
|
102
|
+
- `markAsRead()`: Mark a notification as read.
|
|
103
|
+
- `clearAll()`: Clear all notification history.
|
|
104
|
+
|
|
105
|
+
### Core Components
|
|
106
|
+
|
|
107
|
+
- **`NotificationItem` (`apps/native/src/components/settings/`):** A ready-to-use settings component that allows the user to toggle push notifications on or off. It uses the `usePushNotifications` hook internally.
|
|
108
|
+
|
|
109
|
+
- **`NotificationDemo` (`apps/native/src/components/demo/notification-demo.tsx`):** A comprehensive demo component for testing all notification features including push notifications, local notifications, deep links, and notification history.
|
|
110
|
+
|
|
111
|
+
## How-To Guides
|
|
112
|
+
|
|
113
|
+
### 1. Prompt a User to Enable Notifications
|
|
114
|
+
|
|
115
|
+
You can use the `usePushNotifications` hook in any component to prompt the user to register.
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import { usePushNotifications } from '@/core/notifications';
|
|
119
|
+
import { Button } from '@/components/ui';
|
|
120
|
+
|
|
121
|
+
function MyComponent() {
|
|
122
|
+
const { registerForPushNotificationsAsync, status } = usePushNotifications();
|
|
123
|
+
|
|
124
|
+
// Don't show the button if they already have a token
|
|
125
|
+
if (status.hasToken) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<Button
|
|
131
|
+
label="Enable Notifications"
|
|
132
|
+
onPress={registerForPushNotificationsAsync}
|
|
133
|
+
/>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 2. Send a Notification with Deep Links
|
|
139
|
+
|
|
140
|
+
You can easily send a notification to a user from any Convex action with deep link data for navigation.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// packages/backend/convex/myFeature.ts
|
|
144
|
+
import { action } from './_generated/server';
|
|
145
|
+
import { api } from './_generated/api';
|
|
146
|
+
import { v } from 'convex/values';
|
|
147
|
+
|
|
148
|
+
export const doSomethingAndNotify = action({
|
|
149
|
+
args: {
|
|
150
|
+
userIdToNotify: v.id('users'),
|
|
151
|
+
chatId: v.string(),
|
|
152
|
+
message: v.string(),
|
|
153
|
+
},
|
|
154
|
+
handler: async (ctx, args) => {
|
|
155
|
+
// ... your feature's logic here ...
|
|
156
|
+
|
|
157
|
+
// After your logic is complete, send the notification with deep link
|
|
158
|
+
await ctx.runAction(api.pushNotificationFunctions.sendPushNotification, {
|
|
159
|
+
toUserId: args.userIdToNotify,
|
|
160
|
+
title: 'You have a new message!',
|
|
161
|
+
body: args.message,
|
|
162
|
+
data: {
|
|
163
|
+
type: 'deep_link',
|
|
164
|
+
url: `/chat/${args.chatId}`,
|
|
165
|
+
screen: 'chat',
|
|
166
|
+
params: { chatId: args.chatId },
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// ...
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Supported Deep Link Types:**
|
|
176
|
+
|
|
177
|
+
- **Internal Navigation:** Navigate to a screen within the app
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
data: {
|
|
181
|
+
type: 'deep_link',
|
|
182
|
+
url: '/profile/user-123',
|
|
183
|
+
screen: 'profile',
|
|
184
|
+
params: { userId: 'user-123' }
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
- **External URLs:** Open a URL in the browser
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
data: {
|
|
192
|
+
type: 'external_url',
|
|
193
|
+
url: 'https://vibefast.app'
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
- **Custom Actions:** Trigger custom app actions
|
|
198
|
+
```ts
|
|
199
|
+
data: {
|
|
200
|
+
type: 'action',
|
|
201
|
+
action: 'refresh',
|
|
202
|
+
params: { source: 'notification' }
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### 3. Schedule Local Notifications
|
|
207
|
+
|
|
208
|
+
Local notifications are scheduled on the device and don't require a backend call.
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
import { localNotificationManager } from '@/core/local-notifications/local-notification-manager';
|
|
212
|
+
|
|
213
|
+
function ReminderComponent() {
|
|
214
|
+
// Schedule for 1 hour from now
|
|
215
|
+
const scheduleReminder = async () => {
|
|
216
|
+
await localNotificationManager.scheduleNotificationWithDelay(
|
|
217
|
+
{
|
|
218
|
+
title: 'Medication Reminder',
|
|
219
|
+
body: 'Time to take your medication',
|
|
220
|
+
data: {
|
|
221
|
+
type: 'deep_link',
|
|
222
|
+
url: '/health/medications',
|
|
223
|
+
screen: 'medications',
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
60 * 60,
|
|
227
|
+
); // 1 hour in seconds
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// Schedule for specific date
|
|
231
|
+
const scheduleDailyCheckIn = async () => {
|
|
232
|
+
const tomorrow = new Date();
|
|
233
|
+
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
234
|
+
tomorrow.setHours(9, 0, 0, 0);
|
|
235
|
+
|
|
236
|
+
await localNotificationManager.scheduleNotificationForDate(
|
|
237
|
+
{
|
|
238
|
+
title: 'Daily Check-in',
|
|
239
|
+
body: 'Time for your daily check-in!',
|
|
240
|
+
data: {
|
|
241
|
+
type: 'deep_link',
|
|
242
|
+
url: '/checkin',
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
tomorrow,
|
|
246
|
+
);
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
return (
|
|
250
|
+
<View>
|
|
251
|
+
<Button title="Schedule Reminder" onPress={scheduleReminder} />
|
|
252
|
+
<Button title="Schedule Daily Check-in" onPress={scheduleDailyCheckIn} />
|
|
253
|
+
</View>
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Note:** iOS limits scheduled notifications to 64. Use `getScheduledNotifications()` to check the current count.
|
|
259
|
+
|
|
260
|
+
### 4. Handle Deep Links Manually
|
|
261
|
+
|
|
262
|
+
The `NotificationProvider` handles deep links automatically, but you can also handle them manually:
|
|
263
|
+
|
|
264
|
+
```tsx
|
|
265
|
+
import { deepLinkHandler } from '@/core/navigation/deep-link-handler';
|
|
266
|
+
|
|
267
|
+
function CustomHandler() {
|
|
268
|
+
const handleCustomNavigation = async () => {
|
|
269
|
+
// Navigate to specific screen
|
|
270
|
+
await deepLinkHandler.handleNotificationPress({
|
|
271
|
+
type: 'deep_link',
|
|
272
|
+
url: '/profile/123',
|
|
273
|
+
screen: 'profile',
|
|
274
|
+
params: { userId: '123' },
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Open external URL
|
|
278
|
+
await deepLinkHandler.handleNotificationPress({
|
|
279
|
+
type: 'external_url',
|
|
280
|
+
url: 'https://example.com',
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// Execute custom action
|
|
284
|
+
await deepLinkHandler.handleNotificationPress({
|
|
285
|
+
type: 'action',
|
|
286
|
+
action: 'refresh',
|
|
287
|
+
params: { source: 'notification' },
|
|
288
|
+
});
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### 5. Access Notification History
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
import { notificationStorage } from '@/core/storage/notification-storage';
|
|
297
|
+
|
|
298
|
+
function NotificationHistoryScreen() {
|
|
299
|
+
const [notifications, setNotifications] = useState([]);
|
|
300
|
+
const [unreadCount, setUnreadCount] = useState(0);
|
|
301
|
+
|
|
302
|
+
useEffect(() => {
|
|
303
|
+
loadNotifications();
|
|
304
|
+
}, []);
|
|
305
|
+
|
|
306
|
+
const loadNotifications = async () => {
|
|
307
|
+
const history = await notificationStorage.getAllNotifications();
|
|
308
|
+
const count = await notificationStorage.getUnreadCount();
|
|
309
|
+
setNotifications(history);
|
|
310
|
+
setUnreadCount(count);
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const markAsRead = async (id: string) => {
|
|
314
|
+
await notificationStorage.markAsRead(id);
|
|
315
|
+
loadNotifications();
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
return (
|
|
319
|
+
<View>
|
|
320
|
+
<Text>Unread: {unreadCount}</Text>
|
|
321
|
+
{notifications.map((notif) => (
|
|
322
|
+
<TouchableOpacity key={notif.id} onPress={() => markAsRead(notif.id)}>
|
|
323
|
+
<Text>{notif.title}</Text>
|
|
324
|
+
<Text>{notif.body}</Text>
|
|
325
|
+
</TouchableOpacity>
|
|
326
|
+
))}
|
|
327
|
+
</View>
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Backend (Convex)
|
|
333
|
+
|
|
334
|
+
- **`packages/backend/convex/pushNotificationFunctions.ts`:** This file contains all the backend logic.
|
|
335
|
+
- `recordPushToken` (mutation): Securely stores or updates a user's Expo push token.
|
|
336
|
+
- `getNotificationStatus` (query): Fetches the current notification preferences for the logged-in user.
|
|
337
|
+
- `togglePushNotifications` (mutation): Allows users to pause or resume notifications.
|
|
338
|
+
- `sendPushNotification` (action): The core function for sending a message. It takes a `userId`, message content, and optional deep link data payload, and sends it to the Expo push service.
|
|
339
|
+
- `sendTestNotification` (action): A useful utility for developers to easily test if a user's device is correctly registered.
|
|
340
|
+
|
|
341
|
+
## Testing
|
|
342
|
+
|
|
343
|
+
### Use the Demo Component
|
|
344
|
+
|
|
345
|
+
The `NotificationDemo` component provides a comprehensive testing interface:
|
|
346
|
+
|
|
347
|
+
```tsx
|
|
348
|
+
import { NotificationDemo } from '@/components/demo/notification-demo';
|
|
349
|
+
|
|
350
|
+
function TestScreen() {
|
|
351
|
+
return <NotificationDemo />;
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Features:
|
|
356
|
+
|
|
357
|
+
- Test push notifications with deep links
|
|
358
|
+
- Schedule local notifications
|
|
359
|
+
- Test deep link navigation
|
|
360
|
+
- View notification history
|
|
361
|
+
- Manage permissions
|
|
362
|
+
|
|
363
|
+
### Test Deep Links in Development
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
# iOS Simulator
|
|
367
|
+
xcrun simctl openurl booted "vibefast://chat/test-chat-id"
|
|
368
|
+
|
|
369
|
+
# Android Emulator
|
|
370
|
+
adb shell am start -W -a android.intent.action.VIEW -d "vibefast://chat/test-chat-id" com.your.package.id
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Security & Validation
|
|
374
|
+
|
|
375
|
+
### URL Validation
|
|
376
|
+
|
|
377
|
+
All deep link URLs are validated against allowed patterns in `deepLinkHandler`:
|
|
378
|
+
|
|
379
|
+
- `/chat/*` - Chat screens
|
|
380
|
+
- `/profile/*` - Profile screens
|
|
381
|
+
- `/settings/*` - Settings screens
|
|
382
|
+
- `/analysis/*` - Analysis screens
|
|
383
|
+
- `/` - Home screen
|
|
384
|
+
|
|
385
|
+
### External URL Handling
|
|
386
|
+
|
|
387
|
+
External URLs show a confirmation dialog before opening to prevent phishing attacks.
|
|
388
|
+
|
|
389
|
+
### Data Sanitization
|
|
390
|
+
|
|
391
|
+
All notification data is type-validated in Convex functions using `v.object()` validators.
|
|
392
|
+
|
|
393
|
+
## Platform-Specific Notes
|
|
394
|
+
|
|
395
|
+
### iOS
|
|
396
|
+
|
|
397
|
+
- Maximum 64 scheduled local notifications
|
|
398
|
+
- Notification sounds limited to built-in sounds or custom sounds in app bundle
|
|
399
|
+
- Background execution limited by iOS
|
|
400
|
+
|
|
401
|
+
### Android
|
|
402
|
+
|
|
403
|
+
- Requires `POST_NOTIFICATIONS` permission (Android 13+)
|
|
404
|
+
- Supports custom notification sounds
|
|
405
|
+
- Badge support varies by launcher
|
|
406
|
+
|
|
407
|
+
## Best Practices
|
|
408
|
+
|
|
409
|
+
1. **Always include deep link data** in push notifications for better user experience
|
|
410
|
+
2. **Use relative scheduling** ("in 1 hour") instead of absolute times when possible
|
|
411
|
+
3. **Limit scheduled notifications** to stay under iOS 64 limit
|
|
412
|
+
4. **Test on both platforms** - notification behavior can differ significantly
|
|
413
|
+
5. **Handle permissions gracefully** - some users may deny notifications
|
|
414
|
+
6. **Use categories** to organize notification types
|
|
415
|
+
7. **Don't rely on notifications for critical features** - they can be disabled by users
|
|
416
|
+
8. **Store important notifications** in your backend database, not just locally
|
|
417
|
+
9. **Validate deep link URLs** to prevent navigation to invalid screens
|
|
418
|
+
10. **Log notification interactions** for analytics and debugging
|
|
419
|
+
|
|
420
|
+
## Troubleshooting
|
|
421
|
+
|
|
422
|
+
### Notifications not showing
|
|
423
|
+
|
|
424
|
+
```tsx
|
|
425
|
+
// Check permissions
|
|
426
|
+
const status = await localNotificationManager.getPermissions();
|
|
427
|
+
if (status !== 'granted') {
|
|
428
|
+
await localNotificationManager.requestPermissions();
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Deep links not working
|
|
433
|
+
|
|
434
|
+
```tsx
|
|
435
|
+
// Verify URL format
|
|
436
|
+
const isValid = deepLinkHandler.validateDeepLink('/chat/123');
|
|
437
|
+
console.log('Is valid:', isValid);
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Local notifications not firing
|
|
441
|
+
|
|
442
|
+
```tsx
|
|
443
|
+
// Check scheduled count (iOS limit: 64)
|
|
444
|
+
const scheduled = await localNotificationManager.getScheduledNotifications();
|
|
445
|
+
console.log('Scheduled notifications:', scheduled.length);
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
## Additional Resources
|
|
449
|
+
|
|
450
|
+
- [Expo Notifications Documentation](https://docs.expo.dev/versions/latest/sdk/notifications/)
|
|
451
|
+
- [Expo Router Deep Linking](https://docs.expo.dev/router/reference/linking/)
|
|
452
|
+
- [Convex Actions](https://docs.convex.dev/functions/actions)
|
|
453
|
+
- Demo component: `apps/native/src/components/demo/notification-demo.tsx`
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Quick Actions Reference
|
|
2
|
+
|
|
3
|
+
> Frontend paths reference the Expo workspace (`apps/native/src/...`).
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
The Quick Actions feature is automatically configured and ready to use. Here's everything you need to know:
|
|
8
|
+
|
|
9
|
+
### Immediate Usage
|
|
10
|
+
|
|
11
|
+
1. **Settings Management**: Go to Settings → Quick Actions to manage actions
|
|
12
|
+
2. **Demo & Testing**: Visit Settings → Quick Actions Demo for interactive testing
|
|
13
|
+
3. **Device Testing**: Long-press the app icon on your device to see quick actions
|
|
14
|
+
|
|
15
|
+
### Default Actions
|
|
16
|
+
|
|
17
|
+
The starter comes with 4 pre-configured quick actions:
|
|
18
|
+
|
|
19
|
+
- **Home**: Navigate to home tab
|
|
20
|
+
- **Profile**: Navigate to profile tab
|
|
21
|
+
- **Settings**: Navigate to settings tab
|
|
22
|
+
- **Search**: Navigate to home with search focus
|
|
23
|
+
|
|
24
|
+
## Developer API
|
|
25
|
+
|
|
26
|
+
### Basic Usage
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import {
|
|
30
|
+
quickActionsManager,
|
|
31
|
+
useQuickActionRouting,
|
|
32
|
+
} from '@/features/quick-actions';
|
|
33
|
+
|
|
34
|
+
// In your root layout (already configured)
|
|
35
|
+
useQuickActionRouting();
|
|
36
|
+
|
|
37
|
+
// Programmatic management
|
|
38
|
+
await quickActionsManager.setActions([
|
|
39
|
+
{
|
|
40
|
+
id: 'custom',
|
|
41
|
+
title: 'Custom Action',
|
|
42
|
+
icon: 'symbol:star',
|
|
43
|
+
params: { href: '/custom-route' },
|
|
44
|
+
},
|
|
45
|
+
]);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Manager Methods
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
// Set custom actions
|
|
52
|
+
await quickActionsManager.setActions(actions);
|
|
53
|
+
|
|
54
|
+
// Add single action
|
|
55
|
+
await quickActionsManager.addAction(action);
|
|
56
|
+
|
|
57
|
+
// Remove action by ID
|
|
58
|
+
await quickActionsManager.removeAction('action-id');
|
|
59
|
+
|
|
60
|
+
// Reset to defaults
|
|
61
|
+
await quickActionsManager.resetToDefaults();
|
|
62
|
+
|
|
63
|
+
// Set feature-specific actions
|
|
64
|
+
await quickActionsManager.setFeatureActions();
|
|
65
|
+
|
|
66
|
+
// Check support
|
|
67
|
+
const isSupported = await quickActionsManager.isSupported();
|
|
68
|
+
|
|
69
|
+
// Get max count
|
|
70
|
+
const maxCount = quickActionsManager.getMaxCount();
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Hooks
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import {
|
|
77
|
+
useQuickActionRouting,
|
|
78
|
+
useCurrentQuickAction,
|
|
79
|
+
useSetupQuickActions,
|
|
80
|
+
} from '@/features/quick-actions';
|
|
81
|
+
|
|
82
|
+
// Enable automatic routing (use in root layout)
|
|
83
|
+
useQuickActionRouting();
|
|
84
|
+
|
|
85
|
+
// Get current quick action
|
|
86
|
+
const currentAction = useCurrentQuickAction();
|
|
87
|
+
|
|
88
|
+
// Set up actions on component mount
|
|
89
|
+
useSetupQuickActions(myActions);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Icon Reference
|
|
93
|
+
|
|
94
|
+
### System Icons (Cross-platform)
|
|
95
|
+
|
|
96
|
+
- `"home"`, `"search"`, `"add"`, `"contact"`
|
|
97
|
+
- `"play"`, `"pause"`, `"share"`, `"favorite"`
|
|
98
|
+
- `"mail"`, `"message"`, `"date"`, `"time"`
|
|
99
|
+
|
|
100
|
+
### SF Symbols (iOS only)
|
|
101
|
+
|
|
102
|
+
Use `"symbol:"` prefix:
|
|
103
|
+
|
|
104
|
+
- `"symbol:heart.fill"`, `"symbol:star.fill"`
|
|
105
|
+
- `"symbol:gear"`, `"symbol:person.fill"`
|
|
106
|
+
- `"symbol:magnifyingglass"`, `"symbol:plus"`
|
|
107
|
+
|
|
108
|
+
### Custom Assets
|
|
109
|
+
|
|
110
|
+
Use `"asset:"` prefix:
|
|
111
|
+
|
|
112
|
+
- `"asset:my-custom-icon"`
|
|
113
|
+
- Requires configuration in app.config.ts
|
|
114
|
+
|
|
115
|
+
## Configuration Examples
|
|
116
|
+
|
|
117
|
+
### Basic Action
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
{
|
|
121
|
+
id: 'home',
|
|
122
|
+
title: 'Home',
|
|
123
|
+
icon: 'home',
|
|
124
|
+
params: { href: '/(tabs)/' }
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Advanced Action with Subtitle
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
{
|
|
132
|
+
id: 'ai-chat',
|
|
133
|
+
title: 'AI Chat',
|
|
134
|
+
subtitle: 'Chat with AI assistant',
|
|
135
|
+
icon: 'symbol:message',
|
|
136
|
+
params: {
|
|
137
|
+
href: '/(root)/(protected)/chatbot/',
|
|
138
|
+
source: 'quick-action'
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### External Link Action
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
{
|
|
147
|
+
id: 'support',
|
|
148
|
+
title: 'Support',
|
|
149
|
+
subtitle: 'Get help',
|
|
150
|
+
icon: 'symbol:questionmark.circle',
|
|
151
|
+
params: { href: 'mailto:support@myapp.com' }
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Platform Differences
|
|
156
|
+
|
|
157
|
+
### iOS
|
|
158
|
+
|
|
159
|
+
- **Maximum**: 4 actions (Apple recommendation)
|
|
160
|
+
- **Icons**: SF Symbols preferred, system icons supported
|
|
161
|
+
- **Appearance**: 3D Touch/Haptic Touch menu
|
|
162
|
+
- **Behavior**: Actions appear in consistent order
|
|
163
|
+
|
|
164
|
+
### Android
|
|
165
|
+
|
|
166
|
+
- **Maximum**: Variable (device dependent, typically 4-15)
|
|
167
|
+
- **Icons**: Adaptive icons supported, system icons available
|
|
168
|
+
- **Appearance**: Long-press context menu
|
|
169
|
+
- **Behavior**: Actions can be pinned to home screen
|
|
170
|
+
|
|
171
|
+
## Best Practices
|
|
172
|
+
|
|
173
|
+
### Action Design
|
|
174
|
+
|
|
175
|
+
1. **Limit Count**: Use 4 or fewer actions for optimal UX
|
|
176
|
+
2. **Clear Titles**: Keep titles short and descriptive (max 2 words)
|
|
177
|
+
3. **Meaningful Icons**: Use recognizable, consistent icons
|
|
178
|
+
4. **Logical Order**: Place most important actions first
|
|
179
|
+
|
|
180
|
+
### Technical Implementation
|
|
181
|
+
|
|
182
|
+
1. **Deep Linking**: Always provide `href` params for navigation
|
|
183
|
+
2. **Error Handling**: Gracefully handle unsupported devices
|
|
184
|
+
3. **Performance**: Actions are cached, updates are efficient
|
|
185
|
+
4. **Testing**: Test on both iOS and Android devices
|
|
186
|
+
|
|
187
|
+
### User Experience
|
|
188
|
+
|
|
189
|
+
1. **Discoverability**: Don't rely solely on quick actions for core features
|
|
190
|
+
2. **Consistency**: Keep actions stable, avoid frequent changes
|
|
191
|
+
3. **Accessibility**: Ensure titles are descriptive for screen readers
|
|
192
|
+
4. **Feedback**: Provide visual feedback when actions are triggered
|
|
193
|
+
|
|
194
|
+
## Troubleshooting
|
|
195
|
+
|
|
196
|
+
### Actions Not Appearing
|
|
197
|
+
|
|
198
|
+
- Check device support: `await quickActionsManager.isSupported()`
|
|
199
|
+
- Verify app is built for device (not Expo Go)
|
|
200
|
+
- Check console for error messages
|
|
201
|
+
- Ensure actions array is not empty
|
|
202
|
+
|
|
203
|
+
### Navigation Not Working
|
|
204
|
+
|
|
205
|
+
- Verify routes exist in your app structure
|
|
206
|
+
- Check `useQuickActionRouting()` is called in root layout
|
|
207
|
+
- Validate `href` params in action configuration
|
|
208
|
+
- Test navigation manually first
|
|
209
|
+
|
|
210
|
+
### Icons Not Showing
|
|
211
|
+
|
|
212
|
+
- Use valid system icon names or SF Symbols
|
|
213
|
+
- For custom icons, configure in app.config.ts
|
|
214
|
+
- Check platform-specific icon requirements
|
|
215
|
+
- Test with system icons first
|
|
216
|
+
|
|
217
|
+
## Advanced Usage
|
|
218
|
+
|
|
219
|
+
### Custom Manager
|
|
220
|
+
|
|
221
|
+
```tsx
|
|
222
|
+
class CustomQuickActionsManager extends QuickActionsManager {
|
|
223
|
+
async setContextualActions(context: string) {
|
|
224
|
+
const actions = this.getActionsForContext(context);
|
|
225
|
+
await this.setActions(actions);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Analytics Integration
|
|
231
|
+
|
|
232
|
+
```tsx
|
|
233
|
+
useQuickActionCallback((action) => {
|
|
234
|
+
analytics.track('quick_action_used', {
|
|
235
|
+
action_id: action.id,
|
|
236
|
+
action_title: action.title,
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Dynamic Actions
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
const updateActions = async () => {
|
|
246
|
+
const userRole = await getUserRole();
|
|
247
|
+
const actions = getActionsForRole(userRole);
|
|
248
|
+
await quickActionsManager.setActions(actions);
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
updateActions();
|
|
252
|
+
}, [userRole]);
|
|
253
|
+
```
|