Migrate frontend realtime messaging to SSE.
Switch service integrations and screen/store consumers from websocket events to SSE, and ignore generated dist-web artifacts. Made-with: Cursor
This commit is contained in:
@@ -21,7 +21,7 @@ import {
|
||||
Image,
|
||||
} from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { useNavigation, useRoute, RouteProp } from '@react-navigation/native';
|
||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import * as ImagePicker from 'expo-image-picker';
|
||||
import { colors, spacing, fontSizes, borderRadius, shadows } from '../../theme';
|
||||
@@ -31,6 +31,7 @@ import { ApiError } from '../../services/api';
|
||||
import { uploadService } from '../../services/uploadService';
|
||||
import VoteEditor from '../../components/business/VoteEditor';
|
||||
import { useResponsive, useResponsiveValue } from '../../hooks';
|
||||
import { RootStackParamList } from '../../navigation/types';
|
||||
|
||||
const MAX_TITLE_LENGTH = 100;
|
||||
const MAX_CONTENT_LENGTH = 2000;
|
||||
@@ -57,9 +58,9 @@ const EMOJIS = [
|
||||
'👍', '👎', '✊', '👊', '🤛', '🤜', '👏', '🙌',
|
||||
'👐', '🤲', '🤝', '🙏', '✍️', '💪', '🦾', '🦵',
|
||||
'❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '🤍',
|
||||
'🤎', '💔', '❤️\u200d🔥', '❤️\u200d🩹', '💕', '💞', '💓', '💗',
|
||||
'💖', '💘', '💝', '🎉', '🎊', '🎁', '🎈', '✨',
|
||||
'🔥', '💯', '💢', '💥', '💫', '💦', '💨', '🕳️',
|
||||
'🤎', '💔', '🩹', '💕', '💞', '💓', '💗', '💖',
|
||||
'💘', '💝', '🎉', '🎊', '🎁', '🎈', '✨', '🔥',
|
||||
'💯', '💢', '💥', '💫', '💦', '💨', '🕳️',
|
||||
];
|
||||
|
||||
// 动画值
|
||||
@@ -74,6 +75,9 @@ const getPublishErrorMessage = (error: unknown): string => {
|
||||
|
||||
export const CreatePostScreen: React.FC = () => {
|
||||
const navigation = useNavigation();
|
||||
const route = useRoute<RouteProp<RootStackParamList, 'CreatePost'>>();
|
||||
const isEditMode = route.params?.mode === 'edit' && !!route.params?.postId;
|
||||
const editPostID = route.params?.postId || '';
|
||||
|
||||
// 响应式布局
|
||||
const { isWideScreen, width } = useResponsive();
|
||||
@@ -86,6 +90,7 @@ export const CreatePostScreen: React.FC = () => {
|
||||
const [showTagInput, setShowTagInput] = useState(false);
|
||||
const [showEmojiPanel, setShowEmojiPanel] = useState(false);
|
||||
const [posting, setPosting] = useState(false);
|
||||
const [loadingPost, setLoadingPost] = useState(false);
|
||||
|
||||
// 投票相关状态
|
||||
const [isVotePost, setIsVotePost] = useState(false);
|
||||
@@ -122,6 +127,41 @@ export const CreatePostScreen: React.FC = () => {
|
||||
]).start();
|
||||
}, []);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
navigation.setOptions({
|
||||
title: isEditMode ? '编辑帖子' : '发布帖子',
|
||||
});
|
||||
}, [navigation, isEditMode]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!isEditMode || !editPostID) {
|
||||
return;
|
||||
}
|
||||
|
||||
const loadPostForEdit = async () => {
|
||||
setLoadingPost(true);
|
||||
try {
|
||||
const existingPost = await postService.getPost(editPostID);
|
||||
if (!existingPost) {
|
||||
Alert.alert('提示', '帖子不存在或已被删除');
|
||||
navigation.goBack();
|
||||
return;
|
||||
}
|
||||
setTitle(existingPost.title || '');
|
||||
setContent(existingPost.content || '');
|
||||
setImages((existingPost.images || []).map((img) => ({ uri: img.url, uploading: false })));
|
||||
} catch (error) {
|
||||
console.error('加载待编辑帖子失败:', error);
|
||||
Alert.alert('错误', '加载帖子失败,请稍后重试');
|
||||
navigation.goBack();
|
||||
} finally {
|
||||
setLoadingPost(false);
|
||||
}
|
||||
};
|
||||
|
||||
loadPostForEdit();
|
||||
}, [isEditMode, editPostID, navigation]);
|
||||
|
||||
// 选择图片
|
||||
const handlePickImage = async () => {
|
||||
const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync();
|
||||
@@ -323,19 +363,37 @@ export const CreatePostScreen: React.FC = () => {
|
||||
});
|
||||
navigation.goBack();
|
||||
} else {
|
||||
// 创建普通帖子
|
||||
await postService.createPost({
|
||||
title: title.trim() || '无标题',
|
||||
content: content.trim(),
|
||||
images: imageUrls,
|
||||
});
|
||||
showPrompt({
|
||||
type: 'info',
|
||||
title: '审核中',
|
||||
message: '帖子已提交,内容审核中,稍后展示',
|
||||
duration: 2600,
|
||||
});
|
||||
navigation.goBack();
|
||||
if (isEditMode && editPostID) {
|
||||
const updated = await postService.updatePost(editPostID, {
|
||||
title: title.trim() || '无标题',
|
||||
content: content.trim(),
|
||||
images: imageUrls,
|
||||
});
|
||||
if (!updated) {
|
||||
throw new Error('更新帖子失败');
|
||||
}
|
||||
showPrompt({
|
||||
type: 'success',
|
||||
title: '修改成功',
|
||||
message: '帖子内容已更新',
|
||||
duration: 2200,
|
||||
});
|
||||
navigation.goBack();
|
||||
} else {
|
||||
// 创建普通帖子
|
||||
await postService.createPost({
|
||||
title: title.trim() || '无标题',
|
||||
content: content.trim(),
|
||||
images: imageUrls,
|
||||
});
|
||||
showPrompt({
|
||||
type: 'info',
|
||||
title: '审核中',
|
||||
message: '帖子已提交,内容审核中,稍后展示',
|
||||
duration: 2600,
|
||||
});
|
||||
navigation.goBack();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('发布帖子失败:', error);
|
||||
@@ -631,7 +689,7 @@ export const CreatePostScreen: React.FC = () => {
|
||||
<MaterialCommunityIcons name="loading" size={18} color={colors.primary.contrast} />
|
||||
) : (
|
||||
<Text variant="body" color={colors.primary.contrast} style={styles.postButtonText}>
|
||||
发布
|
||||
{isEditMode ? '保存' : '发布'}
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
@@ -677,10 +735,24 @@ export const CreatePostScreen: React.FC = () => {
|
||||
>
|
||||
{isWideScreen ? (
|
||||
<ResponsiveContainer maxWidth={800}>
|
||||
{renderMainContent()}
|
||||
{loadingPost ? (
|
||||
<View style={styles.loadingContainer}>
|
||||
<MaterialCommunityIcons name="loading" size={28} color={colors.primary.main} />
|
||||
<Text variant="body" color={colors.text.secondary} style={styles.loadingText}>加载帖子中...</Text>
|
||||
</View>
|
||||
) : (
|
||||
renderMainContent()
|
||||
)}
|
||||
</ResponsiveContainer>
|
||||
) : (
|
||||
renderMainContent()
|
||||
loadingPost ? (
|
||||
<View style={styles.loadingContainer}>
|
||||
<MaterialCommunityIcons name="loading" size={28} color={colors.primary.main} />
|
||||
<Text variant="body" color={colors.text.secondary} style={styles.loadingText}>加载帖子中...</Text>
|
||||
</View>
|
||||
) : (
|
||||
renderMainContent()
|
||||
)
|
||||
)}
|
||||
</KeyboardAvoidingView>
|
||||
</SafeAreaView>
|
||||
@@ -934,6 +1006,15 @@ const styles = StyleSheet.create({
|
||||
emojiText: {
|
||||
fontSize: 24,
|
||||
},
|
||||
loadingContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
gap: spacing.md,
|
||||
},
|
||||
loadingText: {
|
||||
fontSize: fontSizes.md,
|
||||
},
|
||||
});
|
||||
|
||||
export default CreatePostScreen;
|
||||
|
||||
Reference in New Issue
Block a user