fix(app): resolve the unread anchor where channel message loads originate (#1701)

This commit is contained in:
Hampus
2026-08-17 16:20:49 +02:00
committed by GitHub
parent 97c29bf1fb
commit c35d29ea0b
3 changed files with 37 additions and 8 deletions
@@ -4,6 +4,7 @@ import type {Channel} from '@app/features/channel/models/Channel';
import type {Guild} from '@app/features/guild/models/Guild';
import {ensureMembersForMessages} from '@app/features/messaging/commands/MessageCommands';
import Messages from '@app/features/messaging/state/MessagingMessages';
import ReadStates from '@app/features/read_state/state/ReadStates';
import {ChannelTypes} from '@fluxer/constants/src/ChannelConstants';
import {useCallback, useEffect, useRef} from 'react';
@@ -56,7 +57,8 @@ export function useChannelHoverPreload({
return;
}
if (preloadMessages) {
if (!Messages.preloadLatestPage(channel.id, guild?.id ?? channel.guildId ?? null)) {
const unreadAnchor = ReadStates.getUnreadJumpAnchor(channel.id);
if (!Messages.preloadLatestPage(channel.id, guild?.id ?? channel.guildId ?? null, unreadAnchor)) {
ensureMembersForCachedChannelMessages(channel.id);
}
}
@@ -185,5 +185,5 @@ function handleReadyInternal(data: ReadyPayload, context: GatewayHandlerContext)
MediaEngine.handleConnectionOpen(guilds);
Initialization.setReady(data);
context.setReady();
Messages.handleConnectionOpen();
Messages.handleConnectionOpen((channelId) => ReadStates.getUnreadJumpAnchor(channelId));
}
@@ -210,13 +210,13 @@ class Messages {
}
@action
preloadLatestPage(channelId: string, guildId?: string | null): boolean {
preloadLatestPage(channelId: string, guildId?: string | null, unreadAnchor?: UnreadJumpAnchor | null): boolean {
if (!this.shouldPreloadLatestPage(channelId)) {
return false;
}
const channel = Channels.getChannel(channelId);
const resolvedGuildId = guildId ?? channel?.guildId ?? (channel?.isPrivate() ? ME : undefined);
this.handleChannelSelect({guildId: resolvedGuildId ?? undefined, channelId});
this.handleChannelSelect({guildId: resolvedGuildId ?? undefined, channelId, unreadAnchor});
return true;
}
@@ -293,7 +293,7 @@ class Messages {
}
@action
handleConnectionOpen(): boolean {
handleConnectionOpen(resolveUnreadAnchor: (channelId: string) => UnreadJumpAnchor | null): boolean {
const selectedChannelId = SelectedChannel.currentChannelId;
let didHydrateSelectedChannel = false;
if (selectedChannelId) {
@@ -307,7 +307,10 @@ class Messages {
}
ChannelMessages.forEach((messages) => {
if (messages.channelId === selectedChannelId && Channels.getChannel(messages.channelId) != null) {
this.startChannelHydration(messages.channelId, {forceScrollToBottom: this.pendingFullHydration});
this.startChannelHydration(messages.channelId, {
forceScrollToBottom: this.pendingFullHydration,
unreadAnchor: resolveUnreadAnchor(messages.channelId),
});
didHydrateSelectedChannel = true;
} else {
this.clearMessages(messages.channelId);
@@ -323,7 +326,18 @@ class Messages {
const messages = ChannelMessages.getOrCreate(selectedChannelId);
if (!messages.ready && !messages.loadingMore && messages.length === 0) {
this.commitMessages(messages.mutate({loadingMore: true}));
MessageCommands.fetchMessages(selectedChannelId, null, null, MAX_MESSAGES_PER_CHANNEL);
const unreadAnchor = resolveUnreadAnchor(selectedChannelId);
if (unreadAnchor != null) {
MessageCommands.jumpToMessage({
channelId: selectedChannelId,
messageId: unreadAnchor.messageId,
offset: unreadAnchor.offset,
flash: false,
jumpType: JumpTypes.INSTANT,
});
} else {
MessageCommands.fetchMessages(selectedChannelId, null, null, MAX_MESSAGES_PER_CHANNEL);
}
didHydrateSelectedChannel = true;
}
}
@@ -335,14 +349,27 @@ class Messages {
channelId: string,
options: {
forceScrollToBottom?: boolean;
unreadAnchor?: UnreadJumpAnchor | null;
} = {},
): void {
if (!Channels.getChannel(channelId)) return;
const {forceScrollToBottom = false} = options;
const {forceScrollToBottom = false, unreadAnchor = null} = options;
const messages = ChannelMessages.getOrCreate(channelId);
this.commitMessages(messages.mutate({loadingMore: true, ready: false, error: false}));
if (forceScrollToBottom) {
Dimension.updateChannelDimensions(channelId, 1, 1, 0);
MessageCommands.fetchMessages(channelId, null, null, MAX_MESSAGES_PER_CHANNEL);
return;
}
if (unreadAnchor != null) {
MessageCommands.jumpToMessage({
channelId,
messageId: unreadAnchor.messageId,
offset: unreadAnchor.offset,
flash: false,
jumpType: JumpTypes.INSTANT,
});
return;
}
MessageCommands.fetchMessages(channelId, null, null, MAX_MESSAGES_PER_CHANNEL);
}