@mobileai/react-native 0.9.16 → 0.9.18

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.
Files changed (214) hide show
  1. package/README.md +2 -2
  2. package/package.json +5 -8
  3. package/lib/module/__cli_tmp__.js.map +0 -1
  4. package/lib/module/components/AIAgent.js.map +0 -1
  5. package/lib/module/components/AIZone.js.map +0 -1
  6. package/lib/module/components/AgentChatBar.js.map +0 -1
  7. package/lib/module/components/AgentErrorBoundary.js.map +0 -1
  8. package/lib/module/components/AgentOverlay.js.map +0 -1
  9. package/lib/module/components/DiscoveryTooltip.js.map +0 -1
  10. package/lib/module/components/HighlightOverlay.js.map +0 -1
  11. package/lib/module/components/Icons.js.map +0 -1
  12. package/lib/module/components/ProactiveHint.js.map +0 -1
  13. package/lib/module/components/cards/InfoCard.js.map +0 -1
  14. package/lib/module/components/cards/ReviewSummary.js.map +0 -1
  15. package/lib/module/config/endpoints.js.map +0 -1
  16. package/lib/module/core/ActionRegistry.js.map +0 -1
  17. package/lib/module/core/AgentRuntime.js.map +0 -1
  18. package/lib/module/core/FiberTreeWalker.js.map +0 -1
  19. package/lib/module/core/IdleDetector.js.map +0 -1
  20. package/lib/module/core/MCPBridge.js.map +0 -1
  21. package/lib/module/core/ScreenDehydrator.js.map +0 -1
  22. package/lib/module/core/ZoneRegistry.js.map +0 -1
  23. package/lib/module/core/systemPrompt.js.map +0 -1
  24. package/lib/module/core/types.js.map +0 -1
  25. package/lib/module/hooks/useAction.js.map +0 -1
  26. package/lib/module/index.js.map +0 -1
  27. package/lib/module/plugin/withAppIntents.js.map +0 -1
  28. package/lib/module/providers/GeminiProvider.js.map +0 -1
  29. package/lib/module/providers/OpenAIProvider.js.map +0 -1
  30. package/lib/module/providers/ProviderFactory.js.map +0 -1
  31. package/lib/module/services/AudioInputService.js.map +0 -1
  32. package/lib/module/services/AudioOutputService.js.map +0 -1
  33. package/lib/module/services/KnowledgeBaseService.js.map +0 -1
  34. package/lib/module/services/VoiceService.js.map +0 -1
  35. package/lib/module/services/flags/FlagService.js.map +0 -1
  36. package/lib/module/services/telemetry/MobileAI.js.map +0 -1
  37. package/lib/module/services/telemetry/PiiScrubber.js.map +0 -1
  38. package/lib/module/services/telemetry/TelemetryService.js.map +0 -1
  39. package/lib/module/services/telemetry/TouchAutoCapture.js.map +0 -1
  40. package/lib/module/services/telemetry/device.js.map +0 -1
  41. package/lib/module/services/telemetry/deviceMetadata.js.map +0 -1
  42. package/lib/module/services/telemetry/index.js.map +0 -1
  43. package/lib/module/services/telemetry/types.js.map +0 -1
  44. package/lib/module/support/CSATSurvey.js.map +0 -1
  45. package/lib/module/support/EscalationEventSource.js.map +0 -1
  46. package/lib/module/support/EscalationSocket.js.map +0 -1
  47. package/lib/module/support/SupportChatModal.js.map +0 -1
  48. package/lib/module/support/SupportGreeting.js.map +0 -1
  49. package/lib/module/support/TicketStore.js.map +0 -1
  50. package/lib/module/support/escalateTool.js.map +0 -1
  51. package/lib/module/support/index.js.map +0 -1
  52. package/lib/module/support/supportPrompt.js.map +0 -1
  53. package/lib/module/support/types.js.map +0 -1
  54. package/lib/module/tools/datePickerTool.js.map +0 -1
  55. package/lib/module/tools/guideTool.js.map +0 -1
  56. package/lib/module/tools/index.js.map +0 -1
  57. package/lib/module/tools/keyboardTool.js.map +0 -1
  58. package/lib/module/tools/longPressTool.js.map +0 -1
  59. package/lib/module/tools/pickerTool.js.map +0 -1
  60. package/lib/module/tools/restoreTool.js.map +0 -1
  61. package/lib/module/tools/scrollTool.js.map +0 -1
  62. package/lib/module/tools/simplifyTool.js.map +0 -1
  63. package/lib/module/tools/sliderTool.js.map +0 -1
  64. package/lib/module/tools/tapTool.js.map +0 -1
  65. package/lib/module/tools/typeTool.js.map +0 -1
  66. package/lib/module/tools/types.js.map +0 -1
  67. package/lib/module/types/jsx.d.js.map +0 -1
  68. package/lib/module/utils/audioUtils.js.map +0 -1
  69. package/lib/module/utils/logger.js.map +0 -1
  70. package/lib/typescript/babel.config.d.ts.map +0 -1
  71. package/lib/typescript/bin/generate-map.d.cts.map +0 -1
  72. package/lib/typescript/eslint.config.d.mts.map +0 -1
  73. package/lib/typescript/generate-map.d.ts.map +0 -1
  74. package/lib/typescript/src/__cli_tmp__.d.ts.map +0 -1
  75. package/lib/typescript/src/components/AIAgent.d.ts.map +0 -1
  76. package/lib/typescript/src/components/AIZone.d.ts.map +0 -1
  77. package/lib/typescript/src/components/AgentChatBar.d.ts.map +0 -1
  78. package/lib/typescript/src/components/AgentErrorBoundary.d.ts.map +0 -1
  79. package/lib/typescript/src/components/AgentOverlay.d.ts.map +0 -1
  80. package/lib/typescript/src/components/DiscoveryTooltip.d.ts.map +0 -1
  81. package/lib/typescript/src/components/HighlightOverlay.d.ts.map +0 -1
  82. package/lib/typescript/src/components/Icons.d.ts.map +0 -1
  83. package/lib/typescript/src/components/ProactiveHint.d.ts.map +0 -1
  84. package/lib/typescript/src/components/cards/InfoCard.d.ts.map +0 -1
  85. package/lib/typescript/src/components/cards/ReviewSummary.d.ts.map +0 -1
  86. package/lib/typescript/src/config/endpoints.d.ts.map +0 -1
  87. package/lib/typescript/src/core/ActionRegistry.d.ts.map +0 -1
  88. package/lib/typescript/src/core/AgentRuntime.d.ts.map +0 -1
  89. package/lib/typescript/src/core/FiberTreeWalker.d.ts.map +0 -1
  90. package/lib/typescript/src/core/IdleDetector.d.ts.map +0 -1
  91. package/lib/typescript/src/core/MCPBridge.d.ts.map +0 -1
  92. package/lib/typescript/src/core/ScreenDehydrator.d.ts.map +0 -1
  93. package/lib/typescript/src/core/ZoneRegistry.d.ts.map +0 -1
  94. package/lib/typescript/src/core/systemPrompt.d.ts.map +0 -1
  95. package/lib/typescript/src/core/types.d.ts.map +0 -1
  96. package/lib/typescript/src/hooks/useAction.d.ts.map +0 -1
  97. package/lib/typescript/src/index.d.ts.map +0 -1
  98. package/lib/typescript/src/plugin/withAppIntents.d.ts.map +0 -1
  99. package/lib/typescript/src/providers/GeminiProvider.d.ts.map +0 -1
  100. package/lib/typescript/src/providers/OpenAIProvider.d.ts.map +0 -1
  101. package/lib/typescript/src/providers/ProviderFactory.d.ts.map +0 -1
  102. package/lib/typescript/src/services/AudioInputService.d.ts.map +0 -1
  103. package/lib/typescript/src/services/AudioOutputService.d.ts.map +0 -1
  104. package/lib/typescript/src/services/KnowledgeBaseService.d.ts.map +0 -1
  105. package/lib/typescript/src/services/VoiceService.d.ts.map +0 -1
  106. package/lib/typescript/src/services/flags/FlagService.d.ts.map +0 -1
  107. package/lib/typescript/src/services/telemetry/MobileAI.d.ts.map +0 -1
  108. package/lib/typescript/src/services/telemetry/PiiScrubber.d.ts.map +0 -1
  109. package/lib/typescript/src/services/telemetry/TelemetryService.d.ts.map +0 -1
  110. package/lib/typescript/src/services/telemetry/TouchAutoCapture.d.ts.map +0 -1
  111. package/lib/typescript/src/services/telemetry/device.d.ts.map +0 -1
  112. package/lib/typescript/src/services/telemetry/deviceMetadata.d.ts.map +0 -1
  113. package/lib/typescript/src/services/telemetry/index.d.ts.map +0 -1
  114. package/lib/typescript/src/services/telemetry/types.d.ts.map +0 -1
  115. package/lib/typescript/src/support/CSATSurvey.d.ts.map +0 -1
  116. package/lib/typescript/src/support/EscalationEventSource.d.ts.map +0 -1
  117. package/lib/typescript/src/support/EscalationSocket.d.ts.map +0 -1
  118. package/lib/typescript/src/support/SupportChatModal.d.ts.map +0 -1
  119. package/lib/typescript/src/support/SupportGreeting.d.ts.map +0 -1
  120. package/lib/typescript/src/support/TicketStore.d.ts.map +0 -1
  121. package/lib/typescript/src/support/escalateTool.d.ts.map +0 -1
  122. package/lib/typescript/src/support/index.d.ts.map +0 -1
  123. package/lib/typescript/src/support/supportPrompt.d.ts.map +0 -1
  124. package/lib/typescript/src/support/types.d.ts.map +0 -1
  125. package/lib/typescript/src/tools/datePickerTool.d.ts.map +0 -1
  126. package/lib/typescript/src/tools/guideTool.d.ts.map +0 -1
  127. package/lib/typescript/src/tools/index.d.ts.map +0 -1
  128. package/lib/typescript/src/tools/keyboardTool.d.ts.map +0 -1
  129. package/lib/typescript/src/tools/longPressTool.d.ts.map +0 -1
  130. package/lib/typescript/src/tools/pickerTool.d.ts.map +0 -1
  131. package/lib/typescript/src/tools/restoreTool.d.ts.map +0 -1
  132. package/lib/typescript/src/tools/scrollTool.d.ts.map +0 -1
  133. package/lib/typescript/src/tools/simplifyTool.d.ts.map +0 -1
  134. package/lib/typescript/src/tools/sliderTool.d.ts.map +0 -1
  135. package/lib/typescript/src/tools/tapTool.d.ts.map +0 -1
  136. package/lib/typescript/src/tools/typeTool.d.ts.map +0 -1
  137. package/lib/typescript/src/tools/types.d.ts.map +0 -1
  138. package/lib/typescript/src/utils/audioUtils.d.ts.map +0 -1
  139. package/lib/typescript/src/utils/logger.d.ts.map +0 -1
  140. package/src/__cli_tmp__.tsx +0 -9
  141. package/src/cli/analyzers/chain-analyzer.ts +0 -183
  142. package/src/cli/extractors/ai-extractor.ts +0 -6
  143. package/src/cli/extractors/ast-extractor.ts +0 -551
  144. package/src/cli/generate-intents.ts +0 -140
  145. package/src/cli/generate-map.ts +0 -121
  146. package/src/cli/generate-swift.ts +0 -116
  147. package/src/cli/scanners/expo-scanner.ts +0 -203
  148. package/src/cli/scanners/rn-scanner.ts +0 -445
  149. package/src/components/AIAgent.tsx +0 -1716
  150. package/src/components/AIZone.tsx +0 -147
  151. package/src/components/AgentChatBar.tsx +0 -1143
  152. package/src/components/AgentErrorBoundary.tsx +0 -78
  153. package/src/components/AgentOverlay.tsx +0 -73
  154. package/src/components/DiscoveryTooltip.tsx +0 -148
  155. package/src/components/HighlightOverlay.tsx +0 -136
  156. package/src/components/Icons.tsx +0 -253
  157. package/src/components/ProactiveHint.tsx +0 -145
  158. package/src/components/cards/InfoCard.tsx +0 -58
  159. package/src/components/cards/ReviewSummary.tsx +0 -76
  160. package/src/config/endpoints.ts +0 -22
  161. package/src/core/ActionRegistry.ts +0 -105
  162. package/src/core/AgentRuntime.ts +0 -1471
  163. package/src/core/FiberTreeWalker.ts +0 -930
  164. package/src/core/IdleDetector.ts +0 -72
  165. package/src/core/MCPBridge.ts +0 -163
  166. package/src/core/ScreenDehydrator.ts +0 -53
  167. package/src/core/ZoneRegistry.ts +0 -44
  168. package/src/core/systemPrompt.ts +0 -431
  169. package/src/core/types.ts +0 -521
  170. package/src/hooks/useAction.ts +0 -182
  171. package/src/index.ts +0 -83
  172. package/src/plugin/withAppIntents.ts +0 -98
  173. package/src/providers/GeminiProvider.ts +0 -357
  174. package/src/providers/OpenAIProvider.ts +0 -379
  175. package/src/providers/ProviderFactory.ts +0 -36
  176. package/src/services/AudioInputService.ts +0 -226
  177. package/src/services/AudioOutputService.ts +0 -236
  178. package/src/services/KnowledgeBaseService.ts +0 -156
  179. package/src/services/VoiceService.ts +0 -451
  180. package/src/services/flags/FlagService.ts +0 -137
  181. package/src/services/telemetry/MobileAI.ts +0 -66
  182. package/src/services/telemetry/PiiScrubber.ts +0 -17
  183. package/src/services/telemetry/TelemetryService.ts +0 -323
  184. package/src/services/telemetry/TouchAutoCapture.ts +0 -165
  185. package/src/services/telemetry/device.ts +0 -93
  186. package/src/services/telemetry/deviceMetadata.ts +0 -13
  187. package/src/services/telemetry/index.ts +0 -13
  188. package/src/services/telemetry/types.ts +0 -75
  189. package/src/support/CSATSurvey.tsx +0 -304
  190. package/src/support/EscalationEventSource.ts +0 -190
  191. package/src/support/EscalationSocket.ts +0 -152
  192. package/src/support/SupportChatModal.tsx +0 -563
  193. package/src/support/SupportGreeting.tsx +0 -161
  194. package/src/support/TicketStore.ts +0 -100
  195. package/src/support/escalateTool.ts +0 -174
  196. package/src/support/index.ts +0 -29
  197. package/src/support/supportPrompt.ts +0 -55
  198. package/src/support/types.ts +0 -155
  199. package/src/tools/datePickerTool.ts +0 -60
  200. package/src/tools/guideTool.ts +0 -76
  201. package/src/tools/index.ts +0 -20
  202. package/src/tools/keyboardTool.ts +0 -30
  203. package/src/tools/longPressTool.ts +0 -61
  204. package/src/tools/pickerTool.ts +0 -115
  205. package/src/tools/restoreTool.ts +0 -33
  206. package/src/tools/scrollTool.ts +0 -156
  207. package/src/tools/simplifyTool.ts +0 -33
  208. package/src/tools/sliderTool.ts +0 -65
  209. package/src/tools/tapTool.ts +0 -93
  210. package/src/tools/typeTool.ts +0 -113
  211. package/src/tools/types.ts +0 -58
  212. package/src/types/jsx.d.ts +0 -20
  213. package/src/utils/audioUtils.ts +0 -54
  214. package/src/utils/logger.ts +0 -38
