Merge pull request #3 from jahnspohrer/dispatcher-service

idea dispatcher service
This commit is contained in:
Enrico Ludwig 2024-09-05 16:47:17 +02:00 committed by GitHub
commit 35818c7915
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 102 additions and 60 deletions

View File

@ -1,8 +1,10 @@
using System;
using System.Diagnostics;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using BetterRaid.Extensions;
using BetterRaid.Services;
using BetterRaid.ViewModels;
@ -13,42 +15,48 @@ namespace BetterRaid;
public class App : Application
{
private static readonly ServiceCollection Services = [];
private static ServiceProvider? _serviceProvider;
public static IServiceProvider? ServiceProvider => _serviceProvider;
private ServiceProvider? _serviceProvider;
public override void Initialize()
{
InitializeServices();
_serviceProvider = InitializeServices();
AvaloniaXamlLoader.Load(_serviceProvider, this);
}
private void InitializeServices()
private ServiceProvider InitializeServices()
{
var Services = new ServiceCollection();
Services.AddSingleton<ITwitchService, TwitchService>();
Services.AddTransient<MainWindowViewModel>();
Services.AddSingleton<ISynchronizaionService, DispatcherService>(serviceProvider => new DispatcherService(Dispatcher.UIThread));
Services.AddTransient<IMainViewModelFactory, MainWindowViewModelFactory>();
_serviceProvider = Services.BuildServiceProvider();
return Services.BuildServiceProvider();
}
public override void OnFrameworkInitializationCompleted()
{
BindingPlugins.DataValidators.RemoveAt(0);
if(_serviceProvider == null)
{
throw new FieldAccessException($"\"{nameof(_serviceProvider)}\" was null");
}
var viewModelFactory = _serviceProvider.GetRequiredService<IMainViewModelFactory>();
var mainWindowViewModel = viewModelFactory.CreateMainWindowViewModel();
var mainWindow = new MainWindow()
{
DataContext = mainWindowViewModel
};
switch (ApplicationLifetime)
{
case IClassicDesktopStyleApplicationLifetime desktop:
desktop.MainWindow = new MainWindow();
desktop.MainWindow.InjectDataContext<MainWindowViewModel>();
desktop.MainWindow = mainWindow;
break;
case ISingleViewApplicationLifetime singleViewPlatform:
singleViewPlatform.MainView = new MainWindow();
singleViewPlatform.MainView.InjectDataContext<MainWindowViewModel>();
singleViewPlatform.MainView = mainWindow;
break;
}

View File

@ -1,21 +0,0 @@
using Avalonia;
using Microsoft.Extensions.DependencyInjection;
namespace BetterRaid.Extensions;
public static class DataContextExtensions
{
public static T? GetDataContextAs<T>(this T obj) where T : StyledElement
{
return obj.DataContext as T;
}
public static void InjectDataContext<T>(this StyledElement e) where T : class
{
if (App.ServiceProvider == null)
return;
var vm = App.ServiceProvider.GetRequiredService<T>();
e.DataContext = vm;
}
}

View File

@ -15,7 +15,7 @@ public static class Tools
private static HttpListener? _oauthListener;
// Source: https://stackoverflow.com/a/43232486
public static void StartOAuthLogin(string url, Action? callback = null, CancellationToken token = default)
public static void StartOAuthLogin(ITwitchService twitchService, Action? callback = null, CancellationToken token = default)
{
if (_oauthListener == null)
{
@ -23,13 +23,13 @@ public static class Tools
_oauthListener.Prefixes.Add(Constants.TwitchOAuthRedirectUrl + "/");
_oauthListener.Start();
Task.Run(() => WaitForCallback(callback, token), token);
Task.Run(() => WaitForCallback(callback, token, twitchService), token);
}
OpenUrl(url);
OpenUrl(twitchService.GetOAuthUrl());
}
private static async Task WaitForCallback(Action? callback, CancellationToken token)
private static async Task WaitForCallback(Action? callback, CancellationToken token, ITwitchService twitchService)
{
if (_oauthListener == null)
return;
@ -107,11 +107,7 @@ public static class Tools
var accessToken = jsonData["access_token"]?.ToString();
var dataService = App.ServiceProvider?.GetService(typeof(ITwitchService));
if (dataService is ITwitchService twitchDataService)
{
twitchDataService.ConnectApiAsync(Constants.TwitchClientId, accessToken!);
}
twitchService.ConnectApiAsync(Constants.TwitchClientId, accessToken!);
res.StatusCode = 200;
res.Close();

View File

@ -0,0 +1,8 @@
using BetterRaid.ViewModels;
namespace BetterRaid.Services;
public interface IMainViewModelFactory
{
MainWindowViewModel CreateMainWindowViewModel();
}

View File

@ -0,0 +1,8 @@
using System;
namespace BetterRaid.Services;
public interface ISynchronizaionService
{
void Invoke(Action action);
}

View File

@ -0,0 +1,18 @@
using Avalonia.Threading;
using System;
using System.Threading;
namespace BetterRaid.Services.Implementations;
public class DispatcherService : ISynchronizaionService
{
private readonly Dispatcher dispatcher;
public DispatcherService(Dispatcher dispatcher)
{
this.dispatcher = dispatcher;
}
public void Invoke(Action action)
{
dispatcher.Invoke(action);
}
}

View File

@ -0,0 +1,22 @@
using BetterRaid.ViewModels;
namespace BetterRaid.Services.Implementations;
public class MainWindowViewModelFactory : IMainViewModelFactory
{
private readonly ITwitchPubSubService twitchPubSubService;
private readonly ITwitchDataService twitchDataService;
private readonly ISynchronizaionService synchronizaionService;
public MainWindowViewModelFactory(ITwitchPubSubService twitchPubSubService, ITwitchDataService twitchDataService, ISynchronizaionService synchronizaionService)
{
this.twitchPubSubService = twitchPubSubService;
this.twitchDataService = twitchDataService;
this.synchronizaionService = synchronizaionService;
}
public MainWindowViewModel CreateMainWindowViewModel()
{
return new MainWindowViewModel(twitchPubSubService, twitchDataService, synchronizaionService);
}
}

View File

@ -18,6 +18,7 @@ public class MainWindowViewModel : ViewModelBase
private string? _filter;
private ObservableCollection<TwitchChannel> _channels = [];
private readonly BetterRaidDatabase? _db;
private readonly ISynchronizaionService _synchronizaionService;
public BetterRaidDatabase? Database
{
@ -49,8 +50,10 @@ public class MainWindowViewModel : ViewModelBase
public bool IsLoggedIn => Twitch.UserChannel != null;
public MainWindowViewModel(ITwitchService twitch)
public MainWindowViewModel(ITwitchService twitch, ISynchronizaionService synchronizaionService)
{
_synchronizaionService = synchronizaionService;
Twitch = twitch;
Twitch.PropertyChanged += OnTwitchPropertyChanged;
@ -73,7 +76,7 @@ public class MainWindowViewModel : ViewModelBase
public void LoginWithTwitch()
{
Tools.StartOAuthLogin(Twitch.GetOAuthUrl(), OnTwitchLoginCallback, CancellationToken.None);
Tools.StartOAuthLogin(Twitch, OnTwitchLoginCallback, CancellationToken.None);
}
private void OnTwitchLoginCallback()