feat(ui): 更新应用品牌名称为 Out Live 并优化睡眠详情页默认数据展示
- 将 Sealife 更名为 Out Live(登录页、隐私弹窗) - 睡眠详情页无数据时显示 "--" 替代固定默认值 - 移除睡眠阶段卡片中的质量标签与总览徽章 - 修复体重历史卡片依赖监听字段与跳转路由 - 调整喝水提醒后台任务时间范围为 8-21 点 - 标签栏按钮新增 activeOpacity=1 禁用点击透明度变化
This commit is contained in:
@@ -61,6 +61,7 @@ export default function TabLayout() {
|
|||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={handlePress}
|
onPress={handlePress}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
|
activeOpacity={1}
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|||||||
@@ -223,8 +223,8 @@ export default function LoginScreen() {
|
|||||||
|
|
||||||
<ScrollView contentContainerStyle={styles.content} showsVerticalScrollIndicator={false}>
|
<ScrollView contentContainerStyle={styles.content} showsVerticalScrollIndicator={false}>
|
||||||
<View style={styles.headerWrap}>
|
<View style={styles.headerWrap}>
|
||||||
<ThemedText style={[styles.title, { color: color.text }]}>Sealife</ThemedText>
|
<ThemedText style={[styles.title, { color: color.text }]}>Out Live</ThemedText>
|
||||||
<ThemedText style={[styles.subtitle, { color: color.textMuted }]}>欢迎登录Sealife</ThemedText>
|
<ThemedText style={[styles.subtitle, { color: color.textMuted }]}>欢迎登录Out Live</ThemedText>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Apple 登录 */}
|
{/* Apple 登录 */}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { ThemedView } from '@/components/ThemedView';
|
||||||
import {
|
import {
|
||||||
fetchCompleteSleepData,
|
fetchCompleteSleepData,
|
||||||
formatSleepTime,
|
formatSleepTime,
|
||||||
@@ -18,7 +19,6 @@ import {
|
|||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
View
|
View
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { ThemedView } from '@/components/ThemedView';
|
|
||||||
|
|
||||||
import { InfoModal, type SleepDetailData } from '@/components/sleep/InfoModal';
|
import { InfoModal, type SleepDetailData } from '@/components/sleep/InfoModal';
|
||||||
import { SleepStagesInfoModal } from '@/components/sleep/SleepStagesInfoModal';
|
import { SleepStagesInfoModal } from '@/components/sleep/SleepStagesInfoModal';
|
||||||
@@ -38,7 +38,7 @@ export default function SleepDetailScreen() {
|
|||||||
const colorTokens = Colors[theme];
|
const colorTokens = Colors[theme];
|
||||||
const [sleepData, setSleepData] = useState<CompleteSleepData | null>(null);
|
const [sleepData, setSleepData] = useState<CompleteSleepData | null>(null);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
// 从导航参数获取日期,如果没有则使用今天
|
// 从导航参数获取日期,如果没有则使用今天
|
||||||
const { date: dateParam } = useLocalSearchParams<{ date?: string }>();
|
const { date: dateParam } = useLocalSearchParams<{ date?: string }>();
|
||||||
const [selectedDate] = useState(() => {
|
const [selectedDate] = useState(() => {
|
||||||
@@ -162,11 +162,9 @@ export default function SleepDetailScreen() {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<Text style={[styles.newStatValue, { color: colorTokens.text }]}>
|
<Text style={[styles.newStatValue, { color: colorTokens.text }]}>
|
||||||
{displayData.totalSleepTime > 0 ? formatSleepTime(displayData.totalSleepTime) : '7h 23m'}
|
{displayData.totalSleepTime > 0 ? formatSleepTime(displayData.totalSleepTime) : '--'}
|
||||||
</Text>
|
</Text>
|
||||||
<View style={[styles.qualityBadge, styles.goodQualityBadge]}>
|
|
||||||
<Text style={[styles.qualityBadgeText, styles.goodQualityText]}>✓ 良好</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={[styles.newStatCard, { backgroundColor: colorTokens.background }]}>
|
<View style={[styles.newStatCard, { backgroundColor: colorTokens.background }]}>
|
||||||
@@ -189,11 +187,8 @@ export default function SleepDetailScreen() {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<Text style={[styles.newStatValue, { color: colorTokens.text }]}>
|
<Text style={[styles.newStatValue, { color: colorTokens.text }]}>
|
||||||
{displayData.sleepQualityPercentage > 0 ? `${displayData.sleepQualityPercentage}%` : '94%'}
|
{displayData.sleepQualityPercentage > 0 ? `${displayData.sleepQualityPercentage}%` : '--%'}
|
||||||
</Text>
|
</Text>
|
||||||
<View style={[styles.qualityBadge, styles.excellentQualityBadge]}>
|
|
||||||
<Text style={[styles.qualityBadgeText, styles.excellentQualityText]}>★ 优秀</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
@@ -228,10 +223,10 @@ export default function SleepDetailScreen() {
|
|||||||
} else {
|
} else {
|
||||||
// 使用默认数据
|
// 使用默认数据
|
||||||
stagesToDisplay = [
|
stagesToDisplay = [
|
||||||
{ stage: SleepStage.Awake, duration: 3, percentage: 1, quality: 'good' as any },
|
{ stage: SleepStage.Awake, duration: 0, percentage: 0, quality: 'good' as any },
|
||||||
{ stage: SleepStage.REM, duration: 89, percentage: 20, quality: 'good' as any },
|
{ stage: SleepStage.REM, duration: 0, percentage: 0, quality: 'good' as any },
|
||||||
{ stage: SleepStage.Core, duration: 295, percentage: 67, quality: 'good' as any },
|
{ stage: SleepStage.Core, duration: 0, percentage: 0, quality: 'good' as any },
|
||||||
{ stage: SleepStage.Deep, duration: 51, percentage: 12, quality: 'poor' as any }
|
{ stage: SleepStage.Deep, duration: 0, percentage: 0, quality: 'poor' as any }
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return stagesToDisplay;
|
return stagesToDisplay;
|
||||||
@@ -269,11 +264,6 @@ export default function SleepDetailScreen() {
|
|||||||
<Text style={[styles.stageCardPercentage, { color: colorTokens.textSecondary }]}>
|
<Text style={[styles.stageCardPercentage, { color: colorTokens.textSecondary }]}>
|
||||||
占总体睡眠的 {stageData.percentage}%
|
占总体睡眠的 {stageData.percentage}%
|
||||||
</Text>
|
</Text>
|
||||||
<View style={[styles.stageCardQuality, { backgroundColor: qualityInfo.bgColor }]}>
|
|
||||||
<Text style={[styles.stageCardQualityText, { color: qualityInfo.color }]}>
|
|
||||||
{qualityInfo.text}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export default function PrivacyConsentModal({
|
|||||||
>
|
>
|
||||||
<View style={styles.overlay}>
|
<View style={styles.overlay}>
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Text style={styles.title}>欢迎来到Sealife</Text>
|
<Text style={styles.title}>欢迎来到Out Live</Text>
|
||||||
|
|
||||||
<View style={styles.contentContainer}>
|
<View style={styles.contentContainer}>
|
||||||
<Text style={styles.description}>
|
<Text style={styles.description}>
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export function WeightHistoryCard() {
|
|||||||
if (hasWeight) {
|
if (hasWeight) {
|
||||||
loadWeightHistory();
|
loadWeightHistory();
|
||||||
}
|
}
|
||||||
}, [hasWeight]);
|
}, [userProfile?.weight]);
|
||||||
|
|
||||||
const loadWeightHistory = async () => {
|
const loadWeightHistory = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -78,7 +78,7 @@ export function WeightHistoryCard() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const navigateToCoach = () => {
|
const navigateToCoach = () => {
|
||||||
pushIfAuthedElseLogin(ROUTES.TAB_COACH);
|
pushIfAuthedElseLogin(ROUTES.WEIGHT_RECORDS);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleShowBMIModal = () => {
|
const handleShowBMIModal = () => {
|
||||||
|
|||||||
@@ -3018,9 +3018,9 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- SocketRocket
|
- SocketRocket
|
||||||
- Yoga
|
- Yoga
|
||||||
- SDWebImage (5.21.1):
|
- SDWebImage (5.21.2):
|
||||||
- SDWebImage/Core (= 5.21.1)
|
- SDWebImage/Core (= 5.21.2)
|
||||||
- SDWebImage/Core (5.21.1)
|
- SDWebImage/Core (5.21.2)
|
||||||
- SDWebImageAVIFCoder (0.11.0):
|
- SDWebImageAVIFCoder (0.11.0):
|
||||||
- libavif/core (>= 0.11.0)
|
- libavif/core (>= 0.11.0)
|
||||||
- SDWebImage (~> 5.10)
|
- SDWebImage (~> 5.10)
|
||||||
@@ -3539,7 +3539,7 @@ SPEC CHECKSUMS:
|
|||||||
RNSentry: f2c39f1113e22413c9bb6e3faa6b27f110d95eaf
|
RNSentry: f2c39f1113e22413c9bb6e3faa6b27f110d95eaf
|
||||||
RNSVG: 6f39605a4c4d200b11435c35bd077553c6b5963a
|
RNSVG: 6f39605a4c4d200b11435c35bd077553c6b5963a
|
||||||
RNWorklets: ad0606bee2a8103c14adb412149789c60b72bfb2
|
RNWorklets: ad0606bee2a8103c14adb412149789c60b72bfb2
|
||||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
SDWebImage: 9f177d83116802728e122410fb25ad88f5c7608a
|
||||||
SDWebImageAVIFCoder: 00310d246aab3232ce77f1d8f0076f8c4b021d90
|
SDWebImageAVIFCoder: 00310d246aab3232ce77f1d8f0076f8c4b021d90
|
||||||
SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c
|
SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c
|
||||||
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
|
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ async function executeWaterReminderTask(): Promise<void> {
|
|||||||
|
|
||||||
// 检查时间限制(避免深夜打扰)
|
// 检查时间限制(避免深夜打扰)
|
||||||
const currentHour = new Date().getHours();
|
const currentHour = new Date().getHours();
|
||||||
if (currentHour < 9 || currentHour >= 21) {
|
if (currentHour < 8 || currentHour >= 21) {
|
||||||
console.log(`当前时间${currentHour}点,不在提醒时间范围内,跳过喝水提醒`);
|
console.log(`当前时间${currentHour}点,不在提醒时间范围内,跳过喝水提醒`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user