diff --git a/src/Downkyi.Core/Settings/SettingsManager.cs b/src/Downkyi.Core/Settings/SettingsManager.cs index 6716091..510c88f 100644 --- a/src/Downkyi.Core/Settings/SettingsManager.cs +++ b/src/Downkyi.Core/Settings/SettingsManager.cs @@ -50,13 +50,16 @@ public partial class SettingsManager /// private AppSettings GetSettings() { + if (appSettings != null) { return appSettings; } + try { - var fileStream = new FileStream(settingsName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - var streamReader = new StreamReader(fileStream, System.Text.Encoding.UTF8); - string jsonWordTemplate = streamReader.ReadToEnd(); - streamReader.Close(); - fileStream.Close(); + string jsonWordTemplate = string.Empty; + using (var stream = new FileStream(settingsName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) + { + using var reader = new StreamReader(stream, System.Text.Encoding.UTF8); + jsonWordTemplate = reader.ReadToEnd(); + } #if DEBUG #else diff --git a/src/Downkyi.UI/Mvvm/BaseServices.cs b/src/Downkyi.UI/Mvvm/BaseServices.cs index 58035e3..ad88aa8 100644 --- a/src/Downkyi.UI/Mvvm/BaseServices.cs +++ b/src/Downkyi.UI/Mvvm/BaseServices.cs @@ -9,8 +9,12 @@ public class BaseServices public INotificationEvent NotificationEvent { get; } + public IClipboardService ClipboardService { get; } + public IDictionaryResource DictionaryResource { get; } + public IMainSearchService MainSearchService { get; } + public INavigationService NavigationService { get; } public IStoragePicker StoragePicker { get; } @@ -19,14 +23,18 @@ public class BaseServices public BaseServices(IBroadcastEvent broadcastEvent, INotificationEvent notificationEvent, + IClipboardService clipboardService, IDictionaryResource dictionaryResource, + IMainSearchService mainSearchService, INavigationService navigationService, IStoragePicker storagePicker, IStorageService storageService) { BroadcastEvent = broadcastEvent; NotificationEvent = notificationEvent; + ClipboardService = clipboardService; DictionaryResource = dictionaryResource; + MainSearchService = mainSearchService; NavigationService = navigationService; StoragePicker = storagePicker; StorageService = storageService; diff --git a/src/Downkyi.UI/Mvvm/Navigation/INavigationAware.cs b/src/Downkyi.UI/Mvvm/Navigation/INavigationAware.cs index 35e50b6..d8df6c2 100644 --- a/src/Downkyi.UI/Mvvm/Navigation/INavigationAware.cs +++ b/src/Downkyi.UI/Mvvm/Navigation/INavigationAware.cs @@ -5,4 +5,4 @@ public interface INavigationAware void OnNavigatedTo(Dictionary? parameter); void OnNavigatedFrom(Dictionary? parameter); -} +} \ No newline at end of file diff --git a/src/Downkyi.UI/Mvvm/ViewModelBase.cs b/src/Downkyi.UI/Mvvm/ViewModelBase.cs index 7b76597..9242a08 100644 --- a/src/Downkyi.UI/Mvvm/ViewModelBase.cs +++ b/src/Downkyi.UI/Mvvm/ViewModelBase.cs @@ -11,7 +11,9 @@ public abstract class ViewModelBase : ObservableObject, INavigationAware protected IBroadcastEvent BroadcastEvent => _baseServices.BroadcastEvent; protected INotificationEvent NotificationEvent => _baseServices.NotificationEvent; + protected IClipboardService ClipboardService => _baseServices.ClipboardService; protected IDictionaryResource DictionaryResource => _baseServices.DictionaryResource; + protected IMainSearchService MainSearchService => _baseServices.MainSearchService; protected INavigationService NavigationService => _baseServices.NavigationService; protected IStoragePicker StoragePicker => _baseServices.StoragePicker; protected IStorageService StorageService => _baseServices.StorageService; diff --git a/src/Downkyi.UI/Services/IClipboardService.cs b/src/Downkyi.UI/Services/IClipboardService.cs new file mode 100644 index 0000000..32c7e64 --- /dev/null +++ b/src/Downkyi.UI/Services/IClipboardService.cs @@ -0,0 +1,6 @@ +namespace Downkyi.UI.Services; + +public interface IClipboardService +{ + Task GetTextAsync(); +} \ No newline at end of file diff --git a/src/Downkyi.UI/Services/IMainSearchService.cs b/src/Downkyi.UI/Services/IMainSearchService.cs new file mode 100644 index 0000000..8064a9a --- /dev/null +++ b/src/Downkyi.UI/Services/IMainSearchService.cs @@ -0,0 +1,28 @@ +namespace Downkyi.UI.Services; + +public interface IMainSearchService +{ + /// + /// 解析支持的输入, + /// 支持的格式有: + /// av号:av170001, AV170001, https://www.bilibili.com/video/av170001 + /// BV号:BV17x411w7KC, https://www.bilibili.com/video/BV17x411w7KC, https://b23.tv/BV17x411w7KC + /// 番剧(电影、电视剧)ss号:ss32982, SS32982, https://www.bilibili.com/bangumi/play/ss32982 + /// 番剧(电影、电视剧)ep号:ep317925, EP317925, https://www.bilibili.com/bangumi/play/ep317925 + /// 番剧(电影、电视剧)md号:md28228367, MD28228367, https://www.bilibili.com/bangumi/media/md28228367 + /// 课程ss号:https://www.bilibili.com/cheese/play/ss205 + /// 课程ep号:https://www.bilibili.com/cheese/play/ep3489 + /// 收藏夹:ml1329019876, ML1329019876, https://www.bilibili.com/medialist/detail/ml1329019876, https://www.bilibili.com/medialist/play/ml1329019876/ + /// 用户空间:uid928123, UID928123, uid:928123, UID:928123, https://space.bilibili.com/928123 + /// + /// + /// + bool BiliInput(string input); + + /// + /// 搜索关键词 + /// + /// + /// + bool SearchKey(string input); +} \ No newline at end of file diff --git a/src/Downkyi.UI/Services/MainSearchService.cs b/src/Downkyi.UI/Services/MainSearchService.cs new file mode 100644 index 0000000..35f4fa4 --- /dev/null +++ b/src/Downkyi.UI/Services/MainSearchService.cs @@ -0,0 +1,140 @@ +using Downkyi.Core.Bili.Utils; +using Downkyi.Core.Settings; +using Downkyi.Core.Settings.Models; +using Downkyi.UI.ViewModels.User; +using Downkyi.UI.ViewModels.Video; + +namespace Downkyi.UI.Services; + +public class MainSearchService : IMainSearchService +{ + private readonly INavigationService NavigationService; + + public MainSearchService(INavigationService navigationService) + { + NavigationService = navigationService; + } + + public bool BiliInput(string input) + { + // 移除剪贴板id + //string validId = input.Replace(AppConstant.ClipboardId, ""); + + string validId = input; + + // 参数 + Dictionary parameter = new() + { + { "key", "MainSearchService" }, + { "value", new object() }, + }; + + // 视频 + if (ParseEntrance.IsAvId(validId)) + { + parameter["value"] = $"{ParseEntrance.VideoUrl}{validId.ToLower()}"; + NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter); + } + else if (ParseEntrance.IsAvUrl(validId)) + { + parameter["value"] = validId; + NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter); + } + else if (ParseEntrance.IsBvId(validId)) + { + parameter["value"] = $"{ParseEntrance.VideoUrl}{input}"; + NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter); + } + else if (ParseEntrance.IsBvUrl(validId)) + { + parameter["value"] = validId; + NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter); + } + // 番剧(电影、电视剧) + else if (ParseEntrance.IsBangumiSeasonId(validId)) + { + parameter["value"] = $"{ParseEntrance.BangumiUrl}{input.ToLower()}"; + NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter); + } + else if (ParseEntrance.IsBangumiSeasonUrl(validId)) + { + parameter["value"] = validId; + NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter); + } + else if (ParseEntrance.IsBangumiEpisodeId(validId)) + { + parameter["value"] = $"{ParseEntrance.BangumiUrl}{input.ToLower()}"; + NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter); + } + else if (ParseEntrance.IsBangumiEpisodeUrl(validId)) + { + parameter["value"] = validId; + NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter); + } + else if (ParseEntrance.IsBangumiMediaId(validId)) + { + parameter["value"] = $"{ParseEntrance.BangumiMediaUrl}{input.ToLower()}"; + NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter); + } + else if (ParseEntrance.IsBangumiMediaUrl(validId)) + { + parameter["value"] = validId; + NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter); + } + // 课程 + else if (ParseEntrance.IsCheeseSeasonUrl(validId) + || ParseEntrance.IsCheeseEpisodeUrl(validId)) + { + parameter["value"] = validId; + NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter); + } + // 用户(参数传入mid) + else if (ParseEntrance.IsUserId(validId) || ParseEntrance.IsUserUrl(validId)) + { + NavigateToViewUserSpace(ParseEntrance.GetUserId(input)); + } + // 收藏夹 + else if (ParseEntrance.IsFavoritesId(validId) || ParseEntrance.IsFavoritesUrl(validId)) + { + parameter["value"] = ParseEntrance.GetFavoritesId(input); + NavigationService.ForwardAsync(PublicFavoritesViewModel.Key, parameter); + } + else + { + return false; + } + return true; + } + + public bool SearchKey(string input) + { + // TODO + return false; + } + + /// + /// 导航到用户空间, + /// 如果传入的mid与本地登录的mid一致, + /// 则进入我的用户空间。 + /// + /// + private void NavigateToViewUserSpace(long mid) + { + Dictionary parameter = new() + { + { "key", "MainSearchService" }, + { "value", mid }, + }; + + UserInfoSettings userInfo = SettingsManager.GetInstance().GetUserInfo(); + if (userInfo != null && userInfo.Mid == mid) + { + NavigationService.ForwardAsync(MySpaceViewModel.Key, parameter); + } + else + { + NavigationService.ForwardAsync(UserSpaceViewModel.Key, parameter); + } + } + +} \ No newline at end of file diff --git a/src/Downkyi.UI/ViewModels/IndexViewModel.cs b/src/Downkyi.UI/ViewModels/IndexViewModel.cs index c18747d..854b3c3 100644 --- a/src/Downkyi.UI/ViewModels/IndexViewModel.cs +++ b/src/Downkyi.UI/ViewModels/IndexViewModel.cs @@ -1,15 +1,18 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Downkyi.Core.Bili; +using Downkyi.Core.Log; using Downkyi.Core.Settings; using Downkyi.Core.Settings.Models; using Downkyi.Core.Storage; using Downkyi.UI.Mvvm; +using Downkyi.UI.Services; using Downkyi.UI.ViewModels.DownloadManager; using Downkyi.UI.ViewModels.Login; using Downkyi.UI.ViewModels.Settings; using Downkyi.UI.ViewModels.Toolbox; using Downkyi.UI.ViewModels.User; +using System.Text.RegularExpressions; namespace Downkyi.UI.ViewModels; @@ -115,9 +118,29 @@ public partial class IndexViewModel : ViewModelBase #region 业务逻辑 + /// + /// 进入B站链接的处理逻辑, + /// 只负责处理输入,并跳转到视频详情页。 + /// 不是支持的格式,则进入搜索页面。 + /// private void EnterBili() { - NotificationEvent.Publish("Enter Bili!"); + if (InputText == string.Empty) + { + return; + } + Log.Logger.Debug(InputText); + + InputText = Regex.Replace(InputText, @"[【]*[^【]*[^】]*[】 ]", ""); + + bool isSupport = MainSearchService.BiliInput(InputText); + if (!isSupport) + { + // 关键词搜索 + MainSearchService.SearchKey(InputText); + } + + InputText = string.Empty; } private async Task UpdateUserInfo() diff --git a/src/Downkyi.UI/ViewModels/Settings/NetworkViewModel.cs b/src/Downkyi.UI/ViewModels/Settings/NetworkViewModel.cs index acd18b1..a85f179 100644 --- a/src/Downkyi.UI/ViewModels/Settings/NetworkViewModel.cs +++ b/src/Downkyi.UI/ViewModels/Settings/NetworkViewModel.cs @@ -114,14 +114,11 @@ public partial class NetworkViewModel : BaseSettingsViewModel for (int i = 1; i <= 10; i++) { Splits.Add(i); } // Aria的日志等级 - AriaLogLevels = new List - { - "DEBUG", - "INFO", - "NOTICE", - "WARN", - "ERROR" - }; + AriaLogLevels.Add("DEBUG"); + AriaLogLevels.Add("INFO"); + AriaLogLevels.Add("NOTICE"); + AriaLogLevels.Add("WARN"); + AriaLogLevels.Add("ERROR"); // Aria同时下载数 for (int i = 1; i <= 10; i++) { AriaMaxConcurrentDownloads.Add(i); } @@ -130,12 +127,9 @@ public partial class NetworkViewModel : BaseSettingsViewModel for (int i = 1; i <= 10; i++) { AriaSplits.Add(i); } // Aria文件预分配 - AriaFileAllocations = new List - { - "NONE", - "PREALLOC", - "FALLOC" - }; + AriaFileAllocations.Add("NONE"); + AriaFileAllocations.Add("PREALLOC"); + AriaFileAllocations.Add("FALLOC"); #endregion } @@ -288,10 +282,8 @@ public partial class NetworkViewModel : BaseSettingsViewModel /// /// [RelayCommand] - private void SetMaxCurrentDownloads(object parameter) + private void SetMaxCurrentDownloads() { - SelectedMaxCurrentDownload = (int)parameter; - bool isSucceed = SettingsManager.GetInstance().SetMaxCurrentDownloads(SelectedMaxCurrentDownload); PublishTip(Key, isSucceed); } @@ -301,10 +293,8 @@ public partial class NetworkViewModel : BaseSettingsViewModel /// /// [RelayCommand] - private void SetSplits(object parameter) + private void SetSplits() { - SelectedSplit = (int)parameter; - bool isSucceed = SettingsManager.GetInstance().SetSplit(SelectedSplit); PublishTip(Key, isSucceed); } @@ -389,9 +379,9 @@ public partial class NetworkViewModel : BaseSettingsViewModel /// /// [RelayCommand] - private void SetAriaLogLevels(string parameter) + private void SetAriaLogLevels() { - var ariaLogLevel = parameter switch + var ariaLogLevel = SelectedAriaLogLevel switch { "DEBUG" => AriaConfigLogLevel.DEBUG, "INFO" => AriaConfigLogLevel.INFO, @@ -409,10 +399,8 @@ public partial class NetworkViewModel : BaseSettingsViewModel /// /// [RelayCommand] - private void SetAriaMaxConcurrentDownloads(object parameter) + private void SetAriaMaxConcurrentDownloads() { - SelectedAriaMaxConcurrentDownload = (int)parameter; - bool isSucceed = SettingsManager.GetInstance().SetMaxCurrentDownloads(SelectedAriaMaxConcurrentDownload); PublishTip(Key, isSucceed); } @@ -422,10 +410,8 @@ public partial class NetworkViewModel : BaseSettingsViewModel /// /// [RelayCommand] - private void SetAriaSplits(object parameter) + private void SetAriaSplits() { - SelectedAriaSplit = (int)parameter; - bool isSucceed = SettingsManager.GetInstance().SetAriaSplit(SelectedAriaSplit); PublishTip(Key, isSucceed); } @@ -498,11 +484,10 @@ public partial class NetworkViewModel : BaseSettingsViewModel /// /// Aria文件预分配事件 /// - /// [RelayCommand] - private void SetAriaFileAllocations(string parameter) + private void SetAriaFileAllocations() { - var ariaFileAllocation = parameter switch + var ariaFileAllocation = SelectedAriaFileAllocation switch { "NONE" => AriaConfigFileAllocation.NONE, "PREALLOC" => AriaConfigFileAllocation.PREALLOC, diff --git a/src/Downkyi.UI/ViewModels/Video/PublicFavoritesViewModel.cs b/src/Downkyi.UI/ViewModels/Video/PublicFavoritesViewModel.cs new file mode 100644 index 0000000..4d9aacd --- /dev/null +++ b/src/Downkyi.UI/ViewModels/Video/PublicFavoritesViewModel.cs @@ -0,0 +1,29 @@ +using CommunityToolkit.Mvvm.Input; +using Downkyi.UI.Mvvm; + +namespace Downkyi.UI.ViewModels.Video; + +public partial class PublicFavoritesViewModel : ViewModelBase +{ + public const string Key = "PublicFavorites"; + + public PublicFavoritesViewModel(BaseServices baseServices) : base(baseServices) + { + } + + #region 命令申明 + + [RelayCommand(FlowExceptionsToTaskScheduler = true)] + private async Task BackwardAsync() + { + Dictionary parameter = new() + { + { "key", Key }, + }; + + await NavigationService.BackwardAsync(parameter); + } + + #endregion + +} \ No newline at end of file diff --git a/src/Downkyi.UI/ViewModels/Video/VideoDetailViewModel.cs b/src/Downkyi.UI/ViewModels/Video/VideoDetailViewModel.cs new file mode 100644 index 0000000..f664035 --- /dev/null +++ b/src/Downkyi.UI/ViewModels/Video/VideoDetailViewModel.cs @@ -0,0 +1,29 @@ +using CommunityToolkit.Mvvm.Input; +using Downkyi.UI.Mvvm; + +namespace Downkyi.UI.ViewModels.Video; + +public partial class VideoDetailViewModel : ViewModelBase +{ + public const string Key = "VideoDetail"; + + public VideoDetailViewModel(BaseServices baseServices) : base(baseServices) + { + } + + #region 命令申明 + + [RelayCommand(FlowExceptionsToTaskScheduler = true)] + private async Task BackwardAsync() + { + Dictionary parameter = new() + { + { "key", Key }, + }; + + await NavigationService.BackwardAsync(parameter); + } + + #endregion + +} \ No newline at end of file diff --git a/src/Downkyi/ServiceLocator.cs b/src/Downkyi/ServiceLocator.cs index 7f0d059..2e798b4 100644 --- a/src/Downkyi/ServiceLocator.cs +++ b/src/Downkyi/ServiceLocator.cs @@ -9,6 +9,7 @@ using Downkyi.UI.ViewModels.Login; using Downkyi.UI.ViewModels.Settings; using Downkyi.UI.ViewModels.Toolbox; using Downkyi.UI.ViewModels.User; +using Downkyi.UI.ViewModels.Video; using Downkyi.ViewModels; using Downkyi.ViewModels.Login; using Downkyi.ViewModels.Settings; @@ -92,31 +93,41 @@ public static class ServiceLocator .AddScoped() .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() //ViewModels .AddSingleton() .AddSingleton() + // + .AddSingleton() + .AddSingleton() + .AddSingleton() + // .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton() - .AddSingleton() + // .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() + // .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() + // + .AddSingleton() + .AddSingleton() + // + .AddSingleton() + .AddSingleton() .BuildServiceProvider()); } } diff --git a/src/Downkyi/Services/ClipboardService.cs b/src/Downkyi/Services/ClipboardService.cs new file mode 100644 index 0000000..600b3d7 --- /dev/null +++ b/src/Downkyi/Services/ClipboardService.cs @@ -0,0 +1,19 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Downkyi.UI.Services; +using System; +using System.Threading.Tasks; + +namespace Downkyi.Services; + +public class ClipboardService : IClipboardService +{ + public async Task GetTextAsync() + { + if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop || + desktop.MainWindow?.Clipboard is not { } provider) + throw new NullReferenceException("Missing Clipboard instance."); + + return await provider.GetTextAsync() ?? string.Empty; + } +} \ No newline at end of file diff --git a/src/Downkyi/ViewModels/MainWindowViewModel.cs b/src/Downkyi/ViewModels/MainWindowViewModel.cs index ed48015..29d1d68 100644 --- a/src/Downkyi/ViewModels/MainWindowViewModel.cs +++ b/src/Downkyi/ViewModels/MainWindowViewModel.cs @@ -1,5 +1,10 @@ -using CommunityToolkit.Mvvm.ComponentModel; +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using Downkyi.Core.Settings; +using Downkyi.Core.Settings.Enum; using Downkyi.Core.Utils; using Downkyi.UI.Mvvm; using Downkyi.UI.ViewModels; @@ -8,8 +13,10 @@ using Downkyi.UI.ViewModels.Login; using Downkyi.UI.ViewModels.Settings; using Downkyi.UI.ViewModels.Toolbox; using Downkyi.UI.ViewModels.User; +using System; using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; namespace Downkyi.ViewModels; @@ -19,6 +26,8 @@ public partial class MainWindowViewModel : ViewModelBase private readonly LinkStack _pages = new(); + private readonly CancellationTokenSource? tokenSource; + #region 页面属性申明 [ObservableProperty] @@ -55,8 +64,61 @@ public partial class MainWindowViewModel : ViewModelBase MessageVisibility = false; }); + // 监听剪贴板线程 + string oldClip = string.Empty; + Task.Run(async () => + { + CancellationToken cancellationToken = tokenSource!.Token; + + if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop || + desktop.MainWindow?.Clipboard is not { } provider) + throw new NullReferenceException("Missing Clipboard instance."); + await provider.SetTextAsync(oldClip); + + while (true) + { + AllowStatus isListenClipboard = SettingsManager.GetInstance().IsListenClipboard(); + if (isListenClipboard != AllowStatus.YES) + { + continue; + } + + // 判断是否该结束线程,若为true,跳出while循环 + if (cancellationToken.IsCancellationRequested) + { + break; + } + else + { + string clip = await ClipboardService.GetTextAsync(); + if (clip.Equals(oldClip)) + { + await Task.Delay(100); + continue; + } + + oldClip = clip; + MainSearchService.BiliInput(clip); + } + } + }, (tokenSource = new CancellationTokenSource()).Token); + } + #region 命令申明 + + /// + /// 退出窗口时执行 + /// + [RelayCommand] + private void OnClosing() + { + // 取消任务 + tokenSource?.Cancel(); + } + + #endregion + public void Forward(string viewKey, Dictionary? parameter = null) { var viewModel = SetContent(viewKey); diff --git a/src/Downkyi/Views/MainWindow.axaml b/src/Downkyi/Views/MainWindow.axaml index e7f0b1a..786e333 100644 --- a/src/Downkyi/Views/MainWindow.axaml +++ b/src/Downkyi/Views/MainWindow.axaml @@ -2,6 +2,8 @@ x:Class="Downkyi.Views.MainWindow" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity" + xmlns:ia="clr-namespace:Avalonia.Xaml.Interactions.Core;assembly=Avalonia.Xaml.Interactions" xmlns:local="using:Downkyi" xmlns:vm="using:Downkyi.ViewModels" Title="{DynamicResource AppName}" @@ -14,6 +16,11 @@ Design.DataContext="{x:Static local:ServiceLocator.MainWindowViewModel}" Icon="/Assets/logo.ico" WindowStartupLocation="CenterScreen"> + + + + + diff --git a/src/Downkyi/Views/Settings/NetworkView.axaml b/src/Downkyi/Views/Settings/NetworkView.axaml index 8be9eb9..c6c8501 100644 --- a/src/Downkyi/Views/Settings/NetworkView.axaml +++ b/src/Downkyi/Views/Settings/NetworkView.axaml @@ -87,15 +87,14 @@ VerticalAlignment="Center" Text="{DynamicResource MaxCurrentDownloads}" /> + SelectedItem="{Binding SelectedMaxCurrentDownload}"> - + @@ -107,15 +106,14 @@ VerticalAlignment="Center" Text="{DynamicResource Split}" /> + SelectedItem="{Binding SelectedSplit}"> - + @@ -203,15 +201,14 @@ VerticalAlignment="Center" Text="{DynamicResource AriaLogLevel}" /> + SelectedItem="{Binding SelectedAriaLogLevel}"> - + @@ -223,15 +220,14 @@ VerticalAlignment="Center" Text="{DynamicResource AriaMaxConcurrentDownloads}" /> + SelectedItem="{Binding SelectedAriaMaxConcurrentDownload}"> - + @@ -243,15 +239,14 @@ VerticalAlignment="Center" Text="{DynamicResource AriaSplit}" /> + SelectedItem="{Binding SelectedAriaSplit}"> - + @@ -376,7 +371,6 @@ VerticalAlignment="Center" Text="{DynamicResource AriaFileAllocation}" /> - +