Preloader fixes
Audio status fix
This commit is contained in:
parent
c7bd824873
commit
2b498a5b2c
@ -4,6 +4,8 @@ import appMessagesManager from "../lib/appManagers/appMessagesManager";
|
||||
import appDocsManager from "../lib/appManagers/appDocsManager";
|
||||
import opusDecodeController from "../lib/opusDecodeController";
|
||||
|
||||
// TODO: если удалить сообщение, и при этом аудио будет играть - оно не остановится, и можно будет по нему перейти вникуда
|
||||
|
||||
class AppAudio {
|
||||
private container: HTMLElement;
|
||||
private audios: {[mid: string]: HTMLAudioElement} = {};
|
||||
@ -133,6 +135,10 @@ class AppAudio {
|
||||
public willBePlayed(audio: HTMLAudioElement) {
|
||||
this.willBePlayedAudio = audio;
|
||||
}
|
||||
|
||||
public audioExists(mid: number) {
|
||||
return !!this.audios[mid];
|
||||
}
|
||||
}
|
||||
|
||||
const appAudio = new AppAudio();
|
||||
|
@ -390,35 +390,39 @@ export default class AudioElement extends HTMLElement {
|
||||
this.addEventListener('click', onClick);
|
||||
this.click();
|
||||
} else {
|
||||
const r = () => {
|
||||
if(appAudio.audioExists(mid)) { // чтобы показать прогресс, если аудио уже было скачано
|
||||
onLoad();
|
||||
} else {
|
||||
const r = () => {
|
||||
onLoad();
|
||||
|
||||
appAudio.willBePlayed(this.audio); // prepare for loading audio
|
||||
appAudio.willBePlayed(this.audio); // prepare for loading audio
|
||||
|
||||
if(!preloader) {
|
||||
preloader = new ProgressivePreloader(null, false);
|
||||
}
|
||||
if(!preloader) {
|
||||
preloader = new ProgressivePreloader(null, false);
|
||||
}
|
||||
|
||||
preloader.attach(downloadDiv);
|
||||
this.append(downloadDiv);
|
||||
preloader.attach(downloadDiv);
|
||||
this.append(downloadDiv);
|
||||
|
||||
new Promise((resolve) => {
|
||||
if(this.audio.readyState >= 2) resolve();
|
||||
else this.addAudioListener('canplay', resolve);
|
||||
}).then(() => {
|
||||
downloadDiv.remove();
|
||||
new Promise((resolve) => {
|
||||
if(this.audio.readyState >= 2) resolve();
|
||||
else this.addAudioListener('canplay', resolve);
|
||||
}).then(() => {
|
||||
downloadDiv.remove();
|
||||
|
||||
//setTimeout(() => {
|
||||
// release loaded audio
|
||||
if(appAudio.willBePlayedAudio == this.audio) {
|
||||
this.audio.play();
|
||||
appAudio.willBePlayedAudio = null;
|
||||
}
|
||||
//}, 10e3);
|
||||
});
|
||||
};
|
||||
//setTimeout(() => {
|
||||
// release loaded audio
|
||||
if(appAudio.willBePlayedAudio == this.audio) {
|
||||
this.audio.play();
|
||||
appAudio.willBePlayedAudio = null;
|
||||
}
|
||||
//}, 10e3);
|
||||
});
|
||||
};
|
||||
|
||||
this.addEventListener('click', r, {once: true});
|
||||
this.addEventListener('click', r, {once: true});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.preloader.attach(downloadDiv, false);
|
||||
|
@ -10,14 +10,18 @@ export default class ProgressivePreloader {
|
||||
|
||||
private promise: CancellablePromise<any> = null;
|
||||
|
||||
constructor(elem?: Element, private cancelable = true) {
|
||||
constructor(elem?: Element, private cancelable = true, streamable = false) {
|
||||
this.preloader = document.createElement('div');
|
||||
this.preloader.classList.add('preloader-container');
|
||||
|
||||
if(streamable) {
|
||||
this.preloader.classList.add('preloader-streamable');
|
||||
}
|
||||
|
||||
this.preloader.innerHTML = `
|
||||
<div class="you-spin-me-round">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="preloader-circular" viewBox="25 25 50 50">
|
||||
<circle class="preloader-path-new" cx="50" cy="50" r="23" fill="none" stroke-miterlimit="10"/>
|
||||
<circle class="preloader-path-new" cx="50" cy="50" r="${streamable ? 19 : 23}" fill="none" stroke-miterlimit="10"/>
|
||||
</svg>
|
||||
</div>`;
|
||||
|
||||
@ -98,6 +102,8 @@ export default class ProgressivePreloader {
|
||||
public detach() {
|
||||
this.detached = true;
|
||||
|
||||
//return;
|
||||
|
||||
if(this.preloader.parentElement) {
|
||||
/* setTimeout(() => */window.requestAnimationFrame(() => {
|
||||
if(!this.detached) return;
|
||||
|
@ -4,7 +4,7 @@ export const isWorker = isWebWorker || isServiceWorker;
|
||||
|
||||
// в SW может быть сразу две переменных TRUE, поэтому проверяю по последней
|
||||
|
||||
const notifyServiceWorker = (...args: any[]) => {
|
||||
const notifyServiceWorker = (all: boolean, ...args: any[]) => {
|
||||
(self as any as ServiceWorkerGlobalScope)
|
||||
.clients
|
||||
.matchAll({ includeUncontrolled: false, type: 'window' })
|
||||
@ -14,8 +14,10 @@ const notifyServiceWorker = (...args: any[]) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
listeners[0].postMessage(...args);
|
||||
listeners.slice(all ? 0 : -1).forEach(listener => {
|
||||
// @ts-ignore
|
||||
listener.postMessage(...args);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -26,4 +28,5 @@ const notifyWorker = (...args: any[]) => {
|
||||
|
||||
const empty = () => {};
|
||||
|
||||
export const notifySomeone = isServiceWorker ? notifyServiceWorker : (isWebWorker ? notifyWorker : empty);
|
||||
export const notifySomeone = isServiceWorker ? notifyServiceWorker.bind(null, false) : (isWebWorker ? notifyWorker : empty);
|
||||
export const notifyAll = isServiceWorker ? notifyServiceWorker.bind(null, true) : (isWebWorker ? notifyWorker : empty);
|
@ -58,10 +58,18 @@ export class AppDownloadManager {
|
||||
//console.log('Will download file:', fileName, url);
|
||||
|
||||
deferred.cancel = () => {
|
||||
const error = new Error('Download canceled');
|
||||
error.name = 'AbortError';
|
||||
|
||||
apiManager.cancelDownload(fileName);
|
||||
delete this.downloads[fileName];
|
||||
delete this.progress[fileName];
|
||||
delete this.progressCallbacks[fileName];
|
||||
|
||||
deferred.reject(error);
|
||||
deferred.cancel = () => {};
|
||||
};
|
||||
|
||||
//return this.downloads[fileName] = {promise, controller};
|
||||
return this.downloads[fileName] = deferred;
|
||||
}
|
||||
|
||||
|
@ -70,8 +70,7 @@ export class AppMediaViewer {
|
||||
this.log = logger('AMV');
|
||||
this.preloader = new ProgressivePreloader();
|
||||
|
||||
this.preloaderStreamable = new ProgressivePreloader(undefined, false);
|
||||
this.preloaderStreamable.preloader.classList.add('preloader-streamable');
|
||||
this.preloaderStreamable = new ProgressivePreloader(undefined, false, true);
|
||||
|
||||
this.lazyLoadQueue = new LazyLoadQueue(undefined, true);
|
||||
|
||||
|
@ -34,7 +34,7 @@ export class FileManager {
|
||||
}
|
||||
}
|
||||
|
||||
public getFakeFileWriter(mimeType: string, saveFileCallback: (blob: Blob) => Promise<Blob>) {
|
||||
public getFakeFileWriter(mimeType: string, saveFileCallback?: (blob: Blob) => Promise<Blob>) {
|
||||
const blobParts: Array<Uint8Array | string> = [];
|
||||
const fakeFileWriter = {
|
||||
write: async(part: Uint8Array | string) => {
|
||||
@ -47,9 +47,10 @@ export class FileManager {
|
||||
truncate: () => {
|
||||
blobParts.length = 0;
|
||||
},
|
||||
finalize: () => {
|
||||
finalize: (saveToStorage = true) => {
|
||||
const blob = blobConstruct(blobParts, mimeType);
|
||||
if(saveFileCallback) {
|
||||
|
||||
if(saveToStorage && saveFileCallback) {
|
||||
saveFileCallback(blob);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ import { logger, LogLevels } from "../logger";
|
||||
import { InputFileLocation, FileLocation, UploadFile } from "../../types";
|
||||
import { isSafari } from "../../helpers/userAgent";
|
||||
import cryptoWorker from "../crypto/cryptoworker";
|
||||
import { notifySomeone } from "../../helpers/context";
|
||||
import { notifySomeone, notifyAll } from "../../helpers/context";
|
||||
|
||||
type Delayed = {
|
||||
offset: number,
|
||||
@ -26,6 +26,8 @@ export type DownloadOptions = {
|
||||
processPart?: (bytes: Uint8Array, offset?: number, queue?: Delayed[]) => Promise<any>
|
||||
};
|
||||
|
||||
const MAX_FILE_SAVE_SIZE = 20e6;
|
||||
|
||||
export class ApiFileManager {
|
||||
public cachedDownloadPromises: {
|
||||
[fileName: string]: CancellablePromise<Blob>
|
||||
@ -334,14 +336,14 @@ export class ApiFileManager {
|
||||
//done += limit;
|
||||
done += result.bytes.byteLength;
|
||||
|
||||
const processedResult = await processDownloaded(result.bytes, offset);
|
||||
checkCancel();
|
||||
|
||||
//if(!isFinal) {
|
||||
////this.log('deferred notify 2:', {done: offset + limit, total: size}, deferred);
|
||||
deferred.notify({done, offset, total: size});
|
||||
//}
|
||||
|
||||
const processedResult = await processDownloaded(result.bytes, offset);
|
||||
checkCancel();
|
||||
|
||||
await writeFilePromise;
|
||||
checkCancel();
|
||||
|
||||
@ -356,7 +358,7 @@ export class ApiFileManager {
|
||||
if(options.processPart) {
|
||||
deferred.resolve();
|
||||
} else {
|
||||
deferred.resolve(fileWriter.finalize());
|
||||
deferred.resolve(fileWriter.finalize(size < MAX_FILE_SAVE_SIZE));
|
||||
}
|
||||
}
|
||||
} catch(err) {
|
||||
@ -384,6 +386,10 @@ export class ApiFileManager {
|
||||
}
|
||||
};
|
||||
|
||||
deferred.notify = (progress: {done: number, total: number, offset: number}) => {
|
||||
notifyAll({progress: {fileName, ...progress}});
|
||||
};
|
||||
|
||||
this.cachedDownloadPromises[fileName] = deferred;
|
||||
|
||||
return deferred;
|
||||
|
@ -1,12 +1,12 @@
|
||||
// just to include
|
||||
import {secureRandom} from '../polyfill';
|
||||
import {secureRandom, CancellablePromise} from '../polyfill';
|
||||
secureRandom;
|
||||
|
||||
import apiManager from "./apiManager";
|
||||
import AppStorage from '../storage';
|
||||
import cryptoWorker from "../crypto/cryptoworker";
|
||||
import networkerFactory from "./networkerFactory";
|
||||
import apiFileManager from './apiFileManager';
|
||||
import apiFileManager, { ApiFileManager } from './apiFileManager';
|
||||
import { logger, LogLevels } from '../logger';
|
||||
import type { ServiceWorkerTask, ServiceWorkerTaskResponse } from './mtproto.service';
|
||||
|
||||
@ -112,6 +112,9 @@ ctx.addEventListener('message', async(e) => {
|
||||
let result = apiFileManager[task.task].apply(apiFileManager, task.args);
|
||||
|
||||
if(result instanceof Promise) {
|
||||
/* (result as ReturnType<ApiFileManager['downloadFile']>).notify = (progress: {done: number, total: number, offset: number}) => {
|
||||
notify({progress: {fileName, ...progress}});
|
||||
}; */
|
||||
result = await result;
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,11 @@
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
circle {
|
||||
stroke-width: 2.5 !important;
|
||||
animation: dashNewStreamable 1.5s ease-in-out infinite !important;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
@ -145,3 +150,18 @@
|
||||
stroke-dashoffset: -286%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dashNewStreamable {
|
||||
0% {
|
||||
stroke-dasharray: 1, 200;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
50% {
|
||||
stroke-dasharray: 89, 200;
|
||||
stroke-dashoffset: -35px;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 89, 200;
|
||||
stroke-dashoffset: -237%;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user