adding pages, login working and hub connecting
This commit is contained in:
parent
562c119e18
commit
d28f28aae6
@ -1,5 +1,8 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Selector.MAUI.Data;
|
||||
using Selector.MAUI.Services;
|
||||
using Selector.SignalR;
|
||||
|
||||
namespace Selector.MAUI;
|
||||
|
||||
@ -16,13 +19,22 @@ public static class MauiProgram
|
||||
});
|
||||
|
||||
builder.Services.AddMauiBlazorWebView();
|
||||
builder.Services.AddLogging(o =>
|
||||
{
|
||||
//o.AddConsole();
|
||||
});
|
||||
|
||||
#if DEBUG
|
||||
builder.Services.AddBlazorWebViewDeveloperTools();
|
||||
builder.Logging.AddDebug();
|
||||
#endif
|
||||
builder.Services.AddHttpClient();
|
||||
|
||||
builder.Services.AddSingleton<WeatherForecastService>();
|
||||
builder.Services.AddTransient<ISelectorNetClient, SelectorNetClient>();
|
||||
builder.Services.AddSingleton<SessionManager>();
|
||||
|
||||
builder.Services.AddSingleton<NowHubClient>();
|
||||
builder.Services.AddSingleton<NowHubCache>();
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
|
9
Selector.MAUI/Models/LoginModel.cs
Normal file
9
Selector.MAUI/Models/LoginModel.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
namespace Selector.MAUI.Models;
|
||||
|
||||
public class LoginModel
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
@page "/counter"
|
||||
|
||||
<h1>Counter</h1>
|
||||
|
||||
<p role="status">Current count: @currentCount</p>
|
||||
|
||||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
|
||||
|
||||
@code {
|
||||
private int currentCount = 0;
|
||||
|
||||
private void IncrementCount()
|
||||
{
|
||||
currentCount++;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,26 @@
|
||||
@page "/"
|
||||
@page "/app"
|
||||
@using Selector.SignalR
|
||||
@inject NowHubClient nowClient
|
||||
@inject NowHubCache nowCache
|
||||
@inject ILogger<Index> logger
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
Welcome to your new app.
|
||||
|
||||
<SurveyPrompt Title="How is Blazor working for you?" />
|
||||
@code {
|
||||
|
||||
protected async override Task OnInitializedAsync()
|
||||
{
|
||||
|
||||
if (nowClient.State == Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Disconnected)
|
||||
{
|
||||
logger.LogInformation("Starting now hub connection");
|
||||
|
||||
await nowClient.StartAsync();
|
||||
nowCache.BindClient();
|
||||
await nowClient.OnConnected();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
29
Selector.MAUI/Pages/Launch.razor
Normal file
29
Selector.MAUI/Pages/Launch.razor
Normal file
@ -0,0 +1,29 @@
|
||||
@page "/"
|
||||
@using Selector.MAUI.Services;
|
||||
@inject ILogger<Login> logger;
|
||||
@inject NavigationManager NavManager;
|
||||
@inject SessionManager sessionManager;
|
||||
|
||||
<h1>Loading...</h1>
|
||||
|
||||
@code {
|
||||
protected async override Task OnInitializedAsync()
|
||||
{
|
||||
logger.LogInformation("Starting up");
|
||||
|
||||
//await sessionManager.LoadUserFromDisk();
|
||||
|
||||
if (sessionManager.IsLoggedIn)
|
||||
{
|
||||
logger.LogInformation("User logged in, navigating to main app");
|
||||
NavManager.NavigateTo("/app");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogInformation("User not logged in, navigating to login");
|
||||
NavManager.NavigateTo("/login");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
43
Selector.MAUI/Pages/Login.razor
Normal file
43
Selector.MAUI/Pages/Login.razor
Normal file
@ -0,0 +1,43 @@
|
||||
@page "/login"
|
||||
@inject SessionManager session
|
||||
@inject NavigationManager navigation
|
||||
|
||||
<h1>Login</h1>
|
||||
|
||||
<p>@toast</p>
|
||||
|
||||
<EditForm Model="@loginModel" OnSubmit="@HandleSubmit">
|
||||
<InputText id="username" @bind-Value="loginModel.Username" />
|
||||
<InputText type="password" placeholder="Password" @bind-Value="loginModel.Password" />
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
</EditForm>
|
||||
|
||||
@code {
|
||||
private LoginModel loginModel = new();
|
||||
private string toast = string.Empty;
|
||||
|
||||
[Inject]
|
||||
private ILogger<Login> logger { get; set; }
|
||||
|
||||
private async Task HandleSubmit()
|
||||
{
|
||||
switch (await session.Authenticate(loginModel.Username, loginModel.Password))
|
||||
{
|
||||
case SelectorNetClient.TokenResponseStatus.Malformed:
|
||||
toast = "Bad Request, Username or Password missing";
|
||||
break;
|
||||
case SelectorNetClient.TokenResponseStatus.UserSearchFailed:
|
||||
toast = "User not found";
|
||||
break;
|
||||
case SelectorNetClient.TokenResponseStatus.BadCreds:
|
||||
toast = "Login failed, try again";
|
||||
break;
|
||||
case SelectorNetClient.TokenResponseStatus.OK:
|
||||
logger.LogInformation("Login succeeded, redirecting");
|
||||
navigation.NavigateTo("/app");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
16
Selector.MAUI/Pages/Now.razor
Normal file
16
Selector.MAUI/Pages/Now.razor
Normal file
@ -0,0 +1,16 @@
|
||||
@page "/now"
|
||||
@using Selector.SignalR;
|
||||
|
||||
<h1>Now</h1>
|
||||
|
||||
@if (nowCache?.LastPlaying?.Track is not null)
|
||||
{
|
||||
<p role="status">@nowCache.LastPlaying.Track.Name</p>
|
||||
}
|
||||
|
||||
|
||||
@code {
|
||||
[Inject]
|
||||
private NowHubCache nowCache { get; set; }
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.get-task-allow</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -31,6 +31,15 @@
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net7.0-ios|AnyCPU'">
|
||||
<CreatePackage>false</CreatePackage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net7.0-ios|AnyCPU'">
|
||||
<CreatePackage>false</CreatePackage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst' and '$(Configuration)' == 'Debug'">
|
||||
<CodeSignEntitlements>Platforms/MacCatalyst/Entitlements.Debug.plist</CodeSignEntitlements>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- App Icon -->
|
||||
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
|
||||
@ -48,6 +57,39 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
|
||||
<!-- <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.2" /> -->
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Forms" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Services\" />
|
||||
<None Remove="Microsoft.Extensions.Http" />
|
||||
<None Remove="System.Net.Http.Json" />
|
||||
<None Remove="NLog.Extensions.Logging" />
|
||||
<None Remove="NLog" />
|
||||
<None Remove="Microsoft.Extensions.Logging.Console" />
|
||||
<None Remove="Models\" />
|
||||
<None Remove="Microsoft.AspNetCore.SignalR.Client" />
|
||||
<None Remove="Microsoft.AspNetCore.Components.Forms" />
|
||||
<None Remove="Platforms\iOS\Entitlements.plist" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Services\" />
|
||||
<Folder Include="Models\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Selector\Selector.csproj" />
|
||||
<ProjectReference Include="..\Selector.SignalR\Selector.SignalR.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Remove="nlog.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- <None Include="nlog.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None> -->
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
110
Selector.MAUI/Services/SelectorNetClient.cs
Normal file
110
Selector.MAUI/Services/SelectorNetClient.cs
Normal file
@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using Selector.SignalR;
|
||||
|
||||
namespace Selector.MAUI.Services;
|
||||
|
||||
public interface ISelectorNetClient
|
||||
{
|
||||
Task<SelectorNetClient.TokenResponse> GetToken(string username, string password);
|
||||
Task<SelectorNetClient.TokenResponse> GetToken(string currentKey);
|
||||
}
|
||||
|
||||
public class SelectorNetClient : ISelectorNetClient
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
private readonly string _baseUrl;
|
||||
private readonly NowHubClient _nowClient;
|
||||
|
||||
public SelectorNetClient(HttpClient client, NowHubClient nowClient)
|
||||
{
|
||||
_client = client;
|
||||
_nowClient = nowClient;
|
||||
|
||||
//var baseOverride = Environment.GetEnvironmentVariable("SELECTOR_BASE_URL");
|
||||
|
||||
//if (!string.IsNullOrWhiteSpace(baseOverride))
|
||||
//{
|
||||
// _baseUrl = baseOverride;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// _baseUrl = "https://selector.sarsoo.xyz";
|
||||
//}
|
||||
|
||||
_baseUrl = "http://localhost:5000";
|
||||
}
|
||||
|
||||
public async Task<TokenResponse> GetToken(string username, string password)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNullOrEmpty(username);
|
||||
ArgumentNullException.ThrowIfNullOrEmpty(password);
|
||||
|
||||
var result = await _client.PostAsync(_baseUrl + "/api/auth/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "Username", username },
|
||||
{ "Password", password }
|
||||
}));
|
||||
|
||||
return FormTokenResponse(result);
|
||||
}
|
||||
|
||||
public async Task<TokenResponse> GetToken(string currentKey)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNullOrEmpty(currentKey);
|
||||
|
||||
var result = await _client.PostAsync(_baseUrl + "/api/auth/token", new StringContent(string.Empty));
|
||||
|
||||
return FormTokenResponse(result);
|
||||
}
|
||||
|
||||
private TokenResponse FormTokenResponse(HttpResponseMessage result)
|
||||
{
|
||||
var ret = new TokenResponse();
|
||||
|
||||
switch (result.StatusCode)
|
||||
{
|
||||
case HttpStatusCode.BadRequest:
|
||||
ret.Status = TokenResponseStatus.Malformed;
|
||||
break;
|
||||
case HttpStatusCode.NotFound:
|
||||
ret.Status = TokenResponseStatus.UserSearchFailed;
|
||||
break;
|
||||
case HttpStatusCode.Unauthorized:
|
||||
ret.Status = TokenResponseStatus.BadCreds;
|
||||
break;
|
||||
case HttpStatusCode.OK:
|
||||
ret.Status = TokenResponseStatus.OK;
|
||||
ret.Token = result.Content.ReadFromJsonAsync<TokenNetworkResponse>().Result.Token;
|
||||
_nowClient.Token = ret.Token;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public class TokenResponse
|
||||
{
|
||||
public string Token { get; set; }
|
||||
public TokenResponseStatus Status { get; set; }
|
||||
}
|
||||
|
||||
public class TokenNetworkResponse
|
||||
{
|
||||
public string Token { get; set; }
|
||||
}
|
||||
|
||||
public enum TokenResponseStatus
|
||||
{
|
||||
Malformed, UserSearchFailed, BadCreds, OK
|
||||
}
|
||||
|
||||
private class TokenModel
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
84
Selector.MAUI/Services/SessionManager.cs
Normal file
84
Selector.MAUI/Services/SessionManager.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Selector.MAUI.Services;
|
||||
|
||||
public class SessionManager
|
||||
{
|
||||
private const string jwt_keychain_key = "last_jwt_key";
|
||||
|
||||
private string lastStoredKey;
|
||||
private DateTime lastRefresh;
|
||||
private readonly ISelectorNetClient _selectorNetClient;
|
||||
private readonly ILogger<SessionManager> _logger;
|
||||
|
||||
public SessionManager(ISelectorNetClient selectorNetClient, ILogger<SessionManager> logger)
|
||||
{
|
||||
_selectorNetClient = selectorNetClient;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public bool IsLoggedIn => !string.IsNullOrWhiteSpace(lastStoredKey);
|
||||
|
||||
public async Task LoadUserFromDisk()
|
||||
{
|
||||
var lastToken = await SecureStorage.Default.GetAsync(jwt_keychain_key);
|
||||
|
||||
lastStoredKey = lastToken;
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(lastToken))
|
||||
{
|
||||
await Authenticate();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SelectorNetClient.TokenResponseStatus> Authenticate(string username, string password)
|
||||
{
|
||||
_logger.LogDebug("Making login token request");
|
||||
|
||||
var tokenResponse = await _selectorNetClient.GetToken(username, password);
|
||||
|
||||
return await HandleTokenResponse(tokenResponse);
|
||||
}
|
||||
|
||||
public async Task<SelectorNetClient.TokenResponseStatus> Authenticate()
|
||||
{
|
||||
_logger.LogDebug("Making token request with current key");
|
||||
|
||||
var tokenResponse = await _selectorNetClient.GetToken(lastStoredKey);
|
||||
|
||||
return await HandleTokenResponse(tokenResponse);
|
||||
}
|
||||
|
||||
private async Task<SelectorNetClient.TokenResponseStatus> HandleTokenResponse(SelectorNetClient.TokenResponse tokenResponse)
|
||||
{
|
||||
switch (tokenResponse.Status)
|
||||
{
|
||||
case SelectorNetClient.TokenResponseStatus.OK:
|
||||
_logger.LogInformation("Token response ok");
|
||||
lastStoredKey = tokenResponse.Token;
|
||||
lastRefresh = DateTime.Now;
|
||||
|
||||
//await SecureStorage.Default.SetAsync(jwt_keychain_key, lastStoredKey);
|
||||
|
||||
break;
|
||||
case SelectorNetClient.TokenResponseStatus.Malformed:
|
||||
_logger.LogInformation("Token request failed, missing username or password");
|
||||
|
||||
break;
|
||||
case SelectorNetClient.TokenResponseStatus.UserSearchFailed:
|
||||
_logger.LogInformation("Token request failed, no user by that name");
|
||||
|
||||
break;
|
||||
case SelectorNetClient.TokenResponseStatus.BadCreds:
|
||||
_logger.LogInformation("Token request failed, bad password");
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
return tokenResponse.Status;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,15 @@
|
||||
@inherits LayoutComponentBase
|
||||
@using Selector.MAUI.Services;
|
||||
|
||||
@inherits LayoutComponentBase
|
||||
@inject SessionManager session
|
||||
|
||||
<div class="page">
|
||||
<div class="sidebar">
|
||||
<NavMenu />
|
||||
</div>
|
||||
|
||||
@if (session.IsLoggedIn)
|
||||
{
|
||||
<div class="sidebar">
|
||||
<NavMenu />
|
||||
</div>
|
||||
}
|
||||
<main>
|
||||
<div class="top-row px-4">
|
||||
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
|
||||
|
@ -15,13 +15,8 @@
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="counter">
|
||||
<span class="oi oi-plus" aria-hidden="true"></span> Counter
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="fetchdata">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
|
||||
<NavLink class="nav-link" href="now">
|
||||
<span class="oi oi-plus" aria-hidden="true"></span> Now
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
|
@ -1,4 +1,5 @@
|
||||
@using System.Net.Http
|
||||
@using Microsoft.Extensions.Logging
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@ -6,4 +7,5 @@
|
||||
@using Microsoft.JSInterop
|
||||
@using Selector.MAUI
|
||||
@using Selector.MAUI.Shared
|
||||
|
||||
@using Selector.MAUI.Models
|
||||
@using Selector.MAUI.Services;
|
||||
|
@ -7,26 +7,37 @@ public abstract class BaseSignalRClient: IAsyncDisposable
|
||||
{
|
||||
private readonly string _baseUrl;
|
||||
protected HubConnection hubConnection;
|
||||
public string Token { get; set; }
|
||||
|
||||
public BaseSignalRClient(string path)
|
||||
public BaseSignalRClient(string path, string token)
|
||||
{
|
||||
var baseOverride = Environment.GetEnvironmentVariable("SELECTOR_BASE_URL");
|
||||
//var baseOverride = Environment.GetEnvironmentVariable("SELECTOR_BASE_URL");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(baseOverride))
|
||||
{
|
||||
_baseUrl = baseOverride;
|
||||
}
|
||||
else
|
||||
{
|
||||
_baseUrl = "https://selector.sarsoo.xyz";
|
||||
}
|
||||
//if (!string.IsNullOrWhiteSpace(baseOverride))
|
||||
//{
|
||||
// _baseUrl = baseOverride;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// _baseUrl = "https://selector.sarsoo.xyz";
|
||||
//}
|
||||
|
||||
_baseUrl = "http://localhost:5000";
|
||||
|
||||
hubConnection = new HubConnectionBuilder()
|
||||
.WithUrl(_baseUrl + "/" + path)
|
||||
.WithUrl(_baseUrl + "/" + path, options =>
|
||||
{
|
||||
options.AccessTokenProvider = () =>
|
||||
{
|
||||
return Task.FromResult(Token);
|
||||
};
|
||||
})
|
||||
.WithAutomaticReconnect()
|
||||
.Build();
|
||||
}
|
||||
|
||||
public HubConnectionState State => hubConnection.State;
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return ((IAsyncDisposable)hubConnection).DisposeAsync();
|
||||
|
93
Selector.SignalR/NowHubCache.cs
Normal file
93
Selector.SignalR/NowHubCache.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SpotifyAPI.Web;
|
||||
|
||||
namespace Selector.SignalR;
|
||||
|
||||
public class NowHubCache
|
||||
{
|
||||
private readonly NowHubClient _connection;
|
||||
private readonly ILogger<NowHubCache> logger;
|
||||
|
||||
public TrackAudioFeatures LastFeature { get; private set; }
|
||||
public List<ICard> LastCards { get; private set; } = new();
|
||||
private readonly object updateLock = new();
|
||||
|
||||
public PlayCount LastPlayCount { get; private set; }
|
||||
public CurrentlyPlayingDTO LastPlaying { get; private set; }
|
||||
|
||||
public NowHubCache(NowHubClient connection, ILogger<NowHubCache> logger)
|
||||
{
|
||||
_connection = connection;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public void BindClient()
|
||||
{
|
||||
_connection.OnNewAudioFeature(af =>
|
||||
{
|
||||
lock (updateLock)
|
||||
{
|
||||
logger.LogInformation("New audio features received: {0}", af);
|
||||
LastFeature = af;
|
||||
}
|
||||
});
|
||||
|
||||
_connection.OnNewCard(c =>
|
||||
{
|
||||
lock(updateLock)
|
||||
{
|
||||
logger.LogInformation("New card received: {0}", c);
|
||||
LastCards.Add(c);
|
||||
}
|
||||
});
|
||||
|
||||
_connection.OnNewPlayCount(pc =>
|
||||
{
|
||||
lock (updateLock)
|
||||
{
|
||||
logger.LogInformation("New play count received: {0}", pc);
|
||||
LastPlayCount = pc;
|
||||
}
|
||||
});
|
||||
|
||||
_connection.OnNewPlaying(async np =>
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (updateLock)
|
||||
{
|
||||
logger.LogInformation("New now playing recieved: {0}", np);
|
||||
LastPlaying = np;
|
||||
LastCards.Clear();
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ public class NowHubClient: BaseSignalRClient, INowPlayingHub, IDisposable
|
||||
private List<IDisposable> NewCardCallbacks = new();
|
||||
private bool disposedValue;
|
||||
|
||||
public NowHubClient(): base("nowhub")
|
||||
public NowHubClient(string token = null): base("nowhub", token)
|
||||
{
|
||||
}
|
||||
|
||||
@ -37,6 +37,26 @@ public class NowHubClient: BaseSignalRClient, INowPlayingHub, IDisposable
|
||||
NewCardCallbacks.Add(hubConnection.On(nameof(OnNewCard), action));
|
||||
}
|
||||
|
||||
public void OnNewPlaying(Func<CurrentlyPlayingDTO, Task> action)
|
||||
{
|
||||
NewPlayingCallbacks.Add(hubConnection.On(nameof(OnNewPlaying), action));
|
||||
}
|
||||
|
||||
public void OnNewAudioFeature(Func<TrackAudioFeatures, Task> action)
|
||||
{
|
||||
NewAudioFeatureCallbacks.Add(hubConnection.On(nameof(OnNewAudioFeature), action));
|
||||
}
|
||||
|
||||
public void OnNewPlayCount(Func<PlayCount, Task> action)
|
||||
{
|
||||
NewPlayCountCallbacks.Add(hubConnection.On(nameof(OnNewPlayCount), action));
|
||||
}
|
||||
|
||||
public void OnNewCard(Func<ICard, Task> action)
|
||||
{
|
||||
NewCardCallbacks.Add(hubConnection.On(nameof(OnNewCard), action));
|
||||
}
|
||||
|
||||
public Task OnConnected()
|
||||
{
|
||||
return hubConnection.InvokeAsync(nameof(OnConnected));
|
||||
|
Loading…
Reference in New Issue
Block a user