Projektdateien hinzufügen.
This commit is contained in:
109
VideoBrowser/ViewModels/AboutViewModel.cs
Normal file
109
VideoBrowser/ViewModels/AboutViewModel.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
namespace VideoBrowser.ViewModels
|
||||
{
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using VideoBrowser.Common;
|
||||
using VideoBrowser.Controls.CefSharpBrowser.Helpers;
|
||||
using VideoBrowser.Resources;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="AboutViewModel" />.
|
||||
/// </summary>
|
||||
public class AboutViewModel
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AboutViewModel"/> class.
|
||||
/// </summary>
|
||||
internal AboutViewModel()
|
||||
{
|
||||
this.ApplicationName = AppEnvironment.LongName;
|
||||
this.ProjectUrlClickedCommand = new RelayCommand(this.OnProjectUrlClicked, nameof(this.ProjectUrlClickedCommand));
|
||||
this.LinkedInCommand = new RelayCommand(this.OnLinkedIn, nameof(this.TwitterCommand));
|
||||
this.TwitterCommand = new RelayCommand(this.OnTwitter, nameof(this.TwitterCommand));
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the AppIcon.
|
||||
/// </summary>
|
||||
public ImageSource AppIcon { get; } = Helpers.ImageHelper.ToImageSource(Properties.Resources.Icon);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ApplicationName.
|
||||
/// </summary>
|
||||
public string ApplicationName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Author.
|
||||
/// </summary>
|
||||
public string Author => $"By {AppEnvironment.Author}";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Icon.
|
||||
/// </summary>
|
||||
public Geometry Icon => Icons.Info;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the LinkedInCommand.
|
||||
/// </summary>
|
||||
public ICommand LinkedInCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ProjectUrl.
|
||||
/// </summary>
|
||||
public string ProjectUrl => AppEnvironment.ProjectUrl;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ProjectUrlClickedCommand.
|
||||
/// </summary>
|
||||
public ICommand ProjectUrlClickedCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the TwitterCommand.
|
||||
/// </summary>
|
||||
public ICommand TwitterCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Version.
|
||||
/// </summary>
|
||||
public string Version => $"Version {AppEnvironment.Version}";
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// The OnLinkedIn.
|
||||
/// </summary>
|
||||
/// <param name="obj">The obj<see cref="object"/>.</param>
|
||||
private void OnLinkedIn(object obj)
|
||||
{
|
||||
ProcessHelper.OpenUrl(@"https://www.linkedin.com/in/ynurcahyo/");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnProjectUrlClicked.
|
||||
/// </summary>
|
||||
/// <param name="obj">The obj<see cref="object"/>.</param>
|
||||
private void OnProjectUrlClicked(object obj)
|
||||
{
|
||||
ProcessHelper.OpenUrl(this.ProjectUrl);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnTwitter.
|
||||
/// </summary>
|
||||
/// <param name="obj">The obj<see cref="object"/>.</param>
|
||||
private void OnTwitter(object obj)
|
||||
{
|
||||
ProcessHelper.OpenUrl(@"https://twitter.com/txtnurcahyo");
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
94
VideoBrowser/ViewModels/DownloadFlyoutViewModel.cs
Normal file
94
VideoBrowser/ViewModels/DownloadFlyoutViewModel.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
namespace VideoBrowser.ViewModels
|
||||
{
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Windows.Input;
|
||||
using VideoBrowser.Common;
|
||||
using VideoBrowser.Controls.CefSharpBrowser.Models;
|
||||
using VideoBrowser.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="DownloadFlyoutViewModel" />.
|
||||
/// </summary>
|
||||
public class DownloadFlyoutViewModel : NotifyPropertyChanged
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private bool _isOpen;
|
||||
|
||||
private string _message;
|
||||
|
||||
#endregion Fields
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DownloadFlyoutViewModel"/> class.
|
||||
/// </summary>
|
||||
/// <param name="models">The models<see cref="ObservableCollection{DownloadItemModel}"/>.</param>
|
||||
internal DownloadFlyoutViewModel(ObservableCollection<DownloadItemModel> models)
|
||||
{
|
||||
this.DownloadItemModels = models;
|
||||
this.DownloadItemModels.CollectionChanged += this.OnDownloadItemModels_CollectionChanged;
|
||||
this.ShowDownloadTabCommand = new RelayCommand(this.OnShowDownloadTab, nameof(this.ShowDownloadTabCommand));
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DownloadItemModels.
|
||||
/// </summary>
|
||||
public ObservableCollection<DownloadItemModel> DownloadItemModels { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IsOpen.
|
||||
/// </summary>
|
||||
public bool IsOpen { get => _isOpen; set => this.Set(this.PropertyChangedHandler, ref _isOpen, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Message.
|
||||
/// </summary>
|
||||
public string Message { get => _message; internal set => this.Set(this.PropertyChangedHandler, ref _message, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ShowDownloadTabAction.
|
||||
/// </summary>
|
||||
public Action ShowDownloadTabAction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ShowDownloadTabCommand.
|
||||
/// </summary>
|
||||
public ICommand ShowDownloadTabCommand { get; }
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// The OnDownloadItemModels_CollectionChanged.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender<see cref="object"/>.</param>
|
||||
/// <param name="e">The e<see cref="NotifyCollectionChangedEventArgs"/>.</param>
|
||||
private void OnDownloadItemModels_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
this.IsOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnShowDownloadTab.
|
||||
/// </summary>
|
||||
/// <param name="obj">The obj<see cref="object"/>.</param>
|
||||
private void OnShowDownloadTab(object obj)
|
||||
{
|
||||
this.ShowDownloadTabAction?.Invoke();
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
142
VideoBrowser/ViewModels/DownloadQueueViewModel.cs
Normal file
142
VideoBrowser/ViewModels/DownloadQueueViewModel.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
namespace VideoBrowser.ViewModels
|
||||
{
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using VideoBrowser.Common;
|
||||
using VideoBrowser.Controls.CefSharpBrowser.Models;
|
||||
using VideoBrowser.Core;
|
||||
using VideoBrowser.Helpers;
|
||||
using VideoBrowser.Models;
|
||||
using VideoBrowser.Resources;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="DownloadQueueViewModel" />.
|
||||
/// </summary>
|
||||
public class DownloadQueueViewModel
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DownloadQueueViewModel"/> class.
|
||||
/// </summary>
|
||||
/// <param name="downloadItemModels">The downloadItemModels<see cref="ObservableCollection{DownloadItemModel}"/>.</param>
|
||||
internal DownloadQueueViewModel(ObservableCollection<DownloadItemModel> downloadItemModels)
|
||||
{
|
||||
this.DownloadItemModels = downloadItemModels;
|
||||
this.OperationCollectionView = CollectionViewSource.GetDefaultView(this.DownloadItemModels);
|
||||
this.RemoveOperationCommand = new RelayCommand(this.OnRemoveOperation);
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DownloadItemModels.
|
||||
/// </summary>
|
||||
public ObservableCollection<DownloadItemModel> DownloadItemModels { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Icon.
|
||||
/// </summary>
|
||||
public Geometry Icon { get; set; } = Icons.Download;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the OperationCollectionView.
|
||||
/// </summary>
|
||||
public ICollectionView OperationCollectionView { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the RemoveOperationCommand.
|
||||
/// </summary>
|
||||
public ICommand RemoveOperationCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ShowMessageAsync.
|
||||
/// </summary>
|
||||
public Action<string, string> ShowMessageAsync { get; set; }
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// The Download.
|
||||
/// </summary>
|
||||
/// <param name="operation">The operation<see cref="Operation"/>.</param>
|
||||
public void Download(Operation operation)
|
||||
{
|
||||
var operationModel = new OperationModel(operation) { PauseDownloadAction = this.OnPauseDownloadCalled, CancelDownloadAction = this.OnCancelDownloadCalled };
|
||||
var element = (DispatcherObject)this.OperationCollectionView;
|
||||
element.InvokeAsync(() =>
|
||||
{
|
||||
if (!this.DownloadItemModels.Contains(operationModel))
|
||||
{
|
||||
this.DownloadItemModels.Insert(0, operationModel);
|
||||
DownloadQueueHandler.Add(operation);
|
||||
}
|
||||
else
|
||||
{
|
||||
var output = Path.GetFileName(operationModel.Operation.Output);
|
||||
this.ShowMessageAsync("Download Canceled", $"The video/audio {output} is already downloaded");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnCancelDownloadCalled.
|
||||
/// </summary>
|
||||
/// <param name="model">The model<see cref="DownloadItemModel"/>.</param>
|
||||
internal void OnCancelDownloadCalled(DownloadItemModel model)
|
||||
{
|
||||
model.Dispose();
|
||||
this.DownloadItemModels.Remove(model);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnPauseDownloadCalled.
|
||||
/// </summary>
|
||||
/// <param name="model">The model<see cref="DownloadItemModel"/>.</param>
|
||||
internal void OnPauseDownloadCalled(DownloadItemModel model)
|
||||
{
|
||||
if (!(model is OperationModel operationModel))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var operation = operationModel.Operation;
|
||||
var status = operation.Status;
|
||||
if (status != OperationStatus.Paused && status != OperationStatus.Queued && status != OperationStatus.Working)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == OperationStatus.Paused)
|
||||
{
|
||||
operation.Resume();
|
||||
model.PauseText = "Pause";
|
||||
}
|
||||
else
|
||||
{
|
||||
operation.Pause();
|
||||
model.PauseText = "Resume";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnRemoveVideo.
|
||||
/// </summary>
|
||||
/// <param name="obj">The obj<see cref="object"/>.</param>
|
||||
private void OnRemoveOperation(object obj)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
250
VideoBrowser/ViewModels/MainWindowViewModel.cs
Normal file
250
VideoBrowser/ViewModels/MainWindowViewModel.cs
Normal file
@@ -0,0 +1,250 @@
|
||||
namespace VideoBrowser.ViewModels
|
||||
{
|
||||
using Dragablz;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using VideoBrowser.Common;
|
||||
using VideoBrowser.Controls.CefSharpBrowser;
|
||||
using VideoBrowser.Controls.CefSharpBrowser.ViewModels;
|
||||
using VideoBrowser.Core;
|
||||
using VideoBrowser.Models;
|
||||
using VideoBrowser.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="MainWindowViewModel" />.
|
||||
/// </summary>
|
||||
public class MainWindowViewModel : NotifyPropertyChanged
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MainWindowViewModel"/> class.
|
||||
/// </summary>
|
||||
/// <param name="globalData">The globalData<see cref="GlobalData"/>.</param>
|
||||
/// <param name="globalBrowserData">The globalBrowserData<see cref="GlobalBrowserData"/>.</param>
|
||||
public MainWindowViewModel(GlobalBrowserData globalBrowserData)
|
||||
{
|
||||
this.ClosingCommand = new RelayCommand(this.OnClosing);
|
||||
this.LoadedCommand = new RelayCommand(this.OnLoaded);
|
||||
this.PressEscCommand = new RelayCommand(this.OnPressEsc);
|
||||
this.PressF2Command = new RelayCommand(this.OnPressF2);
|
||||
this.About = new AboutViewModel();
|
||||
var downloadItemModels = globalBrowserData.DownloadItemModels;
|
||||
this.DownloadQueueViewModel = new DownloadQueueViewModel(downloadItemModels) { ShowMessageAsync = this.ShowMessageAsync };
|
||||
this.DownloadFlyoutViewModel = new DownloadFlyoutViewModel(downloadItemModels) { ShowDownloadTabAction = this.ShowDownloadTabAction };
|
||||
this.WebBrowserTabControlViewModel = new WebBrowserTabControlViewModel(globalBrowserData)
|
||||
{
|
||||
CreateBrowserFunc = this.CreateBrowser
|
||||
};
|
||||
|
||||
this.Initialize();
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the About.
|
||||
/// </summary>
|
||||
public AboutViewModel About { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the CefWindowData.
|
||||
/// </summary>
|
||||
public CefWindowData CefWindowData => this.WebBrowserTabControlViewModel.CefWindowData;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ClosingCommand.
|
||||
/// </summary>
|
||||
public RelayCommand ClosingCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DownloadFlyoutViewModel.
|
||||
/// </summary>
|
||||
public DownloadFlyoutViewModel DownloadFlyoutViewModel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DownloadQueueViewModel.
|
||||
/// </summary>
|
||||
public DownloadQueueViewModel DownloadQueueViewModel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GlobalBrowserData.
|
||||
/// </summary>
|
||||
public GlobalBrowserData GlobalBrowserData => this.WebBrowserTabControlViewModel.GlobalBrowserData;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the LoadedCommand.
|
||||
/// </summary>
|
||||
public ICommand LoadedCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the PressEscCommand.
|
||||
/// </summary>
|
||||
public ICommand PressEscCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the PressF2Command.
|
||||
/// </summary>
|
||||
public ICommand PressF2Command { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Settings.
|
||||
/// </summary>
|
||||
public SettingsViewModel Settings => this.GlobalBrowserData.Settings;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Title.
|
||||
/// </summary>
|
||||
public string Title => $"{AppEnvironment.Name}";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the WebBrowserTabControlViewModel.
|
||||
/// </summary>
|
||||
public WebBrowserTabControlViewModel WebBrowserTabControlViewModel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DownloadAction.
|
||||
/// </summary>
|
||||
private Action<Operation> DownloadAction => this.DownloadQueueViewModel.Download;
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// The CreateBrowser.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="HeaderedItemViewModel"/>.</returns>
|
||||
internal TabItem CreateBrowser()
|
||||
{
|
||||
var model = new WebBrowserHeaderedItemViewModel(this.GlobalBrowserData, this.CefWindowData, this.DownloadAction);
|
||||
return model;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Dispose.
|
||||
/// </summary>
|
||||
private void Dispose()
|
||||
{
|
||||
this.WebBrowserTabControlViewModel.Dispose();
|
||||
var viewModels = this.GlobalBrowserData.WindowViewModels;
|
||||
if (viewModels.Contains(this))
|
||||
{
|
||||
viewModels.Remove(this);
|
||||
}
|
||||
|
||||
if (!viewModels.Any())
|
||||
{
|
||||
this.GlobalBrowserData.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Initialize.
|
||||
/// </summary>
|
||||
private void Initialize()
|
||||
{
|
||||
var args = AppEnvironment.Arguments;
|
||||
var url = Properties.Settings.Default.LastUrl;
|
||||
if (args != null && args.Any())
|
||||
{
|
||||
url = args.First();
|
||||
}
|
||||
|
||||
if (this.WebBrowserTabControlViewModel.TabItems.Any())
|
||||
{
|
||||
var browser = this.WebBrowserTabControlViewModel.TabItems.First();
|
||||
if (browser is WebBrowserHeaderedItemViewModel model)
|
||||
{
|
||||
model.VideoBrowserViewModel.NavigateUrl = url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnClosing.
|
||||
/// </summary>
|
||||
/// <param name="obj">The obj<see cref="object"/>.</param>
|
||||
private void OnClosing(object obj)
|
||||
{
|
||||
var (_, _, commandParameter) = (ValueTuple<object, EventArgs, object>)obj;
|
||||
var window = (Window)commandParameter;
|
||||
var settings = Properties.Settings.Default;
|
||||
settings.WindowPosition = new Point(window.Left, window.Top);
|
||||
settings.WindowWidth = window.ActualWidth;
|
||||
settings.WindowHeight = window.Height;
|
||||
settings.WindowState = window.WindowState;
|
||||
settings.Save();
|
||||
DownloadQueueHandler.Stop();
|
||||
this.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnLoaded.
|
||||
/// </summary>
|
||||
/// <param name="obj">The obj<see cref="object"/>.</param>
|
||||
private void OnLoaded(object obj)
|
||||
{
|
||||
var (_, _, commandParameter) = (ValueTuple<object, EventArgs, object>)obj;
|
||||
var settings = Properties.Settings.Default;
|
||||
var window = (MainWindow)commandParameter;
|
||||
window.Left = settings.WindowPosition.X;
|
||||
window.Top = settings.WindowPosition.Y;
|
||||
window.Width = settings.WindowWidth;
|
||||
window.Height = settings.WindowHeight;
|
||||
window.WindowState = settings.WindowState;
|
||||
this.CefWindowData.MainWindow = window;
|
||||
DownloadQueueHandler.LimitDownloads = settings.ShowMaxSimDownloads;
|
||||
DownloadQueueHandler.StartWatching(settings.MaxSimDownloads);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnPressEsc.
|
||||
/// </summary>
|
||||
/// <param name="obj">The obj<see cref="object"/>.</param>
|
||||
private void OnPressEsc(object obj)
|
||||
{
|
||||
// Leave full screen.
|
||||
if (this.CefWindowData.IsFullScreen)
|
||||
{
|
||||
this.CefWindowData.IsFullScreenCommand.Execute(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnPressF2.
|
||||
/// </summary>
|
||||
/// <param name="obj">The obj<see cref="object"/>.</param>
|
||||
private void OnPressF2(object obj)
|
||||
{
|
||||
var window = this.CefWindowData.MainWindow;
|
||||
window.Width = 1022;
|
||||
window.Height = 900;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ShowDownloadTabAction.
|
||||
/// </summary>
|
||||
private void ShowDownloadTabAction()
|
||||
{
|
||||
var button = this.GlobalBrowserData.GetAddInButton(typeof(DownloadQueueButton));
|
||||
button?.Command.Execute(this.WebBrowserTabControlViewModel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ShowMessageAsync.
|
||||
/// </summary>
|
||||
/// <param name="title">The title<see cref="string"/>.</param>
|
||||
/// <param name="message">The message<see cref="string"/>.</param>
|
||||
private void ShowMessageAsync(string title, string message)
|
||||
{
|
||||
this.CefWindowData.ShowMessageAsync(title, message);
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
386
VideoBrowser/ViewModels/UrlEditorViewModel.cs
Normal file
386
VideoBrowser/ViewModels/UrlEditorViewModel.cs
Normal file
@@ -0,0 +1,386 @@
|
||||
namespace VideoBrowser.ViewModels
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using VideoBrowser.Common;
|
||||
using VideoBrowser.Controls.CefSharpBrowser.ViewModels;
|
||||
using VideoBrowser.Core;
|
||||
using VideoBrowser.Extensions;
|
||||
using VideoBrowser.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="UrlEditorViewModel" />.
|
||||
/// </summary>
|
||||
public class UrlEditorViewModel : NotifyPropertyChanged, IDisposable
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private string _duration;
|
||||
|
||||
private string _fileName;
|
||||
|
||||
private string _fileSize;
|
||||
|
||||
private IList<VideoFormat> _formats;
|
||||
|
||||
private string _imageUrl;
|
||||
|
||||
private bool _isBusy;
|
||||
|
||||
private bool _isDownloadable;
|
||||
|
||||
private bool _isFocused;
|
||||
|
||||
private bool _isFormatComboBoxVisible;
|
||||
|
||||
private bool _isTextBoxFocused;
|
||||
|
||||
private bool _isVisible;
|
||||
|
||||
private string _navigateUrl;
|
||||
|
||||
private VideoFormat _selectedFormat;
|
||||
|
||||
private int _selectedFormatIndex;
|
||||
|
||||
private string _url;
|
||||
|
||||
private VideoInfo _videoInfo;
|
||||
|
||||
#endregion Fields
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UrlEditorViewModel"/> class.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader<see cref="UrlReader"/>.</param>
|
||||
/// <param name="settings">The settings<see cref="Settings"/>.</param>
|
||||
internal UrlEditorViewModel(UrlReader reader, SettingsViewModel settings)
|
||||
{
|
||||
this.UrlReader = reader;
|
||||
this.UrlReader.PropertyChanged += this.OnUrlReader_PropertyChanged;
|
||||
this.Settings = settings;
|
||||
this.DownloadCommand = new RelayCommand(this.OnDownload);
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DownloadCommand.
|
||||
/// </summary>
|
||||
public ICommand DownloadCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Duration.
|
||||
/// </summary>
|
||||
public string Duration { get => this._duration; internal set => this.Set(this.PropertyChangedHandler, ref this._duration, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the FileName.
|
||||
/// </summary>
|
||||
public string FileName { get => this._fileName; internal set => this.Set(this.PropertyChangedHandler, ref this._fileName, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the FileSize.
|
||||
/// </summary>
|
||||
public string FileSize { get => _fileSize; internal set => this.Set(this.PropertyChangedHandler, ref _fileSize, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Formats.
|
||||
/// </summary>
|
||||
public IList<VideoFormat> Formats { get => this._formats; internal set => this.Set(this.PropertyChangedHandler, ref this._formats, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GetFolderCommand.
|
||||
/// </summary>
|
||||
public ICommand GetFolderCommand => this.Settings.GetFolderCommand;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ImageUrl.
|
||||
/// </summary>
|
||||
public string ImageUrl { get => this._imageUrl; set => this.Set(this.PropertyChangedHandler, ref this._imageUrl, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IsBusy.
|
||||
/// </summary>
|
||||
public bool IsBusy { get => _isBusy; set => this.Set(this.PropertyChangedHandler, ref _isBusy, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IsDownloadable.
|
||||
/// </summary>
|
||||
public bool IsDownloadable { get => _isDownloadable; set => this.Set(this.PropertyChangedHandler, ref _isDownloadable, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IsFocused.
|
||||
/// </summary>
|
||||
public bool IsFocused
|
||||
{
|
||||
get => _isFocused;
|
||||
set
|
||||
{
|
||||
if (_isFocused == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_isFocused = value;
|
||||
this.InvokePropertiesChanged(this.OnPropertyChanged, nameof(this.IsFocused), nameof(this.IsVisible));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IsFormatComboBoxVisible.
|
||||
/// </summary>
|
||||
public bool IsFormatComboBoxVisible { get => _isFormatComboBoxVisible; set => this.Set(this.PropertyChangedHandler, ref _isFormatComboBoxVisible, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IsTextBoxFocused.
|
||||
/// </summary>
|
||||
public bool IsTextBoxFocused { get => _isTextBoxFocused; set => this.Set(this.PropertyChangedHandler, ref _isTextBoxFocused, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IsVisible.
|
||||
/// </summary>
|
||||
public bool IsVisible { get => this._isVisible && this.IsFocused; internal set => this.Set(this.PropertyChangedHandler, ref this._isVisible, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the NavigateUrl.
|
||||
/// </summary>
|
||||
public string NavigateUrl
|
||||
{
|
||||
get => this._navigateUrl;
|
||||
set
|
||||
{
|
||||
if (this._navigateUrl == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this._navigateUrl = value;
|
||||
this.IsDownloadable = false;
|
||||
if (this.UrlReader.IsDownloadable)
|
||||
{
|
||||
this.IsBusy = true;
|
||||
Task.Run(() =>
|
||||
{
|
||||
this.VideoInfo = YoutubeDl.GetVideoInfo(this.NavigateUrl);
|
||||
}).ContinueWith(this.LoadVideoInfo);
|
||||
}
|
||||
|
||||
this.IsVisible = this.UrlReader.IsDownloadable;
|
||||
this.OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the NavigateUrlCommand.
|
||||
/// </summary>
|
||||
public ICommand NavigateUrlCommand { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the SelectedFormat.
|
||||
/// </summary>
|
||||
public VideoFormat SelectedFormat
|
||||
{
|
||||
get => this._selectedFormat;
|
||||
set
|
||||
{
|
||||
if (!this.Set(this.PropertyChangedHandler, ref this._selectedFormat, value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.UpdateFileSize();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the SelectedFormatIndex.
|
||||
/// </summary>
|
||||
public int SelectedFormatIndex { get => _selectedFormatIndex; set => this.Set(this.PropertyChangedHandler, ref _selectedFormatIndex, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Settings.
|
||||
/// </summary>
|
||||
public SettingsViewModel Settings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Url.
|
||||
/// </summary>
|
||||
public string Url { get => this._url; set => this.Set(this.PropertyChangedHandler, ref this._url, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UrlReader.
|
||||
/// </summary>
|
||||
public UrlReader UrlReader { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the VideoInfo.
|
||||
/// </summary>
|
||||
public VideoInfo VideoInfo
|
||||
{
|
||||
get => this._videoInfo;
|
||||
set
|
||||
{
|
||||
if (this.VideoInfo != null)
|
||||
{
|
||||
this.VideoInfo.FileSizeUpdated -= this.OnVideoInfo_FileSizeUpdated;
|
||||
}
|
||||
|
||||
this.Set(this.PropertyChangedHandler, ref this._videoInfo, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DownloadAction.
|
||||
/// </summary>
|
||||
internal Action<Operation> DownloadAction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ShowMessageAsyncAction.
|
||||
/// </summary>
|
||||
internal Action<string, string> ShowMessageAsyncAction { get; set; }
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// The Dispose.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.UrlReader.PropertyChanged -= this.OnUrlReader_PropertyChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The LoadVideoInfo.
|
||||
/// </summary>
|
||||
/// <param name="task">The task<see cref="Task"/>.</param>
|
||||
private void LoadVideoInfo(Task task)
|
||||
{
|
||||
this.IsBusy = false;
|
||||
this.IsFocused = true;
|
||||
this.IsTextBoxFocused = true;
|
||||
this.IsDownloadable = false;
|
||||
this.IsFormatComboBoxVisible = false;
|
||||
|
||||
if (this.VideoInfo.RequiresAuthentication)
|
||||
{
|
||||
////var auth = Dialogs.LoginDialog.Show(this);
|
||||
}
|
||||
else if (this.VideoInfo.Failure)
|
||||
{
|
||||
var message = "Couldn't retrieve video. Reason:\n\n" + this.VideoInfo.FailureReason;
|
||||
this.ShowMessageAsyncAction.Invoke("The Video Not Downloadable", message);
|
||||
Logger.Info(message);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.FileName = YoutubeHelper.FormatTitle(this.VideoInfo.Title);
|
||||
this.VideoInfo.FileSizeUpdated += this.OnVideoInfo_FileSizeUpdated;
|
||||
this.Duration = this.VideoInfo.Duration.FormatVideoLength();
|
||||
this.Formats = YoutubeHelper.CheckFormats(this.VideoInfo.Formats);
|
||||
this.ImageUrl = this.VideoInfo.ThumbnailUrl;
|
||||
if (this.Formats.Any())
|
||||
{
|
||||
this.SelectedFormatIndex = this.Formats.Count - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.IsFormatComboBoxVisible = this.VideoInfo.Formats.Count > 0;
|
||||
this.IsDownloadable = true;
|
||||
Properties.Settings.Default.LastUrl = this.NavigateUrl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnDownload.
|
||||
/// </summary>
|
||||
/// <param name="o">The o<see cref="object"/>.</param>
|
||||
private void OnDownload(object o)
|
||||
{
|
||||
var format = this.SelectedFormat;
|
||||
var formatTitle = format.AudioOnly ? format.AudioBitRate.ToString() : format.Format.ToString();
|
||||
this.FileName = FileHelper.GetValidFilename(this.FileName);
|
||||
var fileName = $"{this.FileName}-{formatTitle}.{format.Extension}";
|
||||
var output = Path.Combine(this.Settings.OutputFolder, fileName);
|
||||
if (File.Exists(output))
|
||||
{
|
||||
var message = $@"File ""{fileName}"" is already downloaded. If it was failed, delete it and try again.";
|
||||
this.ShowMessageAsyncAction("Download Canceled", message);
|
||||
return;
|
||||
}
|
||||
|
||||
DownloadOperation operation = format.AudioOnly || format.HasAudioAndVideo
|
||||
? new DownloadOperation(format, output)
|
||||
: new DownloadOperation(format, YoutubeHelper.GetAudioFormat(format), output);
|
||||
Task.Run(() => this.DownloadAction?.Invoke(operation));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnUrlReader_PropertyChanged.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender<see cref="object"/>.</param>
|
||||
/// <param name="e">The e<see cref="PropertyChangedEventArgs"/>.</param>
|
||||
private void OnUrlReader_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
switch (e.PropertyName)
|
||||
{
|
||||
case nameof(this.UrlReader.IsDownloadable):
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnVideoInfo_FileSizeUpdated.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender<see cref="object"/>.</param>
|
||||
/// <param name="e">The e<see cref="FileSizeUpdateEventArgs"/>.</param>
|
||||
private void OnVideoInfo_FileSizeUpdated(object sender, FileSizeUpdateEventArgs e)
|
||||
{
|
||||
this.FileSize = FormatString.FormatFileSize(e.VideoFormat.FileSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The UpdateFileSize.
|
||||
/// </summary>
|
||||
private void UpdateFileSize()
|
||||
{
|
||||
if (this.SelectedFormat == null)
|
||||
{
|
||||
this.FileSize = "Unkown size";
|
||||
}
|
||||
else if (this.SelectedFormat.FileSize == 0)
|
||||
{
|
||||
this.FileSize = "Getting file size...";
|
||||
}
|
||||
else
|
||||
{
|
||||
var total = this.SelectedFormat.FileSize;
|
||||
|
||||
// If the format is VideoOnly, combine audio and video size.
|
||||
if (this.SelectedFormat.VideoOnly)
|
||||
{
|
||||
total += YoutubeHelper.GetAudioFormat(this.SelectedFormat).FileSize;
|
||||
}
|
||||
|
||||
this.FileSize = FormatString.FormatFileSize(total);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
41
VideoBrowser/ViewModels/VideoViewModel.cs
Normal file
41
VideoBrowser/ViewModels/VideoViewModel.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
namespace VideoBrowser.ViewModels
|
||||
{
|
||||
using System.Windows.Media;
|
||||
using VideoBrowser.Common;
|
||||
using VideoBrowser.Extensions;
|
||||
using VideoBrowser.Models;
|
||||
using VideoBrowser.Resources;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="VideoViewModel" />
|
||||
/// </summary>
|
||||
public class VideoViewModel : NotifyPropertyChanged
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private double _downloadProgress;
|
||||
|
||||
private Video _video;
|
||||
|
||||
#endregion Fields
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DownloadProgress
|
||||
/// </summary>
|
||||
public double DownloadProgress { get => this._downloadProgress; set => this.Set(this.PropertyChangedHandler, ref this._downloadProgress, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Icon
|
||||
/// </summary>
|
||||
public Geometry Icon { get; set; } = Icons.SearchVideo;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Video
|
||||
/// </summary>
|
||||
public Video Video { get => this._video; set => this.Set(this.PropertyChangedHandler, ref this._video, value); }
|
||||
|
||||
#endregion Properties
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user