feat: 抽离 imaghe 组件,为图片增加 header
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { Colors } from '@/constants/Colors';
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
import { useWaterDataByDate } from '@/hooks/useWaterData';
|
||||
import { getQuickWaterAmount, setQuickWaterAmount } from '@/utils/userPreferences';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import dayjs from 'dayjs';
|
||||
import { Image } from 'expo-image';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
Alert,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { ROUTES } from '@/constants/Routes';
|
||||
import { useAppSelector } from '@/hooks/redux';
|
||||
import { selectUserAge, selectUserProfile } from '@/store/userSlice';
|
||||
import { fetchBasalEnergyBurned } from '@/utils/health';
|
||||
import dayjs from 'dayjs';
|
||||
import { Image } from 'expo-image';
|
||||
import { router } from 'expo-router';
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ThemedText } from '@/components/ThemedText';
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useThemeColor } from '@/hooks/useThemeColor';
|
||||
import { DietRecord } from '@/services/dietRecords';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import dayjs from 'dayjs';
|
||||
import { Image } from 'expo-image';
|
||||
import React, { useMemo, useRef, useState } from 'react';
|
||||
import { Alert, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||
import { RectButton, Swipeable } from 'react-native-gesture-handler';
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import {
|
||||
Animated,
|
||||
InteractionManager,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
ViewStyle
|
||||
Animated,
|
||||
InteractionManager,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
ViewStyle
|
||||
} from 'react-native';
|
||||
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
|
||||
import { ChallengeType } from '@/services/challengesApi';
|
||||
import { reportChallengeProgress, selectChallengeList } from '@/store/challengesSlice';
|
||||
import { fetchHourlyStepSamples, fetchStepCount, HourlyStepData } from '@/utils/health';
|
||||
import { logger } from '@/utils/logger';
|
||||
import dayjs from 'dayjs';
|
||||
import { Image } from 'expo-image';
|
||||
import { useRouter } from 'expo-router';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AnimatedNumber } from './AnimatedNumber';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { fetchHRVWithStatus } from '@/utils/health';
|
||||
import { convertHrvToStressIndex } from '@/utils/stress';
|
||||
import { Image } from 'expo-image';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { useWaterDataByDate } from '@/hooks/useWaterData';
|
||||
import { appStoreReviewService } from '@/services/appStoreReview';
|
||||
import { getQuickWaterAmount } from '@/utils/userPreferences';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
import dayjs from 'dayjs';
|
||||
import * as Haptics from 'expo-haptics';
|
||||
import { Image } from 'expo-image';
|
||||
import { useRouter } from 'expo-router';
|
||||
import LottieView from 'lottie-react-native';
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import dayjs from 'dayjs';
|
||||
import { Image } from 'expo-image';
|
||||
import { useRouter } from 'expo-router';
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { Toast } from '@/utils/toast.utils';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import dayjs from 'dayjs';
|
||||
import { BlurView } from 'expo-blur';
|
||||
import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
|
||||
import { Image } from 'expo-image';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import dayjs from 'dayjs';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Animated, Modal, Platform, Pressable, Share, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import type { RankingItem } from '@/store/challengesSlice';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { Image } from 'expo-image';
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { Colors } from '@/constants/Colors';
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { BlurView } from 'expo-blur';
|
||||
import { Image } from 'expo-image';
|
||||
import React from 'react';
|
||||
import { ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native';
|
||||
import QuickChips from './QuickChips';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { Colors } from '@/constants/Colors';
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { Image } from 'expo-image';
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||
import Markdown from 'react-native-markdown-display';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Colors, palette } from '@/constants/Colors';
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { palette } from '@/constants/Colors';
|
||||
import { MedicalRecordItem } from '@/services/healthProfile';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import dayjs from 'dayjs';
|
||||
import { Image } from 'expo-image';
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { MedicalRecordCard } from '@/components/health/MedicalRecordCard';
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { palette } from '@/constants/Colors';
|
||||
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
|
||||
import { useCosUpload } from '@/hooks/useCosUpload';
|
||||
@@ -13,7 +14,6 @@ import {
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import dayjs from 'dayjs';
|
||||
import * as DocumentPicker from 'expo-document-picker';
|
||||
import { Image } from 'expo-image';
|
||||
import * as ImagePicker from 'expo-image-picker';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { Image } from 'expo-image';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Animated, Modal, Pressable, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ThemedText } from '@/components/ThemedText';
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { useAppDispatch } from '@/hooks/redux';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { skipMedicationAction, takeMedicationAction } from '@/store/medicationsSlice';
|
||||
@@ -6,7 +7,6 @@ import type { MedicationDisplayItem } from '@/types/medication';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
|
||||
import { Image } from 'expo-image';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Alert, StyleSheet, TouchableOpacity, View } from 'react-native';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
|
||||
import { Image } from 'expo-image';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import React from 'react';
|
||||
import {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { useAppSelector } from '@/hooks/redux';
|
||||
import { useCosUpload } from '@/hooks/useCosUpload';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { BlurView } from 'expo-blur';
|
||||
import { Image } from 'expo-image';
|
||||
import * as ImagePicker from 'expo-image-picker';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
@@ -15,10 +15,10 @@ import {
|
||||
View,
|
||||
} from 'react-native';
|
||||
// 导入统一的食物类型定义
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { Colors } from '@/constants/Colors';
|
||||
import { DEFAULT_IMAGE_FOOD } from '@/constants/Image';
|
||||
import type { FoodItem } from '@/types/food';
|
||||
import { Image } from 'expo-image';
|
||||
|
||||
// 导入统一的食物类型定义
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Image } from 'expo-image';
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import React from 'react';
|
||||
import { Pressable, StyleSheet, Text, View } from 'react-native';
|
||||
import Animated, { FadeIn, FadeOut } from 'react-native-reanimated';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
|
||||
import { ChallengeType } from '@/services/challengesApi';
|
||||
import { reportChallengeProgress, selectChallengeList } from '@/store/challengesSlice';
|
||||
import { logger } from '@/utils/logger';
|
||||
import { fetchCompleteSleepData, formatSleepTime } from '@/utils/sleepHealthKit';
|
||||
import dayjs from 'dayjs';
|
||||
import { Image } from 'expo-image';
|
||||
import { router } from 'expo-router';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
44
components/ui/Image.tsx
Normal file
44
components/ui/Image.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import { API_ORIGIN } from '@/constants/Api';
|
||||
import Constants from 'expo-constants';
|
||||
import { Image as ExpoImage, ImageProps as ExpoImageProps } from 'expo-image';
|
||||
import React, { forwardRef, useMemo } from 'react';
|
||||
|
||||
// Construct User-Agent
|
||||
const APP_NAME = Constants.expoConfig?.name || 'Out Live';
|
||||
const APP_VERSION = Constants.expoConfig?.version || '1.1.5';
|
||||
const USER_AGENT = `${APP_NAME}/${APP_VERSION} (iOS)`;
|
||||
|
||||
export type ImageProps = ExpoImageProps;
|
||||
|
||||
export const Image = forwardRef<ExpoImage, ImageProps>(({ source, ...props }, ref) => {
|
||||
const finalSource = useMemo(() => {
|
||||
if (!source) return source;
|
||||
|
||||
const headers = {
|
||||
'User-Agent': USER_AGENT,
|
||||
'Referer': API_ORIGIN,
|
||||
};
|
||||
|
||||
const addHeaders = (src: any) => {
|
||||
if (typeof src === 'number' || src === null || src === undefined) return src;
|
||||
if (typeof src === 'string') return { uri: src, headers };
|
||||
if (typeof src === 'object' && 'uri' in src) {
|
||||
return {
|
||||
...src,
|
||||
headers: { ...headers, ...(src.headers || {}) }
|
||||
};
|
||||
}
|
||||
return src;
|
||||
};
|
||||
|
||||
if (Array.isArray(source)) {
|
||||
return source.map(addHeaders);
|
||||
}
|
||||
|
||||
return addHeaders(source);
|
||||
}, [source]);
|
||||
|
||||
return <ExpoImage {...props} source={finalSource} ref={ref} />;
|
||||
});
|
||||
|
||||
Image.displayName = 'Image';
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
|
||||
import * as Haptics from 'expo-haptics';
|
||||
import { Image } from 'expo-image';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Image } from '@/components/ui/Image';
|
||||
import { Colors } from '@/constants/Colors';
|
||||
import { ROUTES } from '@/constants/Routes';
|
||||
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
|
||||
@@ -7,7 +8,6 @@ import { fetchWeightHistory } from '@/store/userSlice';
|
||||
import { BMI_CATEGORIES } from '@/utils/bmi';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
|
||||
import { Image } from 'expo-image';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { useRouter } from 'expo-router';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
Reference in New Issue
Block a user