mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 04:46:40 +07:00
110 lines
3 KiB
TypeScript
110 lines
3 KiB
TypeScript
import uuid from 'uuid4';
|
|
import { END, eventChannel, EventChannel } from 'redux-saga';
|
|
import { VALIDATORS } from '~/utils/validators';
|
|
import { IFile, IResultWithStatus } from '~/redux/types';
|
|
import { HTTP_RESPONSES } from './api';
|
|
import { EMPTY_FILE, FILE_MIMES, UPLOAD_TYPES } from '~/redux/uploads/constants';
|
|
|
|
export const IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/jpg'];
|
|
|
|
export function createUploader<T extends {}, R extends {}>(
|
|
callback: (args: any) => any,
|
|
payload: R
|
|
): [
|
|
(args: T) => (args: T & { onProgress: (current: number, total: number) => void }) => any,
|
|
EventChannel<any>
|
|
] {
|
|
let emit;
|
|
|
|
const chan = eventChannel(emitter => {
|
|
emit = emitter;
|
|
return () => null;
|
|
});
|
|
|
|
const onProgress = ({ loaded, total }: { loaded: number; total: number }): void => {
|
|
emit(loaded >= total ? END : { ...payload, progress: parseFloat((loaded / total).toFixed(1)) });
|
|
};
|
|
|
|
const wrappedCallback = args => callback({ ...args, onProgress });
|
|
|
|
return [wrappedCallback, chan];
|
|
}
|
|
|
|
export const uploadGetThumb = async file => {
|
|
if (!file.type || !VALIDATORS.IS_IMAGE_MIME(file.type)) return '';
|
|
|
|
return new Promise<string | ArrayBuffer>(resolve => {
|
|
const reader = new FileReader();
|
|
reader.onloadend = () => resolve(reader.result || '');
|
|
reader.readAsDataURL(file);
|
|
});
|
|
};
|
|
|
|
export const fakeUploader = ({
|
|
file,
|
|
onProgress,
|
|
mustSucceed,
|
|
}: {
|
|
file: { url?: string; error?: string };
|
|
onProgress: (current: number, total: number) => void;
|
|
mustSucceed: boolean;
|
|
}): Promise<IResultWithStatus<IFile>> => {
|
|
const { error } = file;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
setTimeout(() => {
|
|
onProgress(1, 3);
|
|
}, 1000);
|
|
|
|
setTimeout(() => {
|
|
onProgress(2, 3);
|
|
}, 2000);
|
|
|
|
setTimeout(() => {
|
|
onProgress(3, 3);
|
|
if (mustSucceed) {
|
|
resolve({ status: HTTP_RESPONSES.CREATED, data: { ...EMPTY_FILE, id: uuid() } });
|
|
} else {
|
|
reject({ response: { statusText: error } });
|
|
}
|
|
}, 3000);
|
|
});
|
|
};
|
|
|
|
export const getFileType = (file: File): keyof typeof UPLOAD_TYPES | undefined =>
|
|
(file.type && Object.keys(FILE_MIMES).find(mime => FILE_MIMES[mime].includes(file.type))) ||
|
|
undefined;
|
|
|
|
// getImageFromPaste returns any images from paste event
|
|
export const getImageFromPaste = (event: ClipboardEvent): Promise<File | undefined> => {
|
|
const items = event.clipboardData?.items;
|
|
|
|
return new Promise(resolve => {
|
|
for (let index in items) {
|
|
const item = items[index];
|
|
|
|
if (item.kind === 'file' && item.type.match(/^image\//)) {
|
|
const blob = item.getAsFile();
|
|
const reader = new FileReader();
|
|
const type = item.type;
|
|
|
|
reader.onload = function(e) {
|
|
if (!e.target?.result) {
|
|
return;
|
|
}
|
|
|
|
resolve(
|
|
new File([e.target?.result], 'paste.png', {
|
|
type,
|
|
lastModified: new Date().getTime(),
|
|
})
|
|
);
|
|
};
|
|
|
|
reader.readAsArrayBuffer(blob);
|
|
}
|
|
}
|
|
|
|
// resolve(undefined);
|
|
});
|
|
};
|