Merge pull request #78 from mateuszskoczek/features/errors

Features/errors
This commit is contained in:
2024-03-10 01:57:02 +01:00
committed by GitHub
Unverified
16 changed files with 458 additions and 244 deletions

View File

@@ -117,10 +117,10 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="AuthenticationButtonSignIn.Value" xml:space="preserve"> <data name="AuthenticationButtonSignIn.Text" xml:space="preserve">
<value>Sign in</value> <value>Sign in</value>
</data> </data>
<data name="AuthenticationButtonSignOut.Value" xml:space="preserve"> <data name="AuthenticationButtonSignOut.Text" xml:space="preserve">
<value>Sign out</value> <value>Sign out</value>
</data> </data>
<data name="AuthenticationDescriptionLoading.Value" xml:space="preserve"> <data name="AuthenticationDescriptionLoading.Value" xml:space="preserve">
@@ -135,9 +135,18 @@
<data name="TwitchAuthenticationDescriptionAuthenticationInvalid" xml:space="preserve"> <data name="TwitchAuthenticationDescriptionAuthenticationInvalid" xml:space="preserve">
<value>Token expired or is invalid. Please log in again</value> <value>Token expired or is invalid. Please log in again</value>
</data> </data>
<data name="TwitchAuthenticationDescriptionCannotValidate" xml:space="preserve">
<value>Cannot validate token. Check your internet connection and try again later.</value>
</data>
<data name="TwitchAuthenticationDescriptionNotAuthenticated" xml:space="preserve"> <data name="TwitchAuthenticationDescriptionNotAuthenticated" xml:space="preserve">
<value>You are not authenticated. Please sign in</value> <value>You are not authenticated. Please sign in</value>
</data> </data>
<data name="TwitchAuthenticationDescriptionNotAuthenticatedNoInternetConnection" xml:space="preserve">
<value>You are not authenticated and there is no internet connection. Check your internet connection and try again later.</value>
</data>
<data name="TwitchAuthenticationDialogMessage" xml:space="preserve">
<value>An unknown error occured during Twitch login</value>
</data>
<data name="TwitchAuthenticationDialogTitle" xml:space="preserve"> <data name="TwitchAuthenticationDialogTitle" xml:space="preserve">
<value>Twitch authentication error</value> <value>Twitch authentication error</value>
</data> </data>

View File

@@ -117,6 +117,21 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="DialogErrorMessageNoInternetConnection" xml:space="preserve">
<value>No internet connection. Try again later.</value>
</data>
<data name="DialogErrorTitle" xml:space="preserve">
<value>Error</value>
</data>
<data name="ErrorDownloadingTimeout" xml:space="preserve">
<value>Downloading timeout. Check your internet connection and try again later.</value>
</data>
<data name="ErrorFFmpeg" xml:space="preserve">
<value>FFmpeg exited with error.</value>
</data>
<data name="ErrorFFmpegPath" xml:space="preserve">
<value>No FFmpeg executables found. Check path in settings and try again.</value>
</data>
<data name="StatusCancelled.Text" xml:space="preserve"> <data name="StatusCancelled.Text" xml:space="preserve">
<value>Cancelled</value> <value>Cancelled</value>
</data> </data>

View File

@@ -117,6 +117,18 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="ErrorInfoBar.Title" xml:space="preserve">
<value>Error</value>
</data>
<data name="ErrorInfoBarNoInternetConnection" xml:space="preserve">
<value>No internet connection</value>
</data>
<data name="OptionBarCancelAll.Label" xml:space="preserve">
<value>Cancel all</value>
</data>
<data name="OptionBarCancelAll.Width" xml:space="preserve">
<value>80</value>
</data>
<data name="OptionBarDownloadAll.Label" xml:space="preserve"> <data name="OptionBarDownloadAll.Label" xml:space="preserve">
<value>Download all</value> <value>Download all</value>
</data> </data>

View File

@@ -123,6 +123,9 @@
<data name="EmptyUrl" xml:space="preserve"> <data name="EmptyUrl" xml:space="preserve">
<value>Invalid url. Url cannot be empty.</value> <value>Invalid url. Url cannot be empty.</value>
</data> </data>
<data name="SearchTimeout" xml:space="preserve">
<value>Search timeout. Check your internet connection.</value>
</data>
<data name="SourceNotSupported" xml:space="preserve"> <data name="SourceNotSupported" xml:space="preserve">
<value>Invalid url. Url does not match any of supported source.</value> <value>Invalid url. Url does not match any of supported source.</value>
</data> </data>

View File

@@ -126,6 +126,9 @@
<data name="Header.Text" xml:space="preserve"> <data name="Header.Text" xml:space="preserve">
<value>Subscriptions</value> <value>Subscriptions</value>
</data> </data>
<data name="NoInternetConnectionError" xml:space="preserve">
<value>No internet connection</value>
</data>
<data name="PlaylistSearchButton.Content" xml:space="preserve"> <data name="PlaylistSearchButton.Content" xml:space="preserve">
<value>Add</value> <value>Add</value>
</data> </data>

View File

