global update and global fix
This commit is contained in:
89
apps/frontend/lib/chat-message-utils.ts
Normal file
89
apps/frontend/lib/chat-message-utils.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import type { ChatMessage } from '@/lib/api';
|
||||
import { emojiIdToNative, resolveNativeEmojiContent } from '@/lib/emoji-native-map';
|
||||
|
||||
export const QUICK_REACTIONS = ['👍', '❤️', '😂', '😮', '😢', '🙏', '🔥', '👏'] as const;
|
||||
|
||||
export interface ForwardedFromMeta {
|
||||
messageId: string;
|
||||
roomId: string;
|
||||
senderId: string;
|
||||
senderName: string;
|
||||
type: string;
|
||||
content?: string;
|
||||
}
|
||||
|
||||
export function parseForwardedFrom(metadataJson?: string): ForwardedFromMeta | null {
|
||||
if (!metadataJson) return null;
|
||||
try {
|
||||
const meta = JSON.parse(metadataJson) as { forwardedFrom?: ForwardedFromMeta };
|
||||
const forwarded = meta.forwardedFrom;
|
||||
return forwarded?.messageId ? forwarded : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function getMessageCopyText(message: ChatMessage, visibleText?: string) {
|
||||
if (message.isDeleted) return '';
|
||||
if (visibleText?.trim()) return resolveNativeEmojiContent(visibleText.trim());
|
||||
if (message.content?.trim()) {
|
||||
if (message.type === 'EMOJI') {
|
||||
return emojiIdToNative(message.content.trim()) ?? message.content.trim();
|
||||
}
|
||||
return resolveNativeEmojiContent(message.content.trim());
|
||||
}
|
||||
if (message.type === 'POLL' && message.poll) return message.poll.question;
|
||||
return '';
|
||||
}
|
||||
|
||||
export function getMessagePreviewText(message: ChatMessage, visibleText?: string) {
|
||||
if (message.type === 'SYSTEM') {
|
||||
return resolveNativeEmojiContent(message.content?.trim() ?? 'Системное сообщение');
|
||||
}
|
||||
if (message.type === 'POLL' && message.poll) {
|
||||
return `📊 Опрос: ${message.poll.question}`;
|
||||
}
|
||||
const text = getMessageCopyText(message, visibleText);
|
||||
if (text) return text;
|
||||
if (message.type === 'IMAGE') return '📷 Фото';
|
||||
if (message.type === 'VOICE') return '🎤 Голосовое';
|
||||
if (message.type === 'AUDIO') return '🎵 Аудио';
|
||||
if (message.type === 'FILE') return '📄 Файл';
|
||||
if (message.isEncrypted) return '🔒 Зашифрованное сообщение';
|
||||
return 'Сообщение';
|
||||
}
|
||||
|
||||
export function getChatListPreviewText(message?: ChatMessage | null, fallback = '') {
|
||||
if (!message || message.isDeleted) return fallback;
|
||||
return getMessagePreviewText(message);
|
||||
}
|
||||
|
||||
export function isSystemMessage(message: ChatMessage) {
|
||||
return message.type === 'SYSTEM';
|
||||
}
|
||||
|
||||
export function isSelectableMessage(message: ChatMessage) {
|
||||
return !message.isDeleted && !isSystemMessage(message);
|
||||
}
|
||||
|
||||
export function isChatInteractiveTarget(target: EventTarget | null) {
|
||||
if (!(target instanceof HTMLElement)) return false;
|
||||
return Boolean(
|
||||
target.closest('button, a, input, textarea, select, label, [contenteditable="true"], [data-chat-interactive="true"]')
|
||||
);
|
||||
}
|
||||
|
||||
export function canEditMessage(message: ChatMessage, userId?: string, isE2E?: boolean) {
|
||||
return (
|
||||
Boolean(userId && message.senderId === userId) &&
|
||||
!message.isDeleted &&
|
||||
!isSystemMessage(message) &&
|
||||
!message.isEncrypted &&
|
||||
!isE2E &&
|
||||
(message.type === 'TEXT' || message.type === 'EMOJI')
|
||||
);
|
||||
}
|
||||
|
||||
export function canDeleteMessage(message: ChatMessage, userId?: string) {
|
||||
return Boolean(userId && message.senderId === userId && !message.isDeleted && !isSystemMessage(message));
|
||||
}
|
||||
Reference in New Issue
Block a user