Procházet zdrojové kódy

Inmemory caching with photoswipe on thumbnail.

Pushkar Anand před 4 roky
rodič
revize
6adc49cc2b

+ 2 - 1
package.json

@@ -9,7 +9,6 @@
     "start": "next start"
     "start": "next start"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@types/localforage": "^0.0.34",
     "axios": "^0.20.0",
     "axios": "^0.20.0",
     "bootstrap": "^4.5.2",
     "bootstrap": "^4.5.2",
     "comlink": "^4.3.0",
     "comlink": "^4.3.0",
@@ -33,8 +32,10 @@
   "devDependencies": {
   "devDependencies": {
     "@next/bundle-analyzer": "^9.5.3",
     "@next/bundle-analyzer": "^9.5.3",
     "@types/libsodium-wrappers": "^0.7.8",
     "@types/libsodium-wrappers": "^0.7.8",
+    "@types/localforage": "^0.0.34",
     "@types/node": "^14.6.4",
     "@types/node": "^14.6.4",
     "@types/react": "^16.9.49",
     "@types/react": "^16.9.49",
+    "@types/react-photoswipe": "^1.3.0",
     "@types/react-window": "^1.8.2",
     "@types/react-window": "^1.8.2",
     "@types/react-window-infinite-loader": "^1.0.3",
     "@types/react-window-infinite-loader": "^1.0.3",
     "@types/styled-components": "^5.1.3",
     "@types/styled-components": "^5.1.3",

+ 15 - 7
src/pages/gallery/components/PreviewCard.tsx

@@ -1,20 +1,22 @@
 import React, { useEffect, useState } from 'react';
 import React, { useEffect, useState } from 'react';
 import { file, getPreview } from 'services/fileService';
 import { file, getPreview } from 'services/fileService';
-import { getActualKey } from 'utils/common/key';
 import { getData, LS_KEYS } from 'utils/storage/localStorage';
 import { getData, LS_KEYS } from 'utils/storage/localStorage';
 import styled from 'styled-components';
 import styled from 'styled-components';
 
 
 interface IProps {
 interface IProps {
     data: file,
     data: file,
+    updateUrl: (url: string) => void,
+    onClick: () => void,
 }
 }
 
 
-const Cont = styled.div`
+const Cont = styled.div<{ disabled: boolean }>`
     background: #555 url(/image.svg) no-repeat center;
     background: #555 url(/image.svg) no-repeat center;
     margin: 0 4px;
     margin: 0 4px;
     display: inline-block;
     display: inline-block;
     width: 192px;
     width: 192px;
     height: 192px;
     height: 192px;
     overflow: hidden;
     overflow: hidden;
+    cursor: ${props => props.disabled ? 'not-allowed' : 'pointer'};
 
 
     & > img {
     & > img {
         object-fit: cover;
         object-fit: cover;
@@ -25,22 +27,28 @@ const Cont = styled.div`
 
 
 export default function PreviewCard(props: IProps) {
 export default function PreviewCard(props: IProps) {
     const [imgSrc, setImgSrc] = useState<string>();
     const [imgSrc, setImgSrc] = useState<string>();
-    const { data } = props;
+    const { data, onClick, updateUrl } = props;
 
 
     useEffect(() => {
     useEffect(() => {
-        if (data) {
+        if (data && !data.src) {
             const main = async () => {
             const main = async () => {
                 const token = getData(LS_KEYS.USER).token;
                 const token = getData(LS_KEYS.USER).token;
-                const key = await getActualKey();
                 const url = await getPreview(token, data);
                 const url = await getPreview(token, data);
                 setImgSrc(url);
                 setImgSrc(url);
                 data.src = url;
                 data.src = url;
+                updateUrl(url);
             }
             }
             main();
             main();
         }
         }
     }, [data]);
     }, [data]);
 
 
-    return <Cont>
-        <img src={imgSrc} />
+    const handleClick = () => {
+        if (data.src || imgSrc) {
+            onClick();
+        }
+    }
+
+    return <Cont onClick={handleClick} disabled={!data.src && !imgSrc}>
+        <img src={data.src || imgSrc} />
     </Cont>;
     </Cont>;
 }
 }

+ 48 - 10
src/pages/gallery/index.tsx

@@ -7,7 +7,8 @@ import { getData, LS_KEYS } from 'utils/storage/localStorage';
 import PreviewCard from './components/PreviewCard';
 import PreviewCard from './components/PreviewCard';
 import { getActualKey } from 'utils/common/key';
 import { getActualKey } from 'utils/common/key';
 import styled from 'styled-components';
 import styled from 'styled-components';
-import { PhotoSwipeGallery } from 'react-photoswipe';
+import { PhotoSwipe } from 'react-photoswipe';
+import { Options } from 'photoswipe';
 import AutoSizer from 'react-virtualized-auto-sizer';
 import AutoSizer from 'react-virtualized-auto-sizer';
 import { FixedSizeList as List } from 'react-window';
 import { FixedSizeList as List } from 'react-window';
 
 
@@ -36,7 +37,10 @@ export default function Gallery() {
     const router = useRouter();
     const router = useRouter();
     const [loading, setLoading] = useState(false);
     const [loading, setLoading] = useState(false);
     const [data, setData] = useState<file[]>();
     const [data, setData] = useState<file[]>();
-    const [total, setTotal] = useState(1);
+    const [open, setOpen] = useState(false);
+    const [options, setOptions] = useState<Options>({
+        history: false,
+    });
 
 
     useEffect(() => {
     useEffect(() => {
         const key = getKey(SESSION_KEYS.ENCRYPTION_KEY);
         const key = getKey(SESSION_KEYS.ENCRYPTION_KEY);
@@ -49,7 +53,11 @@ export default function Gallery() {
             const encryptionKey = await getActualKey();
             const encryptionKey = await getActualKey();
             const resp = await getFiles("0", token, "100", encryptionKey);
             const resp = await getFiles("0", token, "100", encryptionKey);
             setLoading(false);
             setLoading(false);
-            setData(resp);
+            setData(resp.map(item => ({
+                ...item,
+                w: window.innerWidth,
+                h: window.innerHeight,
+            })));
         };
         };
         main();
         main();
     }, []);
     }, []);
@@ -60,8 +68,32 @@ export default function Gallery() {
         </div>
         </div>
     }
     }
 
 
-    const getThumbnail = (item) => (
-        <PreviewCard data={item} />
+    const updateUrl = (index: number) => (url: string) => {
+        data[index] = {
+            ...data[index],
+            src: url,
+        }
+        setData(data);
+    }
+
+    const handleClose = () => {
+        setOpen(false);
+    }
+
+    const onThumbnailClick = (index: number) => () => {
+        setOptions({
+            ...options,
+            index,
+        });
+        setOpen(true);
+    }
+
+    const getThumbnail = (data: file[], index: number) => (
+        <PreviewCard
+            data={data[index]}
+            updateUrl={updateUrl(index)}
+            onClick={onThumbnailClick(index)}
+        />
     )
     )
 
 
     return (<Container>
     return (<Container>
@@ -75,14 +107,20 @@ export default function Gallery() {
                     
                     
                 >
                 >
                     {({ index, style }) => <ListItem style={style}>
                     {({ index, style }) => <ListItem style={style}>
-                        {getThumbnail(data[index * 5])}
-                        {getThumbnail(data[index * 5 + 1])}
-                        {getThumbnail(data[index * 5 + 2])}
-                        {getThumbnail(data[index * 5 + 3])}
-                        {getThumbnail(data[index * 5 + 4])}
+                        {getThumbnail(data, index * 5)}
+                        {getThumbnail(data, index * 5 + 1)}
+                        {getThumbnail(data, index * 5 + 2)}
+                        {getThumbnail(data, index * 5 + 3)}
+                        {getThumbnail(data, index * 5 + 4)}
                     </ListItem>}
                     </ListItem>}
                 </List>
                 </List>
             )}
             )}
         </AutoSizer>
         </AutoSizer>
+        <PhotoSwipe
+            isOpen={open}
+            items={data}
+            options={options}
+            onClose={handleClose}
+        />
     </Container>);
     </Container>);
 }
 }

+ 1 - 1
src/utils/common/apiUtil.ts

@@ -1,3 +1,3 @@
 export const getEndpoint = () => {
 export const getEndpoint = () => {
-    return process.env.NEXT_PUBLIC_ENTE_ENDPOINT || "https://api.staging.ente.io";
+    return process.env.NEXT_PUBLIC_ENTE_ENDPOINT || "https://api.ente.io";
 }
 }

+ 13 - 0
yarn.lock

@@ -1149,6 +1149,11 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a"
   integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==
   integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==
 
 
+"@types/photoswipe@*":
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/@types/photoswipe/-/photoswipe-4.1.0.tgz#212ad2b05d67828b24d424a01cb6fbb0735d37db"
+  integrity sha512-SWcWlJH8exQ/yijUNQn5pJdSrcsfPwyBmksBPa4NLNaUr4rhaC7YOGcrNSoIAC9LByoEbTIKWQpFVtHjomTTLA==
+
 "@types/prop-types@*", "@types/prop-types@^15.7.3":
 "@types/prop-types@*", "@types/prop-types@^15.7.3":
   version "15.7.3"
   version "15.7.3"
   resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
   resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
@@ -1161,6 +1166,14 @@
   dependencies:
   dependencies:
     "@types/react" "*"
     "@types/react" "*"
 
 
+"@types/react-photoswipe@^1.3.0":
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/@types/react-photoswipe/-/react-photoswipe-1.3.0.tgz#c22948d540e7febe541f9a96742110b566105026"
+  integrity sha512-HqOyG+N1Ifjs3xd88bxGQbxv+ookIs94L/JPpYvcnkb1UMc7nBtEcCNvQ9QPB+eiFFG72z/uqA0poagRl0nopA==
+  dependencies:
+    "@types/photoswipe" "*"
+    "@types/react" "*"
+
 "@types/react-transition-group@^4.4.0":
 "@types/react-transition-group@^4.4.0":
   version "4.4.0"
   version "4.4.0"
   resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.0.tgz#882839db465df1320e4753e6e9f70ca7e9b4d46d"
   resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.0.tgz#882839db465df1320e4753e6e9f70ca7e9b4d46d"