feat: Enhance Oxygen Saturation Card with health permissions and loading state management

feat(i18n): Add common translations and mood-related strings in English and Chinese

fix(i18n): Update metabolism titles for consistency in health translations

chore: Update Podfile.lock to include SDWebImage 5.21.4 and other dependency versions

refactor(moodCheckins): Improve mood configuration retrieval with optional translation support

refactor(sleepHealthKit): Replace useI18n with direct i18n import for sleep quality descriptions
This commit is contained in:
2025-11-28 23:48:38 +08:00
parent bca6670390
commit 83b77615cf
19 changed files with 512 additions and 254 deletions

View File

@@ -3,6 +3,7 @@ import { HeaderBar } from '@/components/ui/HeaderBar';
import { Colors } from '@/constants/Colors';
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { useColorScheme } from '@/hooks/useColorScheme';
import { useI18n } from '@/hooks/useI18n';
import { useSafeAreaTop } from '@/hooks/useSafeAreaWithPadding';
import { getMoodOptions, MoodType } from '@/services/moodCheckins';
import {
@@ -31,6 +32,7 @@ import {
} from 'react-native';
export default function MoodEditScreen() {
const { t } = useI18n();
const safeAreaTop = useSafeAreaTop()
const theme = (useColorScheme() ?? 'light') as 'light' | 'dark';
@@ -51,7 +53,7 @@ export default function MoodEditScreen() {
const scrollViewRef = useRef<ScrollView>(null);
const textInputRef = useRef<TextInput>(null);
const moodOptions = getMoodOptions();
const moodOptions = getMoodOptions(t);
// 从 Redux 获取数据
const moodRecords = useAppSelector(selectMoodRecordsByDate(selectedDate));
@@ -95,7 +97,7 @@ export default function MoodEditScreen() {
const handleSave = async () => {
if (!selectedMood) {
Alert.alert('提示', '请选择心情');
Alert.alert(t('common.alert'), t('mood.edit.alerts.selectMood'));
return;
}
@@ -120,12 +122,12 @@ export default function MoodEditScreen() {
})).unwrap();
}
Alert.alert('成功', existingMood ? '心情记录已更新' : '心情记录已保存', [
{ text: '确定', onPress: () => router.back() }
Alert.alert(t('common.success'), existingMood ? t('mood.edit.alerts.updateSuccess') : t('mood.edit.alerts.saveSuccess'), [
{ text: t('common.confirm'), onPress: () => router.back() }
]);
} catch (error) {
console.error('保存心情失败:', error);
Alert.alert('错误', '保存心情失败,请重试');
Alert.alert(t('common.error'), t('mood.edit.alerts.saveError'));
} finally {
setIsLoading(false);
}
@@ -135,24 +137,24 @@ export default function MoodEditScreen() {
if (!existingMood) return;
Alert.alert(
'确认删除',
'确定要删除这条心情记录吗?',
t('mood.edit.alerts.confirmDeleteTitle'),
t('mood.edit.alerts.confirmDelete'),
[
{ text: '取消', style: 'cancel' },
{ text: t('common.cancel'), style: 'cancel' },
{
text: '删除',
text: t('common.delete'),
style: 'destructive',
onPress: async () => {
try {
setIsDeleting(true);
await dispatch(deleteMoodRecord({ id: existingMood.id })).unwrap();
Alert.alert('成功', '心情记录已删除', [
{ text: '确定', onPress: () => router.back() }
Alert.alert(t('common.success'), t('mood.edit.alerts.deleteSuccess'), [
{ text: t('common.confirm'), onPress: () => router.back() }
]);
} catch (error) {
console.error('删除心情失败:', error);
Alert.alert('错误', '删除心情失败,请重试');
Alert.alert(t('common.error'), t('mood.edit.alerts.deleteError'));
} finally {
setIsDeleting(false);
}
@@ -183,7 +185,7 @@ export default function MoodEditScreen() {
<View style={styles.decorativeCircle2} />
<View style={styles.safeArea} >
<HeaderBar
title={existingMood ? '编辑心情' : '记录心情'}
title={existingMood ? t('mood.edit.editTitle') : t('mood.edit.title')}
onBack={() => router.back()}
withSafeTop={false}
transparent={true}
@@ -207,13 +209,13 @@ export default function MoodEditScreen() {
{/* 日期显示 */}
<View style={styles.dateSection}>
<Text style={styles.dateTitle}>
{dayjs(selectedDate).format('YYYY年M月D日')}
{dayjs(selectedDate).format(t('mood.edit.dateFormat'))}
</Text>
</View>
{/* 心情选择 */}
<View style={styles.moodSection}>
<Text style={styles.sectionTitle}></Text>
<Text style={styles.sectionTitle}>{t('mood.edit.selectMood')}</Text>
<View style={styles.moodOptions}>
{moodOptions.map((mood, index) => (
<TouchableOpacity
@@ -233,7 +235,7 @@ export default function MoodEditScreen() {
{/* 心情强度选择 */}
<View style={styles.intensitySection}>
<Text style={styles.sectionTitle}></Text>
<Text style={styles.sectionTitle}>{t('mood.edit.intensity')}</Text>
<MoodIntensitySlider
value={intensity}
onValueChange={handleIntensityChange}
@@ -248,18 +250,12 @@ export default function MoodEditScreen() {
{/* 心情描述 */}
<View style={styles.descriptionSection}>
<Text style={styles.sectionTitle}></Text>
<Text style={styles.diarySubtitle}></Text>
<Text style={styles.sectionTitle}>{t('mood.edit.diary')}</Text>
<Text style={styles.diarySubtitle}>{t('mood.edit.diarySubtitle')}</Text>
<TextInput
ref={textInputRef}
style={styles.descriptionInput}
placeholder={`今天的心情如何?
你经历过什么特别的事情吗?
有什么让你开心的事?
或者,有什么让你感到困扰?
写下你的感受,让这些时刻成为你珍贵的记忆...`}
placeholder={t('mood.edit.placeholder')}
placeholderTextColor="#a8a8a8"
value={description}
onChangeText={setDescription}
@@ -289,7 +285,7 @@ export default function MoodEditScreen() {
disabled={!selectedMood || isLoading}
>
<Text style={styles.saveButtonText}>
{isLoading ? '保存中...' : existingMood ? '更新心情' : '保存心情'}
{isLoading ? t('mood.edit.saving') : existingMood ? t('mood.edit.update') : t('mood.edit.save')}
</Text>
</TouchableOpacity>
{existingMood && (