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( callback: (args: any) => any, payload: R ): [ (args: T) => (args: T & { onProgress: (current: number, total: number) => void }) => any, EventChannel ] { 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(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> => { 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 => { 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); }); };