@@ -13,6 +13,9 @@ using System.IO;
using VDownload.Services.UI.Notifications; using VDownload.Services.UI.Notifications;
using VDownload.Services.UI.StringResources; using VDownload.Services.UI.StringResources;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Http;
using Instances.Exceptions;
using FFMpegCore.Exceptions;
namespace VDownload.Core.Tasks namespace VDownload.Core.Tasks
{ {
@@ -140,7 +143,11 @@ namespace VDownload.Core.Tasks
await _settingsService.Load(); await _settingsService.Load();
string tempDirectory = $"{_settingsService.Data.Common.Temp.Directory}\\{_configurationService.Common.Path.Temp.TasksDirectory}\\{Id}"; string tempDirectory = $"{_settingsService.Data.Common.Temp.Directory}\\{_configurationService.Common.Path.Temp.TasksDirectory}\\{Guid.NewGuid()}";
if (Directory.Exists(tempDirectory))
{
Directory.Delete(tempDirectory, true);
}
Directory.CreateDirectory(tempDirectory); Directory.CreateDirectory(tempDirectory);
List<string> content = new List<string>() List<string> content = new List<string>()
@@ -180,10 +187,11 @@ namespace VDownload.Core.Tasks
.JoinProgressReporter(onProgressProcessing, downloadResult.NewDuration); .JoinProgressReporter(onProgressProcessing, downloadResult.NewDuration);
await ffmpegBuilder.RunAsync(downloadResult.File, outputPath); await ffmpegBuilder.RunAsync(downloadResult.File, outputPath);
StorageFile outputFile = await StorageFile.GetFileFromPathAsync(outputPath);
UpdateStatusWithDispatcher(DownloadTaskStatus.Finalizing); UpdateStatusWithDispatcher(DownloadTaskStatus.Finalizing);
string destination = $"{DownloadOptions.Directory}\\{DownloadOptions.Filename}.{DownloadOptions.Extension}"; await Finalizing(outputFile);
File.Copy(outputPath, destination, true);
UpdateStatusWithDispatcher(DownloadTaskStatus.EndedSuccessfully); UpdateStatusWithDispatcher(DownloadTaskStatus.EndedSuccessfully);
@@ -199,7 +207,26 @@ namespace VDownload.Core.Tasks
} }
catch (Exception ex) catch (Exception ex)
{ {
UpdateErrorWithDispatcher(ex.Message); string message;
if (ex is TaskCanceledException || ex is HttpRequestException)
{
message = _stringResourcesService.HomeDownloadsViewResources.Get("ErrorDownloadingTimeout");
}
else if (ex is InstanceFileNotFoundException)
{
message = _stringResourcesService.HomeDownloadsViewResources.Get("ErrorFFmpegPath");
}
else if (ex is FFMpegException)
{
message = _stringResourcesService.HomeDownloadsViewResources.Get("ErrorFFmpeg");
}
else
{
message = ex.Message;
}
UpdateErrorWithDispatcher(message);
UpdateStatusWithDispatcher(DownloadTaskStatus.EndedUnsuccessfully); UpdateStatusWithDispatcher(DownloadTaskStatus.EndedUnsuccessfully);
if (_settingsService.Data.Common.Notifications.OnUnsuccessful) if (_settingsService.Data.Common.Notifications.OnUnsuccessful)
@@ -218,11 +245,19 @@ namespace VDownload.Core.Tasks
} }
} }
private void UpdateStatusWithDispatcher(DownloadTaskStatus status) => _dispatcherQueue.TryEnqueue(() => Status = status); protected async Task Finalizing(StorageFile outputFile)
{
StorageFolder destination = await StorageFolder.GetFolderFromPathAsync(DownloadOptions.Directory);
private void UpdateProgressWithDispatcher(double progress) => _dispatcherQueue.TryEnqueue(() => Progress = progress); string filename = $"{DownloadOptions.Filename}.{DownloadOptions.Extension}";
await outputFile.CopyAsync(destination, filename, NameCollisionOption.ReplaceExisting);
}
private void UpdateErrorWithDispatcher(string message) => _dispatcherQueue.TryEnqueue(() => Error = message); protected void UpdateStatusWithDispatcher(DownloadTaskStatus status) => _dispatcherQueue.TryEnqueue(() => Status = status);
protected void UpdateProgressWithDispatcher(double progress) => _dispatcherQueue.TryEnqueue(() => Progress = progress);
protected void UpdateErrorWithDispatcher(string message) => _dispatcherQueue.TryEnqueue(() => Error = message);
#endregion #endregion
} }

View File

