From 740abfa602554c466f07608d49202c08a53a0922 Mon Sep 17 00:00:00 2001 From: flyself <1432593898@qq.com> Date: Thu, 6 Jan 2022 00:12:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E5=88=97=E8=A1=A8=E7=9A=84?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E8=AE=BE=E8=AE=A1=EF=BC=9B=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=A4=84=E7=90=86=EF=BC=9B=E6=95=B4=E7=90=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Aria2cNet/Server/AriaServer.cs | 8 +- .../BiliApi/VideoStream/PlayStreamType.cs | 9 + src/DownKyi.Core/DownKyi.Core.csproj | 5 + src/DownKyi.Core/Settings/SettingsManager.cs | 2 +- src/DownKyi.Core/Storage/Constant.cs | 4 + src/DownKyi.Core/Storage/Database/CoverDb.cs | 26 +- src/DownKyi.Core/Storage/Database/DbHelper.cs | 4 +- .../Database/Download/DownloadBaseDb.cs | 11 + .../Storage/Database/Download/DownloadDb.cs | 113 +++++++ .../Storage/Database/Download/DownloadedDb.cs | 11 + .../Database/Download/DownloadingDb.cs | 11 + src/DownKyi.Core/Storage/Database/HeaderDb.cs | 22 +- src/DownKyi.Core/Storage/StorageManager.cs | 20 ++ src/DownKyi/App.xaml.cs | 38 ++- src/DownKyi/Converter/CountConverter.cs | 21 ++ src/DownKyi/DownKyi.csproj | 28 +- src/DownKyi/Images/VectorImage.cs | 16 +- src/DownKyi/Languages/Default.xaml | 6 + src/DownKyi/Models/DownloadBase.cs | 75 +++++ src/DownKyi/Models/Downloaded.cs | 30 ++ src/DownKyi/Models/Downloading.cs | 47 +++ src/DownKyi/Resources/nodata02.png | Bin 0 -> 11421 bytes src/DownKyi/Services/BangumiInfoService.cs | 24 +- src/DownKyi/Services/CheeseInfoService.cs | 7 +- .../Services/Download/AriaDownloadService.cs | 116 ++++--- .../Services/Download/DownloadService.cs | 2 +- .../Services/Download/IDownloadService.cs | 2 +- src/DownKyi/Services/FavoritesService.cs | 2 +- src/DownKyi/Services/IFavoritesService.cs | 2 +- src/DownKyi/Services/IInfoService.cs | 2 +- src/DownKyi/Services/Utils.cs | 2 +- src/DownKyi/Services/VideoInfoService.cs | 14 +- src/DownKyi/Utils/DictionaryResource.cs | 6 +- src/DownKyi/ViewModels/BaseViewModel.cs | 2 + .../DownloadManager/DownloadBaseItem.cs | 122 ++++++++ .../DownloadManager/DownloadedItem.cs | 122 ++++++++ .../DownloadManager/DownloadingItem.cs | 165 ++++++++++ .../ViewDownloadFinishedViewModel.cs | 50 ++- .../ViewDownloadingViewModel.cs | 14 +- .../ViewModels/PageViewModels/Favorites.cs | 88 ++++++ .../PageViewModels/FavoritesMedia.cs | 125 ++++++++ .../ViewModels/PageViewModels/TabHeader.cs | 37 +++ .../PageViewModels/VideoInfoView.cs | 111 +++++++ .../ViewModels/PageViewModels/VideoPage.cs | 75 +++++ .../ViewModels/PageViewModels/VideoQuality.cs | 36 +++ .../ViewModels/PageViewModels/VideoSection.cs | 31 ++ .../Settings/DisplayFileNamePart.cs | 17 + .../ViewModels/Settings/ViewVideoViewModel.cs | 1 - .../ViewDownloadManagerViewModel.cs | 14 +- .../ViewPublicFavoritesViewModel.cs | 42 +-- .../ViewModels/ViewSettingsViewModel.cs | 14 +- .../ViewModels/ViewToolboxViewModel.cs | 14 +- .../ViewModels/ViewVideoDetailViewModel.cs | 41 ++- .../DownloadManager/ViewDownloadFinished.xaml | 296 +++++++++++++++++- .../DownloadManager/ViewDownloading.xaml | 59 +++- 55 files changed, 1936 insertions(+), 226 deletions(-) create mode 100644 src/DownKyi.Core/BiliApi/VideoStream/PlayStreamType.cs create mode 100644 src/DownKyi.Core/Storage/Database/Download/DownloadBaseDb.cs create mode 100644 src/DownKyi.Core/Storage/Database/Download/DownloadDb.cs create mode 100644 src/DownKyi.Core/Storage/Database/Download/DownloadedDb.cs create mode 100644 src/DownKyi.Core/Storage/Database/Download/DownloadingDb.cs create mode 100644 src/DownKyi/Converter/CountConverter.cs create mode 100644 src/DownKyi/Models/DownloadBase.cs create mode 100644 src/DownKyi/Models/Downloaded.cs create mode 100644 src/DownKyi/Models/Downloading.cs create mode 100644 src/DownKyi/Resources/nodata02.png create mode 100644 src/DownKyi/ViewModels/DownloadManager/DownloadBaseItem.cs create mode 100644 src/DownKyi/ViewModels/DownloadManager/DownloadedItem.cs create mode 100644 src/DownKyi/ViewModels/DownloadManager/DownloadingItem.cs create mode 100644 src/DownKyi/ViewModels/PageViewModels/Favorites.cs create mode 100644 src/DownKyi/ViewModels/PageViewModels/FavoritesMedia.cs create mode 100644 src/DownKyi/ViewModels/PageViewModels/TabHeader.cs create mode 100644 src/DownKyi/ViewModels/PageViewModels/VideoInfoView.cs create mode 100644 src/DownKyi/ViewModels/PageViewModels/VideoPage.cs create mode 100644 src/DownKyi/ViewModels/PageViewModels/VideoQuality.cs create mode 100644 src/DownKyi/ViewModels/PageViewModels/VideoSection.cs create mode 100644 src/DownKyi/ViewModels/Settings/DisplayFileNamePart.cs diff --git a/src/DownKyi.Core/Aria2cNet/Server/AriaServer.cs b/src/DownKyi.Core/Aria2cNet/Server/AriaServer.cs index 6089865..c78853d 100644 --- a/src/DownKyi.Core/Aria2cNet/Server/AriaServer.cs +++ b/src/DownKyi.Core/Aria2cNet/Server/AriaServer.cs @@ -28,14 +28,16 @@ namespace DownKyi.Core.Aria2cNet.Server ListenPort = config.ListenPort; // aria目录 string ariaDir = Environment.CurrentDirectory + "\\aria\\"; + //string ariaDir = StorageManager.GetAriaDir(); // 会话文件 #if DEBUG - string sessionFile = ariaDir + "aira.session"; + string sessionFile = Path.Combine(ariaDir, "aira.session"); + #else - string sessionFile = ariaDir + "aira.session.gz"; + string sessionFile =Path.Combine(ariaDir, "aira.session.gz"); #endif // 日志文件 - string logFile = ariaDir + "aira.log"; + string logFile = Path.Combine(ariaDir, "aira.log"); // 自动保存会话文件的时间间隔 int saveSessionInterval = 30; diff --git a/src/DownKyi.Core/BiliApi/VideoStream/PlayStreamType.cs b/src/DownKyi.Core/BiliApi/VideoStream/PlayStreamType.cs new file mode 100644 index 0000000..e54edbb --- /dev/null +++ b/src/DownKyi.Core/BiliApi/VideoStream/PlayStreamType.cs @@ -0,0 +1,9 @@ +namespace DownKyi.Core.BiliApi.VideoStream +{ + public enum PlayStreamType + { + VIDEO = 1, // 普通视频 + BANGUMI, // 番剧、电影、电视剧等 + CHEESE, // 课程 + } +} diff --git a/src/DownKyi.Core/DownKyi.Core.csproj b/src/DownKyi.Core/DownKyi.Core.csproj index 7e57e38..52019d0 100644 --- a/src/DownKyi.Core/DownKyi.Core.csproj +++ b/src/DownKyi.Core/DownKyi.Core.csproj @@ -174,6 +174,7 @@ + @@ -239,6 +240,10 @@ + + + + diff --git a/src/DownKyi.Core/Settings/SettingsManager.cs b/src/DownKyi.Core/Settings/SettingsManager.cs index b511e84..4530a94 100644 --- a/src/DownKyi.Core/Settings/SettingsManager.cs +++ b/src/DownKyi.Core/Settings/SettingsManager.cs @@ -63,7 +63,7 @@ namespace DownKyi.Core.Settings /// private bool SetSettings() { - string json = JsonConvert.SerializeObject(appSettings, Formatting.Indented); + string json = JsonConvert.SerializeObject(appSettings); try { diff --git a/src/DownKyi.Core/Storage/Constant.cs b/src/DownKyi.Core/Storage/Constant.cs index 2fe9aa4..633ece9 100644 --- a/src/DownKyi.Core/Storage/Constant.cs +++ b/src/DownKyi.Core/Storage/Constant.cs @@ -10,6 +10,9 @@ namespace DownKyi.Core.Storage // 根目录 private static string Root { get; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/Downkyi"; + // Aria + public static string Aria { get; } = $"{Root}/Aria"; + // 日志 public static string Logs { get; } = $"{Root}/Logs"; @@ -17,6 +20,7 @@ namespace DownKyi.Core.Storage public static string Database { get; } = $"{Root}/Storage"; // 历史(搜索、下载) (加密) + public static string Download { get; } = $"{Database}/Download.db"; public static string History { get; } = $"{Database}/History.db"; // 配置 diff --git a/src/DownKyi.Core/Storage/Database/CoverDb.cs b/src/DownKyi.Core/Storage/Database/CoverDb.cs index 15ba8ea..fa53abb 100644 --- a/src/DownKyi.Core/Storage/Database/CoverDb.cs +++ b/src/DownKyi.Core/Storage/Database/CoverDb.cs @@ -8,6 +8,7 @@ namespace DownKyi.Core.Storage.Database { private const string key = "b5018ecc-09d1-4da2-aa49-4625e41e623e"; private readonly DbHelper dbHelper = new DbHelper(StorageManager.GetCoverIndex(), key); + private readonly string tableName = "cover"; public CoverDb() { @@ -30,7 +31,7 @@ namespace DownKyi.Core.Storage.Database { try { - string sql = $"insert into cover values ({cover.Avid}, '{cover.Bvid}', {cover.Cid}, '{cover.Url}', '{cover.Md5}')"; + string sql = $"insert into {tableName} values ({cover.Avid}, '{cover.Bvid}', {cover.Cid}, '{cover.Url}', '{cover.Md5}')"; dbHelper.ExecuteNonQuery(sql); } catch (Exception e) @@ -48,7 +49,7 @@ namespace DownKyi.Core.Storage.Database { try { - string sql = $"update cover set avid={cover.Avid}, bvid='{cover.Bvid}', cid={cover.Cid}, md5='{cover.Md5}' where url glob '{cover.Url}'"; + string sql = $"update {tableName} set avid={cover.Avid}, bvid='{cover.Bvid}', cid={cover.Cid}, md5='{cover.Md5}' where url glob '{cover.Url}'"; dbHelper.ExecuteNonQuery(sql); } catch (Exception e) @@ -56,7 +57,7 @@ namespace DownKyi.Core.Storage.Database Utils.Debugging.Console.PrintLine("Update()发生异常: {0}", e); LogManager.Error("CoverDb", e); } - + } /// @@ -65,7 +66,7 @@ namespace DownKyi.Core.Storage.Database /// public List QueryAll() { - string sql = $"select * from cover"; + string sql = $"select * from {tableName}"; return Query(sql); } @@ -76,17 +77,10 @@ namespace DownKyi.Core.Storage.Database /// public Cover QueryByUrl(string url) { - string sql = $"select * from cover where url glob '{url}'"; - var query = Query(sql); + string sql = $"select * from {tableName} where url glob '{url}'"; + List query = Query(sql); - if (query.Count > 0) - { - return query[0]; - } - else - { - return null; - } + return query.Count > 0 ? query[0] : null; } /// @@ -96,7 +90,7 @@ namespace DownKyi.Core.Storage.Database /// public Cover QueryByMd5(string md5) { - string sql = $"select * from cover where md5 glob '{md5}'"; + string sql = $"select * from {tableName} where md5 glob '{md5}'"; var query = Query(sql); if (query.Count > 0) @@ -141,7 +135,7 @@ namespace DownKyi.Core.Storage.Database /// private void CreateTable() { - string sql = "create table if not exists cover (avid unsigned big int, bvid varchar(20), cid unsigned big int, url varchar(255) unique, md5 varchar(32) unique)"; + string sql = $"create table if not exists {tableName} (avid unsigned big int, bvid varchar(20), cid unsigned big int, url varchar(255) unique, md5 varchar(32) unique)"; dbHelper.ExecuteNonQuery(sql); } diff --git a/src/DownKyi.Core/Storage/Database/DbHelper.cs b/src/DownKyi.Core/Storage/Database/DbHelper.cs index d2c67af..8b6db35 100644 --- a/src/DownKyi.Core/Storage/Database/DbHelper.cs +++ b/src/DownKyi.Core/Storage/Database/DbHelper.cs @@ -64,7 +64,7 @@ namespace DownKyi.Core.Storage.Database /// 执行一条SQL语句 /// /// - public void ExecuteNonQuery(string sql) + public void ExecuteNonQuery(string sql, Action action = null) { lock (conn) { @@ -74,6 +74,8 @@ namespace DownKyi.Core.Storage.Database using (var command = conn.CreateCommand()) { command.CommandText = sql; + // 添加参数 + action?.Invoke(command.Parameters); command.ExecuteNonQuery(); } tr.Commit(); diff --git a/src/DownKyi.Core/Storage/Database/Download/DownloadBaseDb.cs b/src/DownKyi.Core/Storage/Database/Download/DownloadBaseDb.cs new file mode 100644 index 0000000..2d56986 --- /dev/null +++ b/src/DownKyi.Core/Storage/Database/Download/DownloadBaseDb.cs @@ -0,0 +1,11 @@ +namespace DownKyi.Core.Storage.Database.Download +{ + public class DownloadBaseDb : DownloadDb + { + public DownloadBaseDb() + { + tableName = "download_base"; + CreateTable(); + } + } +} diff --git a/src/DownKyi.Core/Storage/Database/Download/DownloadDb.cs b/src/DownKyi.Core/Storage/Database/Download/DownloadDb.cs new file mode 100644 index 0000000..eff2c98 --- /dev/null +++ b/src/DownKyi.Core/Storage/Database/Download/DownloadDb.cs @@ -0,0 +1,113 @@ +using DownKyi.Core.Logging; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SQLite; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; + +namespace DownKyi.Core.Storage.Database.Download +{ + public class DownloadDb + { + private const string key = "bdb8eb69-3698-4af9-b722-9312d0fba623"; + private readonly DbHelper dbHelper = new DbHelper(StorageManager.GetDownload(), key); + protected string tableName = "download"; + + /// + /// 关闭数据库连接 + /// + public void Close() + { + dbHelper.Close(); + } + + /// + /// 插入新的数据 + /// + /// + public void Insert(string uuid, object obj) + { + // 定义一个流 + Stream stream = new MemoryStream(); + // 定义一个格式化器 + BinaryFormatter formatter = new BinaryFormatter(); + // 序列化 + formatter.Serialize(stream, obj); + + byte[] array = null; + array = new byte[stream.Length]; + + //将二进制流写入数组 + stream.Position = 0; + stream.Read(array, 0, (int)stream.Length); + + //关闭流 + stream.Close(); + + try + { + string sql = $"insert into {tableName}(id, data) values (@id, @data)"; + dbHelper.ExecuteNonQuery(sql, new Action((para) => + { + para.Add("@id", DbType.String).Value = uuid; + para.Add("@data", DbType.Binary).Value = array; + })); + } + catch (Exception e) + { + Utils.Debugging.Console.PrintLine("Insert()发生异常: {0}", e); + LogManager.Error("DownloadingDb", e); + } + } + + /// + /// 查询所有数据 + /// + /// + /// + public Dictionary QueryAll() + { + string sql = $"select * from {tableName}"; + return Query(sql); + } + + /// + /// 查询数据 + /// + /// + /// + private Dictionary Query(string sql) + { + Dictionary objects = new Dictionary(); + + dbHelper.ExecuteQuery(sql, reader => + { + while (reader.Read()) + { + // 读取字节数组 + byte[] array = (byte[])reader["data"]; + // 定义一个流 + MemoryStream stream = new MemoryStream(null); + //定义一个格式化器 + BinaryFormatter formatter = new BinaryFormatter(); + // 反序列化 + object obj = formatter.Deserialize(stream); + + objects.Add((string)reader["id"], obj); + } + }); + return objects; + } + + + /// + /// 如果表不存在则创建表 + /// + protected void CreateTable() + { + string sql = $"create table if not exists {tableName} (id varchar(255) unique, data blob)"; + dbHelper.ExecuteNonQuery(sql); + } + } +} diff --git a/src/DownKyi.Core/Storage/Database/Download/DownloadedDb.cs b/src/DownKyi.Core/Storage/Database/Download/DownloadedDb.cs new file mode 100644 index 0000000..7f69652 --- /dev/null +++ b/src/DownKyi.Core/Storage/Database/Download/DownloadedDb.cs @@ -0,0 +1,11 @@ +namespace DownKyi.Core.Storage.Database.Download +{ + public class DownloadedDb : DownloadDb + { + public DownloadedDb() + { + tableName = "downloaded"; + CreateTable(); + } + } +} diff --git a/src/DownKyi.Core/Storage/Database/Download/DownloadingDb.cs b/src/DownKyi.Core/Storage/Database/Download/DownloadingDb.cs new file mode 100644 index 0000000..8569318 --- /dev/null +++ b/src/DownKyi.Core/Storage/Database/Download/DownloadingDb.cs @@ -0,0 +1,11 @@ +namespace DownKyi.Core.Storage.Database.Download +{ + public class DownloadingDb : DownloadDb + { + public DownloadingDb() + { + tableName = "downloading"; + CreateTable(); + } + } +} diff --git a/src/DownKyi.Core/Storage/Database/HeaderDb.cs b/src/DownKyi.Core/Storage/Database/HeaderDb.cs index 67d3d06..6fe2645 100644 --- a/src/DownKyi.Core/Storage/Database/HeaderDb.cs +++ b/src/DownKyi.Core/Storage/Database/HeaderDb.cs @@ -8,6 +8,7 @@ namespace DownKyi.Core.Storage.Database { private const string key = "7c1f1f40-7cdf-4d11-ad28-f0137a3c5308"; private readonly DbHelper dbHelper = new DbHelper(StorageManager.GetHeaderIndex(), key); + private readonly string tableName = "header"; public HeaderDb() { @@ -30,7 +31,7 @@ namespace DownKyi.Core.Storage.Database { try { - string sql = $"insert into header values ({header.Mid}, '{header.Name}', '{header.Url}', '{header.Md5}')"; + string sql = $"insert into {tableName} values ({header.Mid}, '{header.Name}', '{header.Url}', '{header.Md5}')"; dbHelper.ExecuteNonQuery(sql); } catch (Exception e) @@ -48,7 +49,7 @@ namespace DownKyi.Core.Storage.Database { try { - string sql = $"update header set name='{header.Name}', url='{header.Url}', md5='{header.Md5}' where mid={header.Mid}"; + string sql = $"update {tableName} set name='{header.Name}', url='{header.Url}', md5='{header.Md5}' where mid={header.Mid}"; dbHelper.ExecuteNonQuery(sql); } catch (Exception e) @@ -64,7 +65,7 @@ namespace DownKyi.Core.Storage.Database /// public List
QueryAll() { - string sql = $"select * from header"; + string sql = $"select * from {tableName}"; return Query(sql); } @@ -75,17 +76,10 @@ namespace DownKyi.Core.Storage.Database /// public Header QueryByMid(long mid) { - string sql = $"select * from header where mid={mid}"; - var query = Query(sql); + string sql = $"select * from {tableName} where mid={mid}"; + List
query = Query(sql); - if (query.Count > 0) - { - return query[0]; - } - else - { - return null; - } + return query.Count > 0 ? query[0] : null; } @@ -120,7 +114,7 @@ namespace DownKyi.Core.Storage.Database /// private void CreateTable() { - string sql = "create table if not exists header (mid unsigned big int unique, name varchar(255), url varchar(255), md5 varchar(32))"; + string sql = $"create table if not exists {tableName} (mid unsigned big int unique, name varchar(255), url varchar(255), md5 varchar(32))"; dbHelper.ExecuteNonQuery(sql); } diff --git a/src/DownKyi.Core/Storage/StorageManager.cs b/src/DownKyi.Core/Storage/StorageManager.cs index 7531ef3..d8671ab 100644 --- a/src/DownKyi.Core/Storage/StorageManager.cs +++ b/src/DownKyi.Core/Storage/StorageManager.cs @@ -4,6 +4,26 @@ namespace DownKyi.Core.Storage { public static class StorageManager { + /// + /// 获取历史记录的文件路径 + /// + /// + public static string GetAriaDir() + { + CreateDirectory(Constant.Aria); + return Constant.Aria; + } + + /// + /// 获取历史记录的文件路径 + /// + /// + public static string GetDownload() + { + CreateDirectory(Constant.Database); + return Constant.Download; + } + /// /// 获取历史记录的文件路径 /// diff --git a/src/DownKyi/App.xaml.cs b/src/DownKyi/App.xaml.cs index d9b8f33..ed5b1d0 100644 --- a/src/DownKyi/App.xaml.cs +++ b/src/DownKyi/App.xaml.cs @@ -1,4 +1,4 @@ -using DownKyi.Models; +using DownKyi.Core.Settings; using DownKyi.Services.Download; using DownKyi.Utils; using DownKyi.ViewModels; @@ -13,7 +13,9 @@ using DownKyi.Views.Settings; using DownKyi.Views.Toolbox; using Prism.Ioc; using System; +using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Windows; namespace DownKyi @@ -104,5 +106,39 @@ namespace DownKyi Current.Dispatcher.Invoke(callback); } + /// + /// 下载完成列表排序 + /// + /// + public static void SortDownloadedList(DownloadFinishedSort finishedSort) + { + List list = DownloadedList.ToList(); + switch (finishedSort) + { + case DownloadFinishedSort.DOWNLOAD: + // 按下载先后排序 + list.Sort((x, y) => { return x.Downloaded.FinishedTimestamp.CompareTo(y.Downloaded.FinishedTimestamp); }); + break; + case DownloadFinishedSort.NUMBER: + // 按序号排序 + list.Sort((x, y) => + { + int compare = x.MainTitle.CompareTo(y.MainTitle); + return compare == 0 ? x.Order.CompareTo(y.Order) : compare; + }); + break; + default: + break; + } + + // 更新下载完成列表 + // 如果有更好的方法再重写 + DownloadedList.Clear(); + foreach (DownloadedItem item in list) + { + DownloadedList.Add(item); + } + } + } } diff --git a/src/DownKyi/Converter/CountConverter.cs b/src/DownKyi/Converter/CountConverter.cs new file mode 100644 index 0000000..d38fe78 --- /dev/null +++ b/src/DownKyi/Converter/CountConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace DownKyi.Converter +{ + public class CountConverter : IValueConverter + { + public int Count { get; set; } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return ((int)value) > Count; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/DownKyi/DownKyi.csproj b/src/DownKyi/DownKyi.csproj index f309c28..4458ad1 100644 --- a/src/DownKyi/DownKyi.csproj +++ b/src/DownKyi/DownKyi.csproj @@ -79,6 +79,7 @@ MSBuild:Compile Designer + @@ -87,20 +88,19 @@ - - - + + + - - - + + + - - - - - - + + + + + @@ -118,6 +118,9 @@ + + + @@ -447,6 +450,7 @@ PreserveNewest + PreserveNewest diff --git a/src/DownKyi/Images/VectorImage.cs b/src/DownKyi/Images/VectorImage.cs index 921d09a..8e8fb9d 100644 --- a/src/DownKyi/Images/VectorImage.cs +++ b/src/DownKyi/Images/VectorImage.cs @@ -7,29 +7,29 @@ namespace DownKyi.Images private double width; public double Width { - get { return width; } - set { SetProperty(ref width, value); } + get => width; + set => SetProperty(ref width, value); } private double height; public double Height { - get { return height; } - set { SetProperty(ref height, value); } + get => height; + set => SetProperty(ref height, value); } private string data; public string Data { - get { return data; } - set { SetProperty(ref data, value); } + get => data; + set => SetProperty(ref data, value); } private string fill; public string Fill { - get { return fill; } - set { SetProperty(ref fill, value); } + get => fill; + set => SetProperty(ref fill, value); } } diff --git a/src/DownKyi/Languages/Default.xaml b/src/DownKyi/Languages/Default.xaml index 71c49b6..565c157 100644 --- a/src/DownKyi/Languages/Default.xaml +++ b/src/DownKyi/Languages/Default.xaml @@ -91,6 +91,12 @@ 全部开始 全部删除 + 已下载 + 个视频! + 按下载先后排序 + 按序号排序 + 清空所有记录 + 按回车键应用设置 diff --git a/src/DownKyi/Models/DownloadBase.cs b/src/DownKyi/Models/DownloadBase.cs new file mode 100644 index 0000000..53b3514 --- /dev/null +++ b/src/DownKyi/Models/DownloadBase.cs @@ -0,0 +1,75 @@ +using DownKyi.Core.BiliApi.BiliUtils; +using System; +using System.Collections.Generic; + +namespace DownKyi.Models +{ + [Serializable] + public class DownloadBase + { + public DownloadBase() + { + // 唯一id + Uuid = Guid.NewGuid().ToString("N"); + + // 初始化需要下载的内容 + NeedDownloadContent = new Dictionary + { + { "downloadAudio", true }, + { "downloadVideo", true }, + { "downloadDanmaku", true }, + { "downloadSubtitle", true }, + { "downloadCover", true } + }; + } + + // 此条下载项的id + public string Uuid { get; } + + // 需要下载的内容 + public Dictionary NeedDownloadContent { get; private set; } + + // 视频的id + public string Bvid { get; set; } + public long Avid { get; set; } + public long Cid { get; set; } + public long EpisodeId { get; set; } + + // 视频封面的url + public string CoverUrl { get; set; } + + // 视频page的封面的url + public string PageCoverUrl { get; set; } + + // 分区id + public int ZoneId { get; set; } + + // 视频序号 + public int Order { get; set; } + + // 视频主标题 + public string MainTitle { get; set; } + + // 视频标题 + public string Name { get; set; } + + // 时长 + public string Duration { get; set; } + + // 视频编码名称,AVC、HEVC + public string VideoCodecName { get; set; } + + // 视频画质 + public Quality Resolution { get; set; } + + // 音频编码 + public Quality AudioCodec { get; set; } + + // 文件路径,不包含扩展名,所有内容均以此路径下载 + public string FilePath { get; set; } + + // 文件大小 + public string FileSize { get; set; } + + } +} diff --git a/src/DownKyi/Models/Downloaded.cs b/src/DownKyi/Models/Downloaded.cs new file mode 100644 index 0000000..4c31142 --- /dev/null +++ b/src/DownKyi/Models/Downloaded.cs @@ -0,0 +1,30 @@ +using System; + +namespace DownKyi.Models +{ + [Serializable] + public class Downloaded// : DownloadBase + { + public Downloaded() : base() + { + } + + // 下载速度 + public string MaxSpeedDisplay { get; set; } + + // 完成时间戳 + public long FinishedTimestamp { get; set; } + public void SetFinishedTimestamp(long finishedTimestamp) + { + FinishedTimestamp = finishedTimestamp; + + DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区 + DateTime dateTime = startTime.AddSeconds(finishedTimestamp); + FinishedTime = dateTime.ToString("yyyy-MM-dd HH:mm:ss"); + } + + // 完成时间 + public string FinishedTime { get; set; } + + } +} diff --git a/src/DownKyi/Models/Downloading.cs b/src/DownKyi/Models/Downloading.cs new file mode 100644 index 0000000..7147489 --- /dev/null +++ b/src/DownKyi/Models/Downloading.cs @@ -0,0 +1,47 @@ +using DownKyi.Core.BiliApi.VideoStream; +using System; +using System.Collections.Generic; + +namespace DownKyi.Models +{ + [Serializable] + public class Downloading// : DownloadBase + { + public Downloading() : base() + { + // 初始化下载的文件列表 + DownloadFiles = new List(); + } + + // Aria相关 + public string Gid { get; set; } + + // 下载的文件 + public List DownloadFiles { get; private set; } + + // 视频类别 + public PlayStreamType PlayStreamType { get; set; } + + // 下载状态 + public DownloadStatus DownloadStatus { get; set; } + + // 正在下载内容(音频、视频、弹幕、字幕、封面) + public string DownloadContent { get; set; } + + // 下载状态显示 + public string DownloadStatusTitle { get; set; } + + // 下载进度 + public float Progress { get; set; } + + // 已下载大小/文件大小 + public string DownloadingFileSize { get; set; } + + // 下载的最高速度 + public long MaxSpeed { get; set; } + + // 下载速度 + public string SpeedDisplay { get; set; } + + } +} diff --git a/src/DownKyi/Resources/nodata02.png b/src/DownKyi/Resources/nodata02.png new file mode 100644 index 0000000000000000000000000000000000000000..301f3dfb03e696ff8b77e76aa755d81aea411040 GIT binary patch literal 11421 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 s7~!KLkqtRb6arPH2K%4##Q)d8L?dL!) pages = new List(); int order = 0; - foreach (var episode in section.Episodes) + foreach (BangumiEpisode episode in section.Episodes) { order++; // 标题 - string name; - if (episode.LongTitle != null && episode.LongTitle != "") - { - name = $"{episode.Title} {episode.LongTitle}"; - } - else - { - name = episode.Title; - } - + string name = episode.LongTitle != null && episode.LongTitle != "" ? $"{episode.Title} {episode.LongTitle}" : episode.Title; VideoPage page = new VideoPage { Avid = episode.Aid, @@ -176,7 +168,7 @@ namespace DownKyi.Services /// public void GetVideoStream(VideoPage page) { - var playUrl = VideoStream.GetBangumiPlayUrl(page.Avid, page.Bvid, page.Cid); + PlayUrl playUrl = VideoStream.GetBangumiPlayUrl(page.Avid, page.Bvid, page.Cid); Utils.VideoPageInfo(playUrl, page); } diff --git a/src/DownKyi/Services/CheeseInfoService.cs b/src/DownKyi/Services/CheeseInfoService.cs index 81f0987..359e11a 100644 --- a/src/DownKyi/Services/CheeseInfoService.cs +++ b/src/DownKyi/Services/CheeseInfoService.cs @@ -2,10 +2,11 @@ using DownKyi.Core.BiliApi.Cheese; using DownKyi.Core.BiliApi.Cheese.Models; using DownKyi.Core.BiliApi.VideoStream; +using DownKyi.Core.BiliApi.VideoStream.Models; using DownKyi.Core.Storage; using DownKyi.Core.Utils; -using DownKyi.Models; using DownKyi.Utils; +using DownKyi.ViewModels.PageViewModels; using System; using System.Collections.Generic; using System.Windows.Media.Imaging; @@ -48,7 +49,7 @@ namespace DownKyi.Services if (cheeseView.Episodes.Count == 0) { return pages; } int order = 0; - foreach (var episode in cheeseView.Episodes) + foreach (CheeseEpisode episode in cheeseView.Episodes) { order++; string name = episode.Title; @@ -87,7 +88,7 @@ namespace DownKyi.Services /// public void GetVideoStream(VideoPage page) { - var playUrl = VideoStream.GetCheesePlayUrl(page.Avid, page.Bvid, page.Cid, page.EpisodeId); + PlayUrl playUrl = VideoStream.GetCheesePlayUrl(page.Avid, page.Bvid, page.Cid, page.EpisodeId); Utils.VideoPageInfo(playUrl, page); } diff --git a/src/DownKyi/Services/Download/AriaDownloadService.cs b/src/DownKyi/Services/Download/AriaDownloadService.cs index d972c38..8bebe9c 100644 --- a/src/DownKyi/Services/Download/AriaDownloadService.cs +++ b/src/DownKyi/Services/Download/AriaDownloadService.cs @@ -13,6 +13,7 @@ using DownKyi.Core.Storage; using DownKyi.Core.Utils; using DownKyi.Models; using DownKyi.Utils; +using DownKyi.ViewModels.DownloadManager; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -118,14 +119,14 @@ namespace DownKyi.Services.Download if (downloadVideo.BackupUrl != null) { urls.AddRange(downloadVideo.BackupUrl); } // 路径 - string[] temp = downloading.FilePath.Split('/'); - string path = downloading.FilePath.Replace(temp[temp.Length - 1], ""); + string[] temp = downloading.DownloadBase.FilePath.Split('/'); + string path = downloading.DownloadBase.FilePath.Replace(temp[temp.Length - 1], ""); // 下载文件名 string fileName = Guid.NewGuid().ToString("N"); // 记录本次下载的文件 - downloading.DownloadFiles.Add(fileName); + downloading.Downloading.DownloadFiles.Add(fileName); // 开始下载 DownloadResult downloadStatus = DownloadByAria(downloading, urls, path, fileName); @@ -160,7 +161,7 @@ namespace DownKyi.Services.Download // 查询、保存封面 StorageCover storageCover = new StorageCover(); - string cover = storageCover.GetCover(downloading.Avid, downloading.Bvid, downloading.Cid, coverUrl); + string cover = storageCover.GetCover(downloading.DownloadBase.Avid, downloading.DownloadBase.Bvid, downloading.DownloadBase.Cid, coverUrl); if (cover == null) { return null; @@ -172,7 +173,7 @@ namespace DownKyi.Services.Download File.Copy(cover, fileName, true); // 记录本次下载的文件 - downloading.DownloadFiles.Add(fileName); + downloading.Downloading.DownloadFiles.Add(fileName); return fileName; } @@ -200,10 +201,10 @@ namespace DownKyi.Services.Download downloading.SpeedDisplay = string.Empty; string title = $"{downloading.Name}"; - string assFile = $"{downloading.FilePath}.ass"; + string assFile = $"{downloading.DownloadBase.FilePath}.ass"; // 记录本次下载的文件 - downloading.DownloadFiles.Add(assFile); + downloading.Downloading.DownloadFiles.Add(assFile); int screenWidth = SettingsManager.GetInstance().GetDanmakuScreenWidth(); int screenHeight = SettingsManager.GetInstance().GetDanmakuScreenHeight(); @@ -236,7 +237,7 @@ namespace DownKyi.Services.Download .SetTopFilter(SettingsManager.GetInstance().GetDanmakuTopFilter() == AllowStatus.YES) .SetBottomFilter(SettingsManager.GetInstance().GetDanmakuBottomFilter() == AllowStatus.YES) .SetScrollFilter(SettingsManager.GetInstance().GetDanmakuScrollFilter() == AllowStatus.YES) - .Create(downloading.Avid, downloading.Cid, subtitleConfig, assFile); + .Create(downloading.DownloadBase.Avid, downloading.DownloadBase.Cid, subtitleConfig, assFile); return assFile; } @@ -257,7 +258,7 @@ namespace DownKyi.Services.Download List srtFiles = new List(); - var subRipTexts = VideoStream.GetSubtitle(downloading.Avid, downloading.Bvid, downloading.Cid); + var subRipTexts = VideoStream.GetSubtitle(downloading.DownloadBase.Avid, downloading.DownloadBase.Bvid, downloading.DownloadBase.Cid); if (subRipTexts == null) { return null; @@ -265,13 +266,13 @@ namespace DownKyi.Services.Download foreach (var subRip in subRipTexts) { - string srtFile = $"{downloading.FilePath}_{subRip.LanDoc}.srt"; + string srtFile = $"{downloading.DownloadBase.FilePath}_{subRip.LanDoc}.srt"; try { File.WriteAllText(srtFile, subRip.SrtString); // 记录本次下载的文件 - downloading.DownloadFiles.Add(srtFile); + downloading.Downloading.DownloadFiles.Add(srtFile); srtFiles.Add(srtFile); } @@ -302,10 +303,10 @@ namespace DownKyi.Services.Download // 下载速度 downloading.SpeedDisplay = string.Empty; - string finalFile = $"{downloading.FilePath}.mp4"; + string finalFile = $"{downloading.DownloadBase.FilePath}.mp4"; if (videoUid == null) { - finalFile = $"{downloading.FilePath}.aac"; + finalFile = $"{downloading.DownloadBase.FilePath}.aac"; } // 合并音视频 @@ -339,22 +340,22 @@ namespace DownKyi.Services.Download // 下载速度 downloading.SpeedDisplay = string.Empty; - if (downloading.PlayUrl != null && downloading.DownloadStatus == DownloadStatus.NOT_STARTED) + if (downloading.PlayUrl != null && downloading.Downloading.DownloadStatus == DownloadStatus.NOT_STARTED) { return; } // 解析 - switch (downloading.PlayStreamType) + switch (downloading.Downloading.PlayStreamType) { case PlayStreamType.VIDEO: - downloading.PlayUrl = VideoStream.GetVideoPlayUrl(downloading.Avid, downloading.Bvid, downloading.Cid); + downloading.PlayUrl = VideoStream.GetVideoPlayUrl(downloading.DownloadBase.Avid, downloading.DownloadBase.Bvid, downloading.DownloadBase.Cid); break; case PlayStreamType.BANGUMI: - downloading.PlayUrl = VideoStream.GetBangumiPlayUrl(downloading.Avid, downloading.Bvid, downloading.Cid); + downloading.PlayUrl = VideoStream.GetBangumiPlayUrl(downloading.DownloadBase.Avid, downloading.DownloadBase.Bvid, downloading.DownloadBase.Cid); break; case PlayStreamType.CHEESE: - downloading.PlayUrl = VideoStream.GetCheesePlayUrl(downloading.Avid, downloading.Bvid, downloading.Cid, downloading.EpisodeId); + downloading.PlayUrl = VideoStream.GetCheesePlayUrl(downloading.DownloadBase.Avid, downloading.DownloadBase.Bvid, downloading.DownloadBase.Cid, downloading.DownloadBase.EpisodeId); break; default: break; @@ -399,7 +400,7 @@ namespace DownKyi.Services.Download int downloadingCount = 0; foreach (DownloadingItem downloading in downloadingList) { - if (downloading.DownloadStatus == DownloadStatus.DOWNLOADING) + if (downloading.Downloading.DownloadStatus == DownloadStatus.DOWNLOADING) { downloadingCount++; } @@ -413,7 +414,7 @@ namespace DownKyi.Services.Download } // 开始下载 - if (downloading.DownloadStatus == DownloadStatus.NOT_STARTED || downloading.DownloadStatus == DownloadStatus.WAIT_FOR_DOWNLOAD) + if (downloading.Downloading.DownloadStatus == DownloadStatus.NOT_STARTED || downloading.Downloading.DownloadStatus == DownloadStatus.WAIT_FOR_DOWNLOAD) { SingleDownload(downloading); downloadingCount++; @@ -441,8 +442,8 @@ namespace DownKyi.Services.Download private async void SingleDownload(DownloadingItem downloading) { // 路径 - string[] temp = downloading.FilePath.Split('/'); - string path = downloading.FilePath.Replace(temp[temp.Length - 1], ""); + string[] temp = downloading.DownloadBase.FilePath.Split('/'); + string path = downloading.DownloadBase.FilePath.Replace(temp[temp.Length - 1], ""); // 路径不存在则创建 if (!Directory.Exists(path)) { @@ -451,12 +452,12 @@ namespace DownKyi.Services.Download await Task.Run(new Action(() => { - downloading.DownloadStatus = DownloadStatus.DOWNLOADING; + downloading.Downloading.DownloadStatus = DownloadStatus.DOWNLOADING; // 初始化 downloading.DownloadStatusTitle = string.Empty; downloading.DownloadContent = string.Empty; - downloading.DownloadFiles.Clear(); + downloading.Downloading.DownloadFiles.Clear(); // 解析并依次下载音频、视频、弹幕、字幕、封面等内容 Parse(downloading); @@ -466,7 +467,7 @@ namespace DownKyi.Services.Download string audioUid = null; // 如果需要下载音频 - if (downloading.NeedDownloadContent["downloadAudio"]) + if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"]) { audioUid = DownloadAudio(downloading); } @@ -476,7 +477,7 @@ namespace DownKyi.Services.Download string videoUid = null; // 如果需要下载视频 - if (downloading.NeedDownloadContent["downloadVideo"]) + if (downloading.DownloadBase.NeedDownloadContent["downloadVideo"]) { videoUid = DownloadVideo(downloading); } @@ -486,7 +487,7 @@ namespace DownKyi.Services.Download string outputDanmaku = null; // 如果需要下载弹幕 - if (downloading.NeedDownloadContent["downloadDanmaku"]) + if (downloading.DownloadBase.NeedDownloadContent["downloadDanmaku"]) { outputDanmaku = DownloadDanmaku(downloading); } @@ -496,7 +497,7 @@ namespace DownKyi.Services.Download List outputSubtitles = null; // 如果需要下载字幕 - if (downloading.NeedDownloadContent["downloadSubtitle"]) + if (downloading.DownloadBase.NeedDownloadContent["downloadSubtitle"]) { outputSubtitles = DownloadSubtitle(downloading); } @@ -506,15 +507,15 @@ namespace DownKyi.Services.Download string outputCover = null; // 如果需要下载封面 - if (downloading.NeedDownloadContent["downloadCover"]) + if (downloading.DownloadBase.NeedDownloadContent["downloadCover"]) { - string fileName = $"{downloading.FilePath}.{GetImageExtension(downloading.PageCoverUrl)}"; + string fileName = $"{downloading.DownloadBase.FilePath}.{GetImageExtension(downloading.DownloadBase.PageCoverUrl)}"; // page的封面 - outputCover = DownloadCover(downloading, downloading.PageCoverUrl, fileName); + outputCover = DownloadCover(downloading, downloading.DownloadBase.PageCoverUrl, fileName); // 封面 - DownloadCover(downloading, downloading.CoverUrl, $"{path}/Cover.{GetImageExtension(downloading.CoverUrl)}"); + DownloadCover(downloading, downloading.DownloadBase.CoverUrl, $"{path}/Cover.{GetImageExtension(downloading.DownloadBase.CoverUrl)}"); } // 暂停 @@ -522,7 +523,7 @@ namespace DownKyi.Services.Download // 混流 string outputMedia = string.Empty; - if (downloading.NeedDownloadContent["downloadAudio"] || downloading.NeedDownloadContent["downloadVideo"]) + if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"] || downloading.DownloadBase.NeedDownloadContent["downloadVideo"]) { outputMedia = MixedFlow(downloading, audioUid, videoUid); } @@ -531,7 +532,7 @@ namespace DownKyi.Services.Download Pause(downloading); // 检测音频、视频是否下载成功 - if (downloading.NeedDownloadContent["downloadAudio"] || downloading.NeedDownloadContent["downloadVideo"]) + if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"] || downloading.DownloadBase.NeedDownloadContent["downloadVideo"]) { // 只有下载音频不下载视频时才输出aac // 只要下载视频就输出mp4 @@ -542,13 +543,13 @@ namespace DownKyi.Services.Download } // 检测弹幕是否下载成功 - if (downloading.NeedDownloadContent["downloadDanmaku"] && File.Exists(outputDanmaku)) + if (downloading.DownloadBase.NeedDownloadContent["downloadDanmaku"] && File.Exists(outputDanmaku)) { // 成功 } // 检测字幕是否下载成功 - if (downloading.NeedDownloadContent["downloadSubtitle"]) + if (downloading.DownloadBase.NeedDownloadContent["downloadSubtitle"]) { if (outputSubtitles == null) { @@ -567,7 +568,7 @@ namespace DownKyi.Services.Download } // 检测封面是否下载成功 - if (downloading.NeedDownloadContent["downloadCover"] && File.Exists(outputCover)) + if (downloading.DownloadBase.NeedDownloadContent["downloadCover"] && File.Exists(outputCover)) { // 成功 } @@ -578,6 +579,29 @@ namespace DownKyi.Services.Download // 下载结果是否成功等 // 对是否成功的判断:只要outputMedia存在则成功,否则失败 + Downloaded downloaded = new Downloaded + { + MaxSpeedDisplay = Format.FormatSpeed(downloading.Downloading.MaxSpeed), + }; + // 设置完成时间 + downloaded.SetFinishedTimestamp(new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds()); + + DownloadedItem downloadedItem = new DownloadedItem + { + DownloadBase = downloading.DownloadBase, + Downloaded = downloaded + }; + + App.PropertyChangeAsync(new Action(() => + { + // 加入到下载完成list中,并从下载中list去除 + App.DownloadedList.Add(downloadedItem); + App.DownloadingList.Remove(downloading); + + // 下载完成列表排序 + DownloadFinishedSort finishedSort = SettingsManager.GetInstance().GetDownloadFinishedSort(); + App.SortDownloadedList(finishedSort); + })); })); } @@ -607,7 +631,7 @@ namespace DownKyi.Services.Download { string oldStatus = downloading.DownloadStatusTitle; downloading.DownloadStatusTitle = DictionaryResource.GetString("Pausing"); - while (downloading.DownloadStatus == DownloadStatus.PAUSE) + while (downloading.Downloading.DownloadStatus == DownloadStatus.PAUSE) { // 降低CPU占用 Thread.Sleep(100); @@ -621,7 +645,7 @@ namespace DownKyi.Services.Download downloadingCount = 0; foreach (DownloadingItem item in downloadingList) { - if (item.DownloadStatus == DownloadStatus.DOWNLOADING) + if (item.Downloading.DownloadStatus == DownloadStatus.DOWNLOADING) { downloadingCount++; } @@ -731,7 +755,7 @@ namespace DownKyi.Services.Download // 保存gid string gid = ariaAddUri.Result.Result; - downloading.Gid = gid; + downloading.Downloading.Gid = gid; // 管理下载 AriaManager ariaManager = new AriaManager(); @@ -739,15 +763,15 @@ namespace DownKyi.Services.Download ariaManager.DownloadFinish += AriaDownloadFinish; return ariaManager.GetDownloadStatus(gid, new Action(() => { - switch (downloading.DownloadStatus) + switch (downloading.Downloading.DownloadStatus) { case DownloadStatus.PAUSE: - Task ariaPause = AriaClient.PauseAsync(downloading.Gid); + Task ariaPause = AriaClient.PauseAsync(downloading.Downloading.Gid); // 通知UI,并阻塞当前线程 Pause(downloading); break; case DownloadStatus.DOWNLOADING: - Task ariaUnpause = AriaClient.UnpauseAsync(downloading.Gid); + Task ariaUnpause = AriaClient.UnpauseAsync(downloading.Downloading.Gid); break; } })); @@ -756,7 +780,7 @@ namespace DownKyi.Services.Download private void AriaTellStatus(long totalLength, long completedLength, long speed, string gid) { // 当前的下载视频 - DownloadingItem video = downloadingList.FirstOrDefault(it => it.Gid == gid); + DownloadingItem video = downloadingList.FirstOrDefault(it => it.Downloading.Gid == gid); if (video == null) { return; } float percent = 0; @@ -778,9 +802,9 @@ namespace DownKyi.Services.Download video.SpeedDisplay = Format.FormatSpeed(speed); // 最大下载速度 - if (video.MaxSpeed < speed) + if (video.Downloading.MaxSpeed < speed) { - video.MaxSpeed = speed; + video.Downloading.MaxSpeed = speed; } } diff --git a/src/DownKyi/Services/Download/DownloadService.cs b/src/DownKyi/Services/Download/DownloadService.cs index 07288ee..f8612a8 100644 --- a/src/DownKyi/Services/Download/DownloadService.cs +++ b/src/DownKyi/Services/Download/DownloadService.cs @@ -1,4 +1,4 @@ -using DownKyi.Models; +using DownKyi.ViewModels.DownloadManager; using System.Collections.ObjectModel; namespace DownKyi.Services.Download diff --git a/src/DownKyi/Services/Download/IDownloadService.cs b/src/DownKyi/Services/Download/IDownloadService.cs index 3621dad..fea9835 100644 --- a/src/DownKyi/Services/Download/IDownloadService.cs +++ b/src/DownKyi/Services/Download/IDownloadService.cs @@ -1,4 +1,4 @@ -using DownKyi.Models; +using DownKyi.ViewModels.DownloadManager; using System.Collections.Generic; namespace DownKyi.Services.Download diff --git a/src/DownKyi/Services/FavoritesService.cs b/src/DownKyi/Services/FavoritesService.cs index b4bfe9a..2363556 100644 --- a/src/DownKyi/Services/FavoritesService.cs +++ b/src/DownKyi/Services/FavoritesService.cs @@ -1,7 +1,7 @@ using DownKyi.Core.BiliApi.Favorites; using DownKyi.Core.Storage; using DownKyi.Core.Utils; -using DownKyi.Models; +using DownKyi.ViewModels.PageViewModels; using Prism.Events; using System; using System.Collections.ObjectModel; diff --git a/src/DownKyi/Services/IFavoritesService.cs b/src/DownKyi/Services/IFavoritesService.cs index 0fb7d82..f83e761 100644 --- a/src/DownKyi/Services/IFavoritesService.cs +++ b/src/DownKyi/Services/IFavoritesService.cs @@ -1,4 +1,4 @@ -using DownKyi.Models; +using DownKyi.ViewModels.PageViewModels; using Prism.Events; using System.Collections.ObjectModel; diff --git a/src/DownKyi/Services/IInfoService.cs b/src/DownKyi/Services/IInfoService.cs index 4aacf84..a882569 100644 --- a/src/DownKyi/Services/IInfoService.cs +++ b/src/DownKyi/Services/IInfoService.cs @@ -1,4 +1,4 @@ -using DownKyi.Models; +using DownKyi.ViewModels.PageViewModels; using System.Collections.Generic; namespace DownKyi.Services diff --git a/src/DownKyi/Services/Utils.cs b/src/DownKyi/Services/Utils.cs index ed54eb9..b0f55b3 100644 --- a/src/DownKyi/Services/Utils.cs +++ b/src/DownKyi/Services/Utils.cs @@ -3,7 +3,7 @@ using DownKyi.Core.BiliApi.VideoStream.Models; using DownKyi.Core.Settings; using DownKyi.Core.Settings.Models; using DownKyi.Core.Utils; -using DownKyi.Models; +using DownKyi.ViewModels.PageViewModels; using System.Collections.Generic; using System.Linq; diff --git a/src/DownKyi/Services/VideoInfoService.cs b/src/DownKyi/Services/VideoInfoService.cs index a807aaa..5659cca 100644 --- a/src/DownKyi/Services/VideoInfoService.cs +++ b/src/DownKyi/Services/VideoInfoService.cs @@ -4,7 +4,7 @@ using DownKyi.Core.BiliApi.Video.Models; using DownKyi.Core.BiliApi.VideoStream; using DownKyi.Core.Storage; using DownKyi.Core.Utils; -using DownKyi.Models; +using DownKyi.ViewModels.PageViewModels; using System; using System.Collections.Generic; using System.Windows.Media.Imaging; @@ -39,13 +39,13 @@ namespace DownKyi.Services /// 获取视频剧集 /// /// - public List GetVideoPages() + public List GetVideoPages() { if (videoView == null) { return null; } if (videoView.Pages == null) { return null; } if (videoView.Pages.Count == 0) { return null; } - List videoPages = new List(); + List videoPages = new List(); int order = 0; foreach (var page in videoView.Pages) @@ -72,7 +72,7 @@ namespace DownKyi.Services } } - Models.VideoPage videoPage = new Models.VideoPage + ViewModels.PageViewModels.VideoPage videoPage = new ViewModels.PageViewModels.VideoPage { Avid = videoView.Aid, Bvid = videoView.Bvid, @@ -104,12 +104,12 @@ namespace DownKyi.Services foreach (var section in videoView.UgcSeason.Sections) { - List pages = new List(); + List pages = new List(); int order = 0; foreach (var episode in section.Episodes) { order++; - Models.VideoPage page = new Models.VideoPage + ViewModels.PageViewModels.VideoPage page = new ViewModels.PageViewModels.VideoPage { Avid = episode.Aid, Bvid = episode.Bvid, @@ -141,7 +141,7 @@ namespace DownKyi.Services /// 获取视频流的信息,从VideoPage返回 /// /// - public void GetVideoStream(Models.VideoPage page) + public void GetVideoStream(ViewModels.PageViewModels.VideoPage page) { var playUrl = VideoStream.GetVideoPlayUrl(page.Avid, page.Bvid, page.Cid); Utils.VideoPageInfo(playUrl, page); diff --git a/src/DownKyi/Utils/DictionaryResource.cs b/src/DownKyi/Utils/DictionaryResource.cs index 71147da..a6fa53c 100644 --- a/src/DownKyi/Utils/DictionaryResource.cs +++ b/src/DownKyi/Utils/DictionaryResource.cs @@ -15,8 +15,10 @@ namespace DownKyi.Utils /// public static string GetColor(string resourceKey) { - Color color = (Color)Application.Current.Resources[resourceKey]; - return color.ToString(); + //Color color = (Color)Application.Current.Resources[resourceKey]; + //return color.ToString(); + + return Application.Current == null ? "#00000000" : ((Color)Application.Current.Resources[resourceKey]).ToString(); } /// diff --git a/src/DownKyi/ViewModels/BaseViewModel.cs b/src/DownKyi/ViewModels/BaseViewModel.cs index 9710162..54d623f 100644 --- a/src/DownKyi/ViewModels/BaseViewModel.cs +++ b/src/DownKyi/ViewModels/BaseViewModel.cs @@ -41,6 +41,8 @@ namespace DownKyi.ViewModels /// protected void PropertyChangeAsync(Action callback) { + if (Application.Current == null) { return; } + Application.Current.Dispatcher.Invoke(callback); } diff --git a/src/DownKyi/ViewModels/DownloadManager/DownloadBaseItem.cs b/src/DownKyi/ViewModels/DownloadManager/DownloadBaseItem.cs new file mode 100644 index 0000000..454f94b --- /dev/null +++ b/src/DownKyi/ViewModels/DownloadManager/DownloadBaseItem.cs @@ -0,0 +1,122 @@ +using DownKyi.Core.BiliApi.BiliUtils; +using DownKyi.Core.BiliApi.Zone; +using DownKyi.Models; +using Prism.Mvvm; +using System.Windows; +using System.Windows.Media; + +namespace DownKyi.ViewModels.DownloadManager +{ + public class DownloadBaseItem : BindableBase + { + // model数据 + private DownloadBase downloadBase; + public DownloadBase DownloadBase + { + get => downloadBase; + set + { + downloadBase = value; + + ZoneImage = (DrawingImage)Application.Current.Resources[VideoZoneIcon.Instance().GetZoneImageKey(DownloadBase.ZoneId)]; + } + } + + // 视频分区image + private DrawingImage zoneImage; + public DrawingImage ZoneImage + { + get => zoneImage; + set => SetProperty(ref zoneImage, value); + } + + // 视频序号 + public int Order + { + get => DownloadBase.Order; + set + { + DownloadBase.Order = value; + RaisePropertyChanged("Order"); + } + } + + // 视频主标题 + public string MainTitle + { + get => DownloadBase.MainTitle; + set + { + DownloadBase.MainTitle = value; + RaisePropertyChanged("MainTitle"); + } + } + + // 视频标题 + public string Name + { + get => DownloadBase.Name; + set + { + DownloadBase.Name = value; + RaisePropertyChanged("Name"); + } + } + + // 时长 + public string Duration + { + get => DownloadBase.Duration; + set + { + DownloadBase.Duration = value; + RaisePropertyChanged("Duration"); + } + } + + // 视频编码名称,AVC、HEVC + public string VideoCodecName + { + get => DownloadBase.VideoCodecName; + set + { + DownloadBase.VideoCodecName = value; + RaisePropertyChanged("VideoCodecName"); + } + } + + // 视频画质 + public Quality Resolution + { + get => DownloadBase.Resolution; + set + { + DownloadBase.Resolution = value; + RaisePropertyChanged("Resolution"); + } + } + + // 音频编码 + public Quality AudioCodec + { + get => DownloadBase.AudioCodec; + set + { + DownloadBase.AudioCodec = value; + RaisePropertyChanged("AudioCodec"); + } + } + + // 文件大小 + public string FileSize + { + get => DownloadBase.FileSize; + set + { + DownloadBase.FileSize = value; + RaisePropertyChanged("FileSize"); + } + } + + } +} diff --git a/src/DownKyi/ViewModels/DownloadManager/DownloadedItem.cs b/src/DownKyi/ViewModels/DownloadManager/DownloadedItem.cs new file mode 100644 index 0000000..5149d28 --- /dev/null +++ b/src/DownKyi/ViewModels/DownloadManager/DownloadedItem.cs @@ -0,0 +1,122 @@ +using DownKyi.Images; +using DownKyi.Models; +using Prism.Commands; +using System.IO; + +namespace DownKyi.ViewModels.DownloadManager +{ + public class DownloadedItem : DownloadBaseItem + { + public DownloadedItem() : base() + { + } + + // model数据 + public Downloaded Downloaded { get; set; } + + // 下载速度 + public string MaxSpeedDisplay + { + get => Downloaded.MaxSpeedDisplay; + set + { + Downloaded.MaxSpeedDisplay = value; + RaisePropertyChanged("MaxSpeedDisplay"); + } + } + + // 完成时间 + public string FinishedTime + { + get => Downloaded.FinishedTime; + set + { + Downloaded.FinishedTime = value; + RaisePropertyChanged("FinishedTime"); + } + } + + #region 控制按钮 + + private VectorImage openFolder; + public VectorImage OpenFolder + { + get => openFolder; + set => SetProperty(ref openFolder, value); + } + + private VectorImage openVideo; + public VectorImage OpenVideo + { + get => openVideo; + set => SetProperty(ref openVideo, value); + } + + private VectorImage removeVideo; + public VectorImage RemoveVideo + { + get => removeVideo; + set => SetProperty(ref removeVideo, value); + } + + #endregion + + #region 命令申明 + + // 打开文件夹事件 + private DelegateCommand openFolderCommand; + public DelegateCommand OpenFolderCommand => openFolderCommand ?? (openFolderCommand = new DelegateCommand(ExecuteOpenFolderCommand)); + + /// + /// 打开文件夹事件 + /// + private void ExecuteOpenFolderCommand() + { + string videoPath = $"{DownloadBase.FilePath}.mp4"; + if (File.Exists(videoPath)) + { + System.Diagnostics.Process.Start("Explorer", "/select," + videoPath); + } + else + { + //eventAggregator.GetEvent().Publish("没有找到视频文件,可能被删除或移动!"); + } + } + + // 打开视频事件 + private DelegateCommand openVideoCommand; + public DelegateCommand OpenVideoCommand => openVideoCommand ?? (openVideoCommand = new DelegateCommand(ExecuteOpenVideoCommand)); + + /// + /// 打开视频事件 + /// + private void ExecuteOpenVideoCommand() + { + string videoPath = $"{DownloadBase.FilePath}.mp4"; + if (File.Exists(videoPath)) + { + System.Diagnostics.Process.Start(videoPath); + } + else + { + //eventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipAddDownloadingZero")); + //eventAggregator.GetEvent().Publish("没有找到视频文件,可能被删除或移动!"); + } + } + + // 删除事件 + private DelegateCommand removeVideoCommand; + public DelegateCommand RemoveVideoCommand => removeVideoCommand ?? (removeVideoCommand = new DelegateCommand(ExecuteRemoveVideoCommand)); + + /// + /// 删除事件 + /// + private void ExecuteRemoveVideoCommand() + { + App.DownloadedList.Remove(this); + } + + #endregion + + } +} diff --git a/src/DownKyi/ViewModels/DownloadManager/DownloadingItem.cs b/src/DownKyi/ViewModels/DownloadManager/DownloadingItem.cs new file mode 100644 index 0000000..e727366 --- /dev/null +++ b/src/DownKyi/ViewModels/DownloadManager/DownloadingItem.cs @@ -0,0 +1,165 @@ +using DownKyi.Core.BiliApi.VideoStream.Models; +using DownKyi.Images; +using DownKyi.Models; +using DownKyi.Utils; +using Prism.Commands; + +namespace DownKyi.ViewModels.DownloadManager +{ + public class DownloadingItem : DownloadBaseItem + { + public DownloadingItem() : base() + { + // 暂停继续按钮 + StartOrPause = ButtonIcon.Instance().Pause; + StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); + + // 删除按钮 + Delete = ButtonIcon.Instance().Delete; + Delete.Fill = DictionaryResource.GetColor("ColorPrimary"); + } + + // model数据 + public Downloading Downloading { get; set; } + + // 视频流链接 + public PlayUrl PlayUrl { get; set; } + + // 正在下载内容(音频、视频、弹幕、字幕、封面) + public string DownloadContent + { + get => Downloading.DownloadContent; + set + { + Downloading.DownloadContent = value; + RaisePropertyChanged("DownloadContent"); + } + } + + // 下载状态显示 + public string DownloadStatusTitle + { + get => Downloading.DownloadStatusTitle; + set + { + Downloading.DownloadStatusTitle = value; + RaisePropertyChanged("DownloadStatusTitle"); + } + } + + // 下载进度 + public float Progress + { + get => Downloading.Progress; + set + { + Downloading.Progress = value; + RaisePropertyChanged("Progress"); + } + } + + // 已下载大小/文件大小 + public string DownloadingFileSize + { + get => Downloading.DownloadingFileSize; + set + { + Downloading.DownloadingFileSize = value; + RaisePropertyChanged("DownloadingFileSize"); + } + } + + // 下载速度 + public string SpeedDisplay + { + get => Downloading.SpeedDisplay; + set + { + Downloading.SpeedDisplay = value; + RaisePropertyChanged("SpeedDisplay"); + } + } + + + #region 控制按钮 + + private VectorImage startOrPause; + public VectorImage StartOrPause + { + get => startOrPause; + set => SetProperty(ref startOrPause, value); + } + + private VectorImage delete; + public VectorImage Delete + { + get => delete; + set => SetProperty(ref delete, value); + } + + #endregion + + #region 命令申明 + + // 下载列表暂停继续事件 + private DelegateCommand startOrPauseCommand; + public DelegateCommand StartOrPauseCommand => startOrPauseCommand ?? (startOrPauseCommand = new DelegateCommand(ExecuteStartOrPauseCommand)); + + /// + /// 下载列表暂停继续事件 + /// + private void ExecuteStartOrPauseCommand() + { + switch (Downloading.DownloadStatus) + { + case DownloadStatus.NOT_STARTED: + case DownloadStatus.WAIT_FOR_DOWNLOAD: + Downloading.DownloadStatus = DownloadStatus.PAUSE_STARTED; + StartOrPause = ButtonIcon.Instance().Start; + StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); + break; + case DownloadStatus.PAUSE_STARTED: + Downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD; + StartOrPause = ButtonIcon.Instance().Pause; + StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); + break; + case DownloadStatus.PAUSE: + Downloading.DownloadStatus = DownloadStatus.DOWNLOADING; + StartOrPause = ButtonIcon.Instance().Pause; + StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); + break; + case DownloadStatus.DOWNLOADING: + Downloading.DownloadStatus = DownloadStatus.PAUSE; + StartOrPause = ButtonIcon.Instance().Start; + StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); + break; + case DownloadStatus.DOWNLOAD_SUCCEED: + // 下载成功后会从下载列表中删除 + // 不会出现此分支 + break; + case DownloadStatus.DOWNLOAD_FAILED: + Downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD; + StartOrPause = ButtonIcon.Instance().Pause; + StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); + break; + default: + break; + } + } + + // 下载列表删除事件 + private DelegateCommand deleteCommand; + public DelegateCommand DeleteCommand => deleteCommand ?? (deleteCommand = new DelegateCommand(ExecuteDeleteCommand)); + + /// + /// 下载列表删除事件 + /// + private void ExecuteDeleteCommand() + { + App.DownloadingList.Remove(this); + } + + #endregion + + } +} diff --git a/src/DownKyi/ViewModels/DownloadManager/ViewDownloadFinishedViewModel.cs b/src/DownKyi/ViewModels/DownloadManager/ViewDownloadFinishedViewModel.cs index a305a98..492cf1d 100644 --- a/src/DownKyi/ViewModels/DownloadManager/ViewDownloadFinishedViewModel.cs +++ b/src/DownKyi/ViewModels/DownloadManager/ViewDownloadFinishedViewModel.cs @@ -1,11 +1,7 @@ -using DownKyi.Models; +using DownKyi.Core.Settings; using Prism.Commands; using Prism.Events; -using Prism.Mvvm; -using System; -using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; namespace DownKyi.ViewModels.DownloadManager { @@ -18,15 +14,55 @@ namespace DownKyi.ViewModels.DownloadManager private ObservableCollection downloadedList; public ObservableCollection DownloadedList { - get { return downloadedList; } - set { SetProperty(ref downloadedList, value); } + get => downloadedList; + set => SetProperty(ref downloadedList, value); } #endregion public ViewDownloadFinishedViewModel(IEventAggregator eventAggregator) : base(eventAggregator) { + // 初始化DownloadedList DownloadedList = App.DownloadedList; } + + #region 命令申明 + + // 下载完成列表排序事件 + private DelegateCommand finishedSortCommand; + public DelegateCommand FinishedSortCommand => finishedSortCommand ?? (finishedSortCommand = new DelegateCommand(ExecuteFinishedSortCommand)); + + /// + /// 下载完成列表排序事件 + /// + /// + private void ExecuteFinishedSortCommand(object parameter) + { + if (!(parameter is int index)) { return; } + + switch (index) + { + case 1: + App.SortDownloadedList(DownloadFinishedSort.DOWNLOAD); + break; + case 2: + App.SortDownloadedList(DownloadFinishedSort.NUMBER); + break; + } + } + + // 清空下载完成列表事件 + private DelegateCommand clearAllDownloadedCommand; + public DelegateCommand ClearAllDownloadedCommand => clearAllDownloadedCommand ?? (clearAllDownloadedCommand = new DelegateCommand(ExecuteClearAllDownloadedCommand)); + + /// + /// 清空下载完成列表事件 + /// + private void ExecuteClearAllDownloadedCommand() + { + } + + #endregion + } } diff --git a/src/DownKyi/ViewModels/DownloadManager/ViewDownloadingViewModel.cs b/src/DownKyi/ViewModels/DownloadManager/ViewDownloadingViewModel.cs index 547438a..d4bc070 100644 --- a/src/DownKyi/ViewModels/DownloadManager/ViewDownloadingViewModel.cs +++ b/src/DownKyi/ViewModels/DownloadManager/ViewDownloadingViewModel.cs @@ -41,18 +41,18 @@ namespace DownKyi.ViewModels.DownloadManager { foreach (DownloadingItem downloading in downloadingList) { - switch (downloading.DownloadStatus) + switch (downloading.Downloading.DownloadStatus) { case DownloadStatus.NOT_STARTED: case DownloadStatus.WAIT_FOR_DOWNLOAD: - downloading.DownloadStatus = DownloadStatus.PAUSE_STARTED; + downloading.Downloading.DownloadStatus = DownloadStatus.PAUSE_STARTED; break; case DownloadStatus.PAUSE_STARTED: break; case DownloadStatus.PAUSE: break; case DownloadStatus.DOWNLOADING: - downloading.DownloadStatus = DownloadStatus.PAUSE; + downloading.Downloading.DownloadStatus = DownloadStatus.PAUSE; break; case DownloadStatus.DOWNLOAD_SUCCEED: // 下载成功后会从下载列表中删除 @@ -80,16 +80,16 @@ namespace DownKyi.ViewModels.DownloadManager { foreach (DownloadingItem downloading in downloadingList) { - switch (downloading.DownloadStatus) + switch (downloading.Downloading.DownloadStatus) { case DownloadStatus.NOT_STARTED: case DownloadStatus.WAIT_FOR_DOWNLOAD: break; case DownloadStatus.PAUSE_STARTED: - downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD; + downloading.Downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD; break; case DownloadStatus.PAUSE: - downloading.DownloadStatus = DownloadStatus.DOWNLOADING; + downloading.Downloading.DownloadStatus = DownloadStatus.DOWNLOADING; break; case DownloadStatus.DOWNLOADING: break; @@ -98,7 +98,7 @@ namespace DownKyi.ViewModels.DownloadManager // 不会出现此分支 break; case DownloadStatus.DOWNLOAD_FAILED: - downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD; + downloading.Downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD; break; default: break; diff --git a/src/DownKyi/ViewModels/PageViewModels/Favorites.cs b/src/DownKyi/ViewModels/PageViewModels/Favorites.cs new file mode 100644 index 0000000..96f1db8 --- /dev/null +++ b/src/DownKyi/ViewModels/PageViewModels/Favorites.cs @@ -0,0 +1,88 @@ +using Prism.Mvvm; +using System.Windows.Media.Imaging; + +namespace DownKyi.ViewModels.PageViewModels +{ + public class Favorites : BindableBase + { + public string CoverUrl { get; set; } + public long UpperMid { get; set; } + + 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 createTime; + public string CreateTime + { + get => createTime; + set => SetProperty(ref createTime, value); + } + + private string playNumber; + public string PlayNumber + { + get => playNumber; + set => SetProperty(ref playNumber, value); + } + + private string likeNumber; + public string LikeNumber + { + get => likeNumber; + set => SetProperty(ref likeNumber, value); + } + + private string favoriteNumber; + public string FavoriteNumber + { + get => favoriteNumber; + set => SetProperty(ref favoriteNumber, value); + } + + private string shareNumber; + public string ShareNumber + { + get => shareNumber; + set => SetProperty(ref shareNumber, value); + } + + private string description; + public string Description + { + get => description; + set => SetProperty(ref description, value); + } + + private int mediaCount; + public int MediaCount + { + get => mediaCount; + set => SetProperty(ref mediaCount, value); + } + + private string upName; + public string UpName + { + get => upName; + set => SetProperty(ref upName, value); + } + + private BitmapImage upHeader; + public BitmapImage UpHeader + { + get => upHeader; + set => SetProperty(ref upHeader, value); + } + } +} diff --git a/src/DownKyi/ViewModels/PageViewModels/FavoritesMedia.cs b/src/DownKyi/ViewModels/PageViewModels/FavoritesMedia.cs new file mode 100644 index 0000000..b9db2a5 --- /dev/null +++ b/src/DownKyi/ViewModels/PageViewModels/FavoritesMedia.cs @@ -0,0 +1,125 @@ +using DownKyi.Core.BiliApi.BiliUtils; +using DownKyi.Utils; +using Prism.Commands; +using Prism.Events; +using Prism.Mvvm; +using System.Windows.Media.Imaging; + +namespace DownKyi.ViewModels.PageViewModels +{ + public class FavoritesMedia : BindableBase + { + protected readonly IEventAggregator eventAggregator; + + public FavoritesMedia(IEventAggregator eventAggregator) + { + this.eventAggregator = eventAggregator; + } + + public long Avid { get; set; } + public string Bvid { get; set; } + public long UpperMid { get; set; } + + #region 页面属性申明 + + private bool isSelected; + public bool IsSelected + { + get => isSelected; + set => SetProperty(ref isSelected, value); + } + + private int order; + public int Order + { + get => order; + set => SetProperty(ref order, 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 playNumber; + public string PlayNumber + { + get => playNumber; + set => SetProperty(ref playNumber, value); + } + + private string danmakuNumber; + public string DanmakuNumber + { + get => danmakuNumber; + set => SetProperty(ref danmakuNumber, value); + } + + private string favoriteNumber; + public string FavoriteNumber + { + get => favoriteNumber; + set => SetProperty(ref favoriteNumber, value); + } + + private string duration; + public string Duration + { + get => duration; + set => SetProperty(ref duration, value); + } + + private string upName; + public string UpName + { + get => upName; + set => SetProperty(ref upName, value); + } + + #endregion + + #region 命令申明 + + // 视频标题点击事件 + private DelegateCommand titleCommand; + public DelegateCommand TitleCommand => titleCommand ?? (titleCommand = new DelegateCommand(ExecuteTitleCommand)); + + /// + /// 视频标题点击事件 + /// + /// + private void ExecuteTitleCommand(object parameter) + { + if (!(parameter is string tag)) { return; } + + NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, tag, $"{ParseEntrance.VideoUrl}{Bvid}"); + } + + // 视频的UP主点击事件 + private DelegateCommand videoUpperCommand; + public DelegateCommand VideoUpperCommand => videoUpperCommand ?? (videoUpperCommand = new DelegateCommand(ExecuteVideoUpperCommand)); + + /// + /// 视频的UP主点击事件 + /// + /// + private void ExecuteVideoUpperCommand(object parameter) + { + if (!(parameter is string tag)) { return; } + + NavigateToView.NavigateToViewUserSpace(eventAggregator, tag, UpperMid); + } + + #endregion + + } +} diff --git a/src/DownKyi/ViewModels/PageViewModels/TabHeader.cs b/src/DownKyi/ViewModels/PageViewModels/TabHeader.cs new file mode 100644 index 0000000..ad37256 --- /dev/null +++ b/src/DownKyi/ViewModels/PageViewModels/TabHeader.cs @@ -0,0 +1,37 @@ +using DownKyi.Images; +using Prism.Mvvm; + +namespace DownKyi.ViewModels.PageViewModels +{ + public class TabHeader : BindableBase + { + private int id; + public int Id + { + get => id; + set => SetProperty(ref id, value); + } + + private VectorImage image; + public VectorImage Image + { + get => image; + set => SetProperty(ref image, value); + } + + private string title; + public string Title + { + get => title; + set => SetProperty(ref title, value); + } + + private string subTitle; + public string SubTitle + { + get => subTitle; + set => SetProperty(ref subTitle, value); + } + + } +} diff --git a/src/DownKyi/ViewModels/PageViewModels/VideoInfoView.cs b/src/DownKyi/ViewModels/PageViewModels/VideoInfoView.cs new file mode 100644 index 0000000..c4f93a3 --- /dev/null +++ b/src/DownKyi/ViewModels/PageViewModels/VideoInfoView.cs @@ -0,0 +1,111 @@ +using Prism.Mvvm; +using System.Windows.Media.Imaging; + +namespace DownKyi.ViewModels.PageViewModels +{ + public class VideoInfoView : BindableBase + { + public string CoverUrl { get; set; } + public long UpperMid { get; set; } + public int TypeId { get; set; } + + 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 videoZone; + public string VideoZone + { + get => videoZone; + set => SetProperty(ref videoZone, value); + } + + private string createTime; + public string CreateTime + { + get => createTime; + set => SetProperty(ref createTime, value); + } + + private string playNumber; + public string PlayNumber + { + get => playNumber; + set => SetProperty(ref playNumber, value); + } + + private string danmakuNumber; + public string DanmakuNumber + { + get => danmakuNumber; + set => SetProperty(ref danmakuNumber, value); + } + + private string likeNumber; + public string LikeNumber + { + get => likeNumber; + set => SetProperty(ref likeNumber, value); + } + + private string coinNumber; + public string CoinNumber + { + get => coinNumber; + set => SetProperty(ref coinNumber, value); + } + + private string favoriteNumber; + public string FavoriteNumber + { + get => favoriteNumber; + set => SetProperty(ref favoriteNumber, value); + } + + private string shareNumber; + public string ShareNumber + { + get => shareNumber; + set => SetProperty(ref shareNumber, value); + } + + private string replyNumber; + public string ReplyNumber + { + get => replyNumber; + set => SetProperty(ref replyNumber, value); + } + + private string description; + public string Description + { + get => description; + set => SetProperty(ref description, value); + } + + private string upName; + public string UpName + { + get => upName; + set => SetProperty(ref upName, value); + } + + private BitmapImage upHeader; + public BitmapImage UpHeader + { + get => upHeader; + set => SetProperty(ref upHeader, value); + } + + } +} diff --git a/src/DownKyi/ViewModels/PageViewModels/VideoPage.cs b/src/DownKyi/ViewModels/PageViewModels/VideoPage.cs new file mode 100644 index 0000000..6d7704e --- /dev/null +++ b/src/DownKyi/ViewModels/PageViewModels/VideoPage.cs @@ -0,0 +1,75 @@ +using DownKyi.Core.BiliApi.VideoStream.Models; +using Prism.Mvvm; +using System.Collections.Generic; + +namespace DownKyi.ViewModels.PageViewModels +{ + public class VideoPage : BindableBase + { + public PlayUrl PlayUrl { get; set; } + + public long Avid { get; set; } + public string Bvid { get; set; } + public long Cid { get; set; } + public long EpisodeId { get; set; } + + public string FirstFrame { get; set; } + + private bool isSelected; + public bool IsSelected + { + get => isSelected; + set => SetProperty(ref isSelected, value); + } + + private int order; + public int Order + { + get => order; + set => SetProperty(ref order, value); + } + + private string name; + public string Name + { + get => name; + set => SetProperty(ref name, value); + } + + private string duration; + public string Duration + { + get => duration; + set => SetProperty(ref duration, value); + } + + private List audioQualityFormatList; + public List AudioQualityFormatList + { + get => audioQualityFormatList; + set => SetProperty(ref audioQualityFormatList, value); + } + + private string audioQualityFormat; + public string AudioQualityFormat + { + get => audioQualityFormat; + set => SetProperty(ref audioQualityFormat, value); + } + + private List videoQualityList; + public List VideoQualityList + { + get => videoQualityList; + set => SetProperty(ref videoQualityList, value); + } + + private VideoQuality videoQuality; + public VideoQuality VideoQuality + { + get => videoQuality; + set => SetProperty(ref videoQuality, value); + } + + } +} diff --git a/src/DownKyi/ViewModels/PageViewModels/VideoQuality.cs b/src/DownKyi/ViewModels/PageViewModels/VideoQuality.cs new file mode 100644 index 0000000..da4bfe2 --- /dev/null +++ b/src/DownKyi/ViewModels/PageViewModels/VideoQuality.cs @@ -0,0 +1,36 @@ +using Prism.Mvvm; +using System.Collections.Generic; + +namespace DownKyi.ViewModels.PageViewModels +{ + public class VideoQuality : BindableBase + { + private int quality; + public int Quality + { + get => quality; + set => SetProperty(ref quality, value); + } + + private string qualityFormat; + public string QualityFormat + { + get => qualityFormat; + set => SetProperty(ref qualityFormat, value); + } + + private List videoCodecList; + public List VideoCodecList + { + get => videoCodecList; + set => SetProperty(ref videoCodecList, value); + } + + private string selectedVideoCodec; + public string SelectedVideoCodec + { + get => selectedVideoCodec; + set => SetProperty(ref selectedVideoCodec, value); + } + } +} diff --git a/src/DownKyi/ViewModels/PageViewModels/VideoSection.cs b/src/DownKyi/ViewModels/PageViewModels/VideoSection.cs new file mode 100644 index 0000000..5fd4d09 --- /dev/null +++ b/src/DownKyi/ViewModels/PageViewModels/VideoSection.cs @@ -0,0 +1,31 @@ +using Prism.Mvvm; +using System.Collections.Generic; + +namespace DownKyi.ViewModels.PageViewModels +{ + public class VideoSection : BindableBase + { + public long Id { get; set; } + + private string title; + public string Title + { + get => title; + set => SetProperty(ref title, value); + } + + private bool isSelected; + public bool IsSelected + { + get => isSelected; + set => SetProperty(ref isSelected, value); + } + + private List videoPages; + public List VideoPages + { + get => videoPages; + set => SetProperty(ref videoPages, value); + } + } +} diff --git a/src/DownKyi/ViewModels/Settings/DisplayFileNamePart.cs b/src/DownKyi/ViewModels/Settings/DisplayFileNamePart.cs new file mode 100644 index 0000000..70dcf58 --- /dev/null +++ b/src/DownKyi/ViewModels/Settings/DisplayFileNamePart.cs @@ -0,0 +1,17 @@ +using DownKyi.Core.FileName; +using Prism.Mvvm; + +namespace DownKyi.ViewModels.Settings +{ + public class DisplayFileNamePart : BindableBase + { + public FileNamePart Id { get; set; } + + private string title; + public string Title + { + get => title; + set => SetProperty(ref title, value); + } + } +} diff --git a/src/DownKyi/ViewModels/Settings/ViewVideoViewModel.cs b/src/DownKyi/ViewModels/Settings/ViewVideoViewModel.cs index d100b8c..f2cd1f0 100644 --- a/src/DownKyi/ViewModels/Settings/ViewVideoViewModel.cs +++ b/src/DownKyi/ViewModels/Settings/ViewVideoViewModel.cs @@ -2,7 +2,6 @@ using DownKyi.Core.FileName; using DownKyi.Core.Settings; using DownKyi.Events; -using DownKyi.Models; using DownKyi.Utils; using Prism.Commands; using Prism.Events; diff --git a/src/DownKyi/ViewModels/ViewDownloadManagerViewModel.cs b/src/DownKyi/ViewModels/ViewDownloadManagerViewModel.cs index 7125753..74236d9 100644 --- a/src/DownKyi/ViewModels/ViewDownloadManagerViewModel.cs +++ b/src/DownKyi/ViewModels/ViewDownloadManagerViewModel.cs @@ -1,8 +1,8 @@ using DownKyi.Events; using DownKyi.Images; -using DownKyi.Models; using DownKyi.Utils; using DownKyi.ViewModels.DownloadManager; +using DownKyi.ViewModels.PageViewModels; using Prism.Commands; using Prism.Events; using Prism.Regions; @@ -21,22 +21,22 @@ namespace DownKyi.ViewModels private VectorImage arrowBack; public VectorImage ArrowBack { - get { return arrowBack; } - set { SetProperty(ref arrowBack, value); } + get => arrowBack; + set => SetProperty(ref arrowBack, value); } private List tabHeaders; public List TabHeaders { - get { return tabHeaders; } - set { SetProperty(ref tabHeaders, value); } + get => tabHeaders; + set => SetProperty(ref tabHeaders, value); } private int selectTabId; public int SelectTabId { - get { return selectTabId; } - set { SetProperty(ref selectTabId, value); } + get => selectTabId; + set => SetProperty(ref selectTabId, value); } #endregion diff --git a/src/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs b/src/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs index 7db9b83..87dc5ce 100644 --- a/src/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs +++ b/src/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs @@ -1,9 +1,9 @@ using DownKyi.Core.Logging; using DownKyi.Events; using DownKyi.Images; -using DownKyi.Models; using DownKyi.Services; using DownKyi.Utils; +using DownKyi.ViewModels.PageViewModels; using Prism.Commands; using Prism.Events; using Prism.Regions; @@ -23,71 +23,71 @@ namespace DownKyi.ViewModels private string pageName = Tag; public string PageName { - get { return pageName; } - set { SetProperty(ref pageName, value); } + get => pageName; + set => SetProperty(ref pageName, value); } private VectorImage arrowBack; public VectorImage ArrowBack { - get { return arrowBack; } - set { SetProperty(ref arrowBack, value); } + get => arrowBack; + set => SetProperty(ref arrowBack, value); } private VectorImage play; public VectorImage Play { - get { return play; } - set { SetProperty(ref play, value); } + get => play; + set => SetProperty(ref play, value); } private VectorImage like; public VectorImage Like { - get { return like; } - set { SetProperty(ref like, value); } + get => like; + set => SetProperty(ref like, value); } private VectorImage favorite; public VectorImage Favorite { - get { return favorite; } - set { SetProperty(ref favorite, value); } + get => favorite; + set => SetProperty(ref favorite, value); } private VectorImage share; public VectorImage Share { - get { return share; } - set { SetProperty(ref share, value); } + get => share; + set => SetProperty(ref share, value); } private Favorites favorites; public Favorites Favorites { - get { return favorites; } - set { SetProperty(ref favorites, value); } + get => favorites; + set => SetProperty(ref favorites, value); } private ObservableCollection favoritesMedias; public ObservableCollection FavoritesMedias { - get { return favoritesMedias; } - set { SetProperty(ref favoritesMedias, value); } + get => favoritesMedias; + set => SetProperty(ref favoritesMedias, value); } private Visibility contentVisibility; public Visibility ContentVisibility { - get { return contentVisibility; } - set { SetProperty(ref contentVisibility, value); } + get => contentVisibility; + set => SetProperty(ref contentVisibility, value); } private Visibility noDataVisibility; public Visibility NoDataVisibility { - get { return noDataVisibility; } - set { SetProperty(ref noDataVisibility, value); } + get => noDataVisibility; + set => SetProperty(ref noDataVisibility, value); } #endregion diff --git a/src/DownKyi/ViewModels/ViewSettingsViewModel.cs b/src/DownKyi/ViewModels/ViewSettingsViewModel.cs index 6518b94..c197f03 100644 --- a/src/DownKyi/ViewModels/ViewSettingsViewModel.cs +++ b/src/DownKyi/ViewModels/ViewSettingsViewModel.cs @@ -1,7 +1,7 @@ using DownKyi.Events; using DownKyi.Images; -using DownKyi.Models; using DownKyi.Utils; +using DownKyi.ViewModels.PageViewModels; using DownKyi.ViewModels.Settings; using Prism.Commands; using Prism.Events; @@ -21,22 +21,22 @@ namespace DownKyi.ViewModels private VectorImage arrowBack; public VectorImage ArrowBack { - get { return arrowBack; } - set { SetProperty(ref arrowBack, value); } + get => arrowBack; + set => SetProperty(ref arrowBack, value); } private List tabHeaders; public List TabHeaders { - get { return tabHeaders; } - set { SetProperty(ref tabHeaders, value); } + get => tabHeaders; + set => SetProperty(ref tabHeaders, value); } private int selectTabId; public int SelectTabId { - get { return selectTabId; } - set { SetProperty(ref selectTabId, value); } + get => selectTabId; + set => SetProperty(ref selectTabId, value); } #endregion diff --git a/src/DownKyi/ViewModels/ViewToolboxViewModel.cs b/src/DownKyi/ViewModels/ViewToolboxViewModel.cs index e476c17..a161d2d 100644 --- a/src/DownKyi/ViewModels/ViewToolboxViewModel.cs +++ b/src/DownKyi/ViewModels/ViewToolboxViewModel.cs @@ -1,7 +1,7 @@ using DownKyi.Events; using DownKyi.Images; -using DownKyi.Models; using DownKyi.Utils; +using DownKyi.ViewModels.PageViewModels; using DownKyi.ViewModels.Toolbox; using Prism.Commands; using Prism.Events; @@ -21,22 +21,22 @@ namespace DownKyi.ViewModels private VectorImage arrowBack; public VectorImage ArrowBack { - get { return arrowBack; } - set { SetProperty(ref arrowBack, value); } + get => arrowBack; + set => SetProperty(ref arrowBack, value); } private List tabHeaders; public List TabHeaders { - get { return tabHeaders; } - set { SetProperty(ref tabHeaders, value); } + get => tabHeaders; + set => SetProperty(ref tabHeaders, value); } private int selectTabId; public int SelectTabId { - get { return selectTabId; } - set { SetProperty(ref selectTabId, value); } + get => selectTabId; + set => SetProperty(ref selectTabId, value); } #endregion diff --git a/src/DownKyi/ViewModels/ViewVideoDetailViewModel.cs b/src/DownKyi/ViewModels/ViewVideoDetailViewModel.cs index b9a4b19..11486e3 100644 --- a/src/DownKyi/ViewModels/ViewVideoDetailViewModel.cs +++ b/src/DownKyi/ViewModels/ViewVideoDetailViewModel.cs @@ -1,4 +1,5 @@ using DownKyi.Core.BiliApi.BiliUtils; +using DownKyi.Core.BiliApi.VideoStream; using DownKyi.Core.BiliApi.Zone; using DownKyi.Core.FileName; using DownKyi.Core.Logging; @@ -11,6 +12,8 @@ using DownKyi.Models; using DownKyi.Services; using DownKyi.Utils; using DownKyi.ViewModels.Dialogs; +using DownKyi.ViewModels.DownloadManager; +using DownKyi.ViewModels.PageViewModels; using Prism.Commands; using Prism.Events; using Prism.Regions; @@ -22,7 +25,6 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows; -using System.Windows.Media; namespace DownKyi.ViewModels { @@ -568,7 +570,7 @@ namespace DownKyi.ViewModels // 如果存在正在下载列表,则跳过,并提示 foreach (DownloadingItem item in App.DownloadingList) { - if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec) + if (item.DownloadBase.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec) { eventAggregator.GetEvent().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloading")}"); continue; @@ -578,7 +580,7 @@ namespace DownKyi.ViewModels // 如果存在下载完成列表,弹出选择框是否再次下载 foreach (DownloadedItem item in App.DownloadedList) { - if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec) + if (item.DownloadBase.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec) { eventAggregator.GetEvent().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloaded")}"); continue; @@ -661,18 +663,16 @@ namespace DownKyi.ViewModels } // 如果不存在,直接添加到下载列表 - DownloadingItem downloading = new DownloadingItem + DownloadBase downloadBase = new DownloadBase { - PlayUrl = page.PlayUrl, - Bvid = page.Bvid, Avid = page.Avid, Cid = page.Cid, EpisodeId = page.EpisodeId, - CoverUrl = VideoInfoView.CoverUrl, PageCoverUrl = page.FirstFrame, - ZoneImage = (DrawingImage)Application.Current.Resources[VideoZoneIcon.Instance().GetZoneImageKey(zoneId)], + ZoneId = zoneId, + FilePath = filePath, Order = page.Order, MainTitle = VideoInfoView.Title, @@ -681,21 +681,30 @@ namespace DownKyi.ViewModels VideoCodecName = page.VideoQuality.SelectedVideoCodec, Resolution = new Quality { Name = page.VideoQuality.QualityFormat, Id = page.VideoQuality.Quality }, AudioCodec = Constant.GetAudioQualities().FirstOrDefault(t => { return t.Name == page.AudioQualityFormat; }), - FilePath = filePath, - + }; + Downloading downloading = new Downloading + { PlayStreamType = playStreamType, DownloadStatus = DownloadStatus.NOT_STARTED, }; // 需要下载的内容 - downloading.NeedDownloadContent["downloadAudio"] = downloadAudio; - downloading.NeedDownloadContent["downloadVideo"] = downloadVideo; - downloading.NeedDownloadContent["downloadDanmaku"] = downloadDanmaku; - downloading.NeedDownloadContent["downloadSubtitle"] = downloadSubtitle; - downloading.NeedDownloadContent["downloadCover"] = downloadCover; + downloadBase.NeedDownloadContent["downloadAudio"] = downloadAudio; + downloadBase.NeedDownloadContent["downloadVideo"] = downloadVideo; + downloadBase.NeedDownloadContent["downloadDanmaku"] = downloadDanmaku; + downloadBase.NeedDownloadContent["downloadSubtitle"] = downloadSubtitle; + downloadBase.NeedDownloadContent["downloadCover"] = downloadCover; + + DownloadingItem downloadingItem = new DownloadingItem + { + DownloadBase = downloadBase, + Downloading = downloading, + PlayUrl = page.PlayUrl, + //ZoneImage = (DrawingImage)Application.Current.Resources[VideoZoneIcon.Instance().GetZoneImageKey(zoneId)], + }; // 添加到下载列表 - App.DownloadingList.Add(downloading); + App.DownloadingList.Add(downloadingItem); i++; } } diff --git a/src/DownKyi/Views/DownloadManager/ViewDownloadFinished.xaml b/src/DownKyi/Views/DownloadManager/ViewDownloadFinished.xaml index 1c03fd9..49b63b6 100644 --- a/src/DownKyi/Views/DownloadManager/ViewDownloadFinished.xaml +++ b/src/DownKyi/Views/DownloadManager/ViewDownloadFinished.xaml @@ -2,9 +2,303 @@ x:Class="DownKyi.Views.DownloadManager.ViewDownloadFinished" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:converter="clr-namespace:DownKyi.Converter" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True"> + + + + + + - 已下载 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +