mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
fix(app): distrust windows loaded across a connection gap (#2574)
This commit is contained in:
1 parent
24b84c419c
commit
fd6ae4abd7
15 files changed
+186
-32
No files matched your search
@@ -3,7 +3,10 @@
|
||||
import {Message} from '@app/features/messaging/models/MessagingMessage';
|
||||
import {UploadingAttachment} from '@app/features/messaging/models/UploadingAttachment';
|
||||
import {resolveChannelIncomingMessageDecision} from '@app/features/messaging/state/ChannelIncomingMessageStateMachine';
|
||||
import {resolveChannelMessagesLoadDecision} from '@app/features/messaging/state/ChannelMessagesLoadStateMachine';
|
||||
import {
|
||||
resolveChannelMessagesLoadDecision,
|
||||
selectChannelMessagesLoadRestoresTrust,
|
||||
} from '@app/features/messaging/state/ChannelMessagesLoadStateMachine';
|
||||
import MessageReactions from '@app/features/messaging/state/MessageReactions';
|
||||
import {mergeAscendingById} from '@app/features/messaging/utils/MessagePaginationUtils';
|
||||
import SelectedChannel from '@app/features/navigation/state/SelectedChannel';
|
||||
@@ -358,6 +361,10 @@ export class ChannelMessages {
|
||||
ChannelMessages.retainedChannelIds.delete(channelId);
|
||||
}
|
||||
|
||||
static isRetained(channelId: string): boolean {
|
||||
return ChannelMessages.retainedChannelIds.has(channelId);
|
||||
}
|
||||
|
||||
static dropBuffers(channelId: string): void {
|
||||
const instance = ChannelMessages.channelCache.get(channelId);
|
||||
if (!instance) return;
|
||||
@@ -900,6 +907,11 @@ export class ChannelMessages {
|
||||
jumpReturnChannelId: jump?.returnToMessageId ? (jump.returnChannelId ?? this.channelId) : null,
|
||||
jumpReturnGuildId: jump?.returnToMessageId ? (jump.returnGuildId ?? null) : null,
|
||||
};
|
||||
const reachesLiveEdge = selectChannelMessagesLoadRestoresTrust({
|
||||
mode: loadDecision.mode,
|
||||
isAfter,
|
||||
hasMoreAfter,
|
||||
});
|
||||
next = next.cloneAnd({
|
||||
ready: true,
|
||||
loadingMore: false,
|
||||
@@ -907,7 +919,7 @@ export class ChannelMessages {
|
||||
...jumpPatch,
|
||||
hasMoreBefore: loadDecision.preserveHasMoreBefore ? next.hasMoreBefore : hasMoreBefore,
|
||||
hasMoreAfter: loadDecision.preserveHasMoreAfter ? next.hasMoreAfter : hasMoreAfter,
|
||||
cached,
|
||||
cached: reachesLiveEdge ? cached : next.cached || cached,
|
||||
error: false,
|
||||
});
|
||||
return next;
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
resolveChannelMessagesWindowStatus,
|
||||
selectChannelMessagesFillerVisible,
|
||||
selectChannelMessagesLoadDecision,
|
||||
selectChannelMessagesLoadRestoresTrust,
|
||||
selectChannelMessagesSpacerHeight,
|
||||
selectChannelMessagesTailGapId,
|
||||
selectChannelMessagesTailProbeId,
|
||||
@@ -518,3 +519,23 @@ describe('selectChannelMessagesTailProbeOutcome', () => {
|
||||
expect(selectChannelMessagesTailProbeOutcome(outcomeInput({currentJumpTicket: 3}))).toBe('discard');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectChannelMessagesLoadRestoresTrust', () => {
|
||||
it('trusts a window a replacement load rebuilt from scratch', () => {
|
||||
expect(selectChannelMessagesLoadRestoresTrust({mode: 'replace', isAfter: false, hasMoreAfter: false})).toBe(true);
|
||||
});
|
||||
|
||||
it('trusts a window whose tail merge caught up to the live edge', () => {
|
||||
expect(selectChannelMessagesLoadRestoresTrust({mode: 'mergeAfter', isAfter: true, hasMoreAfter: false})).toBe(true);
|
||||
});
|
||||
|
||||
it('keeps distrusting a tail merge that stopped short of the live edge', () => {
|
||||
expect(selectChannelMessagesLoadRestoresTrust({mode: 'mergeAfter', isAfter: true, hasMoreAfter: true})).toBe(false);
|
||||
});
|
||||
|
||||
it('keeps distrusting a page of older history', () => {
|
||||
expect(selectChannelMessagesLoadRestoresTrust({mode: 'mergeBefore', isAfter: false, hasMoreAfter: false})).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -301,6 +301,15 @@ export function selectChannelMessagesTailProbeId(input: ChannelMessagesTailInput
|
||||
return selectChannelMessagesTailGapId(input);
|
||||
}
|
||||
|
||||
export function selectChannelMessagesLoadRestoresTrust(input: {
|
||||
mode: ChannelMessagesLoadMode;
|
||||
isAfter: boolean;
|
||||
hasMoreAfter: boolean;
|
||||
}): boolean {
|
||||
if (input.mode === 'replace') return true;
|
||||
return input.isAfter && !input.hasMoreAfter;
|
||||
}
|
||||
|
||||
export interface ChannelMessagesTailProbeResultInput {
|
||||
probeGeneration: number;
|
||||
currentGeneration: number;
|
||||
|
||||
@@ -201,7 +201,7 @@ class Messages {
|
||||
}
|
||||
|
||||
private hasLoadedPage(messages: ChannelMessages): boolean {
|
||||
return messages.ready && messages.length > 0;
|
||||
return messages.ready && messages.length > 0 && !messages.cached;
|
||||
}
|
||||
|
||||
shouldPreloadLatestPage(channelId: string): boolean {
|
||||
@@ -209,7 +209,9 @@ class Messages {
|
||||
return false;
|
||||
}
|
||||
const messages = ChannelMessages.get(channelId);
|
||||
return !messages || (messages.length === 0 && !messages.loadingMore && !messages.ready);
|
||||
if (!messages) return true;
|
||||
if (messages.loadingMore || ChannelMessages.isRetained(channelId)) return false;
|
||||
return messages.length === 0 ? !messages.ready : messages.cached;
|
||||
}
|
||||
|
||||
@action
|
||||
@@ -286,15 +288,6 @@ class Messages {
|
||||
return true;
|
||||
}
|
||||
|
||||
@action
|
||||
handleResumed(): boolean {
|
||||
ChannelMessages.forEach((messages) => {
|
||||
this.commitMessages(messages.withPatch({ready: true}));
|
||||
});
|
||||
this.notifyChange();
|
||||
return true;
|
||||
}
|
||||
|
||||
@action
|
||||
handleGatewayReady(): boolean {
|
||||
const selectedChannelId = SelectedChannel.currentChannelId;
|
||||
@@ -386,9 +379,10 @@ class Messages {
|
||||
if (!isNonGuildChannel && !guildExists) {
|
||||
return false;
|
||||
}
|
||||
const distrustedTailId = messages.ready && messages.cached ? (messages.last()?.id ?? null) : null;
|
||||
this.commitMessages(messages.withPatch({loadingMore: true}));
|
||||
this.notifyChange();
|
||||
MessageCommands.fetchMessages(channelId, null, null, MAX_MESSAGES_PER_CHANNEL);
|
||||
MessageCommands.fetchMessages(channelId, null, distrustedTailId, MAX_MESSAGES_PER_CHANNEL);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user