Add Windows desktop version

This commit is contained in:
renato97
2025-12-17 19:20:55 +00:00
parent 93dbe0941e
commit 8921d7f2a6
36 changed files with 2760 additions and 0 deletions

View File

@@ -0,0 +1,208 @@
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Threading;
using StreamPlayer.Desktop.Models;
using StreamPlayer.Desktop.ViewModels;
namespace StreamPlayer.Desktop.Views;
public partial class MainWindow : Window
{
private readonly CancellationTokenSource _lifetimeCts = new();
private MainWindowViewModel? _viewModel;
public MainWindow()
{
InitializeComponent();
DataContextChanged += OnDataContextChanged;
Opened += OnOpened;
Closed += OnClosed;
AttachViewModel(DataContext as MainWindowViewModel);
}
private void OnDataContextChanged(object? sender, EventArgs e)
{
AttachViewModel(DataContext as MainWindowViewModel);
}
private void AttachViewModel(MainWindowViewModel? newViewModel)
{
if (_viewModel != null)
{
_viewModel.ChannelRequested -= OnChannelRequested;
_viewModel.UpdateAvailable -= OnUpdateAvailable;
_viewModel.DeviceStatusEvaluated -= OnDeviceStatusEvaluated;
_viewModel.ErrorRaised -= OnErrorRaised;
}
_viewModel = newViewModel;
if (_viewModel != null)
{
_viewModel.ChannelRequested += OnChannelRequested;
_viewModel.UpdateAvailable += OnUpdateAvailable;
_viewModel.DeviceStatusEvaluated += OnDeviceStatusEvaluated;
_viewModel.ErrorRaised += OnErrorRaised;
}
}
private async void OnOpened(object? sender, EventArgs e)
{
if (_viewModel == null)
{
return;
}
try
{
await _viewModel.InitializeAsync(_lifetimeCts.Token);
await _viewModel.CheckForUpdatesAsync(_lifetimeCts.Token);
await _viewModel.VerifyDeviceAsync(_lifetimeCts.Token);
}
catch (OperationCanceledException)
{
// ignored
}
}
private void OnClosed(object? sender, EventArgs e)
{
_lifetimeCts.Cancel();
_lifetimeCts.Dispose();
AttachViewModel(null);
}
private void OnChannelRequested(object? sender, StreamChannel channel)
{
if (channel == null)
{
return;
}
Dispatcher.UIThread.Post(() =>
{
var player = new PlayerWindow(channel);
player.Show(this);
});
}
private async void OnUpdateAvailable(object? sender, UpdateInfo info)
{
var mandatory = info.IsMandatory(AppVersion.VersionCode);
var dialog = new UpdateDialog(info, mandatory);
var result = await dialog.ShowDialog<UpdateDialogAction>(this);
switch (result)
{
case UpdateDialogAction.Download:
LaunchUrl(info.DownloadUrl);
if (mandatory)
{
Close();
}
break;
case UpdateDialogAction.ViewRelease:
LaunchUrl(string.IsNullOrWhiteSpace(info.ReleasePageUrl)
? info.DownloadUrl
: info.ReleasePageUrl);
if (mandatory)
{
Close();
}
break;
case UpdateDialogAction.Exit:
Close();
break;
case UpdateDialogAction.Skip:
default:
break;
}
}
private async void OnDeviceStatusEvaluated(object? sender, DeviceStatus status)
{
if (!status.IsBlocked)
{
return;
}
var dialog = new BlockedDialog(status.Reason, status.TokenPart);
await dialog.ShowDialog(this);
Close();
}
private async void OnErrorRaised(object? sender, string message)
{
if (string.IsNullOrWhiteSpace(message))
{
return;
}
await ShowInfoAsync("Aviso", message);
}
private static void LaunchUrl(string? url)
{
if (string.IsNullOrWhiteSpace(url))
{
return;
}
try
{
Process.Start(new ProcessStartInfo
{
FileName = url,
UseShellExecute = true
});
}
catch
{
// ignore
}
}
private Task ShowInfoAsync(string title, string message)
{
var okButton = new Button
{
Content = "Aceptar",
HorizontalAlignment = HorizontalAlignment.Right,
Width = 120
};
var stack = new StackPanel
{
Spacing = 12
};
stack.Children.Add(new TextBlock
{
Text = message,
TextWrapping = TextWrapping.Wrap
});
stack.Children.Add(okButton);
var dialog = new Window
{
Title = title,
Width = 420,
SizeToContent = SizeToContent.Height,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
CanResize = false,
Content = new Border
{
Padding = new Thickness(20),
Child = stack
}
};
okButton.Click += (_, _) => dialog.Close();
return dialog.ShowDialog(this);
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}