Skip to content

Commit

Permalink
More cleanup and support for error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
dend committed Jul 3, 2024
1 parent a8ea76f commit 3aa330b
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 252 deletions.
240 changes: 135 additions & 105 deletions src/OpenSpartan.Workshop/Core/UserContextManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,45 +213,53 @@ internal static bool InitializeHaloClient(AuthenticationResult authResult)
extendedTicket = await manager.RequestXstsToken(ticket.Token, false);
}).GetAwaiter().GetResult();

Task.Run(async () =>
{
haloToken = await haloAuthClient.GetSpartanToken(haloTicket.Token, 4);
}).GetAwaiter().GetResult();

if (extendedTicket != null)
if (haloTicket != null)
{
XboxUserContext = extendedTicket;

HaloClient = new(haloToken.Token, extendedTicket.DisplayClaims.Xui[0].XUID, userAgent: $"{Configuration.PackageName}/{Configuration.Version}-{Configuration.BuildId}");

Task.Run(async () =>
{
PlayerClearance? clearance = null;
haloToken = await haloAuthClient.GetSpartanToken(haloTicket.Token, 4);
}).GetAwaiter().GetResult();

if ((bool)SettingsViewModel.Instance.Settings.UseObanClearance)
{
clearance = (await SafeAPICall(async () => { return await HaloClient.SettingsActiveFlight(SettingsViewModel.Instance.Settings.Sandbox, SettingsViewModel.Instance.Settings.Build, SettingsViewModel.Instance.Settings.Release); })).Result;
}
else
{
clearance = (await SafeAPICall(async () => { return await HaloClient.SettingsActiveClearance(SettingsViewModel.Instance.Settings.Release); })).Result;
}
if (extendedTicket != null)
{
XboxUserContext = extendedTicket;

if (clearance != null && !string.IsNullOrWhiteSpace(clearance.FlightConfigurationId))
{
HaloClient.ClearanceToken = clearance.FlightConfigurationId;
LogEngine.Log($"Your clearance is {clearance.FlightConfigurationId} and it's set in the client.");
}
else
HaloClient = new(haloToken.Token, extendedTicket.DisplayClaims.Xui[0].XUID, userAgent: $"{Configuration.PackageName}/{Configuration.Version}-{Configuration.BuildId}");

Task.Run(async () =>
{
LogEngine.Log("Could not obtain the clearance.", LogSeverity.Error);
}
}).GetAwaiter().GetResult();
PlayerClearance? clearance = null;
return true;
if ((bool)SettingsViewModel.Instance.Settings.UseObanClearance)
{
clearance = (await SafeAPICall(async () => { return await HaloClient.SettingsActiveFlight(SettingsViewModel.Instance.Settings.Sandbox, SettingsViewModel.Instance.Settings.Build, SettingsViewModel.Instance.Settings.Release); })).Result;
}
else
{
clearance = (await SafeAPICall(async () => { return await HaloClient.SettingsActiveClearance(SettingsViewModel.Instance.Settings.Release); })).Result;
}
if (clearance != null && !string.IsNullOrWhiteSpace(clearance.FlightConfigurationId))
{
HaloClient.ClearanceToken = clearance.FlightConfigurationId;
LogEngine.Log($"Your clearance is {clearance.FlightConfigurationId} and it's set in the client.");
}
else
{
LogEngine.Log("Could not obtain the clearance.", LogSeverity.Error);
}
}).GetAwaiter().GetResult();

return true;
}
else
{
return false;
}
}
else
{
LogEngine.Log("Halo ticket is null. Cannot authenticate.", LogSeverity.Error);
return false;
}
}
Expand Down Expand Up @@ -1963,105 +1971,127 @@ internal static async Task<bool> InitializeAllDataOnLaunch()
{
var instantiationResult = InitializeHaloClient(authResult);

await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>
{
SplashScreenViewModel.Instance.IsBlocking = false;
});

