@10play/expo-air 0.12.0 → 0.12.2
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/cli/dist/server/gitOperations.d.ts +31 -0
- package/cli/dist/server/gitOperations.d.ts.map +1 -0
- package/cli/dist/server/gitOperations.js +232 -0
- package/cli/dist/server/gitOperations.js.map +1 -0
- package/cli/dist/server/promptServer.d.ts +1 -6
- package/cli/dist/server/promptServer.d.ts.map +1 -1
- package/cli/dist/server/promptServer.js +72 -264
- package/cli/dist/server/promptServer.js.map +1 -1
- package/cli/dist/tsconfig.tsbuildinfo +1 -1
- package/cli/dist/types/messages.d.ts +1 -0
- package/cli/dist/types/messages.d.ts.map +1 -1
- package/ios/FloatingBubbleManager.swift +73 -1
- package/ios/widget.jsbundle +12 -6
- package/package.json +1 -1
- package/widget/BubbleContent.tsx +85 -743
- package/widget/components/BranchSwitcher.tsx +205 -40
- package/widget/components/FormattedText.tsx +320 -0
- package/widget/components/Header.tsx +225 -0
- package/widget/components/MessageItems.tsx +308 -0
- package/widget/components/ResponseArea.tsx +32 -617
- package/widget/components/TabBar.tsx +161 -0
- package/widget/services/websocket.ts +1 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import React, { useRef, useEffect } from "react";
|
|
2
|
+
import { View, Text, StyleSheet, TouchableOpacity, Animated, Easing, type TextProps } from "react-native";
|
|
3
|
+
import { SPACING, LAYOUT, COLORS, TYPOGRAPHY, SIZES } from "../constants/design";
|
|
4
|
+
|
|
5
|
+
// Typed animated components for React 19 compatibility
|
|
6
|
+
const AnimatedText = Animated.Text as React.ComponentClass<Animated.AnimatedProps<TextProps>>;
|
|
7
|
+
|
|
8
|
+
export type TabType = "chat" | "changes";
|
|
9
|
+
|
|
10
|
+
interface TabBarProps {
|
|
11
|
+
activeTab: TabType;
|
|
12
|
+
onTabChange: (tab: TabType) => void;
|
|
13
|
+
onNewSession: () => void;
|
|
14
|
+
canStartNew: boolean;
|
|
15
|
+
hasPR: boolean;
|
|
16
|
+
hasChanges: boolean;
|
|
17
|
+
prNumber?: string;
|
|
18
|
+
onCreatePR: () => void;
|
|
19
|
+
onCommit: () => void;
|
|
20
|
+
onViewPR: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function TabBar({
|
|
24
|
+
activeTab,
|
|
25
|
+
onTabChange,
|
|
26
|
+
onNewSession,
|
|
27
|
+
canStartNew,
|
|
28
|
+
hasPR,
|
|
29
|
+
hasChanges,
|
|
30
|
+
prNumber,
|
|
31
|
+
onCreatePR,
|
|
32
|
+
onCommit,
|
|
33
|
+
onViewPR,
|
|
34
|
+
}: TabBarProps) {
|
|
35
|
+
// Determine which CTA to show for Changes tab
|
|
36
|
+
const renderCTA = () => {
|
|
37
|
+
if (activeTab === "chat") {
|
|
38
|
+
return (
|
|
39
|
+
<TouchableOpacity
|
|
40
|
+
onPress={onNewSession}
|
|
41
|
+
style={[styles.ctaButton, !canStartNew && styles.ctaButtonDisabled]}
|
|
42
|
+
disabled={!canStartNew}
|
|
43
|
+
>
|
|
44
|
+
<Text style={[styles.ctaText, !canStartNew && styles.ctaTextDisabled]}>New</Text>
|
|
45
|
+
</TouchableOpacity>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Changes tab - show smart CTA with breathing animation
|
|
50
|
+
if (!hasPR && hasChanges) {
|
|
51
|
+
return <BreathingButton onPress={onCreatePR}>Create PR</BreathingButton>;
|
|
52
|
+
}
|
|
53
|
+
if (hasPR && hasChanges) {
|
|
54
|
+
return <BreathingButton onPress={onCommit}>Commit</BreathingButton>;
|
|
55
|
+
}
|
|
56
|
+
if (hasPR && !hasChanges && prNumber) {
|
|
57
|
+
return <BreathingButton onPress={onViewPR}>#{prNumber}</BreathingButton>;
|
|
58
|
+
}
|
|
59
|
+
return null; // no PR + no changes = nothing
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<View style={styles.tabBar}>
|
|
64
|
+
<View style={styles.tabButtons}>
|
|
65
|
+
<TouchableOpacity onPress={() => onTabChange("chat")}>
|
|
66
|
+
<Text style={[
|
|
67
|
+
styles.tabText,
|
|
68
|
+
activeTab === "chat" ? styles.tabTextActive : styles.tabTextInactive
|
|
69
|
+
]}>
|
|
70
|
+
Chat
|
|
71
|
+
</Text>
|
|
72
|
+
</TouchableOpacity>
|
|
73
|
+
<TouchableOpacity onPress={() => onTabChange("changes")}>
|
|
74
|
+
<Text style={[
|
|
75
|
+
styles.tabText,
|
|
76
|
+
activeTab === "changes" ? styles.tabTextActive : styles.tabTextInactive
|
|
77
|
+
]}>
|
|
78
|
+
Changes
|
|
79
|
+
</Text>
|
|
80
|
+
</TouchableOpacity>
|
|
81
|
+
</View>
|
|
82
|
+
{renderCTA()}
|
|
83
|
+
</View>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function BreathingButton({ children, onPress }: React.PropsWithChildren<{ onPress: () => void }>) {
|
|
88
|
+
const opacityAnim = useRef(new Animated.Value(0.6)).current;
|
|
89
|
+
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
const animation = Animated.loop(
|
|
92
|
+
Animated.sequence([
|
|
93
|
+
Animated.timing(opacityAnim, {
|
|
94
|
+
toValue: 0.9,
|
|
95
|
+
duration: 1500,
|
|
96
|
+
easing: Easing.inOut(Easing.ease),
|
|
97
|
+
useNativeDriver: true,
|
|
98
|
+
}),
|
|
99
|
+
Animated.timing(opacityAnim, {
|
|
100
|
+
toValue: 0.6,
|
|
101
|
+
duration: 1500,
|
|
102
|
+
easing: Easing.inOut(Easing.ease),
|
|
103
|
+
useNativeDriver: true,
|
|
104
|
+
}),
|
|
105
|
+
])
|
|
106
|
+
);
|
|
107
|
+
animation.start();
|
|
108
|
+
return () => animation.stop();
|
|
109
|
+
}, [opacityAnim]);
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<TouchableOpacity onPress={onPress} style={styles.ctaButton} activeOpacity={0.7}>
|
|
113
|
+
<AnimatedText style={[styles.ctaText, { opacity: opacityAnim }]}>
|
|
114
|
+
{children}
|
|
115
|
+
</AnimatedText>
|
|
116
|
+
</TouchableOpacity>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const styles = StyleSheet.create({
|
|
121
|
+
tabBar: {
|
|
122
|
+
flexDirection: "row",
|
|
123
|
+
alignItems: "center",
|
|
124
|
+
justifyContent: "space-between",
|
|
125
|
+
paddingHorizontal: LAYOUT.CONTENT_PADDING_H,
|
|
126
|
+
paddingVertical: SPACING.SM + 2, // 10px
|
|
127
|
+
borderBottomWidth: 1,
|
|
128
|
+
borderBottomColor: COLORS.BORDER,
|
|
129
|
+
},
|
|
130
|
+
tabButtons: {
|
|
131
|
+
flexDirection: "row",
|
|
132
|
+
gap: SPACING.XL,
|
|
133
|
+
},
|
|
134
|
+
tabText: {
|
|
135
|
+
fontSize: TYPOGRAPHY.SIZE_LG,
|
|
136
|
+
fontWeight: TYPOGRAPHY.WEIGHT_MEDIUM,
|
|
137
|
+
},
|
|
138
|
+
tabTextActive: {
|
|
139
|
+
color: COLORS.TEXT_PRIMARY,
|
|
140
|
+
},
|
|
141
|
+
tabTextInactive: {
|
|
142
|
+
color: COLORS.TEXT_MUTED,
|
|
143
|
+
},
|
|
144
|
+
ctaButton: {
|
|
145
|
+
paddingHorizontal: SIZES.CTA_PADDING_H,
|
|
146
|
+
paddingVertical: SIZES.CTA_PADDING_V,
|
|
147
|
+
borderRadius: LAYOUT.BORDER_RADIUS_SM,
|
|
148
|
+
backgroundColor: COLORS.BACKGROUND_INTERACTIVE,
|
|
149
|
+
},
|
|
150
|
+
ctaButtonDisabled: {
|
|
151
|
+
opacity: 0.4,
|
|
152
|
+
},
|
|
153
|
+
ctaText: {
|
|
154
|
+
color: COLORS.TEXT_PRIMARY,
|
|
155
|
+
fontSize: TYPOGRAPHY.SIZE_SM,
|
|
156
|
+
fontWeight: TYPOGRAPHY.WEIGHT_SEMIBOLD,
|
|
157
|
+
},
|
|
158
|
+
ctaTextDisabled: {
|
|
159
|
+
opacity: 0.6,
|
|
160
|
+
},
|
|
161
|
+
});
|