fix(mobile): Chat startet bei neuester Nachricht und Chats nach letzter Aktivität sortieren

Der Verlauf nutzt eine invertierte Liste und öffnet dadurch immer ganz unten.
Raumlisten liefern lastActivityAt; die App sortiert alle Chats danach und
zieht einen Chat nach dem Senden sofort nach oben.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 13:40:09 +02:00
parent e0a94f5e29
commit f0775ad52a
7 changed files with 64 additions and 21 deletions

View File

@@ -6,7 +6,7 @@ export type MobileChatRoom = {
key: string; id?: string; name: string; topic?: string | null;
source: 'internal' | 'collaboration'; group: string; exists: boolean;
type?: string; projectId?: number; projectNumber?: string | null; userId?: string; email?: string | null;
ownerName?: string; remote?: boolean; status?: string; unread?: number;
ownerName?: string; remote?: boolean; status?: string; unread?: number; lastActivityAt?: string | null;
};
export type ChatInvitation = {
id: string; name: string; ownerName?: string; role: string;
@@ -45,6 +45,11 @@ export const chatEndpoint = (room: MobileChatRoom, suffix = '') => room.source =
? `/api/collaboration/rooms/${encodeURIComponent(room.id!)}${suffix}`
: `/api/communication/chat/rooms/${encodeURIComponent(room.key)}${suffix}`;
export const visibleChatRooms = (directory: ChatDirectory) => directory.rooms.filter(room => !directory.hiddenRoomKeys.includes(room.key));
const activity = (room: MobileChatRoom) => (room.lastActivityAt && Date.parse(room.lastActivityAt)) || 0;
// Most recently used chats first; rooms without activity keep their server order at the end.
export const sortChatRooms = (rooms: MobileChatRoom[]) => [...rooms].sort((a, b) => activity(b) - activity(a));
export const touchChatRoom = (rooms: MobileChatRoom[], key: string, at = new Date().toISOString()) =>
sortChatRooms(rooms.map(room => room.key === key ? { ...room, lastActivityAt: at } : room));
export const chatCursor = (room: MobileChatRoom, messages: MobileChatMessage[]) => Math.max(0,
...messages.map(message => room.source === 'collaboration' ? message.seq || 0 : Number(message.id)));
export function mergeChatMessages(current: MobileChatMessage[], incoming: MobileChatMessage[], collaboration: boolean) {
@@ -98,9 +103,9 @@ export function createChatApi(request: Request) {
...room, source: 'internal', group, unread: unread.rooms?.[room.key]?.count || 0,
}));
return {
rooms: [...decorate(base.rooms, 'Räume'), ...decorate(projects.rooms, 'Projekte'), ...decorate(direct.rooms, 'Direkt'),
rooms: sortChatRooms([...decorate(base.rooms, 'Räume'), ...decorate(projects.rooms, 'Projekte'), ...decorate(direct.rooms, 'Direkt'),
...collaboration.rooms.map(room => ({ ...room, key: collaborationKey(room.id),
source: 'collaboration' as const, group: 'Zusammenarbeit', exists: true }))],
source: 'collaboration' as const, group: 'Zusammenarbeit', exists: true }))]),
hiddenRoomKeys: hidden.hiddenRoomKeys, invitations: collaboration.invitations,
canManage: collaboration.canManage === true, projects: collaboration.projects || [],
};