ESG GIFs try
Websocket fix instant connect retry Possible fix to stream FILE_REFERENCE_EXPIRED
This commit is contained in:
parent
9948bab8b0
commit
097a55850c
@ -1,4 +1,4 @@
|
|||||||
import LazyLoadQueue from "../lazyLoadQueue";
|
import LazyLoadQueue, { LazyLoadQueueIntersector } from "../lazyLoadQueue";
|
||||||
import GifsTab from "./tabs/gifs";
|
import GifsTab from "./tabs/gifs";
|
||||||
import { findUpClassName, findUpTag, whichChild } from "../../lib/utils";
|
import { findUpClassName, findUpTag, whichChild } from "../../lib/utils";
|
||||||
import { horizontalMenu } from "../horizontalMenu";
|
import { horizontalMenu } from "../horizontalMenu";
|
||||||
@ -324,6 +324,26 @@ export class EmoticonsDropdown {
|
|||||||
console.warn('got no doc by id:', fileID);
|
console.warn('got no doc by id:', fileID);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public addLazyLoadQueueRepeat(lazyLoadQueue: LazyLoadQueueIntersector, processInvisibleDiv: (div: HTMLElement) => void) {
|
||||||
|
this.events.onClose.push(() => {
|
||||||
|
lazyLoadQueue.lock();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.events.onCloseAfter.push(() => {
|
||||||
|
const divs = lazyLoadQueue.intersector.getVisible();
|
||||||
|
|
||||||
|
for(const div of divs) {
|
||||||
|
processInvisibleDiv(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
lazyLoadQueue.intersector.clearVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.events.onOpenAfter.push(() => {
|
||||||
|
lazyLoadQueue.unlockAndRefresh();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const emoticonsDropdown = new EmoticonsDropdown();
|
const emoticonsDropdown = new EmoticonsDropdown();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { EmoticonsDropdown, EmoticonsTab, EMOTICONSSTICKERGROUP } from "..";
|
import emoticonsDropdown, { EmoticonsDropdown, EmoticonsTab, EMOTICONSSTICKERGROUP } from "..";
|
||||||
import GifsMasonry from "../../gifsMasonry";
|
import GifsMasonry from "../../gifsMasonry";
|
||||||
import Scrollable from "../../scrollable_new";
|
import Scrollable from "../../scrollable_new";
|
||||||
import { putPreloader } from "../../misc";
|
import { putPreloader } from "../../misc";
|
||||||
@ -24,15 +24,15 @@ export default class GifsTab implements EmoticonsTab {
|
|||||||
res.gifs.forEach((doc, idx) => {
|
res.gifs.forEach((doc, idx) => {
|
||||||
res.gifs[idx] = doc = appDocsManager.saveDoc(doc);
|
res.gifs[idx] = doc = appDocsManager.saveDoc(doc);
|
||||||
//if(doc._ == 'documentEmpty') return;
|
//if(doc._ == 'documentEmpty') return;
|
||||||
//masonry.add(doc as MyDocument);
|
masonry.add(doc as MyDocument);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//let line: MTDocument[] = [];
|
|
||||||
|
|
||||||
preloader.remove();
|
preloader.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
emoticonsDropdown.addLazyLoadQueueRepeat(masonry.lazyLoadQueue, masonry.processInvisibleDiv);
|
||||||
|
|
||||||
this.init = null;
|
this.init = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,23 +321,7 @@ export default class StickersTab implements EmoticonsTab {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
emoticonsDropdown.events.onClose.push(() => {
|
emoticonsDropdown.addLazyLoadQueueRepeat(this.lazyLoadQueue, this.processInvisibleDiv);
|
||||||
this.lazyLoadQueue.lock();
|
|
||||||
});
|
|
||||||
|
|
||||||
emoticonsDropdown.events.onCloseAfter.push(() => {
|
|
||||||
const divs = this.lazyLoadQueue.intersector.getVisible();
|
|
||||||
|
|
||||||
for(const div of divs) {
|
|
||||||
this.processInvisibleDiv(div);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.lazyLoadQueue.intersector.clearVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
emoticonsDropdown.events.onOpenAfter.push(() => {
|
|
||||||
this.lazyLoadQueue.unlockAndRefresh();
|
|
||||||
});
|
|
||||||
|
|
||||||
/* setInterval(() => {
|
/* setInterval(() => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -24,14 +24,14 @@ export default class GifsMasonry {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setInterval(() => {
|
/* setInterval(() => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const players = animationIntersector.byGroups[group];
|
const players = animationIntersector.byGroups[group];
|
||||||
|
|
||||||
if(players) {
|
if(players) {
|
||||||
console.log(`GIFS RENDERED IN ${group}:`, players.length, players.filter(p => !p.animation.paused).length, this.lazyLoadQueue.intersector.getVisible().length);
|
console.log(`GIFS RENDERED IN ${group}:`, players.length, players.filter(p => !p.animation.paused).length, this.lazyLoadQueue.intersector.getVisible().length);
|
||||||
}
|
}
|
||||||
}, .25e3);
|
}, .25e3); */
|
||||||
|
|
||||||
let timeout = 0;
|
let timeout = 0;
|
||||||
// memory leak
|
// memory leak
|
||||||
@ -51,12 +51,14 @@ export default class GifsMasonry {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private processVisibleDiv = (div: HTMLElement) => {
|
processVisibleDiv = (div: HTMLElement) => {
|
||||||
const video = div.querySelector('video');
|
const video = div.querySelector('video');
|
||||||
if(video) {
|
if(video) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//console.log('processVisibleDiv');
|
||||||
|
|
||||||
const load = () => {
|
const load = () => {
|
||||||
const docID = div.dataset.docID;
|
const docID = div.dataset.docID;
|
||||||
const doc = appDocsManager.getDoc(docID);
|
const doc = appDocsManager.getDoc(docID);
|
||||||
@ -110,7 +112,7 @@ export default class GifsMasonry {
|
|||||||
this.lazyLoadQueue.push({div, load});
|
this.lazyLoadQueue.push({div, load});
|
||||||
};
|
};
|
||||||
|
|
||||||
private processInvisibleDiv = async(div: HTMLElement) => {
|
processInvisibleDiv = async(div: HTMLElement) => {
|
||||||
return this.scrollPromise.then(async() => {
|
return this.scrollPromise.then(async() => {
|
||||||
//return;
|
//return;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ export default class AppForwardTab implements SliderTab {
|
|||||||
private msgIDs: number[] = [];
|
private msgIDs: number[] = [];
|
||||||
|
|
||||||
onCloseAfterTimeout() {
|
onCloseAfterTimeout() {
|
||||||
|
document.body.classList.remove('is-forward-active');
|
||||||
this.cleanup();
|
this.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +80,7 @@ export default class AppForwardTab implements SliderTab {
|
|||||||
//console.log('forward rendered:', this.container.querySelector('.selector ul').childElementCount);
|
//console.log('forward rendered:', this.container.querySelector('.selector ul').childElementCount);
|
||||||
appSidebarRight.selectTab(AppSidebarRight.SLIDERITEMSIDS.forward);
|
appSidebarRight.selectTab(AppSidebarRight.SLIDERITEMSIDS.forward);
|
||||||
appSidebarRight.toggleSidebar(true);
|
appSidebarRight.toggleSidebar(true);
|
||||||
|
document.body.classList.add('is-forward-active');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,17 +263,10 @@ export default class AppSharedMediaTab implements SliderTab {
|
|||||||
|
|
||||||
case 'inputMessagesFilterDocument': {
|
case 'inputMessagesFilterDocument': {
|
||||||
for(let message of messages) {
|
for(let message of messages) {
|
||||||
if(!message.media.document || ['voice', 'audio', 'gif'].includes(message.media.document.type)) {
|
if(!message.media.document || ['voice', 'audio', 'gif', 'sticker'].includes(message.media.document.type)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let doc = message.media.document;
|
|
||||||
if(doc.attributes) {
|
|
||||||
if(doc.attributes.find((a: any) => a._ == "documentAttributeSticker")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filtered.push(message);
|
filtered.push(message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -234,7 +234,15 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
|||||||
}, {once: true});
|
}, {once: true});
|
||||||
//}
|
//}
|
||||||
|
|
||||||
video.addEventListener('error', deferred.reject);
|
video.addEventListener('error', (e) => {
|
||||||
|
deferred.resolve();
|
||||||
|
/* console.error('video error', e, video.src);
|
||||||
|
if(video.src) { // if wasn't cleaned
|
||||||
|
deferred.reject(e);
|
||||||
|
} else {
|
||||||
|
deferred.resolve();
|
||||||
|
} */
|
||||||
|
});
|
||||||
|
|
||||||
//if(doc.type != 'round') {
|
//if(doc.type != 'round') {
|
||||||
renderImageFromUrl(video, doc.url);
|
renderImageFromUrl(video, doc.url);
|
||||||
|
@ -5,7 +5,7 @@ import type { DownloadOptions } from "../mtproto/apiFileManager";
|
|||||||
import { getFileNameByLocation } from "../bin_utils";
|
import { getFileNameByLocation } from "../bin_utils";
|
||||||
import { InputFile } from "../../layer";
|
import { InputFile } from "../../layer";
|
||||||
import referenceDatabase, {ReferenceBytes} from "../mtproto/referenceDatabase";
|
import referenceDatabase, {ReferenceBytes} from "../mtproto/referenceDatabase";
|
||||||
import appMessagesManager from "./appMessagesManager";
|
import type { ApiError } from "../mtproto/apiManager";
|
||||||
|
|
||||||
export type ResponseMethodBlob = 'blob';
|
export type ResponseMethodBlob = 'blob';
|
||||||
export type ResponseMethodJson = 'json';
|
export type ResponseMethodJson = 'json';
|
||||||
@ -77,30 +77,17 @@ export class AppDownloadManager {
|
|||||||
|
|
||||||
const deferred = this.getNewDeferred(fileName);
|
const deferred = this.getNewDeferred(fileName);
|
||||||
|
|
||||||
const onError = (err: any) => {
|
const onError = (err: ApiError) => {
|
||||||
switch(err.type) {
|
switch(err.type) {
|
||||||
case 'FILE_REFERENCE_EXPIRED': {
|
case 'FILE_REFERENCE_EXPIRED': {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const bytes: ReferenceBytes = options?.location?.file_reference;
|
const bytes: ReferenceBytes = options?.location?.file_reference;
|
||||||
if(bytes) {
|
if(bytes) {
|
||||||
const context = referenceDatabase.getContext(bytes);
|
referenceDatabase.refreshReference(bytes).then(tryDownload);
|
||||||
switch(context?.type) {
|
break;
|
||||||
case 'message': {
|
|
||||||
return appMessagesManager.wrapSingleMessage(context.messageID, true).then(() => {
|
|
||||||
//console.log('FILE_REFERENCE_EXPIRED: got message', context, options, appMessagesManager.getMessage(context.messageID).media);
|
|
||||||
return tryDownload();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
console.warn('FILE_REFERENCE_EXPIRED: not implemented context', context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
console.warn('FILE_REFERENCE_EXPIRED: no context for bytes:', bytes);
|
console.warn('FILE_REFERENCE_EXPIRED: no context for bytes:', bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -6,6 +6,8 @@ import { Modify } from '../../types';
|
|||||||
import appStateManager from './appStateManager';
|
import appStateManager from './appStateManager';
|
||||||
import { MOUNT_CLASS_TO } from '../mtproto/mtproto_config';
|
import { MOUNT_CLASS_TO } from '../mtproto/mtproto_config';
|
||||||
|
|
||||||
|
// TODO: если пак будет сохранён и потом обновлён, то недостающие стикеры не подгрузит
|
||||||
|
|
||||||
export class AppStickersManager {
|
export class AppStickersManager {
|
||||||
private stickerSets: {
|
private stickerSets: {
|
||||||
[stickerSetID: string]: MessagesStickerSet
|
[stickerSetID: string]: MessagesStickerSet
|
||||||
|
@ -29,7 +29,7 @@ export function longToBytes(sLong: string) {
|
|||||||
}
|
}
|
||||||
console.log('longToBytes LEEMON', sLong, performance.now() - perf); */
|
console.log('longToBytes LEEMON', sLong, performance.now() - perf); */
|
||||||
|
|
||||||
const bytes = bigInt2bytes(str2bigInt(sLong, 10), false);
|
const bytes = addPadding(bigInt2bytes(str2bigInt(sLong, 10), false), 8, true, false, false);
|
||||||
//console.log('longToBytes', bytes, b);
|
//console.log('longToBytes', bytes, b);
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
|
@ -15,10 +15,10 @@ ctx.addEventListener('message', (e) => {
|
|||||||
const task = e.data as ServiceWorkerTaskResponse;
|
const task = e.data as ServiceWorkerTaskResponse;
|
||||||
const promise = deferredPromises[task.id];
|
const promise = deferredPromises[task.id];
|
||||||
|
|
||||||
if(task.payload) {
|
if(task.error) {
|
||||||
promise.resolve(task.payload);
|
promise.reject(task.error);
|
||||||
} else {
|
} else {
|
||||||
promise.reject();
|
promise.resolve(task.payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete deferredPromises[task.id];
|
delete deferredPromises[task.id];
|
||||||
@ -33,7 +33,8 @@ export interface ServiceWorkerTask extends WorkerTaskTemplate {
|
|||||||
|
|
||||||
export interface ServiceWorkerTaskResponse extends WorkerTaskTemplate {
|
export interface ServiceWorkerTaskResponse extends WorkerTaskTemplate {
|
||||||
type: 'requestFilePart',
|
type: 'requestFilePart',
|
||||||
payload: UploadFile.uploadFile
|
payload?: UploadFile.uploadFile,
|
||||||
|
originalPayload?: ServiceWorkerTask['payload']
|
||||||
};
|
};
|
||||||
|
|
||||||
const onFetch = (event: FetchEvent): void => {
|
const onFetch = (event: FetchEvent): void => {
|
||||||
|
@ -82,15 +82,15 @@ ctx.addEventListener('message', async(e) => {
|
|||||||
const task = e.data as ServiceWorkerTask;
|
const task = e.data as ServiceWorkerTask;
|
||||||
const responseTask: ServiceWorkerTaskResponse = {
|
const responseTask: ServiceWorkerTaskResponse = {
|
||||||
type: task.type,
|
type: task.type,
|
||||||
id: task.id,
|
id: task.id
|
||||||
payload: null
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await apiFileManager.requestFilePart(...task.payload);
|
const res = await apiFileManager.requestFilePart(...task.payload);
|
||||||
responseTask.payload = res;
|
responseTask.payload = res;
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
|
responseTask.originalPayload = task.payload;
|
||||||
|
responseTask.error = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
respond(responseTask);
|
respond(responseTask);
|
||||||
|
@ -9,6 +9,8 @@ import type { ServiceWorkerTask, ServiceWorkerTaskResponse } from './mtproto.ser
|
|||||||
import { MethodDeclMap } from '../../layer';
|
import { MethodDeclMap } from '../../layer';
|
||||||
import { MOUNT_CLASS_TO } from './mtproto_config';
|
import { MOUNT_CLASS_TO } from './mtproto_config';
|
||||||
import $rootScope from '../rootScope';
|
import $rootScope from '../rootScope';
|
||||||
|
import referenceDatabase from './referenceDatabase';
|
||||||
|
import { ApiError } from './apiManager';
|
||||||
|
|
||||||
type Task = {
|
type Task = {
|
||||||
taskID: number,
|
taskID: number,
|
||||||
@ -126,7 +128,31 @@ class ApiManagerProxy extends CryptoWorkerMethods {
|
|||||||
} else if(task.type == 'convertWebp') {
|
} else if(task.type == 'convertWebp') {
|
||||||
webpWorkerController.postMessage(task);
|
webpWorkerController.postMessage(task);
|
||||||
} else if((task as ServiceWorkerTaskResponse).type == 'requestFilePart') {
|
} else if((task as ServiceWorkerTaskResponse).type == 'requestFilePart') {
|
||||||
navigator.serviceWorker.controller.postMessage(task);
|
const _task = task as ServiceWorkerTaskResponse;
|
||||||
|
|
||||||
|
if(_task.error) {
|
||||||
|
const onError = (error: ApiError) => {
|
||||||
|
if(error?.type == 'FILE_REFERENCE_EXPIRED') {
|
||||||
|
// @ts-ignore
|
||||||
|
const bytes = _task.originalPayload[1].file_reference;
|
||||||
|
referenceDatabase.refreshReference(bytes).then(() => {
|
||||||
|
const newTask: ServiceWorkerTask = {
|
||||||
|
type: _task.type,
|
||||||
|
id: _task.id,
|
||||||
|
payload: _task.originalPayload
|
||||||
|
};
|
||||||
|
|
||||||
|
this.postMessage(newTask);
|
||||||
|
}).catch(onError);
|
||||||
|
} else {
|
||||||
|
navigator.serviceWorker.controller.postMessage(task);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onError(_task.error);
|
||||||
|
} else {
|
||||||
|
navigator.serviceWorker.controller.postMessage(task);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.finalizeTask(task.taskID, task.result, task.error);
|
this.finalizeTask(task.taskID, task.result, task.error);
|
||||||
}
|
}
|
||||||
@ -137,7 +163,7 @@ class ApiManagerProxy extends CryptoWorkerMethods {
|
|||||||
const deferred = this.awaiting[taskID];
|
const deferred = this.awaiting[taskID];
|
||||||
if(deferred !== undefined) {
|
if(deferred !== undefined) {
|
||||||
this.log.debug('done', deferred.taskName, result, error);
|
this.log.debug('done', deferred.taskName, result, error);
|
||||||
result === undefined ? deferred.reject(error) : deferred.resolve(result);
|
error ? deferred.reject(error) : deferred.resolve(result);
|
||||||
delete this.awaiting[taskID];
|
delete this.awaiting[taskID];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import appMessagesManager from "../appManagers/appMessagesManager";
|
||||||
import { Photo } from "../../layer";
|
import { Photo } from "../../layer";
|
||||||
import { deepEqual } from "../utils";
|
import { deepEqual } from "../utils";
|
||||||
import { MOUNT_CLASS_TO } from "./mtproto_config";
|
import { MOUNT_CLASS_TO } from "./mtproto_config";
|
||||||
@ -57,6 +58,34 @@ class ReferenceDatabase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public refreshReference(reference: ReferenceBytes): Promise<void> {
|
||||||
|
const context = this.getContext(reference);
|
||||||
|
switch(context?.type) {
|
||||||
|
case 'message': {
|
||||||
|
return appMessagesManager.wrapSingleMessage(context.messageID, true);
|
||||||
|
// .then(() => {
|
||||||
|
// console.log('FILE_REFERENCE_EXPIRED: got message', context, options, appMessagesManager.getMessage(context.messageID).media);
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
console.warn('FILE_REFERENCE_EXPIRED: not implemented context', context);
|
||||||
|
return Promise.reject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handleReferenceError = (reference: ReferenceBytes, error: ApiError) => {
|
||||||
|
switch(error.type) {
|
||||||
|
case 'FILE_REFERENCE_EXPIRED': {
|
||||||
|
return this.refreshReference(reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
}; */
|
||||||
|
|
||||||
/* public replaceReference(oldReference: ReferenceBytes, newReference: ReferenceBytes) {
|
/* public replaceReference(oldReference: ReferenceBytes, newReference: ReferenceBytes) {
|
||||||
const contexts = this.contexts.get(oldReference);
|
const contexts = this.contexts.get(oldReference);
|
||||||
if(contexts) {
|
if(contexts) {
|
||||||
|
@ -107,6 +107,8 @@ export class Obfuscation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CONNECTION_RETRY_TIMEOUT = 30000;
|
||||||
|
|
||||||
export default class Socket extends MTTransport {
|
export default class Socket extends MTTransport {
|
||||||
ws: WebSocket;
|
ws: WebSocket;
|
||||||
|
|
||||||
@ -129,6 +131,8 @@ export default class Socket extends MTTransport {
|
|||||||
|
|
||||||
codec = intermediatePacketCodec;
|
codec = intermediatePacketCodec;
|
||||||
|
|
||||||
|
lastCloseTime: number;
|
||||||
|
|
||||||
constructor(dcID: number, url: string) {
|
constructor(dcID: number, url: string) {
|
||||||
super(dcID, url);
|
super(dcID, url);
|
||||||
|
|
||||||
@ -169,27 +173,35 @@ export default class Socket extends MTTransport {
|
|||||||
this.log('closed', event, this.pending);
|
this.log('closed', event, this.pending);
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
|
|
||||||
|
const time = Date.now();
|
||||||
|
const diff = time - this.lastCloseTime;
|
||||||
|
let needTimeout = !isNaN(diff) && diff < CONNECTION_RETRY_TIMEOUT ? CONNECTION_RETRY_TIMEOUT - diff : 0;
|
||||||
|
|
||||||
//this.pending.length = 0;
|
//this.pending.length = 0;
|
||||||
/* if(this.networker) {
|
/* if(this.networker) {
|
||||||
this.networker.resend();
|
this.networker.resend();
|
||||||
this.networker.cleanupSent();
|
this.networker.cleanupSent();
|
||||||
} */
|
} */
|
||||||
|
|
||||||
this.log('trying to reconnect...');
|
this.log('will try to reconnect after timeout:', needTimeout / 1000);
|
||||||
this.connect();
|
setTimeout(() => {
|
||||||
|
this.log('trying to reconnect...');
|
||||||
|
this.lastCloseTime = Date.now();
|
||||||
|
this.connect();
|
||||||
|
|
||||||
for(let pending of this.pending) {
|
for(let pending of this.pending) {
|
||||||
if(pending.bodySent) {
|
if(pending.bodySent) {
|
||||||
pending.bodySent = false;
|
pending.bodySent = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(this.networker) {
|
if(this.networker) {
|
||||||
this.ws.addEventListener('open', () => {
|
this.ws.addEventListener('open', () => {
|
||||||
this.networker.resend();
|
this.networker.resend();
|
||||||
this.networker.cleanupSent();
|
this.networker.cleanupSent();
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
}
|
}
|
||||||
|
}, needTimeout);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMessage = (event: MessageEvent) => {
|
handleMessage = (event: MessageEvent) => {
|
||||||
|
@ -34,6 +34,10 @@
|
|||||||
border-left: 1px solid #DADCE0;
|
border-left: 1px solid #DADCE0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.is-forward-active & {
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-header {
|
.sidebar-header {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
|
||||||
@ -315,12 +319,16 @@
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-item-media {
|
.grid-item {
|
||||||
opacity: 1;
|
overflow: hidden;
|
||||||
transition: opacity .2s ease;
|
|
||||||
|
|
||||||
html:not(.is-mac) &.thumbnail {
|
&-media {
|
||||||
filter: blur(7px);
|
opacity: 1;
|
||||||
|
transition: opacity .2s ease;
|
||||||
|
|
||||||
|
html:not(.is-mac) &.thumbnail {
|
||||||
|
filter: blur(7px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1150,7 +1150,7 @@ img.emoji {
|
|||||||
.grid-item {
|
.grid-item {
|
||||||
height: 0;
|
height: 0;
|
||||||
padding-bottom: 100%;
|
padding-bottom: 100%;
|
||||||
overflow: hidden;
|
//overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
5
src/types.d.ts
vendored
5
src/types.d.ts
vendored
@ -1,3 +1,5 @@
|
|||||||
|
import type { ApiError } from "./lib/mtproto/apiManager";
|
||||||
|
|
||||||
export type InvokeApiOptions = Partial<{
|
export type InvokeApiOptions = Partial<{
|
||||||
dcID: number,
|
dcID: number,
|
||||||
timeout: number,
|
timeout: number,
|
||||||
@ -20,7 +22,8 @@ export type InvokeApiOptions = Partial<{
|
|||||||
export type WorkerTaskTemplate = {
|
export type WorkerTaskTemplate = {
|
||||||
type: string,
|
type: string,
|
||||||
id: number,
|
id: number,
|
||||||
payload: any
|
payload?: any,
|
||||||
|
error?: ApiError
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Modify<T, R> = Omit<T, keyof R> & R;
|
export type Modify<T, R> = Omit<T, keyof R> & R;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user