perf: cache media and coalesce realtime sync
This commit is contained in:
@@ -6,6 +6,10 @@ server {
|
|||||||
root /var/www/im-web;
|
root /var/www/im-web;
|
||||||
index index.html;
|
index index.html;
|
||||||
client_max_body_size 100m;
|
client_max_body_size 100m;
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types application/json;
|
||||||
|
|
||||||
location = / {
|
location = / {
|
||||||
try_files /index.html =404;
|
try_files /index.html =404;
|
||||||
@@ -18,6 +22,13 @@ server {
|
|||||||
add_header Cache-Control "no-store";
|
add_header Cache-Control "no-store";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location = /api/media_proxy.php {
|
||||||
|
include snippets/fastcgi-php.conf;
|
||||||
|
fastcgi_param PHP_ADMIN_VALUE "open_basedir=/var/www/im-web/:/tmp/";
|
||||||
|
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
|
||||||
|
fastcgi_read_timeout 300;
|
||||||
|
}
|
||||||
|
|
||||||
location ~ ^/api/.+\.php$ {
|
location ~ ^/api/.+\.php$ {
|
||||||
include snippets/fastcgi-php.conf;
|
include snippets/fastcgi-php.conf;
|
||||||
fastcgi_param PHP_ADMIN_VALUE "open_basedir=/var/www/im-web/:/tmp/";
|
fastcgi_param PHP_ADMIN_VALUE "open_basedir=/var/www/im-web/:/tmp/";
|
||||||
|
|||||||
Vendored
+51
-15
@@ -1521,11 +1521,27 @@ function loadRecentConversations(PDO $db, string $userId, int $limit): array
|
|||||||
return array_slice($conversations, 0, $limit);
|
return array_slice($conversations, 0, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function messageSyncResult(
|
||||||
|
PDO $db,
|
||||||
|
string $userId,
|
||||||
|
array $messages,
|
||||||
|
bool $includeConversations,
|
||||||
|
int $limit
|
||||||
|
): array {
|
||||||
|
$result = ['messages' => $messages];
|
||||||
|
if ($includeConversations) {
|
||||||
|
$result['conversations'] = loadRecentConversations($db, $userId, $limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
$payload = readJsonPayload();
|
$payload = readJsonPayload();
|
||||||
$userId = trim((string)($payload['userId'] ?? ''));
|
$userId = trim((string)($payload['userId'] ?? ''));
|
||||||
$target = trim((string)($payload['target'] ?? ''));
|
$target = trim((string)($payload['target'] ?? ''));
|
||||||
$limit = clampLimit($payload['limit'] ?? 50, 50, 100);
|
$limit = clampLimit($payload['limit'] ?? 50, 50, 100);
|
||||||
$markRead = payloadBool($payload['markRead'] ?? false);
|
$markRead = payloadBool($payload['markRead'] ?? false);
|
||||||
|
$includeConversations = payloadBool($payload['includeConversations'] ?? false);
|
||||||
$conversationType = normalizeConversationType($payload['conversationType'] ?? $payload['type'] ?? 0);
|
$conversationType = normalizeConversationType($payload['conversationType'] ?? $payload['type'] ?? 0);
|
||||||
|
|
||||||
if ($userId === '') {
|
if ($userId === '') {
|
||||||
@@ -1540,28 +1556,48 @@ try {
|
|||||||
if ($target !== '') {
|
if ($target !== '') {
|
||||||
if ($conversationType === 'group') {
|
if ($conversationType === 'group') {
|
||||||
if (isWebGroupTarget(imAppDb(), $target)) {
|
if (isWebGroupTarget(imAppDb(), $target)) {
|
||||||
respond(0, 'success', [
|
respond(0, 'success', messageSyncResult(
|
||||||
'messages' => loadWebGroupMessages(imAppDb(), $userId, $target, $limit, $markRead),
|
$db,
|
||||||
]);
|
$userId,
|
||||||
|
loadWebGroupMessages(imAppDb(), $userId, $target, $limit, $markRead),
|
||||||
|
$includeConversations,
|
||||||
|
$limit
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (isNativeGroupTarget($db, $target)) {
|
if (isNativeGroupTarget($db, $target)) {
|
||||||
respond(0, 'success', [
|
respond(0, 'success', messageSyncResult(
|
||||||
'messages' => loadNativeGroupMessages($db, $userId, $target, $limit, $markRead),
|
$db,
|
||||||
]);
|
$userId,
|
||||||
|
loadNativeGroupMessages($db, $userId, $target, $limit, $markRead),
|
||||||
|
$includeConversations,
|
||||||
|
$limit
|
||||||
|
));
|
||||||
}
|
}
|
||||||
respond(0, 'success', [
|
respond(0, 'success', messageSyncResult(
|
||||||
'messages' => [],
|
$db,
|
||||||
]);
|
$userId,
|
||||||
|
[],
|
||||||
|
$includeConversations,
|
||||||
|
$limit
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (isWebGroupTarget(imAppDb(), $target)) {
|
if (isWebGroupTarget(imAppDb(), $target)) {
|
||||||
respond(0, 'success', [
|
respond(0, 'success', messageSyncResult(
|
||||||
'messages' => loadWebGroupMessages(imAppDb(), $userId, $target, $limit, $markRead),
|
$db,
|
||||||
]);
|
$userId,
|
||||||
|
loadWebGroupMessages(imAppDb(), $userId, $target, $limit, $markRead),
|
||||||
|
$includeConversations,
|
||||||
|
$limit
|
||||||
|
));
|
||||||
}
|
}
|
||||||
$targetId = resolveUserId($db, $target);
|
$targetId = resolveUserId($db, $target);
|
||||||
respond(0, 'success', [
|
respond(0, 'success', messageSyncResult(
|
||||||
'messages' => loadConversationMessages($db, $userId, $targetId, $limit, $markRead),
|
$db,
|
||||||
]);
|
$userId,
|
||||||
|
loadConversationMessages($db, $userId, $targetId, $limit, $markRead),
|
||||||
|
$includeConversations,
|
||||||
|
$limit
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
respond(0, 'success', [
|
respond(0, 'success', [
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Web IM</title><link rel="icon" href="img/5IuOieu9PF8MJtp43kD2kCkdLVjVwDp7.ico"><script src="config/runtime-config.js"></script><script defer="defer" src="js/chunk-vendors.86756863.js"></script><script defer="defer" src="js/app.a89973f7.js"></script><link href="css/app.2c52dabb.css" rel="stylesheet"></head><body><noscript>请启用 JavaScript 后使用 Web IM。</noscript><div id="app"></div></body></html>
|
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Web IM</title><link rel="icon" href="img/5IuOieu9PF8MJtp43kD2kCkdLVjVwDp7.ico"><script src="config/runtime-config.js"></script><script defer="defer" src="js/chunk-vendors.86756863.js"></script><script defer="defer" src="js/app.631b8b2d.js"></script><link href="css/app.2c52dabb.css" rel="stylesheet"></head><body><noscript>请启用 JavaScript 后使用 Web IM。</noscript><div id="app"></div></body></html>
|
||||||
+34
-8
@@ -6281,7 +6281,8 @@ class HttpImClient {
|
|||||||
target: conversation.target || conversation.raw?.target || conversation.id.replace(/^single-/, ''),
|
target: conversation.target || conversation.raw?.target || conversation.id.replace(/^single-/, ''),
|
||||||
limit,
|
limit,
|
||||||
conversationType: conversation.type || conversation.raw?.type || 0,
|
conversationType: conversation.type || conversation.raw?.type || 0,
|
||||||
markRead: Boolean(options.markRead)
|
markRead: Boolean(options.markRead),
|
||||||
|
includeConversations: Boolean(options.includeConversations)
|
||||||
}, {
|
}, {
|
||||||
withCredentials: false
|
withCredentials: false
|
||||||
});
|
});
|
||||||
@@ -6293,6 +6294,19 @@ class HttpImClient {
|
|||||||
displayTimestamp: message.displayTimestamp || message.timestamp,
|
displayTimestamp: message.displayTimestamp || message.timestamp,
|
||||||
conversationId: conversation.id
|
conversationId: conversation.id
|
||||||
}));
|
}));
|
||||||
|
if (options.includeConversations && Array.isArray(response.data?.result?.conversations)) {
|
||||||
|
const remoteConversations = response.data.result.conversations.map(remoteConversation => ({
|
||||||
|
...remoteConversation,
|
||||||
|
updatedAt: Number(remoteConversation.updatedAt || Date.now()),
|
||||||
|
avatarText: remoteConversation.avatarText || String(remoteConversation.title || remoteConversation.target || '?').slice(0, 1).toUpperCase(),
|
||||||
|
raw: remoteConversation.raw || {
|
||||||
|
type: 'single',
|
||||||
|
target: remoteConversation.target,
|
||||||
|
line: 0
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
this.emit('conversationsChanged', remoteConversations);
|
||||||
|
}
|
||||||
const userId = this.currentUser?.userId || '';
|
const userId = this.currentUser?.userId || '';
|
||||||
const messagesByConversation = readLocalMessages(userId);
|
const messagesByConversation = readLocalMessages(userId);
|
||||||
messagesByConversation[conversation.id] = mergeSyncedMessages(messagesByConversation[conversation.id] || [], messages, conversation.id, userId);
|
messagesByConversation[conversation.id] = mergeSyncedMessages(messagesByConversation[conversation.id] || [], messages, conversation.id, userId);
|
||||||
@@ -8015,6 +8029,7 @@ const useConversationStore = (0,pinia__WEBPACK_IMPORTED_MODULE_19__/* .defineSto
|
|||||||
readPresenceEventsBound: false,
|
readPresenceEventsBound: false,
|
||||||
syncInFlight: false,
|
syncInFlight: false,
|
||||||
pendingReadReceiptConversationId: '',
|
pendingReadReceiptConversationId: '',
|
||||||
|
pendingConversationSync: false,
|
||||||
conversationSyncInFlight: false,
|
conversationSyncInFlight: false,
|
||||||
messageSyncTimer: null,
|
messageSyncTimer: null,
|
||||||
messageSyncQueuedAt: 0,
|
messageSyncQueuedAt: 0,
|
||||||
@@ -8126,6 +8141,7 @@ const useConversationStore = (0,pinia__WEBPACK_IMPORTED_MODULE_19__/* .defineSto
|
|||||||
this.syncInFlight = false;
|
this.syncInFlight = false;
|
||||||
this.conversationSyncInFlight = false;
|
this.conversationSyncInFlight = false;
|
||||||
this.pendingReadReceiptConversationId = '';
|
this.pendingReadReceiptConversationId = '';
|
||||||
|
this.pendingConversationSync = false;
|
||||||
this.lastReadSyncByConversation = {};
|
this.lastReadSyncByConversation = {};
|
||||||
this.activeId = '';
|
this.activeId = '';
|
||||||
this.conversations = [];
|
this.conversations = [];
|
||||||
@@ -8560,6 +8576,9 @@ const useConversationStore = (0,pinia__WEBPACK_IMPORTED_MODULE_19__/* .defineSto
|
|||||||
if (wantsReadReceipt) {
|
if (wantsReadReceipt) {
|
||||||
this.pendingReadReceiptConversationId = conversation.id;
|
this.pendingReadReceiptConversationId = conversation.id;
|
||||||
}
|
}
|
||||||
|
if (options.includeConversations) {
|
||||||
|
this.pendingConversationSync = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.syncInFlight = true;
|
this.syncInFlight = true;
|
||||||
@@ -8567,7 +8586,8 @@ const useConversationStore = (0,pinia__WEBPACK_IMPORTED_MODULE_19__/* .defineSto
|
|||||||
const previousMessages = this.messagesByConversation[syncedConversationId] || [];
|
const previousMessages = this.messagesByConversation[syncedConversationId] || [];
|
||||||
try {
|
try {
|
||||||
const messages = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.fetchRemoteMessages(conversation, 50, {
|
const messages = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.fetchRemoteMessages(conversation, 50, {
|
||||||
markRead
|
markRead,
|
||||||
|
includeConversations: Boolean(options.includeConversations)
|
||||||
});
|
});
|
||||||
if (markRead) {
|
if (markRead) {
|
||||||
this.lastReadSyncByConversation = {
|
this.lastReadSyncByConversation = {
|
||||||
@@ -8608,10 +8628,13 @@ const useConversationStore = (0,pinia__WEBPACK_IMPORTED_MODULE_19__/* .defineSto
|
|||||||
// Keep the local view usable if a polling request misses.
|
// Keep the local view usable if a polling request misses.
|
||||||
} finally {
|
} finally {
|
||||||
this.syncInFlight = false;
|
this.syncInFlight = false;
|
||||||
if (this.pendingReadReceiptConversationId === this.activeId && canMarkReadNow()) {
|
if ((this.pendingReadReceiptConversationId === this.activeId || this.pendingConversationSync) && canMarkReadNow()) {
|
||||||
|
const includeConversations = this.pendingConversationSync;
|
||||||
this.pendingReadReceiptConversationId = '';
|
this.pendingReadReceiptConversationId = '';
|
||||||
|
this.pendingConversationSync = false;
|
||||||
this.scheduleActiveMessagesSync({
|
this.scheduleActiveMessagesSync({
|
||||||
allowReadReceipt: true
|
allowReadReceipt: true,
|
||||||
|
includeConversations
|
||||||
}, 700);
|
}, 700);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8627,7 +8650,8 @@ const useConversationStore = (0,pinia__WEBPACK_IMPORTED_MODULE_19__/* .defineSto
|
|||||||
this.pendingMessageSyncOptions = {
|
this.pendingMessageSyncOptions = {
|
||||||
...this.pendingMessageSyncOptions,
|
...this.pendingMessageSyncOptions,
|
||||||
allowReadReceipt: Boolean(this.pendingMessageSyncOptions.allowReadReceipt || options.allowReadReceipt),
|
allowReadReceipt: Boolean(this.pendingMessageSyncOptions.allowReadReceipt || options.allowReadReceipt),
|
||||||
userAction: Boolean(this.pendingMessageSyncOptions.userAction || options.userAction)
|
userAction: Boolean(this.pendingMessageSyncOptions.userAction || options.userAction),
|
||||||
|
includeConversations: Boolean(this.pendingMessageSyncOptions.includeConversations || options.includeConversations)
|
||||||
};
|
};
|
||||||
const maxWait = 1200;
|
const maxWait = 1200;
|
||||||
const runAt = Math.min(now + Math.max(0, Number(delay) || 0), this.messageSyncQueuedAt + maxWait);
|
const runAt = Math.min(now + Math.max(0, Number(delay) || 0), this.messageSyncQueuedAt + maxWait);
|
||||||
@@ -8664,11 +8688,13 @@ const useConversationStore = (0,pinia__WEBPACK_IMPORTED_MODULE_19__/* .defineSto
|
|||||||
}
|
}
|
||||||
window.clearTimeout(this.realtimeSyncTimer);
|
window.clearTimeout(this.realtimeSyncTimer);
|
||||||
this.realtimeSyncTimer = window.setTimeout(() => {
|
this.realtimeSyncTimer = window.setTimeout(() => {
|
||||||
this.refreshRemoteConversations();
|
|
||||||
if (this.activeId) {
|
if (this.activeId) {
|
||||||
this.scheduleActiveMessagesSync({
|
this.scheduleActiveMessagesSync({
|
||||||
allowReadReceipt: canMarkReadNow()
|
allowReadReceipt: canMarkReadNow(),
|
||||||
|
includeConversations: true
|
||||||
}, 700);
|
}, 700);
|
||||||
|
} else {
|
||||||
|
this.refreshRemoteConversations();
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
},
|
},
|
||||||
@@ -9874,4 +9900,4 @@ const __exports__ = _NavigationRail_vue_vue_type_script_setup_true_lang_js__WEBP
|
|||||||
/******/
|
/******/
|
||||||
/******/ })()
|
/******/ })()
|
||||||
;
|
;
|
||||||
//# sourceMappingURL=app.a89973f7.js.map
|
//# sourceMappingURL=app.631b8b2d.js.map
|
||||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
+51
-15
@@ -1521,11 +1521,27 @@ function loadRecentConversations(PDO $db, string $userId, int $limit): array
|
|||||||
return array_slice($conversations, 0, $limit);
|
return array_slice($conversations, 0, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function messageSyncResult(
|
||||||
|
PDO $db,
|
||||||
|
string $userId,
|
||||||
|
array $messages,
|
||||||
|
bool $includeConversations,
|
||||||
|
int $limit
|
||||||
|
): array {
|
||||||
|
$result = ['messages' => $messages];
|
||||||
|
if ($includeConversations) {
|
||||||
|
$result['conversations'] = loadRecentConversations($db, $userId, $limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
$payload = readJsonPayload();
|
$payload = readJsonPayload();
|
||||||
$userId = trim((string)($payload['userId'] ?? ''));
|
$userId = trim((string)($payload['userId'] ?? ''));
|
||||||
$target = trim((string)($payload['target'] ?? ''));
|
$target = trim((string)($payload['target'] ?? ''));
|
||||||
$limit = clampLimit($payload['limit'] ?? 50, 50, 100);
|
$limit = clampLimit($payload['limit'] ?? 50, 50, 100);
|
||||||
$markRead = payloadBool($payload['markRead'] ?? false);
|
$markRead = payloadBool($payload['markRead'] ?? false);
|
||||||
|
$includeConversations = payloadBool($payload['includeConversations'] ?? false);
|
||||||
$conversationType = normalizeConversationType($payload['conversationType'] ?? $payload['type'] ?? 0);
|
$conversationType = normalizeConversationType($payload['conversationType'] ?? $payload['type'] ?? 0);
|
||||||
|
|
||||||
if ($userId === '') {
|
if ($userId === '') {
|
||||||
@@ -1540,28 +1556,48 @@ try {
|
|||||||
if ($target !== '') {
|
if ($target !== '') {
|
||||||
if ($conversationType === 'group') {
|
if ($conversationType === 'group') {
|
||||||
if (isWebGroupTarget(imAppDb(), $target)) {
|
if (isWebGroupTarget(imAppDb(), $target)) {
|
||||||
respond(0, 'success', [
|
respond(0, 'success', messageSyncResult(
|
||||||
'messages' => loadWebGroupMessages(imAppDb(), $userId, $target, $limit, $markRead),
|
$db,
|
||||||
]);
|
$userId,
|
||||||
|
loadWebGroupMessages(imAppDb(), $userId, $target, $limit, $markRead),
|
||||||
|
$includeConversations,
|
||||||
|
$limit
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (isNativeGroupTarget($db, $target)) {
|
if (isNativeGroupTarget($db, $target)) {
|
||||||
respond(0, 'success', [
|
respond(0, 'success', messageSyncResult(
|
||||||
'messages' => loadNativeGroupMessages($db, $userId, $target, $limit, $markRead),
|
$db,
|
||||||
]);
|
$userId,
|
||||||
|
loadNativeGroupMessages($db, $userId, $target, $limit, $markRead),
|
||||||
|
$includeConversations,
|
||||||
|
$limit
|
||||||
|
));
|
||||||
}
|
}
|
||||||
respond(0, 'success', [
|
respond(0, 'success', messageSyncResult(
|
||||||
'messages' => [],
|
$db,
|
||||||
]);
|
$userId,
|
||||||
|
[],
|
||||||
|
$includeConversations,
|
||||||
|
$limit
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (isWebGroupTarget(imAppDb(), $target)) {
|
if (isWebGroupTarget(imAppDb(), $target)) {
|
||||||
respond(0, 'success', [
|
respond(0, 'success', messageSyncResult(
|
||||||
'messages' => loadWebGroupMessages(imAppDb(), $userId, $target, $limit, $markRead),
|
$db,
|
||||||
]);
|
$userId,
|
||||||
|
loadWebGroupMessages(imAppDb(), $userId, $target, $limit, $markRead),
|
||||||
|
$includeConversations,
|
||||||
|
$limit
|
||||||
|
));
|
||||||
}
|
}
|
||||||
$targetId = resolveUserId($db, $target);
|
$targetId = resolveUserId($db, $target);
|
||||||
respond(0, 'success', [
|
respond(0, 'success', messageSyncResult(
|
||||||
'messages' => loadConversationMessages($db, $userId, $targetId, $limit, $markRead),
|
$db,
|
||||||
]);
|
$userId,
|
||||||
|
loadConversationMessages($db, $userId, $targetId, $limit, $markRead),
|
||||||
|
$includeConversations,
|
||||||
|
$limit
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
respond(0, 'success', [
|
respond(0, 'success', [
|
||||||
|
|||||||
@@ -379,7 +379,8 @@ export class HttpImClient {
|
|||||||
target: conversation.target || conversation.raw?.target || conversation.id.replace(/^single-/, ''),
|
target: conversation.target || conversation.raw?.target || conversation.id.replace(/^single-/, ''),
|
||||||
limit,
|
limit,
|
||||||
conversationType: conversation.type || conversation.raw?.type || 0,
|
conversationType: conversation.type || conversation.raw?.type || 0,
|
||||||
markRead: Boolean(options.markRead)
|
markRead: Boolean(options.markRead),
|
||||||
|
includeConversations: Boolean(options.includeConversations)
|
||||||
}, { withCredentials: false });
|
}, { withCredentials: false });
|
||||||
|
|
||||||
if (response.data?.code !== 0) {
|
if (response.data?.code !== 0) {
|
||||||
@@ -391,6 +392,15 @@ export class HttpImClient {
|
|||||||
displayTimestamp: message.displayTimestamp || message.timestamp,
|
displayTimestamp: message.displayTimestamp || message.timestamp,
|
||||||
conversationId: conversation.id
|
conversationId: conversation.id
|
||||||
}));
|
}));
|
||||||
|
if (options.includeConversations && Array.isArray(response.data?.result?.conversations)) {
|
||||||
|
const remoteConversations = response.data.result.conversations.map(remoteConversation => ({
|
||||||
|
...remoteConversation,
|
||||||
|
updatedAt: Number(remoteConversation.updatedAt || Date.now()),
|
||||||
|
avatarText: remoteConversation.avatarText || String(remoteConversation.title || remoteConversation.target || '?').slice(0, 1).toUpperCase(),
|
||||||
|
raw: remoteConversation.raw || { type: 'single', target: remoteConversation.target, line: 0 }
|
||||||
|
}));
|
||||||
|
this.emit('conversationsChanged', remoteConversations);
|
||||||
|
}
|
||||||
const userId = this.currentUser?.userId || '';
|
const userId = this.currentUser?.userId || '';
|
||||||
const messagesByConversation = readLocalMessages(userId);
|
const messagesByConversation = readLocalMessages(userId);
|
||||||
messagesByConversation[conversation.id] = mergeSyncedMessages(messagesByConversation[conversation.id] || [], messages, conversation.id, userId);
|
messagesByConversation[conversation.id] = mergeSyncedMessages(messagesByConversation[conversation.id] || [], messages, conversation.id, userId);
|
||||||
|
|||||||
@@ -345,6 +345,7 @@ export const useConversationStore = defineStore('conversations', {
|
|||||||
readPresenceEventsBound: false,
|
readPresenceEventsBound: false,
|
||||||
syncInFlight: false,
|
syncInFlight: false,
|
||||||
pendingReadReceiptConversationId: '',
|
pendingReadReceiptConversationId: '',
|
||||||
|
pendingConversationSync: false,
|
||||||
conversationSyncInFlight: false,
|
conversationSyncInFlight: false,
|
||||||
messageSyncTimer: null,
|
messageSyncTimer: null,
|
||||||
messageSyncQueuedAt: 0,
|
messageSyncQueuedAt: 0,
|
||||||
@@ -457,6 +458,7 @@ export const useConversationStore = defineStore('conversations', {
|
|||||||
this.syncInFlight = false;
|
this.syncInFlight = false;
|
||||||
this.conversationSyncInFlight = false;
|
this.conversationSyncInFlight = false;
|
||||||
this.pendingReadReceiptConversationId = '';
|
this.pendingReadReceiptConversationId = '';
|
||||||
|
this.pendingConversationSync = false;
|
||||||
this.lastReadSyncByConversation = {};
|
this.lastReadSyncByConversation = {};
|
||||||
this.activeId = '';
|
this.activeId = '';
|
||||||
this.conversations = [];
|
this.conversations = [];
|
||||||
@@ -887,6 +889,9 @@ export const useConversationStore = defineStore('conversations', {
|
|||||||
if (wantsReadReceipt) {
|
if (wantsReadReceipt) {
|
||||||
this.pendingReadReceiptConversationId = conversation.id;
|
this.pendingReadReceiptConversationId = conversation.id;
|
||||||
}
|
}
|
||||||
|
if (options.includeConversations) {
|
||||||
|
this.pendingConversationSync = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.syncInFlight = true;
|
this.syncInFlight = true;
|
||||||
@@ -894,7 +899,8 @@ export const useConversationStore = defineStore('conversations', {
|
|||||||
const previousMessages = this.messagesByConversation[syncedConversationId] || [];
|
const previousMessages = this.messagesByConversation[syncedConversationId] || [];
|
||||||
try {
|
try {
|
||||||
const messages = await imClient.fetchRemoteMessages(conversation, 50, {
|
const messages = await imClient.fetchRemoteMessages(conversation, 50, {
|
||||||
markRead
|
markRead,
|
||||||
|
includeConversations: Boolean(options.includeConversations)
|
||||||
});
|
});
|
||||||
if (markRead) {
|
if (markRead) {
|
||||||
this.lastReadSyncByConversation = {
|
this.lastReadSyncByConversation = {
|
||||||
@@ -938,9 +944,17 @@ export const useConversationStore = defineStore('conversations', {
|
|||||||
// Keep the local view usable if a polling request misses.
|
// Keep the local view usable if a polling request misses.
|
||||||
} finally {
|
} finally {
|
||||||
this.syncInFlight = false;
|
this.syncInFlight = false;
|
||||||
if (this.pendingReadReceiptConversationId === this.activeId && canMarkReadNow()) {
|
if (
|
||||||
|
(this.pendingReadReceiptConversationId === this.activeId || this.pendingConversationSync)
|
||||||
|
&& canMarkReadNow()
|
||||||
|
) {
|
||||||
|
const includeConversations = this.pendingConversationSync;
|
||||||
this.pendingReadReceiptConversationId = '';
|
this.pendingReadReceiptConversationId = '';
|
||||||
this.scheduleActiveMessagesSync({ allowReadReceipt: true }, 700);
|
this.pendingConversationSync = false;
|
||||||
|
this.scheduleActiveMessagesSync({
|
||||||
|
allowReadReceipt: true,
|
||||||
|
includeConversations
|
||||||
|
}, 700);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -957,7 +971,10 @@ export const useConversationStore = defineStore('conversations', {
|
|||||||
allowReadReceipt: Boolean(
|
allowReadReceipt: Boolean(
|
||||||
this.pendingMessageSyncOptions.allowReadReceipt || options.allowReadReceipt
|
this.pendingMessageSyncOptions.allowReadReceipt || options.allowReadReceipt
|
||||||
),
|
),
|
||||||
userAction: Boolean(this.pendingMessageSyncOptions.userAction || options.userAction)
|
userAction: Boolean(this.pendingMessageSyncOptions.userAction || options.userAction),
|
||||||
|
includeConversations: Boolean(
|
||||||
|
this.pendingMessageSyncOptions.includeConversations || options.includeConversations
|
||||||
|
)
|
||||||
};
|
};
|
||||||
const maxWait = 1200;
|
const maxWait = 1200;
|
||||||
const runAt = Math.min(now + Math.max(0, Number(delay) || 0), this.messageSyncQueuedAt + maxWait);
|
const runAt = Math.min(now + Math.max(0, Number(delay) || 0), this.messageSyncQueuedAt + maxWait);
|
||||||
@@ -994,9 +1011,13 @@ export const useConversationStore = defineStore('conversations', {
|
|||||||
}
|
}
|
||||||
window.clearTimeout(this.realtimeSyncTimer);
|
window.clearTimeout(this.realtimeSyncTimer);
|
||||||
this.realtimeSyncTimer = window.setTimeout(() => {
|
this.realtimeSyncTimer = window.setTimeout(() => {
|
||||||
this.refreshRemoteConversations();
|
|
||||||
if (this.activeId) {
|
if (this.activeId) {
|
||||||
this.scheduleActiveMessagesSync({ allowReadReceipt: canMarkReadNow() }, 700);
|
this.scheduleActiveMessagesSync({
|
||||||
|
allowReadReceipt: canMarkReadNow(),
|
||||||
|
includeConversations: true
|
||||||
|
}, 700);
|
||||||
|
} else {
|
||||||
|
this.refreshRemoteConversations();
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user