88using Microsoft . Extensions . Localization ;
99using System . Collections . Frozen ;
1010using Microsoft . FluentUI . AspNetCore . Components ;
11+ using Microsoft . AspNetCore . Components . Authorization ;
12+ using CodeBreaker . Blazor . Client . Contracts . Services ;
1113
1214namespace CodeBreaker . Blazor . Client . Pages ;
1315
1416public partial class GamePage : IDisposable
1517{
1618 //TODO: Get Data from API
1719 private readonly FrozenDictionary < string , GameType > _gameTypes = new Dictionary < string , GameType > ( ) {
18- { "8x5" , GameType . Game8x5 } ,
19- //{ "6x4 Mini", GameType.Game6x4Mini },
2020 { "6x4" , GameType . Game6x4 } ,
21+ //{ "6x4 Mini", GameType.Game6x4Mini },
22+ { "8x5" , GameType . Game8x5 } ,
2123 { "5x5x4" , GameType . Game5x5x4 } ,
2224 } . ToFrozenDictionary ( ) ;
2325
2426 private IDisposable ? _beforeNavigationInterceptor ;
2527 private readonly System . Timers . Timer _timer = new ( TimeSpan . FromHours ( 1 ) ) ;
2628 private GameMode _gameStatus = GameMode . NotRunning ;
27- private string _name = string . Empty ;
29+ private string ? _gamerName ;
30+ private string [ ] ? _gamerNameSuggestions ;
2831 private bool _loadingGame = false ;
32+ private bool _loadingGamerNameSuggestions = false ;
2933 private bool _isGameCancelling = false ;
3034 private GameInfo ? _game ;
3135 private GameType _gameType ; // A workaround, because the GameType in GameInfo is a string.
36+ private bool _isNamePrefilled ;
37+ private PersistingComponentStateSubscription _persistingSubscription ;
38+
39+ [ Inject ] private ILogger < GamePage > Logger { get ; init ; } = default ! ;
3240
3341 [ Inject ] private IGamesClient Client { get ; init ; } = default ! ;
42+
43+ [ Inject ] private IGamerNameSuggestionClient GamerNameSuggestionClient { get ; init ; } = default ! ;
3444
3545 [ Inject ] private NavigationManager NavigationManager { get ; init ; } = default ! ;
3646
37- [ Inject ] private Microsoft . FluentUI . AspNetCore . Components . IDialogService DialogService { get ; init ; } = default ! ;
47+ [ Inject ] private IDialogService DialogService { get ; init ; } = default ! ;
3848
3949 [ Inject ] private IStringLocalizer < Resource > Loc { get ; init ; } = default ! ;
4050
51+ [ CascadingParameter ] private Task < AuthenticationState > AuthenticationStateTask { get ; set ; } = default ! ;
52+
53+ [ Inject ] private PersistentComponentState ApplicationState { get ; init ; } = default ! ;
54+
4155 private string ? SelectedGameTypeKey { get ; set ; }
4256
4357 private GameType ? SelectedGameType => SelectedGameTypeKey is null ? null : _gameTypes [ SelectedGameTypeKey ] ;
4458
45- private bool CanStartGame => ! string . IsNullOrWhiteSpace ( _name ) && _name . Length > 3 && ! _loadingGame ;
59+ private bool CanStartGame => ! string . IsNullOrWhiteSpace ( _gamerName ) && ! _loadingGame ;
4660
4761 protected override async Task OnInitializedAsync ( )
4862 {
4963 _timer . Elapsed += OnTimedEvent ;
5064 _timer . AutoReset = true ;
51- _name = string . Empty ;
65+ _persistingSubscription = ApplicationState . RegisterOnPersisting ( PersistGamerNameAsync ) ;
66+
67+ // Get gamer name from user claims (if available)
68+ _gamerName = ( await AuthenticationStateTask ) . User . FindFirst ( "extension_gamerName" ) ? . Value ;
69+ _isNamePrefilled = ! string . IsNullOrEmpty ( _gamerName ) ;
70+
71+ // Get gamer name suggestions, if not prefilled and therefore the user is not authenticated
72+ if ( ! _isNamePrefilled && ! ApplicationState . TryTakeFromJson ( nameof ( _gamerNameSuggestions ) , out _gamerNameSuggestions ) )
73+ _gamerNameSuggestions = ( await GamerNameSuggestionClient . GetGamerNameSuggestionsAsync ( ) ) . Suggestions ;
74+
75+ // Set the first suggestion as default, if there are any and therefore the user is not authenticated
76+ if ( _gamerNameSuggestions is not null )
77+ _gamerName = _gamerNameSuggestions . FirstOrDefault ( ) ;
78+
5279 await base . OnInitializedAsync ( ) ;
5380 }
5481
@@ -60,6 +87,13 @@ protected override void OnAfterRender(bool firstRender)
6087 base . OnAfterRender ( firstRender ) ;
6188 }
6289
90+ private Task PersistGamerNameAsync ( )
91+ {
92+ ApplicationState . PersistAsJson ( nameof ( _gamerName ) , _gamerName ) ;
93+ ApplicationState . PersistAsJson ( nameof ( _gamerNameSuggestions ) , _gamerNameSuggestions ) ;
94+ return Task . CompletedTask ;
95+ }
96+
6397 private async Task StartGameAsync ( )
6498 {
6599 if ( SelectedGameType is null )
@@ -69,19 +103,24 @@ private async Task StartGameAsync()
69103 {
70104 _loadingGame = true ;
71105 _gameStatus = GameMode . NotRunning ;
72- ( Guid gameId , int numberCodes , int maxMoves , IDictionary < string , string [ ] > fieldValues ) = await Client . StartGameAsync ( SelectedGameType . Value , _name ) ;
73- _game = new ( gameId , SelectedGameType . Value . ToString ( ) , _name , DateTime . Now , numberCodes , maxMoves )
106+ ( Guid gameId , int numberCodes , int maxMoves , IDictionary < string , string [ ] > fieldValues ) = await Client . StartGameAsync ( SelectedGameType . Value , _gamerName ) ;
107+ _game = new ( gameId , SelectedGameType . Value . ToString ( ) , _gamerName , DateTime . Now , numberCodes , maxMoves )
74108 {
75109 FieldValues = fieldValues . ToDictionary ( x => x . Key , x => x . Value . AsEnumerable ( ) ) ,
76110 Codes = [ ]
77111 } ;
78112 _gameType = SelectedGameType . Value ;
79113 _gameStatus = GameMode . Started ;
80114 }
115+ catch ( HttpRequestException ex )
116+ {
117+ Logger . LogError ( ex , ex . Message ) ;
118+ DialogService . ShowError ( ex . Message ) ;
119+ }
81120 catch ( Exception ex )
82121 {
83- //TODO: Handle Exception
84- Console . WriteLine ( ex . Message ) ;
122+ Logger . LogError ( ex , ex . Message ) ;
123+ throw ;
85124 }
86125 finally
87126 {
@@ -179,5 +218,6 @@ public void Dispose()
179218 {
180219 _timer ? . Dispose ( ) ;
181220 _beforeNavigationInterceptor ? . Dispose ( ) ;
221+ _persistingSubscription . Dispose ( ) ;
182222 }
183223}
0 commit comments