feat: relay health check on Watch Together screen

This commit is contained in:
edde746
2026-02-10 22:38:47 +01:00
parent 6e9b78e5b5
commit df844757ec
21 changed files with 90 additions and 11 deletions
+2 -1
View File
@@ -643,7 +643,8 @@
"joinInstructions": "Gib den vom Host geteilten Sitzungscode ein, um seiner Schausitzung beizutreten.",
"failedToCreate": "Sitzung konnte nicht erstellt werden",
"failedToJoin": "Sitzung konnte nicht beigetreten werden",
"sessionCodeCopied": "Sitzungscode in Zwischenablage kopiert"
"sessionCodeCopied": "Sitzungscode in Zwischenablage kopiert",
"relayUnreachable": "Der Relay-Server ist nicht erreichbar. Möglicherweise blockiert dein Internetanbieter die Verbindung. Du kannst es trotzdem versuchen, aber Watch Together funktioniert eventuell nicht."
},
"shaders": {
"title": "Shader",
+2 -1
View File
@@ -623,7 +623,8 @@
"joinInstructions": "Enter the session code shared by the host to join their watch session.",
"failedToCreate": "Failed to create session",
"failedToJoin": "Failed to join session",
"sessionCodeCopied": "Session code copied to clipboard"
"sessionCodeCopied": "Session code copied to clipboard",
"relayUnreachable": "The relay server is unreachable. This may be caused by your ISP blocking the connection. You can still try, but Watch Together may not work."
},
"downloads": {
"title": "Downloads",
+2 -1
View File
@@ -623,7 +623,8 @@
"joinInstructions": "Introduce el código de sesión compartido por el anfitrión para unirte a su sesión.",
"failedToCreate": "Error al crear la sesión",
"failedToJoin": "Error al unirse a la sesión",
"sessionCodeCopied": "Código de sesión copiado al portapapeles"
"sessionCodeCopied": "Código de sesión copiado al portapapeles",
"relayUnreachable": "El servidor de retransmisión no está disponible. Esto puede deberse a que tu proveedor de internet bloquea la conexión. Puedes intentarlo de todos modos, pero Watch Together podría no funcionar."
},
"downloads": {
"title": "Descargas",
+2 -1
View File
@@ -623,7 +623,8 @@
"joinInstructions": "Entrez le code de session partagé par l'hôte pour rejoindre sa session de visionnage.",
"failedToCreate": "Échec de la création de la session",
"failedToJoin": "Échec de la connexion à la session",
"sessionCodeCopied": "Code de session copié dans le presse-papiers"
"sessionCodeCopied": "Code de session copié dans le presse-papiers",
"relayUnreachable": "Le serveur relais est inaccessible. Cela peut être dû au blocage de la connexion par votre fournisseur d'accès. Vous pouvez quand même essayer, mais Watch Together pourrait ne pas fonctionner."
},
"downloads": {
"title": "Téléchargements",
+2 -1
View File
@@ -643,7 +643,8 @@
"joinInstructions": "Inserisci il codice sessione condiviso dall'host per unirti alla loro sessione di visione.",
"failedToCreate": "Impossibile creare la sessione",
"failedToJoin": "Impossibile unirsi alla sessione",
"sessionCodeCopied": "Codice sessione copiato negli appunti"
"sessionCodeCopied": "Codice sessione copiato negli appunti",
"relayUnreachable": "Il server di inoltro non è raggiungibile. Questo potrebbe essere causato dal blocco della connessione da parte del tuo provider. Puoi comunque provare, ma Watch Together potrebbe non funzionare."
},
"shaders": {
"title": "Shader",
+2 -1
View File
@@ -623,7 +623,8 @@
"joinInstructions": "호스트가 공유한 세션 코드를 입력하여 시청 세션에 참여하세요.",
"failedToCreate": "세션 생성 실패",
"failedToJoin": "세션 참여 실패",
"sessionCodeCopied": "세션 코드가 클립보드에 복사되었습니다"
"sessionCodeCopied": "세션 코드가 클립보드에 복사되었습니다",
"relayUnreachable": "릴레이 서버에 연결할 수 없습니다. 인터넷 제공업체가 연결을 차단하고 있을 수 있습니다. 시도해 볼 수 있지만 함께 보기가 작동하지 않을 수 있습니다."
},
"downloads": {
"title": "다운로드",
+2 -1
View File
@@ -643,7 +643,8 @@
"joinInstructions": "Voer de sessiecode in die door de host is gedeeld om deel te nemen aan hun kijksessie.",
"failedToCreate": "Sessie maken mislukt",
"failedToJoin": "Sessie deelnemen mislukt",
"sessionCodeCopied": "Sessiecode gekopieerd naar klembord"
"sessionCodeCopied": "Sessiecode gekopieerd naar klembord",
"relayUnreachable": "De relayserver is niet bereikbaar. Dit kan worden veroorzaakt doordat je internetprovider de verbinding blokkeert. Je kunt het toch proberen, maar Watch Together werkt mogelijk niet."
},
"shaders": {
"title": "Shaders",
+2 -2
View File
@@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 9
/// Strings: 6048 (672 per locale)
/// Strings: 6057 (673 per locale)
///
/// Built on 2026-02-10 at 20:34 UTC
/// Built on 2026-02-10 at 21:37 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import
+2
View File
@@ -904,6 +904,7 @@ class _TranslationsWatchTogetherDe implements TranslationsWatchTogetherEn {
@override String get failedToCreate => 'Sitzung konnte nicht erstellt werden';
@override String get failedToJoin => 'Sitzung konnte nicht beigetreten werden';
@override String get sessionCodeCopied => 'Sitzungscode in Zwischenablage kopiert';
@override String get relayUnreachable => 'Der Relay-Server ist nicht erreichbar. Möglicherweise blockiert dein Internetanbieter die Verbindung. Du kannst es trotzdem versuchen, aber Watch Together funktioniert eventuell nicht.';
}
// Path: shaders
@@ -1715,6 +1716,7 @@ extension on TranslationsDe {
'watchTogether.failedToCreate' => 'Sitzung konnte nicht erstellt werden',
'watchTogether.failedToJoin' => 'Sitzung konnte nicht beigetreten werden',
'watchTogether.sessionCodeCopied' => 'Sitzungscode in Zwischenablage kopiert',
'watchTogether.relayUnreachable' => 'Der Relay-Server ist nicht erreichbar. Möglicherweise blockiert dein Internetanbieter die Verbindung. Du kannst es trotzdem versuchen, aber Watch Together funktioniert eventuell nicht.',
'shaders.title' => 'Shader',
'shaders.noShaderDescription' => 'Keine Videoverbesserung',
'shaders.nvscalerDescription' => 'NVIDIA-Bildskalierung für schärferes Video',
+4
View File
@@ -1927,6 +1927,9 @@ class TranslationsWatchTogetherEn {
/// en: 'Session code copied to clipboard'
String get sessionCodeCopied => 'Session code copied to clipboard';
/// en: 'The relay server is unreachable. This may be caused by your ISP blocking the connection. You can still try, but Watch Together may not work.'
String get relayUnreachable => 'The relay server is unreachable. This may be caused by your ISP blocking the connection. You can still try, but Watch Together may not work.';
}
// Path: downloads
@@ -3048,6 +3051,7 @@ extension on Translations {
'watchTogether.failedToCreate' => 'Failed to create session',
'watchTogether.failedToJoin' => 'Failed to join session',
'watchTogether.sessionCodeCopied' => 'Session code copied to clipboard',
'watchTogether.relayUnreachable' => 'The relay server is unreachable. This may be caused by your ISP blocking the connection. You can still try, but Watch Together may not work.',
'downloads.title' => 'Downloads',
'downloads.manage' => 'Manage',
'downloads.tvShows' => 'TV Shows',
+2
View File
@@ -877,6 +877,7 @@ class _TranslationsWatchTogetherEs implements TranslationsWatchTogetherEn {
@override String get failedToCreate => 'Error al crear la sesión';
@override String get failedToJoin => 'Error al unirse a la sesión';
@override String get sessionCodeCopied => 'Código de sesión copiado al portapapeles';
@override String get relayUnreachable => 'El servidor de retransmisión no está disponible. Esto puede deberse a que tu proveedor de internet bloquea la conexión. Puedes intentarlo de todos modos, pero Watch Together podría no funcionar.';
}
// Path: downloads
@@ -1697,6 +1698,7 @@ extension on TranslationsEs {
'watchTogether.failedToCreate' => 'Error al crear la sesión',
'watchTogether.failedToJoin' => 'Error al unirse a la sesión',
'watchTogether.sessionCodeCopied' => 'Código de sesión copiado al portapapeles',
'watchTogether.relayUnreachable' => 'El servidor de retransmisión no está disponible. Esto puede deberse a que tu proveedor de internet bloquea la conexión. Puedes intentarlo de todos modos, pero Watch Together podría no funcionar.',
'downloads.title' => 'Descargas',
'downloads.manage' => 'Gestionar',
'downloads.tvShows' => 'Series de TV',
+2
View File
@@ -877,6 +877,7 @@ class _TranslationsWatchTogetherFr implements TranslationsWatchTogetherEn {
@override String get failedToCreate => 'Échec de la création de la session';
@override String get failedToJoin => 'Échec de la connexion à la session';
@override String get sessionCodeCopied => 'Code de session copié dans le presse-papiers';
@override String get relayUnreachable => 'Le serveur relais est inaccessible. Cela peut être dû au blocage de la connexion par votre fournisseur d\'accès. Vous pouvez quand même essayer, mais Watch Together pourrait ne pas fonctionner.';
}
// Path: downloads
@@ -1697,6 +1698,7 @@ extension on TranslationsFr {
'watchTogether.failedToCreate' => 'Échec de la création de la session',
'watchTogether.failedToJoin' => 'Échec de la connexion à la session',
'watchTogether.sessionCodeCopied' => 'Code de session copié dans le presse-papiers',
'watchTogether.relayUnreachable' => 'Le serveur relais est inaccessible. Cela peut être dû au blocage de la connexion par votre fournisseur d\'accès. Vous pouvez quand même essayer, mais Watch Together pourrait ne pas fonctionner.',
'downloads.title' => 'Téléchargements',
'downloads.manage' => 'Gérer',
'downloads.tvShows' => 'Show TV',
+2
View File
@@ -904,6 +904,7 @@ class _TranslationsWatchTogetherIt implements TranslationsWatchTogetherEn {
@override String get failedToCreate => 'Impossibile creare la sessione';
@override String get failedToJoin => 'Impossibile unirsi alla sessione';
@override String get sessionCodeCopied => 'Codice sessione copiato negli appunti';
@override String get relayUnreachable => 'Il server di inoltro non è raggiungibile. Questo potrebbe essere causato dal blocco della connessione da parte del tuo provider. Puoi comunque provare, ma Watch Together potrebbe non funzionare.';
}
// Path: shaders
@@ -1715,6 +1716,7 @@ extension on TranslationsIt {
'watchTogether.failedToCreate' => 'Impossibile creare la sessione',
'watchTogether.failedToJoin' => 'Impossibile unirsi alla sessione',
'watchTogether.sessionCodeCopied' => 'Codice sessione copiato negli appunti',
'watchTogether.relayUnreachable' => 'Il server di inoltro non è raggiungibile. Questo potrebbe essere causato dal blocco della connessione da parte del tuo provider. Puoi comunque provare, ma Watch Together potrebbe non funzionare.',
'shaders.title' => 'Shader',
'shaders.noShaderDescription' => 'Nessun miglioramento video',
'shaders.nvscalerDescription' => 'Ridimensionamento NVIDIA per video più nitido',
+2
View File
@@ -877,6 +877,7 @@ class _TranslationsWatchTogetherKo implements TranslationsWatchTogetherEn {
@override String get failedToCreate => '세션 생성 실패';
@override String get failedToJoin => '세션 참여 실패';
@override String get sessionCodeCopied => '세션 코드가 클립보드에 복사되었습니다';
@override String get relayUnreachable => '릴레이 서버에 연결할 수 없습니다. 인터넷 제공업체가 연결을 차단하고 있을 수 있습니다. 시도해 볼 수 있지만 함께 보기가 작동하지 않을 수 있습니다.';
}
// Path: downloads
@@ -1697,6 +1698,7 @@ extension on TranslationsKo {
'watchTogether.failedToCreate' => '세션 생성 실패',
'watchTogether.failedToJoin' => '세션 참여 실패',
'watchTogether.sessionCodeCopied' => '세션 코드가 클립보드에 복사되었습니다',
'watchTogether.relayUnreachable' => '릴레이 서버에 연결할 수 없습니다. 인터넷 제공업체가 연결을 차단하고 있을 수 있습니다. 시도해 볼 수 있지만 함께 보기가 작동하지 않을 수 있습니다.',
'downloads.title' => '다운로드',
'downloads.manage' => '관리',
'downloads.tvShows' => 'TV 프로그램',
+2
View File
@@ -904,6 +904,7 @@ class _TranslationsWatchTogetherNl implements TranslationsWatchTogetherEn {
@override String get failedToCreate => 'Sessie maken mislukt';
@override String get failedToJoin => 'Sessie deelnemen mislukt';
@override String get sessionCodeCopied => 'Sessiecode gekopieerd naar klembord';
@override String get relayUnreachable => 'De relayserver is niet bereikbaar. Dit kan worden veroorzaakt doordat je internetprovider de verbinding blokkeert. Je kunt het toch proberen, maar Watch Together werkt mogelijk niet.';
}
// Path: shaders
@@ -1715,6 +1716,7 @@ extension on TranslationsNl {
'watchTogether.failedToCreate' => 'Sessie maken mislukt',
'watchTogether.failedToJoin' => 'Sessie deelnemen mislukt',
'watchTogether.sessionCodeCopied' => 'Sessiecode gekopieerd naar klembord',
'watchTogether.relayUnreachable' => 'De relayserver is niet bereikbaar. Dit kan worden veroorzaakt doordat je internetprovider de verbinding blokkeert. Je kunt het toch proberen, maar Watch Together werkt mogelijk niet.',
'shaders.title' => 'Shaders',
'shaders.noShaderDescription' => 'Geen videoverbetering',
'shaders.nvscalerDescription' => 'NVIDIA-beeldschaling voor scherpere video',
+2
View File
@@ -904,6 +904,7 @@ class _TranslationsWatchTogetherSv implements TranslationsWatchTogetherEn {
@override String get failedToCreate => 'Det gick inte att skapa session';
@override String get failedToJoin => 'Det gick inte att gå med i session';
@override String get sessionCodeCopied => 'Sessionskod kopierad till urklipp';
@override String get relayUnreachable => 'Reläservern kan inte nås. Detta kan bero på att din internetleverantör blockerar anslutningen. Du kan fortfarande försöka, men Watch Together kanske inte fungerar.';
}
// Path: shaders
@@ -1715,6 +1716,7 @@ extension on TranslationsSv {
'watchTogether.failedToCreate' => 'Det gick inte att skapa session',
'watchTogether.failedToJoin' => 'Det gick inte att gå med i session',
'watchTogether.sessionCodeCopied' => 'Sessionskod kopierad till urklipp',
'watchTogether.relayUnreachable' => 'Reläservern kan inte nås. Detta kan bero på att din internetleverantör blockerar anslutningen. Du kan fortfarande försöka, men Watch Together kanske inte fungerar.',
'shaders.title' => 'Shaders',
'shaders.noShaderDescription' => 'Ingen videoförbättring',
'shaders.nvscalerDescription' => 'NVIDIA-bildskalning för skarpare video',
+2
View File
@@ -904,6 +904,7 @@ class _TranslationsWatchTogetherZh implements TranslationsWatchTogetherEn {
@override String get failedToCreate => '创建会话失败';
@override String get failedToJoin => '加入会话失败';
@override String get sessionCodeCopied => '会话代码已复制到剪贴板';
@override String get relayUnreachable => '无法连接到中继服务器。这可能是由于您的网络运营商屏蔽了连接。您仍然可以尝试,但一起观看功能可能无法正常使用。';
}
// Path: shaders
@@ -1715,6 +1716,7 @@ extension on TranslationsZh {
'watchTogether.failedToCreate' => '创建会话失败',
'watchTogether.failedToJoin' => '加入会话失败',
'watchTogether.sessionCodeCopied' => '会话代码已复制到剪贴板',
'watchTogether.relayUnreachable' => '无法连接到中继服务器。这可能是由于您的网络运营商屏蔽了连接。您仍然可以尝试,但一起观看功能可能无法正常使用。',
'shaders.title' => '着色器',
'shaders.noShaderDescription' => '无视频增强',
'shaders.nvscalerDescription' => 'NVIDIA 图像缩放,使视频更清晰',
+2 -1
View File
@@ -643,7 +643,8 @@
"joinInstructions": "Ange sessionskoden som delats av värden för att gå med i deras tittarsession.",
"failedToCreate": "Det gick inte att skapa session",
"failedToJoin": "Det gick inte att gå med i session",
"sessionCodeCopied": "Sessionskod kopierad till urklipp"
"sessionCodeCopied": "Sessionskod kopierad till urklipp",
"relayUnreachable": "Reläservern kan inte nås. Detta kan bero på att din internetleverantör blockerar anslutningen. Du kan fortfarande försöka, men Watch Together kanske inte fungerar."
},
"shaders": {
"title": "Shaders",
+2 -1
View File
@@ -643,7 +643,8 @@
"joinInstructions": "输入主持人分享的会话代码以加入他们的观看会话。",
"failedToCreate": "创建会话失败",
"failedToJoin": "加入会话失败",
"sessionCodeCopied": "会话代码已复制到剪贴板"
"sessionCodeCopied": "会话代码已复制到剪贴板",
"relayUnreachable": "无法连接到中继服务器。这可能是由于您的网络运营商屏蔽了连接。您仍然可以尝试,但一起观看功能可能无法正常使用。"
},
"shaders": {
"title": "着色器",
@@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:material_symbols_icons/symbols.dart';
@@ -9,6 +11,7 @@ import '../../utils/dialogs.dart';
import '../../widgets/focused_scroll_scaffold.dart';
import '../models/watch_session.dart';
import '../providers/watch_together_provider.dart';
import '../services/watch_together_peer_service.dart';
import '../widgets/join_session_dialog.dart';
/// Main screen for Watch Together functionality
@@ -71,6 +74,30 @@ class _NotInSessionView extends StatefulWidget {
class _NotInSessionViewState extends State<_NotInSessionView> {
bool _isCreating = false;
bool _isJoining = false;
bool? _healthOk;
@override
void initState() {
super.initState();
_checkHealth();
}
Future<void> _checkHealth() async {
try {
final client = HttpClient();
client.connectionTimeout = const Duration(seconds: 5);
final request = await client.getUrl(Uri.parse(WatchTogetherPeerService.healthUrl));
final response = await request.close().timeout(const Duration(seconds: 5));
final body = await response.transform(const SystemEncoding().decoder).join();
client.close();
if (!mounted) return;
setState(() => _healthOk = response.statusCode == 200 && body.trim() == 'ok');
} catch (e) {
appLogger.w('Watch Together health check failed', error: e);
if (!mounted) return;
setState(() => _healthOk = false);
}
}
@override
Widget build(BuildContext context) {
@@ -93,6 +120,27 @@ class _NotInSessionViewState extends State<_NotInSessionView> {
style: theme.textTheme.bodyLarge?.copyWith(color: theme.colorScheme.onSurfaceVariant),
textAlign: TextAlign.center,
),
if (_healthOk == false) ...[
const SizedBox(height: 24),
Card(
color: theme.colorScheme.errorContainer,
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Icon(Symbols.warning_rounded, color: theme.colorScheme.onErrorContainer),
const SizedBox(width: 12),
Expanded(
child: Text(
t.watchTogether.relayUnreachable,
style: theme.textTheme.bodySmall?.copyWith(color: theme.colorScheme.onErrorContainer),
),
),
],
),
),
),
],
const SizedBox(height: 48),
SizedBox(
width: double.infinity,
@@ -30,6 +30,8 @@ class PeerError {
/// - Sending/receiving sync messages through the relay server
/// - Reconnection on WebSocket drops
class WatchTogetherPeerService {
static const String _baseUrl = 'https://ice.plezy.app';
static String get healthUrl => '$_baseUrl/health';
static const String _relayUrl = 'wss://ice.plezy.app/relay';
WebSocketChannel? _channel;