Multitab: Force sync at least every 500ms (#6914)

This commit is contained in:
zubiden 2026-05-05 13:46:25 +02:00 committed by Alexander Zinchuk
parent ee6f56ce7a
commit 0c32fede29
2 changed files with 46 additions and 19 deletions

View File

@ -379,9 +379,10 @@ export function sendApiMessage(
if (!chat) return undefined;
// This is expected to arrive after `updateMessageSendSucceeded` which replaces the local ID,
// so in most cases this will be simply ignored
let isSendCompleted = false;
const timeout = setTimeout(() => {
if (isSendCompleted) return;
sendApiUpdate({
'@type': localMessage.isScheduled ? 'updateScheduledMessage' : 'updateMessage',
id: localMessage.id,
@ -392,6 +393,10 @@ export function sendApiMessage(
isFull: false,
});
}, FAST_SEND_TIMEOUT);
const cancelSendingStatusTimeout = () => {
isSendCompleted = true;
clearTimeout(timeout);
};
const randomId = generateRandomBigInt();
@ -408,7 +413,7 @@ export function sendApiMessage(
scheduledAt,
scheduleRepeatPeriod,
messagePriceInStars,
}, randomId, localMessage, onProgress);
}, randomId, localMessage, onProgress, cancelSendingStatusTimeout);
}
const messagePromise = (async () => {
@ -564,8 +569,11 @@ export function sendApiMessage(
});
}
cancelSendingStatusTimeout();
if (update) handleLocalMessageUpdate(localMessage, update);
} catch (error: any) {
cancelSendingStatusTimeout();
if (error.errorMessage === 'PRIVACY_PREMIUM_REQUIRED') {
sendApiUpdate({ '@type': 'updateRequestUserUpdate', id: chat.id });
}
@ -576,7 +584,6 @@ export function sendApiMessage(
localId: localMessage.id,
error: error.errorMessage,
});
clearTimeout(timeout);
}
})();
@ -595,6 +602,7 @@ const groupedUploads: Record<string, {
counter: number;
singleMediaByIndex: Record<number, GramJs.InputSingleMedia>;
localMessages: Record<string, ApiMessage>;
cancelSendingStatusTimeouts: Record<string, NoneToVoidFunction>;
}> = {};
function sendGroupedMedia(
@ -627,7 +635,8 @@ function sendGroupedMedia(
},
randomId: GramJs.long,
localMessage: ApiMessage,
onProgress?: ApiOnProgress,
onProgress: ApiOnProgress | undefined,
cancelSendingStatusTimeout: NoneToVoidFunction,
) {
let groupIndex = -1;
if (!groupedUploads[groupedId]) {
@ -635,6 +644,7 @@ function sendGroupedMedia(
counter: 0,
singleMediaByIndex: {},
localMessages: {},
cancelSendingStatusTimeouts: {},
};
}
@ -689,12 +699,13 @@ function sendGroupedMedia(
entities: entities ? entities.map(buildMtpMessageEntity) : undefined,
});
groupedUploads[groupedId].localMessages[randomId.toString()] = localMessage;
groupedUploads[groupedId].cancelSendingStatusTimeouts[randomId.toString()] = cancelSendingStatusTimeout;
if (Object.keys(groupedUploads[groupedId].singleMediaByIndex).length < groupedUploads[groupedId].counter) {
return;
}
const { singleMediaByIndex, localMessages } = groupedUploads[groupedId];
const { singleMediaByIndex, localMessages, cancelSendingStatusTimeouts } = groupedUploads[groupedId];
delete groupedUploads[groupedId];
const count = Object.values(singleMediaByIndex).length;
@ -713,7 +724,10 @@ function sendGroupedMedia(
shouldIgnoreUpdates: true,
});
if (update) handleMultipleLocalMessagesUpdate(localMessages, update);
if (!update) return;
Object.values(cancelSendingStatusTimeouts).forEach((cancel) => cancel());
handleMultipleLocalMessagesUpdate(localMessages, update);
})();
return mediaQueue;

View File

@ -94,6 +94,7 @@ type BroadcastChannelInitApi = {
};
const MULTITAB_ESTABLISH_TIMEOUT = 800;
const BROADCAST_DIFF_FALLBACK_TIMEOUT = 500;
export type TypedBroadcastChannel = {
postMessage: (message: BroadcastChannelMessage) => void;
@ -117,6 +118,28 @@ const channel = new BroadcastChannel(DATA_BROADCAST_CHANNEL_NAME) as TypedBroadc
let isBroadcastDiffScheduled = false;
let lastBroadcastDiffGlobal: GlobalState | undefined;
let broadcastDiffFallbackTimeout: number | undefined;
function flushBroadcastDiff() {
if (!isBroadcastDiffScheduled) return;
if (broadcastDiffFallbackTimeout) {
clearTimeout(broadcastDiffFallbackTimeout);
broadcastDiffFallbackTimeout = undefined;
}
const diff = deepDiff(lastBroadcastDiffGlobal, currentGlobal);
if (typeof diff !== 'symbol') {
channel.postMessage({
type: 'globalDiffUpdate',
diff,
});
}
isBroadcastDiffScheduled = false;
lastBroadcastDiffGlobal = undefined;
}
function broadcastDiffOnIdle() {
if (isBroadcastDiffScheduled) return;
@ -124,18 +147,8 @@ function broadcastDiffOnIdle() {
isBroadcastDiffScheduled = true;
lastBroadcastDiffGlobal = currentGlobal;
onFullyIdle(() => {
const diff = deepDiff(lastBroadcastDiffGlobal, currentGlobal);
if (typeof diff !== 'symbol') {
channel.postMessage({
type: 'globalDiffUpdate',
diff,
});
}
isBroadcastDiffScheduled = false;
});
onFullyIdle(flushBroadcastDiff);
broadcastDiffFallbackTimeout = window.setTimeout(flushBroadcastDiff, BROADCAST_DIFF_FALLBACK_TIMEOUT);
}
export function unsubcribeFromMultitabBroadcastChannel() {