refactor(web): unify DM sorting with sortDmChannels across all triggers
This commit is contained in:
@@ -8,6 +8,7 @@ import { useSettingsStore } from '../stores/settingsStore';
|
|||||||
import type { ServerEvent, ClientEvent, ActiveCallInfo, Activity } from '@backspace/shared';
|
import type { ServerEvent, ClientEvent, ActiveCallInfo, Activity } from '@backspace/shared';
|
||||||
import { resolveAssetUrl, normalizeUserAssets, normalizeMessageAssets } from '../utils/assetUrls';
|
import { resolveAssetUrl, normalizeUserAssets, normalizeMessageAssets } from '../utils/assetUrls';
|
||||||
import { broadcastVoiceStatus, broadcastDeafenViaLiveKit } from '../utils/voice';
|
import { broadcastVoiceStatus, broadcastDeafenViaLiveKit } from '../utils/voice';
|
||||||
|
import { sortDmChannels } from '../utils/dmSorting';
|
||||||
import { registerSelfId } from '../utils/identity';
|
import { registerSelfId } from '../utils/identity';
|
||||||
import { getActiveRoom } from './useLiveKit';
|
import { getActiveRoom } from './useLiveKit';
|
||||||
import { useUIStore } from '../stores/uiStore';
|
import { useUIStore } from '../stores/uiStore';
|
||||||
@@ -561,8 +562,8 @@ function handleEvent(origin: string, event: ServerEvent): void {
|
|||||||
const updatedDms = currentDmChannels.map(dm =>
|
const updatedDms = currentDmChannels.map(dm =>
|
||||||
dm.id === existingDm.id ? { ...dm, lastMessage: event.message } : dm,
|
dm.id === existingDm.id ? { ...dm, lastMessage: event.message } : dm,
|
||||||
);
|
);
|
||||||
updatedDms.sort((a, b) => (b.lastMessage?.createdAt ?? b.createdAt) - (a.lastMessage?.createdAt ?? a.createdAt));
|
const { unreadChannels, currentChannelId } = useChatStore.getState();
|
||||||
setDms(updatedDms);
|
setDms(sortDmChannels(updatedDms, unreadChannels, currentChannelId));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -582,12 +583,8 @@ function handleEvent(origin: string, event: ServerEvent): void {
|
|||||||
? { ...dm, lastMessage: event.message }
|
? { ...dm, lastMessage: event.message }
|
||||||
: dm
|
: dm
|
||||||
);
|
);
|
||||||
updatedDms.sort((a, b) => {
|
const { unreadChannels: unread, currentChannelId: curCh } = useChatStore.getState();
|
||||||
const aTime = a.lastMessage?.createdAt ?? a.createdAt;
|
setDms(sortDmChannels(updatedDms, unread, curCh));
|
||||||
const bTime = b.lastMessage?.createdAt ?? b.createdAt;
|
|
||||||
return bTime - aTime;
|
|
||||||
});
|
|
||||||
setDms(updatedDms);
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const { currentChannelId, markChannelUnread } = useChatStore.getState();
|
const { currentChannelId, markChannelUnread } = useChatStore.getState();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { wsSend } from '../hooks/useWebSocket';
|
|||||||
import { isDmChannel, getChannelOrigin, getApiForOrigin, useSpaceStore } from './spaceStore';
|
import { isDmChannel, getChannelOrigin, getApiForOrigin, useSpaceStore } from './spaceStore';
|
||||||
import { useAuthStore } from './authStore';
|
import { useAuthStore } from './authStore';
|
||||||
import { normalizeMessageAssets } from '../utils/assetUrls';
|
import { normalizeMessageAssets } from '../utils/assetUrls';
|
||||||
|
import { sortDmChannels } from '../utils/dmSorting';
|
||||||
|
|
||||||
const MAX_MESSAGES_PER_CHANNEL = 200;
|
const MAX_MESSAGES_PER_CHANNEL = 200;
|
||||||
const MAX_CACHED_CHANNELS = 20;
|
const MAX_CACHED_CHANNELS = 20;
|
||||||
@@ -285,12 +286,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|||||||
? { ...dm, lastMessage: { id: tempId, dmChannelId: channelId, userId: currentUser.id, content, createdAt: Date.now() } }
|
? { ...dm, lastMessage: { id: tempId, dmChannelId: channelId, userId: currentUser.id, content, createdAt: Date.now() } }
|
||||||
: dm
|
: dm
|
||||||
);
|
);
|
||||||
updatedDms.sort((a, b) => {
|
setDmChannels(sortDmChannels(updatedDms, get().unreadChannels, get().currentChannelId));
|
||||||
const aTime = a.lastMessage?.createdAt ?? a.createdAt;
|
|
||||||
const bTime = b.lastMessage?.createdAt ?? b.createdAt;
|
|
||||||
return bTime - aTime;
|
|
||||||
});
|
|
||||||
setDmChannels(updatedDms);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,6 +585,13 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
set({ readStates: rsMap, unreadChannels: unread });
|
set({ readStates: rsMap, unreadChannels: unread });
|
||||||
|
|
||||||
|
// Re-sort DM list now that unread state is known (handles initial load
|
||||||
|
// where populateFromReady runs before read states are processed)
|
||||||
|
const { dmChannels, setDmChannels } = useSpaceStore.getState();
|
||||||
|
if (dmChannels.length > 0) {
|
||||||
|
setDmChannels(sortDmChannels(dmChannels, unread, currentChannelId));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
markChannelUnread: (channelId: string) => {
|
markChannelUnread: (channelId: string) => {
|
||||||
@@ -652,6 +655,12 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|||||||
return { readStates: newReadStates, unreadChannels: newUnread };
|
return { readStates: newReadStates, unreadChannels: newUnread };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Re-sort DM list when a DM is marked as read (moves from unread to read group)
|
||||||
|
if (isDmChannel(channelId)) {
|
||||||
|
const { dmChannels, setDmChannels } = useSpaceStore.getState();
|
||||||
|
setDmChannels(sortDmChannels(dmChannels, get().unreadChannels, channelId));
|
||||||
|
}
|
||||||
|
|
||||||
// Send to the correct instance
|
// Send to the correct instance
|
||||||
const origin = getChannelOrigin(channelId);
|
const origin = getChannelOrigin(channelId);
|
||||||
wsSend({ type: 'channel_ack', channelId, messageId }, origin);
|
wsSend({ type: 'channel_ack', channelId, messageId }, origin);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type { Space, Channel, ChannelCategory, MemberWithUser, SpaceWithChannels
|
|||||||
import { api, BackspaceApiClient } from '../api/client';
|
import { api, BackspaceApiClient } from '../api/client';
|
||||||
import { resolveAssetUrl, normalizeUserAssets } from '../utils/assetUrls';
|
import { resolveAssetUrl, normalizeUserAssets } from '../utils/assetUrls';
|
||||||
import { isSelf } from '../utils/identity';
|
import { isSelf } from '../utils/identity';
|
||||||
|
import { sortDmChannels } from '../utils/dmSorting';
|
||||||
import { useAuthStore } from './authStore';
|
import { useAuthStore } from './authStore';
|
||||||
import { useChatStore } from './chatStore';
|
import { useChatStore } from './chatStore';
|
||||||
|
|
||||||
@@ -670,9 +671,15 @@ export const useSpaceStore = create<SpaceState>((set, get) => ({
|
|||||||
});
|
});
|
||||||
const mergedDms = [...existingDmsFromOtherOrigins, ...incomingDms];
|
const mergedDms = [...existingDmsFromOtherOrigins, ...incomingDms];
|
||||||
|
|
||||||
|
// Sort DMs using unread-first ordering. On initial load, unreadChannels may
|
||||||
|
// still be empty (read states are processed after populateFromReady); the
|
||||||
|
// safety-net re-sort in setReadStates handles that case.
|
||||||
|
const { unreadChannels, currentChannelId } = useChatStore.getState();
|
||||||
|
const sortedDms = sortDmChannels(mergedDms, unreadChannels, currentChannelId);
|
||||||
|
|
||||||
const update: Partial<SpaceState> = {
|
const update: Partial<SpaceState> = {
|
||||||
spaces: mergedSpaces,
|
spaces: mergedSpaces,
|
||||||
dmChannels: mergedDms,
|
dmChannels: sortedDms,
|
||||||
channelToSpaceMap,
|
channelToSpaceMap,
|
||||||
channelLastMessageIds,
|
channelLastMessageIds,
|
||||||
spacePermissions,
|
spacePermissions,
|
||||||
|
|||||||
Reference in New Issue
Block a user