@@ -1,8 +1,10 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.WinUI.Helpers;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -44,10 +46,13 @@ namespace VDownload.Core.ViewModels.Authentication
#region PROPERTIES #region PROPERTIES
[ObservableProperty] [ObservableProperty]
private AuthenticationButton _twitchButtonState = AuthenticationButton.Loading; protected AuthenticationButton _twitchButtonState = AuthenticationButton.Loading;
[ObservableProperty] [ObservableProperty]
private string _twitchDescription; protected bool _twitchButtonEnable = true;
[ObservableProperty]
protected string _twitchDescription;
#endregion #endregion
@@ -107,7 +112,9 @@ namespace VDownload.Core.ViewModels.Authentication
} }
else else
{ {
await _dialogsService.ShowOk(_stringResourcesService.AuthenticationViewResources.Get("TwitchAuthenticationDialogTitle"), "An unknown error occured"); // TODO : Change to string resource string title = _stringResourcesService.AuthenticationViewResources.Get("TwitchAuthenticationDialogTitle");
string message = _stringResourcesService.AuthenticationViewResources.Get("TwitchAuthenticationDialogMessage");
await _dialogsService.ShowOk(title, message);
} }
} }
await TwitchAuthenticationRefresh(); await TwitchAuthenticationRefresh();
@@ -122,17 +129,38 @@ namespace VDownload.Core.ViewModels.Authentication
private async Task TwitchAuthenticationRefresh() private async Task TwitchAuthenticationRefresh()
{ {
TwitchButtonState = AuthenticationButton.Loading; TwitchButtonState = AuthenticationButton.Loading;
TwitchButtonEnable = true;
byte[]? token = await _twitchAuthenticationService.GetToken(); byte[]? token = await _twitchAuthenticationService.GetToken();
if (token is null) if (token is null)
{ {
TwitchDescription = _stringResourcesService.AuthenticationViewResources.Get("TwitchAuthenticationDescriptionNotAuthenticated"); if (!NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
{
TwitchButtonEnable = false;
TwitchDescription = _stringResourcesService.AuthenticationViewResources.Get("TwitchAuthenticationDescriptionNotAuthenticatedNoInternetConnection");
}
else
{
TwitchDescription = _stringResourcesService.AuthenticationViewResources.Get("TwitchAuthenticationDescriptionNotAuthenticated");
}
TwitchButtonState = AuthenticationButton.SignIn; TwitchButtonState = AuthenticationButton.SignIn;
} }
else else
{ {
TwitchValidationResult validationResult = await _twitchAuthenticationService.ValidateToken(token); TwitchValidationResult validationResult;
try
{
validationResult = await _twitchAuthenticationService.ValidateToken(token);
}
catch (Exception ex) when (ex is TaskCanceledException || ex is HttpRequestException)
{
TwitchDescription = _stringResourcesService.AuthenticationViewResources.Get("TwitchAuthenticationDescriptionCannotValidate");
TwitchButtonState = AuthenticationButton.SignIn;
TwitchButtonEnable = false;
return;
}
if (validationResult.Success) if (validationResult.Success)
{ {
TwitchDescription = string.Format(_stringResourcesService.AuthenticationViewResources.Get("TwitchAuthenticationDescriptionAuthenticated"), validationResult.TokenData.Login, validationResult.TokenData.ExpirationDate); TwitchDescription = string.Format(_stringResourcesService.AuthenticationViewResources.Get("TwitchAuthenticationDescriptionAuthenticated"), validationResult.TokenData.Login, validationResult.TokenData.ExpirationDate);

View File

@@ -68,6 +68,14 @@ namespace VDownload.Core.ViewModels.Home
]; ];
if (idleStatuses.Contains(task.Status)) if (idleStatuses.Contains(task.Status))
{ {
if (!NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
{
string title = _stringResourcesService.HomeDownloadsViewResources.Get("DialogErrorTitle");
string message = _stringResourcesService.HomeDownloadsViewResources.Get("DialogErrorMessageNoInternetConnection");
await _dialogsService.ShowOk(title, message);
return;
}
bool continueEnqueue = true; bool continueEnqueue = true;
if (NetworkHelper.Instance.ConnectionInformation.IsInternetOnMeteredConnection) if (NetworkHelper.Instance.ConnectionInformation.IsInternetOnMeteredConnection)
{ {

View File

@@ -4,6 +4,7 @@ using CommunityToolkit.WinUI.Helpers;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using VDownload.Core.Tasks; using VDownload.Core.Tasks;
@@ -23,13 +24,6 @@ namespace VDownload.Core.ViewModels.Home
{ {
#region ENUMS #region ENUMS
public enum OptionBarMessageIconType
{
None,
ProgressRing,
Error
}
public enum OptionBarContentType public enum OptionBarContentType
{ {
None, None,
@@ -80,6 +74,11 @@ namespace VDownload.Core.ViewModels.Home
[ObservableProperty] [ObservableProperty]
private Type _mainContent; private Type _mainContent;
[ObservableProperty]
private string _optionBarError;
[ObservableProperty]
private bool _optionBarIsErrorOpened;
[ObservableProperty] [ObservableProperty]
private OptionBarContentType _optionBarContent; private OptionBarContentType _optionBarContent;
@@ -88,7 +87,7 @@ namespace VDownload.Core.ViewModels.Home
private string _optionBarMessage; private string _optionBarMessage;
[ObservableProperty] [ObservableProperty]
private OptionBarMessageIconType _optionBarMessageIcon; private bool _optionBarLoading;
[ObservableProperty] [ObservableProperty]
private bool _optionBarLoadSubscriptionButtonChecked; private bool _optionBarLoadSubscriptionButtonChecked;
@@ -149,8 +148,10 @@ namespace VDownload.Core.ViewModels.Home
MainContent = _downloadsView; MainContent = _downloadsView;
OptionBarContent = OptionBarContentType.None; OptionBarContent = OptionBarContentType.None;
OptionBarMessageIcon = OptionBarMessageIconType.None; OptionBarLoading = false;
OptionBarMessage = null; OptionBarMessage = null;
OptionBarError = null;
OptionBarIsErrorOpened = true;
OptionBarLoadSubscriptionButtonChecked = false; OptionBarLoadSubscriptionButtonChecked = false;
OptionBarVideoSearchButtonChecked = false; OptionBarVideoSearchButtonChecked = false;
OptionBarPlaylistSearchButtonChecked = false; OptionBarPlaylistSearchButtonChecked = false;
@@ -163,46 +164,57 @@ namespace VDownload.Core.ViewModels.Home
[RelayCommand] [RelayCommand]
public async Task LoadFromSubscription() public async Task LoadFromSubscription()
{ {
MainContent = _downloadsView; SearchButtonClicked();
OptionBarMessageIcon = OptionBarMessageIconType.None;
OptionBarMessage = null;
if (OptionBarLoadSubscriptionButtonChecked) if (OptionBarLoadSubscriptionButtonChecked)
{ {
if (!NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
{
ShowError(ErrorNoInternetConnection());
OptionBarLoadSubscriptionButtonChecked = false;
return;
}
OptionBarContent = OptionBarContentType.None; OptionBarContent = OptionBarContentType.None;
OptionBarVideoSearchButtonChecked = false; OptionBarVideoSearchButtonChecked = false;
OptionBarPlaylistSearchButtonChecked = false; OptionBarPlaylistSearchButtonChecked = false;
OptionBarSearchNotPending = false; StartSearch();
OptionBarMessageIcon = OptionBarMessageIconType.ProgressRing;
OptionBarMessage = _stringResourcesService.HomeViewResources.Get("OptionBarMessageLoading");
SubscriptionsVideoList subList = new SubscriptionsVideoList { Name = _stringResourcesService.CommonResources.Get("SubscriptionVideoListName") }; SubscriptionsVideoList subList = new SubscriptionsVideoList { Name = _stringResourcesService.CommonResources.Get("SubscriptionVideoListName") };
List<Task> tasks = new List<Task>(); List<Task> tasks = new List<Task>();
foreach (Subscription sub in _subscriptionsDataService.Data.ToArray()) try
{ {
tasks.Add(Task.Run(async () => foreach (Subscription sub in _subscriptionsDataService.Data.ToArray())
{ {
Playlist playlist; tasks.Add(Task.Run(async () =>
try
{ {
playlist = await _searchService.SearchPlaylist(sub.Url.OriginalString, 0); Playlist playlist;
} try
catch (MediaSearchException) {
{ playlist = await _searchService.SearchPlaylist(sub.Url.OriginalString, 0);
return; }
} catch (MediaSearchException)
{
return;
}
IEnumerable<Video> newIds = playlist.Where(x => !sub.VideoIds.Contains(x.Id)); IEnumerable<Video> newIds = playlist.Where(x => !sub.VideoIds.Contains(x.Id));
subList.AddRange(newIds); subList.AddRange(newIds);
foreach (Video video in newIds) foreach (Video video in newIds)
{ {
sub.VideoIds.Add(video.Id); sub.VideoIds.Add(video.Id);
} }
})); }));
}
await Task.WhenAll(tasks);
await _subscriptionsDataService.Save();
}
catch (Exception ex) when (ex is TaskCanceledException || ex is HttpRequestException)
{
ShowError(ErrorSearchTimeout());
return;
} }
await Task.WhenAll(tasks);
await _subscriptionsDataService.Save();
if (subList.Count > 0) if (subList.Count > 0)
{ {
@@ -217,17 +229,14 @@ namespace VDownload.Core.ViewModels.Home
} }
OptionBarSearchNotPending = true; OptionBarSearchNotPending = true;
OptionBarMessageIcon = OptionBarMessageIconType.None; OptionBarLoading = false;
} }
} }
[RelayCommand] [RelayCommand]
public void VideoSearchShow() public void VideoSearchShow()
{ {
OptionBarSearchNotPending = true; SearchButtonClicked();
OptionBarMessageIcon = OptionBarMessageIconType.None;
OptionBarMessage = null;
MainContent = _downloadsView;
if (OptionBarContent != OptionBarContentType.VideoSearch) if (OptionBarContent != OptionBarContentType.VideoSearch)
{ {
@@ -244,10 +253,7 @@ namespace VDownload.Core.ViewModels.Home
[RelayCommand] [RelayCommand]
public void PlaylistSearchShow() public void PlaylistSearchShow()
{ {
OptionBarSearchNotPending = true; SearchButtonClicked();
OptionBarMessageIcon = OptionBarMessageIconType.None;
OptionBarMessage = null;
MainContent = _downloadsView;
if (OptionBarContent != OptionBarContentType.PlaylistSearch) if (OptionBarContent != OptionBarContentType.PlaylistSearch)
{ {
@@ -264,9 +270,13 @@ namespace VDownload.Core.ViewModels.Home
[RelayCommand] [RelayCommand]
public async Task VideoSearchStart() public async Task VideoSearchStart()
{ {
OptionBarSearchNotPending = false; if (!NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
OptionBarMessageIcon = OptionBarMessageIconType.ProgressRing; {
OptionBarMessage = _stringResourcesService.HomeViewResources.Get("OptionBarMessageLoading"); ShowError(ErrorNoInternetConnection());
return;
}
StartSearch();
Video video; Video video;
try try
@@ -275,9 +285,12 @@ namespace VDownload.Core.ViewModels.Home
} }
catch (MediaSearchException ex) catch (MediaSearchException ex)
{ {
OptionBarMessageIcon = OptionBarMessageIconType.Error; ShowError(_stringResourcesService.SearchResources.Get(ex.StringCode));
OptionBarMessage = _stringResourcesService.SearchResources.Get(ex.StringCode); return;
OptionBarSearchNotPending = true; }
catch (Exception ex) when (ex is TaskCanceledException || ex is HttpRequestException)
{
ShowError(ErrorSearchTimeout());
return; return;
} }
@@ -286,16 +299,20 @@ namespace VDownload.Core.ViewModels.Home
MainContent = _videoView; MainContent = _videoView;
OptionBarSearchNotPending = true; OptionBarSearchNotPending = true;
OptionBarMessageIcon = OptionBarMessageIconType.None; OptionBarLoading = false;
OptionBarMessage = null; OptionBarMessage = null;
} }
[RelayCommand] [RelayCommand]
public async Task PlaylistSearchStart() public async Task PlaylistSearchStart()
{ {
OptionBarSearchNotPending = false; if (!NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
OptionBarMessageIcon = OptionBarMessageIconType.ProgressRing; {
OptionBarMessage = _stringResourcesService.HomeViewResources.Get("OptionBarMessageLoading"); ShowError(ErrorNoInternetConnection());
return;
}
StartSearch();
Playlist playlist; Playlist playlist;
try try
@@ -304,9 +321,12 @@ namespace VDownload.Core.ViewModels.Home
} }
catch (MediaSearchException ex) catch (MediaSearchException ex)
{ {
OptionBarMessageIcon = OptionBarMessageIconType.Error; ShowError(_stringResourcesService.SearchResources.Get(ex.StringCode));
OptionBarMessage = _stringResourcesService.SearchResources.Get(ex.StringCode); return;
OptionBarSearchNotPending = true; }
catch (Exception ex) when (ex is TaskCanceledException || ex is HttpRequestException)
{
ShowError(ErrorSearchTimeout());
return; return;
} }
@@ -315,13 +335,19 @@ namespace VDownload.Core.ViewModels.Home
MainContent = _videoCollectionView; MainContent = _videoCollectionView;
OptionBarSearchNotPending = true; OptionBarSearchNotPending = true;
OptionBarMessageIcon = OptionBarMessageIconType.None; OptionBarLoading = false;
OptionBarMessage = null; OptionBarMessage = null;
} }
[RelayCommand] [RelayCommand]
public async Task Download() public async Task Download()
{ {
if (!NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
{
ShowError(ErrorNoInternetConnection());
return;
}
if (_downloadTaskManager.Tasks.Count > 0 && NetworkHelper.Instance.ConnectionInformation.IsInternetOnMeteredConnection) if (_downloadTaskManager.Tasks.Count > 0 && NetworkHelper.Instance.ConnectionInformation.IsInternetOnMeteredConnection)
{ {
string title = _stringResourcesService.CommonResources.Get("StartAtMeteredConnectionDialogTitle"); string title = _stringResourcesService.CommonResources.Get("StartAtMeteredConnectionDialogTitle");
@@ -339,13 +365,58 @@ namespace VDownload.Core.ViewModels.Home
} }
} }
[RelayCommand]
public async Task Cancel()
{
List<Task> tasks = new List<Task>();
foreach (DownloadTask task in _downloadTaskManager.Tasks)
{
tasks.Add(task.Cancel());
}
await Task.WhenAll(tasks);
}
[RelayCommand]
public void CloseError()
{
OptionBarError = null;
OptionBarIsErrorOpened = true;
}
#endregion #endregion
#region PRIVATE METHODS #region PRIVATE METHODS
private async void BackToDownload_EventHandler(object sender, EventArgs e) => await Navigation(); protected void ShowError(string message)
{
OptionBarError = message;
OptionBarSearchNotPending = true;
OptionBarLoading = false;
OptionBarMessage = null;
}
protected void SearchButtonClicked()
{
OptionBarSearchNotPending = true;
OptionBarLoading = false;
OptionBarMessage = null;
MainContent = _downloadsView;
}
protected void StartSearch()
{
OptionBarSearchNotPending = false;
OptionBarLoading = true;
OptionBarMessage = _stringResourcesService.HomeViewResources.Get("OptionBarMessageLoading");
}
protected async void BackToDownload_EventHandler(object sender, EventArgs e) => await Navigation();
protected string ErrorNoInternetConnection() => _stringResourcesService.HomeViewResources.Get("ErrorInfoBarNoInternetConnection");
protected string ErrorSearchTimeout() => _stringResourcesService.SearchResources.Get("SearchTimeout");
#endregion #endregion
} }

View File

@@ -1,10 +1,12 @@
using ABI.System; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.WinUI.Helpers;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using VDownload.Core.ViewModels.Subscriptions.Helpers; using VDownload.Core.ViewModels.Subscriptions.Helpers;
@@ -92,6 +94,12 @@ namespace VDownload.Core.ViewModels.Subscriptions
[RelayCommand] [RelayCommand]
public async Task Add() public async Task Add()
{ {
if (!NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
{
ShowError(_stringResourcesService.SubscriptionsViewResources.Get("NoInternetConnectionError"));
return;
}
Loading = true; Loading = true;
Playlist playlist; Playlist playlist;
@@ -101,16 +109,18 @@ namespace VDownload.Core.ViewModels.Subscriptions
} }
catch (MediaSearchException ex) catch (MediaSearchException ex)
{ {
Error = _stringResourcesService.SearchResources.Get(ex.StringCode); ShowError(_stringResourcesService.SearchResources.Get(ex.StringCode));
Loading = false; return;
}
catch (Exception ex) when (ex is TaskCanceledException || ex is HttpRequestException)
{
ShowError(_stringResourcesService.SearchResources.Get("SearchTimeout"));
return; return;
} }
if (_subscriptionsDataService.Data.Any(x => x.Source == playlist.Source && x.Name == playlist.Name)) if (_subscriptionsDataService.Data.Any(x => x.Source == playlist.Source && x.Name == playlist.Name))
{ {
Error = _stringResourcesService.SubscriptionsViewResources.Get("DuplicateError"); ShowError(_stringResourcesService.SubscriptionsViewResources.Get("DuplicateError"));
Loading = false;
return; return;
} }
@@ -137,5 +147,17 @@ namespace VDownload.Core.ViewModels.Subscriptions
} }
#endregion #endregion
#region PRIVATE METHODS
protected void ShowError(string message)
{
Error = message;
Loading = false;
}
#endregion
} }
} }

View File

@@ -33,27 +33,24 @@
<ctc:SettingsCard Header="Twitch"> <ctc:SettingsCard Header="Twitch">
<i:Interaction.Behaviors> <i:Interaction.Behaviors>
<ic:DataTriggerBehavior Binding="{Binding TwitchButtonState, Converter={StaticResource ObjectToStringConverter}}" <ic:DataTriggerBehavior Binding="{Binding TwitchButtonState, Converter={StaticResource ObjectToStringConverter}}"
ComparisonCondition="NotEqual" ComparisonCondition="NotEqual"
Value="Loading"> Value="Loading">
<ic:ChangePropertyAction PropertyName="Description" <ic:ChangePropertyAction PropertyName="Description"
Value="{Binding TwitchDescription}"/> Value="{Binding TwitchDescription}"/>
<ic:ChangePropertyAction PropertyName="Content"> <ic:ChangePropertyAction PropertyName="Content">
<ic:ChangePropertyAction.Value> <ic:ChangePropertyAction.Value>
<Button Command="{Binding TwitchAuthenticationCommand}"> <Button Command="{Binding TwitchAuthenticationCommand}"
<i:Interaction.Behaviors> IsEnabled="{Binding TwitchButtonEnable}">
<ic:DataTriggerBehavior Binding="{Binding TwitchButtonState, Converter={StaticResource ObjectToStringConverter}}" <Button.Content>
ComparisonCondition="Equal" <ctuc:SwitchPresenter Value="{Binding TwitchButtonState, Converter={StaticResource ObjectToStringConverter}}">
Value="SignIn"> <ctuc:Case Value="SignIn">
<ic:ChangePropertyAction x:Uid="/VDownload.Core.Strings/AuthenticationViewResources/AuthenticationButtonSignIn" <TextBlock x:Uid="/VDownload.Core.Strings/AuthenticationViewResources/AuthenticationButtonSignIn"/>
PropertyName="Content"/> </ctuc:Case>
</ic:DataTriggerBehavior> <ctuc:Case Value="SignOut">
<ic:DataTriggerBehavior Binding="{Binding TwitchButtonState, Converter={StaticResource ObjectToStringConverter}}" <TextBlock x:Uid="/VDownload.Core.Strings/AuthenticationViewResources/AuthenticationButtonSignOut"/>
ComparisonCondition="Equal" </ctuc:Case>
Value="SignOut"> </ctuc:SwitchPresenter>
<ic:ChangePropertyAction x:Uid="/VDownload.Core.Strings/AuthenticationViewResources/AuthenticationButtonSignOut" </Button.Content>
PropertyName="Content"/>
</ic:DataTriggerBehavior>
</i:Interaction.Behaviors>
</Button> </Button>
</ic:ChangePropertyAction.Value> </ic:ChangePropertyAction.Value>
</ic:ChangePropertyAction> </ic:ChangePropertyAction>

View File

@@ -25,130 +25,132 @@
<Frame Content="{Binding MainContent, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ViewModelToViewConverter}}"> <Frame Content="{Binding MainContent, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ViewModelToViewConverter}}">
</Frame> </Frame>
<Grid Grid.Row="1" <ctuc:SwitchPresenter Grid.Row="1"
Background="{ThemeResource OptionBarBackgroundColor}" Value="{Binding OptionBarError, Converter={StaticResource IsNotNullConverter}}">
CornerRadius="10"> <ctuc:Case Value="False">
<Grid.ColumnDefinitions> <Grid Background="{ThemeResource OptionBarBackgroundColor}"
<ColumnDefinition/> CornerRadius="10">
<ColumnDefinition Width="50"/> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition/>
</Grid.ColumnDefinitions> <ColumnDefinition Width="50"/>
<ctuc:UniformGrid Grid.Column="0" <ColumnDefinition Width="Auto"/>
Rows="1" </Grid.ColumnDefinitions>
Margin="15,0,0,0"> <ctuc:UniformGrid Grid.Column="0"
<ctuc:UniformGrid.RowDefinitions> Rows="1"
<RowDefinition/> Margin="15,0,0,0">
</ctuc:UniformGrid.RowDefinitions> <ctuc:UniformGrid.RowDefinitions>
<ctuc:UniformGrid.ColumnDefinitions> <RowDefinition/>
<ColumnDefinition/> </ctuc:UniformGrid.RowDefinitions>
<ColumnDefinition Width="Auto"/> <ctuc:UniformGrid.ColumnDefinitions>
</ctuc:UniformGrid.ColumnDefinitions> <ColumnDefinition/>
<ctuc:SwitchPresenter Grid.Row="0" <ColumnDefinition Width="Auto"/>
VerticalAlignment="Stretch" </ctuc:UniformGrid.ColumnDefinitions>
Margin="0,0,15,0" <ctuc:SwitchPresenter Grid.Row="0"
Value="{Binding OptionBarContent, Converter={StaticResource ObjectToStringConverter}}"> VerticalAlignment="Stretch"
<i:Interaction.Behaviors> Margin="0,0,15,0"
<ic:DataTriggerBehavior Binding="{Binding OptionBarContent, Converter={StaticResource ObjectToStringConverter}}" Value="{Binding OptionBarContent, Converter={StaticResource ObjectToStringConverter}}">
ComparisonCondition="Equal" <i:Interaction.Behaviors>
Value="None"> <ic:DataTriggerBehavior Binding="{Binding OptionBarContent, Converter={StaticResource ObjectToStringConverter}}"
<ic:ChangePropertyAction PropertyName="Visibility" ComparisonCondition="Equal"
Value="Collapsed"/> Value="None">
</ic:DataTriggerBehavior> <ic:ChangePropertyAction PropertyName="Visibility"
<ic:DataTriggerBehavior Binding="{Binding OptionBarContent, Converter={StaticResource ObjectToStringConverter}}" Value="Collapsed"/>
ComparisonCondition="NotEqual" </ic:DataTriggerBehavior>
Value="None"> <ic:DataTriggerBehavior Binding="{Binding OptionBarContent, Converter={StaticResource ObjectToStringConverter}}"
<ic:ChangePropertyAction PropertyName="Visibility" ComparisonCondition="NotEqual"
Value="Visible"/> Value="None">
</ic:DataTriggerBehavior> <ic:ChangePropertyAction PropertyName="Visibility"
</i:Interaction.Behaviors> Value="Visible"/>
<ctuc:Case Value="VideoSearch"> </ic:DataTriggerBehavior>
<Grid ColumnSpacing="10" </i:Interaction.Behaviors>
VerticalAlignment="Stretch"> <ctuc:Case Value="VideoSearch">
<Grid.ColumnDefinitions> <Grid ColumnSpacing="10"
<ColumnDefinition/> VerticalAlignment="Stretch">
<ColumnDefinition Width="Auto"/> <Grid.ColumnDefinitions>
</Grid.ColumnDefinitions> <ColumnDefinition/>
<TextBox x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarVideoSearchContentTextBox" <ColumnDefinition Width="Auto"/>
Grid.Column="0" </Grid.ColumnDefinitions>
VerticalAlignment="Center" <TextBox x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarVideoSearchContentTextBox"
Text="{Binding OptionBarVideoSearchTBValue, Mode=TwoWay}"/> Grid.Column="0"
<Button x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarSearchButton" VerticalAlignment="Center"
Grid.Column="1" Text="{Binding OptionBarVideoSearchTBValue, Mode=TwoWay}"/>
IsEnabled="{Binding OptionBarSearchNotPending}" <Button x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarSearchButton"
Command="{Binding VideoSearchStartCommand}"/> Grid.Column="1"
</Grid> IsEnabled="{Binding OptionBarSearchNotPending}"
</ctuc:Case> Command="{Binding VideoSearchStartCommand}"/>
<ctuc:Case Value="PlaylistSearch"> </Grid>
<Grid ColumnSpacing="10"> </ctuc:Case>
<Grid.ColumnDefinitions> <ctuc:Case Value="PlaylistSearch">
<ColumnDefinition/> <Grid ColumnSpacing="10">
<ColumnDefinition Width="Auto"/> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition/>
</Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/>
<TextBox x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarPlaylistSearchContentTextBox" <ColumnDefinition Width="Auto"/>
Grid.Column="0" </Grid.ColumnDefinitions>
VerticalAlignment="Center" <TextBox x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarPlaylistSearchContentTextBox"
Text="{Binding OptionBarPlaylistSearchTBValue, Mode=TwoWay}"/> Grid.Column="0"
<NumberBox x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarPlaylistSearchContentNumberBox" VerticalAlignment="Center"
Grid.Column="1" Text="{Binding OptionBarPlaylistSearchTBValue, Mode=TwoWay}"/>
VerticalAlignment="Center" <NumberBox x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarPlaylistSearchContentNumberBox"
SpinButtonPlacementMode="Compact" Grid.Column="1"
SmallChange="1" VerticalAlignment="Center"
LargeChange="10" SpinButtonPlacementMode="Compact"
Value="{Binding OptionBarPlaylistSearchNBValue, Mode=TwoWay}" SmallChange="1"
Minimum="0"/> LargeChange="10"
<Button x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarSearchButton" Value="{Binding OptionBarPlaylistSearchNBValue, Mode=TwoWay}"
Grid.Column="2" Minimum="0"/>
IsEnabled="{Binding OptionBarSearchNotPending}" <Button x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarSearchButton"
Command="{Binding PlaylistSearchStartCommand}"/> Grid.Column="2"
</Grid> IsEnabled="{Binding OptionBarSearchNotPending}"
</ctuc:Case> Command="{Binding PlaylistSearchStartCommand}"/>
</ctuc:SwitchPresenter> </Grid>
<StackPanel VerticalAlignment="Center" </ctuc:Case>
Orientation="Horizontal"> </ctuc:SwitchPresenter>
<StackPanel.Resources> <StackPanel VerticalAlignment="Center"
<x:Double x:Key="IconSize">20</x:Double> Orientation="Horizontal">
<Thickness x:Key="IconMargin">0,0,10,0</Thickness> <ProgressRing Width="20"
</StackPanel.Resources> Height="20"
<ctuc:SwitchPresenter Value="{Binding OptionBarMessageIcon, Converter={StaticResource ObjectToStringConverter}}"> Margin="0,0,10,0"
<ctuc:Case Value="None"/> Visibility="{Binding OptionBarLoading, Converter={StaticResource BoolToVisibilityConverter}}"/>
<ctuc:Case Value="ProgressRing"> <TextBlock Text="{Binding OptionBarMessage}"/>
<ProgressRing Width="{StaticResource IconSize}" </StackPanel>
Height="{StaticResource IconSize}" </ctuc:UniformGrid>
Margin="{StaticResource IconMargin}"/> <StackPanel Grid.Column="2"
</ctuc:Case> Orientation="Horizontal"
<ctuc:Case Value="Error"> Margin="0,0,4,0">
<Image Width="{StaticResource IconSize}" <AppBarToggleButton x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarLoadSubscription"
Height="{StaticResource IconSize}" Icon="Favorite"
Margin="{StaticResource IconMargin}" IsEnabled="{Binding OptionBarSearchNotPending}"
Source="{StaticResource ImageHomeViewError}"/> IsChecked="{Binding OptionBarLoadSubscriptionButtonChecked, Mode=TwoWay}"
</ctuc:Case> Command="{Binding LoadFromSubscriptionCommand}"/>
</ctuc:SwitchPresenter> <AppBarToggleButton x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarVideoSearch"
<TextBlock Text="{Binding OptionBarMessage}"/> Icon="Video"
</StackPanel> IsEnabled="{Binding OptionBarSearchNotPending}"
</ctuc:UniformGrid> IsChecked="{Binding OptionBarVideoSearchButtonChecked, Mode=TwoWay}"
<StackPanel Grid.Column="2" Command="{Binding VideoSearchShowCommand}"/>
Orientation="Horizontal"> <AppBarToggleButton x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarPlaylistSearch"
<AppBarToggleButton x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarLoadSubscription" Icon="List"
Icon="Favorite" IsEnabled="{Binding OptionBarSearchNotPending}"
IsEnabled="{Binding OptionBarSearchNotPending}" IsChecked="{Binding OptionBarPlaylistSearchButtonChecked, Mode=TwoWay}"
IsChecked="{Binding OptionBarLoadSubscriptionButtonChecked, Mode=TwoWay}" Command="{Binding PlaylistSearchShowCommand}"/>
Command="{Binding LoadFromSubscriptionCommand}"/> <AppBarSeparator/>
<AppBarToggleButton x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarVideoSearch" <AppBarButton x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarCancelAll"
Icon="Video" Icon="Cancel"
IsEnabled="{Binding OptionBarSearchNotPending}" Command="{Binding CancelCommand}"/>
IsChecked="{Binding OptionBarVideoSearchButtonChecked, Mode=TwoWay}" <AppBarButton x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarDownloadAll"
Command="{Binding VideoSearchShowCommand}"/> Icon="Download"
<AppBarToggleButton x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarPlaylistSearch" Command="{Binding DownloadCommand}"/>
Icon="List" </StackPanel>
IsEnabled="{Binding OptionBarSearchNotPending}" </Grid>
IsChecked="{Binding OptionBarPlaylistSearchButtonChecked, Mode=TwoWay}" </ctuc:Case>
Command="{Binding PlaylistSearchShowCommand}"/> <ctuc:Case Value="True">
<AppBarSeparator/> <InfoBar x:Uid="/VDownload.Core.Strings/HomeViewResources/ErrorInfoBar"
<AppBarButton x:Uid="/VDownload.Core.Strings/HomeViewResources/OptionBarDownloadAll" Severity="Error"
Icon="Download" IsOpen="{Binding OptionBarIsErrorOpened, Mode=TwoWay}"
Command="{Binding DownloadCommand}"/> Message="{Binding OptionBarError}"
</StackPanel> CloseButtonCommand="{Binding CloseErrorCommand}"/>
</Grid> </ctuc:Case>
</ctuc:SwitchPresenter>
</Grid> </Grid>
</Page> </Page>

View File

@@ -7,6 +7,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" mc:Ignorable="d"
Closed="Window_Closed"> Closed="Window_Closed"
Activated="Window_Activated">
<WebView2 x:Name="WebView" NavigationCompleted="WebView_NavigationCompleted"/> <WebView2 x:Name="WebView" NavigationCompleted="WebView_NavigationCompleted"/>
</Window> </Window>

View File

@@ -1,3 +1,5 @@
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives; using Microsoft.UI.Xaml.Controls.Primitives;
@@ -84,6 +86,14 @@ namespace VDownload.Services.UI.WebView
_isOpened = false; _isOpened = false;
} }
private void Window_Activated(object sender, WindowActivatedEventArgs args)
{
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(this);
WindowId windowId = Win32Interop.GetWindowIdFromWindow(windowHandle);
AppWindow appWindow = AppWindow.GetFromWindowId(windowId);
appWindow.SetIcon(@"Assets\Logo\Logo.ico");
}
#endregion #endregion
} }
} }

View File

@@ -40,6 +40,9 @@ namespace VDownload.Services.Utility.FFmpeg
protected string _inputFile; protected string _inputFile;
protected string _outputFile; protected string _outputFile;
protected string _audioCodec;
protected string _videoCodec;
protected FFOptions _options; protected FFOptions _options;
#endregion #endregion
@@ -103,6 +106,10 @@ namespace VDownload.Services.Utility.FFmpeg
_inputFile = inputFile; _inputFile = inputFile;
_outputFile = outputFile; _outputFile = outputFile;
IMediaAnalysis analysis = await FFProbe.AnalyseAsync(_inputFile, _options);
_audioCodec = analysis.AudioStreams.First().CodecName;
_videoCodec = analysis.VideoStreams.First().CodecName;
FFMpegArgumentProcessor ffmpegArguments = FFMpegArguments.FromFileInput(inputFile, true, async (options) => await BuildInputArgumentOptions(options)) FFMpegArgumentProcessor ffmpegArguments = FFMpegArguments.FromFileInput(inputFile, true, async (options) => await BuildInputArgumentOptions(options))
.OutputToFile(outputFile, true, async (options) => await BuildOutputArgumentOptions(options)); .OutputToFile(outputFile, true, async (options) => await BuildOutputArgumentOptions(options));
@@ -154,17 +161,13 @@ namespace VDownload.Services.Utility.FFmpeg
private async Task BuildOutputArgumentOptions(FFMpegArgumentOptions options) private async Task BuildOutputArgumentOptions(FFMpegArgumentOptions options)
{ {
IMediaAnalysis analysis = await FFProbe.AnalyseAsync(_inputFile, _options);
string audioCodec = analysis.AudioStreams.First().CodecName;
string videoCodec = analysis.VideoStreams.First().CodecName;
string extension = Path.GetExtension(_outputFile).Replace(".", string.Empty); string extension = Path.GetExtension(_outputFile).Replace(".", string.Empty);
Data.Configuration.Models.Muxer muxer = _configurationService.Common.Processing.Muxers.First(x => x.Extension == extension); Data.Configuration.Models.Muxer muxer = _configurationService.Common.Processing.Muxers.First(x => x.Extension == extension);
if (_mediaType != MediaType.OnlyAudio) if (_mediaType != MediaType.OnlyAudio)
{ {
IEnumerable<string> availableCodecs = muxer.VideoCodecs; IEnumerable<string> availableCodecs = muxer.VideoCodecs;
string selectedCodec = availableCodecs.Contains(videoCodec) ? "copy" : availableCodecs.First(); string selectedCodec = availableCodecs.Contains(_videoCodec) ? "copy" : availableCodecs.First();
options.WithCustomArgument($"-vcodec {selectedCodec}"); options.WithCustomArgument($"-vcodec {selectedCodec}");
} }
else else
@@ -175,7 +178,7 @@ namespace VDownload.Services.Utility.FFmpeg
if (_mediaType != MediaType.OnlyVideo) if (_mediaType != MediaType.OnlyVideo)
{ {
IEnumerable<string> availableCodecs = muxer.AudioCodecs; IEnumerable<string> availableCodecs = muxer.AudioCodecs;
string selectedCodec = availableCodecs.Contains(audioCodec) ? "copy" : availableCodecs.First(); string selectedCodec = availableCodecs.Contains(_audioCodec) ? "copy" : availableCodecs.First();
options.WithCustomArgument($"-acodec {selectedCodec}"); options.WithCustomArgument($"-acodec {selectedCodec}");
} }
else else

View File

@@ -145,15 +145,17 @@ namespace VDownload.Sources.Twitch.Models
{ {
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
using (FileStream inputStream = File.OpenRead(path)) using (FileStream inputStream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{ {
inputStream.CopyTo(outputStream); inputStream.CopyTo(outputStream);
} }
}
if (deleteSource) }
{ foreach (string item in sourceFiles)
File.Delete(path); {
} if (deleteSource)
{
File.Delete(item);
} }
} }
} }
@@ -184,10 +186,7 @@ namespace VDownload.Sources.Twitch.Models
int retriesCount = 0; int retriesCount = 0;
while (true) while (true)
{ {
if (token.IsCancellationRequested) token.ThrowIfCancellationRequested();
{
return;
}
try try
{ {
byte[] data = await _httpClient.GetByteArrayAsync(chunk.Url, token); byte[] data = await _httpClient.GetByteArrayAsync(chunk.Url, token);
@@ -195,10 +194,6 @@ namespace VDownload.Sources.Twitch.Models
onTaskEndSuccessfully.Invoke(); onTaskEndSuccessfully.Invoke();
return; return;
} }
catch (OperationCanceledException)
{
return;
}
catch (Exception ex) when (ex is HttpRequestException || ex is TaskCanceledException) catch (Exception ex) when (ex is HttpRequestException || ex is TaskCanceledException)
{ {
if (_settingsService.Data.Twitch.Vod.ChunkDownloadingError.Retry && retriesCount < _settingsService.Data.Twitch.Vod.ChunkDownloadingError.RetriesCount) if (_settingsService.Data.Twitch.Vod.ChunkDownloadingError.Retry && retriesCount < _settingsService.Data.Twitch.Vod.ChunkDownloadingError.RetriesCount)