feat: add additional simple result dialog
This commit is contained in:
1 parent
3e8c316bc2
commit
4c9e22faf8
10 files changed
+250
-6
No files matched your search
@@ -0,0 +1,8 @@
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using PantherByte.ViewModels;
|
||||
|
||||
namespace PantherByte.Messages;
|
||||
|
||||
public class OpenSimpleDialogMessage(SimpleDialogViewModel vm) : AsyncRequestMessage<SimpleDialogViewModel.SimpleDialogResult?> {
|
||||
public SimpleDialogViewModel ViewModel = vm;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace PantherByte.ViewModels;
|
||||
|
||||
public partial class DependencyProgressViewModel : ViewModelBase, IProgressWindowViewModel {
|
||||
private readonly ProcessStartInfo _processStartInfo;
|
||||
private string _processStdOut = "";
|
||||
private bool _error = false;
|
||||
private bool _inProgress = false;
|
||||
private string _statusMessage = "Downloading ffmpeg...";
|
||||
private string _barColor = "CornflowerBlue";
|
||||
|
||||
public string ProcessStdOut {
|
||||
get => _processStdOut;
|
||||
set => this.RaiseAndSetIfChanged(ref _processStdOut, value);
|
||||
}
|
||||
|
||||
public string StatusMessage {
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
|
||||
public bool Error {
|
||||
get => _error;
|
||||
set => this.RaiseAndSetIfChanged(ref _error, value);
|
||||
}
|
||||
|
||||
public bool InProgress {
|
||||
get => _inProgress;
|
||||
set => this.RaiseAndSetIfChanged(ref _inProgress, value);
|
||||
}
|
||||
|
||||
public string BarColor {
|
||||
get => _barColor;
|
||||
set => this.RaiseAndSetIfChanged(ref _barColor, value);
|
||||
}
|
||||
|
||||
public DependencyProgressViewModel() {
|
||||
_processStartInfo = new ProcessStartInfo() {
|
||||
UseShellExecute = false
|
||||
};
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||
// Windows specific command.
|
||||
_processStartInfo.FileName = "winget";
|
||||
_processStartInfo.Arguments = "install ffmpeg";
|
||||
_processStartInfo.Verb = "runas";
|
||||
} else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
|
||||
// Linux specific command.
|
||||
_processStartInfo.FileName = "sudo";
|
||||
_processStartInfo.Arguments = "apt install ffmpeg";
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public async Task RunProcessAsync() {
|
||||
Process installProcess = new();
|
||||
installProcess.StartInfo = _processStartInfo;
|
||||
|
||||
installProcess.EnableRaisingEvents = true;
|
||||
installProcess.OutputDataReceived += (s, e) => {
|
||||
if (string.IsNullOrWhiteSpace(e.Data)) return;
|
||||
|
||||
Console.WriteLine(e.Data);
|
||||
ProcessStdOut += e.Data;
|
||||
};
|
||||
|
||||
installProcess.ErrorDataReceived += (s, e) => {
|
||||
if (string.IsNullOrWhiteSpace(e.Data)) return;
|
||||
Console.WriteLine(e.Data);
|
||||
ProcessStdOut += e.Data + "\n";
|
||||
Error = true;
|
||||
StatusMessage = "Error occurred while installing ffmpeg.";
|
||||
BarColor = "Red";
|
||||
};
|
||||
|
||||
InProgress = true;
|
||||
try {
|
||||
installProcess.Start();
|
||||
Console.WriteLine("Installation process started.");
|
||||
installProcess.BeginOutputReadLine();
|
||||
installProcess.BeginErrorReadLine();
|
||||
await installProcess.WaitForExitAsync();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Console.WriteLine(ex.Message);
|
||||
Error = true;
|
||||
StatusMessage = "Error occurred while installing ffmpeg.";
|
||||
BarColor = "Red";
|
||||
ProcessStdOut += ex.Message;
|
||||
}
|
||||
finally {
|
||||
InProgress = false;
|
||||
|
||||
if (!Error) {
|
||||
BarColor = "Green";
|
||||
StatusMessage = "Download finished!";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PantherByte.ViewModels;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a series of properties and methods that are used by the <see cref="Views.ProgressWindow"/>.
|
||||
/// It requires the implementation of <see cref="INotifyPropertyChanged"/> as well, so that it can
|
||||
/// preserve the reactivity of the interface.
|
||||
/// </summary>
|
||||
public interface IProgressWindowViewModel : INotifyPropertyChanged {
|
||||
public string ProcessStdOut { get; set; }
|
||||
public string StatusMessage { get; set; }
|
||||
public bool Error { get; set; }
|
||||
public bool InProgress { get; set; }
|
||||
public string BarColor { get; set; }
|
||||
public Task RunProcessAsync();
|
||||
}
|
||||
@@ -13,6 +13,7 @@ using PantherByte.Messages;
|
||||
using PantherByte.Services;
|
||||
using ReactiveUI;
|
||||
using PantherByte.Services.Interfaces;
|
||||
using PantherByte.Views;
|
||||
|
||||
namespace PantherByte.ViewModels;
|
||||
|
||||
@@ -147,6 +148,32 @@ public partial class MainWindowViewModel : ViewModelBase {
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<bool> CheckFfmpegInstalled() {
|
||||
return await Task.Run(async () => {
|
||||
ProcessStartInfo ffmpegInfo = new("ffmpeg") {
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
};
|
||||
|
||||
Process process = new() {
|
||||
StartInfo = ffmpegInfo
|
||||
};
|
||||
|
||||
bool result = true;
|
||||
|
||||
try {
|
||||
process.Start();
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the download process of the file. Generates the command and runs it.
|
||||
/// </summary>
|
||||
@@ -167,6 +194,17 @@ public partial class MainWindowViewModel : ViewModelBase {
|
||||
};
|
||||
info.ArgumentList.AddRange(args[1..]);
|
||||
|
||||
// Check that ffmpeg is installed.
|
||||
var temp = await CheckFfmpegInstalled();
|
||||
// if (!await CheckFfmpegInstalled()) {
|
||||
SimpleDialogViewModel vm = new("Dependency ffmpeg was not found. Would you like to install it?",
|
||||
"Dependency Install");
|
||||
var result = await WeakReferenceMessenger.Default.Send(new OpenSimpleDialogMessage(vm));
|
||||
if (result is not null) {
|
||||
Console.WriteLine($"Received result: {result}");
|
||||
}
|
||||
// }
|
||||
|
||||
// This window isn't linked to the download process yet, but that is the plan.
|
||||
await OpenProgressWindowAsync(info);
|
||||
} catch (Exception ex) {
|
||||
|
||||
@@ -5,7 +5,7 @@ using ReactiveUI;
|
||||
|
||||
namespace PantherByte.ViewModels;
|
||||
|
||||
public class ProgressWindowViewModel : ViewModelBase {
|
||||
public partial class ProgressWindowViewModel : ViewModelBase, IProgressWindowViewModel {
|
||||
// Pass variables between the MainWindow and this window, specifically what point the application
|
||||
// is at in terms of downloading. We'll likely do this as a simple percentage of total progress.
|
||||
private readonly ProcessStartInfo _processStartInfo;
|
||||
@@ -49,11 +49,12 @@ public class ProgressWindowViewModel : ViewModelBase {
|
||||
Process downloadProcess = new();
|
||||
downloadProcess.StartInfo = _processStartInfo;
|
||||
|
||||
downloadProcess.EnableRaisingEvents = true;
|
||||
downloadProcess.OutputDataReceived += (_, e) => {
|
||||
if (!string.IsNullOrWhiteSpace(e.Data)) {
|
||||
if (string.IsNullOrWhiteSpace(e.Data)) return;
|
||||
|
||||
Console.WriteLine(e.Data);
|
||||
ProcessStdOut += e.Data + "\n";
|
||||
}
|
||||
};
|
||||
|
||||
downloadProcess.ErrorDataReceived += (_, e) => {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace PantherByte.ViewModels;
|
||||
|
||||
public partial class SimpleDialogViewModel(string prompt, string title) : ViewModelBase {
|
||||
public enum SimpleDialogResult {
|
||||
Yes,
|
||||
No
|
||||
}
|
||||
|
||||
public string PromptMessage { get; set; } = prompt;
|
||||
public string Title { get; set; } = title;
|
||||
}
|
||||
@@ -16,5 +16,13 @@ public partial class MainWindow : Window {
|
||||
};
|
||||
m.Reply(dialog.ShowDialog<ProgressWindowViewModel?>(w));
|
||||
});
|
||||
|
||||
WeakReferenceMessenger.Default.Register<MainWindow, OpenSimpleDialogMessage>(this,
|
||||
static (w, m) => {
|
||||
var dialog = new SimpleDialog {
|
||||
DataContext = m.ViewModel
|
||||
};
|
||||
m.Reply(dialog.ShowDialog<SimpleDialogViewModel.SimpleDialogResult?>(w));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,7 @@ public partial class ProgressWindow : Window {
|
||||
|
||||
// This feels a little fragile, but we'll leave it for now.
|
||||
Opened += async (_, _) => {
|
||||
if (DataContext is not ProgressWindowViewModel vm)
|
||||
return;
|
||||
|
||||
if (DataContext is IProgressWindowViewModel vm)
|
||||
await vm.RunProcessAsync();
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:PantherByte.ViewModels"
|
||||
x:DataType="vm:SimpleDialogViewModel"
|
||||
mc:Ignorable="d"
|
||||
x:Class="PantherByte.Views.SimpleDialog"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
SizeToContent="WidthAndHeight"
|
||||
Background="Gray"
|
||||
Title="{Binding Title}"
|
||||
CanMaximize="False">
|
||||
<Design.DataContext>
|
||||
<!-- This only sets the DataContext for the previewer in an IDE,
|
||||
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
||||
<vm:SimpleDialogViewModel/>
|
||||
</Design.DataContext>
|
||||
|
||||
<StackPanel Spacing="20" Margin="10" HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="{Binding PromptMessage}" HorizontalAlignment="Center"/>
|
||||
<Grid ColumnDefinitions="*, *" ColumnSpacing="10" Width="200" MaxWidth="300">
|
||||
<Button Grid.Column="0"
|
||||
Content="Yes"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Click="YesButtonClicked"/>
|
||||
<Button Grid.Column="1"
|
||||
Content="No"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Click="NoButtonClicked"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Window>
|
||||
@@ -0,0 +1,19 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using PantherByte.ViewModels;
|
||||
|
||||
namespace PantherByte.Views;
|
||||
|
||||
public partial class SimpleDialog : Window {
|
||||
public SimpleDialog() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void YesButtonClicked(object sender, RoutedEventArgs e) =>
|
||||
Close(SimpleDialogViewModel.SimpleDialogResult.Yes);
|
||||
|
||||
public void NoButtonClicked(object sender, RoutedEventArgs e) =>
|
||||
Close(SimpleDialogViewModel.SimpleDialogResult.No);
|
||||
}
|
||||
Reference in new issue
Block a user