feat: Rename to Toju and add translation
Some checks failed
Deploy Web Apps / deploy (push) Successful in 5m52s
Build Android APK / build-android-apk (push) Failing after 23m15s
Queue Release Build / prepare (push) Successful in 1m42s
Queue Release Build / build-linux (push) Failing after 9m33s
Queue Release Build / build-windows (push) Successful in 26m5s
Queue Release Build / finalize (push) Has been skipped

This commit is contained in:
2026-06-05 17:13:03 +02:00
parent 8ecfc9a1fe
commit ee293d7daf
301 changed files with 8247 additions and 2218 deletions

View File

@@ -14,38 +14,26 @@ describe('resolveAutoScrollBehavior', () => {
it('jumps instantly for the local user own send regardless of grace', () => {
expect(resolveAutoScrollBehavior({ ...base, forceLocalSend: true })).toBe('instant');
expect(
resolveAutoScrollBehavior({ ...base, forceLocalSend: true, withinInitialGrace: true })
).toBe('instant');
expect(resolveAutoScrollBehavior({ ...base, forceLocalSend: true, withinInitialGrace: true })).toBe('instant');
});
it('jumps instantly when near bottom while settling after a channel switch', () => {
expect(
resolveAutoScrollBehavior({ ...base, distanceFromBottom: 40, withinInitialGrace: true })
).toBe('instant');
expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 40, withinInitialGrace: true })).toBe('instant');
});
it('animates smoothly for live messages once settled and near bottom', () => {
expect(
resolveAutoScrollBehavior({ ...base, distanceFromBottom: 40, withinInitialGrace: false })
).toBe('smooth');
expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 40, withinInitialGrace: false })).toBe('smooth');
});
it('shows the indicator (no scroll) when far from the bottom', () => {
expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 800 })).toBe('none');
expect(
resolveAutoScrollBehavior({ ...base, distanceFromBottom: 800, withinInitialGrace: true })
).toBe('none');
expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 800, withinInitialGrace: true })).toBe('none');
});
it('honours a custom sticky threshold', () => {
expect(
resolveAutoScrollBehavior({ ...base, distanceFromBottom: 150, stickyThreshold: 100 })
).toBe('none');
expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 150, stickyThreshold: 100 })).toBe('none');
expect(
resolveAutoScrollBehavior({ ...base, distanceFromBottom: 80, stickyThreshold: 100 })
).toBe('smooth');
expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 80, stickyThreshold: 100 })).toBe('smooth');
});
});

View File

@@ -54,9 +54,6 @@ export const STICKY_BOTTOM_THRESHOLD = 300;
* This is the predicate the message list uses to decide whether a content
* height change (late image/embed/plugin render) should re-pin to bottom.
*/
export function isStuckToBottom(
distanceFromBottom: number,
threshold: number = STICKY_BOTTOM_THRESHOLD
): boolean {
export function isStuckToBottom(distanceFromBottom: number, threshold: number = STICKY_BOTTOM_THRESHOLD): boolean {
return distanceFromBottom <= threshold;
}

View File

@@ -51,12 +51,7 @@ export function findMissingIds(
for (const item of remoteItems) {
const local = localMap.get(item.id);
if (
!local ||
item.ts > local.ts ||
(item.rc !== undefined && item.rc !== local.rc) ||
(item.ac !== undefined && item.ac !== local.ac)
) {
if (!local || item.ts > local.ts || (item.rc !== undefined && item.rc !== local.rc) || (item.ac !== undefined && item.ac !== local.ac)) {
missing.push(item.id);
}
}

View File

@@ -7,10 +7,7 @@ export function getMessageTimestamp(msg: Message): number {
/** Computes the most recent timestamp across a batch of messages. */
export function getLatestTimestamp(messages: Message[]): number {
return messages.reduce(
(max, msg) => Math.max(max, getMessageTimestamp(msg)),
0
);
return messages.reduce((max, msg) => Math.max(max, getMessageTimestamp(msg)), 0);
}
/** Strips sensitive content from a deleted message. */