2026-04-23 22:29:58 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* PostMentionInput - 帖子内容输入框(支持 @提及)
|
|
|
|
|
|
* 复用关注列表加载逻辑
|
|
|
|
|
|
* 检测输入中的 @ 字符,弹出关注者列表供选择
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
import React, { useState, useEffect, useCallback, useRef } from 'react';
|
|
|
|
|
|
import {
|
|
|
|
|
|
View,
|
|
|
|
|
|
TextInput,
|
2026-04-26 01:11:30 +08:00
|
|
|
|
ScrollView,
|
2026-04-23 22:29:58 +08:00
|
|
|
|
TouchableOpacity,
|
|
|
|
|
|
StyleSheet,
|
|
|
|
|
|
Platform,
|
|
|
|
|
|
} from 'react-native';
|
2026-04-24 16:44:01 +08:00
|
|
|
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
2026-04-23 22:29:58 +08:00
|
|
|
|
|
|
|
|
|
|
import Text from '../common/Text';
|
|
|
|
|
|
import Avatar from '../common/Avatar';
|
|
|
|
|
|
import { useAppColors, spacing, fontSizes, borderRadius } from '../../theme';
|
|
|
|
|
|
import { useAuthStore } from '../../stores';
|
|
|
|
|
|
import { authService } from '../../services/auth';
|
2026-04-26 01:11:30 +08:00
|
|
|
|
import { postService } from '../../services/post/postService';
|
2026-04-23 22:29:58 +08:00
|
|
|
|
import { MessageSegment, AtSegmentData } from '../../types';
|
|
|
|
|
|
|
|
|
|
|
|
interface MentionUser {
|
|
|
|
|
|
id: string;
|
|
|
|
|
|
nickname: string;
|
|
|
|
|
|
avatar: string | null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-26 01:11:30 +08:00
|
|
|
|
interface SuggestPost {
|
|
|
|
|
|
id: string;
|
|
|
|
|
|
title: string;
|
|
|
|
|
|
channel?: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type SuggestionMode = 'none' | 'mention' | 'postref';
|
|
|
|
|
|
|
2026-04-23 22:29:58 +08:00
|
|
|
|
interface PostMentionInputProps {
|
|
|
|
|
|
value: string;
|
|
|
|
|
|
onChangeText: (text: string) => void;
|
|
|
|
|
|
onSegmentsChange: (segments: MessageSegment[]) => void;
|
|
|
|
|
|
placeholder?: string;
|
|
|
|
|
|
maxLength?: number;
|
|
|
|
|
|
style?: any;
|
|
|
|
|
|
minHeight?: number;
|
2026-04-24 16:44:01 +08:00
|
|
|
|
autoExpand?: boolean;
|
2026-04-26 01:11:30 +08:00
|
|
|
|
onPostRefPasted?: (postId: string, title: string) => void;
|
2026-05-06 12:53:39 +08:00
|
|
|
|
onSubmitEditing?: () => void;
|
|
|
|
|
|
returnKeyType?: 'default' | 'send' | 'done';
|
2026-04-23 22:29:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const PostMentionInput: React.FC<PostMentionInputProps> = ({
|
|
|
|
|
|
value,
|
|
|
|
|
|
onChangeText,
|
|
|
|
|
|
onSegmentsChange,
|
|
|
|
|
|
placeholder = '说点什么...',
|
|
|
|
|
|
maxLength = 2000,
|
|
|
|
|
|
style,
|
|
|
|
|
|
minHeight = 100,
|
2026-04-24 16:44:01 +08:00
|
|
|
|
autoExpand = false,
|
2026-04-26 01:11:30 +08:00
|
|
|
|
onPostRefPasted,
|
2026-05-06 12:53:39 +08:00
|
|
|
|
onSubmitEditing,
|
|
|
|
|
|
returnKeyType = 'default',
|
2026-04-23 22:29:58 +08:00
|
|
|
|
}) => {
|
|
|
|
|
|
const colors = useAppColors();
|
|
|
|
|
|
const currentUser = useAuthStore(s => s.currentUser);
|
|
|
|
|
|
const [followingUsers, setFollowingUsers] = useState<MentionUser[]>([]);
|
2026-04-26 01:11:30 +08:00
|
|
|
|
const [suggestPosts, setSuggestPosts] = useState<SuggestPost[]>([]);
|
|
|
|
|
|
const [suggestionMode, setSuggestionMode] = useState<SuggestionMode>('none');
|
2026-04-23 22:29:58 +08:00
|
|
|
|
const [mentionQuery, setMentionQuery] = useState('');
|
|
|
|
|
|
const [mentionStartIndex, setMentionStartIndex] = useState(-1);
|
|
|
|
|
|
const [loaded, setLoaded] = useState(false);
|
2026-04-26 01:11:30 +08:00
|
|
|
|
const [postSearchTimer, setPostSearchTimer] = useState<ReturnType<typeof setTimeout> | null>(null);
|
2026-04-23 22:29:58 +08:00
|
|
|
|
const inputRef = useRef<TextInput>(null);
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
if (!loaded && currentUser?.id) {
|
|
|
|
|
|
loadFollowing();
|
|
|
|
|
|
setLoaded(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, [currentUser?.id, loaded]);
|
|
|
|
|
|
|
|
|
|
|
|
const loadFollowing = async () => {
|
|
|
|
|
|
if (!currentUser?.id) return;
|
|
|
|
|
|
try {
|
|
|
|
|
|
const list = await authService.getFollowingList(currentUser.id, 1, 200);
|
|
|
|
|
|
setFollowingUsers(
|
|
|
|
|
|
list.map(u => ({
|
|
|
|
|
|
id: u.id,
|
|
|
|
|
|
nickname: u.nickname || u.username || '',
|
|
|
|
|
|
avatar: u.avatar || null,
|
|
|
|
|
|
}))
|
|
|
|
|
|
);
|
|
|
|
|
|
} catch (_) {
|
|
|
|
|
|
// ignore
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const filteredUsers = followingUsers.filter(u =>
|
|
|
|
|
|
u.nickname.toLowerCase().includes(mentionQuery.toLowerCase())
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const activeMentions = useRef(new Map<number, { endIndex: number; userId: string; nickname: string }>());
|
|
|
|
|
|
const segmentsRef = useRef<MessageSegment[]>([]);
|
|
|
|
|
|
|
|
|
|
|
|
const rebuildSegments = useCallback(
|
|
|
|
|
|
(text: string) => {
|
|
|
|
|
|
const mentions = activeMentions.current;
|
|
|
|
|
|
if (mentions.size === 0) {
|
|
|
|
|
|
onSegmentsChange(text.trim() ? [{ type: 'text', data: { text } }] : []);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const segments: MessageSegment[] = [];
|
|
|
|
|
|
const sorted = Array.from(mentions.entries()).sort((a, b) => a[0] - b[0]);
|
|
|
|
|
|
let lastEnd = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (const [startIdx, mention] of sorted) {
|
|
|
|
|
|
if (startIdx > lastEnd) {
|
|
|
|
|
|
segments.push({ type: 'text', data: { text: text.slice(lastEnd, startIdx) } });
|
|
|
|
|
|
}
|
|
|
|
|
|
segments.push({
|
|
|
|
|
|
type: 'at',
|
|
|
|
|
|
data: { user_id: mention.userId, nickname: mention.nickname } as AtSegmentData,
|
|
|
|
|
|
});
|
|
|
|
|
|
lastEnd = mention.endIndex;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (lastEnd < text.length) {
|
|
|
|
|
|
segments.push({ type: 'text', data: { text: text.slice(lastEnd) } });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onSegmentsChange(segments);
|
|
|
|
|
|
},
|
|
|
|
|
|
[onSegmentsChange]
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const handleChangeText = useCallback(
|
|
|
|
|
|
(text: string) => {
|
|
|
|
|
|
onChangeText(text);
|
|
|
|
|
|
|
|
|
|
|
|
const cursorPos = text.length;
|
|
|
|
|
|
|
2026-04-26 01:11:30 +08:00
|
|
|
|
// Check for # trigger (post ref search)
|
|
|
|
|
|
let hashStart = -1;
|
|
|
|
|
|
for (let i = cursorPos - 1; i >= 0; i--) {
|
|
|
|
|
|
if (text[i] === '#') {
|
|
|
|
|
|
hashStart = i;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (text[i] === ' ' || text[i] === '\n') {
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (hashStart >= 0) {
|
|
|
|
|
|
const query = text.slice(hashStart + 1, cursorPos);
|
|
|
|
|
|
if (query.length >= 1 && !query.includes(' ') && !query.includes('\n')) {
|
|
|
|
|
|
if (postSearchTimer) {
|
|
|
|
|
|
clearTimeout(postSearchTimer);
|
|
|
|
|
|
}
|
|
|
|
|
|
const timer = setTimeout(async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const results = await postService.suggestPosts(query, 8);
|
|
|
|
|
|
setSuggestPosts(results);
|
|
|
|
|
|
setSuggestionMode('postref');
|
|
|
|
|
|
setMentionStartIndex(hashStart);
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
// ignore
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 300);
|
|
|
|
|
|
setPostSearchTimer(timer);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check for @ trigger (mention)
|
|
|
|
|
|
let atStart = -1;
|
2026-04-23 22:29:58 +08:00
|
|
|
|
for (let i = cursorPos - 1; i >= 0; i--) {
|
|
|
|
|
|
if (text[i] === '@') {
|
|
|
|
|
|
atStart = i;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (text[i] === ' ' || text[i] === '\n') {
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (atStart >= 0) {
|
|
|
|
|
|
const query = text.slice(atStart + 1, cursorPos);
|
|
|
|
|
|
if (!query.includes(' ') && !query.includes('\n')) {
|
|
|
|
|
|
setMentionQuery(query);
|
|
|
|
|
|
setMentionStartIndex(atStart);
|
2026-04-26 01:11:30 +08:00
|
|
|
|
setSuggestionMode('mention');
|
2026-04-23 22:29:58 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-26 01:11:30 +08:00
|
|
|
|
setSuggestionMode('none');
|
2026-04-23 22:29:58 +08:00
|
|
|
|
rebuildSegments(text);
|
|
|
|
|
|
},
|
2026-04-26 01:11:30 +08:00
|
|
|
|
[onChangeText, rebuildSegments, postSearchTimer],
|
2026-04-23 22:29:58 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const handleSelectMention = useCallback(
|
|
|
|
|
|
(mentionUser: MentionUser) => {
|
|
|
|
|
|
if (mentionStartIndex < 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
const before = value.slice(0, mentionStartIndex);
|
|
|
|
|
|
const mentionText = `@${mentionUser.nickname} `;
|
|
|
|
|
|
const newText = before + mentionText;
|
|
|
|
|
|
|
|
|
|
|
|
activeMentions.current.set(mentionStartIndex, {
|
|
|
|
|
|
endIndex: before.length + mentionText.length,
|
|
|
|
|
|
userId: mentionUser.id,
|
|
|
|
|
|
nickname: mentionUser.nickname,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
onChangeText(newText);
|
2026-04-26 01:11:30 +08:00
|
|
|
|
setSuggestionMode('none');
|
2026-04-23 22:29:58 +08:00
|
|
|
|
setMentionQuery('');
|
|
|
|
|
|
setMentionStartIndex(-1);
|
|
|
|
|
|
|
|
|
|
|
|
rebuildSegments(newText);
|
|
|
|
|
|
|
|
|
|
|
|
inputRef.current?.focus();
|
|
|
|
|
|
},
|
2026-04-26 01:11:30 +08:00
|
|
|
|
[value, mentionStartIndex, onChangeText, rebuildSegments],
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const handleSelectPost = useCallback(
|
|
|
|
|
|
(post: SuggestPost) => {
|
|
|
|
|
|
if (mentionStartIndex < 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
const before = value.slice(0, mentionStartIndex);
|
|
|
|
|
|
const refText = `#${post.title} `;
|
|
|
|
|
|
const newText = before + refText;
|
|
|
|
|
|
|
|
|
|
|
|
onChangeText(newText);
|
|
|
|
|
|
setSuggestionMode('none');
|
|
|
|
|
|
setSuggestPosts([]);
|
|
|
|
|
|
setMentionStartIndex(-1);
|
|
|
|
|
|
|
|
|
|
|
|
if (onPostRefPasted) {
|
|
|
|
|
|
onPostRefPasted(post.id, post.title);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
rebuildSegments(newText);
|
|
|
|
|
|
|
|
|
|
|
|
inputRef.current?.focus();
|
|
|
|
|
|
},
|
|
|
|
|
|
[value, mentionStartIndex, onChangeText, rebuildSegments, onPostRefPasted],
|
2026-04-23 22:29:58 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const renderMentionItem = ({ item }: { item: MentionUser }) => (
|
|
|
|
|
|
<TouchableOpacity
|
|
|
|
|
|
style={[styles.mentionItem, { borderBottomColor: colors.divider }]}
|
|
|
|
|
|
onPress={() => handleSelectMention(item)}
|
2026-04-24 16:44:01 +08:00
|
|
|
|
activeOpacity={0.7}
|
2026-04-23 22:29:58 +08:00
|
|
|
|
>
|
2026-04-24 16:44:01 +08:00
|
|
|
|
<Avatar source={item.avatar} size={36} name={item.nickname} />
|
|
|
|
|
|
<View style={styles.mentionInfo}>
|
|
|
|
|
|
<Text style={[styles.mentionName, { color: colors.text.primary }]}>
|
|
|
|
|
|
{item.nickname}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Text style={[styles.mentionHint, { color: colors.text.hint }]}>
|
|
|
|
|
|
点击提及
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
<MaterialCommunityIcons name="at" size={18} color={colors.primary.main} />
|
2026-04-23 22:29:58 +08:00
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
2026-04-24 16:44:01 +08:00
|
|
|
|
<View style={[styles.container, style]}>
|
2026-04-23 22:29:58 +08:00
|
|
|
|
<TextInput
|
|
|
|
|
|
ref={inputRef}
|
|
|
|
|
|
value={value}
|
|
|
|
|
|
onChangeText={handleChangeText}
|
|
|
|
|
|
placeholder={placeholder}
|
|
|
|
|
|
placeholderTextColor={colors.text.hint}
|
|
|
|
|
|
maxLength={maxLength}
|
|
|
|
|
|
multiline
|
2026-04-24 16:44:01 +08:00
|
|
|
|
textAlignVertical="top"
|
|
|
|
|
|
scrollEnabled={!autoExpand}
|
2026-05-06 12:53:39 +08:00
|
|
|
|
returnKeyType={returnKeyType}
|
|
|
|
|
|
onSubmitEditing={onSubmitEditing}
|
|
|
|
|
|
blurOnSubmit={false}
|
2026-04-23 22:29:58 +08:00
|
|
|
|
style={[
|
|
|
|
|
|
styles.input,
|
2026-04-24 16:44:01 +08:00
|
|
|
|
autoExpand && styles.inputAutoExpand,
|
2026-04-23 22:29:58 +08:00
|
|
|
|
{
|
|
|
|
|
|
color: colors.text.primary,
|
2026-04-24 16:44:01 +08:00
|
|
|
|
backgroundColor: autoExpand ? 'transparent' : colors.background.default,
|
|
|
|
|
|
minHeight,
|
2026-04-23 22:29:58 +08:00
|
|
|
|
},
|
|
|
|
|
|
]}
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
2026-04-26 01:11:30 +08:00
|
|
|
|
{suggestionMode === 'mention' && filteredUsers.length > 0 && (
|
2026-04-23 22:29:58 +08:00
|
|
|
|
<View style={[styles.mentionPanel, { backgroundColor: colors.background.paper, borderColor: colors.divider }]}>
|
2026-04-26 01:11:30 +08:00
|
|
|
|
<ScrollView
|
2026-04-23 22:29:58 +08:00
|
|
|
|
keyboardShouldPersistTaps="handled"
|
|
|
|
|
|
nestedScrollEnabled
|
|
|
|
|
|
style={styles.mentionList}
|
2026-04-26 01:11:30 +08:00
|
|
|
|
>
|
|
|
|
|
|
{filteredUsers.map(item => (
|
|
|
|
|
|
<React.Fragment key={item.id}>
|
|
|
|
|
|
{renderMentionItem({ item })}
|
|
|
|
|
|
</React.Fragment>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</ScrollView>
|
2026-04-23 22:29:58 +08:00
|
|
|
|
</View>
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
2026-04-26 01:11:30 +08:00
|
|
|
|
{suggestionMode === 'mention' && filteredUsers.length === 0 && (
|
2026-04-23 22:29:58 +08:00
|
|
|
|
<View style={[styles.mentionPanel, { backgroundColor: colors.background.paper, borderColor: colors.divider }]}>
|
|
|
|
|
|
<Text style={[styles.emptyText, { color: colors.text.hint }]}>
|
|
|
|
|
|
没有找到匹配的关注用户
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
)}
|
2026-04-26 01:11:30 +08:00
|
|
|
|
|
|
|
|
|
|
{suggestionMode === 'postref' && suggestPosts.length > 0 && (
|
|
|
|
|
|
<View style={[styles.mentionPanel, { backgroundColor: colors.background.paper, borderColor: colors.divider }]}>
|
|
|
|
|
|
<ScrollView
|
|
|
|
|
|
keyboardShouldPersistTaps="handled"
|
|
|
|
|
|
nestedScrollEnabled
|
|
|
|
|
|
style={styles.mentionList}
|
|
|
|
|
|
>
|
|
|
|
|
|
{suggestPosts.map(item => (
|
|
|
|
|
|
<TouchableOpacity
|
|
|
|
|
|
key={item.id}
|
|
|
|
|
|
style={[styles.mentionItem, { borderBottomColor: colors.divider }]}
|
|
|
|
|
|
onPress={() => handleSelectPost(item)}
|
|
|
|
|
|
activeOpacity={0.7}
|
|
|
|
|
|
>
|
|
|
|
|
|
<MaterialCommunityIcons name="file-document-outline" size={18} color={colors.primary.main} />
|
|
|
|
|
|
<View style={styles.mentionInfo}>
|
|
|
|
|
|
<Text style={[styles.mentionName, { color: colors.text.primary }]} numberOfLines={1}>
|
|
|
|
|
|
{item.title}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Text style={[styles.mentionHint, { color: colors.text.hint }]}>
|
|
|
|
|
|
点击引用帖子
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</ScrollView>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
{suggestionMode === 'postref' && suggestPosts.length === 0 && (
|
|
|
|
|
|
<View style={[styles.mentionPanel, { backgroundColor: colors.background.paper, borderColor: colors.divider }]}>
|
|
|
|
|
|
<Text style={[styles.emptyText, { color: colors.text.hint }]}>
|
|
|
|
|
|
没有找到匹配的帖子
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
)}
|
2026-04-23 22:29:58 +08:00
|
|
|
|
</View>
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
2026-04-24 16:44:01 +08:00
|
|
|
|
container: {
|
|
|
|
|
|
flexGrow: 1,
|
|
|
|
|
|
},
|
2026-04-23 22:29:58 +08:00
|
|
|
|
input: {
|
|
|
|
|
|
fontSize: fontSizes.md,
|
|
|
|
|
|
padding: spacing.sm,
|
|
|
|
|
|
borderRadius: borderRadius.md,
|
|
|
|
|
|
minHeight: 100,
|
|
|
|
|
|
textAlignVertical: 'top' as const,
|
|
|
|
|
|
},
|
2026-04-24 16:44:01 +08:00
|
|
|
|
inputAutoExpand: {
|
|
|
|
|
|
borderRadius: 0,
|
|
|
|
|
|
paddingHorizontal: 0,
|
|
|
|
|
|
paddingTop: spacing.sm,
|
|
|
|
|
|
paddingBottom: spacing.sm,
|
|
|
|
|
|
},
|
2026-04-23 22:29:58 +08:00
|
|
|
|
mentionPanel: {
|
|
|
|
|
|
borderWidth: 1,
|
|
|
|
|
|
borderRadius: borderRadius.md,
|
|
|
|
|
|
maxHeight: 200,
|
|
|
|
|
|
marginTop: spacing.xs,
|
|
|
|
|
|
},
|
|
|
|
|
|
mentionList: {
|
|
|
|
|
|
maxHeight: 200,
|
|
|
|
|
|
},
|
|
|
|
|
|
mentionItem: {
|
|
|
|
|
|
flexDirection: 'row',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
paddingHorizontal: spacing.md,
|
|
|
|
|
|
paddingVertical: spacing.sm,
|
|
|
|
|
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
|
|
|
|
},
|
2026-04-24 16:44:01 +08:00
|
|
|
|
mentionInfo: {
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
marginLeft: spacing.sm,
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
},
|
2026-04-23 22:29:58 +08:00
|
|
|
|
mentionName: {
|
|
|
|
|
|
fontSize: fontSizes.md,
|
2026-04-24 16:44:01 +08:00
|
|
|
|
fontWeight: '500',
|
|
|
|
|
|
},
|
|
|
|
|
|
mentionHint: {
|
|
|
|
|
|
fontSize: fontSizes.xs,
|
|
|
|
|
|
marginTop: 2,
|
2026-04-23 22:29:58 +08:00
|
|
|
|
},
|
|
|
|
|
|
emptyText: {
|
|
|
|
|
|
fontSize: fontSizes.sm,
|
|
|
|
|
|
padding: spacing.md,
|
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export default PostMentionInput;
|