diff --git a/WpfDemoApp/App.config b/WpfDemoApp/App.config
deleted file mode 100644
index b50c74f..0000000
--- a/WpfDemoApp/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/WpfDemoApp/App.xaml b/WpfDemoApp/App.xaml
index 63ff4ca..a786df8 100644
--- a/WpfDemoApp/App.xaml
+++ b/WpfDemoApp/App.xaml
@@ -1,5 +1,5 @@
-
+ StartupUri="Views/MainWindow.xaml">
+
\ No newline at end of file
diff --git a/WpfDemoApp/InformationWindow.xaml b/WpfDemoApp/InformationWindow.xaml
deleted file mode 100644
index d0bc947..0000000
--- a/WpfDemoApp/InformationWindow.xaml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
diff --git a/WpfDemoApp/MainWindow.xaml b/WpfDemoApp/MainWindow.xaml
deleted file mode 100644
index 28fe247..0000000
--- a/WpfDemoApp/MainWindow.xaml
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WpfDemoApp/MainWindow.xaml.cs b/WpfDemoApp/MainWindow.xaml.cs
deleted file mode 100644
index 4813378..0000000
--- a/WpfDemoApp/MainWindow.xaml.cs
+++ /dev/null
@@ -1,107 +0,0 @@
-using System;
-using System.ComponentModel;
-using System.Runtime.CompilerServices;
-using System.Windows;
-using YoutubeDLSharp;
-using YoutubeDLSharp.Metadata;
-using YoutubeDLSharp.Options;
-
-namespace WpfDemoApp
-{
- public partial class MainWindow : Window, INotifyPropertyChanged
- {
- private bool isNotDownloading = true;
- private bool audioOnly = false;
-
- private IProgress progress;
- private IProgress output;
-
- public MainWindow()
- {
- this.YoutubeDL = new YoutubeDL() { YoutubeDLPath = "yt-dlp.exe" };
- this.DataContext = this;
- InitializeComponent();
- progress = new Progress((p) => showProgress(p));
- output = new Progress((s) => txtOutput.AppendText(s + Environment.NewLine));
- }
-
- public YoutubeDL YoutubeDL { get; }
-
- public bool IsNotDownloading
- {
- get => isNotDownloading;
- set
- {
- isNotDownloading = value;
- propertyChanged();
- }
- }
-
- public bool AudioOnly
- {
- get => audioOnly;
- set
- {
- audioOnly = value;
- propertyChanged();
- }
- }
-
- public event PropertyChangedEventHandler PropertyChanged;
-
- private void propertyChanged([CallerMemberName] string property = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
- }
-
- private async void DownloadButton_Click(object sender, RoutedEventArgs e)
- {
- string url = txtUrl.Text;
- IsNotDownloading = false;
- txtOutput.Clear();
- // Parse custom arguments
- OptionSet custom = OptionSet.FromString(txtOptions.Text.Split('\n'));
- RunResult result;
- if (AudioOnly)
- {
- result = await YoutubeDL.RunAudioDownload(
- url, AudioConversionFormat.Mp3, progress: progress,
- output: output, overrideOptions: custom
- );
- }
- else
- {
- result = await YoutubeDL.RunVideoDownload(url, progress: progress, output: output, overrideOptions: custom);
- }
- if (result.Success)
- {
- MessageBox.Show($"Successfully downloaded \"{url}\" to:\n\"{result.Data}\".", "YoutubeDLSharp");
- }
- else showErrorMessage(url, String.Join("\n", result.ErrorOutput));
- IsNotDownloading = true;
- }
-
- private void showProgress(DownloadProgress p)
- {
- txtState.Text = p.State.ToString();
- progDownload.Value = p.Progress;
- txtProgress.Text = $"speed: {p.DownloadSpeed} | left: {p.ETA}";
- }
-
- private async void InformationButton_Click(object sender, RoutedEventArgs e)
- {
- string url = txtUrl.Text;
- RunResult result = await YoutubeDL.RunVideoDataFetch(url);
- if (result.Success)
- {
- var infoWindow = new InformationWindow(result.Data);
- infoWindow.ShowDialog();
- }
- else showErrorMessage(url, String.Join("\n", result.ErrorOutput));
- }
-
- private void showErrorMessage(string url, string error)
- => MessageBox.Show($"Failed to process '{url}'. Output:\n\n{error}", "YoutubeDLSharp - ERROR",
- MessageBoxButton.OK, MessageBoxImage.Error);
- }
-}
diff --git a/WpfDemoApp/ViewModels/MainWindowViewModel.cs b/WpfDemoApp/ViewModels/MainWindowViewModel.cs
new file mode 100644
index 0000000..f376eb4
--- /dev/null
+++ b/WpfDemoApp/ViewModels/MainWindowViewModel.cs
@@ -0,0 +1,110 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System.Windows;
+using WpfDemoApp.Views;
+using YoutubeDLSharp;
+using YoutubeDLSharp.Options;
+
+namespace WpfDemoApp.ViewModels
+{
+ public partial class MainWindowViewModel : ObservableObject
+ {
+ private YoutubeDL _youtubeDL = new();
+ private IProgress _progress;
+ private IProgress _output;
+
+ [ObservableProperty]
+ private bool _audioOnly = false;
+
+ [ObservableProperty]
+ private string _url = "";
+
+ [ObservableProperty]
+ private string _options = "";
+
+ [ObservableProperty]
+ private string _state = "";
+
+ [ObservableProperty]
+ private float _progressValue = 0;
+
+ [ObservableProperty]
+ private string _progressText = "";
+
+ [ObservableProperty]
+ private string _outputText = "";
+
+ public string Version => _youtubeDL.Version;
+
+ public MainWindowViewModel()
+ {
+ _progress = new Progress(ShowDownloadProgress);
+ _output = new Progress(ShowDownloadOutput);
+ }
+
+ [RelayCommand]
+ private async Task Download()
+ {
+ await YoutubeDLSharp.Utils.DownloadBinaries();
+
+ RunResult result;
+
+ var options = Options.Split('\n');
+ var custom = OptionSet.FromString(options);
+ // it seems like yt-dlp doesn't output progress bar by default
+ custom.Progress = true;
+
+ OutputText = "";
+ if (AudioOnly)
+ {
+ result = await _youtubeDL.RunAudioDownload(Url, AudioConversionFormat.Mp3, progress: _progress, output: _output, overrideOptions: custom);
+ }
+ else
+ {
+ result = await _youtubeDL.RunVideoDownload(Url, progress: _progress, output: _output, overrideOptions: custom);
+ }
+
+ if (result.Success)
+ {
+ MessageBox.Show($"Successfully downloaded \"{Url}\" to:\n\"{result.Data}\".", "YoutubeDLSharp");
+ }
+ else
+ {
+ ShowErrorMessage(Url, string.Join("\n", result.ErrorOutput));
+ }
+ }
+
+ [RelayCommand]
+ private async Task FetchInfo()
+ {
+ await YoutubeDLSharp.Utils.DownloadBinaries();
+
+ var result = await _youtubeDL.RunVideoDataFetch(Url);
+ if (result.Success)
+ {
+ // doesn't follow MVVM pattern but project simple enough to use this trick
+ var informationWindow = new InformationWindow(result.Data);
+ informationWindow.ShowDialog();
+ }
+ else ShowErrorMessage(Url, string.Join("\n", result.ErrorOutput));
+ }
+
+ private void ShowDownloadProgress(DownloadProgress progress)
+ {
+ State = progress.State.ToString();
+ ProgressValue = progress.Progress;
+ ProgressText = $"speed: {progress.DownloadSpeed} | left: {progress.ETA}";
+ }
+
+ private void ShowDownloadOutput(string str)
+ {
+ if (str.Contains("[download]")) return;
+
+ OutputText += (str + Environment.NewLine);
+ }
+
+ private void ShowErrorMessage(string url, string error)
+ => MessageBox.Show($"Failed to process '{url}'. Output:\n\n{error}", "YoutubeDLSharp - ERROR",
+ MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+}
\ No newline at end of file
diff --git a/WpfDemoApp/Views/InformationWindow.xaml b/WpfDemoApp/Views/InformationWindow.xaml
new file mode 100644
index 0000000..32d5346
--- /dev/null
+++ b/WpfDemoApp/Views/InformationWindow.xaml
@@ -0,0 +1,15 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/WpfDemoApp/InformationWindow.xaml.cs b/WpfDemoApp/Views/InformationWindow.xaml.cs
similarity index 66%
rename from WpfDemoApp/InformationWindow.xaml.cs
rename to WpfDemoApp/Views/InformationWindow.xaml.cs
index 3533123..b682d21 100644
--- a/WpfDemoApp/InformationWindow.xaml.cs
+++ b/WpfDemoApp/Views/InformationWindow.xaml.cs
@@ -1,15 +1,14 @@
-using System;
-using System.Windows;
+using System.Windows;
using YoutubeDLSharp.Metadata;
-namespace WpfDemoApp
+namespace WpfDemoApp.Views
{
public partial class InformationWindow : Window
{
public InformationWindow(VideoData videoData)
{
- this.DataContext = videoData;
InitializeComponent();
+ DataContext = videoData;
}
}
-}
+}
\ No newline at end of file
diff --git a/WpfDemoApp/Views/MainWindow.xaml b/WpfDemoApp/Views/MainWindow.xaml
new file mode 100644
index 0000000..74e2ab4
--- /dev/null
+++ b/WpfDemoApp/Views/MainWindow.xaml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WpfDemoApp/Views/MainWindow.xaml.cs b/WpfDemoApp/Views/MainWindow.xaml.cs
new file mode 100644
index 0000000..b452ef8
--- /dev/null
+++ b/WpfDemoApp/Views/MainWindow.xaml.cs
@@ -0,0 +1,14 @@
+using System.Windows;
+using WpfDemoApp.ViewModels;
+
+namespace WpfDemoApp.Views
+{
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ DataContext = new MainWindowViewModel();
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/WpfDemoApp/WpfDemoApp.csproj b/WpfDemoApp/WpfDemoApp.csproj
index 3f6f6ba..1611edc 100644
--- a/WpfDemoApp/WpfDemoApp.csproj
+++ b/WpfDemoApp/WpfDemoApp.csproj
@@ -1,17 +1,14 @@
- net462;net6.0-windows
+ net6.0-windows;net8.0-windows
WinExe
false
true
- true
+ enable
+ enable
-
-
-
-
-
+
\ No newline at end of file