if (instantiationResult)
{
if (string.IsNullOrWhiteSpace(HaloClient.ClearanceToken))
{
LogEngine.Log($"The clearance is empty, so many API calls that depend on it may fail.");
}

HomeViewModel.Instance.Gamertag = XboxUserContext.DisplayClaims.Xui[0].Gamertag;
HomeViewModel.Instance.Xuid = XboxUserContext.DisplayClaims.Xui[0].XUID;

var databaseBootstrapResult = DataHandler.BootstrapDatabase();
var journalingMode = DataHandler.SetWALJournalingMode();

if (journalingMode.Equals("wal", StringComparison.Ordinal))
{
LogEngine.Log("Successfully set WAL journaling mode.");
}
else
{
LogEngine.Log("Could not set WAL journaling mode.", LogSeverity.Warning);
}

await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>
{
// Reset all collections to make sure that left-over data is not displayed.
BattlePassViewModel.Instance.BattlePasses = BattlePassViewModel.Instance.BattlePasses ?? [];
MatchesViewModel.Instance.MatchList = MatchesViewModel.Instance.MatchList ?? [];
MedalsViewModel.Instance.Medals = MedalsViewModel.Instance.Medals ?? [];
SplashScreenViewModel.Instance.IsBlocking = false;
});

// We want to populate the medal metadata before we do anything else.
MedalMetadata = await PrepopulateMedalMetadata();
if (instantiationResult)
{
if (string.IsNullOrWhiteSpace(HaloClient.ClearanceToken))
{
LogEngine.Log($"The clearance is empty, so many API calls that depend on it may fail.");
}

// Let's get career data first to make sure that it's quickly populated.
_ = await PopulateCareerData();
HomeViewModel.Instance.Gamertag = XboxUserContext.DisplayClaims.Xui[0].Gamertag;
HomeViewModel.Instance.Xuid = XboxUserContext.DisplayClaims.Xui[0].XUID;

// Service Record data should be pulled early to make sure that we
// get the latest medals quickly before everything else is populated.
_ = await PopulateServiceRecordData();
var databaseBootstrapResult = DataHandler.BootstrapDatabase();
var journalingMode = DataHandler.SetWALJournalingMode();

Parallel.Invoke(
async () => await PopulateMedalData(),
async () => await PopulateExchangeData(),
async () => await PopulateCsrImages(),
async () =>
if (journalingMode.Equals("wal", StringComparison.Ordinal))
{
try
{
await PopulateSeasonCalendar();
}
catch (Exception ex)
{
LogEngine.Log($"Could not populate the calendar. {ex.Message}", LogSeverity.Error);
}
},
async () => await PopulateUserInventory(),
async () => await PopulateCustomizationData(),
async () => await PopulateDecorationData(),
async () =>
LogEngine.Log("Successfully set WAL journaling mode.");
}
else
{
var matchRecordsOutcome = await PopulateMatchRecordsData();
LogEngine.Log("Could not set WAL journaling mode.", LogSeverity.Warning);
}

if (matchRecordsOutcome)
await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>
{
// Reset all collections to make sure that left-over data is not displayed.
BattlePassViewModel.Instance.BattlePasses = BattlePassViewModel.Instance.BattlePasses ?? [];
MatchesViewModel.Instance.MatchList = MatchesViewModel.Instance.MatchList ?? [];
MedalsViewModel.Instance.Medals = MedalsViewModel.Instance.Medals ?? [];
});

// We want to populate the medal metadata before we do anything else.
MedalMetadata = await PrepopulateMedalMetadata();

// Let's get career data first to make sure that it's quickly populated.
_ = await PopulateCareerData();

// Service Record data should be pulled early to make sure that we
// get the latest medals quickly before everything else is populated.
_ = await PopulateServiceRecordData();

