refactor(PostCard, ImageGrid, SmartImage): enhance post editing display and image handling
- Introduced a new method to determine the last edited time for posts, prioritizing content_edited_at for better accuracy in display. - Updated PostCard and PostDetailScreen components to utilize the new editing display logic. - Enhanced ImageGrid and SmartImage components to support additional preview URLs and improve image loading behavior, including lazy loading optimizations for web. - Modified Post and PostDTO interfaces to include contentEditedAt for better tracking of post edits.
This commit is contained in:
@@ -15,7 +15,7 @@ import {
|
||||
Text,
|
||||
Image,
|
||||
} from 'react-native';
|
||||
import { SmartImage, ImageSource } from './SmartImage';
|
||||
import { SmartImage } from './SmartImage';
|
||||
import { colors, spacing, borderRadius } from '../../theme';
|
||||
import { getPreviewImageUrl, ImageDisplayMode } from '../../utils/imageHelper';
|
||||
|
||||
@@ -40,6 +40,8 @@ export interface ImageGridItem {
|
||||
url?: string;
|
||||
thumbnailUrl?: string;
|
||||
thumbnail_url?: string;
|
||||
preview_url?: string;
|
||||
preview_url_large?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
}
|
||||
@@ -108,6 +110,8 @@ interface SingleImageItemProps {
|
||||
maxHeight: number;
|
||||
borderRadiusValue: number;
|
||||
onPress: () => void;
|
||||
usePreview: boolean;
|
||||
displayMode: ImageDisplayMode;
|
||||
}
|
||||
|
||||
const SingleImageItem: React.FC<SingleImageItemProps> = ({
|
||||
@@ -116,23 +120,34 @@ const SingleImageItem: React.FC<SingleImageItemProps> = ({
|
||||
maxHeight,
|
||||
borderRadiusValue,
|
||||
onPress,
|
||||
usePreview,
|
||||
displayMode,
|
||||
}) => {
|
||||
const [aspectRatio, setAspectRatio] = useState<number | null>(null);
|
||||
const uri = image.uri || image.url || '';
|
||||
const mainUri = image.uri || image.url || '';
|
||||
const thumbnailUri =
|
||||
image.thumbnail_url ||
|
||||
image.thumbnailUrl ||
|
||||
image.preview_url ||
|
||||
'';
|
||||
|
||||
useEffect(() => {
|
||||
if (!uri) return;
|
||||
if (image.width && image.height) {
|
||||
setAspectRatio(image.width / image.height);
|
||||
return;
|
||||
}
|
||||
const probeUri = thumbnailUri || mainUri;
|
||||
if (!probeUri) return;
|
||||
let cancelled = false;
|
||||
|
||||
// 添加超时处理,防止高分辨率图片加载卡住
|
||||
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (!cancelled && aspectRatio === null) {
|
||||
setAspectRatio(SINGLE_IMAGE_DEFAULT_ASPECT_RATIO);
|
||||
}
|
||||
}, 3000);
|
||||
|
||||
|
||||
Image.getSize(
|
||||
uri,
|
||||
probeUri,
|
||||
(w, h) => {
|
||||
if (!cancelled) {
|
||||
clearTimeout(timeoutId);
|
||||
@@ -146,11 +161,11 @@ const SingleImageItem: React.FC<SingleImageItemProps> = ({
|
||||
}
|
||||
},
|
||||
);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
return () => {
|
||||
cancelled = true;
|
||||
clearTimeout(timeoutId);
|
||||
};
|
||||
}, [uri]);
|
||||
}, [image.width, image.height, thumbnailUri, mainUri]);
|
||||
|
||||
const effectiveContainerWidth = containerWidth || SCREEN_WIDTH - DEFAULT_CONTAINER_PADDING;
|
||||
|
||||
@@ -189,13 +204,19 @@ const SingleImageItem: React.FC<SingleImageItemProps> = ({
|
||||
width = Math.min(SINGLE_IMAGE_MIN_HEIGHT * aspectRatio, effectiveContainerWidth);
|
||||
}
|
||||
|
||||
const previewForSmart =
|
||||
usePreview && displayMode ? getPreviewImageUrl(image as any, displayMode) : '';
|
||||
const useSmartPreview = !!(usePreview && previewForSmart && mainUri && previewForSmart !== mainUri);
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
style={[styles.singleContainer, { width, height, borderRadius: borderRadiusValue }]}
|
||||
>
|
||||
<SmartImage
|
||||
source={{ uri }}
|
||||
source={{ uri: mainUri }}
|
||||
previewUrl={useSmartPreview ? previewForSmart : undefined}
|
||||
usePreview={useSmartPreview}
|
||||
style={styles.fullSize}
|
||||
resizeMode="cover"
|
||||
borderRadius={borderRadiusValue}
|
||||
@@ -265,12 +286,7 @@ export const ImageGrid: React.FC<ImageGridProps> = ({
|
||||
const renderSingleImage = () => {
|
||||
const image = displayImages[0];
|
||||
if (!image) return null;
|
||||
|
||||
// 获取预览图 URL
|
||||
const previewUrl = usePreview && displayMode
|
||||
? getPreviewImageUrl(image as any, displayMode)
|
||||
: (image.uri || image.url || '');
|
||||
|
||||
|
||||
return (
|
||||
<SingleImageItem
|
||||
image={image}
|
||||
@@ -278,6 +294,8 @@ export const ImageGrid: React.FC<ImageGridProps> = ({
|
||||
maxHeight={singleImageMaxHeight}
|
||||
borderRadiusValue={borderRadiusValue}
|
||||
onPress={() => handleImagePress(0)}
|
||||
usePreview={usePreview}
|
||||
displayMode={displayMode}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user