The top-level view model will typically indicate the state of the application. This includes notifying the user of an error, displaying the health of the connection, and asking them to log in again.
The root view (sometimes called AppShell
) handles OnAppearing
and OnDisappering
to load and unload the view model.
When loading the AppShellViewModel
, add a listener to the JinagaClient
for OnStatusChanged
.
public void Load()
{
jinagaClient.OnStatusChanged += JinagaClient_OnStatusChanged;
}
public void Unload()
{
jinagaClient.OnStatusChanged -= JinagaClient_OnStatusChanged;
}
In the JinagaClient_OnStatusChanged
method, respond to the status by setting observable properties.
Design the indicators to best fit your application.
bool IsSaving
Exception? LastSaveError
int QueueLength
When the Jinaga client is sending a fact to the replicator, the status will indicate that the app is saving. If an error occurs during that process, the status will give you the exception.
The status will also indicate the number of facts in the outgoing queue. If the client is not saving, and there are facts in the queue, then there is unsaved data in the app. You will typically want to prioritize this status to show to the user.
private void JinagaClient_OnStatusChanged(JinagaStatus status)
{
if ((!status.IsSaving || status.LastSaveError != null) && status.QueueLength > 0)
{
// There are facts in the queue, and
// the client is not saving, or has
// experienced an error.
Status = "Red";
if (status.LastSaveError != null)
{
Error = status.LastSaveError.GetMessage();
}
}
}
bool IsLoading
Exception? LastLoadError
When the Jinaga client is fetching from a feed, the status will indicate that the app is loading. If an error occurs during that process, the status will give you the exception.
private void JinagaClient_OnStatusChanged(JinagaStatus status)
{
Busy = status.IsLoading || status.IsSaving;
if ( ... )
{
// Indicate saving errors
}
else if (status.LastLoadError != null)
{
// The client has experienced an error on load.
Status = "Yellow";
Error = status.LastLoadError.GetMessage();
}
else
{
Status = "Green";
Error = string.Empty;
}
}
The JinagaStatus
parameter provides an AuthenticationState
property, which has the following values:
NotAuthenticated
Authenticated
AuthenticationExpired
The NotAuthenticated
and Authenticated
states tell you whether the user is logged in.
The AuthenticationExpired
state tells you that the user was logged in, but the token has expired.
You will typically want to respond to this state by asking the user to log in again.
private void JinagaClient_OnStatusChanged(JinagaStatus status)
{
if (status.AuthenticationState == AuthenticationState.AuthenticationExpired)
{
NavigateToLogin = true;
}
}
As with all status indicators, you should set an observable property. Let the view bind to that property to show the user what is happening and take appropriate action. Do not simply navigate to the login page from the view model when their authentication expires, because that would provide a poor user experience in an offline scenario.