207 lines
4.0 KiB
TypeScript
207 lines
4.0 KiB
TypeScript
import Markdown from "@ronradtke/react-native-markdown-display";
|
|
import { memo } from "react";
|
|
import { ActivityIndicator, StyleSheet, View } from "react-native";
|
|
import { CollapsibleMessage } from "@/components/CollapsibleMessage";
|
|
import { colors, monoFont } from "@/lib/theme";
|
|
|
|
type Props = {
|
|
text: string;
|
|
streaming?: boolean;
|
|
};
|
|
|
|
function AssistantMessageComponent({ text, streaming }: Props) {
|
|
if (!text.trim()) {
|
|
if (!streaming) {
|
|
return null;
|
|
}
|
|
return (
|
|
<View style={styles.thinking}>
|
|
<ActivityIndicator size="small" color={colors.textMuted} />
|
|
</View>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<CollapsibleMessage text={text} forceExpanded={streaming} style={styles.container}>
|
|
<Markdown style={markdownStyles} colorScheme="dark">
|
|
{text}
|
|
</Markdown>
|
|
</CollapsibleMessage>
|
|
);
|
|
}
|
|
|
|
export const AssistantMessage = memo(AssistantMessageComponent);
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
alignSelf: "stretch",
|
|
},
|
|
thinking: {
|
|
alignSelf: "flex-start",
|
|
paddingVertical: 4,
|
|
},
|
|
});
|
|
|
|
const markdownStyles = StyleSheet.create({
|
|
body: {
|
|
color: colors.text,
|
|
fontSize: 15,
|
|
lineHeight: 22,
|
|
},
|
|
paragraph: {
|
|
marginTop: 0,
|
|
marginBottom: 10,
|
|
},
|
|
heading1: {
|
|
color: colors.text,
|
|
fontSize: 22,
|
|
fontWeight: "700",
|
|
marginTop: 12,
|
|
marginBottom: 8,
|
|
},
|
|
heading2: {
|
|
color: colors.text,
|
|
fontSize: 19,
|
|
fontWeight: "700",
|
|
marginTop: 12,
|
|
marginBottom: 6,
|
|
},
|
|
heading3: {
|
|
color: colors.text,
|
|
fontSize: 17,
|
|
fontWeight: "700",
|
|
marginTop: 10,
|
|
marginBottom: 6,
|
|
},
|
|
heading4: {
|
|
color: colors.text,
|
|
fontSize: 15,
|
|
fontWeight: "700",
|
|
marginTop: 8,
|
|
marginBottom: 4,
|
|
},
|
|
heading5: {
|
|
color: colors.text,
|
|
fontSize: 15,
|
|
fontWeight: "600",
|
|
},
|
|
heading6: {
|
|
color: colors.textSecondary,
|
|
fontSize: 14,
|
|
fontWeight: "600",
|
|
},
|
|
strong: {
|
|
fontWeight: "700",
|
|
},
|
|
em: {
|
|
fontStyle: "italic",
|
|
},
|
|
link: {
|
|
color: colors.accent,
|
|
textDecorationLine: "underline",
|
|
},
|
|
blockquote: {
|
|
backgroundColor: colors.surfaceDeep,
|
|
borderLeftWidth: 3,
|
|
borderLeftColor: colors.border,
|
|
paddingHorizontal: 12,
|
|
paddingVertical: 4,
|
|
marginVertical: 6,
|
|
borderRadius: 4,
|
|
},
|
|
code_inline: {
|
|
backgroundColor: colors.surface,
|
|
color: colors.accent,
|
|
fontFamily: monoFont,
|
|
fontSize: 13,
|
|
borderRadius: 4,
|
|
paddingHorizontal: 4,
|
|
},
|
|
code_block: {
|
|
backgroundColor: colors.surfaceDeep,
|
|
borderColor: colors.border,
|
|
borderWidth: 1,
|
|
borderRadius: 8,
|
|
color: colors.text,
|
|
fontFamily: monoFont,
|
|
fontSize: 12.5,
|
|
lineHeight: 18,
|
|
padding: 10,
|
|
marginVertical: 6,
|
|
},
|
|
fence: {
|
|
backgroundColor: colors.surfaceDeep,
|
|
borderColor: colors.border,
|
|
borderWidth: 1,
|
|
borderRadius: 8,
|
|
overflow: "hidden",
|
|
marginVertical: 6,
|
|
},
|
|
fence_header: {
|
|
backgroundColor: colors.surface,
|
|
borderBottomColor: colors.border,
|
|
borderBottomWidth: 1,
|
|
paddingHorizontal: 10,
|
|
paddingVertical: 4,
|
|
},
|
|
fence_code: {
|
|
backgroundColor: colors.surfaceDeep,
|
|
padding: 10,
|
|
},
|
|
fence_language_label: {
|
|
color: colors.textMuted,
|
|
fontFamily: monoFont,
|
|
fontSize: 11,
|
|
},
|
|
fence_copy_text: {
|
|
color: colors.textMuted,
|
|
fontSize: 11,
|
|
},
|
|
fence_token: {
|
|
color: colors.text,
|
|
fontFamily: monoFont,
|
|
fontSize: 12.5,
|
|
lineHeight: 18,
|
|
},
|
|
bullet_list: {
|
|
marginBottom: 10,
|
|
},
|
|
ordered_list: {
|
|
marginBottom: 10,
|
|
},
|
|
list_item: {
|
|
flexDirection: "row",
|
|
marginBottom: 4,
|
|
},
|
|
bullet_list_icon: {
|
|
color: colors.textMuted,
|
|
marginRight: 8,
|
|
},
|
|
ordered_list_icon: {
|
|
color: colors.textMuted,
|
|
marginRight: 8,
|
|
},
|
|
hr: {
|
|
backgroundColor: colors.border,
|
|
height: 1,
|
|
marginVertical: 12,
|
|
},
|
|
table: {
|
|
borderWidth: 1,
|
|
borderColor: colors.border,
|
|
borderRadius: 6,
|
|
marginVertical: 6,
|
|
},
|
|
th: {
|
|
padding: 6,
|
|
fontWeight: "700",
|
|
},
|
|
td: {
|
|
padding: 6,
|
|
},
|
|
tr: {
|
|
borderBottomWidth: 1,
|
|
borderColor: colors.borderSubtle,
|
|
},
|
|
});
|