143 lines
4.0 KiB
TypeScript
143 lines
4.0 KiB
TypeScript
import type { ApiPeerStories, ApiTypeStory } from '../../api/types';
|
|
import type { GlobalState, TabArgs } from '../types';
|
|
|
|
import { getCurrentTabId } from '../../util/establishMultitabRole';
|
|
import { selectPeer } from './chats';
|
|
import { selectTabState } from './tabs';
|
|
|
|
export function selectCurrentViewedStory<T extends GlobalState>(
|
|
global: T,
|
|
...[tabId = getCurrentTabId()]: TabArgs<T>
|
|
) {
|
|
const { storyViewer: { peerId, storyId } } = selectTabState(global, tabId);
|
|
|
|
return { peerId, storyId };
|
|
}
|
|
|
|
export function selectIsStoryViewerOpen<T extends GlobalState>(
|
|
global: T,
|
|
...[tabId = getCurrentTabId()]: TabArgs<T>
|
|
) {
|
|
const { peerId, storyId } = selectCurrentViewedStory(global, tabId);
|
|
|
|
return Boolean(peerId) && Boolean(storyId);
|
|
}
|
|
|
|
export function selectPeerStories<T extends GlobalState>(
|
|
global: T, peerId: string,
|
|
): ApiPeerStories | undefined {
|
|
return global.stories.byPeerId[peerId];
|
|
}
|
|
|
|
export function selectPeerStory<T extends GlobalState>(
|
|
global: T, peerId: string, storyId: number,
|
|
): ApiTypeStory | undefined {
|
|
return selectPeerStories(global, peerId)?.byId[storyId];
|
|
}
|
|
|
|
export function selectPeerFirstUnreadStoryId<T extends GlobalState>(
|
|
global: T, peerId: string,
|
|
) {
|
|
const peerStories = selectPeerStories(global, peerId);
|
|
if (!peerStories) {
|
|
return undefined;
|
|
}
|
|
|
|
if (!peerStories.lastReadId) {
|
|
return peerStories.orderedIds?.[0];
|
|
}
|
|
|
|
const lastReadIndex = peerStories.orderedIds.findIndex((id) => id === peerStories.lastReadId);
|
|
|
|
return peerStories.orderedIds?.[lastReadIndex + 1];
|
|
}
|
|
|
|
export function selectPeerFirstStoryId<T extends GlobalState>(
|
|
global: T, peerId: string,
|
|
) {
|
|
return selectPeerStories(global, peerId)?.orderedIds?.[0];
|
|
}
|
|
|
|
export function selectStoryListForViewer<T extends GlobalState>(
|
|
global: T,
|
|
peerId: string,
|
|
storyId?: number,
|
|
isSingleStory?: boolean,
|
|
isSinglePeer?: boolean,
|
|
isPrivate?: boolean,
|
|
isArchive?: boolean,
|
|
): {
|
|
peerIds: string[];
|
|
storyIdsByPeerId: Record<string, number[]>;
|
|
} | undefined {
|
|
const currentStoryId = storyId
|
|
|| selectPeerFirstUnreadStoryId(global, peerId)
|
|
|| selectPeerFirstStoryId(global, peerId);
|
|
if (!currentStoryId) {
|
|
return undefined;
|
|
}
|
|
|
|
if (isSingleStory) {
|
|
return {
|
|
peerIds: [peerId],
|
|
storyIdsByPeerId: { [peerId]: [currentStoryId] },
|
|
};
|
|
}
|
|
|
|
const peer = selectPeer(global, peerId);
|
|
const story = selectPeerStory(global, peerId, currentStoryId);
|
|
if (!peer || !story) {
|
|
return undefined;
|
|
}
|
|
|
|
const isUnread = (global.stories.byPeerId[peerId].lastReadId || 0) < story.id;
|
|
|
|
if (isSinglePeer) {
|
|
const storyIds = getPeerStoryIdsForViewer(global, peerId, isUnread, isArchive, isPrivate);
|
|
|
|
return storyIds?.length
|
|
? { peerIds: [peerId], storyIdsByPeerId: { [peerId]: storyIds } }
|
|
: undefined;
|
|
}
|
|
|
|
const { orderedPeerIds: { active, archived } } = global.stories;
|
|
const orderedPeerIds = (peer.areStoriesHidden ? archived : active) ?? [];
|
|
const peerIds: string[] = [];
|
|
const storyIdsByPeerId: Record<string, number[]> = {};
|
|
|
|
for (const currentPeerId of orderedPeerIds) {
|
|
const storyIds = getPeerStoryIdsForViewer(global, currentPeerId, isUnread, isArchive, isPrivate);
|
|
if (storyIds?.length) {
|
|
peerIds.push(currentPeerId);
|
|
storyIdsByPeerId[currentPeerId] = storyIds;
|
|
}
|
|
}
|
|
|
|
return peerIds.length ? { peerIds, storyIdsByPeerId } : undefined;
|
|
}
|
|
|
|
function getPeerStoryIdsForViewer<T extends GlobalState>(
|
|
global: T,
|
|
peerId: string,
|
|
isUnread?: boolean,
|
|
isArchive?: boolean,
|
|
isPrivate?: boolean,
|
|
): number[] | undefined {
|
|
const peerStories = selectPeerStories(global, peerId);
|
|
const storySourceProp = isArchive ? 'archiveIds' : isPrivate ? 'pinnedIds' : 'orderedIds';
|
|
const storyIds = peerStories?.[storySourceProp];
|
|
|
|
if (!peerStories || !storyIds?.length) {
|
|
return undefined;
|
|
}
|
|
|
|
if (!peerStories.lastReadId || !isUnread) {
|
|
return storyIds.slice();
|
|
}
|
|
|
|
const lastReadIndex = storyIds.indexOf(peerStories.lastReadId);
|
|
return (storyIds.length > lastReadIndex + 1)
|
|
? storyIds.slice(lastReadIndex + 1)
|
|
: undefined;
|
|
}
|