|
|
@ -1,5 +1,5 @@ |
|
|
<template> |
|
|
<template> |
|
|
<view class="room-page"> |
|
|
<view class="room-page" @tap="handleBlankTap"> |
|
|
<view class="glow glow-a"></view> |
|
|
<view class="glow glow-a"></view> |
|
|
<view class="glow glow-b"></view> |
|
|
<view class="glow glow-b"></view> |
|
|
<view class="nav" :style="{ paddingTop: menuButtonInfo.top + 'px' }"> |
|
|
<view class="nav" :style="{ paddingTop: menuButtonInfo.top + 'px' }"> |
|
|
@ -87,7 +87,7 @@ |
|
|
<view id="message-bottom-anchor" class="message-bottom-spacer" :style="{ height: bottomSafePadding }"></view> |
|
|
<view id="message-bottom-anchor" class="message-bottom-spacer" :style="{ height: bottomSafePadding }"></view> |
|
|
</scroll-view> |
|
|
</scroll-view> |
|
|
|
|
|
|
|
|
<view class="presence-row" :style="{ bottom: presenceBottom }"> |
|
|
<view class="presence-row" :style="{ bottom: presenceBottom }" @tap.stop> |
|
|
<view class="presence-chip quiz-chip" @tap="openQuiz">🎯 {{ quizButtonText }}</view> |
|
|
<view class="presence-chip quiz-chip" @tap="openQuiz">🎯 {{ quizButtonText }}</view> |
|
|
<view class="presence-chip" v-for="item in presenceActions" :key="item" @tap="sendPresence(item)"> |
|
|
<view class="presence-chip" v-for="item in presenceActions" :key="item" @tap="sendPresence(item)"> |
|
|
{{ item }} |
|
|
{{ item }} |
|
|
@ -103,7 +103,7 @@ |
|
|
</view> |
|
|
</view> |
|
|
<view class="emoji-close-mask" v-if="showEmoji" @tap="closeEmoji"></view> |
|
|
<view class="emoji-close-mask" v-if="showEmoji" @tap="closeEmoji"></view> |
|
|
|
|
|
|
|
|
<view class="input-bar" :style="{ bottom: inputBarBottom }"> |
|
|
<view class="input-bar" :style="{ bottom: inputBarBottom }" @tap.stop> |
|
|
<view class="tool-btn" @tap="toggleEmoji">☺</view> |
|
|
<view class="tool-btn" @tap="toggleEmoji">☺</view> |
|
|
<view class="tool-btn voice-toggle" @tap="toggleVoiceMode">{{ voiceMode ? '⌨' : '🎙' }}</view> |
|
|
<view class="tool-btn voice-toggle" @tap="toggleVoiceMode">{{ voiceMode ? '⌨' : '🎙' }}</view> |
|
|
<input class="input" v-if="!voiceMode" v-model="draft" :focus="inputFocus" hold-keyboard="true" :confirm-hold="true" confirm-type="send" :disabled="isBlocked" :placeholder="isBlocked ? '已加入黑名单,无法继续发送' : '轻轻说一句,或保持安静'" |
|
|
<input class="input" v-if="!voiceMode" v-model="draft" :focus="inputFocus" hold-keyboard="true" :confirm-hold="true" confirm-type="send" :disabled="isBlocked" :placeholder="isBlocked ? '已加入黑名单,无法继续发送' : '轻轻说一句,或保持安静'" |
|
|
@ -271,6 +271,7 @@ |
|
|
messagePage: 1, |
|
|
messagePage: 1, |
|
|
messagePageSize: 20, |
|
|
messagePageSize: 20, |
|
|
hasMoreMessages: true, |
|
|
hasMoreMessages: true, |
|
|
|
|
|
hasPeerReply: false, |
|
|
loadingMessages: false, |
|
|
loadingMessages: false, |
|
|
scrollIntoView: '', |
|
|
scrollIntoView: '', |
|
|
scrollAnimation: true, |
|
|
scrollAnimation: true, |
|
|
@ -469,6 +470,20 @@ |
|
|
this.scrollToBottom(false) |
|
|
this.scrollToBottom(false) |
|
|
}, 120) |
|
|
}, 120) |
|
|
}, |
|
|
}, |
|
|
|
|
|
handleBlankTap() { |
|
|
|
|
|
this.closeInput() |
|
|
|
|
|
}, |
|
|
|
|
|
closeInput() { |
|
|
|
|
|
this.inputFocus = false |
|
|
|
|
|
this.showEmoji = false |
|
|
|
|
|
if (uni.hideKeyboard) uni.hideKeyboard() |
|
|
|
|
|
if (this.keyboardHeight > 0) { |
|
|
|
|
|
this.keyboardHeight = 0 |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
this.scrollToBottom(false) |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
localMessageKey() { |
|
|
localMessageKey() { |
|
|
return this.roomId ? 'ie_chat_local_messages_' + this.roomId : '' |
|
|
return this.roomId ? 'ie_chat_local_messages_' + this.roomId : '' |
|
|
}, |
|
|
}, |
|
|
@ -590,6 +605,7 @@ |
|
|
mediaFormat: item.mediaFormat, |
|
|
mediaFormat: item.mediaFormat, |
|
|
poster: item.poster || item.thumbTempFilePath || '', |
|
|
poster: item.poster || item.thumbTempFilePath || '', |
|
|
mine, |
|
|
mine, |
|
|
|
|
|
hasPeerReply: !!item.hasPeerReply, |
|
|
pending: item.mediaAuditStatus === 1, |
|
|
pending: item.mediaAuditStatus === 1, |
|
|
blocked: item.isBlocked === 1, |
|
|
blocked: item.isBlocked === 1, |
|
|
blockTip: item.auditTip || (item.isBlocked === 1 ? '内容未通过审核,请换一个更合适的内容' : ''), |
|
|
blockTip: item.auditTip || (item.isBlocked === 1 ? '内容未通过审核,请换一个更合适的内容' : ''), |
|
|
@ -725,6 +741,7 @@ |
|
|
!(item.clientMsgId && exists.has(item.clientMsgId))) |
|
|
!(item.clientMsgId && exists.has(item.clientMsgId))) |
|
|
this.mergeMessageStatus(latest) |
|
|
this.mergeMessageStatus(latest) |
|
|
if (!appended.length) return |
|
|
if (!appended.length) return |
|
|
|
|
|
this.rememberPeerReply(appended) |
|
|
this.messages = this.messages.concat(appended) |
|
|
this.messages = this.messages.concat(appended) |
|
|
this.scrollToBottom() |
|
|
this.scrollToBottom() |
|
|
}, |
|
|
}, |
|
|
@ -738,6 +755,7 @@ |
|
|
local.blocked = !!remote.blocked |
|
|
local.blocked = !!remote.blocked |
|
|
local.blockTip = remote.blockTip || (local.blocked ? '内容未通过审核,请换一个更合适的内容' : '') |
|
|
local.blockTip = remote.blockTip || (local.blocked ? '内容未通过审核,请换一个更合适的内容' : '') |
|
|
local.mediaAuditStatus = remote.mediaAuditStatus || local.mediaAuditStatus || 0 |
|
|
local.mediaAuditStatus = remote.mediaAuditStatus || local.mediaAuditStatus || 0 |
|
|
|
|
|
if (remote.hasPeerReply) this.hasPeerReply = true |
|
|
local.messageId = remote.messageId || local.messageId |
|
|
local.messageId = remote.messageId || local.messageId |
|
|
local.poster = remote.poster || local.poster || '' |
|
|
local.poster = remote.poster || local.poster || '' |
|
|
local.localOnly = false |
|
|
local.localOnly = false |
|
|
@ -756,6 +774,10 @@ |
|
|
const records = Array.isArray(page) ? page : (page.records || []) |
|
|
const records = Array.isArray(page) ? page : (page.records || []) |
|
|
return records.map(item => this.normalizeMessage(item)).reverse() |
|
|
return records.map(item => this.normalizeMessage(item)).reverse() |
|
|
}, |
|
|
}, |
|
|
|
|
|
rememberPeerReply(list) { |
|
|
|
|
|
if (this.hasPeerReply) return |
|
|
|
|
|
this.hasPeerReply = (list || []).some(item => item && (item.hasPeerReply || (!item.mine && item.messageType && !item.blocked))) |
|
|
|
|
|
}, |
|
|
async loadLatestMessages() { |
|
|
async loadLatestMessages() { |
|
|
if (!this.roomId) return |
|
|
if (!this.roomId) return |
|
|
this.messagePage = 1 |
|
|
this.messagePage = 1 |
|
|
@ -768,6 +790,7 @@ |
|
|
} |
|
|
} |
|
|
const page = await pageIeMessages(this.roomId, this.messagePage, this.messagePageSize) |
|
|
const page = await pageIeMessages(this.roomId, this.messagePage, this.messagePageSize) |
|
|
const latest = this.normalizePage(page) |
|
|
const latest = this.normalizePage(page) |
|
|
|
|
|
this.rememberPeerReply(latest) |
|
|
if (!latest.length && this.messages.length) { |
|
|
if (!latest.length && this.messages.length) { |
|
|
this.hasMoreMessages = false |
|
|
this.hasMoreMessages = false |
|
|
return |
|
|
return |
|
|
@ -787,6 +810,7 @@ |
|
|
try { |
|
|
try { |
|
|
const page = await pageIeMessages(this.roomId, nextPage, this.messagePageSize) |
|
|
const page = await pageIeMessages(this.roomId, nextPage, this.messagePageSize) |
|
|
const older = this.normalizePage(page) |
|
|
const older = this.normalizePage(page) |
|
|
|
|
|
this.rememberPeerReply(older) |
|
|
const exists = new Set(this.messages.map(item => item.messageId || item.clientMsgId)) |
|
|
const exists = new Set(this.messages.map(item => item.messageId || item.clientMsgId)) |
|
|
const deduped = older.filter(item => !exists.has(item.messageId || item.clientMsgId)) |
|
|
const deduped = older.filter(item => !exists.has(item.messageId || item.clientMsgId)) |
|
|
this.messages = deduped.concat(this.messages) |
|
|
this.messages = deduped.concat(this.messages) |
|
|
@ -974,8 +998,12 @@ |
|
|
return true |
|
|
return true |
|
|
}, |
|
|
}, |
|
|
needWaitReply() { |
|
|
needWaitReply() { |
|
|
|
|
|
if (this.hasPeerReply) return false |
|
|
const delivered = this.messages.filter(item => item && !item.blocked && item.messageType) |
|
|
const delivered = this.messages.filter(item => item && !item.blocked && item.messageType) |
|
|
if (delivered.some(item => !item.mine)) return false |
|
|
if (delivered.some(item => !item.mine)) { |
|
|
|
|
|
this.hasPeerReply = true |
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
return delivered.filter(item => item.mine).length >= 3 |
|
|
return delivered.filter(item => item.mine).length >= 3 |
|
|
}, |
|
|
}, |
|
|
async persistMessage(payload) { |
|
|
async persistMessage(payload) { |
|
|
@ -1005,6 +1033,7 @@ |
|
|
msg.mediaFormat = ack.mediaFormat || msg.mediaFormat |
|
|
msg.mediaFormat = ack.mediaFormat || msg.mediaFormat |
|
|
msg.poster = ack.poster || msg.poster || '' |
|
|
msg.poster = ack.poster || msg.poster || '' |
|
|
msg.mediaAuditStatus = ack.mediaAuditStatus || msg.mediaAuditStatus || 0 |
|
|
msg.mediaAuditStatus = ack.mediaAuditStatus || msg.mediaAuditStatus || 0 |
|
|
|
|
|
if (ack.hasPeerReply) this.hasPeerReply = true |
|
|
msg.blocked = ack.isBlocked === 1 |
|
|
msg.blocked = ack.isBlocked === 1 |
|
|
msg.localOnly = false |
|
|
msg.localOnly = false |
|
|
msg.localState = '' |
|
|
msg.localState = '' |
|
|
@ -1628,7 +1657,9 @@ |
|
|
this.applyAck(msg) |
|
|
this.applyAck(msg) |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
this.messages.push(this.normalizeMessage(msg)) |
|
|
const normalized = this.normalizeMessage(msg) |
|
|
|
|
|
this.rememberPeerReply([normalized]) |
|
|
|
|
|
this.messages.push(normalized) |
|
|
this.scrollToBottom() |
|
|
this.scrollToBottom() |
|
|
}) |
|
|
}) |
|
|
ieSocket.onPresence((event) => { |
|
|
ieSocket.onPresence((event) => { |
|
|
|