diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 0b3ae7eacd..a69ed89dcb 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -65,6 +65,7 @@
+
diff --git a/lib/src/app_links.dart b/lib/src/app_links.dart
index 36a9d7949d..7aa7d2bf7d 100644
--- a/lib/src/app_links.dart
+++ b/lib/src/app_links.dart
@@ -3,6 +3,7 @@ import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:flutter/widgets.dart';
import 'package:lichess_mobile/src/model/common/id.dart';
import 'package:lichess_mobile/src/model/puzzle/puzzle_angle.dart';
+import 'package:lichess_mobile/src/view/broadcast/broadcast_game_screen.dart';
import 'package:lichess_mobile/src/view/broadcast/broadcast_round_screen.dart';
import 'package:lichess_mobile/src/view/game/archived_game_screen.dart';
import 'package:lichess_mobile/src/view/puzzle/puzzle_screen.dart';
@@ -22,9 +23,15 @@ Route? resolveAppLinkUri(BuildContext context, Uri appLinkUri) {
final id = appLinkUri.pathSegments[1];
return StudyScreen.buildRoute(context, StudyId(id));
case 'broadcast':
- final id = appLinkUri.pathSegments[3];
- final tab = BroadcastRoundTab.tabOrNullFromString(appLinkUri.fragment);
- return BroadcastRoundScreenLoading.buildRoute(context, BroadcastRoundId(id), initialTab: tab);
+ final roundId = BroadcastRoundId(appLinkUri.pathSegments[3]);
+ if (appLinkUri.pathSegments.length > 4) {
+ final gameId = BroadcastGameId(appLinkUri.pathSegments[4]);
+ return BroadcastGameScreen.buildRoute(context, roundId: roundId, gameId: gameId);
+ } else {
+ final tab = BroadcastRoundTab.tabOrNullFromString(appLinkUri.fragment);
+ return BroadcastRoundScreenLoading.buildRoute(context, roundId, initialTab: tab);
+ }
+
case 'training':
final id = appLinkUri.pathSegments[1];
return PuzzleScreen.buildRoute(
diff --git a/lib/src/view/broadcast/broadcast_game_screen.dart b/lib/src/view/broadcast/broadcast_game_screen.dart
index 848a1e61c5..e75b5ebdd8 100644
--- a/lib/src/view/broadcast/broadcast_game_screen.dart
+++ b/lib/src/view/broadcast/broadcast_game_screen.dart
@@ -29,7 +29,7 @@ import 'package:lichess_mobile/src/widgets/pgn.dart';
import 'package:lichess_mobile/src/widgets/platform_scaffold.dart';
class BroadcastGameScreen extends ConsumerStatefulWidget {
- final BroadcastTournamentId tournamentId;
+ final BroadcastTournamentId? tournamentId;
final BroadcastRoundId roundId;
final BroadcastGameId gameId;
final String? tournamentSlug;
@@ -37,7 +37,7 @@ class BroadcastGameScreen extends ConsumerStatefulWidget {
final String? title;
const BroadcastGameScreen({
- required this.tournamentId,
+ this.tournamentId,
required this.roundId,
required this.gameId,
this.tournamentSlug,
@@ -47,7 +47,7 @@ class BroadcastGameScreen extends ConsumerStatefulWidget {
static Route buildRoute(
BuildContext context, {
- required BroadcastTournamentId tournamentId,
+ BroadcastTournamentId? tournamentId,
required BroadcastRoundId roundId,
required BroadcastGameId gameId,
String? tournamentSlug,
@@ -146,7 +146,7 @@ class _Body extends ConsumerWidget {
required this.tabController,
});
- final BroadcastTournamentId tournamentId;
+ final BroadcastTournamentId? tournamentId;
final BroadcastRoundId roundId;
final BroadcastGameId gameId;
final String? tournamentSlug;
@@ -379,13 +379,13 @@ enum _PlayerWidgetPosition { bottom, top }
class _PlayerWidget extends ConsumerWidget {
const _PlayerWidget({
- required this.tournamentId,
+ this.tournamentId,
required this.roundId,
required this.gameId,
required this.widgetPosition,
});
- final BroadcastTournamentId tournamentId;
+ final BroadcastTournamentId? tournamentId;
final BroadcastRoundId roundId;
final BroadcastGameId gameId;
final _PlayerWidgetPosition widgetPosition;
@@ -415,13 +415,21 @@ class _PlayerWidget extends ConsumerWidget {
return GestureDetector(
onTap: () {
Navigator.of(context).push(
- BroadcastPlayerResultsScreen.buildRoute(
- context,
- tournamentId,
- (player.fideId != null) ? player.fideId!.toString() : player.name,
- playerTitle: player.title,
- playerName: player.name,
- ),
+ (tournamentId != null)
+ ? BroadcastPlayerResultsScreen.buildRoute(
+ context,
+ tournamentId!,
+ (player.fideId != null) ? player.fideId!.toString() : player.name,
+ playerTitle: player.title,
+ playerName: player.name,
+ )
+ : BroadcastPlayerResultsScreenLoading.buildRoute(
+ context,
+ roundId,
+ (player.fideId != null) ? player.fideId!.toString() : player.name,
+ playerTitle: player.title,
+ playerName: player.name,
+ ),
);
},
child: Container(
diff --git a/lib/src/view/broadcast/broadcast_player_results_screen.dart b/lib/src/view/broadcast/broadcast_player_results_screen.dart
index f17d421c72..7c5e828165 100644
--- a/lib/src/view/broadcast/broadcast_player_results_screen.dart
+++ b/lib/src/view/broadcast/broadcast_player_results_screen.dart
@@ -12,11 +12,66 @@ import 'package:lichess_mobile/src/styles/styles.dart';
import 'package:lichess_mobile/src/utils/l10n_context.dart';
import 'package:lichess_mobile/src/utils/navigation.dart';
import 'package:lichess_mobile/src/view/broadcast/broadcast_game_screen.dart';
+import 'package:lichess_mobile/src/view/broadcast/broadcast_player_screen_providers.dart';
import 'package:lichess_mobile/src/view/broadcast/broadcast_player_widget.dart';
import 'package:lichess_mobile/src/widgets/platform_scaffold.dart';
import 'package:lichess_mobile/src/widgets/progression_widget.dart';
import 'package:lichess_mobile/src/widgets/stat_card.dart';
+class BroadcastPlayerResultsScreenLoading extends ConsumerWidget {
+ final BroadcastRoundId roundId;
+ final String playerId;
+ final String? playerTitle;
+ final String playerName;
+
+ const BroadcastPlayerResultsScreenLoading(
+ this.roundId,
+ this.playerId, {
+ required this.playerName,
+ this.playerTitle,
+ });
+
+ static Route buildRoute(
+ BuildContext context,
+ BroadcastRoundId roundId,
+ String playerId, {
+ String? playerTitle,
+ required String playerName,
+ }) {
+ return buildScreenRoute(
+ context,
+ screen: BroadcastPlayerResultsScreenLoading(
+ roundId,
+ playerId,
+ playerTitle: playerTitle,
+ playerName: playerName,
+ ),
+ );
+ }
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ final tournamentId = ref.watch(broadcastTournamentIdProvider(roundId));
+
+ return switch (tournamentId) {
+ AsyncData(:final value) => BroadcastPlayerResultsScreen(
+ value,
+ playerId,
+ playerTitle: playerTitle,
+ playerName: playerName,
+ ),
+ AsyncError(:final error) => PlatformScaffold(
+ appBarTitle: const Text(''),
+ body: Center(child: Text('Cannot load round data: $error')),
+ ),
+ _ => const PlatformScaffold(
+ appBarTitle: Text(''),
+ body: Center(child: CircularProgressIndicator.adaptive()),
+ ),
+ };
+ }
+}
+
class BroadcastPlayerResultsScreen extends StatelessWidget {
final BroadcastTournamentId tournamentId;
final String playerId;
diff --git a/lib/src/view/broadcast/broadcast_player_screen_providers.dart b/lib/src/view/broadcast/broadcast_player_screen_providers.dart
new file mode 100644
index 0000000000..c5c26c24d3
--- /dev/null
+++ b/lib/src/view/broadcast/broadcast_player_screen_providers.dart
@@ -0,0 +1,11 @@
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:lichess_mobile/src/model/broadcast/broadcast_providers.dart';
+import 'package:lichess_mobile/src/model/common/id.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+
+part 'broadcast_player_screen_providers.g.dart';
+
+@riverpod
+Future broadcastTournamentId(Ref ref, BroadcastRoundId roundId) {
+ return ref.watch(broadcastRoundProvider(roundId).selectAsync((round) => round.tournament.id));
+}