Editing correction (in progress)
This commit is contained in:
@@ -267,16 +267,8 @@ function applyTypingFromServer(
|
||||
at: now,
|
||||
}))
|
||||
.filter((t) => t.userId && t.userId !== sessionCache?.chatUserId);
|
||||
const prev = typingMap.value[rid] || [];
|
||||
// نگه داشتن رویدادهای خیلی تازه از WS اگر سرور هنوز خالی است
|
||||
const merged = new Map<string, { userId: string; name?: string; at: number }>();
|
||||
for (const t of prev) {
|
||||
if (now - t.at < 4000) merged.set(t.userId, t);
|
||||
}
|
||||
for (const t of list) merged.set(t.userId, t);
|
||||
const nextList = [...merged.values()];
|
||||
if (!nextList.length) {
|
||||
if (prev.length) {
|
||||
if (!list.length) {
|
||||
if (typingMap.value[rid]) {
|
||||
const next = { ...typingMap.value };
|
||||
delete next[rid];
|
||||
typingMap.value = next;
|
||||
@@ -284,7 +276,31 @@ function applyTypingFromServer(
|
||||
return;
|
||||
}
|
||||
startTypingSweep();
|
||||
typingMap.value = { ...typingMap.value, [rid]: nextList };
|
||||
typingMap.value = { ...typingMap.value, [rid]: list };
|
||||
}
|
||||
|
||||
function applyTypingFromServerAll(
|
||||
rows: Array<{
|
||||
externalRoomId: string;
|
||||
userId: string;
|
||||
fullName: string;
|
||||
chatUserId: string;
|
||||
}>,
|
||||
) {
|
||||
const now = Date.now();
|
||||
const next: Record<string, Array<{ userId: string; name?: string; at: number }>> = {};
|
||||
for (const row of rows) {
|
||||
const rid = String(row.externalRoomId || '').trim();
|
||||
const uid = String(row.chatUserId || row.userId || '').trim();
|
||||
if (!rid || !uid || uid === sessionCache?.chatUserId) continue;
|
||||
const list = next[rid] || [];
|
||||
if (!list.some((t) => t.userId === uid)) {
|
||||
list.push({ userId: uid, name: row.fullName || undefined, at: now });
|
||||
}
|
||||
next[rid] = list;
|
||||
}
|
||||
typingMap.value = next;
|
||||
if (Object.keys(next).length) startTypingSweep();
|
||||
}
|
||||
|
||||
function parseTypingCommand(content: string): string | null {
|
||||
@@ -318,17 +334,21 @@ function stopTypingPoll() {
|
||||
}
|
||||
}
|
||||
|
||||
function startTypingPoll(roomId: string) {
|
||||
stopTypingPoll();
|
||||
const rid = String(roomId || '').trim();
|
||||
if (!rid) return;
|
||||
/** poll همه اتاقها تا پیشنمایش لیست هم «در حال نوشتن» بگیرد */
|
||||
function startTypingPoll() {
|
||||
if (typingPollTimer) return;
|
||||
const tick = async () => {
|
||||
if (activeRoomId.value !== rid) return;
|
||||
if (!pageOpen.value) return;
|
||||
try {
|
||||
const { data } = await api.get<
|
||||
Array<{ userId: string; fullName: string; chatUserId: string }>
|
||||
>('/conversations/rooms/typing', { params: { externalRoomId: rid } });
|
||||
applyTypingFromServer(rid, Array.isArray(data) ? data : []);
|
||||
Array<{
|
||||
externalRoomId: string;
|
||||
userId: string;
|
||||
fullName: string;
|
||||
chatUserId: string;
|
||||
}>
|
||||
>('/conversations/rooms/typing');
|
||||
applyTypingFromServerAll(Array.isArray(data) ? data : []);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
@@ -1130,6 +1150,11 @@ export function useOrgChat() {
|
||||
|
||||
function setConversationsPageOpen(open: boolean) {
|
||||
pageOpen.value = open;
|
||||
if (open) startTypingPoll();
|
||||
else {
|
||||
stopTypingPoll();
|
||||
typingMap.value = {};
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeMessageList(
|
||||
@@ -1164,9 +1189,8 @@ export function useOrgChat() {
|
||||
loadingOlderMessages.value = false;
|
||||
fetchedRawCount = 0;
|
||||
hasMoreMessages.value = false;
|
||||
clearTypingForRoom(roomId);
|
||||
startHiddenPoll(roomId);
|
||||
startTypingPoll(roomId);
|
||||
startTypingPoll();
|
||||
try {
|
||||
const session = await ensureSession();
|
||||
await connectSocket();
|
||||
@@ -1637,7 +1661,6 @@ export function useOrgChat() {
|
||||
|
||||
function clearActiveRoom() {
|
||||
stopHiddenPoll();
|
||||
stopTypingPoll();
|
||||
activeRoomId.value = '';
|
||||
messages.value = [];
|
||||
}
|
||||
|
||||
@@ -341,7 +341,31 @@ function deliveryLabel(delivery?: ChatDelivery) {
|
||||
return '…';
|
||||
}
|
||||
|
||||
function roomTypingPreview(roomId: string): string {
|
||||
void typingTick.value;
|
||||
const list = (typingMap.value?.[roomId] || []).filter(
|
||||
(t) => Date.now() - t.at < 4000,
|
||||
);
|
||||
if (!list.length) return '';
|
||||
const names = list
|
||||
.map((t) => {
|
||||
if (t.name) return t.name;
|
||||
if (t.userId === '__someone__') return '';
|
||||
return (
|
||||
peers.value.find((p) => p.chatUserId === t.userId)?.fullName ||
|
||||
peers.value.find((p) => p.id === t.userId)?.fullName ||
|
||||
''
|
||||
);
|
||||
})
|
||||
.filter(Boolean);
|
||||
if (!names.length) return 'در حال نوشتن…';
|
||||
if (names.length === 1) return `${names[0]} در حال نوشتن…`;
|
||||
return `${toFaDigits(names.length)} نفر در حال نوشتن…`;
|
||||
}
|
||||
|
||||
function roomPreviewText(room: ConversationRoomDto) {
|
||||
const typing = roomTypingPreview(room.externalRoomId);
|
||||
if (typing) return typing;
|
||||
const raw = (room.lastMessagePreview || '').trim();
|
||||
if (!raw) return 'بدون پیام';
|
||||
if (raw === 'وویس') return 'پیام صوتی';
|
||||
@@ -1648,7 +1672,9 @@ onUnmounted(() => {
|
||||
<UiIcon v-if="room.pinned" name="pin" :size="12" class="room-pin-ic" />
|
||||
{{ roomTitle(room) }}
|
||||
</strong>
|
||||
<small>{{ roomPreviewText(room) }}</small>
|
||||
<small :class="{ 'room-typing': Boolean(roomTypingPreview(room.externalRoomId)) }">{{
|
||||
roomPreviewText(room)
|
||||
}}</small>
|
||||
</span>
|
||||
<span v-if="room.unreadCount" class="unread">{{ toFaDigits(room.unreadCount) }}</span>
|
||||
<time>{{ formatListTime(room.lastMessageAt) }}</time>
|
||||
@@ -2694,6 +2720,10 @@ onUnmounted(() => {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
}
|
||||
.room-meta small.room-typing {
|
||||
color: #0f766e;
|
||||
font-weight: 600;
|
||||
}
|
||||
.unread {
|
||||
grid-column: 3;
|
||||
grid-row: 1;
|
||||
|
||||
Reference in New Issue
Block a user