Support duplicate attachments in lightbox
This commit is contained in:
parent
b885ced90d
commit
1a2976dae4
7 changed files with 35 additions and 45 deletions
|
@ -19,7 +19,7 @@ export type Props = {
|
||||||
loadRecentMediaItems: (id: string, limit: number) => void;
|
loadRecentMediaItems: (id: string, limit: number) => void;
|
||||||
showAllMedia: () => void;
|
showAllMedia: () => void;
|
||||||
showLightboxWithMedia: (
|
showLightboxWithMedia: (
|
||||||
selectedAttachmentPath: string | undefined,
|
selectedIndex: number,
|
||||||
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>
|
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>
|
||||||
) => void;
|
) => void;
|
||||||
};
|
};
|
||||||
|
@ -66,9 +66,7 @@ export function ConversationDetailsMediaList({
|
||||||
key={`${mediaItem.message.id}-${mediaItem.index}`}
|
key={`${mediaItem.message.id}-${mediaItem.index}`}
|
||||||
mediaItem={mediaItem}
|
mediaItem={mediaItem}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
onClick={() =>
|
onClick={() => showLightboxWithMedia(mediaItem.index, mediaItems)}
|
||||||
showLightboxWithMedia(mediaItem.attachment.path, mediaItems)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -35,7 +35,7 @@ export function AttachmentSection({
|
||||||
const { message, index, attachment } = mediaItem;
|
const { message, index, attachment } = mediaItem;
|
||||||
|
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
onItemClick({ type, message, attachment });
|
onItemClick({ type, message, attachment, index: mediaItem.index });
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ export type Props = {
|
||||||
media: Array<MediaItemType>;
|
media: Array<MediaItemType>;
|
||||||
saveAttachment: SaveAttachmentActionCreatorType;
|
saveAttachment: SaveAttachmentActionCreatorType;
|
||||||
showLightboxWithMedia: (
|
showLightboxWithMedia: (
|
||||||
selectedAttachmentPath: string | undefined,
|
selectedIndex: number,
|
||||||
media: Array<MediaItemType>
|
media: Array<MediaItemType>
|
||||||
) => void;
|
) => void;
|
||||||
};
|
};
|
||||||
|
@ -106,7 +106,7 @@ function MediaSection({
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'media': {
|
case 'media': {
|
||||||
showLightboxWithMedia(event.attachment.path, media);
|
showLightboxWithMedia(event.index, media);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,5 +7,6 @@ import type { AttachmentType } from '../../../../types/Attachment';
|
||||||
export type ItemClickEvent = {
|
export type ItemClickEvent = {
|
||||||
message: Pick<MessageAttributesType, 'sent_at'>;
|
message: Pick<MessageAttributesType, 'sent_at'>;
|
||||||
attachment: AttachmentType;
|
attachment: AttachmentType;
|
||||||
|
index: number;
|
||||||
type: 'media' | 'documents';
|
type: 'media' | 'documents';
|
||||||
};
|
};
|
||||||
|
|
|
@ -48,12 +48,12 @@ export type LightboxStateType =
|
||||||
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>;
|
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>;
|
||||||
hasPrevMessage: boolean;
|
hasPrevMessage: boolean;
|
||||||
hasNextMessage: boolean;
|
hasNextMessage: boolean;
|
||||||
selectedAttachmentPath: string | undefined;
|
selectedIndex: number | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CLOSE_LIGHTBOX = 'lightbox/CLOSE';
|
const CLOSE_LIGHTBOX = 'lightbox/CLOSE';
|
||||||
const SHOW_LIGHTBOX = 'lightbox/SHOW';
|
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 CloseLightboxActionType = ReadonlyDeep<{
|
||||||
type: typeof CLOSE_LIGHTBOX;
|
type: typeof CLOSE_LIGHTBOX;
|
||||||
|
@ -67,13 +67,13 @@ type ShowLightboxActionType = {
|
||||||
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>;
|
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>;
|
||||||
hasPrevMessage: boolean;
|
hasPrevMessage: boolean;
|
||||||
hasNextMessage: boolean;
|
hasNextMessage: boolean;
|
||||||
selectedAttachmentPath: string | undefined;
|
selectedIndex: number | undefined;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type SetSelectedLightboxPathActionType = ReadonlyDeep<{
|
type SetSelectedLightboxIndexActionType = ReadonlyDeep<{
|
||||||
type: typeof SET_SELECTED_LIGHTBOX_PATH;
|
type: typeof SET_SELECTED_LIGHTBOX_INDEX;
|
||||||
payload: string | undefined;
|
payload: number;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
|
@ -83,7 +83,7 @@ type LightboxActionType =
|
||||||
| MessageDeletedActionType
|
| MessageDeletedActionType
|
||||||
| MessageExpiredActionType
|
| MessageExpiredActionType
|
||||||
| ShowLightboxActionType
|
| ShowLightboxActionType
|
||||||
| SetSelectedLightboxPathActionType;
|
| SetSelectedLightboxIndexActionType;
|
||||||
|
|
||||||
function closeLightbox(): ThunkAction<
|
function closeLightbox(): ThunkAction<
|
||||||
void,
|
void,
|
||||||
|
@ -116,7 +116,7 @@ function closeLightbox(): ThunkAction<
|
||||||
}
|
}
|
||||||
|
|
||||||
function showLightboxWithMedia(
|
function showLightboxWithMedia(
|
||||||
selectedAttachmentPath: string | undefined,
|
selectedIndex: number | undefined,
|
||||||
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>
|
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>
|
||||||
): ShowLightboxActionType {
|
): ShowLightboxActionType {
|
||||||
return {
|
return {
|
||||||
|
@ -124,7 +124,7 @@ function showLightboxWithMedia(
|
||||||
payload: {
|
payload: {
|
||||||
isViewOnce: false,
|
isViewOnce: false,
|
||||||
media,
|
media,
|
||||||
selectedAttachmentPath,
|
selectedIndex,
|
||||||
hasPrevMessage: false,
|
hasPrevMessage: false,
|
||||||
hasNextMessage: false,
|
hasNextMessage: false,
|
||||||
},
|
},
|
||||||
|
@ -202,7 +202,7 @@ function showLightboxForViewOnceMedia(
|
||||||
payload: {
|
payload: {
|
||||||
isViewOnce: true,
|
isViewOnce: true,
|
||||||
media,
|
media,
|
||||||
selectedAttachmentPath: undefined,
|
selectedIndex: undefined,
|
||||||
hasPrevMessage: false,
|
hasPrevMessage: false,
|
||||||
hasNextMessage: false,
|
hasNextMessage: false,
|
||||||
},
|
},
|
||||||
|
@ -335,7 +335,7 @@ function showLightbox(opts: {
|
||||||
payload: {
|
payload: {
|
||||||
isViewOnce: false,
|
isViewOnce: false,
|
||||||
media,
|
media,
|
||||||
selectedAttachmentPath: attachment.path,
|
selectedIndex: media.findIndex(({ path }) => path === attachment.path),
|
||||||
hasPrevMessage:
|
hasPrevMessage:
|
||||||
older.length > 0 && filterValidAttachments(older[0]).length > 0,
|
older.length > 0 && filterValidAttachments(older[0]).length > 0,
|
||||||
hasNextMessage:
|
hasNextMessage:
|
||||||
|
@ -464,12 +464,12 @@ function showLightboxForPrevMessage(): ThunkAction<
|
||||||
return showLightboxForAdjacentMessage(AdjacentMessageDirection.Previous);
|
return showLightboxForAdjacentMessage(AdjacentMessageDirection.Previous);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSelectedLightboxPath(
|
function setSelectedLightboxIndex(
|
||||||
path: string | undefined
|
index: number
|
||||||
): SetSelectedLightboxPathActionType {
|
): SetSelectedLightboxIndexActionType {
|
||||||
return {
|
return {
|
||||||
type: SET_SELECTED_LIGHTBOX_PATH,
|
type: SET_SELECTED_LIGHTBOX_INDEX,
|
||||||
payload: path,
|
payload: index,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,7 +480,7 @@ export const actions = {
|
||||||
showLightboxWithMedia,
|
showLightboxWithMedia,
|
||||||
showLightboxForPrevMessage,
|
showLightboxForPrevMessage,
|
||||||
showLightboxForNextMessage,
|
showLightboxForNextMessage,
|
||||||
setSelectedLightboxPath,
|
setSelectedLightboxIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useLightboxActions = (): BoundActionCreatorsMapObject<
|
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) {
|
if (!state.isShowingLightbox) {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
selectedAttachmentPath: action.payload,
|
selectedIndex: Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(state.media.length - 1, action.payload)
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,7 @@ export const getSelectedIndex = createSelector(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = state.media.findIndex(
|
return state.selectedIndex ?? 0;
|
||||||
item => item.attachment.path === state.selectedAttachmentPath
|
|
||||||
);
|
|
||||||
|
|
||||||
return index > 0 ? index : 0;
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ export function SmartLightbox(): JSX.Element | null {
|
||||||
closeLightbox,
|
closeLightbox,
|
||||||
showLightboxForNextMessage,
|
showLightboxForNextMessage,
|
||||||
showLightboxForPrevMessage,
|
showLightboxForPrevMessage,
|
||||||
setSelectedLightboxPath,
|
setSelectedLightboxIndex,
|
||||||
} = useLightboxActions();
|
} = useLightboxActions();
|
||||||
const { toggleForwardMessagesModal } = useGlobalModalActions();
|
const { toggleForwardMessagesModal } = useGlobalModalActions();
|
||||||
const { pauseVoiceNotePlayer } = useAudioPlayerActions();
|
const { pauseVoiceNotePlayer } = useAudioPlayerActions();
|
||||||
|
@ -58,12 +58,11 @@ export function SmartLightbox(): JSX.Element | null {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setSelectedLightboxPath(media[selectedIndex - 1]?.attachment.path);
|
setSelectedLightboxIndex(selectedIndex - 1);
|
||||||
}, [
|
}, [
|
||||||
showLightboxForPrevMessage,
|
showLightboxForPrevMessage,
|
||||||
media,
|
|
||||||
selectedIndex,
|
selectedIndex,
|
||||||
setSelectedLightboxPath,
|
setSelectedLightboxIndex,
|
||||||
hasPrevMessage,
|
hasPrevMessage,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -74,22 +73,15 @@ export function SmartLightbox(): JSX.Element | null {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setSelectedLightboxPath(media[selectedIndex + 1]?.attachment.path);
|
setSelectedLightboxIndex(selectedIndex + 1);
|
||||||
}, [
|
}, [
|
||||||
showLightboxForNextMessage,
|
showLightboxForNextMessage,
|
||||||
media,
|
media,
|
||||||
selectedIndex,
|
selectedIndex,
|
||||||
setSelectedLightboxPath,
|
setSelectedLightboxIndex,
|
||||||
hasNextMessage,
|
hasNextMessage,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const onSelectAttachment = useCallback(
|
|
||||||
(newIndex: number) => {
|
|
||||||
setSelectedLightboxPath(media[newIndex]?.attachment.path);
|
|
||||||
},
|
|
||||||
[setSelectedLightboxPath, media]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!isShowingLightbox) {
|
if (!isShowingLightbox) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +99,7 @@ export function SmartLightbox(): JSX.Element | null {
|
||||||
onMediaPlaybackStart={pauseVoiceNotePlayer}
|
onMediaPlaybackStart={pauseVoiceNotePlayer}
|
||||||
onPrevAttachment={onPrevAttachment}
|
onPrevAttachment={onPrevAttachment}
|
||||||
onNextAttachment={onNextAttachment}
|
onNextAttachment={onNextAttachment}
|
||||||
onSelectAttachment={onSelectAttachment}
|
onSelectAttachment={setSelectedLightboxIndex}
|
||||||
hasNextMessage={hasNextMessage}
|
hasNextMessage={hasNextMessage}
|
||||||
hasPrevMessage={hasPrevMessage}
|
hasPrevMessage={hasPrevMessage}
|
||||||
/>
|
/>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue