Co-authored-by: Claude (Opus 4.6) <claude@hermes.local> Co-committed-by: Claude (Opus 4.6) <claude@hermes.local>
This commit was merged in pull request #88.
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
|
||||
import { ConnectionBadge } from "@/components/ConnectionBadge";
|
||||
import { JobSubmissionSheet } from "@/components/JobSubmissionSheet";
|
||||
import { TimmyFace } from "@/components/TimmyFace";
|
||||
import { Colors } from "@/constants/colors";
|
||||
import { useTimmy } from "@/context/TimmyContext";
|
||||
@@ -64,6 +65,7 @@ export default function FaceScreen() {
|
||||
const [isListening, setIsListening] = useState(false);
|
||||
const [transcript, setTranscript] = useState("");
|
||||
const [lastReply, setLastReply] = useState("");
|
||||
const [jobSheetVisible, setJobSheetVisible] = useState(false);
|
||||
const micScale = useRef(new Animated.Value(1)).current;
|
||||
const micPulseRef = useRef<Animated.CompositeAnimation | null>(null);
|
||||
const webRecognitionRef = useRef<WebSpeechRecognition | null>(null);
|
||||
@@ -273,31 +275,48 @@ export default function FaceScreen() {
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
{/* Mic button */}
|
||||
{/* Action buttons */}
|
||||
<View style={[styles.micArea, { paddingBottom: bottomPad }]}>
|
||||
<Pressable
|
||||
onPress={handleMicPress}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={isListening ? "Stop listening" : "Start voice"}
|
||||
>
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.micButton,
|
||||
isListening && styles.micButtonActive,
|
||||
{ transform: [{ scale: micScale }] },
|
||||
]}
|
||||
<View style={styles.actionRow}>
|
||||
<Pressable
|
||||
onPress={handleMicPress}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={isListening ? "Stop listening" : "Start voice"}
|
||||
>
|
||||
<Ionicons
|
||||
name={isListening ? "mic" : "mic-outline"}
|
||||
size={32}
|
||||
color={isListening ? "#fff" : C.textSecondary}
|
||||
/>
|
||||
</Animated.View>
|
||||
</Pressable>
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.micButton,
|
||||
isListening && styles.micButtonActive,
|
||||
{ transform: [{ scale: micScale }] },
|
||||
]}
|
||||
>
|
||||
<Ionicons
|
||||
name={isListening ? "mic" : "mic-outline"}
|
||||
size={32}
|
||||
color={isListening ? "#fff" : C.textSecondary}
|
||||
/>
|
||||
</Animated.View>
|
||||
</Pressable>
|
||||
|
||||
<Pressable
|
||||
onPress={() => setJobSheetVisible(true)}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Submit paid job"
|
||||
>
|
||||
<View style={styles.jobButton}>
|
||||
<Ionicons name="flash" size={26} color={C.jobStarted} />
|
||||
</View>
|
||||
</Pressable>
|
||||
</View>
|
||||
<Text style={styles.micHint}>
|
||||
{isListening ? "Listening..." : "Tap to speak to Timmy"}
|
||||
{isListening ? "Listening..." : "Tap mic to speak \u00B7 bolt to submit a job"}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<JobSubmissionSheet
|
||||
visible={jobSheetVisible}
|
||||
onClose={() => setJobSheetVisible(false)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -405,6 +424,26 @@ const styles = StyleSheet.create({
|
||||
paddingTop: 16,
|
||||
gap: 10,
|
||||
},
|
||||
actionRow: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: 20,
|
||||
},
|
||||
jobButton: {
|
||||
width: 52,
|
||||
height: 52,
|
||||
borderRadius: 26,
|
||||
backgroundColor: C.surface,
|
||||
borderWidth: 1.5,
|
||||
borderColor: C.jobStarted + "66",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
shadowColor: C.jobStarted,
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
shadowOpacity: 0.25,
|
||||
shadowRadius: 6,
|
||||
elevation: 4,
|
||||
},
|
||||
micButton: {
|
||||
width: 72,
|
||||
height: 72,
|
||||
|
||||
Reference in New Issue
Block a user