fix support issue

This commit is contained in:
2026-08-05 12:57:05 +03:30
parent e8d5dc9f66
commit 4dcc3c7135
2 changed files with 60 additions and 16 deletions
@@ -63,7 +63,7 @@
" "
:style="{ opacity: getSwipeOpacity(message.id) }" :style="{ opacity: getSwipeOpacity(message.id) }"
> >
↩ <BaseIcon icon="vuesax-linear:undo" size="16" />
</div> </div>
<div <div
:style="getSwipeStyle(message)" :style="getSwipeStyle(message)"
@@ -215,9 +215,13 @@
<BaseButton <BaseButton
class="admin-reply-button" class="admin-reply-button"
title="پاسخ" title="پاسخ"
@pointerdown.stop
@pointerup.stop
@pointercancel.stop
@pointermove.stop
@click.stop="emit('reply', message)" @click.stop="emit('reply', message)"
> >
<div class="w-1rem h-1rem flex justify-center flex items-center mt-1">↩</div> <BaseIcon icon="vuesax-linear:undo" size="16" />
</BaseButton> </BaseButton>
</div> </div>
</div> </div>
@@ -904,6 +908,8 @@ AdminSupport .admin-bubble__image-wrap {
.admin-day-group { .admin-day-group {
display: block; display: block;
position: relative;
isolation: isolate;
} }
.admin-day-sticky { .admin-day-sticky {
@@ -923,12 +929,13 @@ AdminSupport .admin-bubble__image-wrap {
justify-content: center; justify-content: center;
padding: 7px 14px; padding: 7px 14px;
border-radius: 999px; border-radius: 999px;
background: color-mix(in srgb, var(--admin-bg-elevated, #fff) 88%, transparent); background: var(--admin-bg-elevated, #fff);
border: 1px solid var(--admin-border, #e4e4e7); border: 1px solid var(--admin-border, #e4e4e7);
color: var(--admin-text-muted, #3f3f46); color: var(--admin-text-muted, #3f3f46);
backdrop-filter: blur(8px);
font-size: 12px; font-size: 12px;
font-weight: 700; font-weight: 700;
line-height: 1.4;
white-space: nowrap;
box-shadow: 0 6px 20px var(--admin-shadow, rgba(15, 23, 42, 0.06)); box-shadow: 0 6px 20px var(--admin-shadow, rgba(15, 23, 42, 0.06));
} }
@@ -1210,11 +1217,14 @@ AdminSupport .admin-bubble__image-wrap {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size: 18px;
line-height: 1; line-height: 1;
box-shadow: 0 6px 14px rgba(15, 23, 42, 0.045); box-shadow: 0 6px 14px rgba(15, 23, 42, 0.045);
} }
.admin-reply-button :deep(svg) {
display: block;
}
.admin-typing { .admin-typing {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -1660,7 +1670,6 @@ AdminSupport .admin-bubble__image-wrap {
width: 32px; width: 32px;
height: 32px; height: 32px;
flex: 0 0 32px; flex: 0 0 32px;
font-size: 17px;
} }
.admin-message-row--out .admin-reply-button { .admin-message-row--out .admin-reply-button {
@@ -1858,7 +1867,7 @@ html.is-dark .admin-jump-bottom,
html.is-dark .admin-day-chip { html.is-dark .admin-day-chip {
color: var(--admin-text-muted); color: var(--admin-text-muted);
border-color: var(--admin-border); border-color: var(--admin-border);
background: color-mix(in srgb, var(--admin-bg-elevated) 92%, transparent); background: var(--admin-bg-elevated);
} }
html.is-dark .admin-bubble--in { html.is-dark .admin-bubble--in {
@@ -1927,8 +1936,24 @@ html.is-dark .admin-reply-swipe-cue {
color: var(--admin-gold-light, var(--colorPrimary, #2563eb)); color: var(--admin-gold-light, var(--colorPrimary, #2563eb));
} }
html.is-dark .admin-bubble--in .admin-message__reply,
html.is-dark .admin-bubble--out .admin-message__reply {
background: var(--admin-bg-muted) !important;
}
html.is-dark .admin-bubble--in .admin-message__reply-title {
color: var(--admin-gold-light, var(--colorPrimary, #2563eb)) !important;
}
html.is-dark .admin-bubble--in .admin-message__reply-text { html.is-dark .admin-bubble--in .admin-message__reply-text {
color: var(--admin-text-secondary); color: var(--admin-text) !important;
opacity: 0.92;
}
html.is-dark .admin-bubble--out .admin-message__reply-title,
html.is-dark .admin-bubble--out .admin-message__reply-text {
color: var(--admin-text) !important;
opacity: 0.92;
} }
html.is-dark .typing-dot { html.is-dark .typing-dot {
+27 -8
View File
@@ -40,6 +40,7 @@ type PendingOutgoingAdminMessage = {
type: AdminOutgoingMessageType type: AdminOutgoingMessageType
room_id: string room_id: string
content: string content: string
reply?: string
} }
optimisticKey: string | null optimisticKey: string | null
attempts: number attempts: number
@@ -908,7 +909,8 @@ const appendOptimisticAdminMessage = (
roomId: string, roomId: string,
content: string, content: string,
messageId: string, messageId: string,
typeContent: AdminOutgoingMessageType = 'text' typeContent: AdminOutgoingMessageType = 'text',
replyId: string | null = null
) => { ) => {
const optimistic = normalizeMessage( const optimistic = normalizeMessage(
{ {
@@ -918,6 +920,7 @@ const appendOptimisticAdminMessage = (
content, content,
type_content: typeContent, type_content: typeContent,
type: typeContent, type: typeContent,
reply: replyId || undefined,
created_at: new Date().toISOString() created_at: new Date().toISOString()
}, },
'optimistic' 'optimistic'
@@ -1348,7 +1351,7 @@ export const fetchAdminRooms = async () => {
const existing = existingMap.get(roomId) const existing = existingMap.get(roomId)
const serverUnread = Number(room?.unread_count ?? room?.unreadCount ?? 0) const serverUnread = Number(room?.unread_count ?? room?.unreadCount ?? 0)
const localUnread = Number(existing?.unread_count ?? existing?.unreadCount ?? 0) const localUnread = Number(existing?.unread_count ?? existing?.unreadCount ?? 0)
const unread = isViewingRoomNow(roomId) const unread = canTreatAdminRoomAsRead(roomId)
? 0 ? 0
: Math.max(serverUnread, localUnread) : Math.max(serverUnread, localUnread)
@@ -1513,7 +1516,7 @@ export const setAdminActiveRoom = async (
refreshFocusHeartbeat() refreshFocusHeartbeat()
if (isViewingRoomNow(roomId)) { if (isViewingRoomNow(roomId) && isAdminActiveRoomAtBottom.value) {
clearRoomUnread(roomId) clearRoomUnread(roomId)
} }
@@ -1550,9 +1553,11 @@ export const setAdminActiveRoom = async (
export const sendAdminMessage = async ( export const sendAdminMessage = async (
roomId: string, roomId: string,
content: string, content: string,
type: AdminOutgoingMessageType = 'text' type: AdminOutgoingMessageType = 'text',
replyId: string | null = null
) => { ) => {
const value = content.trim() const value = content.trim()
const reply = replyId ? String(replyId).trim() : ''
if (!roomId) throw new Error('room_id is required') if (!roomId) throw new Error('room_id is required')
if (!value) return if (!value) return
@@ -1570,15 +1575,25 @@ export const sendAdminMessage = async (
} }
const messageId = createUuid() const messageId = createUuid()
const optimisticKey = appendOptimisticAdminMessage(roomId, value, messageId, type) const optimisticKey = appendOptimisticAdminMessage(
roomId,
value,
messageId,
type,
reply || null
)
const payload = { const payload: PendingOutgoingAdminMessage['payload'] = {
id: messageId, id: messageId,
type, type,
room_id: roomId, room_id: roomId,
content: value content: value
} }
if (reply) {
payload.reply = reply
}
pendingOutgoingById.set(messageId, { pendingOutgoingById.set(messageId, {
payload, payload,
optimisticKey, optimisticKey,
@@ -1596,8 +1611,12 @@ export const sendAdminMessage = async (
} }
} }
export const sendAdminTextMessage = async (roomId: string, content: string) => { export const sendAdminTextMessage = async (
return await sendAdminMessage(roomId, content, 'text') roomId: string,
content: string,
replyId: string | null = null
) => {
return await sendAdminMessage(roomId, content, 'text', replyId)
} }
export const sendAdminMediaMessage = async ( export const sendAdminMediaMessage = async (