@@ -1,78 +0,0 @@
1
- /**
2
- * AgentErrorBoundary — Catches React rendering errors caused by AI agent actions.
3
- *
4
- * When the AI taps, scrolls, or navigates, the action itself may succeed
5
- * but trigger async side-effects (useEffect, onViewableItemsChanged) that
6
- * crash during the next React render cycle. This boundary catches those
7
- * errors, preventing red screen crashes and auto-recovering the UI.
8
- *
9
- * Recovery strategy:
10
- * 1. Catch the error via getDerivedStateFromError
11
- * 2. Log it and report to agent runtime via onError callback
12
- * 3. Auto-reset after a brief delay — remounts children cleanly
13
- */
14
-
15
- import React from 'react';
16
- import { logger } from '../utils/logger';
17
-
18
- interface Props {
19
- children: React.ReactNode;
20
- /** Called when an error is caught — reports back to agent runtime */
21
- onError?: (error: Error, componentStack?: string) => void;
22
- telemetryRef?: React.RefObject<any>; // Using any to avoid circular import, we duck-type track()
23
- }
24
-
25
- interface State {
26
- hasError: boolean;
27
- }
28
-
29
- export class AgentErrorBoundary extends React.Component<Props, State> {
30
- state: State = { hasError: false };
31
- private resetTimer: ReturnType<typeof setTimeout> | null = null;
32
-
33
- static getDerivedStateFromError(_error: Error): State {
34
- return { hasError: true };
35
- }
36
-
37
- componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
38
- const componentStack = errorInfo?.componentStack || '';
39
- logger.warn(
40
- 'AgentErrorBoundary',
41
- `🛡️ Caught rendering error: ${error.message}\n${componentStack}`
42
- );
43
- this.props.onError?.(error, componentStack);
44
-
45
- // Track the render error silently in analytics
46
- if (this.props.telemetryRef?.current?.track) {
47
- this.props.telemetryRef.current.track('render_error', {
48
- message: error.message,
49
- component: componentStack?.split('\n')[1]?.trim() ?? 'unknown',
50
- screen: this.props.telemetryRef.current.screen,
51
- });
52
- }
53
- }
54
-
55
- componentDidUpdate(_prevProps: Props, prevState: State): void {
56
- // Auto-recover: reset error state after brief delay to remount children
57
- if (this.state.hasError && !prevState.hasError) {
58
- this.resetTimer = setTimeout(() => {
59
- this.setState({ hasError: false });
60
- }, 50);
61
- }
62
- }
63
-
64
- componentWillUnmount(): void {
65
- if (this.resetTimer) {
66
- clearTimeout(this.resetTimer);
67
- }
68
- }
69
-
70
- render(): React.ReactNode {
71
- if (this.state.hasError) {
72
- // Return null briefly — children will remount on next tick
73
- // when hasError resets to false via componentDidUpdate
74
- return null;
75
- }
76
- return this.props.children;
77
- }
78
- }
@@ -1,73 +0,0 @@
1
- /**
2
- * AgentOverlay — Subtle thinking indicator shown while the AI agent is processing.
3
- * Includes a cancel button to stop the agent mid-execution.
4
- */
5
-
6
- import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity } from 'react-native';
7
- import { CloseIcon } from './Icons';
8
-
9
- interface AgentOverlayProps {
10
- visible: boolean;
11
- statusText: string;
12
- onCancel?: () => void;
13
- }
14
-
15
- export function AgentOverlay({ visible, statusText, onCancel }: AgentOverlayProps) {
16
- if (!visible) return null;
17
-
18
- return (
19
- <View style={styles.overlay} pointerEvents="box-none">
20
- <View style={styles.pill}>
21
- <ActivityIndicator size="small" color="#fff" />
22
- <Text style={styles.text}>{statusText || 'Thinking...'}</Text>
23
- {onCancel && (
24
- <TouchableOpacity
25
- onPress={onCancel}
26
- style={styles.cancelButton}
27
- hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
28
- >
29
- <CloseIcon size={12} color="#fff" />
30
- </TouchableOpacity>
31
- )}
32
- </View>
33
- </View>
34
- );
35
- }
36
-
37
- const styles = StyleSheet.create({
38
- overlay: {
39
- position: 'absolute',
40
- top: 60,
41
- left: 0,
42
- right: 0,
43
- alignItems: 'center',
44
- zIndex: 9999,
45
- },
46
- pill: {
47
- flexDirection: 'row',
48
- alignItems: 'center',
49
- gap: 8,
50
- backgroundColor: 'rgba(26, 26, 46, 0.9)',
51
- paddingHorizontal: 16,
52
- paddingVertical: 10,
53
- borderRadius: 20,
54
- maxWidth: '85%',
55
- },
56
- text: {
57
- color: '#fff',
58
- fontSize: 14,
59
- fontWeight: '500',
60
- flexShrink: 1,
61
- },
62
- cancelButton: {
63
- marginLeft: 4,
64
- width: 22,
65
- height: 22,
66
- borderRadius: 11,
67
- backgroundColor: 'rgba(255, 255, 255, 0.2)',
68
- alignItems: 'center',
69
- justifyContent: 'center',
70
- flexShrink: 0,
71
- },
72
- });
73
-
@@ -1,148 +0,0 @@
1
- /**
2
- * DiscoveryTooltip — One-time tooltip shown above the FAB on first use.
3
- *
4
- * Tells users the AI can navigate the app and do things for them.
5
- * Shows once, then persists dismissal via AsyncStorage.
6
- * Bilingual: EN/AR.
7
- */
8
-
9
- import { useEffect, useRef } from 'react';
10
- import {
11
- View,
12
- Text,
13
- Pressable,
14
- StyleSheet,
15
- Animated,
16
- } from 'react-native';
17
-
18
- interface DiscoveryTooltipProps {
19
- language: 'en' | 'ar';
20
- primaryColor?: string;
21
- onDismiss: () => void;
22
- }
23
-
24
- const LABELS = {
25
- en: '✨ I can help you navigate the app and do things for you!',
26
- ar: '✨ أقدر أساعدك تتنقل في التطبيق وأعمل حاجات بدالك!',
27
- };
28
-
29
- const AUTO_DISMISS_MS = 6000;
30
-
31
- export function DiscoveryTooltip({
32
- language,
33
- primaryColor,
34
- onDismiss,
35
- }: DiscoveryTooltipProps) {
36
- const scaleAnim = useRef(new Animated.Value(0)).current;
37
- const opacityAnim = useRef(new Animated.Value(0)).current;
38
-
39
- useEffect(() => {
40
- // Spring-in entry
41
- Animated.parallel([
42
- Animated.spring(scaleAnim, {
43
- toValue: 1,
44
- friction: 6,
45
- tension: 80,
46
- useNativeDriver: true,
47
- }),
48
- Animated.timing(opacityAnim, {
49
- toValue: 1,
50
- duration: 200,
51
- useNativeDriver: true,
52
- }),
53
- ]).start();
54
-
55
- // Auto-dismiss after timeout
56
- const timer = setTimeout(() => {
57
- dismissWithAnimation();
58
- }, AUTO_DISMISS_MS);
59
-
60
- return () => clearTimeout(timer);
61
- // eslint-disable-next-line react-hooks/exhaustive-deps
62
- }, []);
63
-
64
- const dismissWithAnimation = () => {
65
- Animated.parallel([
66
- Animated.timing(scaleAnim, {
67
- toValue: 0,
68
- duration: 200,
69
- useNativeDriver: true,
70
- }),
71
- Animated.timing(opacityAnim, {
72
- toValue: 0,
73
- duration: 200,
74
- useNativeDriver: true,
75
- }),
76
- ]).start(() => onDismiss());
77
- };
78
-
79
- const isArabic = language === 'ar';
80
- const bgColor = primaryColor || '#1a1a2e';
81
-
82
- return (
83
- <Animated.View
84
- style={[
85
- styles.container,
86
- {
87
- backgroundColor: bgColor,
88
- transform: [{ scale: scaleAnim }],
89
- opacity: opacityAnim,
90
- },
91
- ]}
92
- >
93
- <Pressable onPress={dismissWithAnimation} style={styles.contentArea}>
94
- <Text style={[styles.text, isArabic && styles.textRTL]}>
95
- {LABELS[language]}
96
- </Text>
97
- </Pressable>
98
-
99
- {/* Triangle pointer toward FAB */}
100
- <View style={[styles.pointer, { borderTopColor: bgColor }]} />
101
- </Animated.View>
102
- );
103
- }
104
-
105
- const styles = StyleSheet.create({
106
- container: {
107
- position: 'absolute',
108
- bottom: 70,
109
- right: -4,
110
- minWidth: 200,
111
- maxWidth: 260,
112
- borderRadius: 16,
113
- paddingHorizontal: 14,
114
- paddingVertical: 10,
115
- shadowColor: '#000',
116
- shadowOffset: { width: 0, height: 4 },
117
- shadowOpacity: 0.3,
118
- shadowRadius: 8,
119
- elevation: 6,
120
- },
121
- contentArea: {
122
- flexDirection: 'row',
123
- alignItems: 'center',
124
- },
125
- text: {
126
- color: '#ffffff',
127
- fontSize: 13,
128
- lineHeight: 19,
129
- fontWeight: '500',
130
- },
131
- textRTL: {
132
- textAlign: 'right',
133
- writingDirection: 'rtl',
134
- },
135
- pointer: {
136
- position: 'absolute',
137
- bottom: -8,
138
- right: 22,
139
- width: 0,
140
- height: 0,
141
- borderLeftWidth: 8,
142
- borderRightWidth: 8,
143
- borderTopWidth: 8,
144
- borderLeftColor: 'transparent',
145
- borderRightColor: 'transparent',
146
- borderTopColor: '#1a1a2e',
147
- },
148
- });
@@ -1,136 +0,0 @@
1
- import { useEffect, useState, useRef } from 'react';
2
- import { View, Text, StyleSheet, Animated, Pressable, DeviceEventEmitter } from 'react-native';
3
-
4
- export interface HighlightEventData {
5
- pageX: number;
6
- pageY: number;
7
- width: number;
8
- height: number;
9
- message: string;
10
- autoRemoveAfterMs?: number;
11
- }
12
-
13
- export function HighlightOverlay() {
14
- const [highlight, setHighlight] = useState<HighlightEventData | null>(null);
15
- const pulseAnim = useRef(new Animated.Value(1)).current;
16
- const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
17
-
18
- useEffect(() => {
19
- const sub = DeviceEventEmitter.addListener('MOBILE_AI_HIGHLIGHT', (data: HighlightEventData | null) => {
20
- if (timerRef.current) clearTimeout(timerRef.current);
21
-
22
- setHighlight(data);
23
-
24
- if (data) {
25
- // Start pulsing ring
26
- pulseAnim.setValue(1);
27
- Animated.loop(
28
- Animated.sequence([
29
- Animated.timing(pulseAnim, { toValue: 1.2, duration: 800, useNativeDriver: true }),
30
- Animated.timing(pulseAnim, { toValue: 1, duration: 800, useNativeDriver: true }),
31
- ])
32
- ).start();
33
-
34
- // Auto-dismiss
35
- const ms = data.autoRemoveAfterMs || 5000;
36
- timerRef.current = setTimeout(() => {
37
- setHighlight(null);
38
- }, ms);
39
- }
40
- });
41
-
42
- return () => sub.remove();
43
- }, [pulseAnim]);
44
-
45
- if (!highlight) return null;
46
-
47
- const { pageX, pageY, width, height, message } = highlight;
48
-
49
- // Calculate tooltip position (prefer top, fallback to bottom if too close to top edge)
50
- const isTooHigh = pageY < 60;
51
- const tooltipTop = isTooHigh ? pageY + height + 12 : pageY - 45;
52
-
53
- return (
54
- <View style={StyleSheet.absoluteFill} pointerEvents="box-none">
55
- {/* Invisible pressable to dismiss on tap anywhere */}
56
- <Pressable testID="highlight-close-zone" style={StyleSheet.absoluteFill} onPress={() => setHighlight(null)} />
57
-
58
- {/* The Animated Ring */}
59
- <Animated.View
60
- style={[
61
- styles.ring,
62
- {
63
- left: pageX - 4,
64
- top: pageY - 4,
65
- width: width + 8,
66
- height: height + 8,
67
- transform: [{ scale: pulseAnim }],
68
- }
69
- ]}
70
- pointerEvents="none"
71
- />
72
-
73
- {/* The Tooltip */}
74
- <View style={[styles.tooltip, { top: tooltipTop }]} pointerEvents="none">
75
- <Text style={styles.message}>{message}</Text>
76
- <View style={isTooHigh ? styles.arrowUp : styles.arrowDown} />
77
- </View>
78
- </View>
79
- );
80
- }
81
-
82
- const styles = StyleSheet.create({
83
- ring: {
84
- position: 'absolute',
85
- borderWidth: 3,
86
- borderColor: '#007AFF', // iOS blue
87
- borderRadius: 8,
88
- backgroundColor: 'rgba(0, 122, 255, 0.15)', // Very subtle fill
89
- },
90
- tooltip: {
91
- position: 'absolute',
92
- alignSelf: 'center',
93
- backgroundColor: '#007AFF',
94
- paddingHorizontal: 12,
95
- paddingVertical: 8,
96
- borderRadius: 8,
97
- maxWidth: '80%',
98
- shadowColor: '#000',
99
- shadowOpacity: 0.2,
100
- shadowOffset: { width: 0, height: 2 },
101
- shadowRadius: 4,
102
- elevation: 4,
103
- },
104
- message: {
105
- color: '#fff',
106
- fontSize: 14,
107
- fontWeight: 'bold',
108
- textAlign: 'center',
109
- },
110
- arrowDown: {
111
- position: 'absolute',
112
- bottom: -6,
113
- alignSelf: 'center',
114
- width: 0,
115
- height: 0,
116
- borderLeftWidth: 6,
117
- borderRightWidth: 6,
118
- borderTopWidth: 6,
119
- borderLeftColor: 'transparent',
120
- borderRightColor: 'transparent',
121
- borderTopColor: '#007AFF',
122
- },
123
- arrowUp: {
124
- position: 'absolute',
125
- top: -6,
126
- alignSelf: 'center',
127
- width: 0,
128
- height: 0,
129
- borderLeftWidth: 6,
130
- borderRightWidth: 6,
131
- borderBottomWidth: 6,
132
- borderLeftColor: 'transparent',
133
- borderRightColor: 'transparent',
134
- borderBottomColor: '#007AFF',
135
- }
136
- });
@@ -1,253 +0,0 @@
1
- /**
2
- * Icons — Zero-dependency, View-based icons for the AI Agent chat bar.
3
- *
4
- * Why not emoji? iOS Simulator 26+ has a bug where emoji renders as "?".
5
- * Why not Unicode symbols? They look obscure and unprofessional.
6
- * Why not icon libraries? This is a library — zero runtime dependencies.
7
- *
8
- * These icons are built purely from React Native View components,
9
- * rendering identically on every platform and screen size.
10
- */
11
-
12
- import { View } from 'react-native';
13
-
14
- // ─── Mic Icon (pill + stem + base) ────────────────────────────
15
-
16
- export function MicIcon({ size = 20, color = '#fff' }: { size?: number; color?: string }) {
17
- const pillW = size * 0.4;
18
- const pillH = size * 0.5;
19
- const stemW = size * 0.08;
20
- const stemH = size * 0.18;
21
- const baseW = size * 0.35;
22
- const arcW = size * 0.55;
23
- const arcH = size * 0.35;
24
- const arcBorder = size * 0.07;
25
-
26
- return (
27
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
28
- {/* Pill (mic head) */}
29
- <View style={{
30
- width: pillW,
31
- height: pillH,
32
- borderRadius: pillW / 2,
33
- backgroundColor: color,
34
- }} />
35
- {/* Arc (U-shape around mic) */}
36
- <View style={{
37
- width: arcW,
38
- height: arcH,
39
- borderBottomLeftRadius: arcW / 2,
40
- borderBottomRightRadius: arcW / 2,
41
- borderWidth: arcBorder,
42
- borderTopWidth: 0,
43
- borderColor: color,
44
- marginTop: -(pillH * 0.3),
45
- }} />
46
- {/* Stem */}
47
- <View style={{
48
- width: stemW,
49
- height: stemH,
50
- backgroundColor: color,
51
- marginTop: -1,
52
- }} />
53
- {/* Base */}
54
- <View style={{
55
- width: baseW,
56
- height: stemW,
57
- backgroundColor: color,
58
- borderRadius: stemW / 2,
59
- }} />
60
- </View>
61
- );
62
- }
63
-
64
- // ─── Speaker Icon (cone + sound waves) ────────────────────────
65
-
66
- export function SpeakerIcon({ size = 20, color = '#fff', muted = false }: { size?: number; color?: string; muted?: boolean }) {
67
- const bodyW = size * 0.25;
68
- const bodyH = size * 0.3;
69
- const coneW = size * 0.2;
70
-
71
- return (
72
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center', flexDirection: 'row' }}>
73
- {/* Speaker body (rectangle) */}
74
- <View style={{
75
- width: bodyW,
76
- height: bodyH,
77
- backgroundColor: color,
78
- borderRadius: size * 0.03,
79
- }} />
80
- {/* Speaker cone (triangle via borders) */}
81
- <View style={{
82
- width: 0,
83
- height: 0,
84
- borderTopWidth: size * 0.25,
85
- borderTopColor: 'transparent',
86
- borderBottomWidth: size * 0.25,
87
- borderBottomColor: 'transparent',
88
- borderLeftWidth: coneW,
89
- borderLeftColor: color,
90
- marginLeft: -1,
91
- }} />
92
- {muted ? (
93
- /* Mute slash */
94
- <View style={{
95
- position: 'absolute',
96
- width: size * 0.08,
97
- height: size * 0.8,
98
- backgroundColor: color,
99
- borderRadius: size * 0.04,
100
- transform: [{ rotate: '45deg' }],
101
- }} />
102
- ) : (
103
- /* Sound waves */
104
- <View style={{ marginLeft: size * 0.05 }}>
105
- <View style={{
106
- width: size * 0.15,
107
- height: size * 0.3,
108
- borderWidth: size * 0.05,
109
- borderColor: color,
110
- borderLeftWidth: 0,
111
- borderTopLeftRadius: 0,
112
- borderBottomLeftRadius: 0,
113
- borderTopRightRadius: size * 0.15,
114
- borderBottomRightRadius: size * 0.15,
115
- }} />
116
- </View>
117
- )}
118
- </View>
119
- );
120
- }
121
-
122
- // ─── Send Arrow (upward arrow) ────────────────────────────────
123
-
124
- export function SendArrowIcon({ size = 18, color = '#fff' }: { size?: number; color?: string }) {
125
- // Filled right-pointing triangle (like iOS Messages send button)
126
- const triH = size * 0.55;
127
- return (
128
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
129
- <View style={{
130
- width: 0,
131
- height: 0,
132
- borderTopWidth: triH / 2,
133
- borderTopColor: 'transparent',
134
- borderBottomWidth: triH / 2,
135
- borderBottomColor: 'transparent',
136
- borderLeftWidth: triH * 0.85,
137
- borderLeftColor: color,
138
- marginLeft: size * 0.1,
139
- }} />
140
- </View>
141
- );
142
- }
143
-
144
- // ─── Stop Icon (filled square) ────────────────────────────────
145
-
146
- export function StopIcon({ size = 18, color = '#fff' }: { size?: number; color?: string }) {
147
- const sq = size * 0.45;
148
- return (
149
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
150
- <View style={{
151
- width: sq,
152
- height: sq,
153
- backgroundColor: color,
154
- borderRadius: size * 0.05,
155
- }} />
156
- </View>
157
- );
158
- }
159
-
160
- // ─── Recording Dot (pulsing filled circle) ────────────────────
161
-
162
- export function RecordingDot({ size = 18, color = '#FF3B30' }: { size?: number; color?: string }) {
163
- const dotSize = size * 0.45;
164
- return (
165
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
166
- <View style={{
167
- width: dotSize,
168
- height: dotSize,
169
- borderRadius: dotSize / 2,
170
- backgroundColor: color,
171
- }} />
172
- </View>
173
- );
174
- }
175
-
176
- // ─── Loading Spinner (three dots) ─────────────────────────────
177
-
178
- export function LoadingDots({ size = 18, color = '#fff' }: { size?: number; color?: string }) {
179
- const dotSize = size * 0.15;
180
- return (
181
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center', flexDirection: 'row', gap: dotSize * 0.8 }}>
182
- {[0.4, 0.7, 1].map((opacity, i) => (
183
- <View key={i} style={{
184
- width: dotSize,
185
- height: dotSize,
186
- borderRadius: dotSize / 2,
187
- backgroundColor: color,
188
- opacity,
189
- }} />
190
- ))}
191
- </View>
192
- );
193
- }
194
-
195
- // ─── Close / Dismiss (X mark) ─────────────────────────────────
196
-
197
- export function CloseIcon({ size = 14, color = 'rgba(255,255,255,0.6)' }: { size?: number; color?: string }) {
198
- const barW = size * 0.7;
199
- const barH = size * 0.12;
200
- return (
201
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
202
- <View style={{
203
- position: 'absolute',
204
- width: barW,
205
- height: barH,
206
- backgroundColor: color,
207
- borderRadius: barH,
208
- transform: [{ rotate: '45deg' }],
209
- }} />
210
- <View style={{
211
- position: 'absolute',
212
- width: barW,
213
- height: barH,
214
- backgroundColor: color,
215
- borderRadius: barH,
216
- transform: [{ rotate: '-45deg' }],
217
- }} />
218
- </View>
219
- );
220
- }
221
-
222
- // ─── AI Badge (for FAB) ───────────────────────────────────────
223
-
224
- export function AIBadge({ size = 28 }: { size?: number }) {
225
- // Chat bubble — clean, universally represents AI assistant
226
- const bubbleW = size * 0.6;
227
- const bubbleH = size * 0.45;
228
- const tailSize = size * 0.12;
229
- return (
230
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
231
- {/* Bubble body */}
232
- <View style={{
233
- width: bubbleW,
234
- height: bubbleH,
235
- backgroundColor: '#fff',
236
- borderRadius: size * 0.12,
237
- marginBottom: tailSize * 0.5,
238
- }} />
239
- {/* Tail (small triangle at bottom-left) */}
240
- <View style={{
241
- position: 'absolute',
242
- bottom: size * 0.18,
243
- left: size * 0.22,
244
- width: 0,
245
- height: 0,
246
- borderTopWidth: tailSize,
247
- borderTopColor: '#fff',
248
- borderRightWidth: tailSize,
249
- borderRightColor: 'transparent',
250
- }} />
251
- </View>
252
- );
253
- }