Upload fix
Fixed upload preloader
This commit is contained in:
parent
2b498a5b2c
commit
8a5a91b3c4
@ -303,7 +303,7 @@ export default class AudioElement extends HTMLElement {
|
|||||||
downloadDiv.innerHTML = '<div class="tgico-download"></div>';
|
downloadDiv.innerHTML = '<div class="tgico-download"></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(doc.type != 'audio' && !uploading) {
|
if(doc.type != 'audio' || uploading) {
|
||||||
this.append(downloadDiv);
|
this.append(downloadDiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,8 +53,7 @@ export default class ProgressivePreloader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public attach(elem: Element, reset = true, promise?: CancellablePromise<any>, append = true) {
|
public attachPromise(promise: CancellablePromise<any>) {
|
||||||
if(promise/* && false */) {
|
|
||||||
this.promise = promise;
|
this.promise = promise;
|
||||||
|
|
||||||
const tempID = --this.tempID;
|
const tempID = --this.tempID;
|
||||||
@ -86,6 +85,11 @@ export default class ProgressivePreloader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public attach(elem: Element, reset = true, promise?: CancellablePromise<any>, append = true) {
|
||||||
|
if(promise/* && false */) {
|
||||||
|
this.attachPromise(promise);
|
||||||
|
}
|
||||||
|
|
||||||
this.detached = false;
|
this.detached = false;
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
if(this.detached) return;
|
if(this.detached) return;
|
||||||
|
@ -59,7 +59,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
|||||||
|
|
||||||
let img: HTMLImageElement;
|
let img: HTMLImageElement;
|
||||||
if(message) {
|
if(message) {
|
||||||
if(doc.type == 'video') {
|
if(doc.type == 'video' && doc.thumbs?.length) {
|
||||||
return wrapPhoto(doc, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware);
|
return wrapPhoto(doc, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,7 +390,7 @@ export function wrapPhoto(photo: MTPhoto | MTDocument, message: any, container:
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return cacheContext.downloaded ? load() : lazyLoadQueue.push({div: container, load: load, wasSeen: true});
|
return cacheContext.downloaded || !lazyLoadQueue ? load() : lazyLoadQueue.push({div: container, load: load, wasSeen: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, onlyThumb, emoji, width, height, withThumb, loop}: {
|
export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, onlyThumb, emoji, width, height, withThumb, loop}: {
|
||||||
|
@ -124,8 +124,11 @@ class AppDocsManager {
|
|||||||
|
|
||||||
if((doc.type == 'gif' && doc.size > 8e6) || doc.type == 'audio' || doc.type == 'video') {
|
if((doc.type == 'gif' && doc.size > 8e6) || doc.type == 'audio' || doc.type == 'video') {
|
||||||
doc.supportsStreaming = true;
|
doc.supportsStreaming = true;
|
||||||
|
|
||||||
|
if(!doc.url) {
|
||||||
doc.url = this.getFileURL(doc);
|
doc.url = this.getFileURL(doc);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!doc.file_name) {
|
if(!doc.file_name) {
|
||||||
doc.file_name = '';
|
doc.file_name = '';
|
||||||
|
@ -3,6 +3,7 @@ import apiManager from "../mtproto/mtprotoworker";
|
|||||||
import { deferredPromise, CancellablePromise } from "../polyfill";
|
import { deferredPromise, CancellablePromise } from "../polyfill";
|
||||||
import type { DownloadOptions } from "../mtproto/apiFileManager";
|
import type { DownloadOptions } from "../mtproto/apiFileManager";
|
||||||
import { getFileNameByLocation } from "../bin_utils";
|
import { getFileNameByLocation } from "../bin_utils";
|
||||||
|
import { InputFile } from "../../types";
|
||||||
|
|
||||||
export type ResponseMethodBlob = 'blob';
|
export type ResponseMethodBlob = 'blob';
|
||||||
export type ResponseMethodJson = 'json';
|
export type ResponseMethodJson = 'json';
|
||||||
@ -23,6 +24,8 @@ export class AppDownloadManager {
|
|||||||
private progress: {[fileName: string]: Progress} = {};
|
private progress: {[fileName: string]: Progress} = {};
|
||||||
private progressCallbacks: {[fileName: string]: Array<ProgressCallback>} = {};
|
private progressCallbacks: {[fileName: string]: Array<ProgressCallback>} = {};
|
||||||
|
|
||||||
|
private uploadID = 0;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
$rootScope.$on('download_progress', (e) => {
|
$rootScope.$on('download_progress', (e) => {
|
||||||
const details = e.detail as {done: number, fileName: string, total: number, offset: number};
|
const details = e.detail as {done: number, fileName: string, total: number, offset: number};
|
||||||
@ -40,39 +43,56 @@ export class AppDownloadManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public download(options: DownloadOptions, responseMethod?: ResponseMethodBlob): DownloadBlob;
|
private getNewDeferred(fileName: string) {
|
||||||
public download(options: DownloadOptions, responseMethod?: ResponseMethodJson): DownloadJson;
|
|
||||||
public download(options: DownloadOptions, responseMethod: ResponseMethod = 'blob'): DownloadBlob {
|
|
||||||
const fileName = getFileNameByLocation(options.location, {fileName: options.fileName});
|
|
||||||
|
|
||||||
if(this.downloads.hasOwnProperty(fileName)) return this.downloads[fileName];
|
|
||||||
|
|
||||||
const deferred = deferredPromise<Blob>();
|
const deferred = deferredPromise<Blob>();
|
||||||
|
|
||||||
apiManager.downloadFile(options)
|
|
||||||
.then(deferred.resolve, deferred.reject)
|
|
||||||
.finally(() => {
|
|
||||||
delete this.progressCallbacks[fileName];
|
|
||||||
});
|
|
||||||
|
|
||||||
//console.log('Will download file:', fileName, url);
|
|
||||||
|
|
||||||
deferred.cancel = () => {
|
deferred.cancel = () => {
|
||||||
const error = new Error('Download canceled');
|
const error = new Error('Download canceled');
|
||||||
error.name = 'AbortError';
|
error.name = 'AbortError';
|
||||||
|
|
||||||
apiManager.cancelDownload(fileName);
|
apiManager.cancelDownload(fileName);
|
||||||
delete this.downloads[fileName];
|
this.clearDownload(fileName);
|
||||||
delete this.progress[fileName];
|
|
||||||
delete this.progressCallbacks[fileName];
|
|
||||||
|
|
||||||
deferred.reject(error);
|
deferred.reject(error);
|
||||||
deferred.cancel = () => {};
|
deferred.cancel = () => {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
deferred.finally(() => {
|
||||||
|
delete this.progress[fileName];
|
||||||
|
delete this.progressCallbacks[fileName];
|
||||||
|
});
|
||||||
|
|
||||||
return this.downloads[fileName] = deferred;
|
return this.downloads[fileName] = deferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private clearDownload(fileName: string) {
|
||||||
|
delete this.downloads[fileName];
|
||||||
|
}
|
||||||
|
|
||||||
|
public download(options: DownloadOptions): DownloadBlob {
|
||||||
|
const fileName = getFileNameByLocation(options.location, {fileName: options.fileName});
|
||||||
|
if(this.downloads.hasOwnProperty(fileName)) return this.downloads[fileName];
|
||||||
|
|
||||||
|
const deferred = this.getNewDeferred(fileName);
|
||||||
|
apiManager.downloadFile(options).then(deferred.resolve, deferred.reject);
|
||||||
|
|
||||||
|
//console.log('Will download file:', fileName, url);
|
||||||
|
return deferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
public upload(file: File | Blob) {
|
||||||
|
const fileName = /* (file as File).name || */'upload-' + this.uploadID++;
|
||||||
|
|
||||||
|
const deferred = this.getNewDeferred(fileName);
|
||||||
|
apiManager.uploadFile({file, fileName}).then(deferred.resolve, deferred.reject);
|
||||||
|
|
||||||
|
deferred.finally(() => {
|
||||||
|
this.clearDownload(fileName);
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred as any as CancellablePromise<InputFile>;
|
||||||
|
}
|
||||||
|
|
||||||
public getDownload(fileName: string) {
|
public getDownload(fileName: string) {
|
||||||
return this.downloads[fileName];
|
return this.downloads[fileName];
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ import appAudio from '../../components/appAudio';
|
|||||||
import appPollsManager from './appPollsManager';
|
import appPollsManager from './appPollsManager';
|
||||||
import { ripple } from '../../components/ripple';
|
import { ripple } from '../../components/ripple';
|
||||||
import { horizontalMenu } from '../../components/horizontalMenu';
|
import { horizontalMenu } from '../../components/horizontalMenu';
|
||||||
|
import AudioElement from '../../components/audio';
|
||||||
|
|
||||||
//console.log('appImManager included33!');
|
//console.log('appImManager included33!');
|
||||||
|
|
||||||
@ -2251,15 +2252,14 @@ export class AppImManager {
|
|||||||
case 'audio':
|
case 'audio':
|
||||||
case 'voice':
|
case 'voice':
|
||||||
case 'document': {
|
case 'document': {
|
||||||
let doc = appDocsManager.getDoc(message.id);
|
const doc = appDocsManager.getDoc(message.id);
|
||||||
this.log('will wrap pending doc:', doc);
|
this.log('will wrap pending doc:', doc);
|
||||||
let docDiv = wrapDocument(doc, false, true, message.id);
|
const docDiv = wrapDocument(doc, false, true, message.id);
|
||||||
|
|
||||||
if(doc.type == 'audio' || doc.type == 'voice') {
|
if(doc.type == 'audio' || doc.type == 'voice') {
|
||||||
// @ts-ignore
|
(docDiv as AudioElement).preloader = preloader;
|
||||||
docDiv.preloader = preloader;
|
|
||||||
} else {
|
} else {
|
||||||
let icoDiv = docDiv.querySelector('.audio-download, .document-ico');
|
const icoDiv = docDiv.querySelector('.audio-download, .document-ico');
|
||||||
preloader.attach(icoDiv, false);
|
preloader.attach(icoDiv, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import searchIndexManager from '../searchIndexManager';
|
|||||||
import { MTDocument, MTPhotoSize } from "../../types";
|
import { MTDocument, MTPhotoSize } from "../../types";
|
||||||
import { logger, LogLevels } from "../logger";
|
import { logger, LogLevels } from "../logger";
|
||||||
import type {ApiFileManager} from '../mtproto/apiFileManager';
|
import type {ApiFileManager} from '../mtproto/apiFileManager';
|
||||||
|
import appDownloadManager from "./appDownloadManager";
|
||||||
|
|
||||||
//console.trace('include');
|
//console.trace('include');
|
||||||
|
|
||||||
@ -1121,9 +1122,9 @@ export class AppMessagesManager {
|
|||||||
flags |= 256;
|
flags |= 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
let preloader = new ProgressivePreloader(null, true);
|
const preloader = new ProgressivePreloader(null, true);
|
||||||
|
|
||||||
var media = {
|
const media = {
|
||||||
_: 'messageMediaPending',
|
_: 'messageMediaPending',
|
||||||
type: attachType,
|
type: attachType,
|
||||||
file_name: fileName || apiFileName,
|
file_name: fileName || apiFileName,
|
||||||
@ -1132,22 +1133,10 @@ export class AppMessagesManager {
|
|||||||
preloader: preloader,
|
preloader: preloader,
|
||||||
w: options.width,
|
w: options.width,
|
||||||
h: options.height,
|
h: options.height,
|
||||||
url: options.objectURL,
|
url: options.objectURL
|
||||||
progress: {
|
|
||||||
percent: 1,
|
|
||||||
total: file.size,
|
|
||||||
done: 0,
|
|
||||||
cancel: () => {}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
preloader.preloader.onclick = () => {
|
const message: any = {
|
||||||
this.log('cancelling upload', media);
|
|
||||||
this.setTyping('sendMessageCancelAction');
|
|
||||||
media.progress.cancel();
|
|
||||||
};
|
|
||||||
|
|
||||||
var message: any = {
|
|
||||||
_: 'message',
|
_: 'message',
|
||||||
id: messageID,
|
id: messageID,
|
||||||
from_id: fromID,
|
from_id: fromID,
|
||||||
@ -1168,7 +1157,7 @@ export class AppMessagesManager {
|
|||||||
pending: true
|
pending: true
|
||||||
};
|
};
|
||||||
|
|
||||||
var toggleError = (on: boolean) => {
|
const toggleError = (on: boolean) => {
|
||||||
if(on) {
|
if(on) {
|
||||||
message.error = true;
|
message.error = true;
|
||||||
} else {
|
} else {
|
||||||
@ -1178,10 +1167,10 @@ export class AppMessagesManager {
|
|||||||
$rootScope.$broadcast('messages_pending');
|
$rootScope.$broadcast('messages_pending');
|
||||||
};
|
};
|
||||||
|
|
||||||
var uploaded = false,
|
let uploaded = false,
|
||||||
uploadPromise: ReturnType<ApiFileManager['uploadFile']> = null;
|
uploadPromise: ReturnType<ApiFileManager['uploadFile']> = null;
|
||||||
|
|
||||||
let invoke = (flags: number, inputMedia: any) => {
|
const invoke = (flags: number, inputMedia: any) => {
|
||||||
this.setTyping('sendMessageCancelAction');
|
this.setTyping('sendMessageCancelAction');
|
||||||
|
|
||||||
return apiManager.invokeApi('messages.sendMedia', {
|
return apiManager.invokeApi('messages.sendMedia', {
|
||||||
@ -1221,9 +1210,9 @@ export class AppMessagesManager {
|
|||||||
flags |= 128; // clear_draft
|
flags |= 128; // clear_draft
|
||||||
|
|
||||||
if(isDocument) {
|
if(isDocument) {
|
||||||
let {id, access_hash, file_reference} = file as MTDocument;
|
const {id, access_hash, file_reference} = file as MTDocument;
|
||||||
|
|
||||||
let inputMedia = {
|
const inputMedia = {
|
||||||
_: 'inputMediaDocument',
|
_: 'inputMediaDocument',
|
||||||
flags: 0,
|
flags: 0,
|
||||||
id: {
|
id: {
|
||||||
@ -1236,16 +1225,13 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
invoke(flags, inputMedia);
|
invoke(flags, inputMedia);
|
||||||
} else if(file instanceof File || file instanceof Blob) {
|
} else if(file instanceof File || file instanceof Blob) {
|
||||||
let deferred = deferredPromise<void>();
|
const deferred = deferredPromise<void>();
|
||||||
|
|
||||||
this.sendFilePromise.then(() => {
|
this.sendFilePromise.then(() => {
|
||||||
if(!uploaded || message.error) {
|
if(!uploaded || message.error) {
|
||||||
uploaded = false;
|
uploaded = false;
|
||||||
//uploadPromise = apiFileManager.uploadFile(file);
|
uploadPromise = appDownloadManager.upload(file);
|
||||||
uploadPromise = fetch('/upload', {
|
preloader.attachPromise(uploadPromise);
|
||||||
method: 'POST',
|
|
||||||
body: file
|
|
||||||
}).then(res => res.json());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadPromise && uploadPromise.then((inputFile) => {
|
uploadPromise && uploadPromise.then((inputFile) => {
|
||||||
@ -1277,28 +1263,23 @@ export class AppMessagesManager {
|
|||||||
toggleError(true);
|
toggleError(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
uploadPromise.notify = (progress: {done: number, total: number}) => {
|
uploadPromise.addNotifyListener((progress: {done: number, total: number}) => {
|
||||||
this.log('upload progress', progress);
|
this.log('upload progress', progress);
|
||||||
media.progress.done = progress.done;
|
const percents = Math.max(1, Math.floor(100 * progress.done / progress.total));
|
||||||
media.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
|
this.setTyping({_: actionName, progress: percents | 0});
|
||||||
this.setTyping({_: actionName, progress: media.progress.percent | 0});
|
|
||||||
preloader.setProgress(media.progress.percent); // lol, nice
|
|
||||||
$rootScope.$broadcast('history_update', {peerID: peerID});
|
|
||||||
};
|
|
||||||
|
|
||||||
media.progress.cancel = () => {
|
|
||||||
if(!uploaded) {
|
|
||||||
deferred.resolve();
|
|
||||||
uploadPromise.cancel();
|
|
||||||
this.cancelPendingMessage(randomIDS);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
uploadPromise['finally'](() => {
|
|
||||||
deferred.resolve();
|
|
||||||
preloader.detach();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
uploadPromise.catch(err => {
|
||||||
|
if(err.name === 'AbortError' && !uploaded) {
|
||||||
|
this.log('cancelling upload', media);
|
||||||
|
|
||||||
|
deferred.resolve();
|
||||||
|
this.cancelPendingMessage(randomIDS);
|
||||||
|
this.setTyping('sendMessageCancelAction');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadPromise.finally(deferred.resolve);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.sendFilePromise = deferred;
|
this.sendFilePromise = deferred;
|
||||||
@ -1382,12 +1363,6 @@ export class AppMessagesManager {
|
|||||||
_: 'messageMediaPending',
|
_: 'messageMediaPending',
|
||||||
type: 'album',
|
type: 'album',
|
||||||
preloader: preloader,
|
preloader: preloader,
|
||||||
progress: {
|
|
||||||
percent: 1,
|
|
||||||
total: file.size,
|
|
||||||
done: 0,
|
|
||||||
cancel: () => {}
|
|
||||||
},
|
|
||||||
document: undefined as any,
|
document: undefined as any,
|
||||||
photo: undefined as any
|
photo: undefined as any
|
||||||
};
|
};
|
||||||
@ -1442,12 +1417,6 @@ export class AppMessagesManager {
|
|||||||
media.photo = photo;
|
media.photo = photo;
|
||||||
}
|
}
|
||||||
|
|
||||||
preloader.preloader.onclick = () => {
|
|
||||||
this.log('cancelling upload', media);
|
|
||||||
this.setTyping('sendMessageCancelAction');
|
|
||||||
media.progress.cancel();
|
|
||||||
};
|
|
||||||
|
|
||||||
let message = {
|
let message = {
|
||||||
_: 'message',
|
_: 'message',
|
||||||
id: messageID,
|
id: messageID,
|
||||||
@ -1509,36 +1478,52 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
let inputs: any[] = [];
|
let inputs: any[] = [];
|
||||||
for(let i = 0, length = files.length; i < length; ++i) {
|
for(let i = 0, length = files.length; i < length; ++i) {
|
||||||
let file = files[i];
|
const file = files[i];
|
||||||
let message = messages[i];
|
const message = messages[i];
|
||||||
let media = message.media;
|
const media = message.media;
|
||||||
let preloader = media.preloader;
|
const preloader = media.preloader;
|
||||||
let actionName = file.type.indexOf('video/') === 0 ? 'sendMessageUploadVideoAction' : 'sendMessageUploadPhotoAction';
|
const actionName = file.type.indexOf('video/') === 0 ? 'sendMessageUploadVideoAction' : 'sendMessageUploadPhotoAction';
|
||||||
let deferred = deferredPromise<void>();
|
const deferred = deferredPromise<void>();
|
||||||
|
let canceled = false;
|
||||||
|
|
||||||
|
let apiFileName: string;
|
||||||
|
if(file.type.indexOf('video/') === 0) {
|
||||||
|
apiFileName = 'video.mp4';
|
||||||
|
} else {
|
||||||
|
apiFileName = 'photo.' + file.type.split('/')[1];
|
||||||
|
}
|
||||||
|
|
||||||
await this.sendFilePromise;
|
await this.sendFilePromise;
|
||||||
this.sendFilePromise = deferred;
|
this.sendFilePromise = deferred;
|
||||||
|
|
||||||
if(!uploaded || message.error) {
|
if(!uploaded || message.error) {
|
||||||
uploaded = false;
|
uploaded = false;
|
||||||
//uploadPromise = apiFileManager.uploadFile(file);
|
uploadPromise = appDownloadManager.upload(file);
|
||||||
uploadPromise = fetch('/upload', {
|
preloader.attachPromise(uploadPromise);
|
||||||
method: 'POST',
|
|
||||||
body: file
|
|
||||||
}).then(res => res.json());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadPromise.notify = (progress: {done: number, total: number}) => {
|
uploadPromise.addNotifyListener((progress: {done: number, total: number}) => {
|
||||||
this.log('upload progress', progress);
|
this.log('upload progress', progress);
|
||||||
media.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
|
const percents = Math.max(1, Math.floor(100 * progress.done / progress.total));
|
||||||
this.setTyping({_: actionName, progress: media.progress.percent | 0});
|
this.setTyping({_: actionName, progress: percents | 0});
|
||||||
preloader.setProgress(media.progress.percent); // lol, nice
|
});
|
||||||
$rootScope.$broadcast('history_update', {peerID: peerID});
|
|
||||||
};
|
uploadPromise.catch(err => {
|
||||||
|
if(err.name === 'AbortError' && !uploaded) {
|
||||||
|
this.log('cancelling upload item', media);
|
||||||
|
canceled = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await uploadPromise.then((inputFile) => {
|
await uploadPromise.then((inputFile) => {
|
||||||
this.log('appMessagesManager: sendAlbum file uploaded:', inputFile);
|
this.log('appMessagesManager: sendAlbum file uploaded:', inputFile);
|
||||||
|
|
||||||
|
if(canceled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputFile.name = apiFileName;
|
||||||
|
|
||||||
let inputMedia: any;
|
let inputMedia: any;
|
||||||
let details = options.sendFileDetails[i];
|
let details = options.sendFileDetails[i];
|
||||||
if(details.duration) {
|
if(details.duration) {
|
||||||
@ -1568,6 +1553,10 @@ export class AppMessagesManager {
|
|||||||
peer: inputPeer,
|
peer: inputPeer,
|
||||||
media: inputMedia
|
media: inputMedia
|
||||||
}).then(messageMedia => {
|
}).then(messageMedia => {
|
||||||
|
if(canceled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let inputMedia: any;
|
let inputMedia: any;
|
||||||
if(messageMedia.photo) {
|
if(messageMedia.photo) {
|
||||||
let photo = messageMedia.photo;
|
let photo = messageMedia.photo;
|
||||||
@ -1598,7 +1587,6 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
this.log('appMessagesManager: sendAlbum uploadPromise.finally!');
|
this.log('appMessagesManager: sendAlbum uploadPromise.finally!');
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
preloader.detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uploaded = true;
|
uploaded = true;
|
||||||
|
@ -5,7 +5,7 @@ import FileManager from "../filemanager";
|
|||||||
import apiManager from "./apiManager";
|
import apiManager from "./apiManager";
|
||||||
import { deferredPromise, CancellablePromise } from "../polyfill";
|
import { deferredPromise, CancellablePromise } from "../polyfill";
|
||||||
import { logger, LogLevels } from "../logger";
|
import { logger, LogLevels } from "../logger";
|
||||||
import { InputFileLocation, FileLocation, UploadFile } from "../../types";
|
import { InputFileLocation, FileLocation, UploadFile, InputFile } from "../../types";
|
||||||
import { isSafari } from "../../helpers/userAgent";
|
import { isSafari } from "../../helpers/userAgent";
|
||||||
import cryptoWorker from "../crypto/cryptoworker";
|
import cryptoWorker from "../crypto/cryptoworker";
|
||||||
import { notifySomeone, notifyAll } from "../../helpers/context";
|
import { notifySomeone, notifyAll } from "../../helpers/context";
|
||||||
@ -33,6 +33,10 @@ export class ApiFileManager {
|
|||||||
[fileName: string]: CancellablePromise<Blob>
|
[fileName: string]: CancellablePromise<Blob>
|
||||||
} = {};
|
} = {};
|
||||||
|
|
||||||
|
public uploadPromises: {
|
||||||
|
[fileName: string]: CancellablePromise<InputFile>
|
||||||
|
} = {};
|
||||||
|
|
||||||
public downloadPulls: {
|
public downloadPulls: {
|
||||||
[x: string]: Array<{
|
[x: string]: Array<{
|
||||||
cb: () => Promise<UploadFile | void>,
|
cb: () => Promise<UploadFile | void>,
|
||||||
@ -108,8 +112,8 @@ export class ApiFileManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public cancelDownload(fileName: string) {
|
public cancelDownload(fileName: string) {
|
||||||
const promise = this.cachedDownloadPromises[fileName];
|
const promise = this.cachedDownloadPromises[fileName] || this.uploadPromises[fileName];
|
||||||
if(promise) {
|
if(promise && !promise.isRejected && !promise.isFulfilled) {
|
||||||
promise.cancel();
|
promise.cancel();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -401,10 +405,11 @@ export class ApiFileManager {
|
|||||||
return this.getFileStorage().deleteFile(fileName);
|
return this.getFileStorage().deleteFile(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uploadFile(file: Blob | File) {
|
public uploadFile({file, fileName}: {file: Blob | File, fileName: string}) {
|
||||||
var fileSize = file.size,
|
const fileSize = file.size,
|
||||||
isBigFile = fileSize >= 10485760,
|
isBigFile = fileSize >= 10485760;
|
||||||
canceled = false,
|
|
||||||
|
let canceled = false,
|
||||||
resolved = false,
|
resolved = false,
|
||||||
doneParts = 0,
|
doneParts = 0,
|
||||||
partSize = 262144, // 256 Kb
|
partSize = 262144, // 256 Kb
|
||||||
@ -418,27 +423,27 @@ export class ApiFileManager {
|
|||||||
activeDelta = 1;
|
activeDelta = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalParts = Math.ceil(fileSize / partSize);
|
const totalParts = Math.ceil(fileSize / partSize);
|
||||||
|
const fileID: [number, number] = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)];
|
||||||
|
|
||||||
var fileID = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)];
|
let _part = 0;
|
||||||
|
|
||||||
var _part = 0,
|
const resultInputFile: InputFile = {
|
||||||
resultInputFile = {
|
|
||||||
_: isBigFile ? 'inputFileBig' : 'inputFile',
|
_: isBigFile ? 'inputFileBig' : 'inputFile',
|
||||||
id: fileID,
|
id: fileID,
|
||||||
parts: totalParts,
|
parts: totalParts,
|
||||||
name: file instanceof File ? file.name : '',
|
name: fileName,
|
||||||
md5_checksum: ''
|
md5_checksum: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
let deferredHelper: {
|
const deferredHelper: {
|
||||||
resolve?: (input: typeof resultInputFile) => void,
|
resolve?: (input: typeof resultInputFile) => void,
|
||||||
reject?: (error: any) => void,
|
reject?: (error: any) => void,
|
||||||
notify?: (details: {done: number, total: number}) => void
|
notify?: (details: {done: number, total: number}) => void
|
||||||
} = {
|
} = {
|
||||||
notify: (details: {done: number, total: number}) => {}
|
notify: (details: {done: number, total: number}) => {}
|
||||||
};
|
};
|
||||||
let deferred: CancellablePromise<typeof resultInputFile> = new Promise((resolve, reject) => {
|
const deferred: CancellablePromise<typeof resultInputFile> = new Promise((resolve, reject) => {
|
||||||
if(totalParts > 3000) {
|
if(totalParts > 3000) {
|
||||||
return reject({type: 'FILE_TOO_BIG'});
|
return reject({type: 'FILE_TOO_BIG'});
|
||||||
}
|
}
|
||||||
@ -459,13 +464,13 @@ export class ApiFileManager {
|
|||||||
errorHandler = () => {};
|
errorHandler = () => {};
|
||||||
};
|
};
|
||||||
|
|
||||||
let method = isBigFile ? 'upload.saveBigFilePart' : 'upload.saveFilePart';
|
const method = isBigFile ? 'upload.saveBigFilePart' : 'upload.saveFilePart';
|
||||||
for(let offset = 0; offset < fileSize; offset += partSize) {
|
for(let offset = 0; offset < fileSize; offset += partSize) {
|
||||||
let part = _part++; // 0, 1
|
const part = _part++; // 0, 1
|
||||||
this.downloadRequest('upload', () => {
|
this.downloadRequest('upload', () => {
|
||||||
return new Promise<void>((uploadResolve, uploadReject) => {
|
return new Promise<void>((uploadResolve, uploadReject) => {
|
||||||
var reader = new FileReader();
|
const reader = new FileReader();
|
||||||
var blob = file.slice(offset, offset + partSize);
|
const blob = file.slice(offset, offset + partSize);
|
||||||
|
|
||||||
reader.onloadend = (e) => {
|
reader.onloadend = (e) => {
|
||||||
if(canceled) {
|
if(canceled) {
|
||||||
@ -475,6 +480,7 @@ export class ApiFileManager {
|
|||||||
|
|
||||||
if(e.target.readyState != FileReader.DONE) {
|
if(e.target.readyState != FileReader.DONE) {
|
||||||
this.log.error('wrong readyState!');
|
this.log.error('wrong readyState!');
|
||||||
|
uploadReject();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,18 +500,19 @@ export class ApiFileManager {
|
|||||||
uploadResolve();
|
uploadResolve();
|
||||||
|
|
||||||
//////this.log('Progress', doneParts * partSize / fileSize);
|
//////this.log('Progress', doneParts * partSize / fileSize);
|
||||||
|
|
||||||
|
deferred.notify({done: doneParts * partSize, total: fileSize});
|
||||||
|
|
||||||
if(doneParts >= totalParts) {
|
if(doneParts >= totalParts) {
|
||||||
deferred.resolve(resultInputFile);
|
deferred.resolve(resultInputFile);
|
||||||
resolved = true;
|
resolved = true;
|
||||||
} else {
|
|
||||||
deferred.notify({done: doneParts * partSize, total: fileSize});
|
|
||||||
}
|
}
|
||||||
}, errorHandler);
|
}, errorHandler);
|
||||||
};
|
};
|
||||||
|
|
||||||
reader.readAsArrayBuffer(blob);
|
reader.readAsArrayBuffer(blob);
|
||||||
});
|
});
|
||||||
}, activeDelta);
|
}, activeDelta).catch(errorHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
deferred.cancel = () => {
|
deferred.cancel = () => {
|
||||||
@ -516,7 +523,15 @@ export class ApiFileManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return deferred;
|
deferred.notify = (progress: {done: number, total: number}) => {
|
||||||
|
notifyAll({progress: {fileName, ...progress}});
|
||||||
|
};
|
||||||
|
|
||||||
|
deferred.finally(() => {
|
||||||
|
delete this.uploadPromises[fileName];
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.uploadPromises[fileName] = deferred;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +106,7 @@ ctx.addEventListener('message', async(e) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
case 'cancelDownload':
|
case 'cancelDownload':
|
||||||
|
case 'uploadFile':
|
||||||
case 'downloadFile': {
|
case 'downloadFile': {
|
||||||
try {
|
try {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -219,6 +219,10 @@ class ApiManagerProxy extends CryptoWorkerMethods {
|
|||||||
public downloadFile(options: DownloadOptions) {
|
public downloadFile(options: DownloadOptions) {
|
||||||
return this.performTaskWorker('downloadFile', options);
|
return this.performTaskWorker('downloadFile', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public uploadFile(options: {file: Blob | File, fileName: string}) {
|
||||||
|
return this.performTaskWorker('uploadFile', options);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiManagerProxy = new ApiManagerProxy();
|
const apiManagerProxy = new ApiManagerProxy();
|
||||||
|
12
src/types.d.ts
vendored
12
src/types.d.ts
vendored
@ -151,3 +151,15 @@ export type WorkerTaskTemplate = {
|
|||||||
id: number,
|
id: number,
|
||||||
payload: any
|
payload: any
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type inputFile = {
|
||||||
|
_: 'inputFile',
|
||||||
|
parts: number,
|
||||||
|
id: [number, number],
|
||||||
|
name: string,
|
||||||
|
md5_checksum: string
|
||||||
|
};
|
||||||
|
|
||||||
|
export type inputFileBig = Omit<inputFile, 'md5_checksum' | '_'> & {_: 'inputFileBig'};
|
||||||
|
|
||||||
|
export type InputFile = inputFile | inputFileBig;
|
@ -6,7 +6,7 @@ const postcssPresetEnv = require('postcss-preset-env');
|
|||||||
const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin');
|
const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const allowedIPs = ['195.66.140.39', '192.168.31.144', '127.0.0.1', '192.168.31.1', '192.168.31.192', '176.100.18.181', '46.219.250.22'];
|
const allowedIPs = ['195.66.140.39', '192.168.31.144', '127.0.0.1', '192.168.31.1', '192.168.31.192', '176.100.18.181', '46.219.250.22', '193.42.119.184'];
|
||||||
const devMode = process.env.NODE_ENV !== 'production';
|
const devMode = process.env.NODE_ENV !== 'production';
|
||||||
const useLocal = false;
|
const useLocal = false;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user