Compare commits

...
26 Commits
Author SHA1 Message Date
leiurayer 8cd0f82e09 发布v1.5.7 2023-02-18 12:31:57 +08:00
leiurayer 6f3273d411 更新依赖版本 2023-02-17 22:21:53 +08:00
leiurayer e23c59deb4 Update ReadMe 2023-02-17 22:04:22 +08:00
leiurayer 99edb6c369 解决默认编码为AVC,但画质为杜比视界时,不会自动选中HEVC编码的问题 #643 2023-02-17 00:02:34 +08:00
leiurayer 5d4f23d8c4 重写AppInfo中的版本号 2023-02-16 23:07:14 +08:00
leiurayer 683159b87b 下载前检测无效的下载目录 #574 2023-02-13 22:32:46 +08:00
leiurayer d36a2b06e2 Update ReadMe 2023-01-15 11:31:59 +08:00
leiurayer b3af82b3a3 Update ReadMe 2023-01-15 11:23:43 +08:00
leiurayer 8d744eb106 新增自定义UserAgent 2023-01-11 16:56:22 +08:00
leiurayer e4f1f9dce2 修复删除下载项时内建下载器崩溃的bug 2023-01-11 16:55:11 +08:00
leiurayer cc4dd706fe 输出aria2错误信息到UI 2023-01-10 21:26:39 +08:00
leiurayer 9f55fde526 Update log 2023-01-06 17:09:27 +08:00
leiurayer cac7adf53f 发布v1.5.6 2023-01-06 17:02:22 +08:00
leiurayer a93f74d088 修复弹幕无法下载的bug 2023-01-06 16:05:50 +08:00
leiurayer 7b45274cad 修正多线程下载的bug 2023-01-06 15:33:06 +08:00
MoguCloud d8b747a48d Fix FormatFileName
修复当文件名以连续的点、空格、点结尾 (例如"abc . . ")时,无法完全去除开头/结尾的点和空格
需要额外处理当文件名都是非法字符的情况
2022-12-31 16:55:02 +08:00
leiurayer eef382c867 发布v1.5.5 2022-11-06 15:59:21 +08:00
leiurayer eb274f82b9 完成关注和粉丝页面 2022-11-06 15:43:28 +08:00
leiurayer 15c31ee6b8 去除编译警告,纠正注释 2022-11-05 21:48:00 +08:00
leiurayer 2afa3f96d6 微调页码控件 2022-11-05 21:45:01 +08:00
leiurayer 91c9f9ceff 更新分区列表 2022-11-05 21:43:55 +08:00
leiurayer f4d0585008 更新悄悄关注API 2022-11-05 21:43:31 +08:00
leiurayer e06f239557 更新依赖包 2022-10-21 23:41:57 +08:00
leiurayer d572d3d6ae 修复命名格式无AV1编码的问题 2022-10-21 23:40:43 +08:00
leiurayer ef4a87b478 优先解析视频编码顺序为AV1、HEVC、AVC 2022-10-21 23:40:18 +08:00
leiurayer 6b7fb239ad 修复自定义aria服务器监听端口设置无效的问题 2022-10-16 14:55:14 +08:00
74 changed files with 2296 additions and 410 deletions
+25
View File
@@ -1,5 +1,30 @@
# 更新日志
## `2023/02/18` v1.5.7
* [新增] 自定义UserAgent。
* [新增] 程序检查更新。
* [优化] 下载前检测无效的下载目录。
* [优化] 更新依赖版本。
* [优化] 输出Aria2错误信息到UI。
* [修复] 默认编码为AVC,但画质为杜比视界时,不会自动选中HEVC编码的问题。
* [修复] 删除下载项时内建下载器崩溃的问题。
## `2023/01/06` v1.5.6
* [修复] 文件名包含非法字符。
* [修复] 多线程下载的bug。
* [修复] 弹幕无法下载的bug。
## `2022/11/06` v1.5.5
* [优化] 更新分区列表。
* [优化] 更新依赖包。
* [新增] 关注和粉丝页面。
* [修复] 命名格式无AV1编码的问题。
* [修复] 优先解析视频编码顺序为AV1、HEVC、AVC。
* [修复] 自定义aria服务器监听端口设置无效的问题。
## `2022/10/16` v1.5.4
* [新增] 支持AV1编码视频。
+15 -6
View File
@@ -35,6 +35,15 @@
</a>
</p>
[更新日志](CHANGELOG.md)
## 问题
- Aria下载失败:检查aria2c.exe是否可以正常工作和是否允许通过防火墙;或者尝试切换端口号。
- 内建下载器失败:请提issue,也欢迎pr。
- 下载时卡在“混流中”:检查ffmpeg.exe是否可以正常工作。
- 去水印:宽/高为水印的尺寸,X/Y为水印在图像中的位置(以左上角为原点),这四个数据可通过Photoshop获得。
## 赞助
如果这个项目对您有很大帮助,并且您希望支持该项目的开发和维护,请随时扫描一下二维码进行捐赠。非常感谢您的捐款,谢谢!
@@ -47,15 +56,15 @@
发布的压缩包中aria2c.exe和ffmpeg.exe均为32位,如果需要请用下面链接中的文件替换。
* [aria2-1.36.0-win-32bit](third_party/aria2-1.36.0-win-32bit-build1.zip)
* [aria2-1.36.0-win-64bit](third_party/aria2-1.36.0-win-64bit-build1.zip)
* [FFmpeg](https://github.com/leiurayer/FFmpeg-Builds/releases/tag/latest)
- [aria2-1.36.0-win-32bit](third_party/aria2-1.36.0-win-32bit-build1.zip)
- [aria2-1.36.0-win-64bit](third_party/aria2-1.36.0-win-64bit-build1.zip)
- [FFmpeg](https://github.com/leiurayer/FFmpeg-Builds/releases/tag/latest)
### 相关项目
* [哔哩哔哩-API收集整理](https://github.com/SocialSisterYi/bilibili-API-collect):B站API归档
* [Prism](https://github.com/PrismLibrary/Prism):MVVM框架
* [WebPSharp](https://github.com/leiurayer/WebPSharp):WebP格式图片支持,[NuGet程序包](third_party/WebPSharp.0.5.1.nupkg)
- [哔哩哔哩-API收集整理](https://github.com/SocialSisterYi/bilibili-API-collect):B站API归档
- [Prism](https://github.com/PrismLibrary/Prism):MVVM框架
- [WebPSharp](https://github.com/leiurayer/WebPSharp):WebP格式图片支持,[NuGet程序包](third_party/WebPSharp.0.5.1.nupkg)
## 免责申明
@@ -18,8 +18,10 @@ namespace DownKyi.Core.Aria2cNet.Client
private static readonly string JSONRPC = "2.0";
private const string LOCAL_HOST = "http://localhost";
private const string TOKEN = "downkyi";
private const int LISTEN_PORT = 6800;
private static string host = LOCAL_HOST;
private static string token = TOKEN;
private static string token = TOKEN;
private static int listenPort = LISTEN_PORT;
/// <summary>
/// This method adds a new download.
@@ -1039,13 +1041,18 @@ namespace DownKyi.Core.Aria2cNet.Client
AriaClient.host = host;
}
public static void SetListenPort(int listenPort = LISTEN_PORT)
{
AriaClient.listenPort = listenPort;
}
/// <summary>
/// 获取jsonrpc的地址
/// </summary>
/// <returns></returns>
private static string GetRpcUri(int listenPort = 6800)
private static string GetRpcUri()
{
return $"{host}:{listenPort}/jsonrpc";
return $"{host}:{AriaClient.listenPort}/jsonrpc";
}
/// <summary>
@@ -5,8 +5,6 @@ using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace DownKyi.Core.Aria2cNet.Server
{
@@ -22,7 +20,7 @@ namespace DownKyi.Core.Aria2cNet.Server
/// <param name="output"></param>
/// <param name="window"></param>
/// <returns></returns>
public static async Task<bool> StartServerAsync(AriaConfig config, TextBox output = null, Window window = null)
public static async Task<bool> StartServerAsync(AriaConfig config, Action<string> action)
{
// aria端口
ListenPort = config.ListenPort;
@@ -114,17 +112,11 @@ namespace DownKyi.Core.Aria2cNet.Server
null, (s, e) =>
{
if (e.Data == null || e.Data == "" || e.Data.Replace(" ", "") == "") { return; }
Utils.Debugging.Console.PrintLine(e.Data);
LogManager.Debug("AriaServer", e.Data);
if (output != null && window != null)
{
window.Dispatcher.Invoke(new Action(() =>
{
output.Text += e.Data + "\n";
output.ScrollToEnd();
}));
}
action.Invoke(e.Data);
});
});
+10 -10
View File
@@ -6,17 +6,17 @@ namespace DownKyi.Core.BiliApi.BiliUtils
{
private static readonly List<Quality> resolutions = new List<Quality>
{
new Quality { Name = "超高清 8K", Id = 127 },
new Quality { Name = "杜比视界", Id = 126 },
new Quality { Name = "HDR 真彩", Id = 125 },
new Quality { Name = "4K 超清", Id = 120 },
new Quality { Name = "1080P 60帧", Id = 116 },
new Quality { Name = "1080P 高码率", Id = 112 },
new Quality { Name = "1080P 高清", Id = 80 },
new Quality { Name = "720P 60帧", Id = 74 },
new Quality { Name = "720P 高清", Id = 64 },
new Quality { Name = "480P 清晰", Id = 32 },
new Quality { Name = "360P 流畅", Id = 16 },
new Quality { Name = "480P 清晰", Id = 32 },
new Quality { Name = "720P 高清", Id = 64 },
new Quality { Name = "720P 60帧", Id = 74 },
new Quality { Name = "1080P 高清", Id = 80 },
new Quality { Name = "1080P 高码率", Id = 112 },
new Quality { Name = "1080P 60帧", Id = 116 },
new Quality { Name = "4K 超清", Id = 120 },
new Quality { Name = "HDR 真彩", Id = 125 },
new Quality { Name = "杜比视界", Id = 126 },
new Quality { Name = "超高清 8K", Id = 127 },
};
private static readonly List<Quality> codecIds = new List<Quality>
@@ -23,7 +23,9 @@ namespace DownKyi.Core.BiliApi.Users.Models
public string Face { get; set; }
[JsonProperty("sign")]
public string Sign { get; set; }
// face_nft
// official_verify
// vip
// nft_icon
}
}
@@ -8,7 +8,14 @@ namespace DownKyi.Core.BiliApi.Users.Models
public class RelationWhisper : BaseModel
{
[JsonProperty("data")]
public List<RelationFollowInfo> Data { get; set; }
public RelationWhisperData Data { get; set; }
}
public class RelationWhisperData : BaseModel
{
[JsonProperty("list")]
public List<RelationFollowInfo> List { get; set; }
// re_version
}
}
@@ -139,8 +139,8 @@ namespace DownKyi.Core.BiliApi.Users
try
{
RelationWhisper relationWhisper = JsonConvert.DeserializeObject<RelationWhisper>(response);
if (relationWhisper == null || relationWhisper.Data == null) { return null; }
return relationWhisper.Data;
if (relationWhisper == null || relationWhisper.Data == null || relationWhisper.Data.List == null) { return null; }
return relationWhisper.Data.List;
}
catch (Exception e)
{
+2 -5
View File
@@ -1,5 +1,6 @@
using Brotli;
using DownKyi.Core.BiliApi.Login;
using DownKyi.Core.Settings;
using System;
using System.Collections.Generic;
using System.IO;
@@ -50,11 +51,7 @@ namespace DownKyi.Core.BiliApi
request.Method = method;
request.Timeout = 30 * 1000;
// MacOS Safari
//string safari = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15";
// Windows 10 Chrome
string chrome = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36";
request.UserAgent = chrome;
request.UserAgent = SettingsManager.GetInstance().GetUserAgent();
//request.ContentType = "application/json,text/html,application/xhtml+xml,application/xml;charset=UTF-8";
request.Headers["accept-language"] = "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7";
+114 -108
View File
@@ -31,174 +31,180 @@ namespace DownKyi.Core.BiliApi.Zone
//动画
zones.Add(new ZoneAttr(1, "douga", "动画")); // 主分区
zones.Add(new ZoneAttr(24, "mad", "MAD·AMV", 1)); //具有一定制作程度的动画或静画的二次创作视频
zones.Add(new ZoneAttr(25, "mmd", "MMD·3D", 1)); //使用MMD(MikuMikuDance)和其他3D建模类软件制作的视频
zones.Add(new ZoneAttr(47, "voice", "短片·手书·配音", 1)); //追求创新并具有强烈特色的短片、手书(绘)及ACG相关配音
zones.Add(new ZoneAttr(210, "garage_kit", "手办·模玩", 1)); //手办模玩的测评、改造或其他衍生内容
zones.Add(new ZoneAttr(86, "tokusatsu", "特摄", 1)); //特摄相关衍生视频
zones.Add(new ZoneAttr(27, "other", "综合", 1)); //以动画及动画相关内容为素材,包括但不仅限于音频替换、杂谈、排行榜等内容
zones.Add(new ZoneAttr(24, "mad", "MAD·AMV", 1)); // 具有一定制作程度的动画或静画的二次创作视频
zones.Add(new ZoneAttr(25, "mmd", "MMD·3D", 1)); // 使用MMD(MikuMikuDance)和其他3D建模类软件制作的视频
zones.Add(new ZoneAttr(47, "voice", "短片·手书·配音", 1)); // 追求个人特色和创意表达的自制动画短片、手书(绘)及ACGN相关配音
zones.Add(new ZoneAttr(210, "garage_kit", "手办·模玩", 1)); // 手办模玩的测评、改造或其他衍生内容
zones.Add(new ZoneAttr(86, "tokusatsu", "特摄", 1)); // 特摄相关衍生视频
zones.Add(new ZoneAttr(253, "acgntalks", "动漫杂谈", 1)); // 以谈话形式对ACGN文化圈进行的鉴赏、吐槽、评点、解说、推荐、科普等内容
zones.Add(new ZoneAttr(27, "other", "综合", 1)); // 以动画及动画相关内容为素材,包括但不仅限于音频替换、恶搞改编、排行榜等内容
//番剧
zones.Add(new ZoneAttr(13, "anime", "番剧")); // 主分区
zones.Add(new ZoneAttr(33, "serial", "连载动画", 13)); //当季连载的动画番剧
zones.Add(new ZoneAttr(32, "finish", "完结动画", 13)); //已完结的动画番剧合集
zones.Add(new ZoneAttr(51, "information", "资讯", 13)); //动画番剧相关资讯视频
zones.Add(new ZoneAttr(152, "offical", "官方延伸", 13)); //动画番剧为主题的宣传节目、采访视频,及声优相关视频
zones.Add(new ZoneAttr(33, "serial", "连载动画", 13)); // 当季连载的动画番剧
zones.Add(new ZoneAttr(32, "finish", "完结动画", 13)); // 已完结的动画番剧合集
zones.Add(new ZoneAttr(51, "information", "资讯", 13)); // 动画番剧相关资讯视频
zones.Add(new ZoneAttr(152, "offical", "官方延伸", 13)); // 动画番剧为主题的宣传节目、采访视频,及声优相关视频
//国创
zones.Add(new ZoneAttr(167, "guochuang", "国创")); // 主分区
zones.Add(new ZoneAttr(153, "chinese", "国产动画", 167)); //我国出品的PGC动画
zones.Add(new ZoneAttr(168, "original", "国产原创相关", 167)); //
zones.Add(new ZoneAttr(169, "puppetry", "布袋戏", 167)); //
zones.Add(new ZoneAttr(195, "motioncomic", "动态漫·广播剧", 167)); //
zones.Add(new ZoneAttr(170, "information", "资讯", 167)); //
zones.Add(new ZoneAttr(153, "chinese", "国产动画", 167)); // 我国出品的PGC动画
zones.Add(new ZoneAttr(168, "original", "国产原创相关", 167)); //
zones.Add(new ZoneAttr(169, "puppetry", "布袋戏", 167)); //
zones.Add(new ZoneAttr(195, "motioncomic", "动态漫·广播剧", 167)); //
zones.Add(new ZoneAttr(170, "information", "资讯", 167)); //
//音乐
zones.Add(new ZoneAttr(3, "music", "音乐")); // 主分区
zones.Add(new ZoneAttr(28, "original", "原创音乐", 3)); //个人或团队制作以音乐为主要原创因素的歌曲或纯音乐
zones.Add(new ZoneAttr(31, "cover", "翻唱", 3)); //一切非官方的人声再演绎歌曲作品
zones.Add(new ZoneAttr(30, "vocaloid", "VOCALOID·UTAU", 3)); //以雅马哈Vocaloid和UTAU引擎为基础,包含其他调教引擎,运用各类音源进行的歌曲创作内容
zones.Add(new ZoneAttr(194, "electronic", "电音", 3)); //以电子合成器、音乐软体等产生的电子声响制作的音乐
zones.Add(new ZoneAttr(59, "perform", "演奏", 3)); //传统或非传统乐器及器材的演奏作品
zones.Add(new ZoneAttr(193, "mv", "MV", 3)); //音乐录影带,为搭配音乐而拍摄或制作的视频
zones.Add(new ZoneAttr(29, "live", "音乐现场", 3)); //音乐实况表演视频
zones.Add(new ZoneAttr(130, "other", "音乐综合", 3)); //收录无法定义到其他音乐子分区的音乐视频
zones.Add(new ZoneAttr(28, "original", "原创音乐", 3)); // 原创歌曲及纯音乐,包括改编、重编曲及remix
zones.Add(new ZoneAttr(31, "cover", "翻唱", 3)); // 对曲目的人声再演绎视频
zones.Add(new ZoneAttr(59, "perform", "演奏", 3)); // 乐器和非传统乐器器材的演奏作品
zones.Add(new ZoneAttr(30, "vocaloid", "VOCALOID·UTAU", 3)); // 以VOCALOID等歌声合成引擎为基础,运用各类音源进行的创作
zones.Add(new ZoneAttr(29, "live", "音乐现场", 3)); // 音乐表演的实况视频,包括官方/个人拍摄的综艺节目、音乐剧、音乐节、演唱会等
zones.Add(new ZoneAttr(193, "mv", "MV", 3)); // 为音乐作品配合拍摄或制作的音乐录影带(Music Video),以及自制拍摄、剪辑、翻拍MV
zones.Add(new ZoneAttr(243, "commentary", "乐评盘点", 3)); // 音乐类新闻、盘点、点评、reaction、榜单、采访、幕后故事、唱片开箱等
zones.Add(new ZoneAttr(244, "tutorial", "音乐教学", 3)); // 以音乐教学为目的的内容
zones.Add(new ZoneAttr(130, "other", "音乐综合", 3)); // 所有无法被收纳到其他音乐二级分区的音乐类视频
//舞蹈
zones.Add(new ZoneAttr(129, "dance", "舞蹈")); // 主分区
zones.Add(new ZoneAttr(20, "otaku", "宅舞", 129)); //与ACG相关的翻跳、原创舞蹈
zones.Add(new ZoneAttr(198, "hiphop", "街舞", 129)); //收录街舞相关内容,包括赛事现场、舞室作品、个人翻跳、FREESTYLE等
zones.Add(new ZoneAttr(199, "star", "明星舞蹈", 129)); //国内外明星发布的官方舞蹈及其翻跳内容
zones.Add(new ZoneAttr(200, "china", "中国舞", 129)); //传承中国艺术文化的舞蹈内容,包括古典舞、民族民间舞、汉唐舞、古风舞等
zones.Add(new ZoneAttr(154, "three_d", "舞蹈综合", 129)); //收录无法定义到其他舞蹈子分区的舞蹈视频
zones.Add(new ZoneAttr(156, "demo", "舞蹈教程", 129)); //镜面慢速,动作分解,基础教程等具有教学意义的舞蹈视频
zones.Add(new ZoneAttr(20, "otaku", "宅舞", 129)); // 与ACG相关的翻跳、原创舞蹈
zones.Add(new ZoneAttr(198, "hiphop", "街舞", 129)); // 收录街舞相关内容,包括赛事现场、舞室作品、个人翻跳、FREESTYLE等
zones.Add(new ZoneAttr(199, "star", "明星舞蹈", 129)); // 国内外明星发布的官方舞蹈及其翻跳内容
zones.Add(new ZoneAttr(200, "china", "中国舞", 129)); // 传承中国艺术文化的舞蹈内容,包括古典舞、民族民间舞、汉唐舞、古风舞等
zones.Add(new ZoneAttr(154, "three_d", "舞蹈综合", 129)); // 收录无法定义到其他舞蹈子分区的舞蹈视频
zones.Add(new ZoneAttr(156, "demo", "舞蹈教程", 129)); // 镜面慢速,动作分解,基础教程等具有教学意义的舞蹈视频
//游戏
zones.Add(new ZoneAttr(4, "game", "游戏")); // 主分区
zones.Add(new ZoneAttr(17, "stand_alone", "单机游戏", 4)); //以所有平台(PC、主机、移动端)的单机或联机游戏为主的视频内容,包括游戏预告、CG、实况解说及相关的评测、杂谈与视频剪辑等
zones.Add(new ZoneAttr(171, "esports", "电子竞技", 4)); //具有高对抗性的电子竞技游戏项目,其相关的赛事、实况、攻略、解说、短剧等视频。
zones.Add(new ZoneAttr(172, "mobile", "手机游戏", 4)); //以手机及平板设备为主要平台的游戏,其相关的实况、攻略、解说、短剧、演示等视频。
zones.Add(new ZoneAttr(65, "online", "网络游戏", 4)); //由网络运营商运营的多人在线游戏,以及电子竞技的相关游戏内容。包括赛事、攻略、实况、解说等相关视频
zones.Add(new ZoneAttr(173, "board", "桌游棋牌", 4)); //桌游、棋牌、卡牌对战等及其相关电子版游戏的实况、攻略、解说、演示等视频。
zones.Add(new ZoneAttr(121, "gmv", "GMV", 4)); //由游戏素材制作的MV视频。以游戏内容或CG为主制作的,具有一定创作程度的MV类型的视频
zones.Add(new ZoneAttr(136, "music", "音游", 4)); //各个平台上,通过配合音乐与节奏而进行的音乐类游戏视频
zones.Add(new ZoneAttr(19, "mugen", "Mugen", 4)); //以Mugen引擎为平台制作、或与Mugen相关的游戏视频
zones.Add(new ZoneAttr(17, "stand_alone", "单机游戏", 4)); // 以所有平台(PC、主机、移动端)的单机或联机游戏为主的视频内容,包括游戏预告、CG、实况解说及相关的评测、杂谈与视频剪辑等
zones.Add(new ZoneAttr(171, "esports", "电子竞技", 4)); // 具有高对抗性的电子竞技游戏项目,其相关的赛事、实况、攻略、解说、短剧等视频。
zones.Add(new ZoneAttr(172, "mobile", "手机游戏", 4)); // 以手机及平板设备为主要平台的游戏,其相关的实况、攻略、解说、短剧、演示等视频。
zones.Add(new ZoneAttr(65, "online", "网络游戏", 4)); // 由网络运营商运营的多人在线游戏,以及电子竞技的相关游戏内容。包括赛事、攻略、实况、解说等相关视频
zones.Add(new ZoneAttr(173, "board", "桌游棋牌", 4)); // 桌游、棋牌、卡牌对战等及其相关电子版游戏的实况、攻略、解说、演示等视频。
zones.Add(new ZoneAttr(121, "gmv", "GMV", 4)); // 由游戏素材制作的MV视频。以游戏内容或CG为主制作的,具有一定创作程度的MV类型的视频
zones.Add(new ZoneAttr(136, "music", "音游", 4)); // 各个平台上,通过配合音乐与节奏而进行的音乐类游戏视频
zones.Add(new ZoneAttr(19, "mugen", "Mugen", 4)); // 以Mugen引擎为平台制作、或与Mugen相关的游戏视频
//知识
zones.Add(new ZoneAttr(36, "knowledge", "知识")); // 主分区
zones.Add(new ZoneAttr(201, "science", "科学科普", 36)); //回答你的十万个为什么
zones.Add(new ZoneAttr(124, "social_science", "社科·法律·心理", 36)); //基于社会科学、法学、心理学展开或个人观点输出的知识视频
zones.Add(new ZoneAttr(228, "humanity_history", "人文历史", 36)); //看看古今人物,聊聊历史过往,品品文学典籍
zones.Add(new ZoneAttr(207, "business", "财经商业", 36)); //说金融市场,谈宏观经济,一起畅聊商业故事
zones.Add(new ZoneAttr(208, "campus", "校园学习", 36)); //老师很有趣,学生也有才,我们一起搞学习
zones.Add(new ZoneAttr(209, "career", "职业职场", 36)); //职业分享、升级指南,一起成为最有料的职场人
zones.Add(new ZoneAttr(229, "design", "设计·创意", 36)); //天马行空,创意设计,都在这里
zones.Add(new ZoneAttr(122, "skill", "野生技能协会", 36)); //技能党集合,是时候展示真正的技术了
zones.Add(new ZoneAttr(201, "science", "科学科普", 36)); // 回答你的十万个为什么
zones.Add(new ZoneAttr(124, "social_science", "社科·法律·心理", 36)); // 基于社会科学、法学、心理学展开或个人观点输出的知识视频
zones.Add(new ZoneAttr(228, "humanity_history", "人文历史", 36)); // 看看古今人物,聊聊历史过往,品品文学典籍
zones.Add(new ZoneAttr(207, "business", "财经商业", 36)); // 说金融市场,谈宏观经济,一起畅聊商业故事
zones.Add(new ZoneAttr(208, "campus", "校园学习", 36)); // 老师很有趣,学生也有才,我们一起搞学习
zones.Add(new ZoneAttr(209, "career", "职业职场", 36)); // 职业分享、升级指南,一起成为最有料的职场人
zones.Add(new ZoneAttr(229, "design", "设计·创意", 36)); // 天马行空,创意设计,都在这里
zones.Add(new ZoneAttr(122, "skill", "野生技能协会", 36)); // 技能党集合,是时候展示真正的技术了
//科技
zones.Add(new ZoneAttr(188, "tech", "科技")); // 主分区
zones.Add(new ZoneAttr(95, "digital", "数码", 188)); //科技数码产品大全,一起来做发烧友
zones.Add(new ZoneAttr(230, "application", "软件应用", 188)); //超全软件应用指南
zones.Add(new ZoneAttr(231, "computer_tech", "计算机技术", 188)); //研究分析、教学演示、经验分享......有关计算机技术的都在这里
zones.Add(new ZoneAttr(232, "industry", "工业·工程·机械", 188)); //前方高能,机甲重工即将出没
zones.Add(new ZoneAttr(233, "diy", "极客DIY", 188)); //炫酷技能,极客文化,硬核技巧,准备好你的惊讶
zones.Add(new ZoneAttr(95, "digital", "数码", 188)); // 科技数码产品大全,一起来做发烧友
zones.Add(new ZoneAttr(230, "application", "软件应用", 188)); // 超全软件应用指南
zones.Add(new ZoneAttr(231, "computer_tech", "计算机技术", 188)); // 研究分析、教学演示、经验分享......有关计算机技术的都在这里
zones.Add(new ZoneAttr(232, "industry", "科工机械", 188)); // 从小芯片到大工程,一起见证科工力量
zones.Add(new ZoneAttr(233, "diy", "极客DIY", 188)); // 炫酷技能,极客文化,硬核技巧,准备好你的惊讶
//运动
zones.Add(new ZoneAttr(234, "sports", "运动")); // 主分区
zones.Add(new ZoneAttr(235, "basketballfootball", "篮球·足球", 234)); //与篮球、足球相关的视频,包括但不限于篮足球赛事、教学、评述、剪辑、剧情等相关内容
zones.Add(new ZoneAttr(164, "aerobics", "健身", 234)); //与健身相关的视频,包括但不限于瑜伽、CrossFit、健美、力量举、普拉提、街健等相关内容
zones.Add(new ZoneAttr(236, "athletic", "竞技体育", 234)); //与竞技体育相关的视频,包括但不限于乒乓、羽毛球、排球、赛车等竞技项目的赛事、评述、剪辑、剧情等相关内容
zones.Add(new ZoneAttr(237, "culture", "运动文化", 234)); //与运动文化相关的视频,包络但不限于球鞋、球衣、球星卡等运动衍生品的分享、解读,体育产业的分析、科普等相关内容
zones.Add(new ZoneAttr(238, "comprehensive", "运动综合", 234)); //与运动综合相关的视频,包括但不限于钓鱼、骑行、滑板等日常运动分享、教学、Vlog等相关内容
zones.Add(new ZoneAttr(235, "basketball", "篮球", 234)); // 与篮球相关的视频,包括但不限于篮球赛事、教学、评述、剪辑、剧情等相关内容
zones.Add(new ZoneAttr(249, "football", "足球", 234)); // 与足球相关的视频,包括但不限于足球赛事、教学、评述、剪辑、剧情等相关内容
zones.Add(new ZoneAttr(164, "aerobics", "健身", 234)); // 与健身相关的视频,包括但不限于瑜伽、CrossFit、健美、力量举、普拉提、街健等相关内容
zones.Add(new ZoneAttr(236, "athletic", "竞技体育", 234)); // 与竞技体育相关的视频,包括但不限于乒乓、羽毛球、排球、赛车等竞技项目的赛事、评述、剪辑、剧情等相关内容
zones.Add(new ZoneAttr(237, "culture", "运动文化", 234)); // 与运动文化相关的视频,包络但不限于球鞋、球衣、球星卡等运动衍生品的分享、解读,体育产业的分析、科普等相关内容
zones.Add(new ZoneAttr(238, "comprehensive", "运动综合", 234)); // 与运动综合相关的视频,包括但不限于钓鱼、骑行、滑板等日常运动分享、教学、Vlog等相关内容
//汽车
zones.Add(new ZoneAttr(223, "car", "汽车")); // 主分区
zones.Add(new ZoneAttr(176, "life", "汽车生活", 223)); //分享汽车及出行相关的生活体验类视频
zones.Add(new ZoneAttr(224, "culture", "汽车文化", 223)); //车迷的精神圣地,包括汽车赛事、品牌历史、汽车改装、经典车型和汽车模型等
zones.Add(new ZoneAttr(225, "geek", "汽车极客", 223)); //汽车硬核达人聚集地,包括DIY造车、专业评测和技术知识分享
zones.Add(new ZoneAttr(240, "motorcycle", "摩托车", 223)); //骑士们集合啦
zones.Add(new ZoneAttr(226, "smart", "智能出行", 223)); //探索新能源汽车和未来智能出行的前沿阵地
zones.Add(new ZoneAttr(227, "strategy", "购车攻略", 223)); //丰富详实的购车建议和新车体验
zones.Add(new ZoneAttr(245, "racing", "赛车", 223)); // F1等汽车运动相关
zones.Add(new ZoneAttr(246, "modifiedvehicle", "改装玩车", 223)); // 汽车文化及改装车相关内容,包括改装车、老车修复介绍、汽车聚会分享等内容
zones.Add(new ZoneAttr(247, "newenergyvehicle", "新能源车", 223)); // 新能源汽车相关内容,包括电动汽车、混合动力汽车等车型种类,包含不限于新车资讯、试驾体验、专业评测、技术解读、知识科普等内容
zones.Add(new ZoneAttr(248, "touringcar", "房车", 223)); // 房车及营地相关内容,包括不限于产品介绍、驾驶体验、房车生活和房车旅行等内容
zones.Add(new ZoneAttr(240, "motorcycle", "摩托车", 223)); // 骑士们集合啦
zones.Add(new ZoneAttr(227, "strategy", "购车攻略", 223)); // 丰富详实的购车建议和新车体验
zones.Add(new ZoneAttr(176, "life", "汽车生活", 223)); // 分享汽车及出行相关的生活体验类视频
//生活
zones.Add(new ZoneAttr(160, "life", "生活")); // 主分区
zones.Add(new ZoneAttr(138, "funny", "搞笑", 160)); //各种沙雕有趣的搞笑剪辑,挑战,表演,配音等视频
zones.Add(new ZoneAttr(250, "travel", "出行", 160)); //为达到观光游览、休闲娱乐为目的的远途旅行、中近途户外生活、本地探店
zones.Add(new ZoneAttr(239, "home", "家居房产", 160)); //与买房、装修、居家生活相关的分享
zones.Add(new ZoneAttr(161, "handmake", "手工", 160)); //手工制品的制作过程或成品展示、教程、测评类视频
zones.Add(new ZoneAttr(162, "painting", "绘画", 160)); //绘画过程或绘画教程,以及绘画相关的所有视频
zones.Add(new ZoneAttr(21, "daily", "日常", 160)); //记录日常生活,分享生活故事
zones.Add(new ZoneAttr(138, "funny", "搞笑", 160)); // 各种沙雕有趣的搞笑剪辑,挑战,表演,配音等视频
zones.Add(new ZoneAttr(250, "travel", "Energy", 160)); // 为达到观光游览、休闲娱乐为目的的远途旅行、中近途户外生活、本地探店
zones.Add(new ZoneAttr(251, "rurallife", "三农", 160)); // 分享美好农村生活
zones.Add(new ZoneAttr(239, "home", "家居房产", 160)); // 与买房、装修、居家生活相关的分享
zones.Add(new ZoneAttr(161, "handmake", "手工", 160)); // 手工制品的制作过程或成品展示、教程、测评类视频
zones.Add(new ZoneAttr(162, "painting", "绘画", 160)); // 绘画过程或绘画教程,以及绘画相关的所有视频
zones.Add(new ZoneAttr(21, "daily", "日常", 160)); // 记录日常生活,分享生活故事
//美食
zones.Add(new ZoneAttr(211, "food", "美食")); // 主分区
zones.Add(new ZoneAttr(76, "make", "美食制作", 211)); //学做人间美味,展示精湛厨艺
zones.Add(new ZoneAttr(212, "detective", "美食侦探", 211)); //寻找美味餐厅,发现街头美食
zones.Add(new ZoneAttr(213, "measurement", "美食测评", 211)); //吃货世界,品尝世间美味
zones.Add(new ZoneAttr(214, "rural", "田园美食", 211)); //品味乡野美食,寻找山与海的味道
zones.Add(new ZoneAttr(215, "record", "美食记录", 211)); //记录一日三餐,给生活添一点幸福感
zones.Add(new ZoneAttr(76, "make", "美食制作", 211)); // 学做人间美味,展示精湛厨艺
zones.Add(new ZoneAttr(212, "detective", "美食侦探", 211)); // 寻找美味餐厅,发现街头美食
zones.Add(new ZoneAttr(213, "measurement", "美食测评", 211)); // 吃货世界,品尝世间美味
zones.Add(new ZoneAttr(214, "rural", "田园美食", 211)); // 品味乡野美食,寻找山与海的味道
zones.Add(new ZoneAttr(215, "record", "美食记录", 211)); // 记录一日三餐,给生活添一点幸福感
//动物圈
zones.Add(new ZoneAttr(217, "animal", "动物圈")); // 主分区
zones.Add(new ZoneAttr(218, "cat", "喵星人", 217)); //喵喵喵喵喵
zones.Add(new ZoneAttr(219, "dog", "汪星人", 217)); //汪汪汪汪汪
zones.Add(new ZoneAttr(220, "panda", "大熊猫", 217)); //芝麻汤圆营业中
zones.Add(new ZoneAttr(221, "wild_animal", "野生动物", 217)); //内有“猛兽”出没
zones.Add(new ZoneAttr(222, "reptiles", "爬宠", 217)); //鳞甲有灵
zones.Add(new ZoneAttr(75, "animal_composite", "动物综合", 217)); //收录除上述子分区外,其余动物相关视频以及非动物主体或多个动物主体的动物相关延伸内容
zones.Add(new ZoneAttr(218, "cat", "喵星人", 217)); // 喵喵喵喵喵
zones.Add(new ZoneAttr(219, "dog", "汪星人", 217)); // 汪汪汪汪汪
zones.Add(new ZoneAttr(220, "panda", "大熊猫", 217)); // 芝麻汤圆营业中
zones.Add(new ZoneAttr(221, "wild_animal", "野生动物", 217)); // 内有“猛兽”出没
zones.Add(new ZoneAttr(222, "reptiles", "爬宠", 217)); // 鳞甲有灵
zones.Add(new ZoneAttr(75, "animal_composite", "动物综合", 217)); // 收录除上述子分区外,其余动物相关视频以及非动物主体或多个动物主体的动物相关延伸内容
//鬼畜
zones.Add(new ZoneAttr(119, "kichiku", "鬼畜")); // 主分区
zones.Add(new ZoneAttr(22, "guide", "鬼畜调教", 119)); //使用素材在音频、画面上做一定处理,达到与BGM一定的同步感
zones.Add(new ZoneAttr(26, "mad", "音MAD", 119)); //使用素材音频进行一定的二次创作来达到还原原曲的非商业性质稿件
zones.Add(new ZoneAttr(126, "manual_vocaloid", "人力VOCALOID", 119)); //将人物或者角色的无伴奏素材进行人工调音,使其就像VOCALOID一样歌唱的技术
zones.Add(new ZoneAttr(216, "theatre", "鬼畜剧场", 119)); //使用素材进行人工剪辑编排的有剧情的作品
zones.Add(new ZoneAttr(127, "course", "教程演示", 119)); //鬼畜相关的教程演示
zones.Add(new ZoneAttr(22, "guide", "鬼畜调教", 119)); // 使用素材在音频、画面上做一定处理,达到与BGM一定的同步感
zones.Add(new ZoneAttr(26, "mad", "音MAD", 119)); // 使用素材音频进行一定的二次创作来达到还原原曲的非商业性质稿件
zones.Add(new ZoneAttr(126, "manual_vocaloid", "人力VOCALOID", 119)); // 将人物或者角色的无伴奏素材进行人工调音,使其就像VOCALOID一样歌唱的技术
zones.Add(new ZoneAttr(216, "theatre", "鬼畜剧场", 119)); // 使用素材进行人工剪辑编排的有剧情的作品
zones.Add(new ZoneAttr(127, "course", "教程演示", 119)); // 鬼畜相关的教程演示
//时尚
zones.Add(new ZoneAttr(155, "fashion", "时尚")); // 主分区
zones.Add(new ZoneAttr(157, "makeup", "美妆护肤", 155)); //彩妆护肤、美甲美发、仿妆、医美相关内容分享或产品测评
zones.Add(new ZoneAttr(158, "clothing", "穿搭", 155)); //穿搭风格、穿搭技巧的展示分享,涵盖衣服、鞋靴、箱包配件、配饰(帽子、钟表、珠宝首饰)等
zones.Add(new ZoneAttr(159, "trend", "时尚潮流", 155)); //时尚街拍、时装周、时尚大片,时尚品牌、潮流等行业相关记录及知识科普
zones.Add(new ZoneAttr(157, "makeup", "美妆护肤", 155)); // 彩妆护肤、美甲美发、仿妆、医美相关内容分享或产品测评
zones.Add(new ZoneAttr(252, "cos", "仿妆cos", 155)); // 对二次元、三次元人物角色进行模仿、还原、展示、演绎的内容
zones.Add(new ZoneAttr(158, "clothing", "穿搭", 155)); // 穿搭风格、穿搭技巧的展示分享,涵盖衣服、鞋靴、箱包配件、配饰(帽子、钟表、珠宝首饰)等
zones.Add(new ZoneAttr(159, "trend", "时尚潮流", 155)); // 时尚街拍、时装周、时尚大片,时尚品牌、潮流等行业相关记录及知识科普
//资讯
zones.Add(new ZoneAttr(202, "information", "资讯")); // 主分区
zones.Add(new ZoneAttr(203, "hotspot", "热点", 202)); //全民关注的时政热门资讯
zones.Add(new ZoneAttr(204, "global", "环球", 202)); //全球范围内发生的具有重大影响力的事件动态
zones.Add(new ZoneAttr(205, "social", "社会", 202)); //日常生活的社会事件、社会问题、社会风貌的报道
zones.Add(new ZoneAttr(206, "multiple", "综合", 202)); //除上述领域外其它垂直领域的综合资讯
zones.Add(new ZoneAttr(203, "hotspot", "热点", 202)); // 全民关注的时政热门资讯
zones.Add(new ZoneAttr(204, "global", "环球", 202)); // 全球范围内发生的具有重大影响力的事件动态
zones.Add(new ZoneAttr(205, "social", "社会", 202)); // 日常生活的社会事件、社会问题、社会风貌的报道
zones.Add(new ZoneAttr(206, "multiple", "综合", 202)); // 除上述领域外其它垂直领域的综合资讯
//娱乐
zones.Add(new ZoneAttr(5, "ent", "娱乐")); // 主分区
zones.Add(new ZoneAttr(71, "variety", "综艺", 5)); //所有综艺相关,全部一手掌握!
zones.Add(new ZoneAttr(241, "talker", "娱乐杂谈", 5)); //娱乐人物解读、娱乐热点点评、娱乐行业分析
zones.Add(new ZoneAttr(242, "fans", "粉丝创作", 5)); //粉丝向创作视频
zones.Add(new ZoneAttr(137, "celebrity", "明星综合", 5)); //娱乐圈动态、明星资讯相关
zones.Add(new ZoneAttr(71, "variety", "综艺", 5)); // 所有综艺相关,全部一手掌握!
zones.Add(new ZoneAttr(241, "talker", "娱乐杂谈", 5)); // 娱乐人物解读、娱乐热点点评、娱乐行业分析
zones.Add(new ZoneAttr(242, "fans", "粉丝创作", 5)); // 粉丝向创作视频
zones.Add(new ZoneAttr(137, "celebrity", "明星综合", 5)); // 娱乐圈动态、明星资讯相关
//影视
zones.Add(new ZoneAttr(181, "cinephile", "影视")); // 主分区
zones.Add(new ZoneAttr(182, "cinecism", "影视杂谈", 181)); //影视评论、解说、吐槽、科普等
zones.Add(new ZoneAttr(183, "montage", "影视剪辑", 181)); //对影视素材进行剪辑再创作的视频
zones.Add(new ZoneAttr(85, "shortfilm", "短片", 181)); //追求自我表达且具有特色的短片
zones.Add(new ZoneAttr(184, "trailer_info", "预告·资讯", 181)); //影视类相关资讯,预告,花絮等视频
zones.Add(new ZoneAttr(182, "cinecism", "影视杂谈", 181)); // 影视评论、解说、吐槽、科普等
zones.Add(new ZoneAttr(183, "montage", "影视剪辑", 181)); // 对影视素材进行剪辑再创作的视频
zones.Add(new ZoneAttr(85, "shortfilm", "小剧场", 181)); // 有场景、有剧情的演绎类内容
zones.Add(new ZoneAttr(184, "trailer_info", "预告·资讯", 181)); // 影视类相关资讯,预告,花絮等视频
//纪录片
zones.Add(new ZoneAttr(177, "documentary", "纪录片")); // 主分区
zones.Add(new ZoneAttr(37, "history", "人文·历史", 177)); //
zones.Add(new ZoneAttr(178, "science", "科学·探索·自然", 177)); //
zones.Add(new ZoneAttr(179, "military", "军事", 177)); //
zones.Add(new ZoneAttr(180, "travel", "社会·美食·旅行", 177)); //
zones.Add(new ZoneAttr(37, "history", "人文·历史", 177)); //
zones.Add(new ZoneAttr(178, "science", "科学·探索·自然", 177)); //
zones.Add(new ZoneAttr(179, "military", "军事", 177)); //
zones.Add(new ZoneAttr(180, "travel", "社会·美食·旅行", 177)); //
//电影
zones.Add(new ZoneAttr(23, "movie", "电影")); // 主分区
zones.Add(new ZoneAttr(147, "chinese", "华语电影", 23)); //
zones.Add(new ZoneAttr(145, "west", "欧美电影", 23)); //
zones.Add(new ZoneAttr(146, "japan", "日本电影", 23)); //
zones.Add(new ZoneAttr(83, "movie", "其他国家", 23)); //
zones.Add(new ZoneAttr(147, "chinese", "华语电影", 23)); //
zones.Add(new ZoneAttr(145, "west", "欧美电影", 23)); //
zones.Add(new ZoneAttr(146, "japan", "日本电影", 23)); //
zones.Add(new ZoneAttr(83, "movie", "其他国家", 23)); //
//电视剧
zones.Add(new ZoneAttr(11, "tv", "电视剧")); // 主分区
zones.Add(new ZoneAttr(185, "mainland", "国产剧", 11)); //
zones.Add(new ZoneAttr(187, "overseas", "海外剧", 11)); //
zones.Add(new ZoneAttr(185, "mainland", "国产剧", 11)); //
zones.Add(new ZoneAttr(187, "overseas", "海外剧", 11)); //
}
}
+7 -7
View File
@@ -52,11 +52,11 @@
<Reference Include="Brotli.Core, Version=2.1.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Brotli.NET.2.1.1\lib\net45\Brotli.Core.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf, Version=3.20.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.20.1\lib\net45\Google.Protobuf.dll</HintPath>
<Reference Include="Google.Protobuf, Version=3.21.12.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.21.12\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<HintPath>..\packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
@@ -73,8 +73,8 @@
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
@@ -388,9 +388,9 @@
<Error Condition="!Exists('..\packages\Brotli.NET.2.1.1\build\Brotli.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Brotli.NET.2.1.1\build\Brotli.NET.targets'))" />
<Error Condition="!Exists('..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets'))" />
<Error Condition="!Exists('..\packages\WebPSharp.0.5.1\build\WebPSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\WebPSharp.0.5.1\build\WebPSharp.targets'))" />
<Error Condition="!Exists('..\packages\Google.Protobuf.Tools.3.20.1\build\Google.Protobuf.Tools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Google.Protobuf.Tools.3.20.1\build\Google.Protobuf.Tools.targets'))" />
<Error Condition="!Exists('..\packages\Google.Protobuf.Tools.3.21.12\build\Google.Protobuf.Tools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Google.Protobuf.Tools.3.21.12\build\Google.Protobuf.Tools.targets'))" />
</Target>
<Import Project="..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets')" />
<Import Project="..\packages\WebPSharp.0.5.1\build\WebPSharp.targets" Condition="Exists('..\packages\WebPSharp.0.5.1\build\WebPSharp.targets')" />
<Import Project="..\packages\Google.Protobuf.Tools.3.20.1\build\Google.Protobuf.Tools.targets" Condition="Exists('..\packages\Google.Protobuf.Tools.3.20.1\build\Google.Protobuf.Tools.targets')" />
<Import Project="..\packages\Google.Protobuf.Tools.3.21.12\build\Google.Protobuf.Tools.targets" Condition="Exists('..\packages\Google.Protobuf.Tools.3.21.12\build\Google.Protobuf.Tools.targets')" />
</Project>
@@ -27,7 +27,8 @@ namespace DownKyi.Core.Downloader
private bool _rangeAllowed;
private readonly HttpWebRequest _request;
private Action<HttpWebRequest> _requestConfigure = req => req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36";
#endregion
#endregion 属性
#region 公共属性
@@ -68,11 +69,13 @@ namespace DownKyi.Core.Downloader
{
try
{
return PartialDownloaderList.Where(t => t != null).Sum(t => t.TotalBytesRead);
lock (this)
{
return PartialDownloaderList.Where(t => t != null).Sum(t => t.TotalBytesRead);
}
}
catch (Exception e)
catch
{
Logging.LogManager.Error(e);
return 0;
}
}
@@ -91,7 +94,16 @@ namespace DownKyi.Core.Downloader
/// <summary>
/// 下载速度
/// </summary>
public float TotalSpeedInBytes => PartialDownloaderList.Sum(t => t.SpeedInBytes);
public float TotalSpeedInBytes
{
get
{
lock (this)
{
return PartialDownloaderList.Sum(t => t.SpeedInBytes);
}
}
}
/// <summary>
/// 下载块
@@ -103,7 +115,7 @@ namespace DownKyi.Core.Downloader
/// </summary>
public string FilePath { get; set; }
#endregion
#endregion 公共属性
#region 变量
@@ -124,7 +136,7 @@ namespace DownKyi.Core.Downloader
private readonly AsyncOperation _aop;
#endregion
#endregion 变量
#region 下载管理器
@@ -166,7 +178,7 @@ namespace DownKyi.Core.Downloader
{
}
#endregion
#endregion 下载管理器
#region 事件
@@ -181,16 +193,16 @@ namespace DownKyi.Core.Downloader
return;
}
PartialDownloaderList.Sort((x, y) => y.RemainingBytes - x.RemainingBytes);
int rem = PartialDownloaderList[0].RemainingBytes;
PartialDownloaderList.Sort((x, y) => (int)(y.RemainingBytes - x.RemainingBytes));
var rem = PartialDownloaderList[0].RemainingBytes;
if (rem < 50 * 1024)
{
WaitOrResumeAll(PartialDownloaderList, false);
return;
}
int from = PartialDownloaderList[0].CurrentPosition + rem / 2;
int to = PartialDownloaderList[0].To;
var from = PartialDownloaderList[0].CurrentPosition + rem / 2;
var to = PartialDownloaderList[0].To;
if (from > to)
{
WaitOrResumeAll(PartialDownloaderList, false);
@@ -202,16 +214,19 @@ namespace DownKyi.Core.Downloader
var temp = new PartialDownloader(_url, TempFileDirectory, Guid.NewGuid().ToString(), from, to, true);
temp.DownloadPartCompleted += temp_DownloadPartCompleted;
temp.DownloadPartProgressChanged += temp_DownloadPartProgressChanged;
PartialDownloaderList.Add(temp);
lock (this)
{
PartialDownloaderList.Add(temp);
}
temp.Start(_requestConfigure);
}
void temp_DownloadPartProgressChanged(object sender, EventArgs e)
private void temp_DownloadPartProgressChanged(object sender, EventArgs e)
{
UpdateProgress();
}
void UpdateProgress()
private void UpdateProgress()
{
int pr = (int)(TotalBytesReceived * 1d / Size * 100);
if (TotalProgress != pr)
@@ -224,11 +239,11 @@ namespace DownKyi.Core.Downloader
}
}
#endregion
#endregion 事件
#region 方法
void CreateFirstPartitions()
private void CreateFirstPartitions()
{
Size = GetContentLength(ref _rangeAllowed, ref _url);
int maximumPart = (int)(Size / (25 * 1024));
@@ -247,17 +262,21 @@ namespace DownKyi.Core.Downloader
var temp = CreateNew(i, NumberOfParts, Size);
temp.DownloadPartProgressChanged += temp_DownloadPartProgressChanged;
temp.DownloadPartCompleted += temp_DownloadPartCompleted;
PartialDownloaderList.Add(temp);
lock (this)
{
PartialDownloaderList.Add(temp);
}
temp.Start(_requestConfigure);
}
}
void MergeParts()
private void MergeParts()
{
var mergeOrderedList = PartialDownloaderList.OrderBy(x => x.From);
var dir = new FileInfo(FilePath).DirectoryName;
Directory.CreateDirectory(dir);
using (var fs = File.OpenWrite(FilePath))
{
long totalBytesWrite = 0;
@@ -298,12 +317,12 @@ namespace DownKyi.Core.Downloader
}
}
PartialDownloader CreateNew(int order, int parts, long contentLength)
private PartialDownloader CreateNew(int order, int parts, long contentLength)
{
int division = (int)contentLength / parts;
int remaining = (int)contentLength % parts;
int start = division * order;
int end = start + division - 1;
var division = contentLength / parts;
var remaining = contentLength % parts;
var start = division * order;
var end = start + division - 1;
end += order == parts - 1 ? remaining : 0;
return new PartialDownloader(_url, TempFileDirectory, Guid.NewGuid().ToString("N"), start, end, true);
}
@@ -315,15 +334,15 @@ namespace DownKyi.Core.Downloader
/// <param name="wait"></param>
public static void WaitOrResumeAll(List<PartialDownloader> list, bool wait)
{
foreach (var item in list)
for (var index = 0; index < list.Count; index++)
{
if (wait)
{
item.Wait();
list[index].Wait();
}
else
{
item.ResumeAfterWait();
list[index].ResumeAfterWait();
}
}
}
@@ -349,23 +368,21 @@ namespace DownKyi.Core.Downloader
_request.ServicePoint.ConnectionLimit = 4;
_requestConfigure(_request);
long ctl;
using (var resp = _request.GetResponse() as HttpWebResponse)
{
redirectedUrl = resp.ResponseUri.OriginalString;
ctl = resp.ContentLength;
var ctl = resp.ContentLength;
rangeAllowed = resp.Headers.AllKeys.Select((v, i) => new
{
HeaderName = v,
HeaderValue = resp.Headers[i]
}).Any(k => k.HeaderName.ToLower().Contains("range") && k.HeaderValue.ToLower().Contains("byte"));
_request.Abort();
return ctl;
}
return ctl;
}
#endregion
#endregion 方法
#region 公共方法
@@ -374,9 +391,12 @@ namespace DownKyi.Core.Downloader
/// </summary>
public void Pause()
{
foreach (var t in PartialDownloaderList.Where(t => !t.Completed))
lock (this)
{
t.Stop();
foreach (var t in PartialDownloaderList.Where(t => !t.Completed))
{
t.Stop();
}
}
Thread.Sleep(200);
@@ -385,34 +405,10 @@ namespace DownKyi.Core.Downloader
/// <summary>
/// 开始下载
/// </summary>
public void StartAsync()
{
//Task th = new Task(CreateFirstPartitions);
//th.Start();
StartAsync(false);
}
/// <summary>
/// 开始下载
/// </summary>
/// <param name="isWait"></param>
public void StartAsync(bool isWait)
public void Start()
{
Task th = new Task(CreateFirstPartitions);
th.Start();
if (isWait)
{
th.Wait();
}
}
/// <summary>
/// 开始下载
/// </summary>
public void Start()
{
CreateFirstPartitions();
}
/// <summary>
@@ -425,8 +421,8 @@ namespace DownKyi.Core.Downloader
{
if (PartialDownloaderList[i].Stopped)
{
int from = PartialDownloaderList[i].CurrentPosition + 1;
int to = PartialDownloaderList[i].To;
var from = PartialDownloaderList[i].CurrentPosition + 1;
var to = PartialDownloaderList[i].To;
if (from > to)
{
continue;
@@ -435,13 +431,16 @@ namespace DownKyi.Core.Downloader
var temp = new PartialDownloader(_url, TempFileDirectory, Guid.NewGuid().ToString(), from, to, _rangeAllowed);
temp.DownloadPartProgressChanged += temp_DownloadPartProgressChanged;
temp.DownloadPartCompleted += temp_DownloadPartCompleted;
PartialDownloaderList.Add(temp);
lock (this)
{
PartialDownloaderList.Add(temp);
}
PartialDownloaderList[i].To = PartialDownloaderList[i].CurrentPosition;
temp.Start(_requestConfigure);
}
}
}
#endregion
#endregion 公共方法
}
}
@@ -29,11 +29,11 @@ namespace DownKyi.Core.Downloader
public event EventHandler DownloadPartStopped;
private readonly AsyncOperation _aop = AsyncOperationManager.CreateOperation(null);
readonly int[] _lastSpeeds;
int _counter;
private readonly int[] _lastSpeeds;
private long _counter;
private long _to;
private long _totalBytesRead;
private bool _wait;
private int _to;
private int _totalBytesRead;
/// <summary>
/// 下载已停止
@@ -83,7 +83,7 @@ namespace DownKyi.Core.Downloader
/// <summary>
/// to
/// </summary>
public int To
public long To
{
get => _to;
set
@@ -96,17 +96,17 @@ namespace DownKyi.Core.Downloader
/// <summary>
/// from
/// </summary>
public int From { get; }
public long From { get; }
/// <summary>
/// 当前位置
/// </summary>
public int CurrentPosition => From + _totalBytesRead - 1;
public long CurrentPosition => From + _totalBytesRead - 1;
/// <summary>
/// 剩余字节数
/// </summary>
public int RemainingBytes => (int)(ContentLength - _totalBytesRead);
public long RemainingBytes => ContentLength - _totalBytesRead;
/// <summary>
/// 完整路径
@@ -139,7 +139,7 @@ namespace DownKyi.Core.Downloader
/// <param name="from"></param>
/// <param name="to"></param>
/// <param name="rangeAllowed"></param>
public PartialDownloader(string url, string dir, string fileGuid, int from, int to, bool rangeAllowed)
public PartialDownloader(string url, string dir, string fileGuid, long from, long to, bool rangeAllowed)
{
From = from;
_to = to;
@@ -150,7 +150,7 @@ namespace DownKyi.Core.Downloader
_lastSpeeds = new int[10];
}
void DownloadProcedure(Action<HttpWebRequest> config)
private void DownloadProcedure(Action<HttpWebRequest> config)
{
using (var file = new FileStream(FullPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete))
{
@@ -163,6 +163,7 @@ namespace DownKyi.Core.Downloader
req.ServicePoint.ConnectionLimit += 1;
req.ServicePoint.Expect100Continue = true;
req.ProtocolVersion = HttpVersion.Version11;
req.Proxy = WebRequest.GetSystemWebProxy();
config(req);
if (RangeAllowed)
{
@@ -265,4 +266,4 @@ namespace DownKyi.Core.Downloader
_wait = false;
}
}
}
}
+9 -2
View File
@@ -15,7 +15,7 @@ namespace DownKyi.Core.Logging
/// </summary>
public class LogManager
{
static readonly ConcurrentQueue<Tuple<string, string>> LogQueue = new ConcurrentQueue<Tuple<string, string>>();
private static readonly ConcurrentQueue<Tuple<string, string>> LogQueue = new ConcurrentQueue<Tuple<string, string>>();
/// <summary>
/// 自定义事件
@@ -63,14 +63,21 @@ namespace DownKyi.Core.Logging
private static AutoResetEvent Pause => new AutoResetEvent(false);
private static string logDirectory;
/// <summary>
/// 日志存放目录,默认日志放在当前应用程序运行目录下的logs文件夹中
/// </summary>
public static string LogDirectory
{
get => Storage.Constant.Logs; // Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs");
get => logDirectory ?? (Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory).Any(s => s.Contains("Web.config")) ? AppDomain.CurrentDomain.BaseDirectory + @"App_Data\Logs\" : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs"));
set
{
//自定义目录
if (!Directory.Exists(value))
{
Directory.CreateDirectory(value);
}
logDirectory = value;
}
}
+3 -3
View File
@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("DownKyi")]
[assembly: AssemblyProduct("DownKyi.Core")]
[assembly: AssemblyCopyright("Copyright © Downkyi 2020-2022")]
[assembly: AssemblyCopyright("Copyright © Downkyi 2020-2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.1.4.0")]
[assembly: AssemblyFileVersion("2.1.4.0")]
[assembly: AssemblyVersion("2.1.7.0")]
[assembly: AssemblyFileVersion("2.1.7.0")]
@@ -10,6 +10,7 @@ namespace DownKyi.Core.Settings.Models
public AllowStatus IsLiftingOfRegion { get; set; } = AllowStatus.NONE;
public AllowStatus UseSSL { get; set; } = AllowStatus.NONE;
public string UserAgent { get; set; } = string.Empty;
public Downloader Downloader { get; set; } = Downloader.NOT_SET;
public int MaxCurrentDownloads { get; set; } = -1;
@@ -10,6 +10,9 @@ namespace DownKyi.Core.Settings
// 启用https
private readonly AllowStatus useSSL = AllowStatus.YES;
// UserAgent
private readonly string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36";
// 下载器
private readonly Downloader downloader = Downloader.ARIA;
@@ -21,7 +24,7 @@ namespace DownKyi.Core.Settings
// HttpProxy代理
private readonly AllowStatus isHttpProxy = AllowStatus.NO;
private readonly string httpProxy = "";
private readonly string httpProxy = string.Empty;
private readonly int httpProxyListenPort = 0;
// Aria服务器token
@@ -50,7 +53,7 @@ namespace DownKyi.Core.Settings
// Aria HttpProxy代理
private readonly AllowStatus isAriaHttpProxy = AllowStatus.NO;
private readonly string ariaHttpProxy = "";
private readonly string ariaHttpProxy = string.Empty;
private readonly int ariaHttpProxyListenPort = 0;
/// <summary>
@@ -107,6 +110,33 @@ namespace DownKyi.Core.Settings
return SetSettings();
}
/// <summary>
/// 获取UserAgent
/// </summary>
/// <returns></returns>
public string GetUserAgent()
{
appSettings = GetSettings();
if (appSettings.Network.UserAgent == string.Empty)
{
// 第一次获取,先设置默认值
SetUserAgent(userAgent);
return userAgent;
}
return appSettings.Network.UserAgent;
}
/// <summary>
/// 设置UserAgent
/// </summary>
/// <param name="userAgent"></param>
/// <returns></returns>
public bool SetUserAgent(string userAgent)
{
appSettings.Network.UserAgent = userAgent;
return SetSettings();
}
/// <summary>
/// 获取下载器
/// </summary>
+16 -1
View File
@@ -199,7 +199,22 @@ namespace DownKyi.Core.Utils
destName = Regex.Replace(destName, @"\p{C}+", string.Empty);
// 移除前导和尾部的空白字符、dot符
return destName.Trim('.').Trim();
int i, j;
for (i = 0; i < destName.Length; i++)
{
if (destName[i] != ' ' && destName[i] != '.')
{
break;
}
}
for (j = destName.Length - 1; j >= 0; j--)
{
if (destName[j] != ' ' && destName[j] != '.')
{
break;
}
}
return destName.Substring(i, j - i + 1);
}
}
+4
View File
@@ -6,6 +6,10 @@
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+4 -4
View File
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Brotli.NET" version="2.1.1" targetFramework="net472" />
<package id="Google.Protobuf" version="3.20.1" targetFramework="net472" />
<package id="Google.Protobuf.Tools" version="3.20.1" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" />
<package id="Google.Protobuf" version="3.21.12" targetFramework="net472" />
<package id="Google.Protobuf.Tools" version="3.21.12" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.2" targetFramework="net472" />
<package id="QRCoder" version="1.4.3" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="System.Data.SQLite.Core" version="1.0.112.2" targetFramework="net472" />
<package id="System.Memory" version="4.5.4" targetFramework="net472" />
<package id="System.Memory" version="4.5.5" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net472" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net472" />
+13 -7
View File
@@ -4,16 +4,20 @@ using DownKyi.Utils;
using DownKyi.ViewModels;
using DownKyi.ViewModels.Dialogs;
using DownKyi.ViewModels.DownloadManager;
using DownKyi.ViewModels.Friends;
using DownKyi.ViewModels.Settings;
using DownKyi.ViewModels.Toolbox;
using DownKyi.ViewModels.UserSpace;
using DownKyi.Views;
using DownKyi.Views.Dialogs;
using DownKyi.Views.DownloadManager;
using DownKyi.Views.Friends;
using DownKyi.Views.Settings;
using DownKyi.Views.Toolbox;
using DownKyi.Views.UserSpace;
using Prism.DryIoc;
using Prism.Ioc;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -127,19 +131,16 @@ namespace DownKyi
case Downloader.NOT_SET:
break;
case Downloader.BUILT_IN:
downloadService = new BuiltinDownloadService(DownloadingList, DownloadedList);
downloadService = new BuiltinDownloadService(DownloadingList, DownloadedList, (IDialogService)Container.GetContainer().GetService(typeof(IDialogService)));
break;
case Downloader.ARIA:
downloadService = new AriaDownloadService(DownloadingList, DownloadedList);
downloadService = new AriaDownloadService(DownloadingList, DownloadedList, (IDialogService)Container.GetContainer().GetService(typeof(IDialogService)));
break;
case Downloader.CUSTOM_ARIA:
downloadService = new CustomAriaDownloadService(DownloadingList, DownloadedList);
downloadService = new CustomAriaDownloadService(DownloadingList, DownloadedList, (IDialogService)Container.GetContainer().GetService(typeof(IDialogService)));
break;
}
if (downloadService != null)
{
downloadService.Start();
}
downloadService?.Start();
return Container.Resolve<MainWindow>();
}
@@ -184,6 +185,7 @@ namespace DownKyi
containerRegistry.RegisterForNavigation<ViewPublication>(ViewPublicationViewModel.Tag);
containerRegistry.RegisterForNavigation<Views.ViewChannel>(ViewModels.ViewChannelViewModel.Tag);
containerRegistry.RegisterForNavigation<Views.ViewSeasonsSeries>(ViewModels.ViewSeasonsSeriesViewModel.Tag);
containerRegistry.RegisterForNavigation<ViewFriends>(ViewFriendsViewModel.Tag);
containerRegistry.RegisterForNavigation<ViewMySpace>(ViewMySpaceViewModel.Tag);
containerRegistry.RegisterForNavigation<ViewMyFavorites>(ViewMyFavoritesViewModel.Tag);
@@ -195,6 +197,10 @@ namespace DownKyi
containerRegistry.RegisterForNavigation<ViewDownloading>(ViewDownloadingViewModel.Tag);
containerRegistry.RegisterForNavigation<ViewDownloadFinished>(ViewDownloadFinishedViewModel.Tag);
// Friend
containerRegistry.RegisterForNavigation<ViewFollowing>(ViewFollowingViewModel.Tag);
containerRegistry.RegisterForNavigation<ViewFollower>(ViewFollowerViewModel.Tag);
// settings pages
containerRegistry.RegisterForNavigation<ViewBasic>(ViewBasicViewModel.Tag);
containerRegistry.RegisterForNavigation<ViewNetwork>(ViewNetworkViewModel.Tag);
+7 -1
View File
@@ -72,7 +72,7 @@
<Setter Property="Background" Value="#FFFFFFFF" />
<Setter Property="BorderBrush" Value="#FFD7DDE4" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Width" Value="30" />
<Setter Property="MinWidth" Value="30" />
<Setter Property="Height" Value="30" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
@@ -136,6 +136,7 @@
Style="{StaticResource pagerButton}"
Visibility="{Binding FirstVisibility}">
<TextBlock
Padding="10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
@@ -174,6 +175,7 @@
Style="{StaticResource pagerButton}"
Visibility="{Binding PreviousSecondVisibility}">
<TextBlock
Padding="10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
@@ -200,6 +202,7 @@
Style="{StaticResource pagerButton}"
Visibility="{Binding PreviousFirstVisibility}">
<TextBlock
Padding="10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
@@ -239,6 +242,7 @@
Style="{StaticResource pagerButton}"
Visibility="{Binding NextFirstVisibility}">
<TextBlock
Padding="10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
@@ -265,6 +269,7 @@
Style="{StaticResource pagerButton}"
Visibility="{Binding NextSecondVisibility}">
<TextBlock
Padding="10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
@@ -303,6 +308,7 @@
Style="{StaticResource pagerButton}"
Visibility="{Binding LastVisibility}">
<TextBlock
Padding="10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
@@ -60,8 +60,9 @@ namespace DownKyi.CustomControl
}
set
{
if (value < Current || value < 1)
if (value < Current || value < 0)
{
Visibility = Visibility.Hidden;
//throw new Exception("数值不在允许的范围内。");
System.Console.WriteLine(value.ToString());
}
@@ -69,7 +70,7 @@ namespace DownKyi.CustomControl
{
count = value;
if (count == 1) { Visibility = Visibility.Hidden; }
if (count <= 1) { Visibility = Visibility.Hidden; }
else { Visibility = Visibility.Visible; }
OnCountChanged(count);
+33
View File
@@ -76,6 +76,7 @@
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
@@ -121,12 +122,15 @@
<Compile Include="Services\Download\BuiltinDownloadService.cs" />
<Compile Include="Services\Download\DownloadStorageService.cs" />
<Compile Include="Services\SearchService.cs" />
<Compile Include="ViewModels\Friends\ViewFollowerViewModel.cs" />
<Compile Include="ViewModels\Friends\ViewFollowingViewModel.cs" />
<Compile Include="Utils\WindowAdaptation.cs" />
<Compile Include="ViewModels\Dialogs\ViewAlertDialogViewModel.cs" />
<Compile Include="ViewModels\PageViewModels\BangumiFollowMedia.cs" />
<Compile Include="ViewModels\PageViewModels\Favorites.cs" />
<Compile Include="ViewModels\PageViewModels\FavoritesMedia.cs" />
<Compile Include="ViewModels\PageViewModels\ChannelMedia.cs" />
<Compile Include="ViewModels\PageViewModels\FriendInfo.cs" />
<Compile Include="ViewModels\PageViewModels\HistoryMedia.cs" />
<Compile Include="ViewModels\PageViewModels\PublicationMedia.cs" />
<Compile Include="ViewModels\PageViewModels\SpaceItem.cs" />
@@ -177,6 +181,7 @@
<Compile Include="ViewModels\ViewChannelViewModel.cs" />
<Compile Include="ViewModels\ViewDownloadManagerViewModel.cs" />
<Compile Include="ViewModels\Toolbox\ViewExtractMediaViewModel.cs" />
<Compile Include="ViewModels\ViewFriendsViewModel.cs" />
<Compile Include="ViewModels\ViewIndexViewModel.cs" />
<Compile Include="ViewModels\ViewLoginViewModel.cs" />
<Compile Include="ViewModels\Settings\ViewNetworkViewModel.cs" />
@@ -208,6 +213,12 @@
<Compile Include="Views\DownloadManager\ViewDownloading.xaml.cs">
<DependentUpon>ViewDownloading.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Friends\ViewFollower.xaml.cs">
<DependentUpon>ViewFollower.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Friends\ViewFollowing.xaml.cs">
<DependentUpon>ViewFollowing.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Settings\ViewAbout.xaml.cs">
<DependentUpon>ViewAbout.xaml</DependentUpon>
</Compile>
@@ -253,6 +264,9 @@
<Compile Include="Views\ViewDownloadManager.xaml.cs">
<DependentUpon>ViewDownloadManager.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ViewFriends.xaml.cs">
<DependentUpon>ViewFriends.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ViewIndex.xaml.cs">
<DependentUpon>ViewIndex.xaml</DependentUpon>
</Compile>
@@ -380,6 +394,14 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Friends\ViewFollower.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Friends\ViewFollowing.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -456,6 +478,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ViewFriends.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ViewIndex.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -535,6 +561,9 @@
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json">
<Version>13.0.2</Version>
</PackageReference>
<PackageReference Include="Prism.DryIoc" Version="8.1.97" />
<PackageReference Include="System.Data.SQLite.Core">
<Version>1.0.112.2</Version>
@@ -547,6 +576,10 @@
<Resource Include="Resources\default_header.jpg" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Brotli.Core\Brotli.Core.csproj">
<Project>{3107CD63-E257-455E-AE81-1FD3582B067A}</Project>
<Name>Brotli.Core</Name>
</ProjectReference>
<ProjectReference Include="..\DownKyi.Core\DownKyi.Core.csproj">
<Project>{4fde0364-f65b-4812-bfe8-34e886624fbd}</Project>
<Name>DownKyi.Core</Name>
+14
View File
@@ -97,6 +97,17 @@
<system:String x:Key="DownloadAllPublication">下载全部</system:String>
<system:String x:Key="PublicationWait">请稍等,马上就好~</system:String>
<!-- Friend -->
<system:String x:Key="Friend">好友</system:String>
<system:String x:Key="FriendFollowing">关注</system:String>
<system:String x:Key="FriendFollower">粉丝</system:String>
<system:String x:Key="FollowingWait">请稍等,马上就好~</system:String>
<system:String x:Key="FollowerWait">请稍等,马上就好~</system:String>
<system:String x:Key="AllFollowing">全部关注</system:String>
<system:String x:Key="WhisperFollowing">悄悄关注</system:String>
<!-- VideoDetail -->
<system:String x:Key="CopyCover">复制封面图片</system:String>
<system:String x:Key="CopyCoverUrl">复制封面URL</system:String>
@@ -185,6 +196,7 @@
<system:String x:Key="Network">网络</system:String>
<system:String x:Key="UseSSL">启用https(若下载器提示SSL错误,则关闭此项)</system:String>
<system:String x:Key="UserAgent">UserAgent:</system:String>
<system:String x:Key="SelectDownloader">选择下载器(重启生效):</system:String>
<system:String x:Key="BuiltinDownloader">内建下载器(测试)</system:String>
<system:String x:Key="Aria2cDownloader">Aria2下载器</system:String>
@@ -314,6 +326,8 @@
<system:String x:Key="ConfirmDelete">您确定要删除吗?</system:String>
<system:String x:Key="SelectDirectory">请选择文件夹</system:String>
<system:String x:Key="DirectoryError">路径错误!</system:String>
<!-- ViewDownloadSetter -->
<system:String x:Key="DownloadSetter">下载设置</system:String>
<system:String x:Key="Location">位置:</system:String>
+42 -4
View File
@@ -1,15 +1,53 @@
namespace DownKyi.Models
using System;
using System.Text.RegularExpressions;
namespace DownKyi.Models
{
public class AppInfo
{
public string Name { get; } = "哔哩下载姬";
public int VersionCode { get; } = 511;
public int VersionCode { get; }
public string VersionName { get; }
const int a = 1;
const int b = 5;
const int c = 7;
public AppInfo()
{
VersionCode = a * 10000 + b * 100 + c;
#if DEBUG
public string VersionName { get; } = "1.5.4 Debug";
VersionName = $"{a}.{b}.{c}-debug";
#else
public string VersionName { get; } = "1.5.4";
VersionName = $"{a}.{b}.{c}";
#endif
}
public static int VersionNameToCode(string versionName)
{
int code = 0;
var isMatch = Regex.IsMatch(versionName, @"^v?([1-9]\d|\d).([1-9]\d|\d).([1-9]\d|\d)$");
if (!isMatch)
{
return 0;
}
string pattern = @"([1-9]\d|\d)";
var m = Regex.Matches(versionName, pattern);
if (m.Count == 3)
{
int i = 2;
foreach (var item in m)
{
code += int.Parse(item.ToString()) * (int)Math.Pow(100, i);
i--;
}
}
return code;
}
}
}
+3 -3
View File
@@ -12,7 +12,7 @@ using System.Windows;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("DownKyi")]
[assembly: AssemblyProduct("DownKyi")]
[assembly: AssemblyCopyright("Copyright © Downkyi 2020-2022")]
[assembly: AssemblyCopyright("Copyright © Downkyi 2020-2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -51,5 +51,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.5.4.0")]
[assembly: AssemblyFileVersion("1.5.4.0")]
[assembly: AssemblyVersion("1.5.7.0")]
[assembly: AssemblyFileVersion("1.5.7.0")]
+1 -1
View File
@@ -50,7 +50,7 @@ namespace DownKyi.Services
return ShowMessage(image, title, message);
}
private ButtonResult ShowMessage(VectorImage image, string type, string message)
public ButtonResult ShowMessage(VectorImage image, string type, string message)
{
ButtonResult result = ButtonResult.None;
if (dialogService == null)
@@ -260,7 +260,7 @@ namespace DownKyi.Services.Download
}
if (isDownloading) { continue; }
// 如果存在下载完成列表,弹出选择框是否再次下载
// TODO 如果存在下载完成列表,弹出选择框是否再次下载
bool isDownloaded = false;
foreach (DownloadedItem item in App.DownloadedList)
{
@@ -304,14 +304,14 @@ namespace DownKyi.Services.Download
// 文件路径
List<FileNamePart> fileNameParts = SettingsManager.GetInstance().GetFileNameParts();
FileName fileName = FileName.Builder(fileNameParts)
FileName fileName = FileName.Builder(fileNameParts)
.SetSection(Format.FormatFileName(sectionName))
.SetMainTitle(Format.FormatFileName(videoInfoView.Title))
.SetPageTitle(Format.FormatFileName(page.Name))
.SetVideoZone(videoInfoView.VideoZone.Split('>')[0])
.SetAudioQuality(page.AudioQualityFormat)
.SetVideoQuality(page.VideoQuality == null ? "" : page.VideoQuality.QualityFormat)
.SetVideoCodec(page.VideoQuality == null ? "" : page.VideoQuality.SelectedVideoCodec.Contains("AVC") ? "AVC" : page.VideoQuality.SelectedVideoCodec.Contains("HEVC") ? "HEVC" : page.VideoQuality.SelectedVideoCodec.Contains("Dolby") ? "Dolby Vision" : "")
.SetVideoCodec(page.VideoQuality == null ? "" : page.VideoQuality.SelectedVideoCodec.Contains("AVC") ? "AVC" : page.VideoQuality.SelectedVideoCodec.Contains("HEVC") ? "HEVC" : page.VideoQuality.SelectedVideoCodec.Contains("Dolby") ? "Dolby Vision" : page.VideoQuality.SelectedVideoCodec.Contains("AV1") ? "AV1" : "")
.SetVideoPublishTime(page.PublishTime)
.SetAvid(page.Avid)
.SetBvid(page.Bvid)
@@ -7,9 +7,11 @@ using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Core.Logging;
using DownKyi.Core.Settings;
using DownKyi.Core.Utils;
using DownKyi.Images;
using DownKyi.Models;
using DownKyi.Utils;
using DownKyi.ViewModels.DownloadManager;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -24,7 +26,11 @@ namespace DownKyi.Services.Download
/// </summary>
public class AriaDownloadService : DownloadService, IDownloadService
{
public AriaDownloadService(ObservableCollection<DownloadingItem> downloadingList, ObservableCollection<DownloadedItem> downloadedList) : base(downloadingList, downloadedList)
public AriaDownloadService(
ObservableCollection<DownloadingItem> downloadingList,
ObservableCollection<DownloadedItem> downloadedList,
IDialogService dialogService) :
base(downloadingList, downloadedList, dialogService)
{
Tag = "AriaDownloadService";
}
@@ -236,6 +242,8 @@ namespace DownKyi.Services.Download
AriaClient.SetToken();
// 设置aria host
AriaClient.SetHost();
// 设置aria listenPort
AriaClient.SetListenPort();
// 启动Aria服务器
StartAriaServer();
@@ -304,7 +312,7 @@ namespace DownKyi.Services.Download
$"Cookie: {LoginHelper.GetLoginInfoCookiesString()}",
$"Origin: https://www.bilibili.com",
$"Referer: https://www.bilibili.com",
$"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36"
$"User-Agent: {SettingsManager.GetInstance().GetUserAgent()}"
};
AriaConfig config = new AriaConfig()
@@ -325,8 +333,24 @@ namespace DownKyi.Services.Download
FileAllocation = SettingsManager.GetInstance().GetAriaFileAllocation(),
Headers = header
};
var task = await AriaServer.StartServerAsync(config);
string errorMessage = null;
var task = await AriaServer.StartServerAsync(config, new Action<string>((output) =>
{
errorMessage += output + "\n";
}));
if (task) { Console.WriteLine("Start ServerAsync Completed"); }
// 显示错误信息
if (errorMessage != null && errorMessage.Contains("ERROR"))
{
AlertService alertService = new AlertService(dialogService);
ButtonResult result = alertService.ShowMessage(SystemIcon.Instance().Error,
$"Aria2 {DictionaryResource.GetString("Error")}",
errorMessage);
return;
}
for (int i = 0; i < 10; i++)
{
var globOpt = await AriaClient.GetGlobalOptionAsync();
@@ -392,7 +416,7 @@ namespace DownKyi.Services.Download
Out = localFileName,
//Header = $"cookie: {LoginHelper.GetLoginInfoCookiesString()}\nreferer: https://www.bilibili.com",
//UseHead = "true",
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36",
UserAgent = SettingsManager.GetInstance().GetUserAgent(),
};
// 如果设置了代理,则增加HttpProxy
@@ -7,6 +7,7 @@ using DownKyi.Core.Utils;
using DownKyi.Models;
using DownKyi.Utils;
using DownKyi.ViewModels.DownloadManager;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -19,7 +20,10 @@ namespace DownKyi.Services.Download
{
public class BuiltinDownloadService : DownloadService, IDownloadService
{
public BuiltinDownloadService(ObservableCollection<DownloadingItem> downloadingList, ObservableCollection<DownloadedItem> downloadedList) : base(downloadingList, downloadedList)
public BuiltinDownloadService(ObservableCollection<DownloadingItem> downloadingList,
ObservableCollection<DownloadedItem> downloadedList,
IDialogService dialogService
) : base(downloadingList, downloadedList, dialogService)
{
Tag = "BuiltinDownloadService";
}
@@ -134,15 +138,25 @@ namespace DownKyi.Services.Download
}
// 开始下载
var downloadStatus = DownloadByBuiltin(downloading, urls, path, fileName);
if (downloadStatus)
try
{
downloading.Downloading.DownloadedFiles.Add(key);
downloading.Downloading.Gid = null;
return Path.Combine(path, fileName);
var downloadStatus = DownloadByBuiltin(downloading, urls, path, fileName);
if (downloadStatus)
{
downloading.Downloading.DownloadedFiles.Add(key);
downloading.Downloading.Gid = null;
return Path.Combine(path, fileName);
}
else
{
return nullMark;
}
}
else
catch (FileNotFoundException e)
{
Core.Utils.Debugging.Console.PrintLine("BuiltinDownloadService.DownloadVideo()发生异常: {0}", e);
LogManager.Error("BuiltinDownloadService.DownloadVideo()", e);
return nullMark;
}
}
@@ -291,7 +305,7 @@ namespace DownKyi.Services.Download
mtd.Configure(req =>
{
req.CookieContainer = LoginHelper.GetLoginInfoCookies();
req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36";
req.UserAgent = SettingsManager.GetInstance().GetUserAgent();
req.Referer = "https://www.bilibili.com";
req.Headers.Add("Origin", "https://www.bilibili.com");
@@ -356,7 +370,7 @@ namespace DownKyi.Services.Download
};
// 开始下载
mtd.StartAsync();
mtd.Start();
// 阻塞当前任务,监听暂停事件
while (!isComplete)
@@ -9,6 +9,7 @@ using DownKyi.Core.Utils;
using DownKyi.Models;
using DownKyi.Utils;
using DownKyi.ViewModels.DownloadManager;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -23,7 +24,10 @@ namespace DownKyi.Services.Download
/// </summary>
public class CustomAriaDownloadService : DownloadService, IDownloadService
{
public CustomAriaDownloadService(ObservableCollection<DownloadingItem> downloadingList, ObservableCollection<DownloadedItem> downloadedList) : base(downloadingList, downloadedList)
public CustomAriaDownloadService(ObservableCollection<DownloadingItem> downloadingList,
ObservableCollection<DownloadedItem> downloadedList,
IDialogService dialogService
) : base(downloadingList, downloadedList, dialogService)
{
Tag = "AriaDownloadService";
}
@@ -235,6 +239,8 @@ namespace DownKyi.Services.Download
AriaClient.SetToken(SettingsManager.GetInstance().GetAriaToken());
// 设置aria host
AriaClient.SetHost(SettingsManager.GetInstance().GetAriaHost());
// 设置aria listenPort
AriaClient.SetListenPort(SettingsManager.GetInstance().GetAriaListenPort());
// 启动基本服务
BaseStart();
@@ -345,7 +351,7 @@ namespace DownKyi.Services.Download
Out = localFileName,
//Header = $"cookie: {LoginHelper.GetLoginInfoCookiesString()}\nreferer: https://www.bilibili.com",
//UseHead = "true",
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36",
UserAgent = SettingsManager.GetInstance().GetUserAgent(),
};
//// 如果设置了代理,则增加HttpProxy
@@ -11,6 +11,7 @@ using DownKyi.Images;
using DownKyi.Models;
using DownKyi.Utils;
using DownKyi.ViewModels.DownloadManager;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -25,6 +26,8 @@ namespace DownKyi.Services.Download
{
protected string Tag = "DownloadService";
protected IDialogService dialogService;
protected ObservableCollection<DownloadingItem> downloadingList;
protected ObservableCollection<DownloadedItem> downloadedList;
@@ -41,10 +44,13 @@ namespace DownKyi.Services.Download
/// </summary>
/// <param name="downloading"></param>
/// <returns></returns>
public DownloadService(ObservableCollection<DownloadingItem> downloadingList, ObservableCollection<DownloadedItem> downloadedList)
public DownloadService(ObservableCollection<DownloadingItem> downloadingList,
ObservableCollection<DownloadedItem> downloadedList,
IDialogService dialogService)
{
this.downloadingList = downloadingList;
this.downloadedList = downloadedList;
this.dialogService = dialogService;
}
protected PlayUrlDashVideo BaseDownloadAudio(DownloadingItem downloading)
@@ -438,7 +444,20 @@ namespace DownKyi.Services.Download
// 路径不存在则创建
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
try
{
Directory.CreateDirectory(path);
}
catch (Exception e)
{
Core.Utils.Debugging.Console.PrintLine(Tag, e.ToString());
LogManager.Debug(Tag, e.Message);
AlertService alertService = new AlertService(dialogService);
ButtonResult result = alertService.ShowError($"{path}{DictionaryResource.GetString("DirectoryError")}");
return;
}
}
try
+27 -69
View File
@@ -89,40 +89,6 @@ namespace DownKyi.Services
}
}
/// <summary>
/// 设置音质
/// </summary>
/// <param name="playUrl"></param>
/// <param name="defaultAudioQuality"></param>
/// <returns></returns>
private static ObservableCollection<string> GetAudioQualityFormatList_old(PlayUrl playUrl, int defaultAudioQuality)
{
List<string> audioQualityFormatList = new List<string>();
if (playUrl.Dash.Audio == null)
{
return new ObservableCollection<string>();
}
foreach (PlayUrlDashVideo audio in playUrl.Dash.Audio)
{
// 音质id大于设置画质时,跳过
if (audio.Id > defaultAudioQuality) { continue; }
Quality audioQuality = Constant.GetAudioQualities().FirstOrDefault(t => { return t.Id == audio.Id; });
if (audioQuality != null)
{
ListHelper.AddUnique(audioQualityFormatList, audioQuality.Name);
}
}
audioQualityFormatList.Sort(new StringLogicalComparer<string>());
audioQualityFormatList.Reverse();
return new ObservableCollection<string>(audioQualityFormatList);
}
/// <summary>
/// 设置音质
/// </summary>
@@ -244,52 +210,44 @@ namespace DownKyi.Services
VideoQuality selectedVideoQuality = videoQualityList.FirstOrDefault(t => t.Quality == video.Id);
if (selectedVideoQuality == null) { continue; }
if (videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList.Count == 1)
{
// 当获取的视频没有设置的视频编码时,执行
videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].SelectedVideoCodec = videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList[0];
}
// 设置选中的视频编码
//switch (videoCodecs)
//{
// case VideoCodecs.AVC:
// if (videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList.Contains("H.264/AVC"))
// {
// videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].SelectedVideoCodec = "H.264/AVC";
// }
// break;
// case VideoCodecs.HEVC:
// if (videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList.Contains("H.265/HEVC"))
// {
// videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].SelectedVideoCodec = "H.265/HEVC";
// }
// break;
// case VideoCodecs.NONE:
// break;
// default:
// break;
//}
string videoCodecsName = codeIds.FirstOrDefault(t => t.Id == videoCodecs).Name;
if (videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList.Contains(videoCodecsName))
{
videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].SelectedVideoCodec = videoCodecsName;
}
else
{
// 当获取的视频没有设置的视频编码时
foreach (Quality codec in codeIds)
{
if (videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList.Contains(codec.Name))
{
videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].SelectedVideoCodec = codec.Name;
}
if (codec.Id == videoCodecs)
{
break;
}
}
// 若默认编码为AVC,但画质为杜比视界时,
// 上面的foreach不会选中HEVC编码,
// 而杜比视界只有HEVC编码,
// 因此这里再判断并设置一次
if (videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].SelectedVideoCodec == null &&
videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList.Count() > 0)
{
videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].SelectedVideoCodec =
videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList[0];
}
}
}
return videoQualityList;
}
/// <summary>
/// 根据输入的字符串判断是AVC还是HEVC
/// </summary>
/// <param name="origin"></param>
/// <returns></returns>
//internal static string GetVideoCodecName(string origin)
//{
// return origin.Contains("avc") ? "H.264/AVC" : origin.Contains("hev") ? "H.265/HEVC" : origin.Contains("dvh") || origin.Contains("hvc") ? "Dolby Vision" : "";
//}
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ namespace DownKyi.ViewModels
public class BaseViewModel : BindableBase, INavigationAware
{
protected readonly IEventAggregator eventAggregator;
protected readonly IDialogService dialogService;
protected IDialogService dialogService;
protected string ParentView = string.Empty;
public BaseViewModel(IEventAggregator eventAggregator)
@@ -1,6 +1,7 @@
using DownKyi.Images;
using Prism.Commands;
using Prism.Services.Dialogs;
using System.Windows;
namespace DownKyi.ViewModels.Dialogs
{
@@ -20,8 +21,23 @@ namespace DownKyi.ViewModels.Dialogs
private string message;
public string Message
{
get { return message; }
set { SetProperty(ref message, value); }
get => message;
set => SetProperty(ref message, value);
}
private Visibility aloneButton;
public Visibility AloneButton
{
get => aloneButton;
set => SetProperty(ref aloneButton, value);
}
private Visibility twoButton;
public Visibility TwoButton
{
get => twoButton;
set => SetProperty(ref twoButton, value);
}
#endregion
@@ -57,6 +73,17 @@ namespace DownKyi.ViewModels.Dialogs
Image = parameters.GetValue<VectorImage>("image");
Title = parameters.GetValue<string>("title");
Message = parameters.GetValue<string>("message");
if (Image == SystemIcon.Instance().Error)
{
AloneButton = Visibility.Visible;
TwoButton = Visibility.Collapsed;
}
else
{
AloneButton = Visibility.Collapsed;
TwoButton = Visibility.Visible;
}
}
#endregion
@@ -0,0 +1,239 @@
using DownKyi.Core.BiliApi.Users;
using DownKyi.Core.BiliApi.Users.Models;
using DownKyi.Core.Settings.Models;
using DownKyi.Core.Settings;
using DownKyi.Core.Storage;
using DownKyi.CustomControl;
using DownKyi.ViewModels.PageViewModels;
using Prism.Events;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
namespace DownKyi.ViewModels.Friends
{
public class ViewFollowerViewModel : BaseViewModel
{
public const string Tag = "PageFriendsFollower";
// mid
private long mid = -1;
// 每页数量,暂时在此写死,以后在设置中增加选项
private readonly int NumberInPage = 20;
public bool IsEnabled = true;
#region 页面属性申明
private string pageName = ViewFriendsViewModel.Tag;
public string PageName
{
get => pageName;
set => SetProperty(ref pageName, value);
}
private Visibility contentVisibility;
public Visibility ContentVisibility
{
get => contentVisibility;
set => SetProperty(ref contentVisibility, value);
}
private GifImage loading;
public GifImage Loading
{
get => loading;
set => SetProperty(ref loading, value);
}
private Visibility loadingVisibility;
public Visibility LoadingVisibility
{
get => loadingVisibility;
set => SetProperty(ref loadingVisibility, value);
}
private Visibility noDataVisibility;
public Visibility NoDataVisibility
{
get => noDataVisibility;
set => SetProperty(ref noDataVisibility, value);
}
private CustomPagerViewModel pager;
public CustomPagerViewModel Pager
{
get => pager;
set => SetProperty(ref pager, value);
}
private ObservableCollection<FriendInfo> contents;
public ObservableCollection<FriendInfo> Contents
{
get => contents;
set => SetProperty(ref contents, value);
}
#endregion
public ViewFollowerViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
{
#region 属性初始化
// 初始化loading gif
Loading = new GifImage(Properties.Resources.loading);
Loading.StartAnimate();
LoadingVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Collapsed;
Contents = new ObservableCollection<FriendInfo>();
#endregion
}
#region 命令申明
#endregion
private void LoadContent(List<RelationFollowInfo> contents)
{
ContentVisibility = Visibility.Visible;
LoadingVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Collapsed;
foreach (var item in contents)
{
StorageHeader storageHeader = new StorageHeader();
BitmapImage header = storageHeader.GetHeaderThumbnail(item.Mid, item.Name, item.Face, 64, 64);
App.PropertyChangeAsync(new Action(() =>
{
Contents.Add(new FriendInfo(eventAggregator) { Mid = item.Mid, Header = header, Name = item.Name, Sign = item.Sign });
}));
}
}
private async void UpdateContent(int current)
{
// 是否正在获取数据
// 在所有的退出分支中都需要设为true
IsEnabled = false;
Contents.Clear();
ContentVisibility = Visibility.Collapsed;
LoadingVisibility = Visibility.Visible;
NoDataVisibility = Visibility.Collapsed;
RelationFollow data = null;
List<RelationFollowInfo> contents = null;
await Task.Run(() =>
{
data = UserRelation.GetFollowers(mid, current, NumberInPage);
if (data != null && data.List != null && data.List.Count > 0)
{
contents = data.List;
}
if (contents == null) { return; }
LoadContent(contents);
});
if (data == null || contents == null)
{
ContentVisibility = Visibility.Collapsed;
LoadingVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Visible;
}
else
{
UserInfoSettings userInfo = SettingsManager.GetInstance().GetUserInfo();
if (userInfo != null && userInfo.Mid == mid)
{
Pager.Count = (int)Math.Ceiling((double)data.Total / NumberInPage);
}
else
{
int page = (int)Math.Ceiling((double)data.Total / NumberInPage);
if (page > 5)
{
Pager.Count = 5;
}
else
{
Pager.Count = page;
}
}
ContentVisibility = Visibility.Visible;
LoadingVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Collapsed;
}
IsEnabled = true;
}
private void OnCountChanged_Pager(int count) { }
private bool OnCurrentChanged_Pager(int old, int current)
{
if (!IsEnabled)
{
//Pager.Current = old;
return false;
}
UpdateContent(current);
return true;
}
/// <summary>
/// 初始化页面数据
/// </summary>
private void InitView()
{
ContentVisibility = Visibility.Collapsed;
LoadingVisibility = Visibility.Visible;
NoDataVisibility = Visibility.Collapsed;
Contents.Clear();
}
/// <summary>
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
{
base.OnNavigatedTo(navigationContext);
// 传入mid
long parameter = navigationContext.Parameters.GetValue<long>("mid");
if (parameter == 0)
{
return;
}
mid = parameter;
// 是否是从PageFriends的headerTable的item点击进入的
// true表示加载PageFriends后第一次进入此页面
// false表示从headerTable的item点击进入的
bool isFirst = navigationContext.Parameters.GetValue<bool>("isFirst");
if (isFirst)
{
InitView();
//UpdateContent(1);
// 页面选择
Pager = new CustomPagerViewModel(1, (int)Math.Ceiling((double)1 / NumberInPage));
Pager.CurrentChanged += OnCurrentChanged_Pager;
Pager.CountChanged += OnCountChanged_Pager;
Pager.Current = 1;
}
}
}
}
@@ -0,0 +1,415 @@
using DownKyi.Core.BiliApi.Users;
using DownKyi.Core.BiliApi.Users.Models;
using DownKyi.Core.Settings;
using DownKyi.Core.Settings.Models;
using DownKyi.Core.Storage;
using DownKyi.CustomControl;
using DownKyi.Utils;
using DownKyi.ViewModels.PageViewModels;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
namespace DownKyi.ViewModels.Friends
{
public class ViewFollowingViewModel : BaseViewModel
{
public const string Tag = "PageFriendsFollowing";
// mid
private long mid = -1;
// 每页数量,暂时在此写死,以后在设置中增加选项
private readonly int NumberInPage = 20;
#region 页面属性申明
private string pageName = ViewFriendsViewModel.Tag;
public string PageName
{
get => pageName;
set => SetProperty(ref pageName, value);
}
private Visibility contentVisibility;
public Visibility ContentVisibility
{
get => contentVisibility;
set => SetProperty(ref contentVisibility, value);
}
private Visibility innerContentVisibility;
public Visibility InnerContentVisibility
{
get => innerContentVisibility;
set => SetProperty(ref innerContentVisibility, value);
}
private GifImage loading;
public GifImage Loading
{
get => loading;
set => SetProperty(ref loading, value);
}
private Visibility loadingVisibility;
public Visibility LoadingVisibility
{
get => loadingVisibility;
set => SetProperty(ref loadingVisibility, value);
}
private Visibility noDataVisibility;
public Visibility NoDataVisibility
{
get => noDataVisibility;
set => SetProperty(ref noDataVisibility, value);
}
private GifImage contentLoading;
public GifImage ContentLoading
{
get => contentLoading;
set => SetProperty(ref contentLoading, value);
}
private Visibility contentLoadingVisibility;
public Visibility ContentLoadingVisibility
{
get => contentLoadingVisibility;
set => SetProperty(ref contentLoadingVisibility, value);
}
private Visibility contentNoDataVisibility;
public Visibility ContentNoDataVisibility
{
get => contentNoDataVisibility;
set => SetProperty(ref contentNoDataVisibility, value);
}
private ObservableCollection<TabHeader> tabHeaders;
public ObservableCollection<TabHeader> 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<FriendInfo> contents;
public ObservableCollection<FriendInfo> Contents
{
get => contents;
set => SetProperty(ref contents, value);
}
#endregion
public ViewFollowingViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
{
#region 属性初始化
// 初始化loading gif
Loading = new GifImage(Properties.Resources.loading);
Loading.StartAnimate();
LoadingVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Collapsed;
ContentLoading = new GifImage(Properties.Resources.loading);
ContentLoading.StartAnimate();
ContentLoadingVisibility = Visibility.Collapsed;
ContentNoDataVisibility = Visibility.Collapsed;
TabHeaders = new ObservableCollection<TabHeader>();
Contents = new ObservableCollection<FriendInfo>();
#endregion
}
#region 命令申明
// 左侧tab点击事件
private DelegateCommand<object> leftTabHeadersCommand;
public DelegateCommand<object> LeftTabHeadersCommand => leftTabHeadersCommand ?? (leftTabHeadersCommand = new DelegateCommand<object>(ExecuteLeftTabHeadersCommand, CanExecuteLeftTabHeadersCommand));
/// <summary>
/// 左侧tab点击事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteLeftTabHeadersCommand(object parameter)
{
if (!(parameter is TabHeader tabHeader)) { return; }
// 页面选择
Pager = new CustomPagerViewModel(1, (int)Math.Ceiling(double.Parse(tabHeader.SubTitle) / NumberInPage));
Pager.CurrentChanged += OnCurrentChanged_Pager;
Pager.CountChanged += OnCountChanged_Pager;
Pager.Current = 1;
}
/// <summary>
/// 左侧tab点击事件是否允许执行
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
private bool CanExecuteLeftTabHeadersCommand(object parameter)
{
return IsEnabled;
}
#endregion
/// <summary>
/// 初始化页面数据
/// </summary>
private void InitView()
{
ContentVisibility = Visibility.Collapsed;
InnerContentVisibility = Visibility.Collapsed;
LoadingVisibility = Visibility.Visible;
NoDataVisibility = Visibility.Collapsed;
ContentLoadingVisibility = Visibility.Collapsed;
ContentNoDataVisibility = Visibility.Collapsed;
TabHeaders.Clear();
Contents.Clear();
SelectTabId = -1;
}
/// <summary>
/// 初始化左侧列表
/// </summary>
private async void InitLeftTable()
{
TabHeaders.Clear();
UserInfoSettings userInfo = SettingsManager.GetInstance().GetUserInfo();
if (userInfo != null && userInfo.Mid == mid)
{
// 用户的关系状态数
UserRelationStat relationStat = null;
await Task.Run(() =>
{
relationStat = UserStatus.GetUserRelationStat(mid);
});
if (relationStat != null)
{
TabHeaders.Add(new TabHeader { Id = -1, Title = DictionaryResource.GetString("AllFollowing"), SubTitle = relationStat.Following.ToString() });
TabHeaders.Add(new TabHeader { Id = -2, Title = DictionaryResource.GetString("WhisperFollowing"), SubTitle = relationStat.Whisper.ToString() });
}
// 用户的关注分组
List<FollowingGroup> followingGroup = null;
await Task.Run(() =>
{
followingGroup = UserRelation.GetFollowingGroup();
});
if (followingGroup != null)
{
foreach (FollowingGroup tag in followingGroup)
{
TabHeaders.Add(new TabHeader { Id = tag.TagId, Title = tag.Name, SubTitle = tag.Count.ToString() });
}
}
}
else
{
// 用户的关系状态数
UserRelationStat relationStat = null;
await Task.Run(() =>
{
relationStat = UserStatus.GetUserRelationStat(mid);
});
if (relationStat != null)
{
TabHeaders.Add(new TabHeader { Id = -1, Title = DictionaryResource.GetString("AllFollowing"), SubTitle = relationStat.Following.ToString() });
}
}
ContentVisibility = Visibility.Visible;
LoadingVisibility = Visibility.Collapsed;
}
private void LoadContent(List<RelationFollowInfo> contents)
{
InnerContentVisibility = Visibility.Visible;
ContentLoadingVisibility = Visibility.Collapsed;
ContentNoDataVisibility = Visibility.Collapsed;
foreach (var item in contents)
{
StorageHeader storageHeader = new StorageHeader();
BitmapImage header = storageHeader.GetHeaderThumbnail(item.Mid, item.Name, item.Face, 64, 64);
App.PropertyChangeAsync(new Action(() =>
{
Contents.Add(new FriendInfo(eventAggregator) { Mid = item.Mid, Header = header, Name = item.Name, Sign = item.Sign });
}));
}
}
private async Task<bool> LoadAllFollowings(int pn, int ps)
{
List<RelationFollowInfo> contents = null;
await Task.Run(() =>
{
RelationFollow data = UserRelation.GetFollowings(mid, pn, ps);
if (data != null && data.List != null && data.List.Count > 0)
{
contents = data.List;
}
if (contents == null) { return; }
LoadContent(contents);
});
if (contents == null) { return false; }
return true;
}
private async Task<bool> LoadWhispers(int pn, int ps)
{
List<RelationFollowInfo> contents = null;
await Task.Run(() =>
{
contents = UserRelation.GetWhispers(pn, ps);
if (contents == null) { return; }
LoadContent(contents);
});
if (contents == null) { return false; }
return true;
}
private async Task<bool> LoadFollowingGroupContent(int tagId, int pn, int ps)
{
List<RelationFollowInfo> contents = null;
await Task.Run(() =>
{
contents = UserRelation.GetFollowingGroupContent(tagId, pn, ps);
if (contents == null) { return; }
LoadContent(contents);
});
if (contents == null) { return false; }
return true;
}
private async void UpdateContent(int current)
{
// 是否正在获取数据
// 在所有的退出分支中都需要设为true
IsEnabled = false;
Contents.Clear();
InnerContentVisibility = Visibility.Collapsed;
ContentLoadingVisibility = Visibility.Visible;
ContentNoDataVisibility = Visibility.Collapsed;
TabHeader tab = TabHeaders[SelectTabId];
bool isSucceed;
switch (tab.Id)
{
case -1:
isSucceed = await LoadAllFollowings(current, NumberInPage);
break;
case -2:
isSucceed = await LoadWhispers(current, NumberInPage);
break;
default:
isSucceed = await LoadFollowingGroupContent(tab.Id, current, NumberInPage);
break;
}
if (isSucceed)
{
InnerContentVisibility = Visibility.Visible;
ContentLoadingVisibility = Visibility.Collapsed;
ContentNoDataVisibility = Visibility.Collapsed;
}
else
{
InnerContentVisibility = Visibility.Collapsed;
ContentLoadingVisibility = Visibility.Collapsed;
ContentNoDataVisibility = Visibility.Visible;
}
IsEnabled = true;
}
private void OnCountChanged_Pager(int count) { }
private bool OnCurrentChanged_Pager(int old, int current)
{
if (!IsEnabled)
{
//Pager.Current = old;
return false;
}
UpdateContent(current);
return true;
}
/// <summary>
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
{
base.OnNavigatedTo(navigationContext);
// 传入mid
long parameter = navigationContext.Parameters.GetValue<long>("mid");
if (parameter == 0)
{
return;
}
mid = parameter;
// 是否是从PageFriends的headerTable的item点击进入的
// true表示加载PageFriends后第一次进入此页面
// false表示从headerTable的item点击进入的
bool isFirst = navigationContext.Parameters.GetValue<bool>("isFirst");
if (isFirst)
{
InitView();
// 初始化左侧列表
InitLeftTable();
// 进入页面时显示的设置项
SelectTabId = 0;
}
}
}
}
@@ -0,0 +1,65 @@
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 FriendInfo : BindableBase
{
protected readonly IEventAggregator eventAggregator;
public FriendInfo(IEventAggregator eventAggregator)
{
this.eventAggregator = eventAggregator;
}
public long Mid { get; set; }
#region 页面属性申明
private BitmapImage header;
public BitmapImage Header
{
get => header;
set => SetProperty(ref header, value);
}
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
private string sign;
public string Sign
{
get => sign;
set => SetProperty(ref sign, value);
}
#endregion
#region 命令申明
// 视频标题点击事件
private DelegateCommand<object> userCommand;
public DelegateCommand<object> UserCommand => userCommand ?? (userCommand = new DelegateCommand<object>(ExecuteUserCommand));
/// <summary>
/// 视频标题点击事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteUserCommand(object parameter)
{
if (!(parameter is string tag)) { return; }
NavigateToView.NavigationView(eventAggregator, ViewUserSpaceViewModel.Tag, tag, Mid);
}
#endregion
}
}
@@ -5,6 +5,13 @@ namespace DownKyi.ViewModels.PageViewModels
{
public class SpaceItem : BindableBase
{
private bool isEnabled;
public bool IsEnabled
{
get => isEnabled;
set => SetProperty(ref isEnabled, value);
}
private VectorImage image;
public VectorImage Image
{
@@ -5,6 +5,7 @@ using DownKyi.Utils;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using Prism.Services.Dialogs;
namespace DownKyi.ViewModels.Settings
{
@@ -46,7 +47,7 @@ namespace DownKyi.ViewModels.Settings
#endregion
public ViewAboutViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
public ViewAboutViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator, dialogService)
{
#region 属性初始化
@@ -60,7 +61,7 @@ namespace DownKyi.ViewModels.Settings
}
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
@@ -95,7 +95,7 @@ namespace DownKyi.ViewModels.Settings
}
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
@@ -115,7 +115,7 @@ namespace DownKyi.ViewModels.Settings
}
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
@@ -27,6 +27,13 @@ namespace DownKyi.ViewModels.Settings
set => SetProperty(ref useSSL, value);
}
private string userAgent;
public string UserAgent
{
get => userAgent;
set => SetProperty(ref userAgent, value);
}
private bool builtin;
public bool Builtin
{
@@ -268,6 +275,9 @@ namespace DownKyi.ViewModels.Settings
AllowStatus useSSL = SettingsManager.GetInstance().UseSSL();
UseSSL = useSSL == AllowStatus.YES;
// UserAgent
UserAgent = SettingsManager.GetInstance().GetUserAgent();
// 选择下载器
var downloader = SettingsManager.GetInstance().GetDownloader();
switch (downloader)
@@ -360,6 +370,19 @@ namespace DownKyi.ViewModels.Settings
PublishTip(isSucceed);
}
// 设置UserAgent事件
private DelegateCommand userAgentCommand;
public DelegateCommand UserAgentCommand => userAgentCommand ?? (userAgentCommand = new DelegateCommand(ExecuteUserAgentCommand));
/// <summary>
/// 设置UserAgent事件
/// </summary>
private void ExecuteUserAgentCommand()
{
bool isSucceed = SettingsManager.GetInstance().SetUserAgent(UserAgent);
PublishTip(isSucceed);
}
// 下载器选择事件
private DelegateCommand<string> selectDownloaderCommand;
public DelegateCommand<string> SelectDownloaderCommand => selectDownloaderCommand ?? (selectDownloaderCommand = new DelegateCommand<string>(ExecuteSelectDownloaderCommand));
@@ -246,7 +246,7 @@ namespace DownKyi.ViewModels.Settings
}
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
@@ -4,6 +4,8 @@ namespace DownKyi.ViewModels.UserSpace
{
public class TabRightBanner : BindableBase
{
public int Id { get; set; }
private bool isEnabled;
public bool IsEnabled
{
@@ -1,6 +1,5 @@
using DownKyi.Core.BiliApi.Users.Models;
using DownKyi.Core.BiliApi.Zone;
using DownKyi.Events;
using DownKyi.Utils;
using Prism.Commands;
using Prism.Events;
@@ -15,7 +14,7 @@ namespace DownKyi.ViewModels.UserSpace
{
public class ViewArchiveViewModel : BaseViewModel
{
public const string Tag = "PageUserSpaceArchiveView";
public const string Tag = "PageUserSpaceArchive";
private long mid = -1;
@@ -68,13 +67,7 @@ namespace DownKyi.ViewModels.UserSpace
};
// 进入视频页面
NavigationParam param = new NavigationParam
{
ViewName = ViewPublicationViewModel.Tag,
ParentViewName = ViewUserSpaceViewModel.Tag,
Parameter = data
};
eventAggregator.GetEvent<NavigationEvent>().Publish(param);
NavigateToView.NavigationView(eventAggregator, ViewPublicationViewModel.Tag, ViewUserSpaceViewModel.Tag, data);
SelectedItem = -1;
}
@@ -1,6 +1,6 @@
using DownKyi.Core.BiliApi.Users.Models;
using DownKyi.Core.Storage;
using DownKyi.Events;
using DownKyi.Utils;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
@@ -68,13 +68,7 @@ namespace DownKyi.ViewModels.UserSpace
};
// 进入视频页面
NavigationParam param = new NavigationParam
{
ViewName = ViewModels.ViewChannelViewModel.Tag,
ParentViewName = ViewUserSpaceViewModel.Tag,
Parameter = data
};
eventAggregator.GetEvent<NavigationEvent>().Publish(param);
NavigateToView.NavigationView(eventAggregator, ViewModels.ViewChannelViewModel.Tag, ViewUserSpaceViewModel.Tag, data);
SelectedItem = -1;
}
@@ -28,8 +28,6 @@ namespace DownKyi.ViewModels
{
public const string Tag = "PageChannel";
private readonly IDialogService dialogService;
private CancellationTokenSource tokenSource;
private long mid = -1;
@@ -434,7 +432,7 @@ namespace DownKyi.ViewModels
}
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
@@ -109,7 +109,7 @@ namespace DownKyi.ViewModels
#endregion
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
@@ -0,0 +1,159 @@
using DownKyi.Events;
using DownKyi.Images;
using DownKyi.Utils;
using DownKyi.ViewModels.Friends;
using DownKyi.ViewModels.PageViewModels;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace DownKyi.ViewModels
{
public class ViewFriendsViewModel : BaseViewModel
{
public const string Tag = "PageFriends";
private readonly IRegionManager regionManager;
private long mid = -1;
#region 页面属性申明
private VectorImage arrowBack;
public VectorImage ArrowBack
{
get => arrowBack;
set => SetProperty(ref arrowBack, value);
}
private ObservableCollection<TabHeader> tabHeaders;
public ObservableCollection<TabHeader> TabHeaders
{
get => tabHeaders;
set => SetProperty(ref tabHeaders, value);
}
private int selectTabId;
public int SelectTabId
{
get => selectTabId;
set => SetProperty(ref selectTabId, value);
}
#endregion
public ViewFriendsViewModel(IRegionManager regionManager, IEventAggregator eventAggregator) : base(eventAggregator)
{
this.regionManager = regionManager;
#region 属性初始化
ArrowBack = NavigationIcon.Instance().ArrowBack;
ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark");
TabHeaders = new ObservableCollection<TabHeader>
{
new TabHeader { Id = 0, Title = DictionaryResource.GetString("FriendFollowing") },
new TabHeader { Id = 1, Title = DictionaryResource.GetString("FriendFollower") },
};
#endregion
}
#region 命令申明
// 返回事件
private DelegateCommand backSpaceCommand;
public DelegateCommand BackSpaceCommand => backSpaceCommand ?? (backSpaceCommand = new DelegateCommand(ExecuteBackSpace));
/// <summary>
/// 返回事件
/// </summary>
private void ExecuteBackSpace()
{
//InitView();
ArrowBack.Fill = DictionaryResource.GetColor("ColorText");
NavigationParam parameter = new NavigationParam
{
ViewName = ParentView,
ParentViewName = null,
Parameter = null
};
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
}
// 顶部tab点击事件
private DelegateCommand<object> tabHeadersCommand;
public DelegateCommand<object> TabHeadersCommand => tabHeadersCommand ?? (tabHeadersCommand = new DelegateCommand<object>(ExecuteTabHeadersCommand));
/// <summary>
/// 顶部tab点击事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteTabHeadersCommand(object parameter)
{
if (!(parameter is TabHeader tabHeader)) { return; }
// TODO
// 此处应该根据具体状态传入true or false
NavigationView(tabHeader.Id, true);
}
#endregion
/// <summary>
/// 进入子页面
/// </summary>
/// <param name="id"></param>
/// <param name="isFirst"></param>
private void NavigationView(int id, bool isFirst)
{
// isFirst参数表示是否是从PageFriends的headerTable的item点击进入的
// true表示加载PageFriends后第一次进入
// false表示从headerTable的item点击进入
NavigationParameters param = new NavigationParameters()
{
{ "mid", mid },
{ "isFirst", isFirst },
};
switch (id)
{
case 0:
regionManager.RequestNavigate("FriendContentRegion", ViewFollowingViewModel.Tag, param);
break;
case 1:
regionManager.RequestNavigate("FriendContentRegion", ViewFollowerViewModel.Tag, param);
break;
}
}
/// <summary>
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
{
base.OnNavigatedTo(navigationContext);
ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark");
// 根据传入参数不同执行不同任务
var parameter = navigationContext.Parameters.GetValue<Dictionary<string, object>>("Parameter");
if (parameter == null)
{
return;
}
mid = (long)parameter["mid"];
SelectTabId = (int)parameter["friendId"];
NavigationView(SelectTabId, true);
}
}
}
@@ -27,8 +27,6 @@ namespace DownKyi.ViewModels
{
public const string Tag = "PageMyBangumiFollow";
private readonly IDialogService dialogService;
private CancellationTokenSource tokenSource;
private long mid = -1;
@@ -511,7 +509,7 @@ namespace DownKyi.ViewModels
}
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
@@ -26,7 +26,7 @@ namespace DownKyi.ViewModels
{
public const string Tag = "PageMyFavorites";
private readonly IDialogService dialogService;
//private readonly IDialogService dialogService;
private CancellationTokenSource tokenSource1;
private CancellationTokenSource tokenSource2;
@@ -87,7 +87,6 @@ namespace DownKyi.ViewModels
set => SetProperty(ref mediaContentVisibility, value);
}
private Visibility mediaLoadingVisibility;
public Visibility MediaLoadingVisibility
{
@@ -477,7 +476,7 @@ namespace DownKyi.ViewModels
}
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override async void OnNavigatedTo(NavigationContext navigationContext)
@@ -28,8 +28,6 @@ namespace DownKyi.ViewModels
{
public const string Tag = "PageMyHistory";
private readonly IDialogService dialogService;
private CancellationTokenSource tokenSource;
// 每页视频数量,暂时在此写死,以后在设置中增加选项
@@ -504,7 +502,7 @@ namespace DownKyi.ViewModels
}
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
+60 -10
View File
@@ -11,6 +11,7 @@ using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
@@ -240,6 +241,13 @@ namespace DownKyi.ViewModels
set => SetProperty(ref packageList, value);
}
private int selectedStatus;
public int SelectedStatus
{
get => selectedStatus;
set => SetProperty(ref selectedStatus, value);
}
private int selectedPackage;
public int SelectedPackage
{
@@ -328,6 +336,47 @@ namespace DownKyi.ViewModels
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
}
// 页面选择事件
private DelegateCommand statusListCommand;
public DelegateCommand StatusListCommand => statusListCommand ?? (statusListCommand = new DelegateCommand(ExecuteStatusListCommand));
/// <summary>
/// 页面选择事件
/// </summary>
private void ExecuteStatusListCommand()
{
if (SelectedStatus == -1)
{
return;
}
Dictionary<string, object> data = new Dictionary<string, object>
{
{ "mid", mid },
{ "friendId", 0 }
};
switch (SelectedStatus)
{
case 0:
data["friendId"] = 0;
NavigateToView.NavigationView(eventAggregator, ViewFriendsViewModel.Tag, Tag, data);
break;
case 1:
data["friendId"] = 0;
NavigateToView.NavigationView(eventAggregator, ViewFriendsViewModel.Tag, Tag, data);
break;
case 2:
data["friendId"] = 1;
NavigateToView.NavigationView(eventAggregator, ViewFriendsViewModel.Tag, Tag, data);
break;
default:
break;
}
SelectedStatus = -1;
}
// 页面选择事件
private DelegateCommand packageListCommand;
public DelegateCommand PackageListCommand => packageListCommand ?? (packageListCommand = new DelegateCommand(ExecutePackageListCommand));
@@ -391,23 +440,24 @@ namespace DownKyi.ViewModels
CurrentExp = "--/--";
StatusList.Clear();
StatusList.Add(new SpaceItem { Title = DictionaryResource.GetString("Following"), Subtitle = "--" });
StatusList.Add(new SpaceItem { Title = DictionaryResource.GetString("Whisper"), Subtitle = "--" });
StatusList.Add(new SpaceItem { Title = DictionaryResource.GetString("Follower"), Subtitle = "--" });
StatusList.Add(new SpaceItem { Title = DictionaryResource.GetString("Black"), Subtitle = "--" });
StatusList.Add(new SpaceItem { Title = DictionaryResource.GetString("Moral"), Subtitle = "--" });
StatusList.Add(new SpaceItem { Title = DictionaryResource.GetString("Silence"), Subtitle = "N/A" });
StatusList.Add(new SpaceItem { IsEnabled = true, Title = DictionaryResource.GetString("Following"), Subtitle = "--" });
StatusList.Add(new SpaceItem { IsEnabled = true, Title = DictionaryResource.GetString("Whisper"), Subtitle = "--" });
StatusList.Add(new SpaceItem { IsEnabled = true, Title = DictionaryResource.GetString("Follower"), Subtitle = "--" });
StatusList.Add(new SpaceItem { IsEnabled = false, Title = DictionaryResource.GetString("Black"), Subtitle = "--" });
StatusList.Add(new SpaceItem { IsEnabled = false, Title = DictionaryResource.GetString("Moral"), Subtitle = "--" });
StatusList.Add(new SpaceItem { IsEnabled = false, Title = DictionaryResource.GetString("Silence"), Subtitle = "N/A" });
PackageList.Clear();
PackageList.Add(new SpaceItem { Image = NormalIcon.Instance().FavoriteOutline, Title = DictionaryResource.GetString("Favorites") });
PackageList.Add(new SpaceItem { Image = NormalIcon.Instance().Subscription, Title = DictionaryResource.GetString("Subscription") });
PackageList.Add(new SpaceItem { Image = NormalIcon.Instance().ToView, Title = DictionaryResource.GetString("ToView") });
PackageList.Add(new SpaceItem { Image = NormalIcon.Instance().History, Title = DictionaryResource.GetString("History") });
PackageList.Add(new SpaceItem { IsEnabled = true, Image = NormalIcon.Instance().FavoriteOutline, Title = DictionaryResource.GetString("Favorites") });
PackageList.Add(new SpaceItem { IsEnabled = true, Image = NormalIcon.Instance().Subscription, Title = DictionaryResource.GetString("Subscription") });
PackageList.Add(new SpaceItem { IsEnabled = true, Image = NormalIcon.Instance().ToView, Title = DictionaryResource.GetString("ToView") });
PackageList.Add(new SpaceItem { IsEnabled = true, Image = NormalIcon.Instance().History, Title = DictionaryResource.GetString("History") });
NormalIcon.Instance().FavoriteOutline.Fill = DictionaryResource.GetColor("ColorPrimary");
NormalIcon.Instance().Subscription.Fill = DictionaryResource.GetColor("ColorPrimary");
NormalIcon.Instance().ToView.Fill = DictionaryResource.GetColor("ColorPrimary");
NormalIcon.Instance().History.Fill = DictionaryResource.GetColor("ColorPrimary");
SelectedStatus = -1;
SelectedPackage = -1;
ContentVisibility = Visibility.Collapsed;
@@ -27,8 +27,6 @@ namespace DownKyi.ViewModels
{
public const string Tag = "PageMyToView";
private readonly IDialogService dialogService;
private CancellationTokenSource tokenSource;
#region 页面属性申明
@@ -400,7 +398,7 @@ namespace DownKyi.ViewModels
}
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
@@ -26,8 +26,6 @@ namespace DownKyi.ViewModels
{
public const string Tag = "PagePublicFavorites";
private readonly IDialogService dialogService;
private CancellationTokenSource tokenSource;
#region 页面属性申明
@@ -29,8 +29,6 @@ namespace DownKyi.ViewModels
{
public const string Tag = "PagePublication";
private readonly IDialogService dialogService;
private CancellationTokenSource tokenSource;
private long mid = -1;
@@ -487,7 +485,7 @@ namespace DownKyi.ViewModels
}
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
@@ -28,8 +28,6 @@ namespace DownKyi.ViewModels
{
public const string Tag = "PageSeasonsSeries";
private readonly IDialogService dialogService;
private CancellationTokenSource tokenSource;
private long mid = -1;
@@ -121,7 +121,7 @@ namespace DownKyi.ViewModels
#endregion
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
@@ -112,7 +112,7 @@ namespace DownKyi.ViewModels
#endregion
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
@@ -156,6 +156,14 @@ namespace DownKyi.ViewModels
set => SetProperty(ref tabRightBanners, value);
}
private int selectedRightBanner;
public int SelectedRightBanner
{
get => selectedRightBanner;
set => SetProperty(ref selectedRightBanner, value);
}
#endregion
public ViewUserSpaceViewModel(IRegionManager regionManager, IEventAggregator eventAggregator) : base(eventAggregator)
@@ -232,6 +240,48 @@ namespace DownKyi.ViewModels
}
}
// 右侧tab点击事件
private DelegateCommand<object> tabRightBannersCommand;
public DelegateCommand<object> TabRightBannersCommand => tabRightBannersCommand ?? (tabRightBannersCommand = new DelegateCommand<object>(ExecuteTabRightBannersCommand));
/// <summary>
/// 右侧tab点击事件
/// </summary>
private void ExecuteTabRightBannersCommand(object parameter)
{
if (!(parameter is TabRightBanner banner)) { return; }
Dictionary<string, object> data = new Dictionary<string, object>
{
{ "mid", mid },
{ "friendId", 0 }
};
string parentViewName;
if (ParentView == ViewFriendsViewModel.Tag)
{
parentViewName = ViewIndexViewModel.Tag;
}
else
{
parentViewName = Tag;
}
switch (banner.Id)
{
case 0:
data["friendId"] = 0;
NavigateToView.NavigationView(eventAggregator, ViewFriendsViewModel.Tag, parentViewName, data);
break;
case 1:
data["friendId"] = 1;
NavigateToView.NavigationView(eventAggregator, ViewFriendsViewModel.Tag, parentViewName, data);
break;
}
SelectedRightBanner = -1;
}
#endregion
/// <summary>
@@ -254,6 +304,8 @@ namespace DownKyi.ViewModels
TabLeftBanners.Clear();
TabRightBanners.Clear();
SelectedRightBanner = -1;
// 将内容置空,使其不指向任何页面
regionManager.RequestNavigate("UserSpaceContentRegion", "");
@@ -436,6 +488,7 @@ namespace DownKyi.ViewModels
{
TabRightBanners.Add(new TabRightBanner
{
Id = 0,
IsEnabled = true,
LabelColor = DictionaryResource.GetColor("ColorPrimary"),
CountColor = DictionaryResource.GetColor("ColorPrimary"),
@@ -444,6 +497,7 @@ namespace DownKyi.ViewModels
});
TabRightBanners.Add(new TabRightBanner
{
Id = 1,
IsEnabled = true,
LabelColor = DictionaryResource.GetColor("ColorPrimary"),
CountColor = DictionaryResource.GetColor("ColorPrimary"),
@@ -462,6 +516,7 @@ namespace DownKyi.ViewModels
{
TabRightBanners.Add(new TabRightBanner
{
Id = 2,
IsEnabled = false,
LabelColor = DictionaryResource.GetColor("ColorTextGrey"),
CountColor = DictionaryResource.GetColor("ColorTextDark"),
@@ -476,6 +531,7 @@ namespace DownKyi.ViewModels
}
TabRightBanners.Add(new TabRightBanner
{
Id = 3,
IsEnabled = false,
LabelColor = DictionaryResource.GetColor("ColorTextGrey"),
CountColor = DictionaryResource.GetColor("ColorTextDark"),
@@ -490,6 +546,7 @@ namespace DownKyi.ViewModels
}
TabRightBanners.Add(new TabRightBanner
{
Id = 4,
IsEnabled = false,
LabelColor = DictionaryResource.GetColor("ColorTextGrey"),
CountColor = DictionaryResource.GetColor("ColorTextDark"),
@@ -739,7 +739,7 @@ namespace DownKyi.ViewModels
#endregion
/// <summary>
/// 导航到VideoDetail页面时执行
/// 导航到页面时执行
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
+13 -1
View File
@@ -109,7 +109,19 @@
TextTrimming="CharacterEllipsis"
TextWrapping="WrapWithOverflow" />
<Grid Grid.Row="1">
<Button
Grid.Row="1"
Width="75"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Command="{Binding AllowCommand}"
Content="{DynamicResource Allow}"
FontSize="12"
Foreground="{DynamicResource BrushText}"
Style="{StaticResource BtnStyle}"
Visibility="{Binding AloneButton}" />
<Grid Grid.Row="1" Visibility="{Binding TwoButton}">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="100" />
<ColumnDefinition MinWidth="100" />
+153
View File
@@ -0,0 +1,153 @@
<UserControl
x:Class="DownKyi.Views.Friends.ViewFollower"
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:custom="clr-namespace:DownKyi.CustomControl"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<UserControl.Resources>
<Style x:Key="ContentListStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid
Name="nameUserPanel"
Width="400"
Height="80"
Margin="15,15,10,5"
Cursor="Hand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding UserCommand}" CommandParameter="{Binding DataContext.PageName, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Image
Grid.Column="0"
Width="64"
Height="64"
Source="{Binding Header}">
<Image.Clip>
<EllipseGeometry
Center="32,32"
RadiusX="32"
RadiusY="32" />
</Image.Clip>
</Image>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource BrushTextDark}"
Text="{Binding Name}"
TextTrimming="CharacterEllipsis"
TextWrapping="WrapWithOverflow" />
<TextBlock
Grid.Row="1"
HorizontalAlignment="Left"
VerticalAlignment="Top"
FontSize="12"
Foreground="{DynamicResource BrushTextGrey2}"
Text="{Binding Sign}"
TextTrimming="CharacterEllipsis"
TextWrapping="WrapWithOverflow"
ToolTip="{Binding Sign}" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Grid Grid.Column="1" Visibility="{Binding ContentVisibility}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<ListBox
x:Name="nameContents"
Grid.Row="0"
BorderThickness="0"
ItemContainerStyle="{StaticResource ContentListStyle}"
ItemsSource="{Binding Contents}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding ContentsCommand}" CommandParameter="{Binding ElementName=nameContents, Path=SelectedItems}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border
x:Name="Bd"
Padding="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
</ListBox>
<custom:CustomPager
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
DataContext="{Binding Pager}" />
</Grid>
<!-- 加载gif -->
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Vertical"
Visibility="{Binding LoadingVisibility}">
<ContentControl
Width="40"
Height="40"
Content="{Binding Loading}" />
<TextBlock
Margin="0,10,0,0"
FontSize="14"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource FollowerWait}" />
</StackPanel>
<!-- 没有数据提示 -->
<Image
Width="256"
Height="256"
Source="/DownKyi;component/Resources/no-data.png"
Visibility="{Binding NoDataVisibility}" />
</Grid>
</UserControl>
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DownKyi.Views.Friends
{
/// <summary>
/// ViewFollower.xaml 的交互逻辑
/// </summary>
public partial class ViewFollower : UserControl
{
public ViewFollower()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,226 @@
<UserControl
x:Class="DownKyi.Views.Friends.ViewFollowing"
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:custom="clr-namespace:DownKyi.CustomControl"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<UserControl.Resources>
<converter:CountConverter x:Key="CountConverter" Count="1" />
<Style x:Key="ContentListStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid
Name="nameUserPanel"
Width="400"
Height="80"
Margin="15,15,10,5"
Cursor="Hand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding UserCommand}" CommandParameter="{Binding DataContext.PageName, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Image
Grid.Column="0"
Width="64"
Height="64"
Source="{Binding Header}">
<Image.Clip>
<EllipseGeometry
Center="32,32"
RadiusX="32"
RadiusY="32" />
</Image.Clip>
</Image>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource BrushTextDark}"
Text="{Binding Name}"
TextTrimming="CharacterEllipsis"
TextWrapping="WrapWithOverflow" />
<TextBlock
Grid.Row="1"
HorizontalAlignment="Left"
VerticalAlignment="Top"
FontSize="12"
Foreground="{DynamicResource BrushTextGrey2}"
Text="{Binding Sign}"
TextTrimming="CharacterEllipsis"
TextWrapping="WrapWithOverflow"
ToolTip="{Binding Sign}" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Grid Visibility="{Binding ContentVisibility}">
<Grid.ColumnDefinitions>
<ColumnDefinition>
<ColumnDefinition.Style>
<Style TargetType="ColumnDefinition">
<Style.Triggers>
<DataTrigger Binding="{Binding TabHeaders}" Value="{x:Null}">
<Setter Property="Width" Value="0" />
</DataTrigger>
<DataTrigger Binding="{Binding TabHeaders.Count}" Value="0">
<Setter Property="Width" Value="0" />
</DataTrigger>
<DataTrigger Binding="{Binding TabHeaders.Count}" Value="1">
<Setter Property="Width" Value="0" />
</DataTrigger>
<DataTrigger Binding="{Binding TabHeaders.Count, Converter={StaticResource CountConverter}}" Value="true">
<Setter Property="Width" Value="200" />
</DataTrigger>
</Style.Triggers>
</Style>
</ColumnDefinition.Style>
</ColumnDefinition>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- 左侧tab header -->
<ListBox
Name="nameLeftTabHeaders"
Grid.Column="0"
BorderThickness="0"
IsEnabled="{Binding IsEnabled}"
ItemContainerStyle="{StaticResource LeftTabHeaderItemStyle}"
ItemsSource="{Binding TabHeaders}"
SelectedIndex="{Binding SelectTabId}"
Style="{StaticResource LeftTabHeaderStyle}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding LeftTabHeadersCommand}" CommandParameter="{Binding ElementName=nameLeftTabHeaders, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
<!-- 右侧内容区 -->
<Grid Grid.Column="1" Visibility="{Binding InnerContentVisibility}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<ListBox
x:Name="nameContents"
Grid.Row="0"
BorderThickness="0"
ItemContainerStyle="{StaticResource ContentListStyle}"
ItemsSource="{Binding Contents}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding ContentsCommand}" CommandParameter="{Binding ElementName=nameContents, Path=SelectedItems}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border
x:Name="Bd"
Padding="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
</ListBox>
<custom:CustomPager
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
DataContext="{Binding Pager}" />
</Grid>
<!-- 加载gif -->
<StackPanel
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Vertical"
Visibility="{Binding ContentLoadingVisibility}">
<ContentControl
Width="40"
Height="40"
Content="{Binding ContentLoading}" />
<TextBlock
Margin="0,10,0,0"
FontSize="14"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource FollowingWait}" />
</StackPanel>
<!-- 没有数据提示 -->
<Image
Grid.Column="1"
Width="256"
Height="256"
Source="/DownKyi;component/Resources/no-data.png"
Visibility="{Binding ContentNoDataVisibility}" />
</Grid>
<!-- 加载gif -->
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Vertical"
Visibility="{Binding LoadingVisibility}">
<ContentControl
Width="40"
Height="40"
Content="{Binding Loading}" />
<TextBlock
Margin="0,10,0,0"
FontSize="14"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource FollowingWait}" />
</StackPanel>
<!-- 没有数据提示 -->
<Image
Width="256"
Height="256"
Source="/DownKyi;component/Resources/no-data.png"
Visibility="{Binding NoDataVisibility}" />
</Grid>
</UserControl>
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DownKyi.Views.Friends
{
/// <summary>
/// ViewFollowing.xaml 的交互逻辑
/// </summary>
public partial class ViewFollowing : UserControl
{
public ViewFollowing()
{
InitializeComponent();
}
}
}
+2 -2
View File
@@ -188,7 +188,7 @@
Grid.Column="2"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="3.20.1" />
Text="3.21.12" />
<TextBlock
Grid.Row="2"
Grid.Column="3"
@@ -215,7 +215,7 @@
Grid.Column="2"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="13.0.1" />
Text="13.0.2" />
<TextBlock
Grid.Row="3"
Grid.Column="3"
@@ -28,6 +28,26 @@
IsChecked="{Binding UseSSL, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
<TextBlock
Margin="0,20,0,0"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource UserAgent}" />
<TextBox
Name="nameUserAgent"
Height="20"
Margin="0,10,0,0"
HorizontalAlignment="Stretch"
Text="{Binding UserAgent}">
<TextBox.InputBindings>
<KeyBinding
Key="Enter"
Command="{Binding UserAgentCommand}"
CommandParameter="{Binding ElementName=nameUserAgent, Path=Text}" />
</TextBox.InputBindings>
</TextBox>
<StackPanel Margin="0,20,0,0" Orientation="Vertical">
<TextBlock
FontSize="12"
+138
View File
@@ -0,0 +1,138 @@
<UserControl
x:Class="DownKyi.Views.ViewFriends"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:DownKyi.CustomControl"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<UserControl.Resources />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="1" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="0"
Margin="10,5,0,5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding BackSpaceCommand}"
Style="{StaticResource ImageBtnStyle}">
<StackPanel Orientation="Horizontal">
<ContentControl Width="24" Height="24">
<Path
Width="{Binding ArrowBack.Width}"
Height="{Binding ArrowBack.Height}"
Data="{Binding ArrowBack.Data}"
Fill="{Binding ArrowBack.Fill}"
Stretch="None" />
</ContentControl>
<TextBlock
VerticalAlignment="Center"
FontSize="16"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource Friend}" />
</StackPanel>
</Button>
<!-- 顶部Tab -->
<ListBox
Name="nameTabHeaders"
Grid.Column="1"
BorderThickness="0"
ItemsSource="{Binding TabHeaders}"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
SelectedIndex="{Binding SelectTabId, Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding TabHeadersCommand}" CommandParameter="{Binding ElementName=nameTabHeaders, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<StackPanel
x:Name="panel"
Margin="10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Cursor="Hand">
<TextBlock
Name="nameText"
Padding="0,0,0,3"
Text="{Binding Title}" />
<TextBlock Name="nameIndicator" Height="1.5" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="Selector.IsSelected" Value="False">
<Setter TargetName="nameText" Property="Foreground" Value="{DynamicResource BrushTextDark}" />
<Setter TargetName="nameIndicator" Property="Visibility" Value="Hidden" />
<Setter TargetName="nameIndicator" Property="Background" Value="{DynamicResource BrushTextDark}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="nameText" Property="Foreground" Value="{DynamicResource BrushPrimary}" />
</Trigger>
<Trigger Property="Selector.IsSelected" Value="True">
<Setter TargetName="nameText" Property="Foreground" Value="{DynamicResource BrushPrimary}" />
<Setter TargetName="nameIndicator" Property="Visibility" Value="Visible" />
<Setter TargetName="nameIndicator" Property="Background" Value="{DynamicResource BrushPrimary}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border
x:Name="Bd"
Padding="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
</ListBox>
</Grid>
<TextBlock Grid.Row="1" Background="{DynamicResource BrushBorder}" />
<!-- 内容区 -->
<ContentControl Grid.Row="2" prism:RegionManager.RegionName="FriendContentRegion" />
</Grid>
</UserControl>
+28
View File
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DownKyi.Views
{
/// <summary>
/// ViewFriend.xaml 的交互逻辑
/// </summary>
public partial class ViewFriends : UserControl
{
public ViewFriends()
{
InitializeComponent();
}
}
}
+8
View File
@@ -256,8 +256,14 @@
BorderBrush="{x:Null}"
BorderThickness="0"
ItemsSource="{Binding StatusList}"
SelectedIndex="{Binding SelectedStatus}"
SelectionMode="Single"
Style="{StaticResource SpaceStyle}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding StatusListCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
@@ -266,6 +272,8 @@
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Cursor="Hand"
IsEnabled="{Binding IsEnabled}"
Orientation="Vertical">
<TextBlock
HorizontalAlignment="Center"
+7
View File
@@ -277,10 +277,12 @@
</ListBox>
<ListBox
Name="nameTabRightBanners"
Grid.Column="1"
ItemContainerStyle="{StaticResource TabRightBannerStyle}"
ItemsSource="{Binding TabRightBanners}"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
SelectedIndex="{Binding SelectedRightBanner}"
Style="{StaticResource TabBannerStyle}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
@@ -290,6 +292,11 @@
Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding TabRightBannersCommand}" CommandParameter="{Binding ElementName=nameTabRightBanners, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
</Grid>