Editing correction (in progress)

This commit is contained in:
2026-09-30 13:01:42 +03:30
parent 3c0ed3369e
commit c7a60c524d
4 changed files with 135 additions and 23 deletions
+45 -22
View File
@@ -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 = [];
}
+31 -1
View File
@@ -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;