diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 79221cf..0000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2021 FlySelfLog - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/src/DownKyi.Core/BiliApi/BilibiliImages.xaml b/src/DownKyi.Core/BiliApi/BilibiliImages.xaml index a2aed4a..f151f50 100644 --- a/src/DownKyi.Core/BiliApi/BilibiliImages.xaml +++ b/src/DownKyi.Core/BiliApi/BilibiliImages.xaml @@ -1,6 +1,7 @@ - + diff --git a/src/DownKyi.Core/BiliApi/Users/UserSpace.cs b/src/DownKyi.Core/BiliApi/Users/UserSpace.cs index ce85ee6..a0dee12 100644 --- a/src/DownKyi.Core/BiliApi/Users/UserSpace.cs +++ b/src/DownKyi.Core/BiliApi/Users/UserSpace.cs @@ -230,6 +230,20 @@ namespace DownKyi.Core.BiliApi.Users #endregion + #region 合集和列表 + + // TODO + // https://api.bilibili.com/x/polymer/space/seasons_series_list?mid=27899754&page_num=1&page_size=18 + // page_size最大值为20 + + // https://api.bilibili.com/x/polymer/space/seasons_archives_list?mid=23947287&season_id=665&sort_reverse=false&page_num=1&page_size=30 + + // https://api.bilibili.com/x/series/archives?mid=27899754&series_id=1253087&only_normal=true&sort=desc&pn=1&ps=30 + // https://api.bilibili.com/x/series/archives?mid=27899754&series_id=1253087&only_normal=true&sort=asc&pn=1&ps=30 + // https://api.bilibili.com/x/series/series?series_id=1253087 + + #endregion + #region 课程 /// diff --git a/src/DownKyi/App.xaml.cs b/src/DownKyi/App.xaml.cs index 59124ef..1a7b79c 100644 --- a/src/DownKyi/App.xaml.cs +++ b/src/DownKyi/App.xaml.cs @@ -164,6 +164,7 @@ namespace DownKyi containerRegistry.RegisterForNavigation(ViewUserSpaceViewModel.Tag); containerRegistry.RegisterForNavigation(ViewMySpaceViewModel.Tag); containerRegistry.RegisterForNavigation(ViewPublicFavoritesViewModel.Tag); + containerRegistry.RegisterForNavigation(ViewPublicationViewModel.Tag); // downloadManager pages containerRegistry.RegisterForNavigation(ViewDownloadingViewModel.Tag); @@ -197,6 +198,8 @@ namespace DownKyi /// public static void PropertyChangeAsync(Action callback) { + if (Current == null) { return; } + Current.Dispatcher.Invoke(callback); } diff --git a/src/DownKyi/CustomControl/CustomPager.xaml b/src/DownKyi/CustomControl/CustomPager.xaml new file mode 100644 index 0000000..499752c --- /dev/null +++ b/src/DownKyi/CustomControl/CustomPager.xaml @@ -0,0 +1,352 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/DownKyi/CustomControl/CustomPager.xaml.cs b/src/DownKyi/CustomControl/CustomPager.xaml.cs new file mode 100644 index 0000000..5aa31f5 --- /dev/null +++ b/src/DownKyi/CustomControl/CustomPager.xaml.cs @@ -0,0 +1,15 @@ +using System.Windows.Controls; + +namespace DownKyi.CustomControl +{ + /// + /// CustomPager.xaml 的交互逻辑 + /// + public partial class CustomPager : UserControl + { + public CustomPager() + { + InitializeComponent(); + } + } +} diff --git a/src/DownKyi/CustomControl/CustomPagerViewModel.cs b/src/DownKyi/CustomControl/CustomPagerViewModel.cs new file mode 100644 index 0000000..07034fb --- /dev/null +++ b/src/DownKyi/CustomControl/CustomPagerViewModel.cs @@ -0,0 +1,460 @@ +using System.ComponentModel; +using System.Windows; + +namespace DownKyi.CustomControl +{ + public class CustomPagerViewModel : INotifyPropertyChanged + { + public CustomPagerViewModel(int current, int count) + { + Current = current; + Count = count; + + SetView(); + } + + public event PropertyChangedEventHandler PropertyChanged; + + // Current修改的回调 + public delegate bool CurrentChangedHandler(int old, int current); + public event CurrentChangedHandler CurrentChanged; + protected virtual bool OnCurrentChanged(int old, int current) + { + if (CurrentChanged == null) + { + return false; + } + else + { + return CurrentChanged.Invoke(old, current); + } + } + + // Count修改的回调 + public delegate void CountChangedHandler(int count); + public event CountChangedHandler CountChanged; + protected virtual void OnCountChanged(int count) + { + CountChanged?.Invoke(count); + } + + #region 绑定属性 + + private Visibility visibility; + public Visibility Visibility + { + get { return visibility; } + set + { + visibility = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Visibility")); + } + } + + private int count; + public int Count + { + get + { + return count; + } + set + { + if (value < Current || value < 1) + { + //throw new Exception("数值不在允许的范围内。"); + System.Console.WriteLine(value.ToString()); + } + else + { + count = value; + + if (count == 1) { Visibility = Visibility.Hidden; } + else { Visibility = Visibility.Visible; } + + OnCountChanged(count); + + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count")); + } + } + } + + private int current; + public int Current + { + get + { + if (current < 1) { current = 1; } + return current; + } + set + { + if (Count > 0 && (value > Count || value < 1)) + { + //throw new Exception("数值不在允许的范围内。"); + } + else + { + bool isSuccess = OnCurrentChanged(current, value); + if (isSuccess) + { + current = value; + + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Current")); + } + } + } + } + + private int first; + public int First + { + get { return first; } + set + { + first = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("First")); + } + } + + private int previousSecond; + public int PreviousSecond + { + get { return previousSecond; } + set + { + previousSecond = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PreviousSecond")); + } + } + + private int previousFirst; + public int PreviousFirst + { + get { return previousFirst; } + set + { + previousFirst = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PreviousFirst")); + } + } + + private int nextFirst; + public int NextFirst + { + get { return nextFirst; } + set + { + nextFirst = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("NextFirst")); + } + } + + private int nextSecond; + public int NextSecond + { + get { return nextSecond; } + set + { + nextSecond = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("NextSecond")); + } + } + + // 控制Current左边的控件 + private Visibility previousVisibility; + public Visibility PreviousVisibility + { + get { return previousVisibility; } + set + { + previousVisibility = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PreviousVisibility")); + } + } + + private Visibility firstVisibility; + public Visibility FirstVisibility + { + get { return firstVisibility; } + set + { + firstVisibility = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("FirstVisibility")); + } + } + + private Visibility leftJumpVisibility; + public Visibility LeftJumpVisibility + { + get { return leftJumpVisibility; } + set + { + leftJumpVisibility = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LeftJumpVisibility")); + } + } + + private Visibility previousSecondVisibility; + public Visibility PreviousSecondVisibility + { + get { return previousSecondVisibility; } + set + { + previousSecondVisibility = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PreviousSecondVisibility")); + } + } + + private Visibility previousFirstVisibility; + public Visibility PreviousFirstVisibility + { + get { return previousFirstVisibility; } + set + { + previousFirstVisibility = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PreviousFirstVisibility")); + } + } + + // 控制Current右边的控件 + private Visibility nextFirstVisibility; + public Visibility NextFirstVisibility + { + get { return nextFirstVisibility; } + set + { + nextFirstVisibility = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("NextFirstVisibility")); + } + } + + private Visibility nextSecondVisibility; + public Visibility NextSecondVisibility + { + get { return nextSecondVisibility; } + set + { + nextSecondVisibility = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("NextSecondVisibility")); + } + } + + private Visibility rightJumpVisibility; + public Visibility RightJumpVisibility + { + get { return rightJumpVisibility; } + set + { + rightJumpVisibility = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("RightJumpVisibility")); + } + } + + private Visibility lastVisibility; + public Visibility LastVisibility + { + get { return lastVisibility; } + set + { + lastVisibility = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LastVisibility")); + } + } + + private Visibility nextVisibility; + public Visibility NextVisibility + { + get { return nextVisibility; } + set + { + nextVisibility = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("NextVisibility")); + } + } + + #endregion + + + private MyDelegateCommand previousCommand; + public MyDelegateCommand PreviousCommand => previousCommand ?? (previousCommand = new MyDelegateCommand(PreviousExecuted)); + + public void PreviousExecuted(object obj) + { + Current -= 1; + + SetView(); + } + + private MyDelegateCommand firstCommand; + public MyDelegateCommand FirstCommand => firstCommand ?? (firstCommand = new MyDelegateCommand(FirstExecuted)); + + public void FirstExecuted(object obj) + { + Current = 1; + + SetView(); + } + + private MyDelegateCommand previousSecondCommand; + public MyDelegateCommand PreviousSecondCommand => previousSecondCommand ?? (previousSecondCommand = new MyDelegateCommand(PreviousSecondExecuted)); + + public void PreviousSecondExecuted(object obj) + { + Current -= 2; + + SetView(); + } + + private MyDelegateCommand previousFirstCommand; + public MyDelegateCommand PreviousFirstCommand => previousFirstCommand ?? (previousFirstCommand = new MyDelegateCommand(PreviousFirstExecuted)); + + public void PreviousFirstExecuted(object obj) + { + Current -= 1; + + SetView(); + } + + private MyDelegateCommand nextFirstCommand; + public MyDelegateCommand NextFirstCommand => nextFirstCommand ?? (nextFirstCommand = new MyDelegateCommand(NextFirstExecuted)); + + public void NextFirstExecuted(object obj) + { + Current += 1; + + SetView(); + } + + private MyDelegateCommand nextSecondCommand; + public MyDelegateCommand NextSecondCommand => nextSecondCommand ?? (nextSecondCommand = new MyDelegateCommand(NextSecondExecuted)); + + public void NextSecondExecuted(object obj) + { + Current += 2; + + SetView(); + } + + private MyDelegateCommand lastCommand; + public MyDelegateCommand LastCommand => lastCommand ?? (lastCommand = new MyDelegateCommand(LastExecuted)); + + public void LastExecuted(object obj) + { + Current = Count; + + SetView(); + } + + private MyDelegateCommand nextCommand; + public MyDelegateCommand NextCommand => nextCommand ?? (nextCommand = new MyDelegateCommand(NextExecuted)); + + public void NextExecuted(object obj) + { + Current += 1; + + SetView(); + } + + /// + /// 控制显示,暴力实现,以后重构 + /// + private void SetView() + { + First = 1; + PreviousSecond = Current - 2; + PreviousFirst = Current - 1; + NextFirst = Current + 1; + NextSecond = Current + 2; + + // 控制Current左边的控件 + if (Current == 1) + { + PreviousVisibility = Visibility.Collapsed; + FirstVisibility = Visibility.Collapsed; + LeftJumpVisibility = Visibility.Collapsed; + PreviousSecondVisibility = Visibility.Collapsed; + PreviousFirstVisibility = Visibility.Collapsed; + } + else if (Current == 2) + { + PreviousVisibility = Visibility.Visible; + FirstVisibility = Visibility.Collapsed; + LeftJumpVisibility = Visibility.Collapsed; + PreviousSecondVisibility = Visibility.Collapsed; + PreviousFirstVisibility = Visibility.Visible; + } + else if (Current == 3) + { + PreviousVisibility = Visibility.Visible; + FirstVisibility = Visibility.Collapsed; + LeftJumpVisibility = Visibility.Collapsed; + PreviousSecondVisibility = Visibility.Visible; + PreviousFirstVisibility = Visibility.Visible; + } + else if (Current == 4) + { + PreviousVisibility = Visibility.Visible; + FirstVisibility = Visibility.Visible; + LeftJumpVisibility = Visibility.Collapsed; + PreviousSecondVisibility = Visibility.Visible; + PreviousFirstVisibility = Visibility.Visible; + } + else + { + PreviousVisibility = Visibility.Visible; + FirstVisibility = Visibility.Visible; + LeftJumpVisibility = Visibility.Visible; + PreviousSecondVisibility = Visibility.Visible; + PreviousFirstVisibility = Visibility.Visible; + } + + // 控制Current右边的控件 + if (Current == Count) + { + NextFirstVisibility = Visibility.Collapsed; + NextSecondVisibility = Visibility.Collapsed; + RightJumpVisibility = Visibility.Collapsed; + LastVisibility = Visibility.Collapsed; + NextVisibility = Visibility.Collapsed; + } + else if (Current == Count - 1) + { + NextFirstVisibility = Visibility.Visible; + NextSecondVisibility = Visibility.Collapsed; + RightJumpVisibility = Visibility.Collapsed; + LastVisibility = Visibility.Collapsed; + NextVisibility = Visibility.Visible; + } + else if (Current == Count - 2) + { + NextFirstVisibility = Visibility.Visible; + NextSecondVisibility = Visibility.Visible; + RightJumpVisibility = Visibility.Collapsed; + LastVisibility = Visibility.Collapsed; + NextVisibility = Visibility.Visible; + } + else if (Current == Count - 3) + { + NextFirstVisibility = Visibility.Visible; + NextSecondVisibility = Visibility.Visible; + RightJumpVisibility = Visibility.Collapsed; + LastVisibility = Visibility.Visible; + NextVisibility = Visibility.Visible; + } + else + { + NextFirstVisibility = Visibility.Visible; + NextSecondVisibility = Visibility.Visible; + RightJumpVisibility = Visibility.Visible; + LastVisibility = Visibility.Visible; + NextVisibility = Visibility.Visible; + } + } + + + + + + } +} diff --git a/src/DownKyi/CustomControl/MyDelegateCommand.cs b/src/DownKyi/CustomControl/MyDelegateCommand.cs new file mode 100644 index 0000000..02f95be --- /dev/null +++ b/src/DownKyi/CustomControl/MyDelegateCommand.cs @@ -0,0 +1,85 @@ +using System; +using System.Windows.Input; + +namespace DownKyi.CustomControl +{ + /// + /// 绑定命令的工具类 + /// + public class MyDelegateCommand : ICommand + { + + /// + /// 检查命令是否可以执行的事件,在UI事件发生导致控件状态或数据发生变化时触发 + /// + public event EventHandler CanExecuteChanged + { + add + { + if (_canExecute != null) + { + CommandManager.RequerySuggested += value; + } + } + remove + { + if (_canExecute != null) + { + CommandManager.RequerySuggested -= value; + } + } + } + + /// + /// 判断命令是否可以执行的方法 + /// + private Func _canExecute; + + /// + /// 命令需要执行的方法 + /// + private Action _execute; + + /// + /// 创建一个命令 + /// + /// 命令要执行的方法 + public MyDelegateCommand(Action execute) : this(execute, null) + { + } + + /// + /// 创建一个命令 + /// + /// 命令要执行的方法 + /// 判断命令是否能够执行的方法 + public MyDelegateCommand(Action execute, Func canExecute) + { + _execute = execute; + _canExecute = canExecute; + } + + /// + /// 判断命令是否可以执行 + /// + /// 命令传入的参数 + /// 是否可以执行 + public bool CanExecute(object parameter) + { + if (_canExecute == null) return true; + return _canExecute(parameter); + } + + /// + /// 执行命令 + /// + /// + public void Execute(object parameter) + { + if (_execute != null && CanExecute(parameter)) + { + _execute(parameter); + } + } + } +} diff --git a/src/DownKyi/DownKyi.csproj b/src/DownKyi/DownKyi.csproj index 1727b3b..de0a921 100644 --- a/src/DownKyi/DownKyi.csproj +++ b/src/DownKyi/DownKyi.csproj @@ -80,6 +80,11 @@ Designer + + CustomPager.xaml + + + @@ -97,6 +102,7 @@ + @@ -145,6 +151,7 @@ + @@ -208,6 +215,9 @@ ViewMySpace.xaml + + ViewPublication.xaml + ViewPublicFavorites.xaml @@ -223,6 +233,10 @@ ViewVideoDetail.xaml + + Designer + MSBuild:Compile + MSBuild:Compile Designer @@ -379,6 +393,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -497,6 +515,8 @@ + + PreserveNewest diff --git a/src/DownKyi/Languages/Default.xaml b/src/DownKyi/Languages/Default.xaml index 60c0bdb..ddbc76c 100644 --- a/src/DownKyi/Languages/Default.xaml +++ b/src/DownKyi/Languages/Default.xaml @@ -63,6 +63,16 @@ 全部 投稿视频 频道 + 请稍等,马上就好~ + + + 收藏夹 + 个内容 + + + 下载选中项 + 下载全部 + 请稍等,马上就好~ 复制封面图片 @@ -252,10 +262,6 @@ 提取音频 提取视频 - - 收藏夹 - 个内容 - 取消 请选择文件夹 diff --git a/src/DownKyi/Resources/play.png b/src/DownKyi/Resources/play.png new file mode 100644 index 0000000..6377dca Binary files /dev/null and b/src/DownKyi/Resources/play.png differ diff --git a/src/DownKyi/Resources/time.png b/src/DownKyi/Resources/time.png new file mode 100644 index 0000000..25c18ed Binary files /dev/null and b/src/DownKyi/Resources/time.png differ diff --git a/src/DownKyi/Themes/Styles/StyleListBox.xaml b/src/DownKyi/Themes/Styles/StyleListBox.xaml index 5edeebd..9db2e98 100644 --- a/src/DownKyi/Themes/Styles/StyleListBox.xaml +++ b/src/DownKyi/Themes/Styles/StyleListBox.xaml @@ -6,7 +6,13 @@ + + + + + + + Foreground="{DynamicResource BrushTextDark}" + Text="{Binding Title}" + TextTrimming="CharacterEllipsis" /> + + diff --git a/src/DownKyi/ViewModels/PageViewModels/PublicationMedia.cs b/src/DownKyi/ViewModels/PageViewModels/PublicationMedia.cs new file mode 100644 index 0000000..f7c2636 --- /dev/null +++ b/src/DownKyi/ViewModels/PageViewModels/PublicationMedia.cs @@ -0,0 +1,71 @@ +using Prism.Commands; +using Prism.Mvvm; +using System.Windows.Media.Imaging; + +namespace DownKyi.ViewModels.PageViewModels +{ + public class PublicationMedia : BindableBase + { + public long Avid { get; set; } + public string Bvid { get; set; } + + private bool isSelected; + public bool IsSelected + { + get => isSelected; + set => SetProperty(ref isSelected, value); + } + + private BitmapImage cover; + public BitmapImage Cover + { + get => cover; + set => SetProperty(ref cover, value); + } + + private string title; + public string Title + { + get => title; + set => SetProperty(ref title, value); + } + + private string duration; + public string Duration + { + get => duration; + set => SetProperty(ref duration, value); + } + + private string playNumber; + public string PlayNumber + { + get => playNumber; + set => SetProperty(ref playNumber, value); + } + + private string createTime; + public string CreateTime + { + get => createTime; + set => SetProperty(ref createTime, value); + } + + // 视频标题点击事件 + private DelegateCommand titleCommand; + public DelegateCommand TitleCommand => titleCommand ?? (titleCommand = new DelegateCommand(ExecuteTitleCommand)); + + /// + /// 视频标题点击事件 + /// + /// + private void ExecuteTitleCommand(object parameter) + { + if (!(parameter is string tag)) { return; } + + string url = "https://www.bilibili.com/video/" + tag; + System.Diagnostics.Process.Start(url); + } + + } +} diff --git a/src/DownKyi/ViewModels/UserSpace/ViewArchiveViewModel.cs b/src/DownKyi/ViewModels/UserSpace/ViewArchiveViewModel.cs index 8f2cea5..407000d 100644 --- a/src/DownKyi/ViewModels/UserSpace/ViewArchiveViewModel.cs +++ b/src/DownKyi/ViewModels/UserSpace/ViewArchiveViewModel.cs @@ -1,10 +1,13 @@ using DownKyi.Core.BiliApi.Users.Models; using DownKyi.Core.BiliApi.Zone; +using DownKyi.Events; using DownKyi.Utils; +using Prism.Commands; using Prism.Events; using Prism.Regions; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Windows; using System.Windows.Media; @@ -12,7 +15,9 @@ namespace DownKyi.ViewModels.UserSpace { public class ViewArchiveViewModel : BaseViewModel { - public const string Tag = "ArchiveView"; + public const string Tag = "PageUserSpaceArchiveView"; + + private long mid = -1; #region 页面属性申明 @@ -23,6 +28,13 @@ namespace DownKyi.ViewModels.UserSpace set => SetProperty(ref publicationZones, value); } + private int selectedItem; + public int SelectedItem + { + get => selectedItem; + set => SetProperty(ref selectedItem, value); + } + #endregion public ViewArchiveViewModel(IEventAggregator eventAggregator) : base(eventAggregator) @@ -35,6 +47,38 @@ namespace DownKyi.ViewModels.UserSpace } #region 命令申明 + + // 视频选择事件 + private DelegateCommand publicationZonesCommand; + public DelegateCommand PublicationZonesCommand => publicationZonesCommand ?? (publicationZonesCommand = new DelegateCommand(ExecutePublicationZonesCommand)); + + /// + /// 视频选择事件 + /// + /// + private void ExecutePublicationZonesCommand(object parameter) + { + if (!(parameter is PublicationZone zone)) { return; } + + Dictionary data = new Dictionary + { + { "mid", mid }, + { "tid", zone.Tid }, + { "list", PublicationZones.ToList() } + }; + + // 进入视频页面 + NavigationParam param = new NavigationParam + { + ViewName = ViewPublicationViewModel.Tag, + ParentViewName = ViewUserSpaceViewModel.Tag, + Parameter = data + }; + eventAggregator.GetEvent().Publish(param); + + SelectedItem = -1; + } + #endregion public override void OnNavigatedFrom(NavigationContext navigationContext) @@ -42,6 +86,7 @@ namespace DownKyi.ViewModels.UserSpace base.OnNavigatedFrom(navigationContext); PublicationZones.Clear(); + SelectedItem = -1; } /// @@ -53,6 +98,7 @@ namespace DownKyi.ViewModels.UserSpace base.OnNavigatedTo(navigationContext); PublicationZones.Clear(); + SelectedItem = -1; // 根据传入参数不同执行不同任务 var parameter = navigationContext.Parameters.GetValue>("object"); @@ -61,6 +107,9 @@ namespace DownKyi.ViewModels.UserSpace return; } + // 传入mid + mid = navigationContext.Parameters.GetValue("mid"); + int VideoCount = 0; foreach (var zone in parameter) { diff --git a/src/DownKyi/ViewModels/UserSpace/ViewChannelViewModel.cs b/src/DownKyi/ViewModels/UserSpace/ViewChannelViewModel.cs index 88f2da9..f6f38c2 100644 --- a/src/DownKyi/ViewModels/UserSpace/ViewChannelViewModel.cs +++ b/src/DownKyi/ViewModels/UserSpace/ViewChannelViewModel.cs @@ -12,7 +12,7 @@ namespace DownKyi.ViewModels.UserSpace { public class ViewChannelViewModel : BaseViewModel { - public const string Tag = "Channel"; + public const string Tag = "PageUserSpaceChannel"; #region 页面属性申明 diff --git a/src/DownKyi/ViewModels/ViewDownloadManagerViewModel.cs b/src/DownKyi/ViewModels/ViewDownloadManagerViewModel.cs index 74236d9..7e17995 100644 --- a/src/DownKyi/ViewModels/ViewDownloadManagerViewModel.cs +++ b/src/DownKyi/ViewModels/ViewDownloadManagerViewModel.cs @@ -119,6 +119,8 @@ namespace DownKyi.ViewModels //// 进入设置页面时显示的设置项 SelectTabId = 0; regionManager.RequestNavigate("DownloadManagerContentRegion", ViewDownloadingViewModel.Tag, new NavigationParameters()); + + ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); } } diff --git a/src/DownKyi/ViewModels/ViewLoginViewModel.cs b/src/DownKyi/ViewModels/ViewLoginViewModel.cs index b0edff4..6767e83 100644 --- a/src/DownKyi/ViewModels/ViewLoginViewModel.cs +++ b/src/DownKyi/ViewModels/ViewLoginViewModel.cs @@ -63,7 +63,6 @@ namespace DownKyi.ViewModels #endregion } - #region 命令申明 // 返回 @@ -92,7 +91,6 @@ namespace DownKyi.ViewModels #endregion - #region 业务逻辑 /// @@ -224,6 +222,8 @@ namespace DownKyi.ViewModels /// private void InitStatus() { + ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); + LoginQRCode = null; LoginQRCodeOpacity = 1; LoginQRCodeStatus = Visibility.Hidden; diff --git a/src/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs b/src/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs index 40d5013..20fac0f 100644 --- a/src/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs +++ b/src/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs @@ -212,6 +212,11 @@ namespace DownKyi.ViewModels } }); + if (directory == null) + { + return; + } + // 通知用户添加到下载列表的结果 if (i == 0) { @@ -230,6 +235,8 @@ namespace DownKyi.ViewModels { LogManager.Debug(Tag, "初始化页面元素"); + ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); + ContentVisibility = Visibility.Collapsed; NoDataVisibility = Visibility.Collapsed; diff --git a/src/DownKyi/ViewModels/ViewPublicationViewModel.cs b/src/DownKyi/ViewModels/ViewPublicationViewModel.cs new file mode 100644 index 0000000..6ad5896 --- /dev/null +++ b/src/DownKyi/ViewModels/ViewPublicationViewModel.cs @@ -0,0 +1,478 @@ +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 DownKyi.ViewModels.UserSpace; +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 ViewPublicationViewModel : BaseViewModel + { + public const string Tag = "PagePublication"; + + private readonly IDialogService dialogService; + + private CancellationTokenSource tokenSource; + + private long mid = -1; + + // 每页视频数量,暂时在此写死,以后在设置中增加选项 + private readonly int VideoNumberInPage = 30; + + #region 页面属性申明 + + 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 ObservableCollection tabHeaders; + public ObservableCollection TabHeaders + { + get => tabHeaders; + set => SetProperty(ref tabHeaders, value); + } + + private int selectTabId; + public int SelectTabId + { + get => selectTabId; + set => SetProperty(ref selectTabId, 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 ViewPublicationViewModel(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"); + + TabHeaders = new ObservableCollection(); + 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); + } + + // 左侧tab点击事件 + private DelegateCommand leftTabHeadersCommand; + public DelegateCommand LeftTabHeadersCommand => leftTabHeadersCommand ?? (leftTabHeadersCommand = new DelegateCommand(ExecuteLeftTabHeadersCommand, CanExecuteLeftTabHeadersCommand)); + + /// + /// 左侧tab点击事件 + /// + /// + private void ExecuteLeftTabHeadersCommand(object parameter) + { + if (!(parameter is TabHeader tabHeader)) { return; } + + // 页面选择 + Pager = new CustomPagerViewModel(1, (int)Math.Ceiling(double.Parse(tabHeader.SubTitle) / VideoNumberInPage)); + Pager.CurrentChanged += OnCurrentChanged_Pager; + Pager.CountChanged += OnCountChanged_Pager; + Pager.Current = 1; + } + + /// + /// 左侧tab点击事件是否允许执行 + /// + /// + /// + private bool CanExecuteLeftTabHeadersCommand(object parameter) + { + return IsEnabled; + } + + // 全选按钮点击事件 + 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(() => + { + // 添加到下载 + foreach (var media in Medias) + { + // 只下载选中项,跳过未选中项 + 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(); + LoadingVisibility = Visibility.Visible; + NoDataVisibility = Visibility.Collapsed; + + UpdatePublication(current); + + return true; + } + + private async void UpdatePublication(int current) + { + // 是否正在获取数据 + // 在所有的退出分支中都需要设为true + IsEnabled = false; + + var tab = TabHeaders[SelectTabId]; + + await Task.Run(() => + { + CancellationToken cancellationToken = tokenSource.Token; + + var publications = Core.BiliApi.Users.UserSpace.GetPublication(mid, current, VideoNumberInPage, tab.Id); + if (publications == null) + { + // 没有数据,UI提示 + LoadingVisibility = Visibility.Collapsed; + NoDataVisibility = Visibility.Visible; + return; + } + + var videos = publications.Vlist; + if (videos == null) + { + // 没有数据,UI提示 + LoadingVisibility = Visibility.Collapsed; + NoDataVisibility = Visibility.Visible; + return; + } + + foreach (var video in videos) + { + // 查询、保存封面 + string coverUrl = video.Pic; + BitmapImage cover; + if (coverUrl == null || coverUrl == "") + { + cover = 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.Play > 0) + { + play = Format.FormatNumber(video.Play); + } + else + { + play = "--"; + } + + DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区 + DateTime dateCTime = startTime.AddSeconds(video.Created); + string ctime = dateCTime.ToString("yyyy-MM-dd"); + + App.PropertyChangeAsync(new Action(() => + { + PublicationMedia media = new PublicationMedia + { + Avid = video.Aid, + Bvid = video.Bvid, + Cover = cover, + Duration = video.Length, + 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 void InitView() + { + ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); + + TabHeaders.Clear(); + SelectTabId = -1; + } + + /// + /// 导航到VideoDetail页面时执行 + /// + /// + public override void OnNavigatedTo(NavigationContext navigationContext) + { + base.OnNavigatedTo(navigationContext); + + InitView(); + + // 根据传入参数不同执行不同任务 + var parameter = navigationContext.Parameters.GetValue>("Parameter"); + if (parameter == null) + { + return; + } + + mid = (long)parameter["mid"]; + int tid = (int)parameter["tid"]; + List zones = (List)parameter["list"]; + + foreach (var item in zones) + { + TabHeaders.Add(new TabHeader + { + Id = item.Tid, + Title = item.Name, + SubTitle = item.Count.ToString() + }); + } + + // 初始选中项 + var selectTab = TabHeaders.FirstOrDefault(item => item.Id == tid); + SelectTabId = TabHeaders.IndexOf(selectTab); + + // 页面选择 + Pager = new CustomPagerViewModel(1, (int)Math.Ceiling(double.Parse(selectTab.SubTitle) / VideoNumberInPage)); + Pager.CurrentChanged += OnCurrentChanged_Pager; + Pager.CountChanged += OnCountChanged_Pager; + Pager.Current = 1; + } + + } +} diff --git a/src/DownKyi/ViewModels/ViewSettingsViewModel.cs b/src/DownKyi/ViewModels/ViewSettingsViewModel.cs index c197f03..0d30ee8 100644 --- a/src/DownKyi/ViewModels/ViewSettingsViewModel.cs +++ b/src/DownKyi/ViewModels/ViewSettingsViewModel.cs @@ -131,6 +131,8 @@ namespace DownKyi.ViewModels // 进入设置页面时显示的设置项 SelectTabId = 0; regionManager.RequestNavigate("SettingsContentRegion", ViewBasicViewModel.Tag, new NavigationParameters()); + + ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); } } diff --git a/src/DownKyi/ViewModels/ViewToolboxViewModel.cs b/src/DownKyi/ViewModels/ViewToolboxViewModel.cs index a161d2d..e55da00 100644 --- a/src/DownKyi/ViewModels/ViewToolboxViewModel.cs +++ b/src/DownKyi/ViewModels/ViewToolboxViewModel.cs @@ -122,6 +122,8 @@ namespace DownKyi.ViewModels // 进入设置页面时显示的设置项 SelectTabId = 0; regionManager.RequestNavigate("ToolboxContentRegion", ViewBiliHelperViewModel.Tag, new NavigationParameters()); + + ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); } } diff --git a/src/DownKyi/ViewModels/ViewUserSpaceViewModel.cs b/src/DownKyi/ViewModels/ViewUserSpaceViewModel.cs index ba5b274..ad225bb 100644 --- a/src/DownKyi/ViewModels/ViewUserSpaceViewModel.cs +++ b/src/DownKyi/ViewModels/ViewUserSpaceViewModel.cs @@ -216,6 +216,7 @@ namespace DownKyi.ViewModels NavigationParameters param = new NavigationParameters() { { "object", banner.Object }, + { "mid", mid }, }; switch (banner.Id) diff --git a/src/DownKyi/ViewModels/ViewVideoDetailViewModel.cs b/src/DownKyi/ViewModels/ViewVideoDetailViewModel.cs index f6f5db7..15bf298 100644 --- a/src/DownKyi/ViewModels/ViewVideoDetailViewModel.cs +++ b/src/DownKyi/ViewModels/ViewVideoDetailViewModel.cs @@ -665,6 +665,8 @@ namespace DownKyi.ViewModels { base.OnNavigatedTo(navigationContext); + ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); + DownloadManage = ButtonIcon.Instance().DownloadManage; DownloadManage.Height = 24; DownloadManage.Width = 24; diff --git a/src/DownKyi/Views/SplashWindow.xaml b/src/DownKyi/Views/SplashWindow.xaml index 8608fce..3dfa02e 100644 --- a/src/DownKyi/Views/SplashWindow.xaml +++ b/src/DownKyi/Views/SplashWindow.xaml @@ -27,5 +27,15 @@ FontSize="30" Foreground="White" Text="Welcome to DownKyi!" /> + + + diff --git a/src/DownKyi/Views/SplashWindow.xaml.cs b/src/DownKyi/Views/SplashWindow.xaml.cs index fac9b76..aae628b 100644 --- a/src/DownKyi/Views/SplashWindow.xaml.cs +++ b/src/DownKyi/Views/SplashWindow.xaml.cs @@ -1,16 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using DownKyi.Models; 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.Shapes; namespace DownKyi.Views { @@ -22,6 +11,8 @@ namespace DownKyi.Views public SplashWindow() { InitializeComponent(); + + nameVersion.Text = new AppInfo().VersionName; } } } diff --git a/src/DownKyi/Views/UserSpace/ViewArchive.xaml b/src/DownKyi/Views/UserSpace/ViewArchive.xaml index 9faa88b..7854d6c 100644 --- a/src/DownKyi/Views/UserSpace/ViewArchive.xaml +++ b/src/DownKyi/Views/UserSpace/ViewArchive.xaml @@ -2,6 +2,7 @@ x:Class="DownKyi.Views.UserSpace.ViewArchive" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True"> @@ -9,7 +10,17 @@ - + + + + + + @@ -42,7 +53,7 @@ diff --git a/src/DownKyi/Views/UserSpace/ViewChannel.xaml b/src/DownKyi/Views/UserSpace/ViewChannel.xaml index 71fac21..e8362e8 100644 --- a/src/DownKyi/Views/UserSpace/ViewChannel.xaml +++ b/src/DownKyi/Views/UserSpace/ViewChannel.xaml @@ -9,7 +9,7 @@ - + @@ -42,7 +42,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +