refactor upload flow

This commit is contained in:
Rushikesh Tote 2022-03-20 15:53:53 +05:30
parent 2fec2ce6a3
commit 4a08ba8c61
7 changed files with 104 additions and 137 deletions

View file

@ -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",

View file

@ -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, {});

View file

@ -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,
};

View file

@ -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;
}

View file

@ -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);

View file

@ -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,
};
};

View file

@ -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"