hub manager, start page manager, adding to settings

This commit is contained in:
Andy Pack 2023-01-28 14:41:03 +00:00
parent 95e1c66adf
commit e986f32058
Signed by: sarsoo
GPG Key ID: A55BA3536A5E0ED7
15 changed files with 293 additions and 95 deletions

View File

@ -0,0 +1,10 @@
using System;
namespace Selector.MAUI
{
public static class Constants
{
public const string JwtPrefKey = "last_jwt_key";
public const string StartPagePrefKey = "start_page";
}
}

View File

@ -0,0 +1,21 @@
using System;
using Selector.MAUI.Services;
using Selector.SignalR;
namespace Selector.MAUI.Extensions;
public static class ServiceExtensions
{
public static IServiceCollection AddHubs(this IServiceCollection services)
{
services.AddSingleton<NowHubClient>()
.AddSingleton<NowHubCache>();
services.AddSingleton<PastHubClient>();
services.AddSingleton<HubManager>();
return services;
}
}

View File

@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection;
using Selector.MAUI.Data;
using Selector.MAUI.Services;
using Selector.SignalR;
using Selector.MAUI.Extensions;
namespace Selector.MAUI;
@ -31,12 +32,10 @@ public static class MauiProgram
builder.Services.AddHttpClient()
.AddTransient<ISelectorNetClient, SelectorNetClient>();
builder.Services.AddSingleton<SessionManager>();
builder.Services.AddSingleton<SessionManager>()
.AddTransient<StartPageManager>();
builder.Services.AddSingleton<NowHubClient>()
.AddSingleton<NowHubCache>();
builder.Services.AddSingleton<PastHubClient>();
builder.Services.AddHubs();
return builder.Build();
}

View File

@ -1,8 +1,6 @@
@page "/app"
@using Selector.SignalR
@inject NowHubClient nowClient
@inject NowHubCache nowCache
@inject PastHubClient pastClient
@inject HubManager hubManager
@inject ILogger<Index> logger
<h1>run that</h1>
@ -11,16 +9,6 @@
protected async override Task OnInitializedAsync()
{
if (nowClient.State == Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Disconnected)
{
logger.LogInformation("Starting now hub connection");
await nowClient.StartAsync();
await pastClient.StartAsync();
nowCache.BindClient();
await nowClient.OnConnected();
}
await hubManager.EnsureConnected();
}
}

View File

