Enum to type - wip
This commit is contained in:
parent
739c541f5d
commit
ca5b98b8d2
5 changed files with 65 additions and 64 deletions
|
@ -8,7 +8,7 @@ import {
|
|||
DEFAULT_IMPORT_SUGGESTION,
|
||||
PICKED_UPLOAD_TYPE,
|
||||
UPLOAD_STAGES,
|
||||
UPLOAD_STRATEGY,
|
||||
type CollectionMapping,
|
||||
} from "constants/upload";
|
||||
import { t } from "i18next";
|
||||
import isElectron from "is-electron";
|
||||
|
@ -391,7 +391,7 @@ export default function Uploader(props: Props) {
|
|||
};
|
||||
|
||||
const uploadFilesToNewCollections = async (
|
||||
strategy: UPLOAD_STRATEGY,
|
||||
strategy: CollectionMapping,
|
||||
collectionName?: string,
|
||||
) => {
|
||||
try {
|
||||
|
@ -405,7 +405,7 @@ export default function Uploader(props: Props) {
|
|||
string,
|
||||
(File | ElectronFile)[]
|
||||
>();
|
||||
if (strategy === UPLOAD_STRATEGY.SINGLE_COLLECTION) {
|
||||
if (strategy == "root") {
|
||||
collectionNameToFilesMap.set(
|
||||
collectionName,
|
||||
toUploadFiles.current,
|
||||
|
@ -605,10 +605,7 @@ export default function Uploader(props: Props) {
|
|||
}
|
||||
|
||||
const uploadToSingleNewCollection = (collectionName: string) => {
|
||||
uploadFilesToNewCollections(
|
||||
UPLOAD_STRATEGY.SINGLE_COLLECTION,
|
||||
collectionName,
|
||||
);
|
||||
uploadFilesToNewCollections("root", collectionName);
|
||||
};
|
||||
|
||||
const showCollectionCreateModal = (suggestedName: string) => {
|
||||
|
@ -647,7 +644,7 @@ export default function Uploader(props: Props) {
|
|||
`upload pending files to collection - ${pendingDesktopUploadCollectionName.current}`,
|
||||
);
|
||||
uploadFilesToNewCollections(
|
||||
UPLOAD_STRATEGY.SINGLE_COLLECTION,
|
||||
"root",
|
||||
pendingDesktopUploadCollectionName.current,
|
||||
);
|
||||
pendingDesktopUploadCollectionName.current = null;
|
||||
|
@ -655,17 +652,13 @@ export default function Uploader(props: Props) {
|
|||
log.info(
|
||||
`pending upload - strategy - "multiple collections" `,
|
||||
);
|
||||
uploadFilesToNewCollections(
|
||||
UPLOAD_STRATEGY.COLLECTION_PER_FOLDER,
|
||||
);
|
||||
uploadFilesToNewCollections("leaf");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (isElectron() && pickedUploadType === PICKED_UPLOAD_TYPE.ZIPS) {
|
||||
log.info("uploading zip files");
|
||||
uploadFilesToNewCollections(
|
||||
UPLOAD_STRATEGY.COLLECTION_PER_FOLDER,
|
||||
);
|
||||
uploadFilesToNewCollections("leaf");
|
||||
return;
|
||||
}
|
||||
if (isFirstUpload && !importSuggestion.rootFolderName) {
|
||||
|
@ -784,7 +777,7 @@ export default function Uploader(props: Props) {
|
|||
);
|
||||
return;
|
||||
}
|
||||
uploadFilesToNewCollections(UPLOAD_STRATEGY.COLLECTION_PER_FOLDER);
|
||||
uploadFilesToNewCollections("leaf");
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { ensureElectron } from "@/next/electron";
|
||||
import { FolderWatch } from "@/next/types/ipc";
|
||||
import type { CollectionMapping, FolderWatch } from "@/next/types/ipc";
|
||||
import { ensure } from "@/utils/ensure";
|
||||
import {
|
||||
FlexWrapper,
|
||||
HorizontalFlex,
|
||||
|
@ -26,7 +27,7 @@ import {
|
|||
} from "@mui/material";
|
||||
import { styled } from "@mui/material/styles";
|
||||
import UploadStrategyChoiceModal from "components/Upload/UploadStrategyChoiceModal";
|
||||
import { PICKED_UPLOAD_TYPE, UPLOAD_STRATEGY } from "constants/upload";
|
||||
import { PICKED_UPLOAD_TYPE } from "constants/upload";
|
||||
import { t } from "i18next";
|
||||
import { AppContext } from "pages/_app";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
|
@ -44,11 +45,17 @@ interface WatchFolderProps {
|
|||
* This is the screen that controls that "watch folder" feature in the app.
|
||||
*/
|
||||
export const WatchFolder: React.FC<WatchFolderProps> = ({ open, onClose }) => {
|
||||
// The folders we are watching
|
||||
const [watches, setWatches] = useState<FolderWatch[] | undefined>();
|
||||
const [inputFolderPath, setInputFolderPath] = useState<
|
||||
// Temporarily stash the folder path while we show a choice dialog to the
|
||||
// user to select the collection mapping.
|
||||
const [savedFolderPath, setSavedFolderPath] = useState<
|
||||
string | undefined
|
||||
>();
|
||||
// True when we're showing the choice dialog to ask the user to set the
|
||||
// collection mapping.
|
||||
const [choiceModalOpen, setChoiceModalOpen] = useState(false);
|
||||
|
||||
const appContext = useContext(AppContext);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -70,43 +77,34 @@ export const WatchFolder: React.FC<WatchFolderProps> = ({ open, onClose }) => {
|
|||
const folder: any = folders[i];
|
||||
const path = (folder.path as string).replace(/\\/g, "/");
|
||||
if (await watcher.isFolder(path)) {
|
||||
await addFolderForWatching(path);
|
||||
await selectCollectionMappingAndAddWatch(path);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const addFolderForWatching = async (path: string) => {
|
||||
setInputFolderPath(path);
|
||||
const selectCollectionMappingAndAddWatch = async (path: string) => {
|
||||
const files = await ensureElectron().getDirFiles(path);
|
||||
const analysisResult = getImportSuggestion(
|
||||
PICKED_UPLOAD_TYPE.FOLDERS,
|
||||
files,
|
||||
);
|
||||
if (analysisResult.hasNestedFolders) {
|
||||
setSavedFolderPath(path);
|
||||
setChoiceModalOpen(true);
|
||||
} else {
|
||||
addWatchWithStrategy(UPLOAD_STRATEGY.SINGLE_COLLECTION, path);
|
||||
addWatch(path, "root");
|
||||
}
|
||||
};
|
||||
|
||||
const addWatchWithStrategy = async (
|
||||
uploadStrategy: UPLOAD_STRATEGY,
|
||||
folderPath?: string,
|
||||
) => {
|
||||
folderPath = folderPath || inputFolderPath;
|
||||
await watcher.addWatchMapping(
|
||||
folderPath.substring(folderPath.lastIndexOf("/") + 1),
|
||||
folderPath,
|
||||
uploadStrategy,
|
||||
);
|
||||
setInputFolderPath("");
|
||||
const addWatch = async (folderPath: string, mapping: CollectionMapping) => {
|
||||
await watcher.addWatch(folderPath, mapping);
|
||||
setWatches(await watcher.getWatchMappings());
|
||||
};
|
||||
|
||||
const addWatch = async () => {
|
||||
const addNewWatch = async () => {
|
||||
const folderPath = await watcher.selectFolder();
|
||||
if (folderPath) {
|
||||
await addFolderForWatching(folderPath);
|
||||
await selectCollectionMappingAndAddWatch(folderPath);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -117,14 +115,10 @@ export const WatchFolder: React.FC<WatchFolderProps> = ({ open, onClose }) => {
|
|||
|
||||
const closeChoiceModal = () => setChoiceModalOpen(false);
|
||||
|
||||
const uploadToSingleCollection = () => {
|
||||
const addWatchWithMapping = (mapping: CollectionMapping) => {
|
||||
closeChoiceModal();
|
||||
addWatchWithStrategy(UPLOAD_STRATEGY.SINGLE_COLLECTION);
|
||||
};
|
||||
|
||||
const uploadToMultipleCollection = () => {
|
||||
closeChoiceModal();
|
||||
addWatchWithStrategy(UPLOAD_STRATEGY.COLLECTION_PER_FOLDER);
|
||||
setSavedFolderPath(undefined);
|
||||
addWatch(ensure(savedFolderPath), mapping);
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -143,7 +137,7 @@ export const WatchFolder: React.FC<WatchFolderProps> = ({ open, onClose }) => {
|
|||
<DialogContent sx={{ flex: 1 }}>
|
||||
<Stack spacing={1} p={1.5} height={"100%"}>
|
||||
<WatchList {...{ watches, removeWatch }} />
|
||||
<Button fullWidth color="accent" onClick={addWatch}>
|
||||
<Button fullWidth color="accent" onClick={addNewWatch}>
|
||||
<span>+</span>
|
||||
<span
|
||||
style={{
|
||||
|
@ -158,8 +152,8 @@ export const WatchFolder: React.FC<WatchFolderProps> = ({ open, onClose }) => {
|
|||
<UploadStrategyChoiceModal
|
||||
open={choiceModalOpen}
|
||||
onClose={closeChoiceModal}
|
||||
uploadToSingleCollection={uploadToSingleCollection}
|
||||
uploadToMultipleCollection={uploadToMultipleCollection}
|
||||
uploadToSingleCollection={() => addWatchWithMapping("root")}
|
||||
uploadToMultipleCollection={() => addWatchWithMapping("parent")}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
@ -269,7 +263,7 @@ const WatchEntry: React.FC<WatchEntryProps> = ({ watch, removeWatch }) => {
|
|||
return (
|
||||
<SpaceBetweenFlex>
|
||||
<HorizontalFlex>
|
||||
{watch.uploadStrategy === UPLOAD_STRATEGY.SINGLE_COLLECTION ? (
|
||||
{watch.uploadStrategy === "root" ? (
|
||||
<Tooltip title={t("UPLOADED_TO_SINGLE_COLLECTION")}>
|
||||
<FolderOpenIcon />
|
||||
</Tooltip>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { ensureElectron } from "@/next/electron";
|
||||
import { nameAndExtension } from "@/next/file";
|
||||
import log from "@/next/log";
|
||||
import type { FolderWatch } from "@/next/types/ipc";
|
||||
import type { CollectionMapping, FolderWatch } from "@/next/types/ipc";
|
||||
import { UPLOAD_RESULT, UPLOAD_STRATEGY } from "constants/upload";
|
||||
import debounce from "debounce";
|
||||
import uploadManager from "services/upload/uploadManager";
|
||||
|
@ -140,21 +140,22 @@ class WatchFolderService {
|
|||
);
|
||||
}
|
||||
|
||||
async addWatchMapping(
|
||||
rootFolderName: string,
|
||||
folderPath: string,
|
||||
uploadStrategy: UPLOAD_STRATEGY,
|
||||
) {
|
||||
try {
|
||||
await ensureElectron().addWatchMapping(
|
||||
rootFolderName,
|
||||
folderPath,
|
||||
uploadStrategy,
|
||||
);
|
||||
this.syncWithDisk();
|
||||
} catch (e) {
|
||||
log.error("error while adding watch mapping", e);
|
||||
}
|
||||
/**
|
||||
* Add a new folder watch for the given root {@link folderPath}
|
||||
*
|
||||
* @param mapping The {@link CollectionMapping} to use to decide which
|
||||
* collection do files belonging to nested directories go to.
|
||||
*/
|
||||
async addWatch(folderPath: string, mapping: CollectionMapping) {
|
||||
const rootFolderName = folderPath.substring(
|
||||
folderPath.lastIndexOf("/") + 1,
|
||||
);
|
||||
await ensureElectron().addWatchMapping(
|
||||
rootFolderName,
|
||||
folderPath,
|
||||
mapping,
|
||||
);
|
||||
this.syncWithDisk();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -377,8 +377,8 @@ export interface Electron {
|
|||
* A top level folder that was selected by the user for watching.
|
||||
*
|
||||
* The user can set up multiple such watches. Each of these can in turn be
|
||||
* syncing multiple on disk folders to one or more (dependening on the
|
||||
* {@link uploadStrategy}) Ente albums.
|
||||
* syncing multiple on disk folders to one or more Ente collections (depending
|
||||
* on the value of {@link collectionMapping}).
|
||||
*
|
||||
* This type is passed across the IPC boundary. It is persisted on the Node.js
|
||||
* side.
|
||||
|
@ -391,6 +391,12 @@ export interface FolderWatch {
|
|||
ignoredFiles: string[];
|
||||
}
|
||||
|
||||
export type CollectionMapping =
|
||||
/** Map everything to a single collection corresponding to the root directory */
|
||||
| "root"
|
||||
/** Map each file to a collection named after its parent directory */
|
||||
| "parent";
|
||||
|
||||
/**
|
||||
* An on-disk file that was synced as part of a folder watch.
|
||||
*/
|
||||
|
|
7
web/packages/utils/ensure.ts
Normal file
7
web/packages/utils/ensure.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Throw an exception if the given value is undefined.
|
||||
*/
|
||||
export const ensure = <T>(v: T | undefined): T => {
|
||||
if (v === undefined) throw new Error("Required value was not found");
|
||||
return v;
|
||||
};
|
Loading…
Add table
Reference in a new issue