You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			110 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
		
		
			
		
	
	
			110 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
| 
								 
											8 years ago
										 
									 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @prettier
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								import React, { useCallback, useEffect, useState } from 'react';
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								import { Lightbox } from './Lightbox';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								// tslint:disable-next-line: no-submodule-imports
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								import useKey from 'react-use/lib/useKey';
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								import { AttachmentTypeWithPath } from '../../types/Attachment';
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								import { useDispatch, useSelector } from 'react-redux';
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								import { showLightBox } from '../../state/ducks/conversations';
							 | 
						||
| 
								 | 
							
								import { getSelectedConversationKey } from '../../state/selectors/conversations';
							 | 
						||
| 
								 | 
							
								import { MIME } from '../../types';
							 | 
						||
| 
								 | 
							
								import { saveAttachmentToDisk } from '../../util/attachmentsUtil';
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											7 years ago
										 
									 | 
							
								export interface MediaItemType {
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								  objectURL?: string;
							 | 
						||
| 
								 
											7 years ago
										 
									 | 
							
								  thumbnailObjectUrl?: string;
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								  contentType: MIME.MIMEType;
							 | 
						||
| 
								 
											7 years ago
										 
									 | 
							
								  index: number;
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								  attachment: AttachmentTypeWithPath;
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								  messageTimestamp: number;
							 | 
						||
| 
								 | 
							
								  messageSender: string;
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								  messageId: string;
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								type Props = {
							 | 
						||
| 
								 
											7 years ago
										 
									 | 
							
								  media: Array<MediaItemType>;
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								  selectedIndex: number;
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export const LightboxGallery = (props: Props) => {
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								  const { media } = props;
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								  const [currentIndex, setCurrentIndex] = useState(-1);
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								  const selectedConversation = useSelector(getSelectedConversationKey) as string;
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								  const dispatch = useDispatch();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								  // just run once, when the component is mounted. It's to show the lightbox on the specified index at start.
							 | 
						||
| 
								 | 
							
								  useEffect(() => {
							 | 
						||
| 
								 | 
							
								    setCurrentIndex(props.selectedIndex);
							 | 
						||
| 
								 | 
							
								  }, []);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const selectedMedia = media[currentIndex];
							 | 
						||
| 
								 | 
							
								  const firstIndex = 0;
							 | 
						||
| 
								 | 
							
								  const lastIndex = media.length - 1;
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								  const hasPrevious = currentIndex > firstIndex;
							 | 
						||
| 
								 | 
							
								  const hasNext = currentIndex < lastIndex;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const onPrevious = useCallback(() => {
							 | 
						||
| 
								 | 
							
								    setCurrentIndex(Math.max(currentIndex - 1, 0));
							 | 
						||
| 
								 | 
							
								  }, [currentIndex]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const onNext = useCallback(() => {
							 | 
						||
| 
								 | 
							
								    setCurrentIndex(Math.min(currentIndex + 1, lastIndex));
							 | 
						||
| 
								 | 
							
								  }, [currentIndex, lastIndex]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const handleSave = useCallback(() => {
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								    const mediaItem = media[currentIndex];
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								    void saveAttachmentToDisk({ ...mediaItem, conversationId: selectedConversation });
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								  }, [currentIndex, media]);
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								  useKey(
							 | 
						||
| 
								 | 
							
								    'ArrowRight',
							 | 
						||
| 
								 | 
							
								    () => {
							 | 
						||
| 
								 | 
							
								      onNext?.();
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    undefined,
							 | 
						||
| 
								 | 
							
								    [currentIndex]
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								  useKey(
							 | 
						||
| 
								 | 
							
								    'ArrowLeft',
							 | 
						||
| 
								 | 
							
								    () => {
							 | 
						||
| 
								 | 
							
								      onPrevious?.();
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    undefined,
							 | 
						||
| 
								 | 
							
								    [currentIndex]
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								  useKey(
							 | 
						||
| 
								 | 
							
								    'Escape',
							 | 
						||
| 
								 | 
							
								    () => {
							 | 
						||
| 
								 | 
							
								      dispatch(showLightBox(undefined));
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    undefined,
							 | 
						||
| 
								 | 
							
								    [currentIndex]
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								  // just to avoid to render the first element during the first render when the user selected another item
							 | 
						||
| 
								 | 
							
								  if (currentIndex === -1) {
							 | 
						||
| 
								 | 
							
								    return null;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  const objectURL = selectedMedia?.objectURL || 'images/alert-outline.svg';
							 | 
						||
| 
								 | 
							
								  const { attachment } = selectedMedia;
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								  const caption = attachment?.caption;
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								  return (
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								    // tslint:disable: use-simple-attributes
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								    <Lightbox
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								      onPrevious={hasPrevious ? onPrevious : undefined}
							 | 
						||
| 
								 | 
							
								      onNext={hasNext ? onNext : undefined}
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								      onSave={handleSave}
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								      objectURL={objectURL}
							 | 
						||
| 
								 
											4 years ago
										 
									 | 
							
								      caption={caption}
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								      contentType={selectedMedia.contentType}
							 | 
						||
| 
								 | 
							
								    />
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								};
							 |