react-native-ajora
Version:
The most complete AI agent UI for React Native
193 lines • 6.88 kB
JavaScript
import { useCallback } from "react";
import { StyleSheet, Text, TouchableOpacity, View, } from "react-native";
import Color from "./Color";
import { useActionSheet } from "@expo/react-native-action-sheet";
import { pickImageAsync, takePictureAsync, filePickerAsync, } from "./utils/mediaUtils";
import { MaterialIcons } from "@expo/vector-icons";
import { useChatContext } from "./AjoraContext";
export function Actions({ options = {
Camera: () => { },
Photo: () => { },
File: () => { },
Cancel: () => { },
}, optionTintColor: _optionTintColor = Color.optionTintColor, icon: _icon, wrapperStyle: _wrapperStyle, iconTextStyle, onPressActionButton, onUpload, }) {
const { showActionSheetWithOptions } = useActionSheet();
const { ajora } = useChatContext();
const { setMode, setAttachement, clearAttachement, attachement } = ajora;
// eslint-disable-next-line react-hooks/exhaustive-deps
const onActionsPress = useCallback(async () => {
const options = ["Camera", "Photo", "File", "Cancel"];
const cancelButtonIndex = options.length - 1;
const onAttachement = async (attachement) => {
const newAttachement = {
displayName: attachement.displayName,
mimeType: attachement.mimeType,
fileUri: attachement.fileUri,
progress: 0,
isUploaded: false,
};
clearAttachement();
setAttachement(newAttachement);
// Call handleUpload with the attachment data directly instead of relying on state
if (onUpload) {
const onProgress = async (progress, isUploaded) => {
ajora.updateAttachement({
...newAttachement,
progress,
isUploaded: isUploaded ?? false,
});
};
try {
await onUpload({
file: {
fileUri: newAttachement.fileUri ?? "",
displayName: newAttachement.displayName ?? "",
mimeType: newAttachement.mimeType ?? "",
},
onProgress: (progress) => {
onProgress?.(progress, progress === 100);
},
onSuccess: (uploadedUrl) => {
console.log("File uploaded successfully", uploadedUrl);
ajora.updateAttachement({
...newAttachement,
fileUri: uploadedUrl,
isUploaded: true,
progress: 100,
});
},
onError: (error) => {
console.error("File upload failed:", error);
clearAttachement();
},
});
}
catch (error) {
console.error("File upload failed:", error);
ajora.updateAttachement({
...newAttachement,
isUploaded: false,
progress: 0,
});
}
}
else {
console.error("[Ajora]: onUpload is not defined");
}
};
showActionSheetWithOptions({
options,
cancelButtonIndex,
}, async (buttonIndex) => {
switch (buttonIndex) {
case 0:
takePictureAsync(onAttachement);
return;
case 1:
pickImageAsync(onAttachement);
return;
case 2:
filePickerAsync(onAttachement);
return;
}
});
}, [showActionSheetWithOptions, clearAttachement, setAttachement]);
if (false) {
onActionsPress();
}
const onModePress = useCallback(() => {
const options = ["Agent", "Assistant"];
showActionSheetWithOptions({
options,
}, async (buttonIndex) => {
switch (buttonIndex) {
case 0:
setMode("agent");
return;
case 1:
setMode("assistant");
return;
default:
return;
}
});
}, [showActionSheetWithOptions, setMode, options]);
const renderIcon = useCallback(() => {
return (<View>
<MaterialIcons name="attach-file" size={18} color={Color.gray700}/>
</View>);
}, []);
return (<View style={styles.actionsContainer}>
<TouchableOpacity style={[styles.attachButton]} onPress={onActionsPress} activeOpacity={0.7}>
{renderIcon()}
</TouchableOpacity>
<TouchableOpacity style={styles.modeButton} onPress={onModePress} activeOpacity={0.7}>
<Text style={[styles.modeText, iconTextStyle]}>
{ajora.mode.charAt(0).toUpperCase() + ajora.mode.slice(1)}
</Text>
</TouchableOpacity>
</View>);
}
const styles = StyleSheet.create({
actionsContainer: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
gap: 8,
paddingHorizontal: 4,
height: 44, // Match the Send button height
},
attachButton: {
width: 36,
height: 36,
backgroundColor: Color.muted,
borderRadius: 12,
borderWidth: 1,
borderColor: Color.border,
alignItems: "center",
justifyContent: "center",
},
modeButton: {
backgroundColor: Color.muted,
borderRadius: 12,
borderWidth: 1,
borderColor: Color.border,
paddingHorizontal: 12,
paddingVertical: 6,
minWidth: 70,
height: 36,
alignItems: "center",
justifyContent: "center",
},
modeText: {
color: Color.gray700,
fontWeight: "600",
fontSize: 13,
lineHeight: 18,
textAlign: "center",
},
// Legacy styles for backward compatibility
container: {
width: 26,
height: 26,
marginLeft: 10,
marginBottom: 10,
},
wrapper: {
borderRadius: 13,
borderColor: Color.defaultColor,
borderWidth: 2,
flex: 1,
alignItems: "center",
justifyContent: "center",
},
iconText: {
color: Color.defaultColor,
fontWeight: "bold",
fontSize: 16,
lineHeight: 16,
backgroundColor: "transparent",
textAlign: "center",
},
});
//# sourceMappingURL=Actions.js.map