Support duplicate attachments in lightbox

This commit is contained in:
Fedor Indutny 2023-09-26 17:38:21 +02:00 committed by GitHub
parent b885ced90d
commit 1a2976dae4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 35 additions and 45 deletions

View file

@ -19,7 +19,7 @@ export type Props = {
loadRecentMediaItems: (id: string, limit: number) => void;
showAllMedia: () => void;
showLightboxWithMedia: (
selectedAttachmentPath: string | undefined,
selectedIndex: number,
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>
) => void;
};
@ -66,9 +66,7 @@ export function ConversationDetailsMediaList({
key={`${mediaItem.message.id}-${mediaItem.index}`}
mediaItem={mediaItem}
i18n={i18n}
onClick={() =>
showLightboxWithMedia(mediaItem.attachment.path, mediaItems)
}
onClick={() => showLightboxWithMedia(mediaItem.index, mediaItems)}
/>
))}
</div>

View file

@ -35,7 +35,7 @@ export function AttachmentSection({
const { message, index, attachment } = mediaItem;
const onClick = () => {
onItemClick({ type, message, attachment });
onItemClick({ type, message, attachment, index: mediaItem.index });
};
switch (type) {

View file

@ -29,7 +29,7 @@ export type Props = {
media: Array<MediaItemType>;
saveAttachment: SaveAttachmentActionCreatorType;
showLightboxWithMedia: (
selectedAttachmentPath: string | undefined,
selectedIndex: number,
media: Array<MediaItemType>
) => void;
};
@ -106,7 +106,7 @@ function MediaSection({
}
case 'media': {
showLightboxWithMedia(event.attachment.path, media);
showLightboxWithMedia(event.index, media);
break;
}

View file

@ -7,5 +7,6 @@ import type { AttachmentType } from '../../../../types/Attachment';
export type ItemClickEvent = {
message: Pick<MessageAttributesType, 'sent_at'>;
attachment: AttachmentType;
index: number;
type: 'media' | 'documents';
};

View file

@ -48,12 +48,12 @@ export type LightboxStateType =
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>;
hasPrevMessage: boolean;
hasNextMessage: boolean;
selectedAttachmentPath: string | undefined;
selectedIndex: number | undefined;
};
const CLOSE_LIGHTBOX = 'lightbox/CLOSE';
const SHOW_LIGHTBOX = 'lightbox/SHOW';
const SET_SELECTED_LIGHTBOX_PATH = 'lightbox/SET_SELECTED_LIGHTBOX_PATH';
const SET_SELECTED_LIGHTBOX_INDEX = 'lightbox/SET_SELECTED_LIGHTBOX_INDEX';
type CloseLightboxActionType = ReadonlyDeep<{
type: typeof CLOSE_LIGHTBOX;
@ -67,13 +67,13 @@ type ShowLightboxActionType = {
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>;
hasPrevMessage: boolean;
hasNextMessage: boolean;
selectedAttachmentPath: string | undefined;
selectedIndex: number | undefined;
};
};
type SetSelectedLightboxPathActionType = ReadonlyDeep<{
type: typeof SET_SELECTED_LIGHTBOX_PATH;
payload: string | undefined;
type SetSelectedLightboxIndexActionType = ReadonlyDeep<{
type: typeof SET_SELECTED_LIGHTBOX_INDEX;
payload: number;
}>;
// eslint-disable-next-line local-rules/type-alias-readonlydeep
@ -83,7 +83,7 @@ type LightboxActionType =
| MessageDeletedActionType
| MessageExpiredActionType
| ShowLightboxActionType
| SetSelectedLightboxPathActionType;
| SetSelectedLightboxIndexActionType;
function closeLightbox(): ThunkAction<
void,
@ -116,7 +116,7 @@ function closeLightbox(): ThunkAction<
}
function showLightboxWithMedia(
selectedAttachmentPath: string | undefined,
selectedIndex: number | undefined,
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>
): ShowLightboxActionType {
return {
@ -124,7 +124,7 @@ function showLightboxWithMedia(
payload: {
isViewOnce: false,
media,
selectedAttachmentPath,
selectedIndex,
hasPrevMessage: false,
hasNextMessage: false,
},
@ -202,7 +202,7 @@ function showLightboxForViewOnceMedia(
payload: {
isViewOnce: true,
media,
selectedAttachmentPath: undefined,
selectedIndex: undefined,
hasPrevMessage: false,
hasNextMessage: false,
},
@ -335,7 +335,7 @@ function showLightbox(opts: {
payload: {
isViewOnce: false,
media,
selectedAttachmentPath: attachment.path,
selectedIndex: media.findIndex(({ path }) => path === attachment.path),
hasPrevMessage:
older.length > 0 && filterValidAttachments(older[0]).length > 0,
hasNextMessage:
@ -464,12 +464,12 @@ function showLightboxForPrevMessage(): ThunkAction<
return showLightboxForAdjacentMessage(AdjacentMessageDirection.Previous);
}
function setSelectedLightboxPath(
path: string | undefined
): SetSelectedLightboxPathActionType {
function setSelectedLightboxIndex(
index: number
): SetSelectedLightboxIndexActionType {
return {
type: SET_SELECTED_LIGHTBOX_PATH,
payload: path,
type: SET_SELECTED_LIGHTBOX_INDEX,
payload: index,
};
}
@ -480,7 +480,7 @@ export const actions = {
showLightboxWithMedia,
showLightboxForPrevMessage,
showLightboxForNextMessage,
setSelectedLightboxPath,
setSelectedLightboxIndex,
};
export const useLightboxActions = (): BoundActionCreatorsMapObject<
@ -508,14 +508,17 @@ export function reducer(
};
}
if (action.type === SET_SELECTED_LIGHTBOX_PATH) {
if (action.type === SET_SELECTED_LIGHTBOX_INDEX) {
if (!state.isShowingLightbox) {
return state;
}
return {
...state,
selectedAttachmentPath: action.payload,
selectedIndex: Math.max(
0,
Math.min(state.media.length - 1, action.payload)
),
};
}

View file

@ -27,11 +27,7 @@ export const getSelectedIndex = createSelector(
return 0;
}
const index = state.media.findIndex(
item => item.attachment.path === state.selectedAttachmentPath
);
return index > 0 ? index : 0;
return state.selectedIndex ?? 0;
}
);

View file

@ -32,7 +32,7 @@ export function SmartLightbox(): JSX.Element | null {
closeLightbox,
showLightboxForNextMessage,
showLightboxForPrevMessage,
setSelectedLightboxPath,
setSelectedLightboxIndex,
} = useLightboxActions();
const { toggleForwardMessagesModal } = useGlobalModalActions();
const { pauseVoiceNotePlayer } = useAudioPlayerActions();
@ -58,12 +58,11 @@ export function SmartLightbox(): JSX.Element | null {
}
return;
}
setSelectedLightboxPath(media[selectedIndex - 1]?.attachment.path);
setSelectedLightboxIndex(selectedIndex - 1);
}, [
showLightboxForPrevMessage,
media,
selectedIndex,
setSelectedLightboxPath,
setSelectedLightboxIndex,
hasPrevMessage,
]);
@ -74,22 +73,15 @@ export function SmartLightbox(): JSX.Element | null {
}
return;
}
setSelectedLightboxPath(media[selectedIndex + 1]?.attachment.path);
setSelectedLightboxIndex(selectedIndex + 1);
}, [
showLightboxForNextMessage,
media,
selectedIndex,
setSelectedLightboxPath,
setSelectedLightboxIndex,
hasNextMessage,
]);
const onSelectAttachment = useCallback(
(newIndex: number) => {
setSelectedLightboxPath(media[newIndex]?.attachment.path);
},
[setSelectedLightboxPath, media]
);
if (!isShowingLightbox) {
return null;
}
@ -107,7 +99,7 @@ export function SmartLightbox(): JSX.Element | null {
onMediaPlaybackStart={pauseVoiceNotePlayer}
onPrevAttachment={onPrevAttachment}
onNextAttachment={onNextAttachment}
onSelectAttachment={onSelectAttachment}
onSelectAttachment={setSelectedLightboxIndex}
hasNextMessage={hasNextMessage}
hasPrevMessage={hasPrevMessage}
/>