refactor upload flow
This commit is contained in:
parent
2fec2ce6a3
commit
4a08ba8c61
|
@ -59,6 +59,7 @@
|
|||
"typescript": "^4.2.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron/remote": "^2.0.8",
|
||||
"@sentry/electron": "^2.5.1",
|
||||
"@types/mime": "^2.0.3",
|
||||
"@types/node": "^14.14.37",
|
||||
|
|
|
@ -9,6 +9,7 @@ import initSentry from './utils/sentry';
|
|||
import electronReload from 'electron-reload';
|
||||
import Store from 'electron-store';
|
||||
import { PROD_HOST_URL, RENDERER_OUTPUT_DIR } from '../config';
|
||||
require('@electron/remote/main').initialize();
|
||||
|
||||
if (isDev) {
|
||||
electronReload(__dirname, {});
|
||||
|
|
|
@ -3,6 +3,9 @@ import * as fs from 'promise-fs';
|
|||
import * as electron from 'electron';
|
||||
import {
|
||||
getIfToUploadFilesExists,
|
||||
getElectronFile,
|
||||
showUploadFilesDialog,
|
||||
showUploadDirsDialog,
|
||||
getToUploadFiles,
|
||||
setToUploadFiles,
|
||||
} from './utils/upload';
|
||||
|
@ -122,7 +125,10 @@ windowObject['ElectronAPIs'] = {
|
|||
registerRetryFailedExportListener,
|
||||
getExportRecord,
|
||||
setExportRecord,
|
||||
setToUploadFiles,
|
||||
getToUploadFiles,
|
||||
getIfToUploadFilesExists,
|
||||
getElectronFile,
|
||||
showUploadFilesDialog,
|
||||
showUploadDirsDialog,
|
||||
getToUploadFiles,
|
||||
setToUploadFiles,
|
||||
};
|
||||
|
|
|
@ -11,67 +11,3 @@ export interface ElectronFile {
|
|||
toBlob: () => Promise<Blob>;
|
||||
toUInt8Array: () => Promise<Uint8Array>;
|
||||
}
|
||||
|
||||
export interface FileWithCollection {
|
||||
localID: number;
|
||||
collection: Collection;
|
||||
collectionID: number;
|
||||
file: ElectronFile;
|
||||
}
|
||||
|
||||
export interface StoreFileWithCollection {
|
||||
localID: number;
|
||||
collection: Collection;
|
||||
collectionID: number;
|
||||
filePath: string;
|
||||
}
|
||||
|
||||
export interface Collection {
|
||||
id: number;
|
||||
owner: User;
|
||||
key?: string;
|
||||
name?: string;
|
||||
encryptedName?: string;
|
||||
nameDecryptionNonce?: string;
|
||||
type: CollectionType;
|
||||
attributes: collectionAttributes;
|
||||
sharees: User[];
|
||||
updationTime: number;
|
||||
encryptedKey: string;
|
||||
keyDecryptionNonce: string;
|
||||
isDeleted: boolean;
|
||||
isSharedCollection?: boolean;
|
||||
publicURLs?: PublicURL[];
|
||||
}
|
||||
|
||||
interface User {
|
||||
id: number;
|
||||
name: string;
|
||||
email: string;
|
||||
token: string;
|
||||
encryptedToken: string;
|
||||
isTwoFactorEnabled: boolean;
|
||||
twoFactorSessionID: string;
|
||||
}
|
||||
|
||||
interface PublicURL {
|
||||
url: string;
|
||||
deviceLimit: number;
|
||||
validTill: number;
|
||||
enableDownload: boolean;
|
||||
passwordEnabled: boolean;
|
||||
nonce: string;
|
||||
opsLimit: number;
|
||||
memLimit: number;
|
||||
}
|
||||
|
||||
enum CollectionType {
|
||||
folder = 'folder',
|
||||
favorites = 'favorites',
|
||||
album = 'album',
|
||||
}
|
||||
|
||||
interface collectionAttributes {
|
||||
encryptedPath?: string;
|
||||
pathDecryptionNonce?: string;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ export function createWindow(): BrowserWindow {
|
|||
|
||||
addAllowOriginHeader(mainWindow);
|
||||
|
||||
require('@electron/remote/main').enable(mainWindow.webContents);
|
||||
|
||||
if (isDev) {
|
||||
splash.loadFile(`../build/splash.html`);
|
||||
mainWindow.loadURL(PROD_HOST_URL);
|
||||
|
|
|
@ -2,41 +2,32 @@ import ElectronStore from 'electron-store';
|
|||
import path from 'path';
|
||||
import * as fs from 'promise-fs';
|
||||
import mime from 'mime';
|
||||
import {
|
||||
Collection,
|
||||
FileWithCollection,
|
||||
StoreFileWithCollection,
|
||||
} from '../types';
|
||||
import { ENCRYPTION_CHUNK_SIZE } from '../../config';
|
||||
import { dialog } from '@electron/remote';
|
||||
import { ElectronFile } from '../types';
|
||||
|
||||
const store = new ElectronStore();
|
||||
|
||||
export const setToUploadFiles = (
|
||||
files: FileWithCollection[],
|
||||
collections: Collection[],
|
||||
done: boolean
|
||||
) => {
|
||||
store.set('done', done);
|
||||
if (done) {
|
||||
store.delete('files');
|
||||
store.delete('collections');
|
||||
} else {
|
||||
const filesList: StoreFileWithCollection[] = files.map(
|
||||
(file: FileWithCollection) => {
|
||||
return {
|
||||
localID: file.localID,
|
||||
collection: file.collection,
|
||||
collectionID: file.collectionID,
|
||||
filePath: file.file.path,
|
||||
};
|
||||
}
|
||||
);
|
||||
store.set('files', filesList);
|
||||
if (collections) store.set('collections', collections);
|
||||
}
|
||||
const getFilesFromDir = (dirPath: string) => {
|
||||
let files: string[] = [];
|
||||
|
||||
// https://stackoverflow.com/a/63111390
|
||||
const getAllFilePaths = (dirPath: string) => {
|
||||
fs.readdirSync(dirPath).forEach((filePath) => {
|
||||
const absolute = path.join(dirPath, filePath);
|
||||
if (fs.statSync(absolute).isDirectory())
|
||||
return getAllFilePaths(absolute);
|
||||
else return files.push(absolute);
|
||||
});
|
||||
};
|
||||
|
||||
if (fs.statSync(dirPath).isDirectory()) getAllFilePaths(dirPath);
|
||||
else files.push(dirPath);
|
||||
|
||||
return files;
|
||||
};
|
||||
|
||||
export const getFileStream = async (filePath: string) => {
|
||||
const getFileStream = async (filePath: string) => {
|
||||
const file = await fs.open(filePath, 'r');
|
||||
let offset = 0;
|
||||
const readableStream = new ReadableStream<Uint8Array>({
|
||||
|
@ -63,56 +54,81 @@ export const getFileStream = async (filePath: string) => {
|
|||
return readableStream;
|
||||
};
|
||||
|
||||
export const getToUploadFiles = async () => {
|
||||
const files = store.get('files') as StoreFileWithCollection[];
|
||||
if (!files)
|
||||
return {
|
||||
files: [] as FileWithCollection[],
|
||||
collections: [] as Collection[],
|
||||
};
|
||||
export async function showUploadFilesDialog() {
|
||||
const files = await dialog.showOpenDialog({
|
||||
properties: ['openFile', 'multiSelections'],
|
||||
});
|
||||
return files.filePaths;
|
||||
}
|
||||
|
||||
const filesWithStream: FileWithCollection[] = [];
|
||||
export async function showUploadDirsDialog() {
|
||||
const dir = await dialog.showOpenDialog({
|
||||
properties: ['openDirectory', 'multiSelections'],
|
||||
});
|
||||
|
||||
for (const file of files) {
|
||||
const filePath = file.filePath;
|
||||
let files: string[] = [];
|
||||
for (const dirPath of dir.filePaths) {
|
||||
files = files.concat(getFilesFromDir(dirPath));
|
||||
}
|
||||
|
||||
if (fs.existsSync(filePath)) {
|
||||
const fileStats = fs.statSync(filePath);
|
||||
return files;
|
||||
}
|
||||
|
||||
const fileObj: FileWithCollection = {
|
||||
localID: file.localID,
|
||||
collection: file.collection,
|
||||
collectionID: file.collectionID,
|
||||
export async function getElectronFile(filePath: string): Promise<ElectronFile> {
|
||||
const fileStats = fs.statSync(filePath);
|
||||
return {
|
||||
path: filePath,
|
||||
name: path.basename(filePath),
|
||||
size: fileStats.size,
|
||||
lastModified: fileStats.mtime.valueOf(),
|
||||
type: {
|
||||
mimeType: mime.getType(filePath),
|
||||
ext: path.extname(filePath).substring(1),
|
||||
},
|
||||
createReadStream: async () => {
|
||||
return await getFileStream(filePath);
|
||||
},
|
||||
toBlob: async () => {
|
||||
const blob = await fs.readFile(filePath);
|
||||
return new Blob([new Uint8Array(blob)]);
|
||||
},
|
||||
toUInt8Array: async () => {
|
||||
const blob = await fs.readFile(filePath);
|
||||
return new Uint8Array(blob);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
file: {
|
||||
path: filePath,
|
||||
name: path.basename(filePath),
|
||||
size: fileStats.size,
|
||||
lastModified: fileStats.mtime.valueOf(),
|
||||
type: {
|
||||
mimeType: mime.getType(filePath),
|
||||
ext: path.extname(filePath).substring(1),
|
||||
},
|
||||
createReadStream: async () => {
|
||||
return await getFileStream(filePath);
|
||||
},
|
||||
toBlob: async () => {
|
||||
const blob = await fs.readFile(filePath);
|
||||
return new Blob([new Uint8Array(blob)]);
|
||||
},
|
||||
toUInt8Array: async () => {
|
||||
const blob = await fs.readFile(filePath);
|
||||
return new Uint8Array(blob);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
filesWithStream.push(fileObj);
|
||||
export const setToUploadFiles = (
|
||||
filePaths: string[],
|
||||
collectionName: string,
|
||||
collectionIDs: number[],
|
||||
done: boolean
|
||||
) => {
|
||||
store.set('done', done);
|
||||
if (done) {
|
||||
store.delete('filesPaths');
|
||||
store.delete('collectionName');
|
||||
store.delete('collectionIDs');
|
||||
} else {
|
||||
store.set('filesPaths', filePaths);
|
||||
store.set('collectionIDs', collectionIDs);
|
||||
if (collectionName) {
|
||||
store.set('collectionName', collectionName);
|
||||
} else {
|
||||
store.delete('collectionName');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const getToUploadFiles = () => {
|
||||
const filesPaths = store.get('filesPaths') as string[];
|
||||
const collectionName = store.get('collectionName') as string;
|
||||
const collectionIDs = store.get('collectionIDs') as number[];
|
||||
return {
|
||||
files: filesWithStream,
|
||||
collections: store.get('collections') as Collection[],
|
||||
filesPaths,
|
||||
collectionName,
|
||||
collectionIDs,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -52,6 +52,11 @@
|
|||
global-agent "^3.0.0"
|
||||
global-tunnel-ng "^2.7.1"
|
||||
|
||||
"@electron/remote@^2.0.8":
|
||||
version "2.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@electron/remote/-/remote-2.0.8.tgz#85ff321f0490222993207106e2f720273bb1a5c3"
|
||||
integrity sha512-P10v3+iFCIvEPeYzTWWGwwHmqWnjoh8RYnbtZAb3RlQefy4guagzIwcWtfftABIfm6JJTNQf4WPSKWZOpLmHXw==
|
||||
|
||||
"@electron/universal@1.0.5":
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmjs.org/@electron/universal/-/universal-1.0.5.tgz"
|
||||
|
|
Loading…
Reference in a new issue