Merge branch 'dev' of https://code.littlelan.cn/carrot_bbs/frontend into dev
This commit is contained in:
@@ -364,7 +364,7 @@ export const HomeScreen: React.FC = () => {
|
||||
useEffect(() => {
|
||||
if (homeTabPressCount > 0) {
|
||||
// 滚动 FlashList 到顶部
|
||||
flashListRef.current?.scrollToOffset({ offset: 0, animated: true });
|
||||
flashListRef.current?.scrollToOffset({ offset: 0, animated: false });
|
||||
// 滚动 ScrollView 到顶部(网格模式)
|
||||
scrollViewRef.current?.scrollTo({ y: 0, animated: true });
|
||||
// 重置底部 Tab 栏状态
|
||||
|
||||
@@ -38,12 +38,18 @@ import {
|
||||
import { Post, Comment, VoteResultDTO, VoteOptionDTO, MessageSegment } from '../../types';
|
||||
import { useUserStore } from '../../stores';
|
||||
import { useCurrentUser } from '../../stores/auth';
|
||||
import { postService, commentService, uploadService, authService, showPrompt, voteService } from '../../services';
|
||||
import { postService, commentService, authService, showPrompt, voteService } from '../../services';
|
||||
import { postSyncService } from '@/services/post';
|
||||
import { useCursorPagination } from '../../hooks/useCursorPagination';
|
||||
import { CommentItem, VoteCard, ReportDialog, ShareSheet, PostContentRenderer, PostMentionInput } from '../../components/business';
|
||||
import { Avatar, Button, Loading, EmptyState, Text, ImageGallery, ImageGrid, ImageGridItem, AdaptiveLayout, AppBackButton } from '../../components/common';
|
||||
import { useResponsive, useResponsiveValue, useResponsiveSpacing } from '../../hooks';
|
||||
import {
|
||||
type PendingOrRemoteImage,
|
||||
makePendingImageFromAsset,
|
||||
getImageDisplayUri,
|
||||
uploadAllPendingImages,
|
||||
} from '../../utils/pendingImages';
|
||||
import { handleError } from '@/services/core';
|
||||
import { formatDateTime as formatDateTimeUtil, formatRelativeTime as formatRelativeTimeUtil } from '@/utils/formatTime';
|
||||
import * as hrefs from '../../navigation/hrefs';
|
||||
@@ -251,7 +257,7 @@ export const PostDetailScreen: React.FC = () => {
|
||||
const [keyboardHeight, setKeyboardHeight] = useState(0);
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
// 评论图片相关状态
|
||||
const [commentImages, setCommentImages] = useState<{ uri: string; uploading?: boolean }[]>([]);
|
||||
const [commentImages, setCommentImages] = useState<PendingOrRemoteImage[]>([]);
|
||||
const [showEmojiPanel, setShowEmojiPanel] = useState(false);
|
||||
const [isFollowing, setIsFollowing] = useState(false);
|
||||
const [isFollowingMe, setIsFollowingMe] = useState(false);
|
||||
@@ -688,31 +694,8 @@ export const PostDetailScreen: React.FC = () => {
|
||||
});
|
||||
|
||||
if (!result.canceled && result.assets) {
|
||||
const newImages = result.assets.map(asset => ({ uri: asset.uri, uploading: true }));
|
||||
const newImages = result.assets.map(asset => makePendingImageFromAsset(asset, 'ci'));
|
||||
setCommentImages(prev => [...prev, ...newImages]);
|
||||
|
||||
// 上传图片
|
||||
for (let i = 0; i < newImages.length; i++) {
|
||||
const asset = result.assets[i];
|
||||
const uploadResult = await uploadService.uploadImage({
|
||||
uri: asset.uri,
|
||||
type: asset.mimeType || 'image/jpeg',
|
||||
});
|
||||
|
||||
if (uploadResult) {
|
||||
setCommentImages(prev => {
|
||||
const updated = [...prev];
|
||||
const index = prev.findIndex(img => img.uri === asset.uri);
|
||||
if (index !== -1) {
|
||||
updated[index] = { uri: uploadResult.url, uploading: false };
|
||||
}
|
||||
return updated;
|
||||
});
|
||||
} else {
|
||||
Alert.alert('上传失败', '图片上传失败,请重试');
|
||||
setCommentImages(prev => prev.filter(img => img.uri !== asset.uri));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -727,11 +710,17 @@ export const PostDetailScreen: React.FC = () => {
|
||||
const hasContent = commentText.trim() || commentImages.length > 0;
|
||||
if (!hasContent || !post) return;
|
||||
|
||||
// 检查是否有图片正在上传
|
||||
const uploadingImages = commentImages.filter(img => img.uploading);
|
||||
if (uploadingImages.length > 0) {
|
||||
Alert.alert('请稍候', '图片正在上传中,请稍后再试');
|
||||
return;
|
||||
// 上传所有 pending 图片
|
||||
let uploadedImageUrls: string[] = [];
|
||||
if (commentImages.length > 0) {
|
||||
const uploadResult = await uploadAllPendingImages(commentImages, (id, url) => {
|
||||
setCommentImages(prev => prev.map(i => i.id === id ? { id, kind: 'remote' as const, url } : i));
|
||||
});
|
||||
if (!uploadResult.success) {
|
||||
Alert.alert('上传失败', '部分图片上传失败,请重试');
|
||||
return;
|
||||
}
|
||||
uploadedImageUrls = uploadResult.urls;
|
||||
}
|
||||
|
||||
const tempId = `new-${Date.now()}`;
|
||||
@@ -741,9 +730,6 @@ export const PostDetailScreen: React.FC = () => {
|
||||
// 获取根评论 ID:如果被回复评论有 root_id,则使用 root_id;否则使用 parent_id(即被回复的是顶级评论)
|
||||
const rootId = isReply ? (replyingTo.root_id || replyingTo.id) : null;
|
||||
|
||||
// 获取已上传图片的URL列表
|
||||
const uploadedImageUrls = commentImages.filter(img => !img.uploading).map(img => img.uri);
|
||||
|
||||
// 先创建临时评论显示在列表中
|
||||
const tempComment: Comment = {
|
||||
id: tempId,
|
||||
@@ -1501,13 +1487,12 @@ export const PostDetailScreen: React.FC = () => {
|
||||
{commentImages.length > 0 && (
|
||||
<ScrollView horizontal style={styles.commentImagesPreview} showsHorizontalScrollIndicator={false}>
|
||||
{commentImages.map((image, index) => (
|
||||
<View key={index} style={styles.commentImageWrapper}>
|
||||
<Image source={{ uri: image.uri }} style={styles.commentImageThumbnail} resizeMode="cover" />
|
||||
{image.uploading && (
|
||||
<View style={styles.uploadingOverlay}>
|
||||
<Loading size="sm" />
|
||||
</View>
|
||||
)}
|
||||
<View key={image.id} style={styles.commentImageWrapper}>
|
||||
<Image
|
||||
source={{ uri: getImageDisplayUri(image) }}
|
||||
style={styles.commentImageThumbnail}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={styles.removeImageButton}
|
||||
onPress={() => handleRemoveCommentImage(index)}
|
||||
@@ -2185,17 +2170,6 @@ function createPostDetailStyles(colors: AppColors) {
|
||||
height: 60,
|
||||
borderRadius: borderRadius.sm,
|
||||
},
|
||||
uploadingOverlay: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.4)',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
borderRadius: borderRadius.sm,
|
||||
},
|
||||
removeImageButton: {
|
||||
position: 'absolute',
|
||||
top: -6,
|
||||
|
||||
Reference in New Issue
Block a user