diff --git a/src/app/components/telegram-login/telegram-login.component.ts b/src/app/components/telegram-login/telegram-login.component.ts index 2d6380b..f500bfa 100644 --- a/src/app/components/telegram-login/telegram-login.component.ts +++ b/src/app/components/telegram-login/telegram-login.component.ts @@ -23,6 +23,7 @@ export class TelegramLoginComponent implements OnDestroy { private readonly pollIntervalMs = 5000; private pollTimer?: ReturnType; + private telegramFallbackTimer?: ReturnType; private readonly handleVisibilityChange = () => { if (typeof document !== 'undefined' && document.visibilityState === 'visible') { this.checkLoginAfterReturn(); @@ -41,6 +42,7 @@ export class TelegramLoginComponent implements OnDestroy { this.initQrLogin(); } else { this.awaitingTelegramReturn.set(false); + this.clearTelegramFallback(); this.stopPolling(); } }); @@ -54,6 +56,7 @@ export class TelegramLoginComponent implements OnDestroy { ngOnDestroy(): void { this.awaitingTelegramReturn.set(false); + this.clearTelegramFallback(); this.stopPolling(); if (typeof window !== 'undefined') { @@ -65,6 +68,7 @@ export class TelegramLoginComponent implements OnDestroy { close(): void { this.awaitingTelegramReturn.set(false); + this.clearTelegramFallback(); this.authService.hideLogin(); this.stopPolling(); } @@ -78,23 +82,39 @@ export class TelegramLoginComponent implements OnDestroy { this.startPolling(webSessionID); } + const appUrl = this.authService.getTelegramAppLoginUrl(webSessionID); + this.awaitingTelegramReturn.set(true); + this.clearTelegramFallback(); + if (this.isMobileBrowser()) { - this.awaitingTelegramReturn.set(true); - window.location.href = this.authService.getTelegramAppLoginUrl(webSessionID); + window.location.href = appUrl; return; } - window.open(url, '_blank', 'noopener,noreferrer'); + this.openExternalApp(appUrl); + this.telegramFallbackTimer = window.setTimeout(() => { + if (!this.showDialog() || !this.awaitingTelegramReturn()) { + return; + } + + if (typeof document !== 'undefined' && (!document.hasFocus() || document.visibilityState === 'hidden')) { + return; + } + + window.open(url, '_blank', 'noopener,noreferrer'); + }, 1200); } refreshQr(): void { this.awaitingTelegramReturn.set(false); + this.clearTelegramFallback(); this.stopPolling(); this.initQrLogin(); } private initQrLogin(): void { this.awaitingTelegramReturn.set(false); + this.clearTelegramFallback(); this.qrStatus.set('loading'); this.loginUrl.set(''); this.webSessionID.set(''); @@ -129,6 +149,7 @@ export class TelegramLoginComponent implements OnDestroy { next: (session) => { if (session?.active) { this.awaitingTelegramReturn.set(false); + this.clearTelegramFallback(); this.stopPolling(); this.authService.onTelegramLoginComplete(); } @@ -147,6 +168,13 @@ export class TelegramLoginComponent implements OnDestroy { } } + private clearTelegramFallback(): void { + if (this.telegramFallbackTimer) { + clearTimeout(this.telegramFallbackTimer); + this.telegramFallbackTimer = undefined; + } + } + private checkLoginAfterReturn(): void { if (!this.showDialog() || !this.awaitingTelegramReturn()) { return; @@ -165,12 +193,27 @@ export class TelegramLoginComponent implements OnDestroy { this.authService.checkSessionOnce(webSessionID).subscribe(session => { if (session?.active) { this.awaitingTelegramReturn.set(false); + this.clearTelegramFallback(); this.stopPolling(); this.authService.onTelegramLoginComplete(); } }); } + private openExternalApp(url: string): void { + if (typeof document === 'undefined') { + window.location.href = url; + return; + } + + const anchor = document.createElement('a'); + anchor.href = url; + anchor.style.display = 'none'; + document.body.appendChild(anchor); + anchor.click(); + anchor.remove(); + } + private isMobileBrowser(): boolean { if (typeof navigator === 'undefined') { return false;