feat: 更新心情相关页面和组件

- 在心情统计、日历和编辑页面中引入 HeaderBar 组件,提升界面一致性和用户体验
- 移除冗余的头部视图代码,简化组件结构
- 更新心情日历和编辑页面的样式,使用新的颜色常量,增强视觉效果
- 优化心情统计页面的加载状态显示,提升用户交互体验
This commit is contained in:
richarjiang
2025-08-21 19:09:02 +08:00
parent 72e75b602e
commit 098c65b23e
9 changed files with 78 additions and 107 deletions

View File

@@ -198,49 +198,49 @@ export default function CoachScreen() {
{ {
condition: () => hour >= 5 && hour < 9, condition: () => hour >= 5 && hour < 9,
messages: [ messages: [
`${timeGreeting}${name}我是${botName}你的专属健康管理助手。新的一天开始了,让我们一起为你的健康目标努力吧!`, `${timeGreeting}${name}🐳 我是你的小海豹${botName},新的一天开始啦!让我们一起游向健康目标吧~`,
`${timeGreeting}早晨是制定健康计划的最佳时机,我是${botName}可以帮你管理营养摄入、运动计划和生活作息。`, `${timeGreeting}🌅 早晨的阳光真好呢,我是${botName}你的专属小海豹健康伙伴!要不要先制定今天的健康计划呢?`,
`${timeGreeting}${name}作为你的Seal我很高兴能陪伴你的健康之旅。无论是饮食营养、健身锻炼还是生活管理我都能为你提供专业建议。` `${timeGreeting}${name}🐋 小海豹${botName}来报到啦!今天想从哪个方面开始我们的健康之旅呢?营养、运动还是生活管理,我都可以帮你哦~`
] ]
}, },
{ {
condition: () => hour >= 9 && hour < 12, condition: () => hour >= 9 && hour < 12,
messages: [ messages: [
`${timeGreeting}${name}我是${botName},你的智能健康顾问。上午是身体代谢最活跃的时候,有什么健康目标需要我帮你规划吗?`, `${timeGreeting}${name}🐳 上午是身体最活跃的时候呢,小海豹${botName}在这里为你加油!有什么健康目标需要我帮你规划吗?`,
`${timeGreeting}!工作忙碌的上午,别忘了关注身体健康。我是${botName}可以为你提供营养建议运动指导和压力管理方案。`, `${timeGreeting}☀️ 工作忙碌的上午,别忘了给身体一些关爱哦~我是你的小海豹${botName}随时准备为你提供营养建议运动指导`,
`${timeGreeting}${name}!作为你的健康伙伴${botName},我想说:每一个健康的选择都在塑造更好的你。今天想从哪个方面开始呢?` `${timeGreeting}${name}🐋 作为你的小海豹伙伴${botName},我想说:每一个健康的选择都在让我们的身体更棒呢!今天想从哪个方面开始呢?`
] ]
}, },
{ {
condition: () => hour >= 12 && hour < 14, condition: () => hour >= 12 && hour < 14,
messages: [ messages: [
`${timeGreeting}${name}!午餐时间很关键呢,合理的营养搭配能为下午提供充足能量。我是${botName},可以为你分析饮食营养和热量管理。`, `${timeGreeting}${name}🍽️ 午餐时间到啦!小海豹${botName}提醒你,合理的营养搭配能让下午充满能量哦~`,
`${timeGreeting}!忙碌的上午结束了,该关注一下身体需求啦。我是你的健康助手${botName},无论是饮食调整运动安排还是休息建议,都可以找我`, `${timeGreeting}🌊 忙碌的上午结束了,该给身体补充能量啦!我是你的小海豹${botName},无论是饮食调整还是运动安排,都可以找我商量哦~`,
`${timeGreeting}${name}午间是调整状态的好时机。作为你的Seal建议关注饮食均衡适度放松~` `${timeGreeting}${name}🐳 午间时光,小海豹${botName}建议关注饮食均衡,也要适度放松一下呢`
] ]
}, },
{ {
condition: () => hour >= 14 && hour < 18, condition: () => hour >= 14 && hour < 18,
messages: [ messages: [
`${timeGreeting}${name}!下午是身体活动的黄金时段,适合安排一些运动。我是${botName}可以为你制定个性化的健身计划和身材管理方案。`, `${timeGreeting}${name}🌊 下午是动的黄金时段呢!小海豹${botName}可以为你制定个性化的健身计划,让我们一起游向更好的身材吧~`,
`${timeGreeting}!午后时光,正是关注整体健康的好时机我是你的健康管家${botName},从营养摄入到运动锻炼,我都能为你提供科学指导。`, `${timeGreeting}🐋 午后时光,正是关注健康的好时机我是你的小海豹${botName},从营养到运动,我都能为你提供贴心指导哦~`,
`${timeGreeting}${name}!下午时光,身心健康同样重要作为你的智能健康顾问${botName},我在这里支持你的每一个健康目标` `${timeGreeting}${name}🐳 下午时光,身心健康同样重要呢!作为你的小海豹${botName},我在这里支持你的每一个健康目标`
] ]
}, },
{ {
condition: () => hour >= 18 && hour < 22, condition: () => hour >= 18 && hour < 22,
messages: [ messages: [
`${timeGreeting}${name}!忙碌了一天,现在是时候关注身心平衡了。我是${botName}可以为你提供放松建议、营养补充和恢复方案`, `${timeGreeting}${name}🌙 忙碌了一天,现在是放松身心的好时候呢!小海豹${botName}可以为你提供放松建议和恢复方案哦~`,
`${timeGreeting}!夜幕降临,这是一天中最适合总结和调整的时刻我是你的健康伙伴${botName},让我们一起回顾今天的健康表现,规划明天的目标`, `${timeGreeting}🌊 夜幕降临,这是一天中最适合总结的时刻我是你的小海豹${botName},让我们一起回顾今天的健康表现,规划明天的目标吧~`,
`${timeGreeting}${name}!晚间时光属于你自己,也是关爱身体的珍贵时间作为你的Seal,我想陪你聊聊如何更好地管理健康生活` `${timeGreeting}${name}🐳 晚间时光属于你自己,也是关爱身体的珍贵时间作为你的小海豹${botName},我想陪你聊聊如何更好地管理健康生活呢~`
] ]
}, },
{ {
condition: () => hour >= 22 || hour < 5, condition: () => hour >= 22 || hour < 5,
messages: [ messages: [
`${timeGreeting}${name}!优质睡眠是健康的基石呢。我是${botName},如果需要睡眠优化建议或放松技巧,随时可以问我`, `${timeGreeting}${name}🌙 优质睡眠是健康的基石呢!小海豹${botName}提醒你,如果需要睡眠优化建议,随时可以问我哦~`,
`夜深了,${name}。充足的睡眠对身体恢复和新陈代谢都很重要我是你的健康助手${botName},有什么关于睡眠健康的问题都可以咨询我`, `夜深了,${name}🌊 充足的睡眠对身体恢复很重要呢!我是你的小海豹${botName},有什么关于睡眠健康的问题都可以咨询我`,
`夜深了,愿你能拥有高质量的睡眠。我是${botName},明天我们继续在健康管理的路上同行。晚安,${name}` `夜深了,愿你能拥有甜甜的睡眠。🐳 我是你的小海豹${botName},明天我们继续在健康管理的海洋里同行。晚安,${name}`
] ]
} }
]; ];
@@ -249,11 +249,11 @@ export default function CoachScreen() {
const specialMessages = [ const specialMessages = [
{ {
condition: () => !userProfile?.weight && !userProfile?.height, condition: () => !userProfile?.weight && !userProfile?.height,
message: `你好,${name}我是${botName},你的智能健康管理助手。我注意到你还没有完善健康档案,不如先聊聊你的健康目标和身体状况,这样能为你制定更个性化的健康方案` message: `你好,${name}🐳 我是你的小海豹${botName}我注意到你还没有完善健康档案,不如先聊聊你的健康目标和身体状况,这样小海豹就能为你制定更贴心的健康方案啦~`
}, },
{ {
condition: () => userProfile && (!userProfile.pilatesPurposes || userProfile.pilatesPurposes.length === 0), condition: () => userProfile && (!userProfile.pilatesPurposes || userProfile.pilatesPurposes.length === 0),
message: `${timeGreeting}${name}!作为你的Seal,我想更好地了解你的健康需求告诉我你希望在营养摄入、身材管理、健身锻炼或生活管理方面实现什么目标吧~` message: `${timeGreeting}${name}🐋 作为你的小海豹${botName},我想更好地了解你的健康需求呢!告诉我你希望在营养摄入、身材管理、健身锻炼或生活管理方面实现什么目标吧~`
} }
]; ];
@@ -272,7 +272,7 @@ export default function CoachScreen() {
} }
// 默认消息 // 默认消息
return `你好,我是${botName},你的智能健康管理助手。可以向我咨询营养摄入、身材管理、健身锻炼、生活管理等各方面的健康问题~`; return `你好,我是你的小海豹${botName}!🐳 可以向我咨询营养摄入、身材管理、健身锻炼、生活管理等各方面的健康问题`;
}, [userProfile, params?.name]); }, [userProfile, params?.name]);
const chips = useMemo(() => [ const chips = useMemo(() => [
@@ -605,6 +605,8 @@ export default function CoachScreen() {
} }
async function sendStream(text: string, imageUrls: string[] = []) { async function sendStream(text: string, imageUrls: string[] = []) {
console.log('[SEND_STREAM] 开始发送消息:', { text, imageUrls });
const historyForServer = convertToServerMessages(messages); const historyForServer = convertToServerMessages(messages);
const cid = ensureConversationId(); // 可能返回空字符串 const cid = ensureConversationId(); // 可能返回空字符串
const body = { const body = {
@@ -614,6 +616,7 @@ export default function CoachScreen() {
stream: true, stream: true,
}; };
console.log('[SEND_STREAM] 请求体:', { body });
await sendRequestInternal(body, text, imageUrls); await sendRequestInternal(body, text, imageUrls);
} }
@@ -705,6 +708,13 @@ export default function CoachScreen() {
url, url,
})); }));
console.log('[AI_CHAT][ui] 构建用户消息:', {
userMsgId,
text,
imageUrls,
attachments: attachments.length > 0 ? attachments : undefined
});
const userMsg: ChatMessage = { const userMsg: ChatMessage = {
id: userMsgId, id: userMsgId,
role: 'user', role: 'user',
@@ -1700,17 +1710,22 @@ export default function CoachScreen() {
if (!currentCardId) return; if (!currentCardId) return;
try { try {
console.log('[DIET] 开始上传图片:', { uri: asset.uri, name: asset.fileName });
// 上传图片 // 上传图片
const { url } = await upload( const { url } = await upload(
{ uri: asset.uri, name: `diet-${Date.now()}.jpg`, type: 'image/jpeg' }, { uri: asset.uri, name: `diet-${Date.now()}.jpg`, type: 'image/jpeg' },
{ prefix: 'images/diet' } { prefix: 'images/diet' }
); );
console.log('[DIET] 图片上传成功:', { url });
// 移除饮食选择卡片 // 移除饮食选择卡片
setMessages((prev) => prev.filter(msg => msg.id !== currentCardId)); setMessages((prev) => prev.filter(msg => msg.id !== currentCardId));
// 发送包含图片的饮食记录消息,图片通过 imageUrls 参数传递 // 发送包含图片的饮食记录消息,图片通过 imageUrls 参数传递
const dietMsg = `#记饮食:请分析这张食物照片的营养成分和热量`; const dietMsg = `#记饮食:请分析这张食物照片的营养成分和热量`;
console.log('[DIET] 发送饮食记录消息:', { dietMsg, imageUrls: [url] });
await sendStream(dietMsg, [url]); await sendStream(dietMsg, [url]);
} catch (uploadError) { } catch (uploadError) {
console.error('[DIET] 图片上传失败:', uploadError); console.error('[DIET] 图片上传失败:', uploadError);

View File

@@ -798,10 +798,6 @@ const styles = StyleSheet.create({
justifyContent: 'space-between', justifyContent: 'space-between',
marginBottom: 16, marginBottom: 16,
}, },
compactBMICard: {
width: 140,
minHeight: 110,
},
healthMetricsContainer: { healthMetricsContainer: {
marginBottom: 16, marginBottom: 16,
}, },

View File

@@ -10,8 +10,10 @@ import {
selectMoodRecords, selectMoodRecords,
selectMoodStatistics selectMoodStatistics
} from '@/store/moodSlice'; } from '@/store/moodSlice';
import { HeaderBar } from '@/components/ui/HeaderBar';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { LinearGradient } from 'expo-linear-gradient'; import { LinearGradient } from 'expo-linear-gradient';
import { router } from 'expo-router';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { import {
ActivityIndicator, ActivityIndicator,
@@ -88,8 +90,14 @@ export default function MoodStatisticsScreen() {
end={{ x: 0, y: 1 }} end={{ x: 0, y: 1 }}
/> />
<SafeAreaView style={styles.safeArea}> <SafeAreaView style={styles.safeArea}>
<HeaderBar
title="心情统计"
onBack={() => router.back()}
withSafeTop={false}
transparent={true}
tone="light"
/>
<ScrollView style={styles.scrollView} showsVerticalScrollIndicator={false}> <ScrollView style={styles.scrollView} showsVerticalScrollIndicator={false}>
<Text style={styles.title}></Text>
{loading.history || loading.statistics ? ( {loading.history || loading.statistics ? (
<View style={styles.loadingContainer}> <View style={styles.loadingContainer}>
@@ -184,13 +192,7 @@ const styles = StyleSheet.create({
color: '#666', color: '#666',
textAlign: 'center', textAlign: 'center',
}, },
title: {
fontSize: 28,
fontWeight: '800',
color: '#192126',
marginTop: 24,
marginBottom: 24,
},
loadingContainer: { loadingContainer: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',

View File

@@ -1,3 +1,4 @@
import { HeaderBar } from '@/components/ui/HeaderBar';
import { Colors } from '@/constants/Colors'; import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme'; import { useColorScheme } from '@/hooks/useColorScheme';
import { useMoodData } from '@/hooks/useMoodData'; import { useMoodData } from '@/hooks/useMoodData';
@@ -200,13 +201,13 @@ export default function MoodCalendarScreen() {
end={{ x: 0, y: 1 }} end={{ x: 0, y: 1 }}
/> />
<SafeAreaView style={styles.safeArea}> <SafeAreaView style={styles.safeArea}>
<View style={styles.header}> <HeaderBar
<TouchableOpacity onPress={() => router.back()}> title="心情日历"
<Text style={styles.backButton}></Text> onBack={() => router.back()}
</TouchableOpacity> withSafeTop={false}
<Text style={styles.headerTitle}></Text> transparent={true}
<View style={styles.headerSpacer} /> tone="light"
</View> />
<ScrollView style={styles.content}> <ScrollView style={styles.content}>
{/* 日历视图 */} {/* 日历视图 */}
@@ -347,27 +348,7 @@ const styles = StyleSheet.create({
safeArea: { safeArea: {
flex: 1, flex: 1,
}, },
header: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 20,
paddingVertical: 16,
},
backButton: {
fontSize: 24,
color: '#666',
},
headerTitle: {
fontSize: 20,
fontWeight: '600',
color: '#333',
flex: 1,
textAlign: 'center',
},
headerSpacer: {
width: 24,
},
content: { content: {
flex: 1, flex: 1,
}, },
@@ -430,11 +411,11 @@ const styles = StyleSheet.create({
marginBottom: 8, marginBottom: 8,
}, },
dayButtonSelected: { dayButtonSelected: {
backgroundColor: '#4CAF50', backgroundColor: Colors.light.accentGreen,
}, },
dayButtonToday: { dayButtonToday: {
borderWidth: 2, borderWidth: 2,
borderColor: '#4CAF50', borderColor: Colors.light.accentGreen,
}, },
dayContent: { dayContent: {
position: 'relative', position: 'relative',
@@ -456,7 +437,7 @@ const styles = StyleSheet.create({
fontWeight: '600', fontWeight: '600',
}, },
dayNumberToday: { dayNumberToday: {
color: '#4CAF50', color: Colors.light.accentGreen,
fontWeight: '600', fontWeight: '600',
}, },
dayNumberDisabled: { dayNumberDisabled: {
@@ -520,7 +501,7 @@ const styles = StyleSheet.create({
paddingHorizontal: 16, paddingHorizontal: 16,
height: 32, height: 32,
borderRadius: 16, borderRadius: 16,
backgroundColor: '#4CAF50', backgroundColor: Colors.light.accentGreen,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
}, },
@@ -538,7 +519,7 @@ const styles = StyleSheet.create({
width: 48, width: 48,
height: 48, height: 48,
borderRadius: 24, borderRadius: 24,
backgroundColor: '#4CAF50', backgroundColor: Colors.light.accentGreen,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
marginRight: 12, marginRight: 12,

View File

@@ -1,3 +1,4 @@
import { HeaderBar } from '@/components/ui/HeaderBar';
import { Colors } from '@/constants/Colors'; import { Colors } from '@/constants/Colors';
import { useAppDispatch, useAppSelector } from '@/hooks/redux'; import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { useColorScheme } from '@/hooks/useColorScheme'; import { useColorScheme } from '@/hooks/useColorScheme';
@@ -168,15 +169,13 @@ export default function MoodEditScreen() {
end={{ x: 0, y: 1 }} end={{ x: 0, y: 1 }}
/> />
<SafeAreaView style={styles.safeArea}> <SafeAreaView style={styles.safeArea}>
<View style={styles.header}> <HeaderBar
<TouchableOpacity onPress={() => router.back()}> title={existingMood ? '编辑心情' : '记录心情'}
<Text style={styles.backButton}></Text> onBack={() => router.back()}
</TouchableOpacity> withSafeTop={false}
<Text style={styles.headerTitle}> transparent={true}
{existingMood ? '编辑心情' : '记录心情'} tone="light"
</Text> />
<View style={styles.headerSpacer} />
</View>
<ScrollView style={styles.content}> <ScrollView style={styles.content}>
{/* 日期显示 */} {/* 日期显示 */}
@@ -274,27 +273,7 @@ const styles = StyleSheet.create({
safeArea: { safeArea: {
flex: 1, flex: 1,
}, },
header: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 20,
paddingVertical: 16,
},
backButton: {
fontSize: 24,
color: '#666',
},
headerTitle: {
fontSize: 20,
fontWeight: '600',
color: '#333',
flex: 1,
textAlign: 'center',
},
headerSpacer: {
width: 24,
},
content: { content: {
flex: 1, flex: 1,
}, },
@@ -339,7 +318,7 @@ const styles = StyleSheet.create({
selectedMoodOption: { selectedMoodOption: {
backgroundColor: '#e8f5e8', backgroundColor: '#e8f5e8',
borderWidth: 2, borderWidth: 2,
borderColor: '#4CAF50', borderColor: Colors.light.accentGreen,
}, },
moodEmoji: { moodEmoji: {
fontSize: 24, fontSize: 24,
@@ -378,7 +357,7 @@ const styles = StyleSheet.create({
backgroundColor: '#ddd', backgroundColor: '#ddd',
}, },
intensityDotActive: { intensityDotActive: {
backgroundColor: '#4CAF50', backgroundColor: Colors.light.accentGreen,
}, },
intensityLabels: { intensityLabels: {
flexDirection: 'row', flexDirection: 'row',
@@ -416,7 +395,7 @@ const styles = StyleSheet.create({
backgroundColor: '#fff', backgroundColor: '#fff',
}, },
saveButton: { saveButton: {
backgroundColor: '#4CAF50', backgroundColor: Colors.light.accentGreen,
borderRadius: 12, borderRadius: 12,
paddingVertical: 16, paddingVertical: 16,
alignItems: 'center', alignItems: 'center',

View File

@@ -293,7 +293,6 @@ const styles = StyleSheet.create({
card: { card: {
borderRadius: 22, borderRadius: 22,
padding: 18, padding: 18,
marginBottom: 16,
overflow: 'hidden', overflow: 'hidden',
backgroundColor: '#FFFFFF', backgroundColor: '#FFFFFF',
}, },

View File

@@ -118,9 +118,7 @@ export function FitnessRingsCard({
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
backgroundColor: '#FFFFFF',
borderRadius: 16, borderRadius: 16,
padding: 12,
shadowColor: '#000', shadowColor: '#000',
shadowOffset: { shadowOffset: {
width: 0, width: 0,

View File

@@ -20,6 +20,7 @@ export const palette = {
orange: '#FCC46F', orange: '#FCC46F',
blue: '#87CEEB', // 更贴近logo背景的天空蓝 blue: '#87CEEB', // 更贴近logo背景的天空蓝
blueSecondary: '#4682B4', // 钢蓝色,用于选中状态 blueSecondary: '#4682B4', // 钢蓝色,用于选中状态
green: '#9ceb87', // 温暖的绿色,用于心情日历等
} as const; } as const;
const primaryColor = palette.blue; // 应用主题色 const primaryColor = palette.blue; // 应用主题色
@@ -54,12 +55,12 @@ export const Colors = {
danger: palette.red, danger: palette.red,
info: palette.blue, info: palette.blue,
accentPurple: palette.purple, accentPurple: palette.purple,
accentGreen: palette.blue, accentGreen: palette.green, // 温暖的绿色
accentGreenDark: palette.blueSecondary, // 深绿色,用于文本和强调 accentGreenDark: palette.blueSecondary, // 深绿色,用于文本和强调
// 日期选择器主题色 // 日期选择器主题色
datePickerNormal: palette.blue, datePickerNormal: palette.blue,
datePickerSelected: palette.blueSecondary, datePickerSelected: palette.green, // 使用温暖的绿色作为选中状态
// 结构色(优化后的蓝色主题) // 结构色(优化后的蓝色主题)
border: 'rgba(135,206,235,0.2)', // 蓝色调边框 border: 'rgba(135,206,235,0.2)', // 蓝色调边框
@@ -111,7 +112,7 @@ export const Colors = {
// 日期选择器主题色 // 日期选择器主题色
datePickerNormal: palette.blue, datePickerNormal: palette.blue,
datePickerSelected: palette.blueSecondary, datePickerSelected: palette.green, // 使用温暖的绿色作为选中状态
// 结构色 // 结构色
border: '#2A2F32', border: '#2A2F32',

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="EXPO-VIEWCONTROLLER-1"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="EXPO-VIEWCONTROLLER-1">
<device id="retina6_12" orientation="portrait" appearance="light"/> <device id="retina6_9" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
@@ -14,7 +14,7 @@
<objects> <objects>
<viewController storyboardIdentifier="SplashScreenViewController" id="EXPO-VIEWCONTROLLER-1" sceneMemberID="viewController"> <viewController storyboardIdentifier="SplashScreenViewController" id="EXPO-VIEWCONTROLLER-1" sceneMemberID="viewController">
<view key="view" userInteractionEnabled="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="EXPO-ContainerView" userLabel="ContainerView"> <view key="view" userInteractionEnabled="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="EXPO-ContainerView" userLabel="ContainerView">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/> <rect key="frame" x="0.0" y="0.0" width="440" height="956"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews> <subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" misplaced="YES" image="SplashScreenLogo" translatesAutoresizingMaskIntoConstraints="NO" id="EXPO-SplashScreen" userLabel="SplashScreenLogo"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" misplaced="YES" image="SplashScreenLogo" translatesAutoresizingMaskIntoConstraints="NO" id="EXPO-SplashScreen" userLabel="SplashScreenLogo">