@ -3,6 +3,8 @@
@inject ILogger<Login> logger;
@inject NavigationManager NavManager;
@inject SessionManager sessionManager;
@inject HubManager hubManager;
@inject StartPageManager startManager;
<h1>Loading...</h1>
@ -15,8 +17,11 @@
if (sessionManager.IsLoggedIn)
{
await hubManager.EnsureConnected();
logger.LogInformation("User logged in, navigating to main app");
NavManager.NavigateTo("/app");
startManager.NavigateToStartPage();
}
else
{

View File

@ -1,7 +1,5 @@
@page "/past"
@using Selector.SignalR;
@using System.Linq;
@implements IDisposable
<h1>Past</h1>

View File

@ -1,8 +1,23 @@
@page "/settings"
<h1>Settings</h1>
<div class="form-container">
<h1>Settings</h1>
<button @onclick="@SignOut">Sign Out</button>
<div class="row">
<RadzenCard>
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Start Page</RadzenText>
<RadzenDropDown AllowClear="true" TValue="string" Class="w-100"
Data=@startManager.StartPages
@bind-Value="currentStartPage"
Change=@OnStartPageChange />
</RadzenCard>
</div>
<div class="row">
<RadzenButton Click=@(_ => SignOut()) Text="Sign Out" ButtonStyle="ButtonStyle.Danger" />
</div>
<SignatureImage/>
</div>
@code {
@ -10,10 +25,19 @@
private SessionManager sessionManager { get; set; }
[Inject]
private NavigationManager navigationManager { get; set; }
[Inject]
private StartPageManager startManager { get; set; }
private string currentStartPage { get; set; }
protected async override Task OnInitializedAsync()
{
currentStartPage = startManager.GetStartPage();
}
private void OnStartPageChange(object value)
{
startManager.SetStartPage((string) value);
}
private void SignOut()

View File

@ -0,0 +1,20 @@
body {
}
.form-container {
max-width: 300px;
margin: auto;
}
.row {
padding-top: 5px;
padding-bottom: 5px;
}
::deep h3 {
text-align: left;
}
h1 {
padding-bottom: 20px;
}

View File

@ -98,10 +98,12 @@
<None Remove="Microsoft.AspNetCore.SignalR.Client" />
<None Remove="Microsoft.AspNetCore.Components.Forms" />
<None Remove="Radzen.Blazor" />
<None Remove="Extensions\" />
</ItemGroup>
<ItemGroup>
<Folder Include="Services\" />
<Folder Include="Models\" />
<Folder Include="Extensions\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Selector\Selector.csproj" />

View File

@ -0,0 +1,43 @@
using System;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.Logging;
using Selector.SignalR;
namespace Selector.MAUI.Services;
public class HubManager
{
private readonly NowHubClient nowClient;
private readonly NowHubCache nowCache;
private readonly PastHubClient pastClient;
private readonly ILogger<HubManager> logger;
public HubManager(NowHubClient nowClient, NowHubCache nowCache, PastHubClient pastClient, ILogger<HubManager> logger)
{
this.nowClient = nowClient;
this.nowCache = nowCache;
this.pastClient = pastClient;
this.logger = logger;
}
public async Task EnsureConnected()
{
if (nowClient.State == HubConnectionState.Disconnected)
{
logger.LogInformation("Starting now hub connection");
await nowClient.StartAsync();
nowCache.BindClient();
await nowClient.OnConnected();
}
if (pastClient.State == HubConnectionState.Disconnected)
{
logger.LogInformation("Starting past hub connection");
await pastClient.StartAsync();
await pastClient.OnConnected();
}
}
}

View File

@ -5,9 +5,7 @@ namespace Selector.MAUI.Services;
public class SessionManager
{
private const string jwt_keychain_key = "last_jwt_key";
private string lastStoredKey;
private string lastStoredKey;
private DateTime lastRefresh;
private readonly ISelectorNetClient _selectorNetClient;
private readonly ILogger<SessionManager> _logger;
@ -23,7 +21,7 @@ public class SessionManager
public async Task LoadUserFromDisk()
{
//var lastToken = await SecureStorage.Default.GetAsync(jwt_keychain_key);
var lastToken = Preferences.Default.Get(jwt_keychain_key, string.Empty);
var lastToken = Preferences.Default.Get(Constants.JwtPrefKey, string.Empty);
lastStoredKey = lastToken;
@ -62,7 +60,7 @@ public class SessionManager
//await SecureStorage.Default.SetAsync(jwt_keychain_key, lastStoredKey);
// I know, but I can't get secure storage to work
Preferences.Default.Set(jwt_keychain_key, lastStoredKey);
Preferences.Default.Set(Constants.JwtPrefKey, lastStoredKey);
break;
case SelectorNetClient.TokenResponseStatus.Malformed:

View File

@ -0,0 +1,62 @@
using System;
using Microsoft.AspNetCore.Components;
namespace Selector.MAUI.Services;
public class StartPageManager
{
private readonly NavigationManager navManager;
public string[] StartPages { get; } = new[]
{
Home, Now, Past
};
public const string Home = "Home";
public const string Now = "Now";
public const string Past = "Past";
public StartPageManager(NavigationManager navManager)
{
this.navManager = navManager;
}
public string GetStartPage()
{
var savedStartPage = Preferences.Default.Get(Constants.StartPagePrefKey, string.Empty);
if (!string.IsNullOrWhiteSpace(savedStartPage))
{
return savedStartPage;
}
else
{
return Home;
}
}
public void NavigateToStartPage()
{
var startPage = GetStartPage();
switch (startPage)
{
case Now:
navManager.NavigateTo("/now");
break;
case Past:
navManager.NavigateTo("/past");
break;
case Home:
default:
navManager.NavigateTo("/app");
break;
}
}
public void SetStartPage(string value)
{
Preferences.Default.Set(Constants.StartPagePrefKey, value);
}
}

View File

@ -0,0 +1,16 @@
<div style="text-align: center">
<a href="https://sarsoo.xyz/about/" style="display: inline-block">
<img src="/andy.png"
alt="AP"
width="120px"
style="display: block;
margin-left: auto;
margin-right: auto;
padding: 8px">
</a>
</div>
@code {
}

View File

@ -11,7 +11,7 @@
<link href="css/link.css" rel="stylesheet" />
<link href="css/input.css" rel="stylesheet" />
<link href="Selector.MAUI.styles.css" rel="stylesheet" />
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
<link rel="stylesheet" href="_content/Radzen.Blazor/css/dark-base.css">
</head>
<body>

View File

@ -13,7 +13,10 @@ public class NowHubCache
public List<ICard> LastCards { get; private set; } = new();
private readonly object updateLock = new();
public PlayCount LastPlayCount { get; private set; }
private readonly object bindingLock = new();
private bool isBound = false;
public PlayCount LastPlayCount { get; private set; }
public CurrentlyPlayingDTO LastPlaying { get; private set; }
public event EventHandler NewAudioFeature;
@ -29,74 +32,83 @@ public class NowHubCache
public void BindClient()
{
_connection.OnNewAudioFeature(af =>
lock(bindingLock)
{
lock (updateLock)
if(!isBound)
{
logger.LogInformation("New audio features received: {0}", af);
LastFeature = af;
NewAudioFeature?.Invoke(this, null);
}
});
_connection.OnNewAudioFeature(af =>
{
lock (updateLock)
{
logger.LogInformation("New audio features received: {0}", af);
LastFeature = af;
NewAudioFeature?.Invoke(this, null);
}
});
_connection.OnNewCard(c =>
{
lock(updateLock)
{
logger.LogInformation("New card received: {0}", c);
LastCards.Add(c);
NewCard?.Invoke(this, null);
_connection.OnNewCard(c =>
{
lock (updateLock)
{
logger.LogInformation("New card received: {0}", c);
LastCards.Add(c);
NewCard?.Invoke(this, null);
}
});
_connection.OnNewPlayCount(pc =>
{
lock (updateLock)
{
logger.LogInformation("New play count received: {0}", pc);
LastPlayCount = pc;
NewPlayCount?.Invoke(this, null);
}
});
_connection.OnNewPlaying(async np =>
{
try
{
lock (updateLock)
{
logger.LogInformation("New now playing recieved: {0}", np);
LastPlaying = np;
LastCards.Clear();
NewNowPlaying?.Invoke(this, null);
}
if (LastPlaying?.Track is not null)
{
if (!string.IsNullOrWhiteSpace(LastPlaying.Track.Id))
{
await _connection.SendAudioFeatures(LastPlaying.Track.Id);
}
await _connection.SendPlayCount(
LastPlaying.Track.Name,
LastPlaying.Track.Artists.FirstOrDefault()?.Name,
LastPlaying.Track.Album?.Name,
LastPlaying.Track.Album?.Artists.FirstOrDefault()?.Name
);
await _connection.SendFacts(
LastPlaying.Track.Name,
LastPlaying.Track.Artists.FirstOrDefault()?.Name,
LastPlaying.Track.Album?.Name,
LastPlaying.Track.Album?.Artists.FirstOrDefault()?.Name
);
}
}
catch (Exception e)
{
logger.LogError(e, "Error while handling new now playing");
}
});
isBound = true;
}
});
_connection.OnNewPlayCount(pc =>
{
lock (updateLock)
{
logger.LogInformation("New play count received: {0}", pc);
LastPlayCount = pc;
NewPlayCount?.Invoke(this, null);
}
});
_connection.OnNewPlaying(async np =>
{
try
{
lock (updateLock)
{
logger.LogInformation("New now playing recieved: {0}", np);
LastPlaying = np;
LastCards.Clear();
NewNowPlaying?.Invoke(this, null);
}
if (LastPlaying?.Track is not null)
{
if (!string.IsNullOrWhiteSpace(LastPlaying.Track.Id))
{
await _connection.SendAudioFeatures(LastPlaying.Track.Id);
}
await _connection.SendPlayCount(
LastPlaying.Track.Name,
LastPlaying.Track.Artists.FirstOrDefault()?.Name,
LastPlaying.Track.Album?.Name,
LastPlaying.Track.Album?.Artists.FirstOrDefault()?.Name
);
await _connection.SendFacts(
LastPlaying.Track.Name,
LastPlaying.Track.Artists.FirstOrDefault()?.Name,
LastPlaying.Track.Album?.Name,
LastPlaying.Track.Album?.Artists.FirstOrDefault()?.Name
);
}
}catch(Exception e)
{
logger.LogError(e, "Error while handling new now playing");
}
});
}
}
}