diff --git a/apps/meteor/client/components/ImageGallery/ImageGallery.styles.css b/apps/meteor/client/components/ImageGallery/ImageGallery.styles.css deleted file mode 100644 index 5891362140e3b..0000000000000 --- a/apps/meteor/client/components/ImageGallery/ImageGallery.styles.css +++ /dev/null @@ -1,72 +0,0 @@ -:root { - --swiper-navigation-size: 44px; -} - -.swiper-container { - background-color: var(--rcx-color-surface-overlay, rgba(0, 0, 0, 0.6)); -} - -.rcx-swiper-close-button, -.rcx-swiper-prev-button, -.rcx-swiper-next-button { - color: var(--rcx-color-font-pure-white, #ffffff) !important; -} - -.rcx-swiper-close-button { - position: absolute; - z-index: 10; - top: 10px; - right: 10px; -} - -.rcx-swiper-prev-button, -.rcx-swiper-next-button { - position: absolute; - z-index: 10; - top: 50%; - - cursor: pointer; -} - -.rcx-swiper-prev-button.swiper-button-disabled, -.rcx-swiper-next-button.swiper-button-disabled { - cursor: auto; - pointer-events: none; - - opacity: 0.35; -} - -.rcx-swiper-prev-button.swiper-button-hidden, -.rcx-swiper-next-button.swiper-button-hidden { - cursor: auto; - pointer-events: none; - - opacity: 0; -} - -.swiper-navigation-disabled .rcx-swiper-prev-button, -.swiper-navigation-disabled .rcx-swiper-next-button { - display: none !important; -} - -.rcx-swiper-prev-button, -.swiper-rtl .rcx-swiper-next-button { - right: auto; - left: 10px; -} - -.rcx-swiper-prev-button::after, -.swiper-rtl .rcx-swiper-next-button::after { - content: 'prev'; -} - -.rcx-swiper-next-button, -.swiper-rtl .rcx-swiper-prev-button { - right: 10px; - left: auto; -} - -.rcx-swiper-next-button::after, -.swiper-rtl .rcx-swiper-prev-button::after { - content: 'next'; -} diff --git a/apps/meteor/client/components/ImageGallery/ImageGallery.tsx b/apps/meteor/client/components/ImageGallery/ImageGallery.tsx index ac550981d9b0d..7fbdda69de7d5 100644 --- a/apps/meteor/client/components/ImageGallery/ImageGallery.tsx +++ b/apps/meteor/client/components/ImageGallery/ImageGallery.tsx @@ -1,5 +1,6 @@ -import { IconButton, ModalBackdrop, Throbber } from '@rocket.chat/fuselage'; -import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { css } from '@rocket.chat/css-in-js'; +import { Box, IconButton, ModalBackdrop, Throbber } from '@rocket.chat/fuselage'; +import React, { useMemo, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { Keyboard, Navigation, Zoom, A11y } from 'swiper'; import type { SwiperRef } from 'swiper/react'; @@ -10,32 +11,88 @@ import 'swiper/swiper.css'; import 'swiper/modules/navigation/navigation.min.css'; import 'swiper/modules/keyboard/keyboard.min.css'; import 'swiper/modules/zoom/zoom.min.css'; -import './ImageGallery.styles.css'; import { useRecordList } from '../../hooks/lists/useRecordList'; import { useRoom } from '../../views/room/contexts/RoomContext'; import { useFilesList } from '../../views/room/contextualBar/RoomFiles/hooks/useFilesList'; +const swiperStyle = css` + .swiper-container { + background-color: var(--rcx-color-surface-overlay, rgba(0, 0, 0, 0.6)); + } + + .rcx-swiper-close-button, + .rcx-swiper-prev-button, + .rcx-swiper-next-button { + color: var(--rcx-color-font-pure-white, #ffffff) !important; + } + + .rcx-swiper-close-button { + position: absolute; + z-index: 10; + top: 10px; + right: 10px; + } + + .rcx-swiper-prev-button, + .rcx-swiper-next-button { + position: absolute; + z-index: 10; + top: 50%; + + cursor: pointer; + } + + .rcx-swiper-prev-button.swiper-button-disabled, + .rcx-swiper-next-button.swiper-button-disabled { + cursor: auto; + pointer-events: none; + + opacity: 0.35; + } + + .rcx-swiper-prev-button.swiper-button-hidden, + .rcx-swiper-next-button.swiper-button-hidden { + cursor: auto; + pointer-events: none; + + opacity: 0; + } + + .rcx-swiper-prev-button, + .swiper-rtl .rcx-swiper-next-button { + right: auto; + left: 10px; + } + + .rcx-swiper-next-button, + .swiper-rtl .rcx-swiper-prev-button { + right: 10px; + left: auto; + } +`; const ImageGallery = ({ url, onClose, sortByRecent }: { url: string; onClose: () => void; sortByRecent?: boolean; name?: string }) => { const room = useRoom(); const swiperRef = useRef(null); const [images, setImages] = useState([]); - const [swiperInst, setSwiperInst] = useState(); + const [, setSwiperInst] = useState(); const [currentSlide, setCurrentSlide] = useState(); const { filesList, loadMoreItems } = useFilesList(useMemo(() => ({ rid: room._id, type: 'image', text: '' }), [room._id])); const { phase, items: filesItems } = useRecordList(filesList); - useEffect(() => { - const list = sortByRecent ? [...filesItems] : [...filesItems].reverse(); + const onBeforeInit = useMemo( + () => () => { + const list = sortByRecent ? [...filesItems] : [...filesItems].reverse(); - if (phase === 'resolved') { - setImages(list.map((item) => item.url || '').filter(Boolean)); - setCurrentSlide(list.findIndex((item) => url.includes(item._id))); - } - return () => swiperInst?.update(); - }, [filesItems, phase, sortByRecent, swiperInst, url]); + if (phase === 'resolved') { + setImages(list.map((item) => item.url || '').filter(Boolean)); + setCurrentSlide(list.findIndex((item) => url.includes(item._id))); + } + }, + [filesItems, phase, sortByRecent, url], + ); const swiperLoader = ( @@ -46,39 +103,47 @@ const ImageGallery = ({ url, onClose, sortByRecent }: { url: string; onClose: () return createPortal(swiperLoader, document.body); } + const handleLoadMore = () => { + loadMoreItems(images.length - currentSlide, images.length + 1); + }; + const swiperContainer = ( -
- - swiperRef?.current?.swiper.slidePrev()} /> - swiperRef?.current?.swiper.slideNext()} /> - String(keyCode) === '27' && onClose()} - modules={[Navigation, Zoom, Keyboard, A11y]} - onInit={(swiper) => setSwiperInst(swiper)} - onReachEnd={() => loadMoreItems(images.length - currentSlide, images.length + 1)} - > - {images?.map((image, index) => ( - -
- -
- + +
+ + swiperRef?.current?.swiper.slidePrev()} /> + swiperRef?.current?.swiper.slideNext()} /> + String(keyCode) === '27' && onClose()} + modules={[Navigation, Zoom, Keyboard, A11y]} + onInit={(swiper) => setSwiperInst(swiper)} + onReachBeginning={handleLoadMore} + onReachEnd={handleLoadMore} + onBeforeInit={onBeforeInit} + > + {images?.map((image, index) => ( + +
+ +
+ +
-
- - ))} - -
+ + ))} + +
+ ); return createPortal(swiperContainer, document.body); }; diff --git a/apps/meteor/client/components/ImageGallery/hooks/useGalleryList.ts b/apps/meteor/client/components/ImageGallery/hooks/useGalleryList.ts deleted file mode 100644 index 6b75b5c86db6d..0000000000000 --- a/apps/meteor/client/components/ImageGallery/hooks/useGalleryList.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { useUserRoom, useUserId, useEndpoint } from '@rocket.chat/ui-contexts'; -import { useCallback, useEffect, useMemo, useState } from 'react'; - -import { useScrollableRecordList } from '../../../hooks/lists/useScrollableRecordList'; -import { useStreamUpdatesForMessageList } from '../../../hooks/lists/useStreamUpdatesForMessageList'; -import { useComponentDidUpdate } from '../../../hooks/useComponentDidUpdate'; -// import type { FilesListOptions } from '../../../lib/lists/FilesList'; -import { FilesList } from '../../../lib/lists/FilesList'; -import type { MessageList } from '../../../lib/lists/MessageList'; -// import { getConfig } from '../../../lib/utils/getConfig'; - -export const useGalleryList = ({ - rid, - name, - url, -}: any): { - filesList: FilesList; - initialItemCount: number; - reload: () => void; - loadMoreItems: (start: number, end: number) => void; -} => { - const options = useMemo(() => ({ rid, type: 'image', text: '' }), [rid]); - - const [filesList, setFilesList] = useState(() => new FilesList(options)); - const reload = useCallback(() => setFilesList(new FilesList(options)), [options]); - const room = useUserRoom(options.rid); - const uid = useUserId(); - - useComponentDidUpdate(() => { - options && reload(); - }, [options, reload]); - - useEffect(() => { - if (filesList.options !== options) { - filesList.updateFilters(options); - } - }, [filesList, options]); - - const roomTypes = { - c: '/v1/channels.files', - l: '/v1/channels.files', - v: '/v1/channels.files', - d: '/v1/im.files', - p: '/v1/groups.files', - } as const; - - const apiEndPoint = room ? roomTypes[room.t] : '/v1/channels.files'; - const getFiles = useEndpoint('GET', apiEndPoint); - - const fetchMessages = useCallback( - async (start, end) => { - console.log(start, end, url); - const { files, total } = await getFiles({ - roomId: options.rid, - offset: start, - count: end, - sort: JSON.stringify({ uploadedAt: -1 }), - query: JSON.stringify({ - name: { $regex: options.text || '', $options: 'i' }, - ...(options.type !== 'all' && { - typeGroup: options.type, - }), - }), - }); - // http://localhost:3000/ufs/GridFS:Uploads/65243e6f0ceb6de1166812a6/Clipboard%20-%20October%209,%202023%2014:54.png - // /ufs/GridFS:Uploads/65243e6f0ceb6de1166812a6/Clipboard%20-%20October%209,%202023%2014:54.png - - console.log('files', files); - return { - items: files.map((file) => ({ - ...file, - uploadedAt: file.uploadedAt ? new Date(file.uploadedAt) : undefined, - modifiedAt: file.modifiedAt ? new Date(file.modifiedAt) : undefined, - })), - itemCount: total, - }; - }, - [url, getFiles, options.rid, options.text, options.type], - ); - - const { loadMoreItems, initialItemCount } = useScrollableRecordList(filesList, fetchMessages, 10); - - // TODO: chapter day : frontend create useStreamUpdatesForUploadList - useStreamUpdatesForMessageList(filesList as unknown as MessageList, uid, options.rid || null); - - return { - reload, - filesList, - loadMoreItems, - initialItemCount, - }; -};