Increment view count on view (#3097)

This commit is contained in:
Alexander Zinchuk 2023-04-27 18:53:34 +04:00
parent 565a281d02
commit f8513e3242
7 changed files with 66 additions and 7 deletions

View File

@ -875,14 +875,16 @@ export async function markMessagesRead({
}
export async function fetchMessageViews({
chat, ids,
chat, ids, shouldIncrement,
}: {
chat: ApiChat; ids: number[];
chat: ApiChat;
ids: number[];
shouldIncrement?: boolean;
}) {
const result = await invokeRequest(new GramJs.messages.GetMessagesViews({
peer: buildInputPeer(chat.id, chat.accessHash),
id: ids,
increment: false,
increment: shouldIncrement,
}));
if (!result) return undefined;

View File

@ -302,7 +302,8 @@ const MessageList: FC<OwnProps & StateProps> = ({
if (!messageIds || !messagesById || threadId !== MAIN_THREAD_ID) {
return;
}
const ids = messageIds.filter((id) => messagesById[id]?.repliesThreadInfo?.isComments);
const ids = messageIds.filter((id) => messagesById[id]?.repliesThreadInfo?.isComments
|| messagesById[id]?.views !== undefined);
if (!ids.length) return;

View File

@ -90,7 +90,7 @@ const MessageListContent: FC<OwnProps> = ({
observeIntersectionForReading,
observeIntersectionForLoading,
observeIntersectionForPlaying,
} = useMessageObservers(type, containerRef, memoFirstUnreadIdRef, onPinnedIntersectionChange);
} = useMessageObservers(type, containerRef, memoFirstUnreadIdRef, onPinnedIntersectionChange, chatId);
const {
backwardsTriggerRef,

View File

@ -17,9 +17,11 @@ export default function useMessageObservers(
containerRef: RefObject<HTMLDivElement>,
memoFirstUnreadIdRef: { current: number | undefined },
onPinnedIntersectionChange: PinnedIntersectionChangedCallback,
chatId: string,
) {
const {
markMessageListRead, markMentionsRead, animateUnreadReaction,
scheduleForViewsIncrement,
} = getActions();
const { isMobile } = useAppLayout();
@ -40,6 +42,7 @@ export default function useMessageObservers(
const reactionIds: number[] = [];
const viewportPinnedIdsToAdd: number[] = [];
const viewportPinnedIdsToRemove: number[] = [];
const scheduledToUpdateViews: number[] = [];
let isReversed = false;
entries.forEach((entry) => {
@ -49,6 +52,7 @@ export default function useMessageObservers(
const { dataset } = target as HTMLDivElement;
const messageId = Number(dataset.lastMessageId || dataset.messageId);
const shouldUpdateViews = dataset.shouldUpdateViews === 'true';
const albumMainId = dataset.albumMainId ? Number(dataset.albumMainId) : undefined;
if (!isIntersecting) {
@ -76,6 +80,10 @@ export default function useMessageObservers(
if (dataset.isPinned) {
viewportPinnedIdsToAdd.push(albumMainId || messageId);
}
if (shouldUpdateViews) {
scheduledToUpdateViews.push(albumMainId || messageId);
}
});
if (memoFirstUnreadIdRef.current && maxId >= memoFirstUnreadIdRef.current) {
@ -93,6 +101,10 @@ export default function useMessageObservers(
if (viewportPinnedIdsToAdd.length || viewportPinnedIdsToRemove.length) {
onPinnedIntersectionChange({ viewportPinnedIdsToAdd, viewportPinnedIdsToRemove, isReversed });
}
if (scheduledToUpdateViews.length) {
scheduleForViewsIncrement({ chatId, ids: scheduledToUpdateViews });
}
});
useBackgroundMode(freezeForReading, unfreezeForReading);

View File

@ -1236,6 +1236,7 @@ const Message: FC<OwnProps & StateProps> = ({
data-has-unread-mention={message.hasUnreadMention || undefined}
data-has-unread-reaction={hasUnreadReaction || undefined}
data-is-pinned={isPinned || undefined}
data-should-update-views={message.views !== undefined}
/>
{!isInDocumentGroup && (
<div className="message-select-control">

View File

@ -1,5 +1,7 @@
import type { RequiredGlobalActions } from '../../index';
import { addActionHandler, getGlobal, setGlobal } from '../../index';
import {
addActionHandler, getActions, getGlobal, setGlobal,
} from '../../index';
import type {
ActionReturnType, ApiDraft, GlobalState, TabArgs,
@ -1473,8 +1475,43 @@ addActionHandler('translateMessages', (global, actions, payload): ActionReturnTy
return global;
});
// https://github.com/telegramdesktop/tdesktop/blob/11906297d82b6ff57b277da5251d2e6eb3d8b6d0/Telegram/SourceFiles/api/api_views.cpp#L22
const SEND_VIEWS_TIMEOUT = 1000;
let viewsIncrementTimeout: number | undefined;
let idsToIncrementViews: Record<string, Set<number>> = {};
function incrementViews() {
if (viewsIncrementTimeout) {
clearTimeout(viewsIncrementTimeout);
viewsIncrementTimeout = undefined;
}
// eslint-disable-next-line eslint-multitab-tt/no-getactions-in-actions
const { loadMessageViews } = getActions();
Object.entries(idsToIncrementViews).forEach(([chatId, ids]) => {
loadMessageViews({ chatId, ids: Array.from(ids), shouldIncrement: true });
});
idsToIncrementViews = {};
}
addActionHandler('scheduleForViewsIncrement', (global, actions, payload): ActionReturnType => {
const { ids, chatId } = payload;
if (!viewsIncrementTimeout) {
setTimeout(incrementViews, SEND_VIEWS_TIMEOUT);
}
if (!idsToIncrementViews[chatId]) {
idsToIncrementViews[chatId] = new Set();
}
ids.forEach((id) => {
idsToIncrementViews[chatId].add(id);
});
});
addActionHandler('loadMessageViews', async (global, actions, payload): Promise<void> => {
const { chatId, ids } = payload;
const { chatId, ids, shouldIncrement } = payload;
const chat = selectChat(global, chatId);
if (!chat) return;
@ -1482,6 +1519,7 @@ addActionHandler('loadMessageViews', async (global, actions, payload): Promise<v
const result = await callApi('fetchMessageViews', {
chat,
ids,
shouldIncrement,
});
if (!result) return;

View File

@ -1736,9 +1736,14 @@ export interface ActionPayloads {
chatId: string;
offsetId?: number;
};
scheduleForViewsIncrement: {
chatId: string;
ids: number[];
};
loadMessageViews: {
chatId: string;
ids: number[];
shouldIncrement?: boolean;
};
animateUnreadReaction: {
messageIds: number[];