From aac78d508a75801643368a76d2990b6c576bc7e0 Mon Sep 17 00:00:00 2001 From: croire <1432593898@qq.com> Date: Thu, 16 Jun 2022 00:12:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81UP=E4=B8=BB=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=A9=BA=E9=97=B4=E7=9A=84=E5=90=88=E9=9B=86=E5=92=8C=E5=88=97?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/SpaceSeasonsSeriesArchives.cs | 3 +- .../Users/Models/SpaceSeasonsSeriesStat.cs | 11 + DownKyi.Core/DownKyi.Core.csproj | 1 + DownKyi/App.xaml.cs | 2 + DownKyi/DownKyi.csproj | 17 + DownKyi/Images/NormalIcon.cs | 46 +- DownKyi/Languages/Default.xaml | 1 + DownKyi/ViewModels/UserSpace/SeasonsSeries.cs | 47 ++ .../UserSpace/ViewSeasonsSeriesViewModel.cs | 199 ++++++ .../ViewModels/ViewSeasonsSeriesViewModel.cs | 672 ++++++++++++++++++ DownKyi/ViewModels/ViewUserSpaceViewModel.cs | 37 +- .../Views/UserSpace/ViewSeasonsSeries.xaml | 135 ++++ .../Views/UserSpace/ViewSeasonsSeries.xaml.cs | 28 + DownKyi/Views/ViewSeasonsSeries.xaml | 331 +++++++++ DownKyi/Views/ViewSeasonsSeries.xaml.cs | 28 + 15 files changed, 1548 insertions(+), 10 deletions(-) create mode 100644 DownKyi.Core/BiliApi/Users/Models/SpaceSeasonsSeriesStat.cs create mode 100644 DownKyi/ViewModels/UserSpace/SeasonsSeries.cs create mode 100644 DownKyi/ViewModels/UserSpace/ViewSeasonsSeriesViewModel.cs create mode 100644 DownKyi/ViewModels/ViewSeasonsSeriesViewModel.cs create mode 100644 DownKyi/Views/UserSpace/ViewSeasonsSeries.xaml create mode 100644 DownKyi/Views/UserSpace/ViewSeasonsSeries.xaml.cs create mode 100644 DownKyi/Views/ViewSeasonsSeries.xaml create mode 100644 DownKyi/Views/ViewSeasonsSeries.xaml.cs diff --git a/DownKyi.Core/BiliApi/Users/Models/SpaceSeasonsSeriesArchives.cs b/DownKyi.Core/BiliApi/Users/Models/SpaceSeasonsSeriesArchives.cs index 3b23101..38daebe 100644 --- a/DownKyi.Core/BiliApi/Users/Models/SpaceSeasonsSeriesArchives.cs +++ b/DownKyi.Core/BiliApi/Users/Models/SpaceSeasonsSeriesArchives.cs @@ -19,7 +19,8 @@ namespace DownKyi.Core.BiliApi.Users.Models public string Pic { get; set; } [JsonProperty("pubdate")] public long Pubdate { get; set; } - // stat + [JsonProperty("stat")] + public SpaceSeasonsSeriesStat Stat { get; set; } // state [JsonProperty("title")] public string Title { get; set; } diff --git a/DownKyi.Core/BiliApi/Users/Models/SpaceSeasonsSeriesStat.cs b/DownKyi.Core/BiliApi/Users/Models/SpaceSeasonsSeriesStat.cs new file mode 100644 index 0000000..ef53bd2 --- /dev/null +++ b/DownKyi.Core/BiliApi/Users/Models/SpaceSeasonsSeriesStat.cs @@ -0,0 +1,11 @@ +using DownKyi.Core.BiliApi.Models; +using Newtonsoft.Json; + +namespace DownKyi.Core.BiliApi.Users.Models +{ + public class SpaceSeasonsSeriesStat : BaseModel + { + [JsonProperty("view")] + public long View { get; set; } + } +} diff --git a/DownKyi.Core/DownKyi.Core.csproj b/DownKyi.Core/DownKyi.Core.csproj index 4ee018b..ba9c276 100644 --- a/DownKyi.Core/DownKyi.Core.csproj +++ b/DownKyi.Core/DownKyi.Core.csproj @@ -223,6 +223,7 @@ + diff --git a/DownKyi/App.xaml.cs b/DownKyi/App.xaml.cs index cae6342..e09d666 100644 --- a/DownKyi/App.xaml.cs +++ b/DownKyi/App.xaml.cs @@ -180,6 +180,7 @@ namespace DownKyi containerRegistry.RegisterForNavigation(ViewUserSpaceViewModel.Tag); containerRegistry.RegisterForNavigation(ViewPublicationViewModel.Tag); containerRegistry.RegisterForNavigation(ViewModels.ViewChannelViewModel.Tag); + containerRegistry.RegisterForNavigation(ViewModels.ViewSeasonsSeriesViewModel.Tag); containerRegistry.RegisterForNavigation(ViewMySpaceViewModel.Tag); containerRegistry.RegisterForNavigation(ViewMyFavoritesViewModel.Tag); @@ -206,6 +207,7 @@ namespace DownKyi // UserSpace containerRegistry.RegisterForNavigation(ViewArchiveViewModel.Tag); containerRegistry.RegisterForNavigation(ViewModels.UserSpace.ViewChannelViewModel.Tag); + containerRegistry.RegisterForNavigation(ViewModels.UserSpace.ViewSeasonsSeriesViewModel.Tag); // dialogs containerRegistry.RegisterDialog(ViewAlertDialogViewModel.Tag); diff --git a/DownKyi/DownKyi.csproj b/DownKyi/DownKyi.csproj index 328074d..aac8fe5 100644 --- a/DownKyi/DownKyi.csproj +++ b/DownKyi/DownKyi.csproj @@ -164,12 +164,15 @@ + + + @@ -234,9 +237,15 @@ ViewArchive.xaml + + ViewSeasonsSeries.xaml + ViewChannel.xaml + + ViewSeasonsSeries.xaml + ViewChannel.xaml @@ -426,10 +435,18 @@ Designer MSBuild:Compile + + MSBuild:Compile + Designer + Designer MSBuild:Compile + + MSBuild:Compile + Designer + Designer MSBuild:Compile diff --git a/DownKyi/Images/NormalIcon.cs b/DownKyi/Images/NormalIcon.cs index 7977bf2..669c798 100644 --- a/DownKyi/Images/NormalIcon.cs +++ b/DownKyi/Images/NormalIcon.cs @@ -1,4 +1,6 @@ -namespace DownKyi.Images +using DownKyi.ViewModels.UserSpace; + +namespace DownKyi.Images { public class NormalIcon { @@ -267,6 +269,46 @@ Fill = "#FF000000" }; + Channel1 = new VectorImage + { + Height = 24, + Width = 24, + Data = @"M116.57 0 q-30.86 0 -57.71 16 q-26.85 16 -42.85 42.85 q-16 26.85 -16 57.71 l0 468.57 q0 30.86 16 57.72 + q16 26.86 42.85 42.86 q26.85 16 57.71 16 l643.43 0 q32 0 58.86 -16 q26.86 -16 42.86 -42.86 + q16 -26.86 16 -57.72 l0 -468.57 q0 -30.86 -16 -57.71 q-16 -26.85 -42.86 -42.85 q-26.86 -16 -58.86 -16 + l-643.43 0 ZM262.86 848 q-40 0 -72.57 -25.71 q-32.58 -25.72 -39.43 -62.29 l697.14 0 q36.57 0 62.29 -25.71 + q25.71 -25.72 25.71 -62.29 l0 -521.14 q37.71 11.43 62.86 42.28 q25.14 30.86 25.14 69.72 l0 468.57 + q0 30.86 -16 57.72 q-16 26.86 -42.86 42.86 q-26.86 16 -58.86 16 l-643.43 0 ZM88 174.86 + q0 -36.57 25.14 -62.29 q25.14 -25.71 61.72 -25.71 l526.85 0 q36.58 0 62.29 25.71 q25.71 25.72 25.71 62.29 + l0 350.85 q0 36.58 -25.71 62.29 q-25.71 25.71 -62.29 25.71 l-526.85 0 q-36.57 0 -61.72 -25.71 + q-25.14 -25.71 -25.14 -62.29 l0 -350.85 ZM609.14 374.86 q11.43 -6.86 11.43 -22.29 q0 -15.43 -11.43 -26.86 + l-214.85 -146.28 q-13.72 -10.29 -28.57 -1.72 q-14.86 8.58 -14.86 26.86 l0 297.14 q0 18.29 14.86 26.86 + q14.85 8.57 28.57 -2.86 l214.85 -150.85 Z", + Fill = "#FF000000" + }; + + SeasonsSeries = new VectorImage + { + Height = 24, + Width = 24, + Data = @"M974.2 382.22 l-401.47 177.37 q-28.88 13.75 -60.5 13.75 q-31.62 0 -60.5 -13.75 l-400.09 -177.37 + q-20.63 -11 -33 -30.25 q-12.38 -19.25 -13.06 -43.31 q-0.68 -24.06 10.32 -45.38 q11 -21.32 31.62 -35.07 + l402.85 -210.36 q28.87 -17.87 63.25 -17.87 q34.38 0 63.25 19.25 l398.72 207.61 q22 12.37 33.69 34.37 + q11.68 22 10.31 46.06 q-1.38 24.06 -13.06 44 q-11.69 19.94 -32.31 30.94 ZM939.83 292.86 l-400.1 -207.62 + q-11 -8.25 -24.75 -9.62 q-16.5 1.37 -30.25 9.62 l-400.1 207.62 q-2.75 6.87 -2.75 12.37 q0 5.5 4.13 9.62 + l397.35 175.99 q20.62 9.63 28.18 9.63 q7.56 0 26.81 -8.25 l404.22 -178.74 q1.38 -11 -4.12 -20.62 + l1.38 0 ZM20.01 512.84 q8.25 -4.12 19.25 -4.12 q11 0 19.25 5.5 q16.5 9.62 39.87 20.62 l413.85 186.99 + l394.6 -178.74 l60.49 -30.25 q9.63 -4.12 19.94 -4.12 q10.31 0 19.25 5.5 q8.94 5.5 13.75 15.12 + q4.81 9.63 3.43 19.25 q-1.37 23.37 -21.99 31.62 l-64.62 31.62 l-424.85 193.87 l-422.1 -192.49 + q-35.74 -12.38 -68.74 -33 q-9.63 -5.5 -15.13 -14.43 q-5.5 -8.94 -6.18 -19.25 q-0.69 -10.32 4.82 -19.25 + q5.5 -8.94 15.12 -14.44 l0 0 ZM58.51 732.83 q17.87 9.62 41.25 20.62 l412.47 186.99 l394.6 -178.74 + l60.49 -30.25 q9.63 -5.5 19.94 -4.81 q10.31 0.69 19.25 6.18 q8.94 5.5 13.75 15.12 q4.81 9.63 3.43 19.94 + q-1.37 10.32 -6.87 18.57 q-5.5 8.25 -15.12 12.37 l-64.62 31.62 l-424.85 192.49 l-422.1 -191.11 + q-35.74 -13.75 -68.74 -34.37 q-13.75 -6.88 -17.88 -22 q-4.13 -15.13 3.44 -28.87 q7.56 -13.75 22.68 -17.87 + q15.13 -4.13 28.88 4.13 Z", + Fill = "#FF000000" + }; + PlatformIpad = new VectorImage { Height = 16, @@ -357,6 +399,8 @@ public VectorImage VideoUp { get; private set; } public VectorImage Channel { get; private set; } + public VectorImage Channel1 { get; private set; } + public VectorImage SeasonsSeries { get; private set; } public VectorImage PlatformIpad { get; private set; } public VectorImage PlatformMobile { get; private set; } diff --git a/DownKyi/Languages/Default.xaml b/DownKyi/Languages/Default.xaml index 4cedf8c..ce65c29 100644 --- a/DownKyi/Languages/Default.xaml +++ b/DownKyi/Languages/Default.xaml @@ -63,6 +63,7 @@ 全部 投稿视频 频道 + 合集和列表 请稍等,马上就好~ diff --git a/DownKyi/ViewModels/UserSpace/SeasonsSeries.cs b/DownKyi/ViewModels/UserSpace/SeasonsSeries.cs new file mode 100644 index 0000000..0641112 --- /dev/null +++ b/DownKyi/ViewModels/UserSpace/SeasonsSeries.cs @@ -0,0 +1,47 @@ +using DownKyi.Images; +using Prism.Mvvm; +using System.Windows.Media; + +namespace DownKyi.ViewModels.UserSpace +{ + public class SeasonsSeries : BindableBase + { + public long Id { get; set; } + + private ImageSource cover; + public ImageSource Cover + { + get => cover; + set => SetProperty(ref cover, value); + } + + private VectorImage typeImage; + public VectorImage TypeImage + { + get => typeImage; + set => SetProperty(ref typeImage, value); + } + + private string name; + public string Name + { + get => name; + set => SetProperty(ref name, value); + } + + private int count; + public int Count + { + get => count; + set => SetProperty(ref count, value); + } + + private string ctime; + public string Ctime + { + get => ctime; + set => SetProperty(ref ctime, value); + } + + } +} diff --git a/DownKyi/ViewModels/UserSpace/ViewSeasonsSeriesViewModel.cs b/DownKyi/ViewModels/UserSpace/ViewSeasonsSeriesViewModel.cs new file mode 100644 index 0000000..b8f783b --- /dev/null +++ b/DownKyi/ViewModels/UserSpace/ViewSeasonsSeriesViewModel.cs @@ -0,0 +1,199 @@ +using DownKyi.Core.BiliApi.Users.Models; +using DownKyi.Core.Storage; +using DownKyi.Events; +using DownKyi.Images; +using Prism.Commands; +using Prism.Events; +using Prism.Regions; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; + +namespace DownKyi.ViewModels.UserSpace +{ + public class ViewSeasonsSeriesViewModel : BaseViewModel + { + public const string Tag = "PageUserSpaceSeasonsSeries"; + + private long mid = -1; + + #region 页面属性申明 + + private ObservableCollection seasonsSeries; + public ObservableCollection SeasonsSeries + { + get => seasonsSeries; + set => SetProperty(ref seasonsSeries, value); + } + + private int selectedItem; + public int SelectedItem + { + get => selectedItem; + set => SetProperty(ref selectedItem, value); + } + + #endregion + + public ViewSeasonsSeriesViewModel(IEventAggregator eventAggregator) : base(eventAggregator) + { + #region 属性初始化 + + SeasonsSeries = new ObservableCollection(); + + #endregion + } + + #region 命令申明 + + // 视频选择事件 + private DelegateCommand seasonsSeriesCommand; + public DelegateCommand SeasonsSeriesCommand => seasonsSeriesCommand ?? (seasonsSeriesCommand = new DelegateCommand(ExecuteSeasonsSeriesCommand)); + + /// + /// 视频选择事件 + /// + /// + private void ExecuteSeasonsSeriesCommand(object parameter) + { + if (!(parameter is SeasonsSeries seasonsSeries)) { return; } + + // 应该用枚举的,偷懒直接用数字 + int type = 0; + if (seasonsSeries.TypeImage == NormalIcon.Instance().SeasonsSeries) + { + type = 1; + } + else if (seasonsSeries.TypeImage == NormalIcon.Instance().Channel1) + { + type = 2; + } + Dictionary data = new Dictionary + { + { "mid", mid }, + { "id", seasonsSeries.Id }, + { "name", seasonsSeries.Name }, + { "count", seasonsSeries.Count }, + { "type", type } + }; + + // 进入视频页面 + NavigationParam param = new NavigationParam + { + ViewName = ViewModels.ViewSeasonsSeriesViewModel.Tag, + ParentViewName = ViewUserSpaceViewModel.Tag, + Parameter = data + }; + eventAggregator.GetEvent().Publish(param); + + SelectedItem = -1; + } + + #endregion + + public override void OnNavigatedFrom(NavigationContext navigationContext) + { + base.OnNavigatedFrom(navigationContext); + + SeasonsSeries.Clear(); + SelectedItem = -1; + } + + /// + /// 接收mid参数 + /// + /// + public async override void OnNavigatedTo(NavigationContext navigationContext) + { + base.OnNavigatedTo(navigationContext); + + SeasonsSeries.Clear(); + SelectedItem = -1; + + // 根据传入参数不同执行不同任务 + var parameter = navigationContext.Parameters.GetValue("object"); + if (parameter == null) + { + return; + } + + // 传入mid + mid = navigationContext.Parameters.GetValue("mid"); + + foreach (var item in parameter.SeasonsList) + { + if (item.Meta.Total <= 0) { continue; } + + BitmapImage image = null; + if (item.Meta.Cover == null || item.Meta.Cover == "") + { + image = new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")); + } + else + { + StorageCover storageCover = new StorageCover(); + string cover = null; + await Task.Run(() => + { + cover = storageCover.GetCover(item.Meta.Cover); + }); + image = storageCover.GetCoverThumbnail(cover, 190, 190); + } + + // 当地时区 + DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); + DateTime dateCTime = startTime.AddSeconds(item.Meta.Ptime); + string mtime = dateCTime.ToString("yyyy-MM-dd"); + + SeasonsSeries.Add(new SeasonsSeries + { + Id = item.Meta.SeasonId, + Cover = image, + TypeImage = NormalIcon.Instance().SeasonsSeries, + Name = item.Meta.Name, + Count = item.Meta.Total, + Ctime = mtime + }); + } + + foreach (var item in parameter.SeriesList) + { + if (item.Meta.Total <= 0) { continue; } + + BitmapImage image = null; + if (item.Meta.Cover == null || item.Meta.Cover == "") + { + image = new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")); + } + else + { + StorageCover storageCover = new StorageCover(); + string cover = null; + await Task.Run(() => + { + cover = storageCover.GetCover(item.Meta.Cover); + }); + image = storageCover.GetCoverThumbnail(cover, 190, 190); + } + + // 当地时区 + DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); + DateTime dateCTime = startTime.AddSeconds(item.Meta.Mtime); + string mtime = dateCTime.ToString("yyyy-MM-dd"); + + SeasonsSeries.Add(new SeasonsSeries + { + Id = item.Meta.SeriesId, + Cover = image, + TypeImage = NormalIcon.Instance().Channel1, + Name = item.Meta.Name, + Count = item.Meta.Total, + Ctime = mtime + }); + } + + } + } +} diff --git a/DownKyi/ViewModels/ViewSeasonsSeriesViewModel.cs b/DownKyi/ViewModels/ViewSeasonsSeriesViewModel.cs new file mode 100644 index 0000000..0c4377f --- /dev/null +++ b/DownKyi/ViewModels/ViewSeasonsSeriesViewModel.cs @@ -0,0 +1,672 @@ +using DownKyi.Core.BiliApi.VideoStream; +using DownKyi.Core.Storage; +using DownKyi.Core.Utils; +using DownKyi.CustomControl; +using DownKyi.Events; +using DownKyi.Images; +using DownKyi.Services; +using DownKyi.Services.Download; +using DownKyi.Utils; +using DownKyi.ViewModels.PageViewModels; +using Prism.Commands; +using Prism.Events; +using Prism.Regions; +using Prism.Services.Dialogs; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media.Imaging; + +namespace DownKyi.ViewModels +{ + public class ViewSeasonsSeriesViewModel : BaseViewModel + { + public const string Tag = "PageSeasonsSeries"; + + private readonly IDialogService dialogService; + + private CancellationTokenSource tokenSource; + + private long mid = -1; + private long id = -1; + private int type = 0; + + // 每页视频数量,暂时在此写死,以后在设置中增加选项 + private readonly int VideoNumberInPage = 30; + + #region 页面属性申明 + + private string pageName = Tag; + public string PageName + { + get => pageName; + set => SetProperty(ref pageName, value); + } + + private GifImage loading; + public GifImage Loading + { + get => loading; + set => SetProperty(ref loading, value); + } + + private Visibility loadingVisibility; + public Visibility LoadingVisibility + { + get => loadingVisibility; + set => SetProperty(ref loadingVisibility, value); + } + + private Visibility noDataVisibility; + public Visibility NoDataVisibility + { + get => noDataVisibility; + set => SetProperty(ref noDataVisibility, value); + } + + private VectorImage arrowBack; + public VectorImage ArrowBack + { + get => arrowBack; + set => SetProperty(ref arrowBack, value); + } + + private VectorImage downloadManage; + public VectorImage DownloadManage + { + get => downloadManage; + set => SetProperty(ref downloadManage, value); + } + + private string title; + public string Title + { + get => title; + set => SetProperty(ref title, value); + } + + private bool isEnabled = true; + public bool IsEnabled + { + get => isEnabled; + set => SetProperty(ref isEnabled, value); + } + + private CustomPagerViewModel pager; + public CustomPagerViewModel Pager + { + get => pager; + set => SetProperty(ref pager, value); + } + + private ObservableCollection medias; + public ObservableCollection Medias + { + get => medias; + set => SetProperty(ref medias, value); + } + + private bool isSelectAll; + public bool IsSelectAll + { + get => isSelectAll; + set => SetProperty(ref isSelectAll, value); + } + + #endregion + + public ViewSeasonsSeriesViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator) + { + this.dialogService = dialogService; + + #region 属性初始化 + + // 初始化loading gif + Loading = new GifImage(Properties.Resources.loading); + Loading.StartAnimate(); + LoadingVisibility = Visibility.Collapsed; + NoDataVisibility = Visibility.Collapsed; + + ArrowBack = NavigationIcon.Instance().ArrowBack; + ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); + + // 下载管理按钮 + DownloadManage = ButtonIcon.Instance().DownloadManage; + DownloadManage.Height = 24; + DownloadManage.Width = 24; + DownloadManage.Fill = DictionaryResource.GetColor("ColorPrimary"); + + Medias = new ObservableCollection(); + + #endregion + } + + #region 命令申明 + + // 返回事件 + private DelegateCommand backSpaceCommand; + public DelegateCommand BackSpaceCommand => backSpaceCommand ?? (backSpaceCommand = new DelegateCommand(ExecuteBackSpace)); + + /// + /// 返回事件 + /// + private void ExecuteBackSpace() + { + ArrowBack.Fill = DictionaryResource.GetColor("ColorText"); + + // 结束任务 + tokenSource?.Cancel(); + + NavigationParam parameter = new NavigationParam + { + ViewName = ParentView, + ParentViewName = null, + Parameter = null + }; + eventAggregator.GetEvent().Publish(parameter); + } + + // 前往下载管理页面 + private DelegateCommand downloadManagerCommand; + public DelegateCommand DownloadManagerCommand => downloadManagerCommand ?? (downloadManagerCommand = new DelegateCommand(ExecuteDownloadManagerCommand)); + + /// + /// 前往下载管理页面 + /// + private void ExecuteDownloadManagerCommand() + { + NavigationParam parameter = new NavigationParam + { + ViewName = ViewDownloadManagerViewModel.Tag, + ParentViewName = Tag, + Parameter = null + }; + eventAggregator.GetEvent().Publish(parameter); + } + + // 全选按钮点击事件 + private DelegateCommand selectAllCommand; + public DelegateCommand SelectAllCommand => selectAllCommand ?? (selectAllCommand = new DelegateCommand(ExecuteSelectAllCommand)); + + /// + /// 全选按钮点击事件 + /// + /// + private void ExecuteSelectAllCommand(object parameter) + { + if (IsSelectAll) + { + foreach (var item in Medias) + { + item.IsSelected = true; + } + } + else + { + foreach (var item in Medias) + { + item.IsSelected = false; + } + } + } + + // 列表选择事件 + private DelegateCommand mediasCommand; + public DelegateCommand MediasCommand => mediasCommand ?? (mediasCommand = new DelegateCommand(ExecuteMediasCommand)); + + /// + /// 列表选择事件 + /// + /// + private void ExecuteMediasCommand(object parameter) + { + if (!(parameter is IList selectedMedia)) { return; } + + if (selectedMedia.Count == Medias.Count) + { + IsSelectAll = true; + } + else + { + IsSelectAll = false; + } + } + + // 添加选中项到下载列表事件 + private DelegateCommand addToDownloadCommand; + public DelegateCommand AddToDownloadCommand => addToDownloadCommand ?? (addToDownloadCommand = new DelegateCommand(ExecuteAddToDownloadCommand)); + + /// + /// 添加选中项到下载列表事件 + /// + private void ExecuteAddToDownloadCommand() + { + AddToDownload(true); + } + + // 添加所有视频到下载列表事件 + private DelegateCommand addAllToDownloadCommand; + public DelegateCommand AddAllToDownloadCommand => addAllToDownloadCommand ?? (addAllToDownloadCommand = new DelegateCommand(ExecuteAddAllToDownloadCommand)); + + /// + /// 添加所有视频到下载列表事件 + /// + private void ExecuteAddAllToDownloadCommand() + { + AddToDownload(false); + } + + #endregion + + /// + /// 添加到下载 + /// + /// + private async void AddToDownload(bool isOnlySelected) + { + // 频道里只有视频 + AddToDownloadService addToDownloadService = new AddToDownloadService(PlayStreamType.VIDEO); + + // 选择文件夹 + string directory = addToDownloadService.SetDirectory(dialogService); + + // 视频计数 + int i = 0; + await Task.Run(() => + { + // 为了避免执行其他操作时, + // Medias变化导致的异常 + var list = Medias.ToList(); + + // 添加到下载 + foreach (var media in list) + { + // 只下载选中项,跳过未选中项 + if (isOnlySelected && !media.IsSelected) { continue; } + + /// 有分P的就下载全部 + + // 开启服务 + VideoInfoService videoInfoService = new VideoInfoService(media.Bvid); + + addToDownloadService.SetVideoInfoService(videoInfoService); + addToDownloadService.GetVideo(); + addToDownloadService.ParseVideo(videoInfoService); + // 下载 + i += addToDownloadService.AddToDownload(eventAggregator, directory); + } + }); + + if (directory == null) + { + return; + } + + // 通知用户添加到下载列表的结果 + if (i <= 0) + { + eventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipAddDownloadingZero")); + } + else + { + eventAggregator.GetEvent().Publish($"{DictionaryResource.GetString("TipAddDownloadingFinished1")}{i}{DictionaryResource.GetString("TipAddDownloadingFinished2")}"); + } + } + + private void OnCountChanged_Pager(int count) { } + + private bool OnCurrentChanged_Pager(int old, int current) + { + if (!IsEnabled) + { + //Pager.Current = old; + return false; + } + + Medias.Clear(); + IsSelectAll = false; + LoadingVisibility = Visibility.Visible; + NoDataVisibility = Visibility.Collapsed; + + //UpdateChannel(current); + + if (type == 1) { UpdateSeasons(current); } + if (type == 2) { UpdateSeries(current); } + + return true; + } + + //private async void UpdateChannel(int current) + //{ + // // 是否正在获取数据 + // // 在所有的退出分支中都需要设为true + // IsEnabled = false; + + // await Task.Run(() => + // { + // CancellationToken cancellationToken = tokenSource.Token; + + // var channels = Core.BiliApi.Users.UserSpace.GetChannelVideoList(mid, cid, current, VideoNumberInPage); + // if (channels == null || channels.Count == 0) + // { + // // 没有数据,UI提示 + // LoadingVisibility = Visibility.Collapsed; + // NoDataVisibility = Visibility.Visible; + // return; + // } + + // foreach (var video in channels) + // { + // if (video.Cid == 0) + // { + // continue; + // } + + // // 查询、保存封面 + // string coverUrl = video.Pic; + // BitmapImage cover; + // if (coverUrl == null || coverUrl == "") + // { + // cover = null; // new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")); + // } + // else + // { + // if (!coverUrl.ToLower().StartsWith("http")) + // { + // coverUrl = $"https:{video.Pic}"; + // } + + // StorageCover storageCover = new StorageCover(); + // cover = storageCover.GetCoverThumbnail(video.Aid, video.Bvid, -1, coverUrl, 200, 125); + // } + + // // 播放数 + // string play = string.Empty; + // if (video.Stat != null) + // { + // if (video.Stat.View > 0) + // { + // play = Format.FormatNumber(video.Stat.View); + // } + // else + // { + // play = "--"; + // } + // } + // else + // { + // play = "--"; + // } + + // DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区 + // DateTime dateCTime = startTime.AddSeconds(video.Ctime); + // string ctime = dateCTime.ToString("yyyy-MM-dd"); + + // App.PropertyChangeAsync(new Action(() => + // { + // ChannelMedia media = new ChannelMedia(eventAggregator) + // { + // Avid = video.Aid, + // Bvid = video.Bvid, + // Cover = cover ?? new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")), + // Duration = Format.FormatDuration3(video.Duration), + // Title = video.Title, + // PlayNumber = play, + // CreateTime = ctime + // }; + // Medias.Add(media); + + // LoadingVisibility = Visibility.Collapsed; + // NoDataVisibility = Visibility.Collapsed; + // })); + + // // 判断是否该结束线程,若为true,跳出循环 + // if (cancellationToken.IsCancellationRequested) + // { + // break; + // } + // } + + // }, (tokenSource = new CancellationTokenSource()).Token); + + // IsEnabled = true; + //} + + private async void UpdateSeasons(int current) + { + // 是否正在获取数据 + // 在所有的退出分支中都需要设为true + IsEnabled = false; + + await Task.Run(() => + { + CancellationToken cancellationToken = tokenSource.Token; + + var seasons = Core.BiliApi.Users.UserSpace.GetSeasonsDetail(mid, id, current, VideoNumberInPage); + if (seasons == null || seasons.Meta.Total == 0) + { + // 没有数据,UI提示 + LoadingVisibility = Visibility.Collapsed; + NoDataVisibility = Visibility.Visible; + return; + } + + foreach (var video in seasons.Archives) + { + //if (video.Cid == 0) + //{ + // continue; + //} + + // 查询、保存封面 + string coverUrl = video.Pic; + BitmapImage cover; + if (coverUrl == null || coverUrl == "") + { + cover = null; // new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")); + } + else + { + if (!coverUrl.ToLower().StartsWith("http")) + { + coverUrl = $"https:{video.Pic}"; + } + + StorageCover storageCover = new StorageCover(); + cover = storageCover.GetCoverThumbnail(video.Aid, video.Bvid, -1, coverUrl, 200, 125); + } + + // 播放数 + string play = string.Empty; + if (video.Stat != null) + { + if (video.Stat.View > 0) + { + play = Format.FormatNumber(video.Stat.View); + } + else + { + play = "--"; + } + } + else + { + play = "--"; + } + + DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区 + DateTime dateCTime = startTime.AddSeconds(video.Ctime); + string ctime = dateCTime.ToString("yyyy-MM-dd"); + + App.PropertyChangeAsync(new Action(() => + { + ChannelMedia media = new ChannelMedia(eventAggregator) + { + Avid = video.Aid, + Bvid = video.Bvid, + Cover = cover ?? new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")), + Duration = Format.FormatDuration3(video.Duration), + Title = video.Title, + PlayNumber = play, + CreateTime = ctime + }; + Medias.Add(media); + + LoadingVisibility = Visibility.Collapsed; + NoDataVisibility = Visibility.Collapsed; + })); + + // 判断是否该结束线程,若为true,跳出循环 + if (cancellationToken.IsCancellationRequested) + { + break; + } + } + + }, (tokenSource = new CancellationTokenSource()).Token); + + IsEnabled = true; + } + + private async void UpdateSeries(int current) + { + // 是否正在获取数据 + // 在所有的退出分支中都需要设为true + IsEnabled = false; + + await Task.Run(() => + { + CancellationToken cancellationToken = tokenSource.Token; + + var meta = Core.BiliApi.Users.UserSpace.GetSeriesMeta(id); + var series = Core.BiliApi.Users.UserSpace.GetSeriesDetail(mid, id, current, VideoNumberInPage); + if (series == null || meta.Meta.Total == 0) + { + // 没有数据,UI提示 + LoadingVisibility = Visibility.Collapsed; + NoDataVisibility = Visibility.Visible; + return; + } + + foreach (var video in series.Archives) + { + //if (video.Cid == 0) + //{ + // continue; + //} + + // 查询、保存封面 + string coverUrl = video.Pic; + BitmapImage cover; + if (coverUrl == null || coverUrl == "") + { + cover = null; // new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")); + } + else + { + if (!coverUrl.ToLower().StartsWith("http")) + { + coverUrl = $"https:{video.Pic}"; + } + + StorageCover storageCover = new StorageCover(); + cover = storageCover.GetCoverThumbnail(video.Aid, video.Bvid, -1, coverUrl, 200, 125); + } + + // 播放数 + string play = string.Empty; + if (video.Stat != null) + { + if (video.Stat.View > 0) + { + play = Format.FormatNumber(video.Stat.View); + } + else + { + play = "--"; + } + } + else + { + play = "--"; + } + + DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区 + DateTime dateCTime = startTime.AddSeconds(video.Ctime); + string ctime = dateCTime.ToString("yyyy-MM-dd"); + + App.PropertyChangeAsync(new Action(() => + { + ChannelMedia media = new ChannelMedia(eventAggregator) + { + Avid = video.Aid, + Bvid = video.Bvid, + Cover = cover ?? new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")), + Duration = Format.FormatDuration3(video.Duration), + Title = video.Title, + PlayNumber = play, + CreateTime = ctime + }; + Medias.Add(media); + + LoadingVisibility = Visibility.Collapsed; + NoDataVisibility = Visibility.Collapsed; + })); + + // 判断是否该结束线程,若为true,跳出循环 + if (cancellationToken.IsCancellationRequested) + { + break; + } + } + + }, (tokenSource = new CancellationTokenSource()).Token); + + IsEnabled = true; + } + + /// + /// 导航到VideoDetail页面时执行 + /// + /// + public override void OnNavigatedTo(NavigationContext navigationContext) + { + base.OnNavigatedTo(navigationContext); + + ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); + + DownloadManage = ButtonIcon.Instance().DownloadManage; + DownloadManage.Height = 24; + DownloadManage.Width = 24; + DownloadManage.Fill = DictionaryResource.GetColor("ColorPrimary"); + + // 根据传入参数不同执行不同任务 + var parameter = navigationContext.Parameters.GetValue>("Parameter"); + if (parameter == null) + { + return; + } + + Medias.Clear(); + IsSelectAll = false; + + mid = (long)parameter["mid"]; + id = (long)parameter["id"]; + type = (int)parameter["type"]; + Title = (string)parameter["name"]; + int count = (int)parameter["count"]; + + // 页面选择 + Pager = new CustomPagerViewModel(1, (int)Math.Ceiling((double)count / VideoNumberInPage)); + Pager.CurrentChanged += OnCurrentChanged_Pager; + Pager.CountChanged += OnCountChanged_Pager; + Pager.Current = 1; + } + + } +} diff --git a/DownKyi/ViewModels/ViewUserSpaceViewModel.cs b/DownKyi/ViewModels/ViewUserSpaceViewModel.cs index 96511b7..764cd38 100644 --- a/DownKyi/ViewModels/ViewUserSpaceViewModel.cs +++ b/DownKyi/ViewModels/ViewUserSpaceViewModel.cs @@ -220,12 +220,15 @@ namespace DownKyi.ViewModels switch (banner.Id) { - case 0: + case 0: // 投稿 regionManager.RequestNavigate("UserSpaceContentRegion", ViewArchiveViewModel.Tag, param); break; - case 1: + case 1: // 频道(弃用) regionManager.RequestNavigate("UserSpaceContentRegion", UserSpace.ViewChannelViewModel.Tag, param); break; + case 2: // 合集和列表 + regionManager.RequestNavigate("UserSpaceContentRegion", UserSpace.ViewSeasonsSeriesViewModel.Tag, param); + break; } } @@ -385,20 +388,38 @@ namespace DownKyi.ViewModels } // 频道 - List channelList = null; + //List channelList = null; + //await Task.Run(() => + //{ + // channelList = Core.BiliApi.Users.UserSpace.GetChannelList(mid); + //}); + //if (channelList != null && channelList.Count > 0) + //{ + // TabLeftBanners.Add(new TabLeftBanner + // { + // Object = channelList, + // Id = 1, + // Icon = NormalIcon.Instance().Channel, + // IconColor = "#FF23C9ED", + // Title = DictionaryResource.GetString("Channel") + // }); + //} + + // 合集和列表 + SpaceSeasonsSeries seasonsSeries = null; await Task.Run(() => { - channelList = Core.BiliApi.Users.UserSpace.GetChannelList(mid); + seasonsSeries = Core.BiliApi.Users.UserSpace.GetSeasonsSeries(mid, 1, 20); }); - if (channelList != null && channelList.Count > 0) + if (seasonsSeries != null && seasonsSeries.Page.Total > 0) { TabLeftBanners.Add(new TabLeftBanner { - Object = channelList, - Id = 1, + Object = seasonsSeries, + Id = 2, Icon = NormalIcon.Instance().Channel, IconColor = "#FF23C9ED", - Title = DictionaryResource.GetString("Channel") + Title = DictionaryResource.GetString("SeasonsSeries") }); } diff --git a/DownKyi/Views/UserSpace/ViewSeasonsSeries.xaml b/DownKyi/Views/UserSpace/ViewSeasonsSeries.xaml new file mode 100644 index 0000000..28ba580 --- /dev/null +++ b/DownKyi/Views/UserSpace/ViewSeasonsSeries.xaml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DownKyi/Views/UserSpace/ViewSeasonsSeries.xaml.cs b/DownKyi/Views/UserSpace/ViewSeasonsSeries.xaml.cs new file mode 100644 index 0000000..426cd10 --- /dev/null +++ b/DownKyi/Views/UserSpace/ViewSeasonsSeries.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace DownKyi.Views.UserSpace +{ + /// + /// ViewChannel.xaml 的交互逻辑 + /// + public partial class ViewSeasonsSeries : UserControl + { + public ViewSeasonsSeries() + { + InitializeComponent(); + } + } +} diff --git a/DownKyi/Views/ViewSeasonsSeries.xaml b/DownKyi/Views/ViewSeasonsSeries.xaml new file mode 100644 index 0000000..00070e6 --- /dev/null +++ b/DownKyi/Views/ViewSeasonsSeries.xaml @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +