Pārlūkot izejas kodu

wip zip selection on web itself

Manav Rathi 1 gadu atpakaļ
vecāks
revīzija
13f0ff3af5

+ 52 - 7
web/apps/photos/src/components/Upload/Uploader.tsx

@@ -76,8 +76,10 @@ interface Props {
     showSessionExpiredMessage: () => void;
     showUploadFilesDialog: () => void;
     showUploadDirsDialog: () => void;
+    showUploadZipFilesDialog?: () => void;
     webFolderSelectorFiles: File[];
     webFileSelectorFiles: File[];
+    webFileSelectorZipFiles?: File[];
     dragAndDropFiles: File[];
     uploadCollection?: Collection;
     uploadTypeSelectorIntent: UploadTypeSelectorIntent;
@@ -255,24 +257,59 @@ export default function Uploader(props: Props) {
         ) {
             log.info(`received file upload request`);
             setWebFiles(props.webFileSelectorFiles);
+        } else if (
+            pickedUploadType.current === PICKED_UPLOAD_TYPE.ZIPS &&
+            props.webFileSelectorZipFiles?.length > 0
+        ) {
+            if (electron) {
+                const main = async () => {
+                    const zips: File[] = [];
+                    let electronFiles = [] as ElectronFile[];
+                    for (const file of props.webFileSelectorZipFiles) {
+                        if (file.name.endsWith(".zip")) {
+                            const zipFiles = await electron.lsZip(
+                                (file as any).path,
+                            );
+                            log.info(
+                                `zip file - ${file.name} contains ${zipFiles.length} files`,
+                            );
+                            zips.push(file);
+                            // TODO(MR): This cast is incorrect, but interim.
+                            electronFiles = [
+                                ...electronFiles,
+                                ...(zipFiles as unknown as ElectronFile[]),
+                            ];
+                        }
+                    }
+                    // setWebFiles(props.webFileSelectorZipFiles);
+                    zipPaths.current = zips.map((file) => (file as any).path);
+                    setElectronFiles(electronFiles);
+                };
+                main();
+            }
         } else if (props.dragAndDropFiles?.length > 0) {
             isDragAndDrop.current = true;
             if (electron) {
                 const main = async () => {
                     try {
-                        log.info(`uploading dropped files from desktop app`);
                         // check and parse dropped files which are zip files
+                        log.info(`uploading dropped files from desktop app`);
+                        const zips: File[] = [];
                         let electronFiles = [] as ElectronFile[];
                         for (const file of props.dragAndDropFiles) {
                             if (file.name.endsWith(".zip")) {
-                                const zipFiles =
-                                    await electron.getElectronFilesFromGoogleZip(
-                                        (file as any).path,
-                                    );
+                                const zipFiles = await electron.lsZip(
+                                    (file as any).path,
+                                );
                                 log.info(
                                     `zip file - ${file.name} contains ${zipFiles.length} files`,
                                 );
-                                electronFiles = [...electronFiles, ...zipFiles];
+                                zips.push(file);
+                                // TODO(MR): This cast is incorrect, but interim.
+                                electronFiles = [
+                                    ...electronFiles,
+                                    ...(zipFiles as unknown as ElectronFile[]),
+                                ];
                             } else {
                                 // type cast to ElectronFile as the file is dropped from desktop app
                                 // type file and ElectronFile should be interchangeable, but currently they have some differences.
@@ -290,6 +327,9 @@ export default function Uploader(props: Props) {
                         log.info(
                             `uploading dropped files from desktop app - ${electronFiles.length} files found`,
                         );
+                        zipPaths.current = zips.map(
+                            (file) => (file as any).path,
+                        );
                         setElectronFiles(electronFiles);
                     } catch (e) {
                         log.error("failed to upload desktop dropped files", e);
@@ -306,6 +346,7 @@ export default function Uploader(props: Props) {
         props.dragAndDropFiles,
         props.webFileSelectorFiles,
         props.webFolderSelectorFiles,
+        props.webFileSelectorZipFiles,
     ]);
 
     useEffect(() => {
@@ -768,7 +809,11 @@ export default function Uploader(props: Props) {
         } else if (type === PICKED_UPLOAD_TYPE.FOLDERS) {
             props.showUploadDirsDialog();
         } else {
-            appContext.setDialogMessage(getDownloadAppMessage());
+            if (props.showUploadZipFilesDialog && electron) {
+                props.showUploadZipFilesDialog();
+            } else {
+                appContext.setDialogMessage(getDownloadAppMessage());
+            }
         }
     };
 

+ 4 - 0
web/apps/photos/src/components/UploadSelectorInputs.tsx

@@ -2,12 +2,16 @@ export default function UploadSelectorInputs({
     getDragAndDropInputProps,
     getFileSelectorInputProps,
     getFolderSelectorInputProps,
+    getZipFileSelectorInputProps,
 }) {
     return (
         <>
             <input {...getDragAndDropInputProps()} />
             <input {...getFileSelectorInputProps()} />
             <input {...getFolderSelectorInputProps()} />
+            {getZipFileSelectorInputProps && (
+                <input {...getZipFileSelectorInputProps()} />
+            )}
         </>
     );
 }

+ 11 - 0
web/apps/photos/src/pages/gallery/index.tsx

@@ -224,6 +224,14 @@ export default function Gallery() {
     } = useFileInput({
         directory: true,
     });
+    const {
+        selectedFiles: webFileSelectorZipFiles,
+        open: openZipFileSelector,
+        getInputProps: getZipFileSelectorInputProps,
+    } = useFileInput({
+        directory: false,
+        accept: ".zip"
+    });
 
     const [isInSearchMode, setIsInSearchMode] = useState(false);
     const [searchResultSummary, setSetSearchResultSummary] =
@@ -1023,6 +1031,7 @@ export default function Gallery() {
                     getDragAndDropInputProps={getDragAndDropInputProps}
                     getFileSelectorInputProps={getFileSelectorInputProps}
                     getFolderSelectorInputProps={getFolderSelectorInputProps}
+                    getZipFileSelectorInputProps={getZipFileSelectorInputProps}
                 />
                 {blockingLoad && (
                     <LoadingOverlay>
@@ -1123,10 +1132,12 @@ export default function Gallery() {
                     }
                     webFileSelectorFiles={webFileSelectorFiles}
                     webFolderSelectorFiles={webFolderSelectorFiles}
+                    webFileSelectorZipFiles={webFileSelectorZipFiles}
                     dragAndDropFiles={dragAndDropFiles}
                     uploadTypeSelectorView={uploadTypeSelectorView}
                     showUploadFilesDialog={openFileSelector}
                     showUploadDirsDialog={openFolderSelector}
+                    showUploadZipFilesDialog={openZipFileSelector}
                     showSessionExpiredMessage={showSessionExpiredMessage}
                 />
                 <Sidebar

+ 1 - 0
web/apps/photos/src/pages/shared-albums/index.tsx

@@ -550,6 +550,7 @@ export default function PublicCollectionGallery() {
                     getDragAndDropInputProps={getDragAndDropInputProps}
                     getFileSelectorInputProps={getFileSelectorInputProps}
                     getFolderSelectorInputProps={getFolderSelectorInputProps}
+                    getZipFileSelectorInputProps={undefined}
                 />
                 <SharedAlbumNavbar
                     showUploadButton={

+ 17 - 3
web/packages/shared/hooks/useFileInput.tsx

@@ -18,6 +18,11 @@ export interface FileWithPath extends File {
     readonly path?: string;
 }
 
+interface UseFileInputParams {
+    directory?: boolean;
+    accept?: string;
+}
+
 /**
  * Return three things:
  *
@@ -33,10 +38,18 @@ export interface FileWithPath extends File {
  *   user selected directories - in that case, it will be the recursive list of
  *   files within this directory.
  *
- * @param param0 If {@link directory} is true, the file open dialog will ask the
- * user to select directories. Otherwise it'll ask the user to select files.
+ * @param param0
+ *
+ * - If {@link directory} is true, the file open dialog will ask the user to
+ *   select directories. Otherwise it'll ask the user to select files.
+ *
+ * - If {@link accept} is specified, it'll restrict the type of files that the
+ *   user can select by setting the "accept" attribute of the underlying HTML
+ *   input element we use to surface the file selector dialog. For value of
+ *   accept can be an extension or a MIME type (See
+ *   https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept).
  */
-export default function useFileInput({ directory }: { directory?: boolean }) {
+export default function useFileInput({ directory, accept }: UseFileInputParams) {
     const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
     const inputRef = useRef<HTMLInputElement>();
 
@@ -66,6 +79,7 @@ export default function useFileInput({ directory }: { directory?: boolean }) {
             ...(directory ? { directory: "", webkitdirectory: "" } : {}),
             ref: inputRef,
             onChange: handleChange,
+            ...(accept ? { accept } : {}),
         }),
         [],
     );