From 3ddb8e73e3cbd8d91fdd497cc7134783087cac99 Mon Sep 17 00:00:00 2001 From: Mateusz Skoczek Date: Mon, 4 Mar 2024 00:28:32 +0100 Subject: [PATCH] metered connection warnings added --- .../Strings/en-US/CommonResources.resw | 126 ++++++++++++++++++ .../Home/HomeDownloadsViewModel.cs | 27 +++- .../Home/HomePlaylistViewModel.cs | 25 +++- .../Home/HomeVideoViewModel.cs | 42 ++++-- .../Home/HomeViewModel.cs | 22 ++- .../VDownload.Core.ViewModels.csproj | 1 + .../NetworkService.cs | 36 +++++ .../VDownload.Services.Utility.Network.csproj | 13 ++ .../StringResourcesService.cs | 3 + VDownload.sln | 21 ++- VDownload/App.xaml.cs | 2 + VDownload/VDownload.csproj | 1 + 12 files changed, 298 insertions(+), 21 deletions(-) create mode 100644 VDownload.Core/VDownload.Core.Strings/Strings/en-US/CommonResources.resw create mode 100644 VDownload.Services.Utility.Network/NetworkService.cs create mode 100644 VDownload.Services.Utility.Network/VDownload.Services.Utility.Network.csproj diff --git a/VDownload.Core/VDownload.Core.Strings/Strings/en-US/CommonResources.resw b/VDownload.Core/VDownload.Core.Strings/Strings/en-US/CommonResources.resw new file mode 100644 index 0000000..2deb893 --- /dev/null +++ b/VDownload.Core/VDownload.Core.Strings/Strings/en-US/CommonResources.resw @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + You are trying to download a video using a metered connection. Do you want to continue? + + + Warning + + \ No newline at end of file diff --git a/VDownload.Core/VDownload.Core.ViewModels/Home/HomeDownloadsViewModel.cs b/VDownload.Core/VDownload.Core.ViewModels/Home/HomeDownloadsViewModel.cs index 1af5186..44aed75 100644 --- a/VDownload.Core/VDownload.Core.ViewModels/Home/HomeDownloadsViewModel.cs +++ b/VDownload.Core/VDownload.Core.ViewModels/Home/HomeDownloadsViewModel.cs @@ -7,6 +7,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using VDownload.Core.Tasks; +using VDownload.Services.UI.Dialogs; +using VDownload.Services.UI.StringResources; +using VDownload.Services.Utility.Network; namespace VDownload.Core.ViewModels.Home { @@ -16,6 +19,10 @@ namespace VDownload.Core.ViewModels.Home protected readonly IDownloadTaskManager _tasksManager; + protected readonly INetworkService _networkService; + protected readonly IDialogsService _dialogsService; + protected readonly IStringResourcesService _stringResourcesService; + #endregion @@ -33,11 +40,15 @@ namespace VDownload.Core.ViewModels.Home #region CONSTRUCTORS - public HomeDownloadsViewModel(IDownloadTaskManager tasksManager) + public HomeDownloadsViewModel(IDownloadTaskManager tasksManager, INetworkService networkService, IDialogsService dialogsService, IStringResourcesService stringResourcesService) { _tasksManager = tasksManager; _tasksManager.TaskCollectionChanged += Tasks_CollectionChanged; + _networkService = networkService; + _dialogsService = dialogsService; + _stringResourcesService = stringResourcesService; + _taskListIsEmpty = _tasksManager.Tasks.Count == 0; } @@ -59,7 +70,19 @@ namespace VDownload.Core.ViewModels.Home ]; if (idleStatuses.Contains(task.Status)) { - task.Enqueue(); + bool continueEnqueue = true; + if (_networkService.IsMetered) + { + string title = _stringResourcesService.CommonResources.Get("StartAtMeteredConnectionDialogTitle"); + string message = _stringResourcesService.CommonResources.Get("StartAtMeteredConnectionDialogMessage"); + DialogResultYesNo result = await _dialogsService.ShowYesNo(title, message); + continueEnqueue = result == DialogResultYesNo.Yes; + } + + if (continueEnqueue) + { + task.Enqueue(); + } } else { diff --git a/VDownload.Core/VDownload.Core.ViewModels/Home/HomePlaylistViewModel.cs b/VDownload.Core/VDownload.Core.ViewModels/Home/HomePlaylistViewModel.cs index f509d70..0319b62 100644 --- a/VDownload.Core/VDownload.Core.ViewModels/Home/HomePlaylistViewModel.cs +++ b/VDownload.Core/VDownload.Core.ViewModels/Home/HomePlaylistViewModel.cs @@ -17,6 +17,9 @@ using VDownload.Sources.Twitch.Configuration.Models; using SimpleToolkit.MVVM; using System.Text.RegularExpressions; using VDownload.Services.Utility.Filename; +using VDownload.Services.UI.Dialogs; +using VDownload.Services.UI.StringResources; +using VDownload.Services.Utility.Network; namespace VDownload.Core.ViewModels.Home { @@ -29,6 +32,9 @@ namespace VDownload.Core.ViewModels.Home protected readonly ISettingsService _settingsService; protected readonly IStoragePickerService _storagePickerService; protected readonly IFilenameService _filenameService; + protected readonly INetworkService _networkService; + protected readonly IDialogsService _dialogsService; + protected readonly IStringResourcesService _stringResourcesService; #endregion @@ -174,12 +180,15 @@ namespace VDownload.Core.ViewModels.Home #region CONSTRUCTORS - public HomePlaylistViewModel(IDownloadTaskManager tasksManager, ISettingsService settingsService, IStoragePickerService storagePickerService, IFilenameService filenameService) + public HomePlaylistViewModel(IDownloadTaskManager tasksManager, ISettingsService settingsService, IStoragePickerService storagePickerService, IFilenameService filenameService, INetworkService networkService, IDialogsService dialogsService, IStringResourcesService stringResourcesService) { _tasksManager = tasksManager; _settingsService = settingsService; _storagePickerService = storagePickerService; _filenameService = filenameService; + _networkService = networkService; + _dialogsService = dialogsService; + _stringResourcesService = stringResourcesService; _removedVideos = new List(); @@ -271,10 +280,10 @@ namespace VDownload.Core.ViewModels.Home } [RelayCommand] - public void CreateTasksAndDownload() => CreateTasks(true); + public async Task CreateTasksAndDownload() => await CreateTasks(true); [RelayCommand] - public void CreateTasks() => CreateTasks(false); + public async Task CreateTasks() => await CreateTasks(false); #endregion @@ -282,8 +291,16 @@ namespace VDownload.Core.ViewModels.Home #region PRIVATE METHODS - protected void CreateTasks(bool download) + protected async Task CreateTasks(bool download) { + if (download && _networkService.IsMetered) + { + string title = _stringResourcesService.CommonResources.Get("StartAtMeteredConnectionDialogTitle"); + string message = _stringResourcesService.CommonResources.Get("StartAtMeteredConnectionDialogMessage"); + DialogResultYesNo result = await _dialogsService.ShowYesNo(title, message); + download = result == DialogResultYesNo.Yes; + } + IEnumerable videos = Videos.Cast>() .Where(x => x.Value) .Select(x => x.Key); diff --git a/VDownload.Core/VDownload.Core.ViewModels/Home/HomeVideoViewModel.cs b/VDownload.Core/VDownload.Core.ViewModels/Home/HomeVideoViewModel.cs index be75bed..f0494bf 100644 --- a/VDownload.Core/VDownload.Core.ViewModels/Home/HomeVideoViewModel.cs +++ b/VDownload.Core/VDownload.Core.ViewModels/Home/HomeVideoViewModel.cs @@ -10,8 +10,11 @@ using System.Threading.Tasks; using VDownload.Core.Tasks; using VDownload.Models; using VDownload.Services.Data.Settings; +using VDownload.Services.UI.Dialogs; using VDownload.Services.UI.StoragePicker; +using VDownload.Services.UI.StringResources; using VDownload.Services.Utility.Filename; +using VDownload.Services.Utility.Network; namespace VDownload.Core.ViewModels.Home { @@ -24,6 +27,9 @@ namespace VDownload.Core.ViewModels.Home protected readonly ISettingsService _settingsService; protected readonly IStoragePickerService _storagePickerService; protected readonly IFilenameService _filenameService; + protected readonly INetworkService _networkService; + protected readonly IDialogsService _dialogsService; + protected readonly IStringResourcesService _stringResourcesService; #endregion @@ -91,12 +97,15 @@ namespace VDownload.Core.ViewModels.Home #region CONSTRUCTORS - public HomeVideoViewModel(IDownloadTaskManager tasksManager, ISettingsService settingsService, IStoragePickerService storagePickerService, IFilenameService filenameService) + public HomeVideoViewModel(IDownloadTaskManager tasksManager, ISettingsService settingsService, IStoragePickerService storagePickerService, IFilenameService filenameService, INetworkService networkService, IDialogsService dialogsService, IStringResourcesService stringResourcesService) { _tasksManager = tasksManager; _settingsService = settingsService; _storagePickerService = storagePickerService; _filenameService = filenameService; + _networkService = networkService; + _dialogsService = dialogsService; + _stringResourcesService = stringResourcesService; } #endregion @@ -141,19 +150,10 @@ namespace VDownload.Core.ViewModels.Home } [RelayCommand] - public void CreateTask() - { - _tasksManager.AddTask(_video, BuildDownloadOptions()); - CloseRequested?.Invoke(this, EventArgs.Empty); - } + public async Task CreateTask() => await CreateTask(false); [RelayCommand] - public void CreateTaskAndDownload() - { - DownloadTask task = _tasksManager.AddTask(_video, BuildDownloadOptions()); - CloseRequested?.Invoke(this, EventArgs.Empty); - task.Enqueue(); - } + public async Task CreateTaskAndDownload() => await CreateTask(true); #endregion @@ -161,6 +161,24 @@ namespace VDownload.Core.ViewModels.Home #region PRIVATE METHODS + protected async Task CreateTask(bool download) + { + if (download && _networkService.IsMetered) + { + string title = _stringResourcesService.CommonResources.Get("StartAtMeteredConnectionDialogTitle"); + string message = _stringResourcesService.CommonResources.Get("StartAtMeteredConnectionDialogMessage"); + DialogResultYesNo result = await _dialogsService.ShowYesNo(title, message); + download = result == DialogResultYesNo.Yes; + } + + DownloadTask task = _tasksManager.AddTask(_video, BuildDownloadOptions()); + CloseRequested?.Invoke(this, EventArgs.Empty); + if (download) + { + task.Enqueue(); + } + } + protected VideoDownloadOptions BuildDownloadOptions() { return new VideoDownloadOptions(Duration) diff --git a/VDownload.Core/VDownload.Core.ViewModels/Home/HomeViewModel.cs b/VDownload.Core/VDownload.Core.ViewModels/Home/HomeViewModel.cs index 2a32d43..62d6c23 100644 --- a/VDownload.Core/VDownload.Core.ViewModels/Home/HomeViewModel.cs +++ b/VDownload.Core/VDownload.Core.ViewModels/Home/HomeViewModel.cs @@ -9,9 +9,12 @@ using VDownload.Core.Tasks; using VDownload.Models; using VDownload.Services.Data.Configuration; using VDownload.Services.Data.Settings; +using VDownload.Services.UI.Dialogs; using VDownload.Services.UI.StringResources; +using VDownload.Services.Utility.Network; using VDownload.Sources; using VDownload.Sources.Common; +using VDownload.Sources.Twitch.Configuration.Models; namespace VDownload.Core.ViewModels.Home { @@ -49,6 +52,8 @@ namespace VDownload.Core.ViewModels.Home protected readonly ISettingsService _settingsService; protected readonly IStringResourcesService _stringResourcesService; protected readonly ISearchService _searchService; + protected readonly INetworkService _networkService; + protected readonly IDialogsService _dialogsService; protected readonly IDownloadTaskManager _downloadTaskManager; @@ -108,12 +113,14 @@ namespace VDownload.Core.ViewModels.Home #region CONSTRUCTORS - public HomeViewModel(IConfigurationService configurationService, ISettingsService settingsService, IStringResourcesService stringResourcesService, ISearchService searchService, IDownloadTaskManager downloadTaskManager, HomeVideoViewModel videoViewModel, HomePlaylistViewModel playlistViewModel) + public HomeViewModel(IConfigurationService configurationService, ISettingsService settingsService, IStringResourcesService stringResourcesService, ISearchService searchService, INetworkService networkService, IDialogsService dialogsService, IDownloadTaskManager downloadTaskManager, HomeVideoViewModel videoViewModel, HomePlaylistViewModel playlistViewModel) { _configurationService = configurationService; _settingsService = settingsService; _stringResourcesService = stringResourcesService; _searchService = searchService; + _networkService = networkService; + _dialogsService = dialogsService; _downloadTaskManager = downloadTaskManager; @@ -258,8 +265,19 @@ namespace VDownload.Core.ViewModels.Home } [RelayCommand] - public void Download() + public async Task Download() { + if (_downloadTaskManager.Tasks.Count > 0 && _networkService.IsMetered) + { + string title = _stringResourcesService.CommonResources.Get("StartAtMeteredConnectionDialogTitle"); + string message = _stringResourcesService.CommonResources.Get("StartAtMeteredConnectionDialogMessage"); + DialogResultYesNo result = await _dialogsService.ShowYesNo(title, message); + if (result == DialogResultYesNo.No) + { + return; + } + } + foreach (DownloadTask task in _downloadTaskManager.Tasks) { task.Enqueue(); diff --git a/VDownload.Core/VDownload.Core.ViewModels/VDownload.Core.ViewModels.csproj b/VDownload.Core/VDownload.Core.ViewModels/VDownload.Core.ViewModels.csproj index bf7da03..5b32417 100644 --- a/VDownload.Core/VDownload.Core.ViewModels/VDownload.Core.ViewModels.csproj +++ b/VDownload.Core/VDownload.Core.ViewModels/VDownload.Core.ViewModels.csproj @@ -18,6 +18,7 @@ + diff --git a/VDownload.Services.Utility.Network/NetworkService.cs b/VDownload.Services.Utility.Network/NetworkService.cs new file mode 100644 index 0000000..313d3f2 --- /dev/null +++ b/VDownload.Services.Utility.Network/NetworkService.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.Networking.Connectivity; + +namespace VDownload.Services.Utility.Network +{ + public interface INetworkService + { + bool IsMetered { get; } + } + + + + public class NetworkService : INetworkService + { + #region FIELDS + + protected readonly IEnumerable _notMeteredTypes = [ + NetworkCostType.Unknown, + NetworkCostType.Unrestricted + ]; + + #endregion + + + + #region PROPERTIES + + public bool IsMetered => !_notMeteredTypes.Contains(NetworkInformation.GetInternetConnectionProfile().GetConnectionCost().NetworkCostType); + + #endregion + } +} diff --git a/VDownload.Services.Utility.Network/VDownload.Services.Utility.Network.csproj b/VDownload.Services.Utility.Network/VDownload.Services.Utility.Network.csproj new file mode 100644 index 0000000..ee3a055 --- /dev/null +++ b/VDownload.Services.Utility.Network/VDownload.Services.Utility.Network.csproj @@ -0,0 +1,13 @@ + + + + netcoreapp3.1 + enable + enable + + + + + + + diff --git a/VDownload.Services/VDownload.Services.UI/VDownload.Services.UI.StringResources/StringResourcesService.cs b/VDownload.Services/VDownload.Services.UI/VDownload.Services.UI.StringResources/StringResourcesService.cs index 5fe0549..c064786 100644 --- a/VDownload.Services/VDownload.Services.UI/VDownload.Services.UI.StringResources/StringResourcesService.cs +++ b/VDownload.Services/VDownload.Services.UI/VDownload.Services.UI.StringResources/StringResourcesService.cs @@ -13,6 +13,7 @@ namespace VDownload.Services.UI.StringResources StringResources AuthenticationViewResources { get; } StringResources NotificationsResources { get; } StringResources SearchResources { get; } + StringResources CommonResources { get; } } @@ -37,6 +38,7 @@ namespace VDownload.Services.UI.StringResources public StringResources AuthenticationViewResources { get; protected set; } public StringResources NotificationsResources { get; protected set; } public StringResources SearchResources { get; protected set; } + public StringResources CommonResources { get; protected set; } #endregion @@ -56,6 +58,7 @@ namespace VDownload.Services.UI.StringResources AuthenticationViewResources = BuildResource("AuthenticationViewResources"); NotificationsResources = BuildResource("NotificationsResources"); SearchResources = BuildResource("SearchResources"); + CommonResources = BuildResource("CommonResources"); } #endregion diff --git a/VDownload.sln b/VDownload.sln index 93ba10b..9acb368 100644 --- a/VDownload.sln +++ b/VDownload.sln @@ -69,7 +69,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VDownload.Core.Tasks", "VDo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VDownload.Services.Utility.FFmpeg", "VDownload.Services\VDownload.Services.Utility\VDownload.Services.Utility.FFmpeg\VDownload.Services.Utility.FFmpeg.csproj", "{A3166F8A-ECAD-4D4B-9BE3-96FEC799B27B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VDownload.Services.Utility.Filename", "VDownload.Services\VDownload.Services.Utility\VDownload.Services.Utility.Filename\VDownload.Services.Utility.Filename.csproj", "{4647EFB5-A206-4F47-976D-BAED11B52579}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VDownload.Services.Utility.Filename", "VDownload.Services\VDownload.Services.Utility\VDownload.Services.Utility.Filename\VDownload.Services.Utility.Filename.csproj", "{4647EFB5-A206-4F47-976D-BAED11B52579}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VDownload.Services.Utility.Network", "VDownload.Services.Utility.Network\VDownload.Services.Utility.Network.csproj", "{08AEC43D-34C3-4B19-A577-B69FF755BD7F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -521,6 +523,22 @@ Global {4647EFB5-A206-4F47-976D-BAED11B52579}.Release|x64.Build.0 = Release|Any CPU {4647EFB5-A206-4F47-976D-BAED11B52579}.Release|x86.ActiveCfg = Release|Any CPU {4647EFB5-A206-4F47-976D-BAED11B52579}.Release|x86.Build.0 = Release|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Debug|ARM64.Build.0 = Debug|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Debug|x64.ActiveCfg = Debug|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Debug|x64.Build.0 = Debug|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Debug|x86.ActiveCfg = Debug|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Debug|x86.Build.0 = Debug|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Release|Any CPU.Build.0 = Release|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Release|ARM64.ActiveCfg = Release|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Release|ARM64.Build.0 = Release|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Release|x64.ActiveCfg = Release|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Release|x64.Build.0 = Release|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Release|x86.ActiveCfg = Release|Any CPU + {08AEC43D-34C3-4B19-A577-B69FF755BD7F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -555,6 +573,7 @@ Global {3BE998A3-1126-4496-BF60-80D0CEA4D24F} = {8539067C-9968-4AEB-928C-FEDC43989A79} {A3166F8A-ECAD-4D4B-9BE3-96FEC799B27B} = {1020167A-4101-496E-82CF-41B65769DD28} {4647EFB5-A206-4F47-976D-BAED11B52579} = {1020167A-4101-496E-82CF-41B65769DD28} + {08AEC43D-34C3-4B19-A577-B69FF755BD7F} = {1020167A-4101-496E-82CF-41B65769DD28} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {9FD7B842-C3E2-4FD0-AD8A-C8E619280AB7} diff --git a/VDownload/App.xaml.cs b/VDownload/App.xaml.cs index 2e9b054..0643854 100644 --- a/VDownload/App.xaml.cs +++ b/VDownload/App.xaml.cs @@ -28,6 +28,7 @@ using VDownload.Services.Utility.Encryption; using VDownload.Services.Utility.FFmpeg; using VDownload.Services.Utility.Filename; using VDownload.Services.Utility.HttpClient; +using VDownload.Services.Utility.Network; using VDownload.Sources; using VDownload.Sources.Twitch; using VDownload.Sources.Twitch.Api; @@ -122,6 +123,7 @@ namespace VDownload services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); } protected void BuildSourcesServices(IServiceCollection services) diff --git a/VDownload/VDownload.csproj b/VDownload/VDownload.csproj index 8a756cf..8856ca1 100644 --- a/VDownload/VDownload.csproj +++ b/VDownload/VDownload.csproj @@ -170,6 +170,7 @@ +