Reconnect button
This commit is contained in:
parent
c95d2a83f2
commit
07dff5479c
@ -15,6 +15,9 @@ import Button from "./button";
|
|||||||
import ProgressivePreloader from "./preloader";
|
import ProgressivePreloader from "./preloader";
|
||||||
import SetTransition from "./singleTransition";
|
import SetTransition from "./singleTransition";
|
||||||
import sessionStorage from '../lib/sessionStorage';
|
import sessionStorage from '../lib/sessionStorage';
|
||||||
|
import { ConnectionStatus } from "../lib/mtproto/connectionStatus";
|
||||||
|
import { cancelEvent } from "../helpers/dom/cancelEvent";
|
||||||
|
import apiManager from "../lib/mtproto/mtprotoworker";
|
||||||
|
|
||||||
export default class ConnectionStatusComponent {
|
export default class ConnectionStatusComponent {
|
||||||
public static CHANGE_STATE_DELAY = 1000;
|
public static CHANGE_STATE_DELAY = 1000;
|
||||||
@ -23,9 +26,10 @@ export default class ConnectionStatusComponent {
|
|||||||
private statusEl: HTMLElement;
|
private statusEl: HTMLElement;
|
||||||
private statusPreloader: ProgressivePreloader;
|
private statusPreloader: ProgressivePreloader;
|
||||||
|
|
||||||
private currentLangPackKey = '';
|
private currentLangPackKey: LangPackKey;
|
||||||
|
|
||||||
private connectingTimeout: number;
|
private hadConnect = false;
|
||||||
|
private retryAt: number;
|
||||||
private connecting = false;
|
private connecting = false;
|
||||||
private updating = false;
|
private updating = false;
|
||||||
|
|
||||||
@ -77,13 +81,13 @@ export default class ConnectionStatusComponent {
|
|||||||
|
|
||||||
/* let bool = true;
|
/* let bool = true;
|
||||||
document.addEventListener('dblclick', () => {
|
document.addEventListener('dblclick', () => {
|
||||||
rootScope.broadcast('connection_status_change', {
|
rootScope.dispatchEvent('connection_status_change', {
|
||||||
dcId: 2,
|
dcId: 2,
|
||||||
isFileDownload: false,
|
isFileDownload: false,
|
||||||
isFileNetworker: false,
|
isFileNetworker: false,
|
||||||
isFileUpload: false,
|
isFileUpload: false,
|
||||||
name: "NET-2",
|
name: "NET-2",
|
||||||
online: bool = !bool,
|
status: bool ? (bool = false, ConnectionStatus.Closed) : (bool = true, ConnectionStatus.Connected),
|
||||||
_: "networkerStatus"
|
_: "networkerStatus"
|
||||||
});
|
});
|
||||||
}); */
|
}); */
|
||||||
@ -101,34 +105,61 @@ export default class ConnectionStatusComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const status = rootScope.connectionStatus['NET-' + baseDcId];
|
const status = rootScope.connectionStatus['NET-' + baseDcId];
|
||||||
const online = status && status.online;
|
const online = status && status.status === ConnectionStatus.Connected;
|
||||||
|
|
||||||
if(this.connecting && online) {
|
if(this.connecting && online) {
|
||||||
apiUpdatesManager.forceGetDifference();
|
apiUpdatesManager.forceGetDifference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(online && !this.hadConnect) {
|
||||||
|
this.hadConnect = true;
|
||||||
|
}
|
||||||
|
|
||||||
this.connecting = !online;
|
this.connecting = !online;
|
||||||
this.connectingTimeout = status && status.timeout;
|
this.retryAt = status && status.retryAt;
|
||||||
DEBUG && this.log('connecting', this.connecting);
|
DEBUG && this.log('connecting', this.connecting);
|
||||||
this.setState();
|
this.setState();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
private setStatusText = (langPackKey: LangPackKey) => {
|
private setStatusText = (langPackKey: LangPackKey, args?: any[]) => {
|
||||||
if(this.currentLangPackKey === langPackKey) return;
|
if(this.currentLangPackKey === langPackKey) return;
|
||||||
this.currentLangPackKey = langPackKey;
|
this.currentLangPackKey = langPackKey;
|
||||||
replaceContent(this.statusEl, i18n(langPackKey));
|
replaceContent(this.statusEl, i18n(langPackKey, args));
|
||||||
this.statusPreloader.attach(this.statusEl);
|
this.statusPreloader.attach(this.statusEl);
|
||||||
};
|
};
|
||||||
|
|
||||||
private setState = () => {
|
private setState = () => {
|
||||||
const timeout = ConnectionStatusComponent.CHANGE_STATE_DELAY;
|
const timeout = ConnectionStatusComponent.CHANGE_STATE_DELAY;
|
||||||
if(this.connecting) {
|
if(this.connecting) {
|
||||||
// if(this.connectingTimeout) {
|
if(this.hadConnect) {
|
||||||
// this.setStatusText('ConnectionStatus.Reconnect');
|
if(this.retryAt !== undefined) {
|
||||||
// } else {
|
const timerSpan = document.createElement('span');
|
||||||
|
const retryAt = this.retryAt;
|
||||||
|
const setTime = () => {
|
||||||
|
const now = Date.now();
|
||||||
|
timerSpan.innerText = '' + Math.round((retryAt - now) / 1000);
|
||||||
|
if(now > retryAt) {
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
setTime();
|
||||||
|
const interval = setInterval(setTime, 1e3);
|
||||||
|
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.classList.add('force-reconnect');
|
||||||
|
a.append(i18n('ConnectionStatus.Reconnect'));
|
||||||
|
a.addEventListener('click', (e) => {
|
||||||
|
cancelEvent(e);
|
||||||
|
apiManager.forceReconnect();
|
||||||
|
});
|
||||||
|
this.setStatusText('ConnectionStatus.ReconnectIn', [timerSpan, a]);
|
||||||
|
} else {
|
||||||
|
this.setStatusText('ConnectionStatus.Reconnecting');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
this.setStatusText('ConnectionStatus.Waiting');
|
this.setStatusText('ConnectionStatus.Waiting');
|
||||||
// }
|
}
|
||||||
} else if(this.updating) {
|
} else if(this.updating) {
|
||||||
this.setStatusText('Updating');
|
this.setStatusText('Updating');
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ const App = {
|
|||||||
id: 1025907,
|
id: 1025907,
|
||||||
hash: '452b0359b988148995f22ff0f4229750',
|
hash: '452b0359b988148995f22ff0f4229750',
|
||||||
version: '0.5.7',
|
version: '0.5.7',
|
||||||
langPackVersion: '0.2.3',
|
langPackVersion: '0.2.4',
|
||||||
langPack: 'macos',
|
langPack: 'macos',
|
||||||
langPackCode: 'en',
|
langPackCode: 'en',
|
||||||
domains: [] as string[],
|
domains: [] as string[],
|
||||||
|
@ -47,6 +47,7 @@ const lang = {
|
|||||||
"ChatList.Menu.SwitchTo.Z": "Switch to Z version",
|
"ChatList.Menu.SwitchTo.Z": "Switch to Z version",
|
||||||
"ConnectionStatus.ReconnectIn": "Reconnect in %ds, %s",
|
"ConnectionStatus.ReconnectIn": "Reconnect in %ds, %s",
|
||||||
"ConnectionStatus.Reconnect": "reconnect",
|
"ConnectionStatus.Reconnect": "reconnect",
|
||||||
|
"ConnectionStatus.Reconnecting": "Reconnecting...",
|
||||||
"ConnectionStatus.Waiting": "Waiting for network...",
|
"ConnectionStatus.Waiting": "Waiting for network...",
|
||||||
"Deactivated.Title": "Too many tabs...",
|
"Deactivated.Title": "Too many tabs...",
|
||||||
"Deactivated.Subtitle": "Telegram supports only one active tab with the app.\nClick anywhere to continue using this tab.",
|
"Deactivated.Subtitle": "Telegram supports only one active tab with the app.\nClick anywhere to continue using this tab.",
|
||||||
|
22
src/lib/mtproto/connectionStatus.ts
Normal file
22
src/lib/mtproto/connectionStatus.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
export enum ConnectionStatus {
|
||||||
|
Connected,
|
||||||
|
Connecting,
|
||||||
|
Closed
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ConnectionStatusChange = {
|
||||||
|
_: 'networkerStatus',
|
||||||
|
status: ConnectionStatus,
|
||||||
|
dcId: number,
|
||||||
|
name: string,
|
||||||
|
isFileNetworker: boolean,
|
||||||
|
isFileDownload: boolean,
|
||||||
|
isFileUpload: boolean,
|
||||||
|
retryAt?: number
|
||||||
|
};
|
@ -189,7 +189,7 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
|
|||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('online', (event) => {
|
window.addEventListener('online', (event) => {
|
||||||
this.postMessage({type: 'online'});
|
this.forceReconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
/// #if !MTPROTO_SW
|
/// #if !MTPROTO_SW
|
||||||
@ -543,6 +543,10 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
|
|||||||
public startAll() {
|
public startAll() {
|
||||||
return this.performTaskWorkerVoid('startAll');
|
return this.performTaskWorkerVoid('startAll');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public forceReconnect() {
|
||||||
|
this.postMessage({type: 'online'});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiManagerProxy = new ApiManagerProxy();
|
const apiManagerProxy = new ApiManagerProxy();
|
||||||
|
@ -33,6 +33,7 @@ import HTTP from './transports/http';
|
|||||||
import type TcpObfuscated from './transports/tcpObfuscated';
|
import type TcpObfuscated from './transports/tcpObfuscated';
|
||||||
import { bigInt2str, rightShift_, str2bigInt } from '../../vendor/leemon';
|
import { bigInt2str, rightShift_, str2bigInt } from '../../vendor/leemon';
|
||||||
import { forEachReverse } from '../../helpers/array';
|
import { forEachReverse } from '../../helpers/array';
|
||||||
|
import { ConnectionStatus } from './connectionStatus';
|
||||||
|
|
||||||
//console.error('networker included!', new Error().stack);
|
//console.error('networker included!', new Error().stack);
|
||||||
|
|
||||||
@ -121,6 +122,7 @@ export default class MTPNetworker {
|
|||||||
private log: ReturnType<typeof logger>;
|
private log: ReturnType<typeof logger>;
|
||||||
|
|
||||||
public isOnline = false;
|
public isOnline = false;
|
||||||
|
public status: ConnectionStatus = ConnectionStatus.Closed;
|
||||||
private lastResponseTime = 0;
|
private lastResponseTime = 0;
|
||||||
|
|
||||||
private debug = DEBUG /* && false */ || Modes.debug;
|
private debug = DEBUG /* && false */ || Modes.debug;
|
||||||
@ -190,7 +192,7 @@ export default class MTPNetworker {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
if((this.transport as TcpObfuscated).connected) {
|
if((this.transport as TcpObfuscated).connected) {
|
||||||
this.setConnectionStatus(true);
|
this.setConnectionStatus(ConnectionStatus.Connected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -694,7 +696,7 @@ export default class MTPNetworker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.log.error('timeout', message);
|
this.log.error('timeout', message);
|
||||||
this.setConnectionStatus(false);
|
this.setConnectionStatus(ConnectionStatus.Closed);
|
||||||
|
|
||||||
/* this.getEncryptedOutput(message).then(bytes => {
|
/* this.getEncryptedOutput(message).then(bytes => {
|
||||||
this.log.error('timeout encrypted', bytes);
|
this.log.error('timeout encrypted', bytes);
|
||||||
@ -703,7 +705,7 @@ export default class MTPNetworker {
|
|||||||
|
|
||||||
promise.finally(() => {
|
promise.finally(() => {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
this.setConnectionStatus(true);
|
this.setConnectionStatus(ConnectionStatus.Connected);
|
||||||
|
|
||||||
if(!--this.activeRequests && this.onDrain) {
|
if(!--this.activeRequests && this.onDrain) {
|
||||||
this.onDrainTimeout = self.setTimeout(() => {
|
this.onDrainTimeout = self.setTimeout(() => {
|
||||||
@ -722,21 +724,23 @@ export default class MTPNetworker {
|
|||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConnectionStatus(online: boolean, timeout?: number) {
|
public setConnectionStatus(status: ConnectionStatus, retryAt?: number) {
|
||||||
const willChange = this.isOnline !== online;
|
const isOnline = status === ConnectionStatus.Connected;
|
||||||
this.isOnline = online;
|
const willChange = this.status !== status;
|
||||||
|
this.isOnline = isOnline;
|
||||||
|
this.status = status;
|
||||||
|
|
||||||
if(willChange) {
|
if(willChange) {
|
||||||
if(networkerFactory.onConnectionStatusChange) {
|
if(networkerFactory.onConnectionStatusChange) {
|
||||||
networkerFactory.onConnectionStatusChange({
|
networkerFactory.onConnectionStatusChange({
|
||||||
_: 'networkerStatus',
|
_: 'networkerStatus',
|
||||||
online: this.isOnline,
|
status,
|
||||||
dcId: this.dcId,
|
dcId: this.dcId,
|
||||||
name: this.name,
|
name: this.name,
|
||||||
isFileNetworker: this.isFileNetworker,
|
isFileNetworker: this.isFileNetworker,
|
||||||
isFileDownload: this.isFileDownload,
|
isFileDownload: this.isFileDownload,
|
||||||
isFileUpload: this.isFileUpload,
|
isFileUpload: this.isFileUpload,
|
||||||
timeout
|
retryAt
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,9 @@
|
|||||||
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { ConnectionStatusChange } from "./connectionStatus";
|
||||||
import MTPNetworker from "./networker";
|
import MTPNetworker from "./networker";
|
||||||
import { ConnectionStatusChange, InvokeApiOptions } from "../../types";
|
import { InvokeApiOptions } from "../../types";
|
||||||
import MTTransport from "./transports/transport";
|
import MTTransport from "./transports/transport";
|
||||||
import App from "../../config/app";
|
import App from "../../config/app";
|
||||||
import { MOUNT_CLASS_TO } from "../../config/debug";
|
import { MOUNT_CLASS_TO } from "../../config/debug";
|
||||||
|
@ -10,6 +10,7 @@ import MTPNetworker from "../networker";
|
|||||||
import Obfuscation from "./obfuscation";
|
import Obfuscation from "./obfuscation";
|
||||||
import MTTransport, { MTConnection, MTConnectionConstructable } from "./transport";
|
import MTTransport, { MTConnection, MTConnectionConstructable } from "./transport";
|
||||||
import intermediatePacketCodec from './intermediate';
|
import intermediatePacketCodec from './intermediate';
|
||||||
|
import { ConnectionStatus } from "../connectionStatus";
|
||||||
|
|
||||||
export default class TcpObfuscated implements MTTransport {
|
export default class TcpObfuscated implements MTTransport {
|
||||||
private codec = intermediatePacketCodec;
|
private codec = intermediatePacketCodec;
|
||||||
@ -58,7 +59,7 @@ export default class TcpObfuscated implements MTTransport {
|
|||||||
|
|
||||||
if(this.networker) {
|
if(this.networker) {
|
||||||
this.pending.length = 0; // ! clear queue and reformat messages to container, because if sending simultaneously 10+ messages, connection will die
|
this.pending.length = 0; // ! clear queue and reformat messages to container, because if sending simultaneously 10+ messages, connection will die
|
||||||
this.networker.setConnectionStatus(true);
|
this.networker.setConnectionStatus(ConnectionStatus.Connected);
|
||||||
this.networker.cleanupSent();
|
this.networker.cleanupSent();
|
||||||
this.networker.resend();
|
this.networker.resend();
|
||||||
} else {
|
} else {
|
||||||
@ -113,15 +114,16 @@ export default class TcpObfuscated implements MTTransport {
|
|||||||
private onClose = () => {
|
private onClose = () => {
|
||||||
this.clear();
|
this.clear();
|
||||||
|
|
||||||
let needTimeout: number;
|
let needTimeout: number, retryAt: number;
|
||||||
if(this.autoReconnect) {
|
if(this.autoReconnect) {
|
||||||
const time = Date.now();
|
const time = Date.now();
|
||||||
const diff = time - this.lastCloseTime;
|
const diff = time - this.lastCloseTime;
|
||||||
needTimeout = !isNaN(diff) && diff < this.retryTimeout ? this.retryTimeout - diff : 0;
|
needTimeout = !isNaN(diff) && diff < this.retryTimeout ? this.retryTimeout - diff : 0;
|
||||||
|
retryAt = time + needTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.networker) {
|
if(this.networker) {
|
||||||
this.networker.setConnectionStatus(false, needTimeout);
|
this.networker.setConnectionStatus(ConnectionStatus.Closed, retryAt);
|
||||||
this.pending.length = 0;
|
this.pending.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,6 +170,7 @@ export default class TcpObfuscated implements MTTransport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.networker.setConnectionStatus(ConnectionStatus.Connecting);
|
||||||
this.connect();
|
this.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import type { MyDocument } from "./appManagers/appDocsManager";
|
|||||||
import type { AppMessagesManager, Dialog, MessagesStorage } from "./appManagers/appMessagesManager";
|
import type { AppMessagesManager, Dialog, MessagesStorage } from "./appManagers/appMessagesManager";
|
||||||
import type { Poll, PollResults } from "./appManagers/appPollsManager";
|
import type { Poll, PollResults } from "./appManagers/appPollsManager";
|
||||||
import type { MyDialogFilter } from "./storages/filters";
|
import type { MyDialogFilter } from "./storages/filters";
|
||||||
import type { ConnectionStatusChange } from "../types";
|
|
||||||
import type { UserTyping } from "./appManagers/appProfileManager";
|
import type { UserTyping } from "./appManagers/appProfileManager";
|
||||||
import type Chat from "../components/chat/chat";
|
import type Chat from "../components/chat/chat";
|
||||||
import type { UserAuth } from "./mtproto/mtproto_config";
|
import type { UserAuth } from "./mtproto/mtproto_config";
|
||||||
@ -17,6 +16,7 @@ import type { State, Theme } from "./appManagers/appStateManager";
|
|||||||
import type { MyDraftMessage } from "./appManagers/appDraftsManager";
|
import type { MyDraftMessage } from "./appManagers/appDraftsManager";
|
||||||
import type { PushSubscriptionNotify } from "./mtproto/webPushApiManager";
|
import type { PushSubscriptionNotify } from "./mtproto/webPushApiManager";
|
||||||
import type { PushNotificationObject } from "./serviceWorker/push";
|
import type { PushNotificationObject } from "./serviceWorker/push";
|
||||||
|
import type { ConnectionStatusChange } from "./mtproto/connectionStatus";
|
||||||
import EventListenerBase from "../helpers/eventListenerBase";
|
import EventListenerBase from "../helpers/eventListenerBase";
|
||||||
import { MOUNT_CLASS_TO } from "../config/debug";
|
import { MOUNT_CLASS_TO } from "../config/debug";
|
||||||
|
|
||||||
|
@ -442,11 +442,17 @@
|
|||||||
&-button {
|
&-button {
|
||||||
color: #2e3939;
|
color: #2e3939;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
pointer-events: none;
|
cursor: default;
|
||||||
padding-left: 4.5rem;
|
padding-left: 4.5rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
height: 3.5rem;
|
height: 3.5rem;
|
||||||
|
|
||||||
|
.force-reconnect {
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: underline;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
transform: translateY(-100%);
|
transform: translateY(-100%);
|
||||||
|
|
||||||
.preloader-container {
|
.preloader-container {
|
||||||
@ -468,6 +474,7 @@
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background-color: var(--surface-color);
|
||||||
|
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -557,7 +557,7 @@ input:-webkit-autofill:active {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bg-warning {
|
.bg-warning {
|
||||||
background: #fed85a;
|
background: #fed85a !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contextmenu {
|
.contextmenu {
|
||||||
|
11
src/types.d.ts
vendored
11
src/types.d.ts
vendored
@ -79,14 +79,3 @@ export namespace AuthState {
|
|||||||
_: 'authStateSignedIn'
|
_: 'authStateSignedIn'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ConnectionStatusChange = {
|
|
||||||
_: 'networkerStatus',
|
|
||||||
online: boolean,
|
|
||||||
dcId: number,
|
|
||||||
name: string,
|
|
||||||
isFileNetworker: boolean,
|
|
||||||
isFileDownload: boolean,
|
|
||||||
isFileUpload: boolean,
|
|
||||||
timeout?: number
|
|
||||||
};
|
|
||||||
|
Loading…
Reference in New Issue
Block a user