From 9e366e1123eecbfca52368ef15d0cd02f3d2b368 Mon Sep 17 00:00:00 2001 From: Tremendous Stimulus <295218925+tremendous-stimulus@users.noreply.github.com> Date: Wed, 24 Jun 2026 00:13:55 +0300 Subject: [PATCH] =?UTF-8?q?feat(ios):=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D0=B9=20=D1=81=D1=82=D0=B0=D1=82=D1=83=D1=81?= =?UTF-8?q?=20captcha=20+=20=D0=BF=D0=B0=D1=83=D0=B7=D0=B0=20watchdog=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B2=D1=80=D0=B5=D0=BC=D1=8F=20=D1=80=D0=B5?= =?UTF-8?q?=D1=88=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Пока пользователь решает captcha вручную, поднимаем сессионный captchaActive: watchdog не считает подключение зависшим (двигает дедлайн) и отдаёт StateCaptcha вместо connecting, чтобы UI не показывал ошибку. --- ios/mobile.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/ios/mobile.go b/ios/mobile.go index 651be95..f7438fa 100644 --- a/ios/mobile.go +++ b/ios/mobile.go @@ -28,6 +28,9 @@ const ( StateConnecting = "connecting" StateConnected = "connected" StateError = "error" + // StateCaptcha — пользователь решает captcha вручную. Отдельный статус, чтобы + // UI не показывал ошибку, а watchdog не считал это зависшим подключением. + StateCaptcha = "captcha" ) // Snapshot — единый консистентный снимок состояния сессии для UI: и стадия @@ -196,9 +199,16 @@ func Start(link, peer, dns, listen, transport, obfKey string) error { // Если приложение зарегистрировало презентер — включаем ручной fallback // captcha (авто-решатель пробуется первым, при провале показываем WebView). // Без презентера solver == nil: при captcha-блоке поток упадёт, как раньше. + // + // captchaActive (сессионный) поднимается на время ручного решения: пока он + // true, watchdog не считает подключение зависшим и UI показывает StateCaptcha. + var captchaActive atomic.Bool var solver vk.ManualSolverFunc if p := currentCaptchaPresenter(); p != nil { - solver = vk.IOSManualSolver(p.Show, p.Hide) + solver = vk.IOSManualSolver( + func(url string) { captchaActive.Store(true); p.Show(url) }, + func() { captchaActive.Store(false); p.Hide() }, + ) } prov, err := vk.New(vk.Config{ @@ -261,6 +271,16 @@ func Start(link, peer, dns, listen, transport, obfKey string) error { if n > 0 { everConnected = true } + + // Пока пользователь решает captcha — таймаут на паузу (двигаем + // дедлайн вперёд, чтобы после решения дать свежее окно) и + // показываем отдельный статус вместо «зависшего» connecting. + if captchaActive.Load() { + deadline = time.Now().Add(connectTimeout) + setStatus(&statusInfo{state: StateCaptcha, streams: int(n), total: cfg.TURN.N}) + continue + } + state := StateConnecting if n > 0 { state = StateConnected