From 6910fdec70539780f49da25efc82167a874f8798 Mon Sep 17 00:00:00 2001 From: lafay <2021211506@stu.hit.edu.cn> Date: Thu, 16 Apr 2026 11:39:58 +0800 Subject: [PATCH] refactor(ui): remove QQ-style action bar from PostDetailScreen Replace the bottom action bar (like, comment, share, favorite buttons) with a simplified comment section header showing only the comment count. Also add `setIsComposerVisible(false)` after comment submission to hide the composer. --- .kilo/package-lock.json | 115 ++++++ src/screens/home/PostDetailScreen.tsx | 537 +++++++++++++++----------- 2 files changed, 427 insertions(+), 225 deletions(-) create mode 100644 .kilo/package-lock.json diff --git a/.kilo/package-lock.json b/.kilo/package-lock.json new file mode 100644 index 0000000..86ea34f --- /dev/null +++ b/.kilo/package-lock.json @@ -0,0 +1,115 @@ +{ + "name": ".kilo", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@kilocode/plugin": "7.2.10" + } + }, + "node_modules/@kilocode/plugin": { + "version": "7.2.10", + "resolved": "https://registry.npmjs.org/@kilocode/plugin/-/plugin-7.2.10.tgz", + "integrity": "sha512-VJPhJC+E5WWu7XgEJzrVOxKJlwJ+OATwxEzgjqEPj8KN5N38YxUPBY/rzUTjv90x7nkzyk1rFGfCVqXdA/Koug==", + "license": "MIT", + "dependencies": { + "@kilocode/sdk": "7.2.10", + "zod": "4.1.8" + }, + "peerDependencies": { + "@opentui/core": ">=0.1.97", + "@opentui/solid": ">=0.1.97" + }, + "peerDependenciesMeta": { + "@opentui/core": { + "optional": true + }, + "@opentui/solid": { + "optional": true + } + } + }, + "node_modules/@kilocode/sdk": { + "version": "7.2.10", + "resolved": "https://registry.npmjs.org/@kilocode/sdk/-/sdk-7.2.10.tgz", + "integrity": "sha512-H6jGXYAhN/yjOGX3MRZ0OxyEAuRGY3VOwDbLTh4O6ljpgutFHaLvomDZ82qNVy7gl7AjJgi3SAQAt9UQpeGl/w==", + "license": "MIT", + "dependencies": { + "cross-spawn": "7.0.6" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/zod": { + "version": "4.1.8", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/src/screens/home/PostDetailScreen.tsx b/src/screens/home/PostDetailScreen.tsx index ded82b6..4919fae 100644 --- a/src/screens/home/PostDetailScreen.tsx +++ b/src/screens/home/PostDetailScreen.tsx @@ -22,7 +22,7 @@ import { Image, Clipboard, } from 'react-native'; -import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'; +import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useNavigation, useRouter, useLocalSearchParams } from 'expo-router'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import * as ImagePicker from 'expo-image-picker'; @@ -795,8 +795,9 @@ export const PostDetailScreen: React.FC = () => { } setCommentText(''); - setCommentImages([]); // 清除图片 - setReplyingTo(null); // 清除回复状态 + setCommentImages([]); + setReplyingTo(null); + setIsComposerVisible(false); // 更新帖子评论数 setPost(prev => prev ? { @@ -1235,74 +1236,35 @@ export const PostDetailScreen: React.FC = () => { )} - {/* 底部操作栏 - QQ频道风格 */} - - - - - {post.likes_count > 0 ? formatNumber(post.likes_count) : '点赞'} + {/* 评论标题 - 类似图片中的样式 */} + + + + 评论 - - - - - - {post.comments_count > 0 ? formatNumber(post.comments_count) : '评论'} + + {post.comments_count || 0} - - - - - - {post.shares_count > 0 ? formatNumber(post.shares_count) : '分享'} - - - - - - - {post.is_favorited ? '已收藏' : '收藏'} - - - - - {/* 评论标题 - 现代化简洁分区头 */} - - - - - 评论区 - - - {post.comments_count} - - + ); - }, [post, postImages, currentUser?.id, isDeleting, handleLike, handleShare, handleFavorite, handleDeletePost, handleEditPost, handleImagePress, voteResult, isVoteLoading, handleVote, handleUnvote, isDesktop, isTablet, isWideScreen, responsivePadding, responsiveGap]); + }, [post, postImages, currentUser?.id, isDeleting, handleDeletePost, handleEditPost, handleImagePress, voteResult, isVoteLoading, handleVote, handleUnvote, isDesktop, isTablet, isWideScreen, responsivePadding, responsiveGap]); // 回复评论 const [replyingTo, setReplyingTo] = useState(null); + const [isComposerVisible, setIsComposerVisible] = useState(false); const handleReply = (comment: Comment) => { setReplyingTo(comment); - // 可以在这里添加聚焦输入框的逻辑 + setIsComposerVisible(true); }; const handleCancelReply = () => { @@ -1373,37 +1335,42 @@ export const PostDetailScreen: React.FC = () => { ); }, [currentUser?.id, handleDeleteComment, handleImagePress, handleLikeComment, handleLoadMoreReplies, post?.user_id, handleReportComment]); - // 渲染空评论 - 现代化设计 + // 渲染空评论 - 类似图片中的样式 const renderEmptyComments = useCallback(() => ( - - + {/* 四个方块图标 */} + + + + + - - 还没有评论 - - - 成为第一个评论的人吧~ + + 这里空空如也,邀请好友来互动吧! - ), [isDesktop]); + ), []); + + const openComposer = () => { + setIsComposerVisible(true); + }; + + const closeComposer = () => { + setIsComposerVisible(false); + Keyboard.dismiss(); + }; - // 渲染评论输入框 const renderCommentInput = () => ( {/* 回复提示 */} - {replyingTo && ( + {replyingTo && !isComposerVisible && ( 回复 {replyingTo.author.nickname} @@ -1413,70 +1380,153 @@ export const PostDetailScreen: React.FC = () => { )} - - {/* 已选图片预览 */} - {commentImages.length > 0 && ( - - {commentImages.map((image, index) => ( - - - {image.uploading && ( - - - - )} - handleRemoveCommentImage(index)} - > - + + {!isComposerVisible ? ( + /* Collapsed state - simple input trigger */ + + + + {replyingTo ? `回复 ${replyingTo.author.nickname}...` : '来说点什么吧!'} + + + + + + + {formatNumber(post?.likes_count || 0)} + + + + + + + {formatNumber(post?.favorites_count || 0)} + + + + + + + {formatNumber(post?.shares_count || 0)} + + + + ) : ( + /* Expanded state - full composer */ + + {/* Reply hint */} + {replyingTo && ( + + + 回复 {replyingTo.author.nickname} + + + - ))} - + )} + + {/* Text Input */} + + + {/* Image preview */} + {commentImages.length > 0 && ( + + {commentImages.map((image, index) => ( + + + {image.uploading && ( + + + + )} + handleRemoveCommentImage(index)} + > + + + + ))} + + )} + + {/* Toolbar */} + + + = 3} + > + = 3 ? colors.text.disabled : colors.text.secondary} + /> + + {}} + > + + + {}} + > + + + + {commentText.length}/500 + + + + 0) && styles.expandedSendButtonDisabled + ]} + onPress={handleSendComment} + disabled={!(commentText.trim() || commentImages.length > 0)} + > + 发送 + + + )} - - - {/* 图片选择按钮 */} - = 3} - > - = 3 ? colors.text.disabled : colors.text.secondary} - /> - - - - 0) && styles.sendButtonDisabled - ]} - onPress={handleSendComment} - disabled={!(commentText.trim() || commentImages.length > 0)} - > - 0) ? colors.primary.main : colors.text.disabled} - /> - - ); @@ -1559,20 +1609,20 @@ export const PostDetailScreen: React.FC = () => { if (!post) { return ( - + - + ); } // 桌面端双栏布局 if (useDualColumnLayout) { return ( - + { onClose={() => setShowImageModal(false)} enableSave /> - + ); } // 移动端单栏布局 return ( - + { setReportTarget(null); }} /> - + ); }; @@ -1915,62 +1965,35 @@ function createPostDetailStyles(colors: AppColors) { voteLoadingText: { marginTop: spacing.sm, }, - actionBar: { - flexDirection: 'row', - justifyContent: 'space-around', - paddingVertical: spacing.md, - borderTopWidth: StyleSheet.hairlineWidth, - borderTopColor: colors.divider, - backgroundColor: colors.background.paper, - }, - actionButton: { - flexDirection: 'row', - alignItems: 'center', - paddingHorizontal: spacing.md, - paddingVertical: spacing.xs, - borderRadius: borderRadius.lg, - }, - actionText: { - fontSize: fontSizes.sm, - marginLeft: 6, - fontWeight: '500', - }, commentSectionHeader: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - borderTopWidth: StyleSheet.hairlineWidth, - borderTopColor: colors.divider, + flexDirection: 'column', + alignItems: 'flex-start', paddingTop: spacing.lg, }, - commentSectionTitleBlock: { - flex: 1, - minWidth: 0, - }, commentSectionTitleRow: { flexDirection: 'row', alignItems: 'center', }, commentSectionTitle: { - fontWeight: '800', + fontWeight: '600', color: colors.text.primary, - letterSpacing: -0.2, + letterSpacing: 0, }, - commentCountBadge: { - backgroundColor: colors.background.default, - borderWidth: StyleSheet.hairlineWidth, - borderColor: colors.divider, - paddingHorizontal: spacing.sm + 2, - paddingVertical: 3, - borderRadius: 999, - marginLeft: spacing.sm, - minWidth: 24, - alignItems: 'center', + commentSectionCount: { + marginLeft: spacing.xs, + fontSize: fontSizes.sm, }, - commentCountText: { - fontSize: fontSizes.xs, - fontWeight: '700', - color: colors.text.secondary, + commentSectionUnderline: { + width: 28, + height: 3, + backgroundColor: colors.text.primary, + marginTop: spacing.xs, + borderRadius: borderRadius.xs, + }, + commentSectionCount: { + marginLeft: spacing.xs, + fontSize: fontSizes.sm, + color: colors.text.hint, }, inputContainer: { backgroundColor: colors.background.paper, @@ -1991,29 +2014,37 @@ function createPostDetailStyles(colors: AppColors) { marginLeft: spacing.sm, padding: 2, }, - inputWrapper: { + inputTrigger: { + flex: 1, + backgroundColor: colors.background.default, + borderRadius: 18, + paddingHorizontal: spacing.md, + paddingVertical: spacing.sm + 2, + minHeight: 38, + justifyContent: 'center', + }, + inputTriggerText: { + fontSize: fontSizes.sm, + color: colors.text.hint, + }, + bottomComposerRow: { flexDirection: 'row', alignItems: 'center', - backgroundColor: colors.background.default, - borderRadius: 20, - paddingHorizontal: spacing.md, + gap: spacing.xs + 2, }, - input: { - flex: 1, - minHeight: 40, - maxHeight: 100, - color: colors.text.primary, - paddingVertical: spacing.sm, + bottomActionItem: { + alignItems: 'center', + justifyContent: 'center', + paddingVertical: 2, + paddingHorizontal: spacing.sm + 1, + marginLeft: spacing.xs, }, - sendButton: { - padding: spacing.sm, - }, - sendButtonDisabled: { - opacity: 0.5, - }, - imagePickerButton: { - padding: spacing.sm, - marginRight: spacing.xs, + bottomActionCount: { + marginTop: 1, + fontSize: fontSizes.xs, + color: colors.text.secondary, + lineHeight: fontSizes.xs + 2, + fontWeight: '500', }, commentImagesPreview: { maxHeight: 80, @@ -2050,6 +2081,62 @@ function createPostDetailStyles(colors: AppColors) { backgroundColor: colors.background.paper, borderRadius: 9, }, + // Expanded composer styles + expandedComposer: { + backgroundColor: colors.background.paper, + }, + expandedReplyHint: { + flexDirection: 'row', + alignItems: 'center', + marginBottom: spacing.sm, + }, + expandedTextInput: { + minHeight: 80, + maxHeight: 160, + fontSize: fontSizes.md, + color: colors.text.primary, + paddingVertical: spacing.sm, + textAlignVertical: 'top', + lineHeight: 22, + }, + expandedToolbar: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginTop: spacing.sm, + paddingTop: spacing.sm, + borderTopWidth: StyleSheet.hairlineWidth, + borderTopColor: colors.divider, + }, + expandedToolbarLeft: { + flexDirection: 'row', + alignItems: 'center', + flex: 1, + }, + expandedToolbarItem: { + padding: spacing.xs, + marginRight: spacing.sm, + }, + expandedCharCount: { + marginLeft: 'auto', + marginRight: spacing.sm, + }, + expandedSendButton: { + backgroundColor: colors.primary.main, + paddingHorizontal: spacing.md, + paddingVertical: spacing.sm, + borderRadius: borderRadius.md, + minWidth: 60, + alignItems: 'center', + }, + expandedSendButtonDisabled: { + backgroundColor: colors.text.disabled, + }, + expandedSendButtonText: { + color: colors.text.inverse, + fontSize: fontSizes.sm, + fontWeight: '600', + }, modalContainer: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.9)', @@ -2074,33 +2161,33 @@ function createPostDetailStyles(colors: AppColors) { paddingVertical: spacing.xs, borderRadius: borderRadius.md, }, - // 空评论状态样式(与平铺评论区一致,无卡片气泡) + // 空评论状态样式(类似图片中的四个方块样式) emptyCommentsContainer: { alignItems: 'center', justifyContent: 'center', - marginHorizontal: spacing.md, - marginTop: spacing.md, - marginBottom: spacing.lg, - paddingVertical: spacing.xl, - paddingHorizontal: spacing.md, + paddingVertical: spacing.xl * 2.5, }, - emptyCommentsIconWrapper: { - width: 40, - height: 40, - alignItems: 'center', - justifyContent: 'center', - marginBottom: spacing.sm, - opacity: 0.85, + emptyCommentsGrid: { + flexDirection: 'row', + flexWrap: 'wrap', + width: 48, + height: 48, + marginBottom: spacing.md, }, - emptyCommentsTitle: { - fontSize: fontSizes.md, - fontWeight: '500', - color: colors.text.primary, - marginBottom: spacing.xs, + emptyCommentsGridItem: { + width: 20, + height: 20, + backgroundColor: colors.background.disabled, + margin: 2, + borderRadius: borderRadius.xs, + }, + emptyCommentsGridItemActive: { + backgroundColor: colors.text.hint, }, emptyCommentsSubtitle: { fontSize: fontSizes.sm, textAlign: 'center', + color: colors.text.hint, }, // 侧边栏样式 sidebar: {