Parallel.Invoke(
async () => await PopulateMedalData(),
async () => await PopulateExchangeData(),
async () => await PopulateCsrImages(),
async () =>
{
await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>
try
{
MatchesViewModel.Instance.MatchLoadingState = MetadataLoadingState.Completed;
MatchesViewModel.Instance.MatchLoadingParameter = string.Empty;
});
}
},
async () =>
{
try
await PopulateSeasonCalendar();
}
catch (Exception ex)
{
LogEngine.Log($"Could not populate the calendar. {ex.Message}", LogSeverity.Error);
}
},
async () => await PopulateUserInventory(),
async () => await PopulateCustomizationData(),
async () => await PopulateDecorationData(),
async () =>
{
await PopulateBattlePassData(BattlePassLoadingCancellationTracker.Token);
var matchRecordsOutcome = await PopulateMatchRecordsData();
await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>
if (matchRecordsOutcome)
{
BattlePassViewModel.Instance.BattlePassLoadingState = MetadataLoadingState.Completed;
});
}
catch
await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>
{
MatchesViewModel.Instance.MatchLoadingState = MetadataLoadingState.Completed;
MatchesViewModel.Instance.MatchLoadingParameter = string.Empty;
});
}
},
async () =>
{
BattlePassLoadingCancellationTracker = new CancellationTokenSource();
}
});
try
{
await PopulateBattlePassData(BattlePassLoadingCancellationTracker.Token);
return true;
await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>
{
BattlePassViewModel.Instance.BattlePassLoadingState = MetadataLoadingState.Completed;
});
}
catch
{
BattlePassLoadingCancellationTracker = new CancellationTokenSource();
}
});

return true;
}

return false;
}
else
{
await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>
{
SplashScreenViewModel.Instance.IsErrorMessageDisplayed = true;
});

LogEngine.Log("Could not authenticate with Halo services.", LogSeverity.Error);
return false;
}
}
else
{
await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>
{
SplashScreenViewModel.Instance.IsErrorMessageDisplayed = true;
});

LogEngine.Log("Could not authenticate with Halo services.", LogSeverity.Error);
return false;
}
return false;
}
}
}
10 changes: 9 additions & 1 deletion src/OpenSpartan.Workshop/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,15 @@
</NavigationView>

<Grid Grid.RowSpan="2" Background="#2F2F2F" DataContext="{x:Bind viewmodels:SplashScreenViewModel.Instance}" Visibility="{Binding IsBlocking, Converter={StaticResource BoolToVisibilityConverter}}">
<Image Source="CustomImages/logo-icon.png" Height="256" VerticalAlignment="Center" HorizontalAlignment="Center"></Image>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Image Source="CustomImages/logo-icon.png" Height="256" ></Image>
<Border CornerRadius="4" Margin="0,12,0,0" DataContext="{x:Bind viewmodels:SplashScreenViewModel.Instance}" Visibility="{Binding IsErrorMessageDisplayed, Converter={StaticResource BoolToVisibilityConverter}}">
<StackPanel Orientation="Horizontal" Background="#D32F2F" Padding="12">
<FontIcon Glyph="&#xE783;" Margin="0,0,8,0"></FontIcon>
<TextBlock Text="Error connecting to Halo Infinite API or auth services. Please re-launch the app."/>
</StackPanel>
</Border>
</StackPanel>
</Grid>
</Grid>
</Window>
15 changes: 15 additions & 0 deletions src/OpenSpartan.Workshop/ViewModels/SplashScreenViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ internal sealed class SplashScreenViewModel : Observable
private SplashScreenViewModel()
{
IsBlocking = true;
IsErrorMessageDisplayed = false;
}

public bool IsErrorMessageDisplayed
{
get => _isErrorMessageDisplayed;
set
{
if (_isErrorMessageDisplayed != value)
{
_isErrorMessageDisplayed = value;
NotifyPropertyChanged();
}
}
}

public bool IsBlocking
Expand All @@ -25,6 +39,7 @@ public bool IsBlocking
}
}

private bool _isErrorMessageDisplayed;
private bool _isBlocking;

public void NotifyPropertyChanged([CallerMemberName] string? propertyName = null)
Expand Down
Loading

0 comments on commit 3aa330b

Please sign in to comment.