下载服务基本完成

This commit is contained in:
flyself 2021-12-22 10:12:18 +08:00
parent fc5ba508b0
commit 871f60df6b
60 changed files with 3350 additions and 492 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -1,5 +1,6 @@
using DownKyi.Core.Aria2cNet.Client;
using DownKyi.Core.Logging;
using System;
using System.Threading;
namespace DownKyi.Core.Aria2cNet
@ -32,10 +33,14 @@ namespace DownKyi.Core.Aria2cNet
/// <summary>
/// 获取gid下载项的状态
///
/// TODO
/// 对于下载的不同状态的返回值的测试
/// </summary>
/// <param name="gid"></param>
/// <param name="action"></param>
/// <returns></returns>
public DownloadStatus GetDownloadStatus(string gid)
public DownloadResult GetDownloadStatus(string gid, Action action = null)
{
string filePath = "";
while (true)
@ -48,7 +53,7 @@ namespace DownKyi.Core.Aria2cNet
if (status.Result.Error.Message.Contains("is not found"))
{
OnDownloadFinish(false, null, gid, status.Result.Error.Message);
return DownloadStatus.ABORT;
return DownloadResult.ABORT;
}
}
@ -60,9 +65,16 @@ namespace DownKyi.Core.Aria2cNet
long totalLength = long.Parse(status.Result.Result.TotalLength);
long completedLength = long.Parse(status.Result.Result.CompletedLength);
long speed = long.Parse(status.Result.Result.DownloadSpeed);
// 回调
OnTellStatus(totalLength, completedLength, speed, gid);
// 在外部执行
if (action != null)
{
action.Invoke();
}
if (status.Result.Result.Status == "complete")
{
break;
@ -86,14 +98,14 @@ namespace DownKyi.Core.Aria2cNet
// 返回回调信息,退出函数
OnDownloadFinish(false, null, gid, status.Result.Result.ErrorMessage);
return DownloadStatus.FAILED;
return DownloadResult.FAILED;
}
// 降低CPU占用
Thread.Sleep(100);
}
OnDownloadFinish(true, filePath, gid, null);
return DownloadStatus.SUCCESS;
return DownloadResult.SUCCESS;
}
/// <summary>

View File

@ -0,0 +1,12 @@
namespace DownKyi.Core.Aria2cNet
{
/// <summary>
/// 下载状态
/// </summary>
public enum DownloadResult
{
SUCCESS = 1,
FAILED,
ABORT
}
}

View File

@ -18,5 +18,19 @@ namespace DownKyi.Core.BiliApi.Bangumi
{ 10, "Unknown" }
};
public static Dictionary<int, int> TypeId = new Dictionary<int, int>()
{
{ 1, 13 },
{ 2, 23 },
{ 3, 177 },
{ 4, 167 },
{ 5, 11 },
{ 6, -1 },
{ 7, -1 },
{ 8, -1 },
{ 9, -1 },
{ 10, -1 }
};
}
}

View File

@ -14,5 +14,15 @@ namespace DownKyi.Core.BiliApi.BiliUtils
{ 30280, "192K" }
};
/// <summary>
/// 音质id及含义
/// </summary>
public static Dictionary<string, int> AudioQualityId { get; } = new Dictionary<string, int>()
{
{ "64K", 30216 },
{ "132K", 30232 },
{ "192K", 30280 }
};
}
}

View File

@ -0,0 +1,14 @@
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.Models.Json
{
public class SubRipText : BaseModel
{
[JsonProperty("lan")]
public string Lan { get; set; }
[JsonProperty("lan_doc")]
public string LanDoc { get; set; }
[JsonProperty("srtString")]
public string SrtString { get; set; }
}
}

View File

@ -0,0 +1,16 @@
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.Models.Json
{
public class Subtitle : BaseModel
{
[JsonProperty("from")]
public float From { get; set; }
[JsonProperty("to")]
public float To { get; set; }
[JsonProperty("location")]
public int Location { get; set; }
[JsonProperty("content")]
public string Content { get; set; }
}
}

View File

@ -0,0 +1,69 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Models.Json
{
public class SubtitleJson : BaseModel
{
[JsonProperty("font_size")]
public float FontSize { get; set; }
[JsonProperty("font_color")]
public string FontColor { get; set; }
[JsonProperty("background_alpha")]
public float BackgroundAlpha { get; set; }
[JsonProperty("background_color")]
public string BackgroundColor { get; set; }
[JsonProperty("Stroke")]
public string Stroke { get; set; }
[JsonProperty("body")]
public List<Subtitle> Body { get; set; }
/// <summary>
/// srt格式字幕
/// </summary>
/// <returns></returns>
public string ToSubRip()
{
string subRip = string.Empty;
for (int i = 0; i < Body.Count; i++)
{
subRip += $"{i + 1}\n";
subRip += $"{Second2hms(Body[i].From)} --> {Second2hms(Body[i].To)}\n";
subRip += $"{Body[i].Content}\n";
subRip += "\n";
}
return subRip;
}
/// <summary>
/// 秒数转 时:分:秒 格式
/// </summary>
/// <param name="seconds"></param>
/// <returns></returns>
private static string Second2hms(float seconds)
{
if (seconds < 0)
{
return "00:00:00,000";
}
int i = (int)Math.Floor(seconds / 1.0);
int dec = (int)(Math.Round(seconds % 1.0f, 2) * 100);
if (dec >= 100)
{
dec = 99;
}
int min = (int)Math.Floor(i / 60.0);
int second = (int)(i % 60.0f);
int hour = (int)Math.Floor(min / 60.0);
min = (int)Math.Floor(min % 60.0f);
return $"{hour:D2}:{min:D2}:{second:D2},{dec:D3}";
}
}
}

View File

@ -21,5 +21,7 @@ namespace DownKyi.Core.BiliApi.Video.Models
public string Weblink { get; set; }
[JsonProperty("dimension")]
public Dimension Dimension { get; set; }
[JsonProperty("first_frame")]
public string FirstFrame { get; set; }
}
}

View File

@ -0,0 +1,34 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.VideoStream.Models
{
// https://api.bilibili.com/x/player/v2?cid={cid}&aid={avid}&bvid={bvid}
public class PlayerV2Origin : BaseModel
{
//[JsonProperty("code")]
//public int Code { get; set; }
//[JsonProperty("message")]
//public string Message { get; set; }
//[JsonProperty("ttl")]
//public int Ttl { get; set; }
[JsonProperty("data")]
public PlayerV2 Data { get; set; }
}
public class PlayerV2 : BaseModel
{
[JsonProperty("aid")]
public long Aid { get; set; }
[JsonProperty("bvid")]
public string Bvid { get; set; }
// allow_bp
// no_share
[JsonProperty("cid")]
public long Cid { get; set; }
// ...
[JsonProperty("subtitle")]
public SubtitleInfo Subtitle { get; set; }
}
}

View File

@ -0,0 +1,25 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.VideoStream.Models
{
public class Subtitle : BaseModel
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("lan")]
public string Lan { get; set; }
[JsonProperty("lan_doc")]
public string LanDoc { get; set; }
[JsonProperty("is_lock")]
public bool IsLock { get; set; }
[JsonProperty("author_mid")]
public long AuthorMid { get; set; }
[JsonProperty("subtitle_url")]
public string SubtitleUrl { get; set; }
[JsonProperty("type")]
public int Type { get; set; }
[JsonProperty("id_str")]
public string IdStr { get; set; }
}
}

View File

@ -0,0 +1,18 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.VideoStream.Models
{
public class SubtitleInfo : BaseModel
{
[JsonProperty("allow_submit")]
public bool AllowSubmit { get; set; }
[JsonProperty("lan")]
public string Lan { get; set; }
[JsonProperty("lan_doc")]
public string LanDoc { get; set; }
[JsonProperty("subtitles")]
public List<Subtitle> Subtitles { get; set; }
}
}

View File

@ -1,13 +1,88 @@
using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Core.BiliApi.Models.Json;
using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Core.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.VideoStream
{
public static class VideoStream
{
/// <summary>
/// 获取播放器信息web端
/// </summary>
/// <param name="avid"></param>
/// <param name="bvid"></param>
/// <param name="cid"></param>
/// <returns></returns>
public static PlayerV2 PlayerV2(long avid, string bvid, long cid)
{
string url = $"https://api.bilibili.com/x/player/v2?cid={cid}&aid={avid}&bvid={bvid}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
try
{
var playUrl = JsonConvert.DeserializeObject<PlayerV2Origin>(response);
return playUrl?.Data;
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("PlayerV2()发生异常: {0}", e);
LogManager.Error("PlayerV2()", e);
return null;
}
}
/// <summary>
/// 获取所有字幕<br/>
/// 若视频没有字幕返回null
/// </summary>
/// <param name="avid"></param>
/// <param name="bvid"></param>
/// <param name="cid"></param>
/// <returns></returns>
public static List<SubRipText> GetSubtitle(long avid, string bvid, long cid)
{
List<SubRipText> subRipTexts = new List<SubRipText>();
// 获取播放器信息
PlayerV2 player = PlayerV2(avid, bvid, cid);
if (player == null) { return subRipTexts; }
if (player.Subtitle != null && player.Subtitle.Subtitles != null && player.Subtitle.Subtitles.Count == 0)
{
return null;
}
foreach (var subtitle in player.Subtitle.Subtitles)
{
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb($"https:{subtitle.SubtitleUrl}", referer);
try
{
var subtitleJson = JsonConvert.DeserializeObject<SubtitleJson>(response);
if (subtitleJson == null) { continue; }
subRipTexts.Add(new SubRipText
{
Lan = subtitle.Lan,
LanDoc = subtitle.LanDoc,
SrtString = subtitleJson.ToSubRip()
});
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetSubtitle()发生异常: {0}", e);
LogManager.Error("GetSubtitle()", e);
}
}
return subRipTexts;
}
/// <summary>
/// 获取普通视频的视频流
/// </summary>
@ -92,7 +167,7 @@ namespace DownKyi.Core.BiliApi.VideoStream
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetPlayUrl()发生异常: {0}", e);
LogManager.Error("GetPlayUrl", e);
LogManager.Error("GetPlayUrl()", e);
return null;
}
}

View File

@ -2,7 +2,6 @@
namespace DownKyi.Core.BiliApi.Zone
{
public class VideoZone
{
private static VideoZone that;
@ -21,7 +20,7 @@ namespace DownKyi.Core.BiliApi.Zone
return that;
}
public List<ZoneAttr> GetZone()
public List<ZoneAttr> GetZones()
{
return zones;
}
@ -59,7 +58,7 @@ namespace DownKyi.Core.BiliApi.Zone
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(193, "mv", "MV", 3)); //音乐录影带,为搭配音乐而拍摄或制作的视频
zones.Add(new ZoneAttr(29, "live", "音乐现场", 3)); //音乐实况表演视频
zones.Add(new ZoneAttr(130, "other", "音乐综合", 3)); //收录无法定义到其他音乐子分区的音乐视频
@ -84,37 +83,48 @@ namespace DownKyi.Core.BiliApi.Zone
zones.Add(new ZoneAttr(19, "mugen", "Mugen", 4)); //以Mugen引擎为平台制作、或与Mugen相关的游戏视频
//知识
zones.Add(new ZoneAttr(36, "technology", "知识")); // 主分区
zones.Add(new ZoneAttr(36, "knowledge", "知识")); // 主分区
zones.Add(new ZoneAttr(201, "science", "科学科普", 36)); //回答你的十万个为什么
zones.Add(new ZoneAttr(124, "fun", "社科人文", 36)); //聊聊互联网社会法律,看看历史趣闻艺术,品品文化心理人物
zones.Add(new ZoneAttr(207, "finance", "财经", 36)); //宏观经济分析,证券市场动态,商业帝国故事,知识与财富齐飞~
zones.Add(new ZoneAttr(208, "campus", "校园学习", 36)); //老师很有趣,同学多人才,我们都爱搞学习
zones.Add(new ZoneAttr(209, "career", "职业职场", 36)); //职场加油站,成为最有料的职场人
zones.Add(new ZoneAttr(122, "wild", "野生技术协会", 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, "digital", "数码")); // 主分区
zones.Add(new ZoneAttr(95, "mobile", "手机平板", 188)); //手机平板、app 和产品教程等相关视频
zones.Add(new ZoneAttr(189, "pc", "电脑装机", 188)); //电脑、笔记本、装机配件、外设和软件教程等相关视频
zones.Add(new ZoneAttr(190, "photography", "摄影摄像", 188)); //摄影摄像器材、拍摄剪辑技巧、拍摄作品分享等相关视频
zones.Add(new ZoneAttr(191, "intelligence_av", "影音智能", 188)); //影音设备、智能硬件、生活家电等相关视频
//科技
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(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(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(160, "life", "生活")); // 主分区
zones.Add(new ZoneAttr(138, "funny", "搞笑", 160)); //各种沙雕有趣的搞笑剪辑,挑战,表演,配音等视频
zones.Add(new ZoneAttr(21, "daily", "日常", 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(163, "sports", "运动", 160)); //运动相关的记录、教程、装备评测和精彩瞬间剪辑视频
zones.Add(new ZoneAttr(174, "other", "其他", 160)); //对分区归属不明的视频进行归纳整合的特定分区
zones.Add(new ZoneAttr(21, "daily", "日常", 160)); //记录日常生活,分享生活故事
//美食
zones.Add(new ZoneAttr(211, "food", "美食")); // 主分区
@ -143,11 +153,9 @@ namespace DownKyi.Core.BiliApi.Zone
//时尚
zones.Add(new ZoneAttr(155, "fashion", "时尚")); // 主分区
zones.Add(new ZoneAttr(157, "makeup", "美妆", 155)); //涵盖妆容、发型、美甲等教程,彩妆、护肤相关产品测评、分享等
zones.Add(new ZoneAttr(158, "clothing", "服饰", 155)); //服饰风格、搭配技巧相关的展示和教程视频
zones.Add(new ZoneAttr(164, "aerobics", "健身", 155)); //器械、有氧、拉伸运动等,以达到强身健体、减肥瘦身、形体塑造目的
zones.Add(new ZoneAttr(159, "catwalk", "T台", 155)); //发布会走秀现场及模特相关时尚片、采访、后台花絮
zones.Add(new ZoneAttr(192, "trends", "风尚标", 155)); //时尚明星专访、街拍、时尚购物相关知识科普
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(202, "information", "资讯")); // 主分区
@ -158,8 +166,10 @@ namespace DownKyi.Core.BiliApi.Zone
//娱乐
zones.Add(new ZoneAttr(5, "ent", "娱乐")); // 主分区
zones.Add(new ZoneAttr(71, "variety", "综艺", 5)); //国内外有趣的综艺和综艺相关精彩剪辑
zones.Add(new ZoneAttr(137, "star", "明星", 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", "影视")); // 主分区

View File

@ -0,0 +1,88 @@
namespace DownKyi.Core.BiliApi.Zone
{
/// <summary>
/// 视频分区图标
/// </summary>
public class VideoZoneIcon
{
private static VideoZoneIcon instance;
/// <summary>
/// 获取VideoZoneIcon实例
/// </summary>
/// <returns></returns>
public static VideoZoneIcon Instance()
{
if (instance == null)
{
instance = new VideoZoneIcon();
}
return instance;
}
/// <summary>
/// 隐藏VideoZoneIcon()方法,必须使用单例模式
/// </summary>
private VideoZoneIcon() { }
/// <summary>
/// 根据tid获取视频分区图标
/// </summary>
/// <param name="tid"></param>
/// <returns></returns>
public string GetZoneImageKey(int tid)
{
switch (tid)
{
// 课堂
case -10:
return "Zone.cheeseDrawingImage";
case 1:
return "Zone.dougaDrawingImage";
case 13:
return "Zone.animeDrawingImage";
case 167:
return "Zone.guochuangDrawingImage";
case 3:
return "Zone.musicDrawingImage";
case 129:
return "Zone.danceDrawingImage";
case 4:
return "Zone.gameDrawingImage";
case 36:
return "Zone.techDrawingImage";
case 188:
return "Zone.digitalDrawingImage";
case 234:
return "Zone.sportsDrawingImage";
case 223:
return "Zone.carDrawingImage";
case 160:
return "Zone.lifeDrawingImage";
case 211:
return "Zone.foodDrawingImage";
case 217:
return "Zone.animalDrawingImage";
case 119:
return "Zone.kichikuDrawingImage";
case 155:
return "Zone.fashionDrawingImage";
case 202:
return "Zone.informationDrawingImage";
case 5:
return "Zone.entDrawingImage";
case 181:
return "Zone.cinephileDrawingImage";
case 177:
return "Zone.documentaryDrawingImage";
case 23:
return "Zone.movieDrawingImage";
case 11:
return "Zone.teleplayDrawingImage";
default:
return "videoUpDrawingImage";
}
}
}
}

View File

@ -0,0 +1,308 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DrawingImage x:Key="Zone.adDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FF9796ED" Geometry="F1 M1024,1024z M0,0z M576.768,153.6C609.536,121.088 708.864,167.424 798.72,257.28 888.576,347.136 935.168,446.464 902.4,479.232A27.648,27.648,0,0,1,896.256,483.84C858.624,506.624,256.256,861.44,256.256,861.44A110.592,110.592,0,0,1,207.872,830.464A140.288,140.288,0,0,1,173.312,781.312C173.312,781.312,554.496,192.512,572.672,160.512A34.56,34.56,0,0,1,576.768,153.6z" />
<GeometryDrawing Brush="#FF9289F0" Geometry="F1 M1024,1024z M0,0z M172.288,780.032C167.424,783.36,136.96,800,121.088,808.96A18.688,18.688,0,0,0,111.36,828.416A104.192,104.192,0,0,0,142.848,886.784A117.504,117.504,0,0,0,202.24,919.808A19.2,19.2,0,0,0,222.208,911.36C232.96,894.208,254.208,860.16,255.232,860.16A110.592,110.592,0,0,1,206.848,829.184A140.288,140.288,0,0,1,172.288,780.032z" />
<GeometryDrawing Brush="#FFF7DF88" Geometry="F1 M1024,1024z M0,0z M576.768,153.6C609.536,121.088 708.864,167.424 798.72,257.28 888.576,347.136 935.168,446.464 902.4,479.232A27.648,27.648,0,0,1,896.256,483.84C858.624,506.624 793.856,544 793.856,544 793.856,544 729.856,539.904 620.544,430.336 518.144,327.936 508.416,259.328 508.416,259.328 508.416,259.328 548.352,197.632 570.88,160.512A34.56,34.56,0,0,1,576.768,153.6z" />
<GeometryDrawing Brush="#FF8683EA" Geometry="F1 M1024,1024z M0,0z M680.45816,374.49224A230.144,83.712,45,1,0,798.844805,256.105595A230.144,83.712,45,1,0,680.45816,374.49224z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.animalDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFB7299" Geometry="F1 M1024,1024z M0,0z M517.376,465.152A144.924444,144.924444,0,0,1,654.904889,564.366222C656.184889,568.291555,657.180445,572.216889,657.806222,576.170667A132.266667,132.266667,0,0,1,643.527111,839.936L380.472889,839.936A132.266667,132.266667,0,0,1,366.222222,576.142222C366.848,572.16,367.815111,568.234666,369.095111,564.366222A144.924444,144.924444,0,0,1,506.624,465.152L517.376,465.152z M420.693333,418.104889C470.954666,414.321778 506.311111,358.940445 499.740444,294.371556 493.141333,229.802667 447.089777,180.48 396.828444,184.263111 346.595555,188.017778 311.210666,243.427555 317.809778,307.996444 324.408889,372.565333 370.460445,421.859555 420.721778,418.076444z M603.306667,418.104889C653.539556,421.859556 699.591111,372.593778 706.190222,307.996444 712.789333,243.427555 677.404444,188.017777 627.171556,184.263111 576.910223,180.48 530.858667,229.774222 524.259556,294.343111 517.660445,358.912 553.045334,414.321778 603.278222,418.076444z M717.425778,551.139556C756.508445,572.956445 814.336,546.872889 846.563556,492.913778 878.819556,438.954667 873.272889,377.543111 834.190222,355.726222 795.079111,333.909333 737.251555,359.992889 705.024,413.952 672.768,467.911111 678.314667,529.322667 717.425778,551.139556z M306.574222,551.139556C345.685333,529.322667 351.232,467.911112 318.976,413.952 286.748444,359.992889 228.920889,333.909333 189.838222,355.726222 150.727111,377.543111 145.180444,438.954666 177.408,492.913778 209.664,546.872889 267.491556,572.956445 306.574222,551.139556z" />
<GeometryDrawing Brush="#FFFFD7E7" Geometry="F1 M1024,1024z M0,0z M621.511111,113.777778C697.742222,112.839111 759.978667,187.790222 771.015111,287.118222 808.760889,273.806222 846.876444,274.204444 878.307556,291.441778 949.020445,330.211556 959.061334,439.409778 900.750222,535.352889A272.327111,272.327111,0,0,1,829.639111,613.688889C838.798222,636.558222,843.861333,661.532445,843.861333,687.672889L843.861333,711.111111A199.111111,199.111111,0,0,1,644.750222,910.222222L379.249778,910.222222A199.111111,199.111111,0,0,1,180.138667,711.111111L180.138667,687.672889C180.138667,661.504,185.201778,636.558222,194.360889,613.660444A272.099556,272.099556,0,0,1,123.249778,535.352889C64.9386670000001,439.409778 74.9795560000001,330.211556 145.692444,291.441778 177.123555,274.204445 215.239111,273.806222 253.013333,287.089778 264.021333,187.790222 326.257778,112.839111 402.488889,113.777778 444.899556,114.318222 483.640889,138.24 512,176.554667 540.359111,138.268445 579.100444,114.318223 621.511111,113.777778z" />
<GeometryDrawing Brush="#FFFB7299" Geometry="F1 M1024,1024z M0,0z M512,465.152A141.198222,141.198222,0,0,1,646.741333,564.110222L646.826667,564.366222C648.732445,570.453333,649.841778,576.597333,650.183111,582.656A132.266667,132.266667,0,0,1,640.455111,846.819556L383.544889,846.819556A132.266667,132.266667,0,0,1,373.873778,582.627556L373.674667,587.207111C373.674667,579.470222,374.869334,571.761778,377.173333,564.366222L377.258667,564.081778A141.198222,141.198222,0,0,1,512,465.180444z M420.693333,418.104889C470.954666,414.321778 506.311111,358.940445 499.740444,294.371556 493.141333,229.802667 447.089777,180.48 396.828444,184.263111 346.595555,188.017778 311.210666,243.427555 317.809778,307.996444 324.408889,372.565333 370.460445,421.859555 420.721778,418.076444z M603.306667,418.104889C653.539556,421.859556 699.591111,372.593778 706.190222,307.996444 712.789333,243.427555 677.404444,188.017777 627.171556,184.263111 576.910223,180.48 530.858667,229.774222 524.259556,294.343111 517.660445,358.912 553.045334,414.321778 603.278222,418.076444z M717.425778,551.139556C756.508445,572.956445 814.336,546.872889 846.563556,492.913778 878.819556,438.954667 873.272889,377.543111 834.190222,355.726222 795.079111,333.909333 737.251555,359.992889 705.024,413.952 672.768,467.911111 678.314667,529.322667 717.425778,551.139556z M306.574222,551.139556C345.685333,529.322667 351.232,467.911112 318.976,413.952 286.748444,359.992889 228.920889,333.909333 189.838222,355.726222 150.727111,377.543111 145.180444,438.954666 177.408,492.913778 209.664,546.872889 267.491556,572.956445 306.574222,551.139556z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.animeDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFB813A" Geometry="F1 M1024,1024z M0,0z M588.8,359.68L576.768,352.256 727.04,145.664A30.976,30.976,0,0,0,675.84,109.312L522.24,319.488 281.6,170.24A30.976,30.976,0,1,0,248.576,222.976L486.4,369.92 463.616,401.408A30.976,30.976,0,1,0,514.816,437.76L540.416,402.688 556.544,412.416A30.976,30.976,0,1,0,588.8,359.68z" />
<GeometryDrawing Brush="#FFFB813A" Geometry="F1 M1024,1024z M0,0z M763.648,850.688 M710.4,850.688A53.248,53.248,0,1,0,816.896,850.688A53.248,53.248,0,1,0,710.4,850.688z" />
<GeometryDrawing Brush="#FFFB813A" Geometry="F1 M1024,1024z M0,0z M261.12,797.44A53.248,53.248,0,1,0,314.624,850.688A53.248,53.248,0,0,0,261.12,797.44z" />
<GeometryDrawing Brush="#FFFDDE80" Geometry="F1 M1024,1024z M0,0z M141.312,314.368 M234.24,314.368L790.528,314.368Q883.456,314.368,883.456,407.296L883.456,768Q883.456,860.928,790.528,860.928L234.24,860.928Q141.312,860.928,141.312,768L141.312,407.296Q141.312,314.368,234.24,314.368z" />
<GeometryDrawing Brush="#FFFFFFFF" Geometry="F1 M1024,1024z M0,0z M520.448,575.232 M392.192,575.232A128.256,128.256,0,1,0,648.704,575.232A128.256,128.256,0,1,0,392.192,575.232z" />
<GeometryDrawing Brush="#FFFB813A" Geometry="F1 M1024,1024z M0,0z M476.928,546.56C476.928,519.68,496.128,508.928,519.168,520.96L568.832,549.632A25.6,25.6,0,0,1,568.832,598.272L519.168,626.944C496.128,640.512,476.928,629.504,476.928,602.624z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.carDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FF23ADE5" Geometry="F1 M210.688,588.8L236.288,588.8A51.2,51.2,0,0,1,287.488,634.368L301.568,762.368A51.2,51.2,0,0,1,256,819.2L225.024,819.2A51.2,51.2,0,0,1,173.824,773.632L159.744,645.632A51.2,51.2,0,0,1,204.8,588.8z M788.224,588.8L813.824,588.8A51.2,51.2,0,0,1,865.024,640A41.984,41.984,0,0,1,865.024,645.632L850.944,773.632A51.2,51.2,0,0,1,799.744,819.2L774.144,819.2A51.2,51.2,0,0,1,722.944,768A41.984,41.984,0,0,1,722.944,762.368L737.024,634.368A51.2,51.2,0,0,1,788.224,588.8z M906.496,392.96A38.656,38.656,0,0,1,880.896,441.088L855.296,448.512A38.4,38.4,0,0,1,832.768,375.04L858.368,367.616A38.144,38.144,0,0,1,906.496,392.96z M215.296,422.912A38.4,38.4,0,0,1,167.424,448.512L141.824,441.088A38.656,38.656,0,0,1,116.224,392.96A38.144,38.144,0,0,1,164.096,367.36L189.696,374.784A38.4,38.4,0,0,1,215.296,422.912z" />
<GeometryDrawing Brush="#FF48CFE5" Geometry="F1 M292.608,201.216A1109.76,1109.76,0,0,1,512,179.2A1165.568,1165.568,0,0,1,736,201.216A51.2,51.2,0,0,1,774.144,233.216L870.4,486.4 870.4,716.8A25.6,25.6,0,0,1,844.8,742.4L179.2,742.4A25.6,25.6,0,0,1,153.6,716.8L153.6,486.4 256,232.704A51.2,51.2,0,0,1,292.608,201.216z" />
<GeometryDrawing Brush="#FFFFFFFF" Geometry="F1 M204.8,512 M230.4,512L332.8,512Q358.4,512,358.4,537.6L358.4,563.2Q358.4,588.8,332.8,588.8L230.4,588.8Q204.8,588.8,204.8,563.2L204.8,537.6Q204.8,512,230.4,512z" />
<GeometryDrawing Brush="#FFFFFFFF" Geometry="F1 M665.6,512 M691.2,512L793.6,512Q819.2,512,819.2,537.6L819.2,563.2Q819.2,588.8,793.6,588.8L691.2,588.8Q665.6,588.8,665.6,563.2L665.6,537.6Q665.6,512,691.2,512z" />
<GeometryDrawing Brush="#FFFDDE80" Geometry="F1 M327.68,270.848A1000.96,1000.96,0,0,1,499.712,256A1429.248,1429.248,0,0,1,696.576,271.36A25.6,25.6,0,0,1,717.568,289.536L757.248,424.192A25.6,25.6,0,0,1,739.84,455.936A24.064,24.064,0,0,1,730.368,455.936Q605.184,443.904,499.968,443.904A1894.4,1894.4,0,0,0,295.168,455.168A25.6,25.6,0,0,1,267.008,432.384A25.6,25.6,0,0,1,267.008,422.4L307.2,288.768A25.6,25.6,0,0,1,327.68,270.848z" />
<GeometryDrawing Brush="#FF23ADE5" Geometry="F1 M614.4,358.4A102.4,102.4,0,0,0,513.536,445.184L564.736,445.184A51.2,51.2,0,0,1,663.808,450.304L715.008,454.656A102.4,102.4,0,0,0,614.4,358.4z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.cheeseDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V128 H128 V0 H0 Z">
<GeometryDrawing Brush="#FFFBC92A" Geometry="F1 M128,128z M0,0z M105.8,0C109.2,0 112.3,0.9 115.2,2.6 118.1,4.3 120.3,6.6 122,9.5 123.7,12.4 124.5,15.5 124.5,19L124.5,108.9C124.5,112.4 123.7,115.6 122,118.4 120.3,121.3 118,123.6 115.2,125.3 112.4,127 109.2,127.9 105.8,127.9L61.6,127.9C61.6,126.6 60.6,125.4 58.7,124.4 56.8,123.4 54.5,122.9 51.9,122.9 49.3,122.9 47,123.4 45.1,124.4 43.2,125.4 42.2,126.6 42.2,127.9L22.2,127.9C18.8,127.9 15.7,127 12.8,125.3 9.9,123.6 7.7,121.3 6,118.4 4.3,115.5 3.5,112.4 3.5,108.9L3.5,19.1C3.6,15.6 4.5,12.4 6.1,9.6 7.7,6.8 10,4.4 12.8,2.7 15.7,1 18.8,0.100000000000001 22.2,0.100000000000001L105.8,0.100000000000001 105.8,0z" />
<GeometryDrawing Brush="#FFFFEA85" Geometry="F1 M128,128z M0,0z M105.8,0C109.2,0 112.3,0.9 115.2,2.6 118.1,4.3 120.3,6.6 122,9.5 123.7,12.4 124.5,15.5 124.5,19L124.5,54.2C120.2,54.7 116.7,55.5 114,56.9 111.3,58.3 110,59.8 110,61.5 110,63.2 111.3,64.7 114,66.1 116.7,67.4 120.2,68.3 124.5,68.6L124.5,74.5C124.5,78 123.7,81.2 122,84 120.3,86.9 118,89.1 115.2,90.8 112.4,92.5 109.2,93.3 105.8,93.3L22.2,93.3C18.8,93.3 15.7,92.5 12.8,90.8 9.9,89.1 7.7,86.8 6,84 4.3,81.1 3.5,78 3.5,74.5L3.5,19.1C3.6,15.6 4.5,12.4 6.1,9.6 7.7,6.8 10,4.4 12.8,2.7 15.7,1 18.8,0.100000000000001 22.2,0.100000000000001L105.8,0 105.8,0z" />
<GeometryDrawing Brush="#FFFBC92A" Geometry="F1 M128,128z M0,0z M32.6,93.4C32.6,95.2 33.4,96.9 35.1,98.4 36.8,99.9 39.1,101.1 42.1,102 45.1,102.9 48.3,103.3 51.9,103.3 55.4,103.3 58.7,102.9 61.6,102 64.5,101.1 66.9,99.9 68.6,98.4 70.3,96.9 71.2,95.3 71.2,93.5 71.2,91.8 70.3,90.1 68.6,88.6 66.9,87.1 64.5,85.9 61.6,85 58.7,84.1 55.4,83.7 51.9,83.7 48.4,83.7 45.1,84.1 42.1,85 39.1,85.9 36.8,87.1 35.1,88.6 33.5,90.1 32.6,91.7 32.6,93.4L32.6,93.4z" />
<GeometryDrawing Brush="#FFF4B828" Geometry="F1 M128,128z M0,0z M18.1,113.2C18.1,115.2 18.8,116.9 20.2,118.3 21.6,119.6 23.3,120.3 25.3,120.3 27.3,120.3 29,119.6 30.4,118.3 31.9,117 32.6,115.3 32.6,113.3 32.6,111.3 31.9,109.6 30.4,108.2 28.9,106.8 27.2,106.1 25.3,106.1 23.4,106.1 21.6,106.8 20.2,108.2 18.8,109.6 18.1,111.2 18.1,113.2L18.1,113.2z" />
<GeometryDrawing Brush="#FFF4B828" Geometry="F1 M128,128z M0,0z M56.7,113.2C56.7,115.2 57.9,116.9 60.2,118.3 62.5,119.7 65.4,120.3 68.7,120.3 72,120.3 74.9,119.6 77.3,118.3 79.7,117 80.9,115.3 80.9,113.3 80.9,111.3 79.7,109.6 77.3,108.2 74.9,106.8 72,106.1 68.7,106.1 65.4,106.1 62.5,106.8 60.2,108.2 57.9,109.6 56.7,111.2 56.7,113.2L56.7,113.2z" />
<GeometryDrawing Brush="#FFF0BF4C" Geometry="F1 M128,128z M0,0z M87.9,58.2C88.8,57.3 89.9,56.9 91.2,56.9 92.5,57 93.6,57.5 94.4,58.4 95.2,59.3 95.7,60.5 95.7,61.8 95.7,63.1 95.2,64.2 94.2,65.1 89.1,70 83.2,73.4 76.5,75.1 69.8,76.8 63,76.8 56.3,75.1 49.6,73.4 43.6,70 38.4,65.1 37.5,64.2 37,63.1 37,61.8 36.9,60.5 37.4,59.4 38.3,58.4 39.2,57.4 40.3,56.9 41.6,56.9 42.9,56.8 44,57.3 44.9,58.2 48.8,62 53.4,64.6 58.6,66 63.8,67.3 69,67.3 74.2,66 79.4,64.7 83.9,62 87.9,58.2L87.9,58.2z" />
<GeometryDrawing Brush="#FFF0BF4C" Geometry="F1 M128,128z M0,0z M98.1,23.8L98.9,23.8C100.8,23.8 102.5,24.5 103.9,25.9 105.3,27.3 106,29 105.8,30.9L105.8,40.3C105.8,42.3 105.1,44 103.8,45.4 102.5,46.8 100.8,47.5 98.9,47.5L98.1,47.5C96.1,47.4 94.4,46.7 93,45.3 91.6,43.9 91,42.3 91,40.2L91,30.8C91,28.9 91.7,27.2 93.1,25.8 94.5,24.5 96.2,23.8 98.1,23.8z" />
<GeometryDrawing Brush="#FFF0BF4C" Geometry="F1 M128,128z M0,0z M33.8,23.8L34.6,23.8C36.5,23.8 38.2,24.5 39.6,25.9 41,27.3 41.7,29 41.5,30.9L41.5,40.3C41.5,42.3 40.8,44 39.5,45.4 38.2,46.8 36.5,47.5 34.6,47.5L33.8,47.5C31.8,47.4 30.1,46.7 28.7,45.3 27.4,44 26.7,42.3 26.7,40.2L26.7,30.8C26.7,28.9 27.4,27.2 28.8,25.8 30.2,24.5 31.9,23.8 33.8,23.8z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.cinephileDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FF9796ED" Geometry="F1 M1024,1024z M0,0z M147.2,201.728 M226.816,201.728L797.952,201.728Q877.568,201.728,877.568,281.344L877.568,739.584Q877.568,819.2,797.952,819.2L226.816,819.2Q147.2,819.2,147.2,739.584L147.2,281.344Q147.2,201.728,226.816,201.728z" />
<GeometryDrawing Brush="#FF7B78EA" Geometry="F1 M1024,1024z M0,0z M222.976,269.312L300.032,269.312 300.032,327.168 222.976,327.168z M390.144,269.312L467.2,269.312 467.2,327.168 390.144,327.168z M557.312,269.312L634.368,269.312 634.368,327.168 557.312,327.168z M724.48,269.312L801.536,269.312 801.536,327.168 724.48,327.168z M222.976,693.76L300.032,693.76 300.032,751.616 222.976,751.616z M390.144,693.76L467.2,693.76 467.2,751.616 390.144,751.616z M557.312,693.76L634.368,693.76 634.368,751.616 557.312,751.616z M147.2,375.296L877.568,375.296 877.568,645.376 147.2,645.376z" />
<GeometryDrawing Brush="#FFFFD043" Geometry="F1 M1024,1024z M0,0z M521.369822,529.707066 M544.721316,506.355571L547.255587,503.821301Q570.607081,480.469807,593.958576,503.821301L793.622903,703.485628Q816.974397,726.837122,793.622903,750.188617L791.088632,752.722888Q767.737138,776.074382,744.385644,752.722888L544.721316,553.05856Q521.369822,529.707066,544.721316,506.355571z" />
<GeometryDrawing Brush="#FFFFD778" Geometry="F1 M1024,1024z M0,0z M708.352,418.816L682.752,418.816 682.752,394.496A13.568,13.568,0,0,0,669.184,380.928L665.6,380.928A13.312,13.312,0,0,0,652.288,394.496L652.288,418.816 626.688,418.816A13.568,13.568,0,0,0,613.12,432.384L613.12,438.016A13.568,13.568,0,0,0,626.688,451.584L652.288,451.584 652.288,475.904A13.312,13.312,0,0,0,665.6,489.472L671.232,489.472A13.568,13.568,0,0,0,684.8,475.904L684.8,451.584 710.4,451.584A13.312,13.312,0,0,0,723.712,438.016L723.712,432.384A13.312,13.312,0,0,0,708.352,418.816z M517.888,418.816L492.288,418.816 492.288,394.496A13.312,13.312,0,0,0,478.976,380.928L473.344,380.928A13.568,13.568,0,0,0,459.776,394.496L459.776,418.816 435.2,418.816A13.312,13.312,0,0,0,421.888,432.384L421.888,438.016A13.312,13.312,0,0,0,435.2,451.584L460.8,451.584 460.8,475.904A13.568,13.568,0,0,0,474.368,489.472L480,489.472A13.312,13.312,0,0,0,493.312,475.904L493.312,451.584 518.912,451.584A13.312,13.312,0,0,0,532.224,438.016L532.224,432.384A13.312,13.312,0,0,0,517.888,418.816z M493.568,572.16L475.136,572.16 475.136,553.728A10.24,10.24,0,0,0,464.896,543.488L460.8,543.488A10.24,10.24,0,0,0,450.56,553.728L450.56,572.16 432.128,572.16A10.24,10.24,0,0,0,421.888,582.4L421.888,586.752A10.24,10.24,0,0,0,432.128,596.992L450.56,596.992 450.56,614.4A10.24,10.24,0,0,0,460.8,624.64L465.152,624.64A10.24,10.24,0,0,0,475.392,614.4L475.392,595.968 493.824,595.968A10.24,10.24,0,0,0,504.064,585.728L504.064,581.376A10.24,10.24,0,0,0,493.568,572.16z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.comicDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFDDE80" Geometry="F1 M1024,1024z M0,0z M722.204444,843.491556L170.524444,843.491556A70.144,70.144,0,0,1,100.551111,773.575111L100.551111,400.896A70.144,70.144,0,0,1,170.524444,330.951111L722.204444,330.951111A70.144,70.144,0,0,1,792.120889,400.924444L792.120889,773.546667A70.144,70.144,0,0,1,722.204444,843.491556" />
<GeometryDrawing Brush="#FF9796ED" Geometry="F1 M1024,1024z M0,0z M710.314667,341.703111C732.928,334.364444,748.515556,312.604444,746.382222,288.910222A143.616,143.616,0,0,0,739.84,256.768C700.359111,135.139556 510.72,87.722667 316.273778,150.869333 121.799111,214.016 -3.783111,363.804444 35.697778,485.461333 39.111111,495.985777 43.690667,505.912889 49.294222,515.271111 61.525333,535.694222 86.897778,544.142222 109.511111,536.803556L710.314667,341.703111z" />
<GeometryDrawing Brush="#FF7B78EB" Geometry="F1 M1024,1024z M0,0z M281.031111,123.676444L292.266667,158.293333C297.244445,173.624889 313.884445,182.072889 329.187556,177.095111 344.519112,172.117333 352.995556,155.505778 348.017778,140.174222L336.782222,105.585778A29.383111,29.383111,0,0,0,299.861333,86.784C284.501333,91.733333,276.053333,108.373333,281.031111,123.676444" />
<GeometryDrawing Brush="#FFFFAF66" Geometry="F1 M1024,1024z M0,0z M444.16,714.069333A139.747556,139.747556,0,0,0,582.456889,594.517333A17.493333,17.493333,0,0,0,565.333333,574.321778L322.986667,574.321778A17.493333,17.493333,0,0,0,305.863111,594.517333A139.776,139.776,0,0,0,444.16,714.069333" />
<GeometryDrawing Brush="#FF9796ED" Geometry="F1 M1024,1024z M0,0z M704.796444,680.903111L618.951111,640.284444C618.951111,640.284444 631.239111,696.035555 690.346667,732.956444 690.261334,733.696 690.062223,734.378666 689.976889,735.146667 677.262222,829.696 728.177778,914.545778 803.669333,924.700444 879.160889,934.826666 950.641777,866.389333 963.356444,771.84 976.042666,677.319111 925.155555,592.440889 849.635556,582.314667 789.617778,574.236445 732.216889,615.964445 704.796444,680.903111z" />
<GeometryDrawing Brush="#FFC5C2FF" Geometry="F1 M1024,1024z M0,0z M856.064,682.012444L836.266667,781.169778A6.570667,6.570667,0,0,1,829.809778,786.460444L812.032,786.460444A6.599111,6.599111,0,0,1,805.489778,778.922667L819.968,679.793778A6.542222,6.542222,0,0,1,826.453333,674.133333L849.607111,674.133333C853.788444,674.133333,856.888889,677.944889,856.064,682.012444 M833.166222,818.090667L830.179556,834.389333A6.570667,6.570667,0,0,1,823.722667,839.793778L802.759111,839.793778A6.599111,6.599111,0,0,1,796.273778,832.142222L798.919111,815.872A6.599111,6.599111,0,0,1,805.404444,810.325333L826.680889,810.325333C830.805333,810.325333,833.934222,814.051555,833.166222,818.090667" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.danceDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFC6B8A" Geometry="F1 M1024,1024z M0,0z M956.672,513.792A476.416,476.416,0,0,0,66.304,513.792L512,727.296 416.768,772.864A117.76,117.76,0,0,0,609.024,772.864L512,727.04z" />
<GeometryDrawing Brush="#FFFFFFFF" Geometry="F1 M1024,1024z M0,0z M512,727.296L720.64,627.456A222.976,222.976,0,0,0,303.872,627.456z" />
<GeometryDrawing Brush="#FFFF5C7A" Geometry="F1 M1024,1024z M0,0z M405.4528,751.5392L946.6368,492.9536 960.6656,522.2656 419.4816,780.8768z" />
<GeometryDrawing Brush="#FFF14767" Geometry="F1 M1024,1024z M0,0z M666.624,545.792L647.936,530.432 535.296,665.856 575.488,492.8 551.936,487.168 511.744,659.712 471.296,487.168 447.488,492.8 488.192,665.856 375.296,530.432 356.608,545.792 468.224,679.936 76.544,493.056 62.72,522.24 603.904,780.8 617.984,751.36 530.432,709.632 666.624,545.792z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.digitalDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFFBA7B" Geometry="F1 M1024,1024z M0,0z M298.496,284.928L316.16,233.728A36.608,36.608,0,0,1,349.44,211.712L674.816,211.712A37.12,37.12,0,0,1,709.12,233.728L726.528,284.928 815.104,284.928A69.376,69.376,0,0,1,881.664,355.584L881.664,732.928A69.12,69.12,0,0,1,813.824,803.072L209.92,803.072A69.12,69.12,0,0,1,141.568,732.928L141.568,355.584A69.376,69.376,0,0,1,209.92,284.928z" />
<GeometryDrawing Brush="#FFFB952C" Geometry="F1 M1024,1024z M0,0z M141.568,457.728L881.664,457.728 881.664,729.088A69.632,69.632,0,0,1,807.936,803.072L210.688,803.072A69.12,69.12,0,0,1,141.568,733.696z" />
<GeometryDrawing Brush="#FFFB952C" Geometry="F1 M1024,1024z M0,0z M512,358.4A197.376,197.376,0,1,1,314.624,555.776A197.632,197.632,0,0,1,512,358.4z" />
<GeometryDrawing Brush="#FFFFFFFF" Geometry="F1 M1024,1024z M0,0z M512,409.6A148.224,148.224,0,1,1,364.032,557.568A147.968,147.968,0,0,1,512,409.6z" />
<GeometryDrawing Brush="#FFFB952C" Geometry="F1 M1024,1024z M0,0z M512,457.728A98.816,98.816,0,1,1,413.44,556.288A98.56,98.56,0,0,1,512,457.728z" />
<GeometryDrawing Brush="#FFFFFFFF" Geometry="F1 M1024,1024z M0,0z M733.696,358.4L807.68,358.4A25.6,25.6,0,0,1,833.28,384A25.6,25.6,0,0,1,807.68,409.6L733.696,409.6A25.6,25.6,0,0,1,708.096,384A25.6,25.6,0,0,1,733.696,358.4z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.documentaryDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FF47CFE5" Geometry="F1 M1024,1024z M0,0z M404.9,386.765C334.0025,384.2 261.5525,398.825 208.25,424.9475 159.4025,448.91 90.62,514.4075 86.3225,560.51L821.645,560.51C818.4275,560.51 809.63,551.0825 806.9075,548.99 801.89,545.165 797.165,541.1825 792.1475,537.4475 780.245,528.5375 767.4875,520.55 755,512.4725A1040.175,1040.175,0,0,0,677.9375,466.8875C625.4675,438.9425,570.0725,416.0825,512.2475,401.885A533.88,533.88,0,0,0,404.9,386.765" />
<GeometryDrawing Brush="#FF47CFE5" Geometry="F1 M1024,1024z M0,0z M744.605,489.1625C731.8925,521.4725,607.895,525.9275,563.21,525.9275L137.8025,525.9275C122.57,525.9275 108.035,531.125 98.045,540.1925 88.145,549.17 83.9375,560.96 86.345,572.5475 86.345,572.66 86.345,572.8175 86.435,572.885 95.7275,616.5575 122.165,656.225 162.8,687.5675 164.42,688.8275 166.0625,690.0875 167.7275,691.3025 274.4675,769.76 460.25,772.46 591.1775,735.1775 632.6225,723.3875 672.0425,707.0075 706.355,685.5425 745.3475,661.1525 785.15,628.235 808.6625,593.81 812.1275,588.7475 849.8825,532.6325 850.625,532.925L744.605,489.1625z" />
<GeometryDrawing Brush="#FF2BBAE4" Geometry="F1 M1024,1024z M0,0z M918.0575,505.3175L888.1775,488.24A75.0825,75.0825,0,0,0,818.0675,486.1025A75.375,75.375,0,0,0,780.65,426.7475L750.725,409.67A11.4525,11.4525,0,0,0,735.065,413.945L727.235,427.6475A59.0625,59.0625,0,0,0,749.195,508.22L764.99,517.265A0.045,0.045,0,0,1,764.945,517.31L816.425,546.74 816.47,546.695 833.93,556.685A59.085,59.085,0,0,0,914.5025,534.7475L922.3325,521.0225A11.5425,11.5425,0,0,0,918.0575,505.3175" />
<GeometryDrawing Brush="#FFE5E6E6" Geometry="F1 M1024,1024z M0,0z M654.515,712.4975C351.3275,720.8675,266.3,564.425,266.3,564.425L85.7825,564.425A31.995,31.995,0,0,0,86.4125,572.885C95.705,616.5575 122.1425,656.225 162.7775,687.5675 164.3975,688.85 166.04,690.0875 167.705,691.3025 274.4225,769.76 460.205,772.4825 591.1325,735.1775A509.6925,509.6925,0,0,0,654.515,712.4975" />
<GeometryDrawing Brush="#FFE4E5E4" Geometry="F1 M1024,1024z M0,0z M654.515,712.4975C589.355,714.2975 534.365,708.0875 487.9475,698.255 438.9425,687.8825 461.78,757.565 484.73,755.045 522.215,750.9725 558.395,744.4475 591.1325,735.1325A502.3575,502.3575,0,0,0,654.515,712.4975" />
<GeometryDrawing Brush="#FF47CFE5" Geometry="F1 M1024,1024z M0,0z M407.1275,674.9225C428.705,744.7625 476.8325,792.575 523.9025,788.57 527.6375,788.2325 530.135,784.4975 529.415,780.83L504.98,655.2125A5.715,5.715,0,0,0,498.2975,650.7125L411.5825,667.61A5.7825,5.7825,0,0,0,407.1275,674.9225" />
<GeometryDrawing Brush="#FF0099BC" Geometry="F1 M1024,1024z M0,0z M441.2375,614.7125A29.295,29.295,0,1,1,382.625,614.735A29.295,29.295,0,0,1,441.2375,614.7125" />
<GeometryDrawing Brush="#FF47CFE5" Geometry="F1 M1024,1024z M0,0z M252.5975,310.4675A64.2825,64.2825,0,0,1,316.9025,246.365C335.7125,246.365,352.6325,254.4875,364.4225,267.4925A64.17,64.17,0,0,1,476.135,310.4675A16.56,16.56,0,0,1,459.5525,327.05A16.56,16.56,0,0,1,442.9475,310.4675A31.05,31.05,0,0,0,380.96,308.3075L380.78,308.3075 380.8925,385.775A16.5825,16.5825,0,1,1,347.705,385.775L347.705,310.3775C347.705,293.345,333.7775,279.44,316.745,279.44A31.05,31.05,0,0,0,285.7175,310.4675A16.56,16.56,0,1,1,252.5975,310.4675" />
<GeometryDrawing Brush="#FF47CFE5" Geometry="F1 M1024,1024z M0,0z M364.3325,408.0275A22.2525,22.2525,0,0,1,342.125,385.7975L342.125,310.4A25.3575,25.3575,0,1,0,291.41,310.49A22.23,22.23,0,0,1,246.995,310.49C246.995,272.0375,278.36,240.74,316.9025,240.74A69.75,69.75,0,0,1,364.4225,259.505A70.2,70.2,0,0,1,412.0325,240.74C450.485,240.74,481.7825,272.0375,481.7825,310.49A22.23,22.23,0,0,1,437.345,310.49A25.425,25.425,0,0,0,386.6075,308.7125L386.45,311.0975 386.54,385.7975A22.2525,22.2525,0,0,1,364.3325,408.0275z M316.79,273.8375C336.95,273.8375,353.3525,290.24,353.3525,310.4L353.3525,385.82A10.98,10.98,0,1,0,375.2675,385.82L375.1775,302.7275 376.1,302.7275A36.7425,36.7425,0,0,1,411.92,273.86C432.125,273.86,448.5725,290.3075,448.5725,310.5125A10.98,10.98,0,0,0,470.51,310.5125C470.51,278.2475 444.275,252.0125 412.01,252.0125 395.5625,252.0125 379.7225,259.0325 368.5625,271.3175L364.4,275.8625 360.2375,271.25A58.635,58.635,0,0,0,316.9025,251.9675A58.635,58.635,0,0,0,258.245,310.4675A10.9575,10.9575,0,0,0,280.16,310.4675A36.675,36.675,0,0,1,316.79,273.8375z" />
<GeometryDrawing Brush="#FF0099BC" Geometry="F1 M1024,1024z M0,0z M389.87,621.2825L323.54,621.2825A47.79,47.79,0,0,1,288.5075,605.69L264.7925,579.995A28.575,28.575,0,0,0,243.9125,570.7025L91.0475,570.7025A6.525,6.525,0,1,1,91.0475,557.6075L243.935,557.6075C255.3875,557.6075,266.5025,562.535,274.4225,571.13L298.1375,596.8475C304.7975,604.0475,314.0675,608.1875,323.5625,608.1875L389.8925,608.1875A6.525,6.525,0,1,1,389.87,621.2825" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.dougaDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FF7B78EB" Geometry="F1 M1024,1024z M0,0z M273.408,166.912L751.104,166.912C809.472,166.912,857.088,214.528,857.088,272.896L857.088,750.592C857.088,808.96,809.472,856.576,751.104,856.576L273.408,856.576C215.04,856.576,167.424,808.96,167.424,750.592L167.424,273.408C166.912,215.04,215.04,166.912,273.408,166.912z" />
<GeometryDrawing Brush="#FF9796ED" Geometry="F1 M1024,1024z M0,0z M512,525.312L512,624.128C545.28,609.28 584.704,624.64 599.552,657.92 614.4,691.2 599.04,730.624 565.76,745.472 548.864,753.152 529.92,753.152 512.512,745.472L512.512,857.088 273.408,857.088C215.04,857.088,167.424,809.472,167.424,751.104L167.424,512 304.64,512C283.136,531.456 280.576,565.248 300.032,586.752 319.488,608.256 353.28,610.816 374.784,591.36 396.288,572.416 398.848,538.112 379.392,516.608L374.784,512 512,512 512,471.04C507.904,471.552 502.784,471.552 498.688,471.04 447.488,471.04 412.672,423.424 412.672,365.056 412.672,306.688 433.664,257.024 498.688,257.024L512,257.024 512,166.912 750.592,166.912C808.96,166.912,856.576,214.528,856.576,272.896L856.576,524.8 735.744,524.8C756.736,501.248 755.2,465.408 732.16,443.904 708.608,422.912 672.768,424.448 651.264,447.488 631.296,468.992 631.296,502.784 651.264,524.288L512,524.288z" />
<GeometryDrawing Brush="#FF6A68C6" Geometry="F1 M1024,1024z M0,0z M512,525.312L512,624.128 525.312,620.032C561.152,612.352 598.016,635.904 605.184,672.256 612.864,708.096 586.752,744.448 550.912,751.104 546.816,752.128 542.208,752.128 537.6,752.128 528.384,752.128 521.216,749.056 512.512,745.984L512.512,857.6 498.176,857.6 498.176,724.992 516.608,733.184C543.744,744.96 574.976,732.672 586.752,705.536 598.528,678.4 586.24,647.168 559.104,635.392 545.792,629.76 530.432,629.76 516.608,635.392L498.176,643.584 498.176,525.824 399.872,525.824C414.72,559.104 399.36,598.528 366.08,613.376 332.8,628.224 293.376,612.864 278.528,579.584 270.848,562.688 270.848,543.744 278.528,526.336L166.912,526.336 166.912,512 304.128,512C282.624,531.456 280.064,565.248 299.52,586.752 318.976,608.256 352.768,610.816 374.272,591.36 395.776,571.904 398.336,538.112 378.88,516.608L374.272,512 512,512 512,472.064 498.688,472.064C447.488,472.064 412.672,424.96 412.672,366.08 412.672,307.2 433.664,256.512 498.688,256.512L512,256.512 512,166.912 525.312,166.912 525.312,272.896 498.688,272.896C449.024,272.896 425.472,306.176 425.472,367.104 425.472,420.352 456.192,459.776 498.688,459.776 502.272,460.288 506.368,460.288 509.952,459.776L525.312,457.728 525.312,512 628.224,512C614.4,476.16 632.32,435.2 668.672,421.376 704.512,407.552 745.472,425.472 759.296,461.824 765.44,477.696 765.44,495.616 759.296,512L857.088,512 857.088,525.312 736.256,525.312C757.248,501.76 755.712,465.92 732.672,444.416 709.12,423.424 673.28,424.96 651.776,448 631.808,469.504 631.808,503.296 651.776,524.8L512,524.8z" />
<GeometryDrawing Brush="#FFFDDE80" Geometry="F1 M1024,1024z M0,0z M444.928,693.248C421.888,706.56 392.704,698.368 379.904,675.84 375.808,668.16 373.76,660.48 373.76,651.776L373.76,392.192C373.76,365.568 394.752,344.576 421.376,344.576 430.08,344.576 438.272,346.624 445.952,351.232L667.648,483.84C690.688,497.152 697.856,526.336 684.544,548.864 680.448,555.52 674.304,561.664 667.648,565.76" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.entDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFF8693" Geometry="F1 M1024,1024z M0,0z M534.442796,378.982175 M570.646663,415.186042L601.238931,445.77831Q637.442798,481.982177,601.238931,518.186044L240.648413,878.776562Q204.444546,914.980429,168.240679,878.776562L137.648411,848.184294Q101.444544,811.980427,137.648411,775.776559L498.238929,415.186042Q534.442796,378.982175,570.646663,415.186042z" />
<GeometryDrawing Brush="#FFFC6376" Geometry="F1 M1024,1024z M0,0z M369.92,543.744L507.392,406.272A38.912,38.912,0,0,1,561.92,406.272L610.304,454.912A38.4,38.4,0,0,1,610.304,509.44L472.32,647.424z" />
<GeometryDrawing Brush="#FFFFA9B1" Geometry="F1 M1024,1024z M0,0z M286.133941,631.021801 M298.988557,643.871931L371.589979,716.448014Q384.444595,729.298143,371.594465,742.15276L369.965575,743.782218Q357.115446,756.636834,344.26083,743.786704L271.659408,671.210621Q258.804792,658.360492,271.654922,645.505876L273.283812,643.876417Q286.133941,631.021801,298.988557,643.871931z" />
<GeometryDrawing Brush="#FFFDDE80" Geometry="F1 M1024,1024z M0,0z M737.024,547.584A99.328,99.328,0,0,1,799.744,484.864L850.944,471.296A27.136,27.136,0,0,0,864,421.632L826.624,384A98.816,98.816,0,0,1,803.84,298.24L820.736,235.008C827.904,207.872,811.776,191.488,784.64,198.912L721.408,215.808A98.816,98.816,0,0,1,635.648,192.768L598.272,155.904A27.136,27.136,0,0,0,548.864,169.216L535.04,220.416A97.792,97.792,0,0,1,472.576,283.136L421.376,296.96A27.136,27.136,0,0,0,408.064,346.368L445.44,384A97.536,97.536,0,0,1,468.48,469.504L451.584,532.736C444.16,560.128,460.544,576.256,487.68,569.088L550.912,552.192A97.792,97.792,0,0,1,636.672,574.976L674.048,612.352A26.88,26.88,0,0,0,723.456,599.04z" />
<GeometryDrawing Brush="#FFFCC029" Geometry="F1 M1024,1024z M0,0z M886.272,417.536L811.52,342.528 841.984,228.096A41.216,41.216,0,0,0,833.28,186.624A41.728,41.728,0,0,0,791.808,179.2L677.376,209.92 602.624,133.888A41.728,41.728,0,0,0,563.2,120.576A41.216,41.216,0,0,0,534.784,152.064L507.392,254.464 404.48,281.6A42.24,42.24,0,0,0,372.736,309.76A42.24,42.24,0,0,0,386.048,350.208L460.8,425.216 430.08,539.648A41.728,41.728,0,0,0,439.04,581.12A37.888,37.888,0,0,0,466.432,591.872A56.832,56.832,0,0,0,480.512,589.824L594.944,559.104 669.696,634.112A45.824,45.824,0,0,0,700.928,648.448A34.304,34.304,0,0,0,709.888,648.448A41.216,41.216,0,0,0,738.304,616.96L765.696,514.56 868.096,487.168A41.984,41.984,0,0,0,899.584,458.752A40.96,40.96,0,0,0,886.272,417.536z M801.536,214.016L806.656,214.016A16.896,16.896,0,0,1,806.656,219.136L781.056,312.832 708.096,239.104z M769.536,353.792L734.976,481.792 606.976,516.352 504.576,413.952 539.136,285.952 667.136,251.392z M570.112,161.792C570.112,159.232,571.904,157.696,571.904,157.184A9.984,9.984,0,0,1,576,160.256L635.648,219.904 548.352,243.2z M412.416,323.84L409.6,320A12.8,12.8,0,0,1,414.464,317.952L495.616,296.192 472.064,384z M470.784,554.24A18.944,18.944,0,0,1,465.664,554.24A17.92,17.92,0,0,1,465.664,549.12L491.264,455.424 563.2,528.64z M701.184,605.44C701.184,608.256,699.648,609.536,699.648,610.304A20.992,20.992,0,0,1,695.296,606.976L635.904,547.584 723.2,524.032z M857.344,449.28L776.192,471.04 799.488,384 858.88,443.392A40.96,40.96,0,0,1,862.208,447.232A12.8,12.8,0,0,1,858.112,449.792z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.fashionDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFF6A9B" Geometry="F1 M1024,1024z M0,0z M691.2,204.8A44.032,44.032,0,0,1,721.152,238.848A117.76,117.76,0,0,1,708.096,315.648C708.096,315.648,688.896,345.6,683.776,355.584A235.008,235.008,0,0,0,658.176,462.592L658.176,503.296 365.312,503.296 365.312,463.872A235.008,235.008,0,0,0,339.712,356.864C334.592,346.88,315.392,316.928,315.392,316.928A117.76,117.76,0,0,1,302.336,240.128A44.544,44.544,0,0,1,336.896,204.8L336.896,147.712A29.952,29.952,0,0,1,364.032,115.968A29.952,29.952,0,0,1,391.68,147.712L391.68,221.44A237.056,237.056,0,0,0,512,253.952A241.408,241.408,0,0,0,637.184,218.88L637.184,147.712A27.136,27.136,0,1,1,690.944,147.712z" />
<GeometryDrawing Brush="#FFFF9DC6" Geometry="F1 M1024,1024z M0,0z M658.432,487.936L365.312,487.936 204.8,780.288A36.352,36.352,0,0,0,215.04,826.88A492.288,492.288,0,0,0,810.496,826.88A36.608,36.608,0,0,0,819.2,779.52z" />
<GeometryDrawing Brush="#FFFF6A9B" Geometry="F1 M1024,1024z M0,0z M409.6,537.6A9.984,9.984,0,0,0,396.032,542.208L271.872,792.832A10.496,10.496,0,0,0,276.48,806.4A14.848,14.848,0,0,0,281.088,806.4A9.984,9.984,0,0,0,290.048,800.768L414.208,549.888A10.24,10.24,0,0,0,409.6,537.6z M455.936,643.072A9.984,9.984,0,0,0,443.904,650.496L403.456,821.248A10.24,10.24,0,0,0,410.88,833.536L413.184,833.536A9.728,9.728,0,0,0,422.912,825.6L463.36,654.848A9.984,9.984,0,0,0,455.936,643.072z M750.848,791.808L626.688,541.184A9.984,9.984,0,0,0,614.4,537.6A10.24,10.24,0,0,0,609.792,550.912L733.952,801.792A9.984,9.984,0,0,0,742.912,807.424A14.848,14.848,0,0,0,747.52,807.424A10.496,10.496,0,0,0,750.848,791.808z M579.84,650.496A9.984,9.984,0,0,0,560.384,655.104L600.832,825.856A9.728,9.728,0,0,0,610.56,833.792L612.864,833.792A10.24,10.24,0,0,0,620.288,821.504z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.foodDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<DrawingGroup.Transform>
<TranslateTransform X="0" Y="1.4210854715202004E-14" />
</DrawingGroup.Transform>
<GeometryDrawing Brush="#FFFA942D" Geometry="F1 M1024,1024z M0,0z M192.075294,503.883294 M116.781176,503.883294A75.294118,75.294118,0,1,0,267.369412,503.883294A75.294118,75.294118,0,1,0,116.781176,503.883294z" />
<GeometryDrawing Brush="#FFFA942D" Geometry="F1 M1024,1024z M0,0z M342.663529,411.211294 M267.369412,411.211294A75.294118,75.294118,0,1,0,417.957647,411.211294A75.294118,75.294118,0,1,0,267.369412,411.211294z" />
<GeometryDrawing Brush="#FFFE5D79" Geometry="F1 M1024,1024z M0,0z M284.747294,480.722824 M209.453176,480.722824A75.294118,75.294118,0,1,0,360.041412,480.722824A75.294118,75.294118,0,1,0,209.453176,480.722824z" />
<GeometryDrawing Brush="#FFFA942D" Geometry="F1 M1024,1024z M0,0z M765.470118,532.841412 M638.042353,532.841412A127.427765,127.427765,0,1,0,892.897882,532.841412A127.427765,127.427765,0,1,0,638.042353,532.841412z" />
<GeometryDrawing Brush="#FFFA942D" Geometry="F1 M1024,1024z M0,0z M632.259765,457.547294 M499.049412,457.547294A133.210353,133.210353,0,1,0,765.470118,457.547294A133.210353,133.210353,0,1,0,499.049412,457.547294z" />
<GeometryDrawing Brush="#FFFE5D79" Geometry="F1 M1024,1024z M0,0z M672.798118,556.016941 M522.209882,556.016941A150.588235,150.588235,0,1,0,823.386353,556.016941A150.588235,150.588235,0,1,0,522.209882,556.016941z" />
<GeometryDrawing Brush="#FFFDDC7A" Geometry="F1 M1024,1024z M0,0z M932.291765,474.925176A28.762353,28.762353,0,0,1,961.039059,503.687529L960.993882,505.042824 960.903529,506.398118C946.597647,657.317647,830.298353,779.264,680.161882,805.586824L700.340706,886.332235A23.160471,23.160471,0,0,1,677.872941,915.109647L343.371294,915.109647A23.160471,23.160471,0,0,1,320.903529,886.332235L341.082353,805.586824C192.813176,779.595294,77.552941,660.329412,60.928,512.015059L60.370824,506.639059A28.958118,28.958118,0,0,1,89.193412,474.925176L932.276706,474.925176z" />
<GeometryDrawing Brush="#FFF6C338" Geometry="F1 M1024,1024z M0,0z M442.548706,196.924235L578.695529,196.924235C599.958588,196.924235,618.496,211.380706,623.646118,232.011294L684.378353,474.925176 336.865882,474.925176 397.598118,232.026353A46.336,46.336,0,0,1,442.548706,196.924235z" />
<GeometryDrawing Brush="#FFC6D2E1" Geometry="F1 M1024,1024z M0,0z M688.037647,192.903529C697.479529,162.725647 716.423529,163.493647 722.718118,145.317647 729.780706,124.867765 732.084706,99.599059 729.645176,69.496471 746.496,87.43153 755.621647,106.511059 760.591059,131.779765 765.485177,156.717177 751.465412,175.962353 731.527529,206.260706 711.604705,236.574118 722.718117,273.874824 731.527529,301.176471 714.676705,283.256471 671.623529,245.398589 688.052706,192.903529z M283.361882,154.247529C294.686117,116.540235 317.424941,117.473882 324.969412,94.765176 333.462588,69.210352 336.233412,37.632 333.281882,-1.4210854715202E-14 353.520941,22.407529 364.483764,46.260706 370.447059,77.854118 376.32,109.025883 359.499294,133.074824 335.570824,170.962824 311.627295,208.835765 324.969412,255.442824 335.570824,289.596235 315.331765,267.173647 263.634824,219.873882 283.361882,154.247529z" />
<GeometryDrawing Brush="#FFF5BC20" Geometry="F1 M1024,1024z M0,0z M510.629647,706.605176A92.672,92.672,0,0,1,603.301647,799.277176L603.301647,915.109647 417.957647,915.109647 417.957647,799.277176A92.672,92.672,0,0,1,510.629647,706.605176z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.gameDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FF58D598" Geometry="F1 M1024,1024z M0,0z M166.4,166.144 M256.512,166.144L767.488,166.144Q857.6,166.144,857.6,256.256L857.6,767.232Q857.6,857.344,767.488,857.344L256.512,857.344Q166.4,857.344,166.4,767.232L166.4,256.256Q166.4,166.144,256.512,166.144z" />
<GeometryDrawing Brush="#FF17AD8A" Geometry="F1 M1024,1024z M0,0z M307.2,325.632L443.648,325.632 443.648,462.08 307.2,462.08z M580.096,325.632L716.544,325.632 716.544,462.08 580.096,462.08z" />
<GeometryDrawing Brush="#FF17AD8A" Geometry="F1 M1024,1024z M0,0z M443.648,462.336L443.648,538.112 379.392,538.112 379.392,742.656 438.784,742.656 438.784,674.56 585.216,674.56 585.216,742.656 644.352,742.656 644.352,538.112 580.096,538.112 580.096,462.336 443.648,462.336z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.guochuangDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FF58D598" Geometry="F1 M1024,1024z M0,0z M873.472,321.792C827.392,275.2,771.072,248.32,711.936,281.6A177.152,177.152,0,0,0,660.736,120.064C660.736,120.064 577.28,227.584 645.632,339.712 633.344,353.28 621.312,366.848 609.28,379.136 582.4,406.272 623.872,448.256 650.496,421.12L719.104,351.488C759.808,310.528 795.904,327.68 832,363.776 858.624,390.656 900.096,348.672 873.472,321.792z" />
<GeometryDrawing Brush="#FFFF5C7A" Geometry="F1 M1024,1024z M0,0z M705.024,344.576A189.696,189.696,0,0,0,434.176,344.576A195.072,195.072,0,0,0,392.96,407.04A249.088,249.088,0,0,0,215.296,481.536A256,256,0,0,0,215.296,841.216A248.576,248.576,0,0,0,570.112,841.216A256,256,0,0,0,643.584,662.016A190.976,190.976,0,0,0,705.024,620.288A195.84,195.84,0,0,0,705.024,344.576z" />
<GeometryDrawing Brush="#FFF14767" Geometry="F1 M1024,1024z M0,0z M514.304,808.704A187.136,187.136,0,0,1,247.04,803.584A193.536,193.536,0,0,1,252.16,532.48C252.16,532.48,207.104,653.312,295.936,746.752A210.176,210.176,0,0,0,514.304,808.704" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.informationDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FF7DD3E0" Geometry="F1 M1024,1024z M0,0z M760.685714,768A21.942857,21.942857,0,0,0,780.522057,789.840457L782.628571,789.942857A21.942857,21.942857,0,0,0,804.469029,770.106514L804.571429,768 804.571429,321.828571 833.828571,321.828571A58.514286,58.514286,0,0,1,892.342857,380.342857L892.342857,819.2A58.514286,58.514286,0,0,1,833.828571,877.714286L190.171429,877.714286A58.514286,58.514286,0,0,1,131.657143,819.2L131.657143,204.8A58.514286,58.514286,0,0,1,190.171429,146.285714L702.171429,146.285714A58.514286,58.514286,0,0,1,760.685714,204.8L760.685714,768z" />
<GeometryDrawing Brush="#FF3DA9D3" Geometry="F1 M1024,1024z M0,0z M219.428571,234.057143 M248.685714,234.057143L643.657143,234.057143Q672.914286,234.057143,672.914286,263.314286L672.914286,526.628571Q672.914286,555.885714,643.657143,555.885714L248.685714,555.885714Q219.428571,555.885714,219.428571,526.628571L219.428571,263.314286Q219.428571,234.057143,248.685714,234.057143z" />
<GeometryDrawing Brush="#FFFFD469" Geometry="F1 M1024,1024z M0,0z M404.772571,300.514743L534.235429,381.44A15.945143,15.945143,0,0,1,534.235429,408.502857L404.772571,489.428114A15.945143,15.945143,0,0,1,380.342857,475.896686L380.342857,314.046171A15.945143,15.945143,0,0,1,404.772571,300.514743z" />
<GeometryDrawing Brush="#FF3DA9D3" Geometry="F1 M1024,1024z M0,0z M219.428571,614.4 M248.685714,614.4L643.657143,614.4Q672.914286,614.4,672.914286,643.657143L672.914286,643.657143Q672.914286,672.914286,643.657143,672.914286L248.685714,672.914286Q219.428571,672.914286,219.428571,643.657143L219.428571,643.657143Q219.428571,614.4,248.685714,614.4z" />
<GeometryDrawing Brush="#FF3DA9D3" Geometry="F1 M1024,1024z M0,0z M219.428571,731.428571 M248.685714,731.428571L468.114286,731.428571Q497.371429,731.428571,497.371429,760.685714L497.371429,760.685714Q497.371429,789.942857,468.114286,789.942857L248.685714,789.942857Q219.428571,789.942857,219.428571,760.685714L219.428571,760.685714Q219.428571,731.428571,248.685714,731.428571z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.kichikuDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFC6B8A" Geometry="F1 M1024,1024z M0,0z M918.784,510.208A187.904,187.904,0,0,0,829.952,350.72A156.416,156.416,0,0,0,831.744,328.704A150.784,150.784,0,0,0,620.8,190.208A151.04,151.04,0,0,0,404.48,190.208A150.784,150.784,0,0,0,193.536,328.704A156.416,156.416,0,0,0,195.328,350.72A187.648,187.648,0,0,0,181.504,660.224L181.504,661.76A215.296,215.296,0,0,0,514.304,840.96A215.04,215.04,0,0,0,847.104,661.76L847.104,659.2A187.904,187.904,0,0,0,918.784,510.208z" />
<GeometryDrawing Brush="#FFFFFFFF" Geometry="F1 M1024,1024z M0,0z M680.704,479.744A150.528,150.528,0,0,1,572.672,435.2A150.016,150.016,0,0,1,452.608,435.2A150.528,150.528,0,0,1,344.576,481.024L333.312,481.024 333.312,648.192A166.4,166.4,0,0,0,499.2,814.08L532.736,814.08A166.4,166.4,0,0,0,698.624,648.192L698.624,478.464A137.216,137.216,0,0,1,680.704,479.744z" />
<GeometryDrawing Brush="#FFE2006C" Geometry="F1 M1024,1024z M0,0z M510.464,651.264 M476.928,651.264A33.536,33.536,0,1,0,544,651.264A33.536,33.536,0,1,0,476.928,651.264z" />
<GeometryDrawing Brush="#FFFF5C7A" Geometry="F1 M1024,1024z M0,0z M635.904,554.496L614.4,554.496 614.4,532.992A12.032,12.032,0,0,0,602.624,521.216L597.76,521.216A12.032,12.032,0,0,0,585.984,532.992L585.984,554.496 564.736,554.496A11.776,11.776,0,0,0,552.96,566.016L552.96,571.136A11.776,11.776,0,0,0,564.736,582.656L585.984,582.656 585.984,604.16A12.032,12.032,0,0,0,597.76,615.936L602.624,615.936A12.032,12.032,0,0,0,614.4,604.16L614.4,582.656 635.648,582.656A11.776,11.776,0,0,0,647.424,571.136L647.424,566.016A11.776,11.776,0,0,0,635.904,554.496z M455.936,554.496L435.2,554.496 435.2,532.992A12.032,12.032,0,0,0,423.424,521.216L418.56,521.216A12.032,12.032,0,0,0,406.784,532.992L406.784,554.496 384,554.496A11.776,11.776,0,0,0,372.224,566.016L372.224,571.136A11.776,11.776,0,0,0,384,582.656L405.248,582.656 405.248,604.16A12.032,12.032,0,0,0,417.024,615.936L421.888,615.936A12.032,12.032,0,0,0,435.2,604.16L435.2,582.656 456.448,582.656A11.52,11.52,0,0,0,468.224,571.136L468.224,566.016A11.52,11.52,0,0,0,455.936,554.496z" />
<GeometryDrawing Brush="#FFEB53A8" Geometry="F1 M1024,1024z M0,0z M600.32,651.008A12.288,12.288,0,0,0,588.032,663.552C588.032,697.6 553.216,725.248 511.232,725.248 469.248,725.248 434.432,697.6 434.432,663.552A12.544,12.544,0,1,0,408.832,663.552C408.832,711.168 454.656,750.08 511.232,750.08 567.808,750.08 613.632,711.168 613.632,663.552A12.544,12.544,0,0,0,600.32,651.008z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.lifeDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFFD778" Geometry="F1 M1024,1024z M0,0z M881.408,664.064L881.408,504.32A168.192,168.192,0,0,0,753.408,341.76L745.472,339.968 745.472,484.864A12.288,12.288,0,0,1,730.88,496.64A170.752,170.752,0,0,0,700.416,493.824L561.664,493.824 561.664,466.176A37.632,37.632,0,0,1,573.44,438.528A175.872,175.872,0,0,0,631.296,302.848A179.2,179.2,0,0,0,460.8,132.352A175.872,175.872,0,0,0,279.808,308.48L279.808,409.6 312.064,409.6A225.536,225.536,0,0,0,327.936,428.8A36.608,36.608,0,0,1,337.408,454.4L337.408,496.896A193.792,193.792,0,0,0,179.2,712.96A197.12,197.12,0,0,0,376.32,879.616L701.44,879.616A148.48,148.48,0,0,0,747.008,873.472A217.088,217.088,0,0,0,811.264,841.728A176.896,176.896,0,0,0,829.44,826.112L834.048,821.76A156.16,156.16,0,0,0,881.408,709.888L881.408,674.048C881.92,670.976,881.664,667.392,881.408,664.064z" />
<GeometryDrawing Brush="#FFFB813A" Geometry="F1 M1024,1024z M0,0z M468.736,238.592A40.192,40.192,0,1,0,508.928,278.784A40.192,40.192,0,0,0,468.736,238.592z M323.584,362.752L217.6,362.752A34.816,34.816,0,1,0,217.6,432.128L323.84,432.128A34.816,34.816,0,1,0,323.84,362.752z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.movieDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFE5E6E6" Geometry="F1 M1024,1024z M0,0z M954.624,452.864L919.04,452.864 919.04,283.904A37.376,37.376,0,0,0,893.44,247.296A36.608,36.608,0,0,0,846.848,281.6L846.848,451.84 199.936,451.84 199.936,282.88A37.632,37.632,0,0,0,174.336,246.272A36.352,36.352,0,0,0,128,281.6L128,451.84 92.16,451.84A15.616,15.616,0,0,0,76.8,467.712L76.8,550.4A15.36,15.36,0,0,0,92.16,566.016L119.04,566.016 119.04,651.264A135.68,135.68,0,0,0,253.44,787.456L367.872,787.456A135.68,135.68,0,0,0,502.272,651.264L502.272,630.272A7.936,7.936,0,0,1,509.952,622.336L535.552,622.336A7.68,7.68,0,0,1,543.232,630.272L543.232,651.264A135.936,135.936,0,0,0,677.632,787.456L793.6,787.456A135.68,135.68,0,0,0,928,651.264L928,566.016 953.6,566.016A15.36,15.36,0,0,0,968.96,550.4L968.96,468.736A15.616,15.616,0,0,0,953.6,452.864" />
<GeometryDrawing Brush="#FFFF5C7A" Geometry="F1 M1024,1024z M0,0z M361.216,727.552L258.816,727.552A87.296,87.296,0,0,1,172.8,640L172.8,560.128A61.184,61.184,0,0,1,233.216,498.688L386.816,498.688A61.184,61.184,0,0,1,447.232,560.128L447.232,640A87.296,87.296,0,0,1,360.704,727.552" />
<GeometryDrawing Brush="#FF2CBAE5" Geometry="F1 M1024,1024z M0,0z M685.568,727.552L787.968,727.552A87.296,87.296,0,0,0,873.984,640L873.984,560.128A61.184,61.184,0,0,0,813.568,498.688L659.968,498.688A61.184,61.184,0,0,0,599.552,560.128L599.552,640A87.296,87.296,0,0,0,686.08,727.552" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.musicDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FF45C7DD" Geometry="F1 M1024,1024z M0,0z M881.92,460.8A335.36,335.36,0,0,0,547.584,125.696L474.368,125.696A335.616,335.616,0,0,0,139.776,460.8L139.776,774.4A18.688,18.688,0,0,0,158.208,793.088L200.192,793.088C213.76,839.424,238.08,873.472,288.768,873.472L387.072,873.472A37.376,37.376,0,0,0,424.448,836.608L425.728,551.936A36.864,36.864,0,0,0,388.608,514.816L288.768,514.816A111.616,111.616,0,0,0,237.568,527.616L237.568,454.4A242.432,242.432,0,0,1,479.232,212.736L546.56,212.736A242.176,242.176,0,0,1,787.968,454.4L787.968,528.896A110.592,110.592,0,0,0,733.696,514.816L633.856,514.816A36.864,36.864,0,0,0,596.736,551.936L596.736,836.608A37.376,37.376,0,0,0,634.112,873.472L732.416,873.472C783.616,873.472,807.424,839.424,820.992,793.088L862.976,793.088A18.688,18.688,0,0,0,881.408,774.4z" />
<GeometryDrawing Brush="#FFFF5C7A" Geometry="F1 M1024,1024z M0,0z M646.141043,825.220963 M646.186439,792.708994L646.46024,596.613185Q646.505635,564.101217,679.017604,564.146612L680.041603,564.148042Q712.553571,564.193437,712.508176,596.705406L712.234374,792.801215Q712.188979,825.313183,679.677011,825.267788L678.653012,825.266358Q646.141044,825.220963,646.186439,792.708994z" />
<GeometryDrawing Brush="#FFFF5C7A" Geometry="F1 M1024,1024z M0,0z M307.222608,825.246563 M307.268003,792.734594L307.541804,596.638785Q307.587199,564.126817,340.099168,564.172212L341.123167,564.173642Q373.635135,564.219037,373.58974,596.731006L373.315939,792.826815Q373.270544,825.338783,340.758575,825.293388L339.734576,825.291958Q307.222608,825.246563,307.268003,792.734594z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.sportsDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FF1BAD8B" Geometry="F1 M1024,1024z M0,0z M497.8944,517.8624L521.7792,547.1232A58.5728,58.5728,0,0,1,516.1728,627.1744L241.9456,880.7424A47.7184,47.7184,0,0,1,176.3328,879.9744A49.8176,49.8176,0,0,1,172.032,813.1584L280.6016,676.7872 406.7072,518.4256A58.5728,58.5728,0,0,1,497.8944,517.8624z" />
<GeometryDrawing Brush="#FF57D59A" Geometry="F1 M1024,1024z M0,0z M698.9312,153.6A117.1456,117.1456,0,0,1,710.3488,387.328L770.7648,433.2288C775.1168,436.5568,780.928,437.1456,785.8688,434.816L859.4944,400.1792A46.2848,46.2848,0,0,1,918.6048,417.7664A44.3392,44.3392,0,0,1,906.6752,477.0816L780.7232,567.3472A58.5728,58.5728,0,0,1,714.7776,568.9088L648.7296,526.1568 604.5952,573.9264 675.2,657.2544C676.864,659.2,678.4,661.2736,679.808,663.4496L681.7536,666.752A58.5728,58.5728,0,0,1,658.8928,746.368L466.7904,852.7104A49.3824,49.3824,0,0,1,401.0496,835.712A52.096,52.096,0,0,1,412.9536,767.1296L518.5024,683.9552 412.2112,615.6544 410.6752,614.6304A59.7504,59.7504,0,0,1,409.7792,614.016L395.9552,606.848A58.5728,58.5728,0,0,1,372.6592,524.5696L444.3392,405.6832 413.6192,391.8592A14.6432,14.6432,0,0,0,399.2832,393.1904L318.7968,448.7936A48.8704,48.8704,0,0,1,256.128,442.8288A39.3472,39.3472,0,0,1,257.92,385.9712L386.2016,270.8224A58.5728,58.5728,0,0,1,443.648,258.7904L587.1872,306.048A117.1456,117.1456,0,0,1,698.9312,153.6z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.technologyDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFFA200" Geometry="F1 M1024,1024z M0,0z M492.270933,147.729067A255.342933,255.342933,0,0,1,627.2,620.2624L627.2,671.4624A37.546667,37.546667,0,0,1,601.6,705.595733L379.733333,705.595733A44.654933,44.654933,0,0,1,354.133333,671.4624L354.133333,620.2624A256.648533,256.648533,0,0,1,492.270933,147.729067z" />
<GeometryDrawing Brush="#FFFFF0D3" Geometry="F1 M1024,1024z M0,0z M550.4,534.929067L550.4,458.129067 601.6,458.129067C648.209067,458.129067,652.8,431.342934,652.8,415.4624L652.8,287.4624C652.8,264.3456,635.5968,244.795733,601.6,244.795733L388.266667,244.795733C346.1632,244.795733,328.533334,265.9072,328.533333,287.4624L328.533333,364.2624 430.933333,364.2624 430.933333,295.995733 550.4,295.995733 550.4,415.4624 499.2,415.4624C438.698667,414.8992,422.4,439.867733,422.4,458.129067L422.4,534.929067 550.4,534.929067z M487.7312,559.4624A59.733333,59.733333,0,1,1,427.997867,619.195733A59.733333,59.733333,0,0,1,487.7312,559.4624z" />
<GeometryDrawing Brush="#FF5FB5EC" Geometry="F1 M1024,1024z M0,0z M354.133333,739.7376L627.2,739.7376 627.2,748.270933A128,128,0,0,1,499.2,876.270933L482.133333,876.270933A128,128,0,0,1,354.133333,748.270933L354.133333,739.7376z" />
<GeometryDrawing Brush="#FFFFE074" Geometry="F1 M1024,1024z M0,0z M746.666667,210.6624L866.133333,210.6624A17.066667,17.066667,0,0,1,866.133333,244.795733L746.666667,244.795733A17.066667,17.066667,0,0,1,746.666667,210.6624z M806.4,150.929067A17.066667,17.066667,0,0,1,823.466667,167.995733L823.466667,287.4624A17.066667,17.066667,0,0,1,789.333333,287.4624L789.333333,167.995733A17.066667,17.066667,0,0,1,806.4,150.929067z" />
<GeometryDrawing Brush="#FFFFE074" Geometry="F1 M1024,1024z M0,0z M157.866667,662.929067L277.333333,662.929067A17.066667,17.066667,0,0,1,277.333333,697.0624L157.866667,697.0624A17.066667,17.066667,0,0,1,157.866667,662.929067z M217.6,603.195733A17.066667,17.066667,0,0,1,234.666667,620.2624L234.666667,739.729067A17.066667,17.066667,0,0,1,200.533333,739.729067L200.533333,620.2624A17.066667,17.066667,0,0,1,217.6,603.195733z" />
<GeometryDrawing Brush="#FFFFE074" Geometry="F1 M1024,1024z M0,0z M200.533333,662.9376L234.666667,662.9376 234.666667,697.070933 200.533333,697.070933z" />
<GeometryDrawing Brush="#FFFFE074" Geometry="F1 M1024,1024z M0,0z M789.333333,210.670933L823.466667,210.670933 823.466667,244.804267 789.333333,244.804267z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.techDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFFD778" Geometry="F1 M1024,1024z M0,0z M510.208,683.264L396.032,683.264 345.344,892.672 674.816,892.672 624.128,683.264 510.208,683.264z" />
<GeometryDrawing Brush="#FF48CFE5" Geometry="F1 M1024,1024z M0,0z M535.552,150.528L535.552,122.368A25.6,25.6,0,1,0,484.352,122.368L484.352,150.528A271.872,271.872,0,0,0,239.36,420.096L239.36,517.376A25.6,25.6,0,0,0,266.24,544.256L754.176,544.256A25.6,25.6,0,0,0,779.776,517.376L779.776,420.096A271.616,271.616,0,0,0,535.552,150.528z" />
<GeometryDrawing Brush="#FF2CBAE5" Geometry="F1 M1024,1024z M0,0z M125.696,464.64 M228.864,464.64L791.296,464.64Q894.464,464.64,894.464,567.808L894.464,583.168Q894.464,686.336,791.296,686.336L228.864,686.336Q125.696,686.336,125.696,583.168L125.696,567.808Q125.696,464.64,228.864,464.64z" />
<GeometryDrawing Brush="#FFFFD778" Geometry="F1 M1024,1024z M0,0z M742.4,537.6A37.632,37.632,0,1,0,780.032,575.232A37.376,37.376,0,0,0,742.4,537.6z M276.736,537.6A37.632,37.632,0,1,0,314.368,575.232A37.632,37.632,0,0,0,276.736,537.6z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.technology_oldDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFFD778" Geometry="F1 M1024,1024z M0,0z M510.208,683.264L396.032,683.264 345.344,892.672 674.816,892.672 624.128,683.264 510.208,683.264z" />
<GeometryDrawing Brush="#FF48CFE5" Geometry="F1 M1024,1024z M0,0z M535.552,150.528L535.552,122.368A25.6,25.6,0,1,0,484.352,122.368L484.352,150.528A271.872,271.872,0,0,0,239.36,420.096L239.36,517.376A25.6,25.6,0,0,0,266.24,544.256L754.176,544.256A25.6,25.6,0,0,0,779.776,517.376L779.776,420.096A271.616,271.616,0,0,0,535.552,150.528z" />
<GeometryDrawing Brush="#FF2CBAE5" Geometry="F1 M1024,1024z M0,0z M125.696,464.64 M228.864,464.64L791.296,464.64Q894.464,464.64,894.464,567.808L894.464,583.168Q894.464,686.336,791.296,686.336L228.864,686.336Q125.696,686.336,125.696,583.168L125.696,567.808Q125.696,464.64,228.864,464.64z" />
<GeometryDrawing Brush="#FFFFD778" Geometry="F1 M1024,1024z M0,0z M742.4,537.6A37.632,37.632,0,1,0,780.032,575.232A37.376,37.376,0,0,0,742.4,537.6z M276.736,537.6A37.632,37.632,0,1,0,314.368,575.232A37.632,37.632,0,0,0,276.736,537.6z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.teleplayDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FFFFB161" Geometry="F1 M1024,1024z M0,0z M271.616,247.808A212.224,212.224,0,0,0,221.952,420.608L247.552,547.328C304.384,569.088,307.712,634.88,314.88,696.576A1167.872,1167.872,0,0,1,505.088,682.496A1247.488,1247.488,0,0,1,701.184,696.576C708.864,634.88,705.536,569.856,761.088,547.84L786.688,419.84A211.712,211.712,0,0,0,736.768,247.552A218.624,218.624,0,0,0,571.648,172.8L436.736,172.8A218.624,218.624,0,0,0,271.616,247.552" />
<GeometryDrawing Brush="#FFFFE494" Geometry="F1 M1024,1024z M0,0z M505.088,412.672L470.272,378.112A19.456,19.456,0,0,0,442.88,405.504L468.48,431.104 442.88,456.704A19.456,19.456,0,0,0,470.272,484.096L505.088,449.536 540.16,484.096A18.688,18.688,0,0,0,553.728,489.728A19.456,19.456,0,0,0,567.552,456.704L541.952,431.104 567.552,405.504A19.456,19.456,0,0,0,553.728,372.48A18.688,18.688,0,0,0,540.16,378.112z" />
<GeometryDrawing Brush="#FFFB952C" Geometry="F1 M1024,1024z M0,0z M822.016,482.56A130.816,130.816,0,0,0,688.128,610.56L688.128,679.424 320,680.96 320,611.584A130.304,130.304,0,0,0,199.68,483.584L186.112,483.584A81.92,81.92,0,0,0,102.4,563.2A76.8,76.8,0,0,0,102.4,576.512A79.104,79.104,0,0,0,141.312,631.296L150.272,635.648 152.576,635.648A25.6,25.6,0,0,1,167.936,657.664L167.936,721.408A112.384,112.384,0,0,0,248.832,826.88A51.2,51.2,0,0,0,347.648,832.768L660.736,832.768A51.2,51.2,0,0,0,759.552,826.88A112.384,112.384,0,0,0,838.656,721.408L838.656,650.752A25.6,25.6,0,0,1,846.848,639.232L848.384,639.232 852.992,636.416A80.384,80.384,0,0,0,904.192,574.976L904.192,562.944A81.92,81.92,0,0,0,820.48,483.328" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</ResourceDictionary>

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -67,7 +68,12 @@ namespace DownKyi.Core.Danmaku2Ass
public void CreateFile(string fileName, string text)
{
File.WriteAllText(fileName, text);
try
{
File.WriteAllText(fileName, text);
}
catch (Exception)
{ }
}
public Dictionary<string, int> Report()

View File

@ -62,6 +62,7 @@ namespace DownKyi.Core.Danmaku2Ass
int second = (int)(i % 60.0f);
int hour = (int)Math.Floor(min / 60.0);
min = (int)Math.Floor(min % 60.0f);
return $"{hour:D}:{min:D2}:{second:D2}.{dec:D2}";
}

View File

@ -111,7 +111,7 @@
<Compile Include="Aria2cNet\Client\Entity\SystemMulticall.cs" />
<Compile Include="Aria2cNet\Client\Entity\SystemMulticallMathod.cs" />
<Compile Include="Aria2cNet\Client\HowChangePosition.cs" />
<Compile Include="Aria2cNet\DownloadStatus.cs" />
<Compile Include="Aria2cNet\DownloadResult.cs" />
<Compile Include="Aria2cNet\Server\AriaConfig.cs" />
<Compile Include="Aria2cNet\Server\AriaConfigFileAllocation.cs" />
<Compile Include="Aria2cNet\Server\AriaConfigLogLevel.cs" />
@ -160,13 +160,19 @@
<Compile Include="BiliApi\Login\Models\LoginUrl.cs" />
<Compile Include="BiliApi\Login\Models\UserInfoForNavigation.cs" />
<Compile Include="BiliApi\Models\Dimension.cs" />
<Compile Include="BiliApi\Models\Json\SubRipText.cs" />
<Compile Include="BiliApi\Models\Json\Subtitle.cs" />
<Compile Include="BiliApi\Models\Json\SubtitleJson.cs" />
<Compile Include="BiliApi\Models\VideoOwner.cs" />
<Compile Include="BiliApi\protobuf\bilibili\community\service\dm\v1\Dm.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayerV2.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayUrl.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayUrlDash.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayUrlDashVideo.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayUrlDurl.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayUrlSupportFormat.cs" />
<Compile Include="BiliApi\VideoStream\Models\Subtitle.cs" />
<Compile Include="BiliApi\VideoStream\Models\SubtitleInfo.cs" />
<Compile Include="BiliApi\VideoStream\VideoStream.cs" />
<Compile Include="BiliApi\Video\Dynamic.cs" />
<Compile Include="BiliApi\Video\Models\RankingVideoView.cs" />
@ -188,6 +194,7 @@
<Compile Include="BiliApi\Video\VideoInfo.cs" />
<Compile Include="BiliApi\WebClient.cs" />
<Compile Include="BiliApi\Zone\VideoZone.cs" />
<Compile Include="BiliApi\Zone\VideoZoneIcon.cs" />
<Compile Include="BiliApi\Zone\ZoneAttr.cs" />
<Compile Include="Danmaku2Ass\Bilibili.cs" />
<Compile Include="Danmaku2Ass\Collision.cs" />
@ -203,6 +210,9 @@
<Compile Include="Downloader\MultiThreadDownloader.cs" />
<Compile Include="Downloader\PartialDownloader.cs" />
<Compile Include="FFmpeg\FFmpegHelper.cs" />
<Compile Include="FileName\FileName.cs" />
<Compile Include="FileName\FileNamePart.cs" />
<Compile Include="FileName\HyphenSeparated.cs" />
<Compile Include="Logging\LogInfo.cs" />
<Compile Include="Logging\LogLevel.cs" />
<Compile Include="Logging\LogManager.cs" />
@ -255,7 +265,12 @@
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Page Include="BiliApi\Zone\ZoneImage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Brotli.NET.2.1.1\build\Brotli.NET.targets" Condition="Exists('..\packages\Brotli.NET.2.1.1\build\Brotli.NET.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

View File

@ -7,13 +7,13 @@ namespace DownKyi.Core.FFmpeg
{
public static class FFmpegHelper
{
private const string Tag = "PageToolboxDelogo";
private const string Tag = "FFmpegHelper";
/// <summary>
/// 合并音频和视频
/// </summary>
/// <param name="video1"></param>
/// <param name="video2"></param>
/// <param name="video1">音频</param>
/// <param name="video2">视频</param>
/// <param name="destVideo"></param>
public static bool MergeVideo(string video1, string video2, string destVideo)
{
@ -24,7 +24,7 @@ namespace DownKyi.Core.FFmpeg
}
if (video2 == null || !File.Exists(video2))
{
param = $"-i \"{video1}\" -acodec copy -vcodec copy -f mp4 \"{destVideo}\"";
param = $"-i \"{video1}\" -acodec copy -f aac \"{destVideo}\"";
}
if (!File.Exists(video1) && !File.Exists(video2)) { return false; }

View File

@ -0,0 +1,130 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace DownKyi.Core.FileName
{
public class FileName
{
private readonly List<FileNamePart> nameParts;
private int order = -1;
private string section = "SECTION";
private string mainTitle = "MAIN_TITLE";
private string pageTitle = "PAGE_TITLE";
private string videoZone = "VIDEO_ZONE";
private string audioQuality = "AUDIO_QUALITY";
private string videoQuality = "VIDEO_QUALITY";
private string videoCodec = "VIDEO_CODEC";
private FileName(List<FileNamePart> nameParts)
{
this.nameParts = nameParts;
}
public static FileName Builder(List<FileNamePart> nameParts)
{
return new FileName(nameParts);
}
public FileName SetOrder(int order)
{
this.order = order;
return this;
}
public FileName SetSection(string section)
{
this.section = section;
return this;
}
public FileName SetMainTitle(string mainTitle)
{
this.mainTitle = mainTitle;
return this;
}
public FileName SetPageTitle(string pageTitle)
{
this.pageTitle = pageTitle;
return this;
}
public FileName SetVideoZone(string videoZone)
{
this.videoZone = videoZone;
return this;
}
public FileName SetAudioQuality(string audioQuality)
{
this.audioQuality = audioQuality;
return this;
}
public FileName SetVideoQuality(string videoQuality)
{
this.videoQuality = videoQuality;
return this;
}
public FileName SetVideoCodec(string videoCodec)
{
this.videoCodec = videoCodec;
return this;
}
public string RelativePath()
{
string path = string.Empty;
foreach (FileNamePart part in nameParts)
{
switch (part)
{
case FileNamePart.ORDER:
if (order != -1)
{
path += order;
}
else
{
path += "ORDER";
}
break;
case FileNamePart.SECTION:
path += section;
break;
case FileNamePart.MAIN_TITLE:
path += mainTitle;
break;
case FileNamePart.PAGE_TITLE:
path += pageTitle;
break;
case FileNamePart.VIDEO_ZONE:
path += videoZone;
break;
case FileNamePart.AUDIO_QUALITY:
path += audioQuality;
break;
case FileNamePart.VIDEO_QUALITY:
path += videoQuality;
break;
case FileNamePart.VIDEO_CODEC:
path += videoCodec;
break;
}
if (((int)part) >= 100)
{
path += HyphenSeparated.Hyphen[(int)part];
}
}
// 避免连续多个斜杠
path = Regex.Replace(path, @"//+", "/");
// 避免以斜杠开头和结尾的情况
return path.TrimEnd('/').TrimStart('/');
}
}
}

View File

@ -0,0 +1,35 @@
namespace DownKyi.Core.FileName
{
public enum FileNamePart
{
// Video
ORDER = 1,
SECTION,
MAIN_TITLE,
PAGE_TITLE,
VIDEO_ZONE,
AUDIO_QUALITY,
VIDEO_QUALITY,
VIDEO_CODEC,
// 斜杠
SLASH = 100,
// HyphenSeparated
UNDERSCORE = 101, // 下划线
HYPHEN, // 连字符
PLUS, // 加号
COMMA, // 逗号
PERIOD, // 句号
AND, // and
NUMBER, // #
OPEN_PAREN, // 左圆括号
CLOSE_PAREN, // 右圆括号
OPEN_BRACKET, // 左方括号
CLOSE_BRACKET, // 右方括号
OPEN_BRACE, // 左花括号
CLOSE_brace, // 右花括号
BLANK, // 空白符
}
}

View File

@ -0,0 +1,31 @@
using System.Collections.Generic;
namespace DownKyi.Core.FileName
{
/// <summary>
/// 文件名字段
/// </summary>
public static class HyphenSeparated
{
// 文件名的分隔符
public static Dictionary<int, string> Hyphen = new Dictionary<int, string>()
{
{ 100, "/" },
{ 101, "_" },
{ 102, "-" },
{ 103, "+" },
{ 104, "," },
{ 105, "." },
{ 106, "&" },
{ 107, "#" },
{ 108, "(" },
{ 109, ")" },
{ 110, "[" },
{ 111, "]" },
{ 112, "{" },
{ 113, "}" },
{ 114, " " },
};
}
}

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using DownKyi.Core.FileName;
using System.Collections.Generic;
namespace DownKyi.Core.Settings.Models
{
@ -7,16 +8,13 @@ namespace DownKyi.Core.Settings.Models
/// </summary>
public class VideoSettings
{
public VideoCodecs VideoCodecs { get; set; }
public int Quality { get; set; }
public int AudioQuality { get; set; }
public AllowStatus IsAddOrder { get; set; }
public AllowStatus IsTranscodingFlvToMp4 { get; set; }
public string SaveVideoRootPath { get; set; }
public List<string> HistoryVideoRootPaths { get; set; }
public AllowStatus IsUseSaveVideoRootPath { get; set; }
public AllowStatus IsCreateFolderForMedia { get; set; }
public AllowStatus IsDownloadDanmaku { get; set; }
public AllowStatus IsDownloadCover { get; set; }
public VideoCodecs VideoCodecs { get; set; } // AVC or HEVC
public int Quality { get; set; } // 画质
public int AudioQuality { get; set; } // 音质
public AllowStatus IsTranscodingFlvToMp4 { get; set; } // 是否将flv转为mp4
public string SaveVideoRootPath { get; set; } // 视频保存路径
public List<string> HistoryVideoRootPaths { get; set; } // 历史视频保存路径
public AllowStatus IsUseSaveVideoRootPath { get; set; } // 是否使用默认视频保存路径
public List<FileNamePart> FileNameParts { get; set; } // 文件命名格式
}
}

View File

@ -1,4 +1,5 @@
using System;
using DownKyi.Core.FileName;
using System;
using System.Collections.Generic;
using System.IO;
@ -15,9 +16,6 @@ namespace DownKyi.Core.Settings
// 设置优先下载音质
private readonly int audioQuality = 30280;
// 是否在下载的视频前增加序号
private readonly AllowStatus isAddOrder = AllowStatus.NO;
// 是否下载flv视频后转码为mp4
private readonly AllowStatus isTranscodingFlvToMp4 = AllowStatus.YES;
@ -30,14 +28,21 @@ namespace DownKyi.Core.Settings
// 是否使用默认下载目录,如果是,则每次点击下载选中项时不再询问下载目录
private readonly AllowStatus isUseSaveVideoRootPath = AllowStatus.NO;
// 是否为不同视频分别创建文件夹
private readonly AllowStatus isCreateFolderForMedia = AllowStatus.YES;
// 是否在下载视频的同时下载弹幕
private readonly AllowStatus isDownloadDanmaku = AllowStatus.YES;
// 是否在下载视频的同时下载封面
private readonly AllowStatus isDownloadCover = AllowStatus.YES;
// 文件命名格式
private readonly List<FileNamePart> fileNameParts = new List<FileNamePart>
{
FileNamePart.MAIN_TITLE,
FileNamePart.SLASH,
FileNamePart.SECTION,
FileNamePart.SLASH,
FileNamePart.ORDER,
FileNamePart.HYPHEN,
FileNamePart.PAGE_TITLE,
FileNamePart.HYPHEN,
FileNamePart.VIDEO_QUALITY,
FileNamePart.HYPHEN,
FileNamePart.VIDEO_CODEC,
};
/// <summary>
/// 获取优先下载的视频编码
@ -120,33 +125,6 @@ namespace DownKyi.Core.Settings
return SetSettings();
}
/// <summary>
/// 获取是否给视频增加序号
/// </summary>
/// <returns></returns>
public AllowStatus IsAddOrder()
{
appSettings = GetSettings();
if (appSettings.Video.IsAddOrder == 0)
{
// 第一次获取,先设置默认值
IsAddOrder(isAddOrder);
return isAddOrder;
}
return appSettings.Video.IsAddOrder;
}
/// <summary>
/// 设置是否给视频增加序号
/// </summary>
/// <param name="isAddOrder"></param>
/// <returns></returns>
public bool IsAddOrder(AllowStatus isAddOrder)
{
appSettings.Video.IsAddOrder = isAddOrder;
return SetSettings();
}
/// <summary>
/// 获取是否下载flv视频后转码为mp4
/// </summary>
@ -256,83 +234,29 @@ namespace DownKyi.Core.Settings
}
/// <summary>
/// 获取是否为不同视频分别创建文件夹
/// 获取文件命名格式
/// </summary>
/// <returns></returns>
public AllowStatus IsCreateFolderForMedia()
public List<FileNamePart> GetFileNameParts()
{
appSettings = GetSettings();
if (appSettings.Video.IsCreateFolderForMedia == 0)
if (appSettings.Video.FileNameParts == null || appSettings.Video.FileNameParts.Count == 0)
{
// 第一次获取,先设置默认值
IsCreateFolderForMedia(isCreateFolderForMedia);
return isCreateFolderForMedia;
SetFileNameParts(fileNameParts);
return fileNameParts;
}
return appSettings.Video.IsCreateFolderForMedia;
return appSettings.Video.FileNameParts;
}
/// <summary>
/// 设置是否为不同视频分别创建文件夹
/// 设置文件命名格式
/// </summary>
/// <param name="isCreateFolderForMedia"></param>
/// <param name="historyPaths"></param>
/// <returns></returns>
public bool IsCreateFolderForMedia(AllowStatus isCreateFolderForMedia)
public bool SetFileNameParts(List<FileNamePart> fileNameParts)
{
appSettings.Video.IsCreateFolderForMedia = isCreateFolderForMedia;
return SetSettings();
}
/// <summary>
/// 获取是否在下载视频的同时下载弹幕
/// </summary>
/// <returns></returns>
public AllowStatus IsDownloadDanmaku()
{
appSettings = GetSettings();
if (appSettings.Video.IsDownloadDanmaku == 0)
{
// 第一次获取,先设置默认值
IsDownloadDanmaku(isDownloadDanmaku);
return isDownloadDanmaku;
}
return appSettings.Video.IsDownloadDanmaku;
}
/// <summary>
/// 设置是否在下载视频的同时下载弹幕
/// </summary>
/// <param name="isDownloadDanmaku"></param>
/// <returns></returns>
public bool IsDownloadDanmaku(AllowStatus isDownloadDanmaku)
{
appSettings.Video.IsDownloadDanmaku = isDownloadDanmaku;
return SetSettings();
}
/// <summary>
/// 获取是否在下载视频的同时下载封面
/// </summary>
/// <returns></returns>
public AllowStatus IsDownloadCover()
{
appSettings = GetSettings();
if (appSettings.Video.IsDownloadCover == 0)
{
// 第一次获取,先设置默认值
IsDownloadCover(isDownloadCover);
return isDownloadCover;
}
return appSettings.Video.IsDownloadCover;
}
/// <summary>
/// 设置是否在下载视频的同时下载封面
/// </summary>
/// <param name="isDownloadCover"></param>
/// <returns></returns>
public bool IsDownloadCover(AllowStatus isDownloadCover)
{
appSettings.Video.IsDownloadCover = isDownloadCover;
appSettings.Video.FileNameParts = fileNameParts;
return SetSettings();
}

View File

@ -1,4 +1,6 @@
namespace DownKyi.Core.Utils
using System.Text.RegularExpressions;
namespace DownKyi.Core.Utils
{
public static class Format
{
@ -120,15 +122,15 @@
}
else if (speed < 1024)
{
formatSpeed = speed.ToString("#.##") + "B/s";
formatSpeed = string.Format("{0:F2}", speed) + "B/s";
}
else if (speed < 1024 * 1024)
{
formatSpeed = (speed / 1024).ToString("#.##") + "KB/s";
formatSpeed = string.Format("{0:F2}", speed / 1024) + "KB/s";
}
else
{
formatSpeed = (speed / 1024 / 1024).ToString("#.##") + "MB/s";
formatSpeed = string.Format("{0:F2}", speed / 1024 / 1024) + "MB/s";
}
return formatSpeed;
}
@ -164,5 +166,39 @@
return formatFileSize;
}
/// <summary>
/// 去除非法字符
/// </summary>
/// <param name="originName"></param>
/// <returns></returns>
public static string FormatFileName(string originName)
{
string destName = originName;
// Windows中不能作为文件名的字符
destName = destName.Replace("\\", " ");
destName = destName.Replace("/", " ");
destName = destName.Replace(":", " ");
destName = destName.Replace("*", " ");
destName = destName.Replace("?", " ");
destName = destName.Replace("\"", " ");
destName = destName.Replace("<", " ");
destName = destName.Replace(">", " ");
destName = destName.Replace("|", " ");
// 转义字符
destName = destName.Replace("\a", "");
destName = destName.Replace("\b", "");
destName = destName.Replace("\f", "");
destName = destName.Replace("\n", "");
destName = destName.Replace("\r", "");
destName = destName.Replace("\t", "");
destName = destName.Replace("\v", "");
// 控制字符
destName = Regex.Replace(destName, @"\p{C}+", string.Empty);
return destName.Trim();
}
}
}

View File

@ -9,6 +9,7 @@
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/ThemeDefault.xaml" />
<ResourceDictionary Source="Languages/Default.xaml" />
<ResourceDictionary Source="pack://application:,,,/DownKyi.Core;component/BiliApi/Zone/ZoneImage.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

View File

@ -1,4 +1,6 @@
using DownKyi.Utils;
using DownKyi.Models;
using DownKyi.Services.Download;
using DownKyi.Utils;
using DownKyi.ViewModels;
using DownKyi.ViewModels.Dialogs;
using DownKyi.ViewModels.DownloadManager;
@ -11,6 +13,7 @@ using DownKyi.Views.Settings;
using DownKyi.Views.Toolbox;
using Prism.Ioc;
using System;
using System.Collections.ObjectModel;
using System.Windows;
namespace DownKyi
@ -20,6 +23,12 @@ namespace DownKyi
/// </summary>
public partial class App
{
public static ObservableCollection<DownloadingItem> DownloadingList { get; set; }
public static ObservableCollection<DownloadedItem> DownloadedList { get; set; }
// 下载服务
private IDownloadService downloadService;
protected override Window CreateShell()
{
// 设置主题
@ -30,9 +39,27 @@ namespace DownKyi
DictionaryResource.LoadLanguage("Default");
//DictionaryResource.LoadLanguage("en_US");
// 初始化数据
DownloadingList = new ObservableCollection<DownloadingItem>();
DownloadedList = new ObservableCollection<DownloadedItem>();
// TODO 从数据库读取
// 启动下载服务
downloadService = new AriaDownloadService(DownloadingList, DownloadedList);
downloadService.Start();
return Container.Resolve<MainWindow>();
}
protected override void OnExit(ExitEventArgs e)
{
// 关闭下载服务
downloadService.End();
base.OnExit(e);
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// pages

View File

@ -87,9 +87,15 @@
<Compile Include="Images\LogoIcon.cs" />
<Compile Include="Images\NavigationIcon.cs" />
<Compile Include="Images\NormalIcon.cs" />
<Compile Include="Models\DownloadBaseItem.cs" />
<Compile Include="Models\DownloadedItem.cs" />
<Compile Include="Models\DownloadingItem.cs" />
<Compile Include="Models\DownloadStatus.cs" />
<Compile Include="Models\Favorites.cs" />
<Compile Include="Models\FavoritesMedia.cs" />
<Compile Include="Models\DisplayFileNamePart.cs" />
<Compile Include="Models\ParseScopeDisplay.cs" />
<Compile Include="Models\PlayStreamType.cs" />
<Compile Include="Models\Resolution.cs" />
<Compile Include="Models\TabHeader.cs" />
<Compile Include="Models\VideoQuality.cs" />
@ -98,7 +104,10 @@
<Compile Include="Models\VideoSection.cs" />
<Compile Include="Services\BangumiInfoService.cs" />
<Compile Include="Services\CheeseInfoService.cs" />
<Compile Include="Services\Download\AriaDownloadService.cs" />
<Compile Include="Services\Download\DownloadService.cs" />
<Compile Include="Services\FavoritesService.cs" />
<Compile Include="Services\Download\IDownloadService.cs" />
<Compile Include="Services\IFavoritesService.cs" />
<Compile Include="Services\IInfoService.cs" />
<Compile Include="Services\IResolutionService.cs" />

View File

@ -68,6 +68,41 @@
V8.5z M5.5,10v15h21V10H5.5z",
Fill = "#FF000000"
};
Delete = new VectorImage
{
Height = 18,
Width = 18,
Data = @"M634.29 513.52 l364.34 -363.32 q25.37 -27.4 25.37 -60.89 q0 -33.49 -26.38 -59.88 q-26.38 -26.39 -59.88 -26.39
q-33.49 0 -60.9 25.38 l-363.32 364.33 l-363.32 -372.45 q-28.42 -20.3 -65.46 -20.3 q-37.04 0 -64.44 20.3
q-20.3 27.4 -20.3 64.44 q0 37.04 20.3 65.46 l372.45 363.32 l-364.33 363.32 q-25.38 27.41 -25.38 60.9 q0 33.49 26.39 59.88
q26.39 26.38 59.88 26.38 q33.49 0 60.89 -25.37 l363.32 -364.34 l363.32 364.34 q27.41 25.37 60.9 25.37 q33.49 0 59.88 -26.38
q26.38 -26.38 26.38 -59.88 q0 -33.49 -25.37 -60.9 l-364.34 -363.32 Z",
Fill = "#FF000000"
};
Start = new VectorImage
{
Height = 20,
Width = 17,
Data = @"M895.12 402.34 l-633.28 -383.81 q-30.16 -17.82 -64.43 -18.51 q-34.27 -0.69 -65.11 16.45 q-30.84 17.13 -47.97 47.29
q-17.13 30.16 -17.13 64.42 l0 767.62 q0 34.27 17.13 63.74 q17.14 29.47 47.97 47.29 q30.84 17.82 65.11 17.13
q34.27 -0.69 64.43 -18.5 l633.28 -383.81 q28.79 -17.82 45.24 -46.6 q16.45 -28.79 16.45 -63.06 q0 -34.27 -16.45 -63.05
q-16.45 -28.79 -45.24 -46.61 Z",
Fill = "#FF000000"
};
Pause = new VectorImage
{
Height = 20,
Width = 15,
Data = @"M255.66 0 q-53.75 0 -90.97 37.21 q-37.21 37.21 -37.21 90.96 l0 769.04 q1.38 55.12 37.21 90.95 q35.84 35.84 90.28 35.84
q54.44 0 90.96 -35.84 q36.52 -35.83 37.9 -90.95 l0 -769.04 q-1.38 -53.75 -38.59 -90.96 q-37.21 -37.21 -89.58 -37.21
ZM768.34 0 q-52.37 0 -89.58 37.21 q-37.21 37.21 -38.59 90.96 l0 769.04 q1.38 55.12 37.9 90.95 q36.52 35.84 90.96 35.84
q54.44 0 90.28 -35.84 q35.83 -35.83 37.21 -90.95 l0 -769.04 q0 -53.75 -37.21 -90.96 q-37.22 -37.21 -90.97 -37.21 Z",
Fill = "#FF000000"
};
}
public VectorImage GeneralSearch { get; private set; }
@ -75,5 +110,9 @@
public VectorImage DownloadManage { get; private set; }
public VectorImage Toolbox { get; private set; }
public VectorImage Delete { get; private set; }
public VectorImage Start { get; private set; }
public VectorImage Pause { get; private set; }
}
}

View File

@ -1,6 +1,6 @@
namespace DownKyi.Images
{
class LogoIcon
public class LogoIcon
{
private static LogoIcon instance;
public static LogoIcon Instance()

View File

@ -64,10 +64,33 @@
<system:String x:Key="DownloadSelected">下载选中项</system:String>
<system:String x:Key="AddAllToDownload">下载全部</system:String>
<system:String x:Key="TipAlreadyToAddDownloading">已经添加到下载列表~</system:String>
<system:String x:Key="TipAlreadyToAddDownloaded">已经下载完成~</system:String>
<system:String x:Key="TipAddDownloadingZero">没有选中项符合下载要求!</system:String>
<system:String x:Key="TipAddDownloadingFinished1">成功添加了</system:String>
<system:String x:Key="TipAddDownloadingFinished2">项~</system:String>
<!-- DownloadManager -->
<system:String x:Key="Downloading">正在下载</system:String>
<system:String x:Key="DownloadFinished">已下载</system:String>
<system:String x:Key="DownloadingAudio">音频</system:String>
<system:String x:Key="DownloadingVideo">视频</system:String>
<system:String x:Key="DownloadingDanmaku">弹幕</system:String>
<system:String x:Key="DownloadingSubtitle">字幕</system:String>
<system:String x:Key="DownloadingCover">封面</system:String>
<system:String x:Key="Parsing">正在解析……</system:String>
<system:String x:Key="WhileDownloading">下载中……</system:String>
<system:String x:Key="MixedFlow">混流中……</system:String>
<system:String x:Key="Pausing">暂停中……</system:String>
<system:String x:Key="Waiting">等待中……</system:String>
<system:String x:Key="TotalDownloading1">正在下载</system:String>
<system:String x:Key="TotalDownloading2">个视频!</system:String>
<system:String x:Key="PauseAllDownloading">全部暂停</system:String>
<system:String x:Key="ContinueAllDownloading">全部开始</system:String>
<system:String x:Key="DeleteAllDownloading">全部删除</system:String>
<!-- Settings -->
<system:String x:Key="PressEnterToApplySettingTip">按回车键应用设置</system:String>
@ -96,16 +119,23 @@
<system:String x:Key="Video">视频</system:String>
<system:String x:Key="FirstVideoCodecs">优先下载的视频编码:</system:String>
<system:String x:Key="FirstVideoQuality">优先下载的视频画质:</system:String>
<system:String x:Key="IsAddVideoOrder">启用视频编号</system:String>
<system:String x:Key="IsAddVideoOrderTip">勾选后,将为下载完成的视频的文件名添加上序号</system:String>
<system:String x:Key="IsTranscodingFlvToMp4">下载FLV视频后转码为mp4</system:String>
<system:String x:Key="IsUseDefaultDirectory">使用默认下载目录</system:String>
<system:String x:Key="DefaultDirectory">默认下载目录:</system:String>
<system:String x:Key="DefaultDirectoryTip">默认将文件下载到该文件夹中</system:String>
<system:String x:Key="ChangeDirectory">更改目录</system:String>
<system:String x:Key="IsCreateFolderForMedia">为不同视频分别创建文件夹</system:String>
<system:String x:Key="IsDownloadDanmaku">在下载视频的同时下载弹幕</system:String>
<system:String x:Key="IsDownloadCover">在下载视频的同时下载封面</system:String>
<system:String x:Key="FileNameParts">文件命名格式</system:String>
<system:String x:Key="FileName">文件名:</system:String>
<system:String x:Key="OptionalFields">可选字段:</system:String>
<system:String x:Key="DisplayOrder">序号</system:String>
<system:String x:Key="DisplaySection">视频章节</system:String>
<system:String x:Key="DisplayMainTitle">视频标题</system:String>
<system:String x:Key="DisplayPageTitle">分P标题</system:String>
<system:String x:Key="DisplayVideoZone">视频分区</system:String>
<system:String x:Key="DisplayAudioQuality">音质</system:String>
<system:String x:Key="DisplayVideoQuality">画质</system:String>
<system:String x:Key="DisplayVideoCodec">视频编码</system:String>
<system:String x:Key="DisplaySpace">空格</system:String>
<system:String x:Key="SettingDanmaku">弹幕</system:String>
<system:String x:Key="FilterType">按类型屏蔽</system:String>

View File

@ -0,0 +1,17 @@
using DownKyi.Core.FileName;
using Prism.Mvvm;
namespace DownKyi.Models
{
public class DisplayFileNamePart : BindableBase
{
public FileNamePart Id { get; set; }
private string title;
public string Title
{
get => title;
set => SetProperty(ref title, value);
}
}
}

View File

@ -0,0 +1,122 @@
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Windows.Media;
namespace DownKyi.Models
{
public class DownloadBaseItem : BindableBase
{
public DownloadBaseItem()
{
// 唯一id
Uuid = Guid.NewGuid().ToString("N");
// 初始化需要下载的内容
NeedDownloadContent = new Dictionary<string, bool>
{
{ "downloadAudio", true },
{ "downloadVideo", true },
{ "downloadDanmaku", true },
{ "downloadSubtitle", true },
{ "downloadCover", true }
};
}
// 此条下载项的id
public string Uuid { get; }
// 需要下载的内容
public Dictionary<string, bool> NeedDownloadContent { get; private set; }
// 视频的id
public string Bvid { get; set; }
public long Avid { get; set; }
public long Cid { get; set; }
public long EpisodeId { get; set; }
// 视频封面的url
public string CoverUrl { get; set; }
private DrawingImage zoneImage;
public DrawingImage ZoneImage
{
get => zoneImage;
set => SetProperty(ref zoneImage, value);
}
// 视频序号
private int order;
public int Order
{
get => order;
set => SetProperty(ref order, value);
}
// 视频主标题
private string mainTitle;
public string MainTitle
{
get => mainTitle;
set => SetProperty(ref mainTitle, value);
}
// 视频标题
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
// 时长
private string duration;
public string Duration
{
get => duration;
set => SetProperty(ref duration, value);
}
// 音频编码
public int AudioCodecId { get; set; }
private string audioCodecName;
public string AudioCodecName
{
get => audioCodecName;
set => SetProperty(ref audioCodecName, value);
}
// 视频编码
// "hev1.2.4.L156.90"
// "avc1.640034"
//public string VideoCodecId { get; set; }
// 视频编码名称AVC、HEVC
private string videoCodecName;
public string VideoCodecName
{
get => videoCodecName;
set => SetProperty(ref videoCodecName, value);
}
// 视频画质
private Resolution resolution;
public Resolution Resolution
{
get => resolution;
set => SetProperty(ref resolution, value);
}
// 文件路径,不包含扩展名,所有内容均以此路径下载
public string FilePath { get; set; }
// 文件大小
private string fileSize;
public string FileSize
{
get => fileSize;
set => SetProperty(ref fileSize, value);
}
}
}

View File

@ -0,0 +1,13 @@
namespace DownKyi.Models
{
public enum DownloadStatus
{
NOT_STARTED, // 未开始,从未开始下载
WAIT_FOR_DOWNLOAD, // 等待下载,下载过,但是启动本次下载周期未开始,如重启程序后未开始
PAUSE_STARTED, // 暂停启动下载
PAUSE, // 暂停
DOWNLOADING, // 下载中
DOWNLOAD_SUCCEED, // 下载成功
DOWNLOAD_FAILED, // 下载失败
}
}

View File

@ -0,0 +1,9 @@
namespace DownKyi.Models
{
public class DownloadedItem : DownloadBaseItem
{
public DownloadedItem() : base()
{
}
}
}

View File

@ -0,0 +1,165 @@
using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Images;
using DownKyi.Utils;
using Prism.Commands;
using System.Collections.Generic;
namespace DownKyi.Models
{
public class DownloadingItem : DownloadBaseItem
{
public DownloadingItem() : base()
{
// 初始化下载的文件列表
DownloadFiles = new List<string>();
// 暂停继续按钮
StartOrPause = ButtonIcon.Instance().Pause;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
// 删除按钮
Delete = ButtonIcon.Instance().Delete;
Delete.Fill = DictionaryResource.GetColor("ColorPrimary");
}
public PlayUrl PlayUrl { get; set; }
// Aria相关
public string Gid { get; set; }
// 下载的文件
public List<string> DownloadFiles { get; private set; }
// 视频类别
public PlayStreamType PlayStreamType { get; set; }
// 正在下载内容(音频、视频、弹幕、字幕、封面)
private string downloadContent;
public string DownloadContent
{
get => downloadContent;
set => SetProperty(ref downloadContent, value);
}
// 下载状态
public DownloadStatus DownloadStatus { get; set; }
// 下载状态显示
private string downloadStatusTitle;
public string DownloadStatusTitle
{
get => downloadStatusTitle;
set => SetProperty(ref downloadStatusTitle, value);
}
// 下载进度
private float progress;
public float Progress
{
get => progress;
set => SetProperty(ref progress, value);
}
// 已下载大小/文件大小
private string downloadingFileSize;
public string DownloadingFileSize
{
get => downloadingFileSize;
set => SetProperty(ref downloadingFileSize, value);
}
// 下载的最高速度
public long MaxSpeed { get; set; }
// 下载速度
private string speedDisplay;
public string SpeedDisplay
{
get => speedDisplay;
set => SetProperty(ref speedDisplay, value);
}
#region
private VectorImage startOrPause;
public VectorImage StartOrPause
{
get => startOrPause;
set => SetProperty(ref startOrPause, value);
}
private VectorImage delete;
public VectorImage Delete
{
get => delete;
set => SetProperty(ref delete, value);
}
#endregion
#region
// 下载列表暂停继续事件
private DelegateCommand startOrPauseCommand;
public DelegateCommand StartOrPauseCommand => startOrPauseCommand ?? (startOrPauseCommand = new DelegateCommand(ExecuteStartOrPauseCommand));
/// <summary>
/// 下载列表暂停继续事件
/// </summary>
private void ExecuteStartOrPauseCommand()
{
switch (DownloadStatus)
{
case DownloadStatus.NOT_STARTED:
case DownloadStatus.WAIT_FOR_DOWNLOAD:
DownloadStatus = DownloadStatus.PAUSE_STARTED;
StartOrPause = ButtonIcon.Instance().Start;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
break;
case DownloadStatus.PAUSE_STARTED:
DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD;
StartOrPause = ButtonIcon.Instance().Pause;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
break;
case DownloadStatus.PAUSE:
DownloadStatus = DownloadStatus.DOWNLOADING;
StartOrPause = ButtonIcon.Instance().Pause;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
break;
case DownloadStatus.DOWNLOADING:
DownloadStatus = DownloadStatus.PAUSE;
StartOrPause = ButtonIcon.Instance().Start;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
break;
case DownloadStatus.DOWNLOAD_SUCCEED:
// 下载成功后会从下载列表中删除
// 不会出现此分支
break;
case DownloadStatus.DOWNLOAD_FAILED:
DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD;
StartOrPause = ButtonIcon.Instance().Pause;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
break;
default:
break;
}
}
// 下载列表删除事件
private DelegateCommand deleteCommand;
public DelegateCommand DeleteCommand => deleteCommand ?? (deleteCommand = new DelegateCommand(ExecuteDeleteCommand));
/// <summary>
/// 下载列表删除事件
/// </summary>
private void ExecuteDeleteCommand()
{
App.DownloadingList.Remove(this);
}
#endregion
}
}

View File

@ -0,0 +1,9 @@
namespace DownKyi.Models
{
public enum PlayStreamType
{
VIDEO = 1, // 普通视频
BANGUMI, // 番剧、电影、电视剧等
CHEESE, // 课程
}
}

View File

@ -9,103 +9,104 @@ namespace DownKyi.Models
{
public string CoverUrl { get; set; }
public long UpperMid { get; set; }
public int TypeId { get; set; }
private BitmapImage cover;
public BitmapImage Cover
{
get { return cover; }
set { SetProperty(ref cover, value); }
get => cover;
set => SetProperty(ref cover, value);
}
private string title;
public string Title
{
get { return title; }
set { SetProperty(ref title, value); }
get => title;
set => SetProperty(ref title, value);
}
private string videoZone;
public string VideoZone
{
get { return videoZone; }
set { SetProperty(ref videoZone, value); }
get => videoZone;
set => SetProperty(ref videoZone, value);
}
private string createTime;
public string CreateTime
{
get { return createTime; }
set { SetProperty(ref createTime, value); }
get => createTime;
set => SetProperty(ref createTime, value);
}
private string playNumber;
public string PlayNumber
{
get { return playNumber; }
set { SetProperty(ref playNumber, value); }
get => playNumber;
set => SetProperty(ref playNumber, value);
}
private string danmakuNumber;
public string DanmakuNumber
{
get { return danmakuNumber; }
set { SetProperty(ref danmakuNumber, value); }
get => danmakuNumber;
set => SetProperty(ref danmakuNumber, value);
}
private string likeNumber;
public string LikeNumber
{
get { return likeNumber; }
set { SetProperty(ref likeNumber, value); }
get => likeNumber;
set => SetProperty(ref likeNumber, value);
}
private string coinNumber;
public string CoinNumber
{
get { return coinNumber; }
set { SetProperty(ref coinNumber, value); }
get => coinNumber;
set => SetProperty(ref coinNumber, value);
}
private string favoriteNumber;
public string FavoriteNumber
{
get { return favoriteNumber; }
set { SetProperty(ref favoriteNumber, value); }
get => favoriteNumber;
set => SetProperty(ref favoriteNumber, value);
}
private string shareNumber;
public string ShareNumber
{
get { return shareNumber; }
set { SetProperty(ref shareNumber, value); }
get => shareNumber;
set => SetProperty(ref shareNumber, value);
}
private string replyNumber;
public string ReplyNumber
{
get { return replyNumber; }
set { SetProperty(ref replyNumber, value); }
get => replyNumber;
set => SetProperty(ref replyNumber, value);
}
private string description;
public string Description
{
get { return description; }
set { SetProperty(ref description, value); }
get => description;
set => SetProperty(ref description, value);
}
private string upName;
public string UpName
{
get { return upName; }
set { SetProperty(ref upName, value); }
get => upName;
set => SetProperty(ref upName, value);
}
private BitmapImage upHeader;
public BitmapImage UpHeader
{
get { return upHeader; }
set { SetProperty(ref upHeader, value); }
get => upHeader;
set => SetProperty(ref upHeader, value);
}
}

View File

@ -13,60 +13,62 @@ namespace DownKyi.Models
public long Cid { get; set; }
public long EpisodeId { get; set; }
public string FirstFrame { get; set; }
private bool isSelected;
public bool IsSelected
{
get { return isSelected; }
set { SetProperty(ref isSelected, value); }
get => isSelected;
set => SetProperty(ref isSelected, value);
}
private int order;
public int Order
{
get { return order; }
set { SetProperty(ref order, value); }
get => order;
set => SetProperty(ref order, value);
}
private string name;
public string Name
{
get { return name; }
set { SetProperty(ref name, value); }
get => name;
set => SetProperty(ref name, value);
}
private string duration;
public string Duration
{
get { return duration; }
set { SetProperty(ref duration, value); }
get => duration;
set => SetProperty(ref duration, value);
}
private List<string> audioQualityFormatList;
public List<string> AudioQualityFormatList
{
get { return audioQualityFormatList; }
set { SetProperty(ref audioQualityFormatList, value); }
get => audioQualityFormatList;
set => SetProperty(ref audioQualityFormatList, value);
}
private string audioQualityFormat;
public string AudioQualityFormat
{
get { return audioQualityFormat; }
set { SetProperty(ref audioQualityFormat, value); }
get => audioQualityFormat;
set => SetProperty(ref audioQualityFormat, value);
}
private List<VideoQuality> videoQualityList;
public List<VideoQuality> VideoQualityList
{
get { return videoQualityList; }
set { SetProperty(ref videoQualityList, value); }
get => videoQualityList;
set => SetProperty(ref videoQualityList, value);
}
private VideoQuality videoQuality;
public VideoQuality VideoQuality
{
get { return videoQuality; }
set { SetProperty(ref videoQuality, value); }
get => videoQuality;
set => SetProperty(ref videoQuality, value);
}
}

View File

@ -8,30 +8,29 @@ namespace DownKyi.Models
private int quality;
public int Quality
{
get { return quality; }
set { SetProperty(ref quality, value); }
get => quality;
set => SetProperty(ref quality, value);
}
private string qualityFormat;
public string QualityFormat
{
get { return qualityFormat; }
set { SetProperty(ref qualityFormat, value); }
get => qualityFormat;
set => SetProperty(ref qualityFormat, value);
}
private List<string> videoCodecList;
public List<string> VideoCodecList
{
get { return videoCodecList; }
set { SetProperty(ref videoCodecList, value); }
get => videoCodecList;
set => SetProperty(ref videoCodecList, value);
}
private string selectedVideoCodec;
public string SelectedVideoCodec
{
get { return selectedVideoCodec; }
set { SetProperty(ref selectedVideoCodec, value); }
get => selectedVideoCodec;
set => SetProperty(ref selectedVideoCodec, value);
}
}
}

View File

@ -8,6 +8,7 @@ using DownKyi.Models;
using DownKyi.Utils;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Windows.Media.Imaging;
namespace DownKyi.Services
@ -63,21 +64,28 @@ namespace DownKyi.Services
string name;
// 判断title是否为数字如果是则将share_copy作为name否则将title作为name
if (int.TryParse(episode.Title, out int result))
{
name = episode.ShareCopy;
}
else
{
if (episode.LongTitle != null && episode.LongTitle != "")
{
name = $"{episode.Title} {episode.LongTitle}";
}
else
{
name = episode.Title;
}
}
//if (int.TryParse(episode.Title, out int result))
//{
// name = Regex.Replace(episode.ShareCopy, @"《.*?》", "");
// //name = episode.ShareCopy;
//}
//else
//{
// if (episode.LongTitle != null && episode.LongTitle != "")
// {
// name = $"{episode.Title} {episode.LongTitle}";
// }
// else
// {
// name = episode.Title;
// }
//}
// 将share_copy作为name删除《》中的标题
name = Regex.Replace(episode.ShareCopy, @"^《.*?》", "");
// 删除前后空白符
name = name.Trim();
VideoPage page = new VideoPage
{
@ -85,6 +93,7 @@ namespace DownKyi.Services
Bvid = episode.Bvid,
Cid = episode.Cid,
EpisodeId = -1,
FirstFrame = episode.Cover,
Order = order,
Name = name,
Duration = "N/A"
@ -141,6 +150,7 @@ namespace DownKyi.Services
Bvid = episode.Bvid,
Cid = episode.Cid,
EpisodeId = -1,
FirstFrame = episode.Cover,
Order = order,
Name = name,
Duration = "N/A"
@ -210,6 +220,9 @@ namespace DownKyi.Services
videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover));
videoInfoView.Title = bangumiSeason.Title;
// 分区id
videoInfoView.TypeId = BangumiType.TypeId[bangumiSeason.Type];
videoInfoView.VideoZone = DictionaryResource.GetString(BangumiType.Type[bangumiSeason.Type]);
videoInfoView.PlayNumber = Format.FormatNumber(bangumiSeason.Stat.Views);

View File

@ -61,6 +61,7 @@ namespace DownKyi.Services
Bvid = null,
Cid = episode.Cid,
EpisodeId = episode.Id,
FirstFrame = episode.Cover,
Order = order,
Name = name,
Duration = "N/A"
@ -129,6 +130,10 @@ namespace DownKyi.Services
videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover));
videoInfoView.Title = cheeseView.Title;
// 分区id
// 课堂的type id B站没有定义这里自定义为-10
videoInfoView.TypeId = -10;
videoInfoView.VideoZone = DictionaryResource.GetString("Cheese");
videoInfoView.CreateTime = "";

View File

@ -0,0 +1,763 @@
using DownKyi.Core.Aria2cNet;
using DownKyi.Core.Aria2cNet.Client;
using DownKyi.Core.Aria2cNet.Client.Entity;
using DownKyi.Core.Aria2cNet.Server;
using DownKyi.Core.BiliApi.Login;
using DownKyi.Core.BiliApi.VideoStream;
using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Core.Danmaku2Ass;
using DownKyi.Core.FFmpeg;
using DownKyi.Core.Logging;
using DownKyi.Core.Settings;
using DownKyi.Core.Storage;
using DownKyi.Core.Utils;
using DownKyi.Models;
using DownKyi.Utils;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace DownKyi.Services.Download
{
/// <summary>
/// 音视频采用Aria下载其余采用WebClient下载
/// </summary>
public class AriaDownloadService : DownloadService, IDownloadService
{
private CancellationTokenSource tokenSource;
public AriaDownloadService(ObservableCollection<DownloadingItem> downloadingList, ObservableCollection<DownloadedItem> downloadedList) : base(downloadingList, downloadedList)
{
Tag = "AriaDownloadService";
}
#region
/// <summary>
/// 下载音频,返回下载文件路径
/// </summary>
/// <param name="downloading"></param>
/// <returns></returns>
public string DownloadAudio(DownloadingItem downloading)
{
// 更新状态显示
downloading.DownloadStatusTitle = DictionaryResource.GetString("WhileDownloading");
downloading.DownloadContent = DictionaryResource.GetString("DownloadingAudio");
// 如果没有Dash返回null
if (downloading.PlayUrl == null || downloading.PlayUrl.Dash == null) { return null; }
// 如果audio列表没有内容则返回null
if (downloading.PlayUrl.Dash.Audio == null) { return null; }
else if (downloading.PlayUrl.Dash.Audio.Count == 0) { return null; }
// 根据音频id匹配
PlayUrlDashVideo downloadAudio = null;
foreach (PlayUrlDashVideo audio in downloading.PlayUrl.Dash.Audio)
{
if (audio.Id == downloading.AudioCodecId)
{
downloadAudio = audio;
break;
}
}
return DownloadVideo(downloading, downloadAudio);
}
/// <summary>
/// 下载视频,返回下载文件路径
/// </summary>
/// <param name="downloading"></param>
/// <returns></returns>
public string DownloadVideo(DownloadingItem downloading)
{
// 更新状态显示
downloading.DownloadStatusTitle = DictionaryResource.GetString("WhileDownloading");
downloading.DownloadContent = DictionaryResource.GetString("DownloadingVideo");
// 如果没有Dash返回null
if (downloading.PlayUrl == null || downloading.PlayUrl.Dash == null) { return null; }
// 如果Video列表没有内容则返回null
if (downloading.PlayUrl.Dash.Video == null) { return null; }
else if (downloading.PlayUrl.Dash.Video.Count == 0) { return null; }
// 根据视频编码匹配
PlayUrlDashVideo downloadVideo = null;
foreach (PlayUrlDashVideo video in downloading.PlayUrl.Dash.Video)
{
if (video.Id == downloading.Resolution.Id && Utils.GetVideoCodecName(video.Codecs) == downloading.VideoCodecName)
{
downloadVideo = video;
break;
}
}
return DownloadVideo(downloading, downloadVideo);
}
/// <summary>
/// 将下载音频和视频的函数中相同代码抽象出来
/// </summary>
/// <param name="downloading"></param>
/// <param name="downloadVideo"></param>
/// <returns></returns>
private string DownloadVideo(DownloadingItem downloading, PlayUrlDashVideo downloadVideo)
{
// 如果为空,说明没有匹配到可下载的音频视频
if (downloadVideo == null) { return null; }
// 下载链接
List<string> urls = new List<string>();
if (downloadVideo.BaseUrl != null) { urls.Add(downloadVideo.BaseUrl); }
if (downloadVideo.BackupUrl != null) { urls.AddRange(downloadVideo.BackupUrl); }
// 路径
string[] temp = downloading.FilePath.Split('/');
string path = downloading.FilePath.Replace(temp[temp.Length - 1], "");
// 下载文件名
string fileName = Guid.NewGuid().ToString("N");
// 记录本次下载的文件
downloading.DownloadFiles.Add(fileName);
// 开始下载
DownloadResult downloadStatus = DownloadByAria(downloading, urls, path, fileName);
switch (downloadStatus)
{
case DownloadResult.SUCCESS:
return Path.Combine(path, fileName);
case DownloadResult.FAILED:
return null;
case DownloadResult.ABORT:
return null;
default:
return null;
}
}
#endregion
/// <summary>
/// 下载封面
/// </summary>
/// <param name="downloading"></param>
public string DownloadCover(DownloadingItem downloading)
{
// 更新状态显示
downloading.DownloadStatusTitle = DictionaryResource.GetString("WhileDownloading");
downloading.DownloadContent = DictionaryResource.GetString("DownloadingCover");
// 下载大小
downloading.DownloadingFileSize = string.Empty;
// 下载速度
downloading.SpeedDisplay = string.Empty;
// 查询、保存封面
StorageCover storageCover = new StorageCover();
string cover = storageCover.GetCover(downloading.Avid, downloading.Bvid, downloading.Cid, downloading.CoverUrl);
if (cover == null)
{
return null;
}
// 图片的扩展名
string[] temp = downloading.CoverUrl.Split('.');
string fileExtension = temp[temp.Length - 1];
// 图片的地址
string coverPath = $"{StorageManager.GetCover()}/{cover}";
// 复制图片到指定位置
try
{
string fileName = $"{downloading.FilePath}.{fileExtension}";
File.Copy(coverPath, fileName);
// 记录本次下载的文件
downloading.DownloadFiles.Add(fileName);
return fileName;
}
catch (Exception e)
{
Core.Utils.Debugging.Console.PrintLine(e);
LogManager.Error(Tag, e);
}
return null;
}
/// <summary>
/// 下载弹幕
/// </summary>
/// <param name="downloading"></param>
public string DownloadDanmaku(DownloadingItem downloading)
{
// 更新状态显示
downloading.DownloadStatusTitle = DictionaryResource.GetString("WhileDownloading");
downloading.DownloadContent = DictionaryResource.GetString("DownloadingDanmaku");
// 下载大小
downloading.DownloadingFileSize = string.Empty;
// 下载速度
downloading.SpeedDisplay = string.Empty;
string title = $"{downloading.Name}";
string assFile = $"{downloading.FilePath}.ass";
// 记录本次下载的文件
downloading.DownloadFiles.Add(assFile);
int screenWidth = SettingsManager.GetInstance().GetDanmakuScreenWidth();
int screenHeight = SettingsManager.GetInstance().GetDanmakuScreenHeight();
//if (SettingsManager.GetInstance().IsCustomDanmakuResolution() != AllowStatus.YES)
//{
// if (downloadingEntity.Width > 0 && downloadingEntity.Height > 0)
// {
// screenWidth = downloadingEntity.Width;
// screenHeight = downloadingEntity.Height;
// }
//}
// 字幕配置
Config subtitleConfig = new Config
{
Title = title,
ScreenWidth = screenWidth,
ScreenHeight = screenHeight,
FontName = SettingsManager.GetInstance().GetDanmakuFontName(),
BaseFontSize = SettingsManager.GetInstance().GetDanmakuFontSize(),
LineCount = SettingsManager.GetInstance().GetDanmakuLineCount(),
LayoutAlgorithm = SettingsManager.GetInstance().GetDanmakuLayoutAlgorithm().ToString("G").ToLower(), // async/sync
TuneDuration = 0,
DropOffset = 0,
BottomMargin = 0,
CustomOffset = 0
};
Core.Danmaku2Ass.Bilibili.GetInstance()
.SetTopFilter(SettingsManager.GetInstance().GetDanmakuTopFilter() == AllowStatus.YES)
.SetBottomFilter(SettingsManager.GetInstance().GetDanmakuBottomFilter() == AllowStatus.YES)
.SetScrollFilter(SettingsManager.GetInstance().GetDanmakuScrollFilter() == AllowStatus.YES)
.Create(downloading.Avid, downloading.Cid, subtitleConfig, assFile);
return assFile;
}
/// <summary>
/// 下载字幕
/// </summary>
/// <param name="downloading"></param>
public List<string> DownloadSubtitle(DownloadingItem downloading)
{
// 更新状态显示
downloading.DownloadStatusTitle = DictionaryResource.GetString("WhileDownloading");
downloading.DownloadContent = DictionaryResource.GetString("DownloadingSubtitle");
// 下载大小
downloading.DownloadingFileSize = string.Empty;
// 下载速度
downloading.SpeedDisplay = string.Empty;
List<string> srtFiles = new List<string>();
var subRipTexts = VideoStream.GetSubtitle(downloading.Avid, downloading.Bvid, downloading.Cid);
if (subRipTexts == null)
{
return null;
}
foreach (var subRip in subRipTexts)
{
string srtFile = $"{downloading.FilePath}_{subRip.LanDoc}.srt";
try
{
File.WriteAllText(srtFile, subRip.SrtString);
// 记录本次下载的文件
downloading.DownloadFiles.Add(srtFile);
srtFiles.Add(srtFile);
}
catch (Exception e)
{
Core.Utils.Debugging.Console.PrintLine("DownloadSubtitle()发生异常: {0}", e);
LogManager.Error("DownloadSubtitle()", e);
}
}
return srtFiles;
}
/// <summary>
/// 混流音频和视频
/// </summary>
/// <param name="downloading"></param>
/// <param name="audioUid"></param>
/// <param name="videoUid"></param>
/// <returns></returns>
public string MixedFlow(DownloadingItem downloading, string audioUid, string videoUid)
{
// 更新状态显示
downloading.DownloadStatusTitle = DictionaryResource.GetString("MixedFlow");
downloading.DownloadContent = DictionaryResource.GetString("DownloadingVideo");
// 下载大小
downloading.DownloadingFileSize = string.Empty;
// 下载速度
downloading.SpeedDisplay = string.Empty;
string finalFile = $"{downloading.FilePath}.mp4";
if (videoUid == null)
{
finalFile = $"{downloading.FilePath}.aac";
}
// 合并音视频
FFmpegHelper.MergeVideo(audioUid, videoUid, finalFile);
// 获取文件大小
if (File.Exists(finalFile))
{
FileInfo info = new FileInfo(finalFile);
downloading.FileSize = Format.FormatFileSize(info.Length);
}
else
{
downloading.FileSize = Format.FormatFileSize(0);
}
return finalFile;
}
/// <summary>
/// 解析视频流的下载链接
/// </summary>
/// <param name="downloading"></param>
public void Parse(DownloadingItem downloading)
{
// 更新状态显示
downloading.DownloadStatusTitle = DictionaryResource.GetString("Parsing");
downloading.DownloadContent = string.Empty;
// 下载大小
downloading.DownloadingFileSize = string.Empty;
// 下载速度
downloading.SpeedDisplay = string.Empty;
if (downloading.PlayUrl != null && downloading.DownloadStatus == DownloadStatus.NOT_STARTED)
{
return;
}
// 解析
switch (downloading.PlayStreamType)
{
case PlayStreamType.VIDEO:
downloading.PlayUrl = VideoStream.GetVideoPlayUrl(downloading.Avid, downloading.Bvid, downloading.Cid);
break;
case PlayStreamType.BANGUMI:
downloading.PlayUrl = VideoStream.GetBangumiPlayUrl(downloading.Avid, downloading.Bvid, downloading.Cid);
break;
case PlayStreamType.CHEESE:
downloading.PlayUrl = VideoStream.GetCheesePlayUrl(downloading.Avid, downloading.Bvid, downloading.Cid, downloading.EpisodeId);
break;
default:
break;
}
}
/// <summary>
/// 停止下载服务
/// </summary>
public void End()
{
// TODO
// 保存数据
// 关闭Aria服务器
CloseAriaServer();
// 结束任务
tokenSource.Cancel();
}
/// <summary>
/// 启动下载服务
/// </summary>
public async void Start()
{
// 启动Aria服务器
StartAriaServer();
await Task.Run(DoWork, (tokenSource = new CancellationTokenSource()).Token);
}
/// <summary>
/// 执行任务
/// </summary>
private void DoWork()
{
CancellationToken cancellationToken = tokenSource.Token;
while (true)
{
int maxDownloading = SettingsManager.GetInstance().GetAriaMaxConcurrentDownloads();
int downloadingCount = 0;
foreach (DownloadingItem downloading in downloadingList)
{
if (downloading.DownloadStatus == DownloadStatus.DOWNLOADING)
{
downloadingCount++;
}
}
foreach (DownloadingItem downloading in downloadingList)
{
if (downloadingCount >= maxDownloading)
{
break;
}
// 开始下载
if (downloading.DownloadStatus == DownloadStatus.NOT_STARTED || downloading.DownloadStatus == DownloadStatus.WAIT_FOR_DOWNLOAD)
{
SingleDownload(downloading);
downloadingCount++;
}
}
// 判断是否该结束线程若为true跳出while循环
if (cancellationToken.IsCancellationRequested)
{
Core.Utils.Debugging.Console.PrintLine("AriaDownloadService: 下载服务结束跳出while循环");
LogManager.Debug(Tag, "下载服务结束");
break;
}
// 降低CPU占用
Thread.Sleep(100);
}
}
/// <summary>
/// 下载一个视频
/// </summary>
/// <param name="downloading"></param>
/// <returns></returns>
private async void SingleDownload(DownloadingItem downloading)
{
await Task.Run(new Action(() =>
{
downloading.DownloadStatus = DownloadStatus.DOWNLOADING;
// 初始化
downloading.DownloadStatusTitle = string.Empty;
downloading.DownloadContent = string.Empty;
downloading.DownloadFiles.Clear();
// 解析并依次下载音频、视频、弹幕、字幕、封面等内容
Parse(downloading);
// 暂停
Pause(downloading);
string audioUid = null;
// 如果需要下载音频
if (downloading.NeedDownloadContent["downloadAudio"])
{
audioUid = DownloadAudio(downloading);
}
// 暂停
Pause(downloading);
string videoUid = null;
// 如果需要下载视频
if (downloading.NeedDownloadContent["downloadVideo"])
{
videoUid = DownloadVideo(downloading);
}
// 暂停
Pause(downloading);
string outputDanmaku = null;
// 如果需要下载弹幕
if (downloading.NeedDownloadContent["downloadDanmaku"])
{
outputDanmaku = DownloadDanmaku(downloading);
}
// 暂停
Pause(downloading);
List<string> outputSubtitles = null;
// 如果需要下载字幕
if (downloading.NeedDownloadContent["downloadSubtitle"])
{
outputSubtitles = DownloadSubtitle(downloading);
}
// 暂停
Pause(downloading);
string outputCover = null;
// 如果需要下载封面
if (downloading.NeedDownloadContent["downloadCover"])
{
outputCover = DownloadCover(downloading);
}
// 暂停
Pause(downloading);
// 混流
string outputMedia = MixedFlow(downloading, audioUid, videoUid);
// 暂停
Pause(downloading);
// 检测音频、视频是否下载成功
if (downloading.NeedDownloadContent["downloadAudio"] || downloading.NeedDownloadContent["downloadVideo"])
{
// 只有下载音频不下载视频时才输出aac
// 只要下载视频就输出mp4
if (File.Exists(outputMedia))
{
// 成功
}
}
// 检测弹幕是否下载成功
if (downloading.NeedDownloadContent["downloadDanmaku"] && File.Exists(outputDanmaku))
{
// 成功
}
// 检测字幕是否下载成功
if (downloading.NeedDownloadContent["downloadSubtitle"])
{
if (outputSubtitles == null)
{
// 为null时表示不存在字幕
}
else
{
foreach (string subtitle in outputSubtitles)
{
if (File.Exists(subtitle))
{
// 成功
}
}
}
}
// 检测封面是否下载成功
if (downloading.NeedDownloadContent["downloadCover"] && File.Exists(outputCover))
{
// 成功
}
// TODO
// 将下载结果写入数据库
// 包括下载请求的DownloadingItem对象
// 下载结果是否成功等
// 对是否成功的判断只要outputMedia存在则成功否则失败
}));
}
/// <summary>
/// 强制暂停
/// </summary>
/// <param name="downloading"></param>
private void Pause(DownloadingItem downloading)
{
string oldStatus = downloading.DownloadStatusTitle;
downloading.DownloadStatusTitle = DictionaryResource.GetString("Pausing");
while (downloading.DownloadStatus == DownloadStatus.PAUSE)
{
// 降低CPU占用
Thread.Sleep(100);
}
downloading.DownloadStatusTitle = DictionaryResource.GetString("Waiting");
int maxDownloading = SettingsManager.GetInstance().GetAriaMaxConcurrentDownloads();
int downloadingCount;
do
{
downloadingCount = 0;
foreach (DownloadingItem item in downloadingList)
{
if (item.DownloadStatus == DownloadStatus.DOWNLOADING)
{
downloadingCount++;
}
}
// 降低CPU占用
Thread.Sleep(100);
} while (downloadingCount > maxDownloading);
downloading.DownloadStatusTitle = oldStatus;
}
/// <summary>
/// 启动Aria服务器
/// </summary>
private async void StartAriaServer()
{
List<string> header = new List<string>
{
$"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 / 91.0.4472.77 Safari / 537.36"
};
AriaConfig config = new AriaConfig()
{
ListenPort = SettingsManager.GetInstance().GetAriaListenPort(),
Token = "downkyi",
LogLevel = SettingsManager.GetInstance().GetAriaLogLevel(),
MaxConcurrentDownloads = SettingsManager.GetInstance().GetAriaMaxConcurrentDownloads(),
MaxConnectionPerServer = 16, // 最大取16
Split = SettingsManager.GetInstance().GetAriaSplit(),
//MaxTries = 5,
MinSplitSize = 10, // 10MB
MaxOverallDownloadLimit = SettingsManager.GetInstance().GetAriaMaxOverallDownloadLimit() * 1024L, // 输入的单位是KB/s所以需要乘以1024
MaxDownloadLimit = SettingsManager.GetInstance().GetAriaMaxDownloadLimit() * 1024L, // 输入的单位是KB/s所以需要乘以1024
MaxOverallUploadLimit = 0,
MaxUploadLimit = 0,
ContinueDownload = true,
FileAllocation = SettingsManager.GetInstance().GetAriaFileAllocation(),
Headers = header
};
var task = await AriaServer.StartServerAsync(config);
if (task) { Console.WriteLine("Start ServerAsync Completed"); }
Console.WriteLine("Start ServerAsync end");
// 恢复所有下载
//var ariaPause = await AriaClient.UnpauseAllAsync();
//if (ariaPause != null)
//{
// Core.Utils.Debugging.Console.PrintLine(ariaPause.ToString());
//}
}
/// <summary>
/// 关闭Aria服务器
/// </summary>
private void CloseAriaServer()
{
new Thread(() =>
{
// 暂停所有下载
var ariaPause = AriaClient.PauseAllAsync();
Core.Utils.Debugging.Console.PrintLine(ariaPause.ToString());
// 关闭服务器
bool close = AriaServer.CloseServer();
Core.Utils.Debugging.Console.PrintLine(close);
})
{ IsBackground = false }
.Start();
}
/// <summary>
/// 采用Aria下载文件
/// </summary>
/// <param name="downloading"></param>
/// <returns></returns>
private DownloadResult DownloadByAria(DownloadingItem downloading, List<string> urls, string path, string localFileName)
{
// path已斜杠结尾去掉斜杠
path = path.TrimEnd('/').TrimEnd('\\');
AriaSendOption option = new AriaSendOption
{
//HttpProxy = $"http://{Settings.GetAriaHttpProxy()}:{Settings.GetAriaHttpProxyListenPort()}",
Dir = path,
Out = localFileName
//Header = $"cookie: {Login.GetLoginInfoCookiesString()}\nreferer: https://www.bilibili.com",
//UseHead = "true",
//UserAgent = Utils.GetUserAgent()
};
// 如果设置了代理则增加HttpProxy
if (SettingsManager.GetInstance().IsAriaHttpProxy() == AllowStatus.YES)
{
option.HttpProxy = $"http://{SettingsManager.GetInstance().GetAriaHttpProxy()}:{SettingsManager.GetInstance().GetAriaHttpProxyListenPort()}";
}
// 添加一个下载
Task<AriaAddUri> ariaAddUri = AriaClient.AddUriAsync(urls, option);
if (ariaAddUri == null || ariaAddUri.Result == null || ariaAddUri.Result.Result == null)
{
return DownloadResult.FAILED;
}
// 保存gid
string gid = ariaAddUri.Result.Result;
downloading.Gid = gid;
// 管理下载
AriaManager ariaManager = new AriaManager();
ariaManager.TellStatus += AriaTellStatus;
ariaManager.DownloadFinish += AriaDownloadFinish;
return ariaManager.GetDownloadStatus(gid, new Action(() =>
{
switch (downloading.DownloadStatus)
{
case DownloadStatus.PAUSE:
Task<AriaPause> ariaPause = AriaClient.PauseAsync(downloading.Gid);
// 通知UI并阻塞当前线程
Pause(downloading);
break;
case DownloadStatus.DOWNLOADING:
Task<AriaPause> ariaUnpause = AriaClient.UnpauseAsync(downloading.Gid);
break;
}
}));
}
private void AriaTellStatus(long totalLength, long completedLength, long speed, string gid)
{
// 当前的下载视频
DownloadingItem video = downloadingList.FirstOrDefault(it => it.Gid == gid);
if (video == null) { return; }
float percent = 0;
if (totalLength != 0)
{
percent = (float)completedLength / totalLength * 100;
}
// 根据进度判断本次是否需要更新UI
if (Math.Abs(percent - video.Progress) < 0.01) { return; }
// 下载进度
video.Progress = percent;
// 下载大小
video.DownloadingFileSize = Format.FormatFileSize(completedLength) + "/" + Format.FormatFileSize(totalLength);
// 下载速度
video.SpeedDisplay = Format.FormatSpeed(speed);
// 最大下载速度
if (video.MaxSpeed < speed)
{
video.MaxSpeed = speed;
}
}
private void AriaDownloadFinish(bool isSuccess, string downloadPath, string gid, string msg)
{
//throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,25 @@
using DownKyi.Models;
using System.Collections.ObjectModel;
namespace DownKyi.Services.Download
{
public class DownloadService
{
protected string Tag = "DownloadService";
protected ObservableCollection<DownloadingItem> downloadingList;
protected ObservableCollection<DownloadedItem> downloadedList;
/// <summary>
/// 初始化
/// </summary>
/// <param name="downloading"></param>
/// <returns></returns>
public DownloadService(ObservableCollection<DownloadingItem> downloadingList, ObservableCollection<DownloadedItem> downloadedList)
{
this.downloadingList = downloadingList;
this.downloadedList = downloadedList;
}
}
}

View File

@ -0,0 +1,19 @@
using DownKyi.Models;
using System.Collections.Generic;
namespace DownKyi.Services.Download
{
public interface IDownloadService
{
void Parse(DownloadingItem downloading);
string DownloadAudio(DownloadingItem downloading);
string DownloadVideo(DownloadingItem downloading);
string DownloadDanmaku(DownloadingItem downloading);
List<string> DownloadSubtitle(DownloadingItem downloading);
string DownloadCover(DownloadingItem downloading);
string MixedFlow(DownloadingItem downloading, string audioUid, string videoUid);
void Start();
void End();
}
}

View File

@ -26,9 +26,9 @@ namespace DownKyi.Services
page.PlayUrl = playUrl;
// 获取设置
var userInfo = SettingsManager.GetInstance().GetUserInfo();
UserInfoSettings userInfo = SettingsManager.GetInstance().GetUserInfo();
int defaultQuality = SettingsManager.GetInstance().GetQuality();
var videoCodecs = SettingsManager.GetInstance().GetVideoCodecs();
VideoCodecs videoCodecs = SettingsManager.GetInstance().GetVideoCodecs();
int defaultAudioQuality = SettingsManager.GetInstance().GetAudioQuality();
// 未登录时最高仅720P
@ -201,7 +201,7 @@ namespace DownKyi.Services
/// </summary>
/// <param name="origin"></param>
/// <returns></returns>
private static string GetVideoCodecName(string origin)
internal static string GetVideoCodecName(string origin)
{
return origin.Contains("avc") ? "H.264/AVC" : origin.Contains("hev") ? "H.265/HEVC" : "";
}

View File

@ -78,6 +78,7 @@ namespace DownKyi.Services
Bvid = videoView.Bvid,
Cid = page.Cid,
EpisodeId = -1,
FirstFrame = page.FirstFrame,
Order = order,
Name = name,
Duration = "N/A"
@ -114,6 +115,7 @@ namespace DownKyi.Services
Bvid = episode.Bvid,
Cid = episode.Cid,
EpisodeId = -1,
FirstFrame = episode.Page.FirstFrame,
Order = order,
Name = episode.Title,
Duration = "N/A"
@ -160,7 +162,7 @@ namespace DownKyi.Services
// 分区
string videoZone = string.Empty;
var zoneList = Core.BiliApi.Zone.VideoZone.Instance().GetZone();
var zoneList = Core.BiliApi.Zone.VideoZone.Instance().GetZones();
var zone = zoneList.Find(it => it.Id == videoView.Tid);
if (zone != null)
{
@ -203,6 +205,9 @@ namespace DownKyi.Services
videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover));
videoInfoView.Title = videoView.Title;
// 分区id
videoInfoView.TypeId = videoView.Tid;
videoInfoView.VideoZone = videoZone;
DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区

View File

@ -23,6 +23,7 @@
<SolidColorBrush x:Key="BrushForegroundDark" Color="{DynamicResource ColorForegroundDark}" />
<SolidColorBrush x:Key="BrushBackgroundDark" Color="{DynamicResource ColorBackgroundDark}" />
<SolidColorBrush x:Key="BrushForegroundGrey" Color="{DynamicResource ColorForegroundGrey}" />
<SolidColorBrush x:Key="BrushForegroundGrey2" Color="{DynamicResource ColorForegroundGrey2}" />
<SolidColorBrush x:Key="BrushBackgroundGrey" Color="{DynamicResource ColorBackgroundGrey}" />
<SolidColorBrush x:Key="BrushBackgroundGreyTranslucent" Color="{DynamicResource ColorBackgroundGreyTranslucent}" />
<SolidColorBrush x:Key="BrushBackgroundGreyTranslucent2" Color="{DynamicResource ColorBackgroundGreyTranslucent2}" />
@ -34,6 +35,7 @@
<SolidColorBrush x:Key="BrushHeaderGrey" Color="{DynamicResource ColorHeaderGrey}" />
<SolidColorBrush x:Key="BrushBorder" Color="{DynamicResource ColorBorder}" />
<SolidColorBrush x:Key="BrushBorderTranslucent" Color="{DynamicResource ColorBorderTranslucent}" />
<SolidColorBrush x:Key="BrushImageBorder" Color="{DynamicResource ColorImageBorder}" />
<SolidColorBrush x:Key="BrushImageBackground" Color="{DynamicResource ColorImageBackground}" />

View File

@ -23,6 +23,7 @@
<Color x:Key="ColorForegroundDark">#FFFFFFFF</Color>
<Color x:Key="ColorBackgroundDark">#FF00A1D6</Color>
<Color x:Key="ColorForegroundGrey">#FFBDBDBD</Color>
<Color x:Key="ColorForegroundGrey2">#FFE4E4E4</Color>
<Color x:Key="ColorBackgroundGrey">#FFBDBDBD</Color>
<Color x:Key="ColorBackgroundGreyTranslucent">#C8BDBDBD</Color>
<Color x:Key="ColorBackgroundGreyTranslucent2">#7FBDBDBD</Color>
@ -34,6 +35,7 @@
<Color x:Key="ColorHeaderGrey">#FFF4F4F4</Color>
<Color x:Key="ColorBorder">#FF999999</Color>
<Color x:Key="ColorBorderTranslucent">#7F999999</Color>
<Color x:Key="ColorImageBorder">#7FD0D0D0</Color>
<Color x:Key="ColorImageBackground">#7FD0D0D0</Color>

View File

@ -1,5 +1,6 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- 左侧导航栏 -->
<Style x:Key="LeftTabHeaderItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
@ -66,7 +67,7 @@
<Style x:Key="LeftTabHeaderStyle" TargetType="{x:Type ListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ControlTemplate TargetType="{x:Type ListBox}">
<Border
Padding="0"
Background="{DynamicResource BrushTabHeaderGrey}"
@ -81,4 +82,120 @@
</Setter>
</Style>
<!-- TAG样式1 -->
<Style x:Key="TagItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border
Name="Border"
Margin="5,3"
Padding="8,2"
Background="{DynamicResource BrushPrimary}"
CornerRadius="10"
Cursor="Hand">
<ContentPresenter
Name="content"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding Title}" />
</Border>
<ControlTemplate.Triggers>
<!-- 顺序很重要,不能修改 -->
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushBackgroundGrey}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushPrimaryTranslucent}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushPrimary}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TagStyle" TargetType="{x:Type ListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled">
<WrapPanel
IsItemsHost="True"
Orientation="Horizontal"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- TAG样式2 -->
<Style x:Key="TagItem2Style" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border
Name="Border"
Margin="5,3"
Padding="8,2"
Background="{DynamicResource BrushPrimary}"
CornerRadius="10"
Cursor="Hand">
<ContentPresenter
Name="content"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding Title}" />
</Border>
<ControlTemplate.Triggers>
<!-- 顺序很重要,不能修改 -->
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushBackgroundGrey}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushBackgroundGrey}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushPrimaryTranslucent}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Tag2Style" TargetType="{x:Type ListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Border
Padding="5"
Background="{TemplateBinding Background}"
BorderBrush="{DynamicResource BrushBorder}"
BorderThickness="1"
CornerRadius="10">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled">
<WrapPanel
IsItemsHost="True"
Orientation="Horizontal"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -26,7 +26,7 @@ namespace DownKyi.Utils
/// <returns></returns>
public static string GetString(string resourceKey)
{
return (string)Application.Current.Resources[resourceKey];
return Application.Current == null ? "" : (string)Application.Current.Resources[resourceKey];
}
/// <summary>

View File

@ -1,8 +1,10 @@
using Prism.Commands;
using DownKyi.Models;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace DownKyi.ViewModels.DownloadManager
@ -11,9 +13,20 @@ namespace DownKyi.ViewModels.DownloadManager
{
public const string Tag = "PageDownloadManagerDownloadFinished";
#region
private ObservableCollection<DownloadedItem> downloadedList;
public ObservableCollection<DownloadedItem> DownloadedList
{
get { return downloadedList; }
set { SetProperty(ref downloadedList, value); }
}
#endregion
public ViewDownloadFinishedViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
{
DownloadedList = App.DownloadedList;
}
}
}

View File

@ -1,9 +1,9 @@
using Prism.Commands;
using DownKyi.Images;
using DownKyi.Models;
using DownKyi.Utils;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;
namespace DownKyi.ViewModels.DownloadManager
{
@ -11,9 +11,117 @@ namespace DownKyi.ViewModels.DownloadManager
{
public const string Tag = "PageDownloadManagerDownloading";
#region
private ObservableCollection<DownloadingItem> downloadingList;
public ObservableCollection<DownloadingItem> DownloadingList
{
get => downloadingList;
set => SetProperty(ref downloadingList, value);
}
#endregion
public ViewDownloadingViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
{
// 初始化DownloadingList
DownloadingList = App.DownloadingList;
}
#region
// 暂停所有下载事件
private DelegateCommand pauseAllDownloadingCommand;
public DelegateCommand PauseAllDownloadingCommand => pauseAllDownloadingCommand ?? (pauseAllDownloadingCommand = new DelegateCommand(ExecutePauseAllDownloadingCommand));
/// <summary>
/// 暂停所有下载事件
/// </summary>
private void ExecutePauseAllDownloadingCommand()
{
foreach (DownloadingItem downloading in downloadingList)
{
switch (downloading.DownloadStatus)
{
case DownloadStatus.NOT_STARTED:
case DownloadStatus.WAIT_FOR_DOWNLOAD:
downloading.DownloadStatus = DownloadStatus.PAUSE_STARTED;
break;
case DownloadStatus.PAUSE_STARTED:
break;
case DownloadStatus.PAUSE:
break;
case DownloadStatus.DOWNLOADING:
downloading.DownloadStatus = DownloadStatus.PAUSE;
break;
case DownloadStatus.DOWNLOAD_SUCCEED:
// 下载成功后会从下载列表中删除
// 不会出现此分支
break;
case DownloadStatus.DOWNLOAD_FAILED:
break;
default:
break;
}
downloading.StartOrPause = ButtonIcon.Instance().Start;
downloading.StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
}
}
// 继续所有下载事件
private DelegateCommand continueAllDownloadingCommand;
public DelegateCommand ContinueAllDownloadingCommand => continueAllDownloadingCommand ?? (continueAllDownloadingCommand = new DelegateCommand(ExecuteContinueAllDownloadingCommand));
/// <summary>
/// 继续所有下载事件
/// </summary>
private void ExecuteContinueAllDownloadingCommand()
{
foreach (DownloadingItem downloading in downloadingList)
{
switch (downloading.DownloadStatus)
{
case DownloadStatus.NOT_STARTED:
case DownloadStatus.WAIT_FOR_DOWNLOAD:
break;
case DownloadStatus.PAUSE_STARTED:
downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD;
break;
case DownloadStatus.PAUSE:
downloading.DownloadStatus = DownloadStatus.DOWNLOADING;
break;
case DownloadStatus.DOWNLOADING:
break;
case DownloadStatus.DOWNLOAD_SUCCEED:
// 下载成功后会从下载列表中删除
// 不会出现此分支
break;
case DownloadStatus.DOWNLOAD_FAILED:
downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD;
break;
default:
break;
}
downloading.StartOrPause = ButtonIcon.Instance().Pause;
downloading.StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
}
}
// 删除所有下载事件
private DelegateCommand deleteAllDownloadingCommand;
public DelegateCommand DeleteAllDownloadingCommand => deleteAllDownloadingCommand ?? (deleteAllDownloadingCommand = new DelegateCommand(ExecuteDeleteAllDownloadingCommand));
/// <summary>
/// 删除所有下载事件
/// </summary>
private void ExecuteDeleteAllDownloadingCommand()
{
DownloadingList.Clear();
}
#endregion
}
}

View File

@ -304,6 +304,7 @@ namespace DownKyi.ViewModels
/// <param name="e"></param>
private void OnClipboardUpdated(object sender, EventArgs e)
{
#region
times += 1;
DispatcherTimer timer = new DispatcherTimer
{
@ -319,6 +320,8 @@ namespace DownKyi.ViewModels
return;
}
#endregion
AllowStatus isListenClipboard = SettingsManager.GetInstance().IsListenClipboard();
if (isListenClipboard != AllowStatus.YES)
{

View File

@ -1,4 +1,5 @@
using DownKyi.Core.Settings;
using DownKyi.Core.FileName;
using DownKyi.Core.Settings;
using DownKyi.Events;
using DownKyi.Models;
using DownKyi.Services;
@ -6,7 +7,9 @@ using DownKyi.Utils;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace DownKyi.ViewModels.Settings
@ -22,82 +25,76 @@ namespace DownKyi.ViewModels.Settings
private List<string> videoCodecs;
public List<string> VideoCodecs
{
get { return videoCodecs; }
set { SetProperty(ref videoCodecs, value); }
get => videoCodecs;
set => SetProperty(ref videoCodecs, value);
}
private string selectedVideoCodec;
public string SelectedVideoCodec
{
get { return selectedVideoCodec; }
set { SetProperty(ref selectedVideoCodec, value); }
get => selectedVideoCodec;
set => SetProperty(ref selectedVideoCodec, value);
}
private List<Resolution> videoQualityList;
public List<Resolution> VideoQualityList
{
get { return videoQualityList; }
set { SetProperty(ref videoQualityList, value); }
get => videoQualityList;
set => SetProperty(ref videoQualityList, value);
}
private Resolution selectedVideoQuality;
public Resolution SelectedVideoQuality
{
get { return selectedVideoQuality; }
set { SetProperty(ref selectedVideoQuality, value); }
}
private bool isAddVideoOrder;
public bool IsAddVideoOrder
{
get { return isAddVideoOrder; }
set { SetProperty(ref isAddVideoOrder, value); }
get => selectedVideoQuality;
set => SetProperty(ref selectedVideoQuality, value);
}
private bool isTranscodingFlvToMp4;
public bool IsTranscodingFlvToMp4
{
get { return isTranscodingFlvToMp4; }
set { SetProperty(ref isTranscodingFlvToMp4, value); }
get => isTranscodingFlvToMp4;
set => SetProperty(ref isTranscodingFlvToMp4, value);
}
private bool isUseDefaultDirectory;
public bool IsUseDefaultDirectory
{
get { return isUseDefaultDirectory; }
set { SetProperty(ref isUseDefaultDirectory, value); }
get => isUseDefaultDirectory;
set => SetProperty(ref isUseDefaultDirectory, value);
}
private string saveVideoDirectory;
public string SaveVideoDirectory
{
get { return saveVideoDirectory; }
set { SetProperty(ref saveVideoDirectory, value); }
get => saveVideoDirectory;
set => SetProperty(ref saveVideoDirectory, value);
}
private bool isCreateFolderForMedia;
public bool IsCreateFolderForMedia
private ObservableCollection<DisplayFileNamePart> selectedFileName;
public ObservableCollection<DisplayFileNamePart> SelectedFileName
{
get { return isCreateFolderForMedia; }
set { SetProperty(ref isCreateFolderForMedia, value); }
get => selectedFileName;
set => SetProperty(ref selectedFileName, value);
}
private bool isDownloadDanmaku;
public bool IsDownloadDanmaku
private ObservableCollection<DisplayFileNamePart> optionalFields;
public ObservableCollection<DisplayFileNamePart> OptionalFields
{
get { return isDownloadDanmaku; }
set { SetProperty(ref isDownloadDanmaku, value); }
get => optionalFields;
set => SetProperty(ref optionalFields, value);
}
private bool isDownloadCover;
public bool IsDownloadCover
private int selectedOptionalField;
public int SelectedOptionalField
{
get { return isDownloadCover; }
set { SetProperty(ref isDownloadCover, value); }
get => selectedOptionalField;
set => SetProperty(ref selectedOptionalField, value);
}
#endregion
public ViewVideoViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
{
@ -113,6 +110,17 @@ namespace DownKyi.ViewModels.Settings
// 优先下载画质
VideoQualityList = new ResolutionService().GetResolution();
// 文件命名格式
SelectedFileName = new ObservableCollection<DisplayFileNamePart>();
OptionalFields = new ObservableCollection<DisplayFileNamePart>();
foreach (FileNamePart item in Enum.GetValues(typeof(FileNamePart)))
{
string display = DisplayFileNamePart(item);
OptionalFields.Add(new DisplayFileNamePart { Id = item, Title = display });
}
SelectedOptionalField = -1;
#endregion
}
@ -135,10 +143,6 @@ namespace DownKyi.ViewModels.Settings
int quality = SettingsManager.GetInstance().GetQuality();
SelectedVideoQuality = VideoQualityList.FirstOrDefault(t => { return t.Id == quality; });
// 是否在下载的视频前增加序号
AllowStatus isAddOrder = SettingsManager.GetInstance().IsAddOrder();
IsAddVideoOrder = isAddOrder == AllowStatus.YES;
// 是否下载flv视频后转码为mp4
AllowStatus isTranscodingFlvToMp4 = SettingsManager.GetInstance().IsTranscodingFlvToMp4();
IsTranscodingFlvToMp4 = isTranscodingFlvToMp4 == AllowStatus.YES;
@ -150,17 +154,14 @@ namespace DownKyi.ViewModels.Settings
// 默认下载目录
SaveVideoDirectory = SettingsManager.GetInstance().GetSaveVideoRootPath();
// 是否为不同视频分别创建文件夹
AllowStatus isCreateFolderForMedia = SettingsManager.GetInstance().IsCreateFolderForMedia();
IsCreateFolderForMedia = isCreateFolderForMedia == AllowStatus.YES;
// 是否在下载视频的同时下载弹幕
AllowStatus isDownloadDanmaku = SettingsManager.GetInstance().IsDownloadDanmaku();
IsDownloadDanmaku = isDownloadDanmaku == AllowStatus.YES;
// 是否在下载视频的同时下载封面
AllowStatus isDownloadCover = SettingsManager.GetInstance().IsDownloadCover();
IsDownloadCover = isDownloadCover == AllowStatus.YES;
// 文件命名格式
List<FileNamePart> fileNameParts = SettingsManager.GetInstance().GetFileNameParts();
SelectedFileName.Clear();
foreach (FileNamePart item in fileNameParts)
{
string display = DisplayFileNamePart(item);
SelectedFileName.Add(new DisplayFileNamePart { Id = item, Title = display });
}
isOnNavigatedTo = false;
}
@ -199,21 +200,6 @@ namespace DownKyi.ViewModels.Settings
PublishTip(isSucceed);
}
// 是否在下载的视频前增加序号事件
private DelegateCommand IisAddVideoOrderCommand;
public DelegateCommand IsAddVideoOrderCommand => IisAddVideoOrderCommand ?? (IisAddVideoOrderCommand = new DelegateCommand(ExecuteIsAddVideoOrderCommand));
/// <summary>
/// 是否在下载的视频前增加序号事件
/// </summary>
private void ExecuteIsAddVideoOrderCommand()
{
AllowStatus isAddOrder = IsAddVideoOrder ? AllowStatus.YES : AllowStatus.NO;
bool isSucceed = SettingsManager.GetInstance().IsAddOrder(isAddOrder);
PublishTip(isSucceed);
}
// 是否下载flv视频后转码为mp4事件
private DelegateCommand isTranscodingFlvToMp4Command;
public DelegateCommand IsTranscodingFlvToMp4Command => isTranscodingFlvToMp4Command ?? (isTranscodingFlvToMp4Command = new DelegateCommand(ExecuteIsTranscodingFlvToMp4Command));
@ -265,50 +251,62 @@ namespace DownKyi.ViewModels.Settings
}
}
// 是否为不同视频分别创建文件夹事件
private DelegateCommand isCreateFolderForMediaCommand;
public DelegateCommand IsCreateFolderForMediaCommand => isCreateFolderForMediaCommand ?? (isCreateFolderForMediaCommand = new DelegateCommand(ExecuteIsCreateFolderForMediaCommand));
// 选中文件名字段点击事件
private DelegateCommand<object> selectedFileNameCommand;
public DelegateCommand<object> SelectedFileNameCommand => selectedFileNameCommand ?? (selectedFileNameCommand = new DelegateCommand<object>(ExecuteSelectedFileNameCommand));
/// <summary>
/// 是否为不同视频分别创建文件夹事件
/// 选中文件名字段点击事件
/// </summary>
private void ExecuteIsCreateFolderForMediaCommand()
/// <param name="parameter"></param>
private void ExecuteSelectedFileNameCommand(object parameter)
{
AllowStatus isCreateFolderForMedia = IsCreateFolderForMedia ? AllowStatus.YES : AllowStatus.NO;
bool isSucceed = SelectedFileName.Remove((DisplayFileNamePart)parameter);
if (!isSucceed)
{
PublishTip(isSucceed);
return;
}
bool isSucceed = SettingsManager.GetInstance().IsCreateFolderForMedia(isCreateFolderForMedia);
List<FileNamePart> fileName = new List<FileNamePart>();
foreach (DisplayFileNamePart item in SelectedFileName)
{
fileName.Add(item.Id);
}
isSucceed = SettingsManager.GetInstance().SetFileNameParts(fileName);
PublishTip(isSucceed);
}
// 是否在下载视频的同时下载弹幕事件
private DelegateCommand isDownloadDanmakuCommand;
public DelegateCommand IsDownloadDanmakuCommand => isDownloadDanmakuCommand ?? (isDownloadDanmakuCommand = new DelegateCommand(ExecuteIsDownloadDanmakuCommand));
// 可选文件名字段点击事件
private DelegateCommand<object> optionalFieldsCommand;
public DelegateCommand<object> OptionalFieldsCommand => optionalFieldsCommand ?? (optionalFieldsCommand = new DelegateCommand<object>(ExecuteOptionalFieldsCommand));
/// <summary>
/// 是否在下载视频的同时下载弹幕事件
/// 可选文件名字段点击事件
/// </summary>
private void ExecuteIsDownloadDanmakuCommand()
/// <param name="parameter"></param>
private void ExecuteOptionalFieldsCommand(object parameter)
{
AllowStatus isDownloadDanmaku = IsDownloadDanmaku ? AllowStatus.YES : AllowStatus.NO;
if (SelectedOptionalField == -1)
{
return;
}
bool isSucceed = SettingsManager.GetInstance().IsDownloadDanmaku(isDownloadDanmaku);
SelectedFileName.Add((DisplayFileNamePart)parameter);
List<FileNamePart> fileName = new List<FileNamePart>();
foreach (DisplayFileNamePart item in SelectedFileName)
{
fileName.Add(item.Id);
}
bool isSucceed = SettingsManager.GetInstance().SetFileNameParts(fileName);
PublishTip(isSucceed);
SelectedOptionalField = -1;
}
// 是否在下载视频的同时下载封面事件
private DelegateCommand isDownloadCoverCommand;
public DelegateCommand IsDownloadCoverCommand => isDownloadCoverCommand ?? (isDownloadCoverCommand = new DelegateCommand(ExecuteIsDownloadCoverCommand));
/// <summary>
/// 是否在下载视频的同时下载封面事件
/// </summary>
private void ExecuteIsDownloadCoverCommand()
{
AllowStatus isDownloadCover = IsDownloadCover ? AllowStatus.YES : AllowStatus.NO;
bool isSucceed = SettingsManager.GetInstance().IsDownloadCover(isDownloadCover);
PublishTip(isSucceed);
}
#endregion
@ -379,5 +377,54 @@ namespace DownKyi.ViewModels.Settings
}
}
/// <summary>
/// 文件名字段显示
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
private string DisplayFileNamePart(FileNamePart item)
{
string display = string.Empty;
switch (item)
{
case FileNamePart.ORDER:
display = DictionaryResource.GetString("DisplayOrder");
break;
case FileNamePart.SECTION:
display = DictionaryResource.GetString("DisplaySection");
break;
case FileNamePart.MAIN_TITLE:
display = DictionaryResource.GetString("DisplayMainTitle");
break;
case FileNamePart.PAGE_TITLE:
display = DictionaryResource.GetString("DisplayPageTitle");
break;
case FileNamePart.VIDEO_ZONE:
display = DictionaryResource.GetString("DisplayVideoZone");
break;
case FileNamePart.AUDIO_QUALITY:
display = DictionaryResource.GetString("DisplayAudioQuality");
break;
case FileNamePart.VIDEO_QUALITY:
display = DictionaryResource.GetString("DisplayVideoQuality");
break;
case FileNamePart.VIDEO_CODEC:
display = DictionaryResource.GetString("DisplayVideoCodec");
break;
}
if (((int)item) >= 100)
{
display = HyphenSeparated.Hyphen[(int)item];
}
if (display == " ")
{
display = DictionaryResource.GetString("DisplaySpace");
}
return display;
}
}
}

View File

@ -1,6 +1,9 @@
using DownKyi.Core.BiliApi.BiliUtils;
using DownKyi.Core.BiliApi.Zone;
using DownKyi.Core.FileName;
using DownKyi.Core.Logging;
using DownKyi.Core.Settings;
using DownKyi.Core.Utils;
using DownKyi.CustomControl;
using DownKyi.Events;
using DownKyi.Images;
@ -13,11 +16,13 @@ using Prism.Events;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
namespace DownKyi.ViewModels
{
@ -32,76 +37,75 @@ namespace DownKyi.ViewModels
private VectorImage arrowBack;
public VectorImage ArrowBack
{
get { return arrowBack; }
set { SetProperty(ref arrowBack, value); }
get => arrowBack;
set => SetProperty(ref arrowBack, value);
}
private string inputText;
public string InputText
{
get { return inputText; }
set { SetProperty(ref inputText, value); }
get => inputText;
set => SetProperty(ref inputText, value);
}
private GifImage loading;
public GifImage Loading
{
get { return loading; }
set { SetProperty(ref loading, value); }
get => loading;
set => SetProperty(ref loading, value);
}
private Visibility loadingVisibility;
public Visibility LoadingVisibility
{
get { return loadingVisibility; }
set { SetProperty(ref loadingVisibility, value); }
get => loadingVisibility;
set => SetProperty(ref loadingVisibility, value);
}
private VectorImage downloadManage;
public VectorImage DownloadManage
{
get { return downloadManage; }
set { SetProperty(ref downloadManage, value); }
get => downloadManage;
set => SetProperty(ref downloadManage, value);
}
private VideoInfoView videoInfoView;
public VideoInfoView VideoInfoView
{
get { return videoInfoView; }
set { SetProperty(ref videoInfoView, value); }
get => videoInfoView;
set => SetProperty(ref videoInfoView, value);
}
private ObservableCollection<VideoSection> videoSections;
public ObservableCollection<VideoSection> VideoSections
{
get { return videoSections; }
set { SetProperty(ref videoSections, value); }
get => videoSections;
set => SetProperty(ref videoSections, value);
}
private bool isSelectAll;
public bool IsSelectAll
{
get { return isSelectAll; }
set { SetProperty(ref isSelectAll, value); }
get => isSelectAll;
set => SetProperty(ref isSelectAll, value);
}
private Visibility contentVisibility;
public Visibility ContentVisibility
{
get { return contentVisibility; }
set { SetProperty(ref contentVisibility, value); }
get => contentVisibility;
set => SetProperty(ref contentVisibility, value);
}
private Visibility noDataVisibility;
public Visibility NoDataVisibility
{
get { return noDataVisibility; }
set { SetProperty(ref noDataVisibility, value); }
get => noDataVisibility;
set => SetProperty(ref noDataVisibility, value);
}
#endregion
public ViewVideoDetailViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator)
{
this.dialogService = dialogService;
@ -265,7 +269,7 @@ namespace DownKyi.ViewModels
if (!(parameter is VideoSection section)) { return; }
bool isSelectAll = true;
foreach (var page in section.VideoPages)
foreach (VideoPage page in section.VideoPages)
{
if (!page.IsSelected)
{
@ -304,7 +308,7 @@ namespace DownKyi.ViewModels
private void ExecuteKeySelectAllCommand(object parameter)
{
if (!(parameter is VideoSection section)) { return; }
foreach (var page in section.VideoPages)
foreach (VideoPage page in section.VideoPages)
{
page.IsSelected = true;
}
@ -323,14 +327,14 @@ namespace DownKyi.ViewModels
if (!(parameter is VideoSection section)) { return; }
if (IsSelectAll)
{
foreach (var page in section.VideoPages)
foreach (VideoPage page in section.VideoPages)
{
page.IsSelected = true;
}
}
else
{
foreach (var page in section.VideoPages)
foreach (VideoPage page in section.VideoPages)
{
page.IsSelected = false;
}
@ -424,11 +428,11 @@ namespace DownKyi.ViewModels
case ParseScope.NONE:
break;
case ParseScope.SELECTED_ITEM:
foreach (var section in VideoSections)
foreach (VideoSection section in VideoSections)
{
foreach (var page in section.VideoPages)
foreach (VideoPage page in section.VideoPages)
{
var videoPage = section.VideoPages.FirstOrDefault(t => t == page);
VideoPage videoPage = section.VideoPages.FirstOrDefault(t => t == page);
if (videoPage.IsSelected)
{
@ -439,13 +443,13 @@ namespace DownKyi.ViewModels
}
break;
case ParseScope.CURRENT_SECTION:
foreach (var section in VideoSections)
foreach (VideoSection section in VideoSections)
{
if (section.IsSelected)
{
foreach (var page in section.VideoPages)
foreach (VideoPage page in section.VideoPages)
{
var videoPage = section.VideoPages.FirstOrDefault(t => t == page);
VideoPage videoPage = section.VideoPages.FirstOrDefault(t => t == page);
// 执行解析任务
UnityUpdateView(ParseVideo, null, videoPage);
@ -454,11 +458,11 @@ namespace DownKyi.ViewModels
}
break;
case ParseScope.ALL:
foreach (var section in VideoSections)
foreach (VideoSection section in VideoSections)
{
foreach (var page in section.VideoPages)
foreach (VideoPage page in section.VideoPages)
{
var videoPage = section.VideoPages.FirstOrDefault(t => t == page);
VideoPage videoPage = section.VideoPages.FirstOrDefault(t => t == page);
// 执行解析任务
UnityUpdateView(ParseVideo, null, videoPage);
@ -530,12 +534,6 @@ namespace DownKyi.ViewModels
downloadDanmaku = result.Parameters.GetValue<bool>("downloadDanmaku");
downloadSubtitle = result.Parameters.GetValue<bool>("downloadSubtitle");
downloadCover = result.Parameters.GetValue<bool>("downloadCover");
// 文件夹不存在则创建
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
}
});
}
@ -545,8 +543,164 @@ namespace DownKyi.ViewModels
// 这时直接退出
if (directory == string.Empty) { return; }
// 文件夹不存在则创建
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
// 添加视频计数
int i = 0;
// 添加到下载
eventAggregator.GetEvent<MessageEvent>().Publish(directory);
foreach (VideoSection section in VideoSections)
{
foreach (VideoPage page in section.VideoPages)
{
// 只下载选中项,跳过未选中项
if (!page.IsSelected) { continue; }
// 没有解析的也跳过
if (page.PlayUrl == null) { continue; }
// 判断是否同一个视频需要cid、画质、音质、视频编码都相同
// 如果存在正在下载列表,则跳过,并提示
foreach (DownloadingItem item in App.DownloadingList)
{
if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodecName == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec)
{
eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloading")}");
continue;
}
}
// 如果存在下载完成列表,弹出选择框是否再次下载
foreach (DownloadedItem item in App.DownloadedList)
{
if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodecName == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec)
{
eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloaded")}");
continue;
}
}
// 视频分区
int zoneId = -1;
List<ZoneAttr> zoneList = VideoZone.Instance().GetZones();
ZoneAttr zone = zoneList.Find(it => it.Id == VideoInfoView.TypeId);
if (zone != null)
{
ZoneAttr zoneParent = zoneList.Find(it => it.Id == zone.ParentId);
if (zoneParent != null)
{
zoneId = zoneParent.Id;
}
}
// 如果只有一个视频章节,则不在命名中出现
string sectionName = string.Empty;
if (VideoSections.Count > 1)
{
sectionName = section.Title;
}
// 文件路径
List<FileNamePart> fileNameParts = SettingsManager.GetInstance().GetFileNameParts();
FileName fileName = FileName.Builder(fileNameParts)
.SetOrder(page.Order)
.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.QualityFormat)
.SetVideoCodec(page.VideoQuality.SelectedVideoCodec.Contains("AVC") ? "AVC" : page.VideoQuality.SelectedVideoCodec.Contains("HEVC") ? "HEVC" : "");
string filePath = Path.Combine(directory, fileName.RelativePath());
// 视频类别
PlayStreamType playStreamType;
switch (VideoInfoView.TypeId)
{
case -10:
playStreamType = PlayStreamType.CHEESE;
break;
case 13:
case 23:
case 177:
case 167:
case 11:
playStreamType = PlayStreamType.BANGUMI;
break;
case 1:
case 3:
case 129:
case 4:
case 36:
case 188:
case 234:
case 223:
case 160:
case 211:
case 217:
case 119:
case 155:
case 202:
case 5:
case 181:
default:
playStreamType = PlayStreamType.VIDEO;
break;
}
// 如果不存在,直接添加到下载列表
DownloadingItem downloading = new DownloadingItem
{
PlayUrl = page.PlayUrl,
Bvid = page.Bvid,
Avid = page.Avid,
Cid = page.Cid,
EpisodeId = page.EpisodeId,
CoverUrl = page.FirstFrame,
ZoneImage = (DrawingImage)Application.Current.Resources[VideoZoneIcon.Instance().GetZoneImageKey(zoneId)],
Order = page.Order,
MainTitle = VideoInfoView.Title,
Name = page.Name,
Duration = page.Duration,
AudioCodecId = Constant.AudioQualityId[page.AudioQualityFormat],
AudioCodecName = page.AudioQualityFormat,
VideoCodecName = page.VideoQuality.SelectedVideoCodec,
Resolution = new Resolution { Name = page.VideoQuality.QualityFormat, Id = page.VideoQuality.Quality },
FilePath = filePath,
PlayStreamType = playStreamType,
DownloadStatus = DownloadStatus.NOT_STARTED,
};
// 需要下载的内容
downloading.NeedDownloadContent["downloadAudio"] = downloadAudio;
downloading.NeedDownloadContent["downloadVideo"] = downloadVideo;
downloading.NeedDownloadContent["downloadDanmaku"] = downloadDanmaku;
downloading.NeedDownloadContent["downloadSubtitle"] = downloadSubtitle;
downloading.NeedDownloadContent["downloadCover"] = downloadCover;
// 添加到下载列表
App.DownloadingList.Add(downloading);
i++;
}
}
// 通知用户添加到下载列表的结果
if (i == 0)
{
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipAddDownloadingZero"));
}
else
{
eventAggregator.GetEvent<MessageEvent>().Publish($"{DictionaryResource.GetString("TipAddDownloadingFinished1")}{i}{DictionaryResource.GetString("TipAddDownloadingFinished2")}");
}
}
/// <summary>
@ -627,12 +781,12 @@ namespace DownKyi.ViewModels
NoDataVisibility = Visibility.Collapsed;
}
var videoSections = videoInfoService.GetVideoSections();
List<VideoSection> videoSections = videoInfoService.GetVideoSections();
if (videoSections == null)
{
LogManager.Debug(Tag, "videoSections is not exist.");
var pages = videoInfoService.GetVideoPages();
List<VideoPage> pages = videoInfoService.GetVideoPages();
PropertyChangeAsync(new Action(() =>
{

View File

@ -2,9 +2,309 @@
x:Class="DownKyi.Views.DownloadManager.ViewDownloading"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<UserControl.Resources>
<Style x:Key="DownloadingStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid Height="70">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="320" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Width="48"
Height="48"
Source="{Binding ZoneImage}" />
<!-- 标题等视频信息 -->
<Grid Grid.Column="1" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource BrushTextDark}"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding MainTitle}">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}-{1}">
<Binding Path="Order" />
<Binding Path="Name" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<TextBlock
Grid.Row="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextGrey2}">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} · {1} · {2} · {3}">
<Binding Path="Duration" />
<Binding Path="Resolution.Name" />
<Binding Path="VideoCodecName" />
<Binding Path="AudioCodecName" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}" Value="Maximized">
<Setter Property="Width" Value="auto" />
</DataTrigger>
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}" Value="Normal">
<Setter Property="Width" Value="400" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
<!-- 进度条 -->
<Grid Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0" VerticalAlignment="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
HorizontalAlignment="Left"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="DownloadContent" />
<Binding Path="DownloadStatusTitle" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<TextBlock
Grid.Column="1"
HorizontalAlignment="Right"
FontSize="12"
Foreground="{DynamicResource BrushTextGrey2}">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="DownloadingFileSize" />
<Binding Path="SpeedDisplay" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Grid>
<ProgressBar
Grid.Row="1"
Height="20"
VerticalAlignment="Top"
BorderBrush="{x:Null}"
BorderThickness="0"
Value="{Binding Progress}">
<ProgressBar.Style>
<Style TargetType="{x:Type ProgressBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Border
Name="PART_Track"
Background="{DynamicResource BrushForegroundGrey2}"
BorderThickness="0" />
<Border
Name="PART_Indicator"
HorizontalAlignment="Left"
Background="{DynamicResource BrushPrimary}"
BorderThickness="0" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ProgressBar.Style>
</ProgressBar>
</Grid>
<!-- 控制面板,暂停继续删除 -->
<Grid Grid.Column="3">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border
Grid.Column="0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Background="{DynamicResource BrushBackground}"
Cursor="Hand">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding StartOrPauseCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ContentControl>
<Path
Width="{Binding StartOrPause.Width}"
Height="{Binding StartOrPause.Height}"
Data="{Binding StartOrPause.Data}"
Fill="{Binding StartOrPause.Fill}"
Stretch="UniformToFill" />
</ContentControl>
</Border>
<Border
Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Background="{DynamicResource BrushBackground}"
Cursor="Hand">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding DeleteCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ContentControl>
<Path
Width="{Binding Delete.Width}"
Height="{Binding Delete.Height}"
Data="{Binding Delete.Data}"
Fill="{Binding Delete.Fill}"
Stretch="UniformToFill" />
</ContentControl>
</Border>
</Grid>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<TextBlock>正在下载</TextBlock>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="1" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<ListBox
Grid.Row="0"
BorderThickness="0"
ItemContainerStyle="{StaticResource DownloadingStyle}"
ItemsSource="{Binding DownloadingList}">
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border
x:Name="Bd"
Padding="0"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer CanContentScroll="False" Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
</ListBox>
<TextBlock Grid.Row="1" Background="{DynamicResource BrushBorderTranslucent}" />
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="85" />
<ColumnDefinition Width="85" />
<ColumnDefinition Width="85" />
</Grid.ColumnDefinitions>
<StackPanel
Grid.Column="0"
Margin="10,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource TotalDownloading1}" />
<TextBlock
Margin="3,0"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource BrushPrimary}"
Text="{Binding DownloadingList.Count}" />
<TextBlock
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource TotalDownloading2}" />
</StackPanel>
<Button
Grid.Column="1"
Width="75"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding PauseAllDownloadingCommand}"
Content="{DynamicResource PauseAllDownloading}"
FontSize="12"
Style="{StaticResource BtnBorderStyle}" />
<Button
Grid.Column="2"
Width="75"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding ContinueAllDownloadingCommand}"
Content="{DynamicResource ContinueAllDownloading}"
FontSize="12"
Style="{StaticResource BtnBorderStyle}" />
<Button
Grid.Column="3"
Width="75"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding DeleteAllDownloadingCommand}"
Content="{DynamicResource DeleteAllDownloading}"
FontSize="12"
Style="{StaticResource BtnBorderStyle}" />
</Grid>
</Grid>
<!-- TODO 没有数据时显示图片或文字 -->
</Grid>
</UserControl>

View File

@ -54,31 +54,6 @@
</ComboBox>
</StackPanel>
<TextBlock
Height="1"
Margin="0,20,0,0"
Background="{DynamicResource BrushBorder}" />
<StackPanel Margin="0,20,0,0" Orientation="Horizontal">
<CheckBox
Name="nameIsAddVideoOrder"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding IsAddVideoOrderCommand}"
Content="{DynamicResource IsAddVideoOrder}"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding IsAddVideoOrder, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
<TextBlock
Margin="10,0,0,0"
VerticalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource IsAddVideoOrderTip}" />
</StackPanel>
<CheckBox
Margin="0,20,0,0"
HorizontalAlignment="Left"
@ -154,43 +129,73 @@
</StackPanel>
</StackPanel>
<CheckBox
<GroupBox
Margin="0,20,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding IsCreateFolderForMediaCommand}"
Content="{DynamicResource IsCreateFolderForMedia}"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding IsCreateFolderForMedia, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
Padding="10,10"
HorizontalAlignment="Stretch">
<GroupBox.Header>
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource FileNameParts}" />
</GroupBox.Header>
<TextBlock
Height="1"
Margin="0,20,0,0"
Background="{DynamicResource BrushBorder}" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<CheckBox
Margin="0,20,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding IsDownloadDanmakuCommand}"
Content="{DynamicResource IsDownloadDanmaku}"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding IsDownloadDanmaku, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
<TextBlock
Grid.Row="0"
Grid.Column="0"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource FileName}" />
<ListBox
x:Name="nameSelectedFileName"
Grid.Row="0"
Grid.Column="1"
MinHeight="30"
Margin="0,0,0,20"
ItemContainerStyle="{StaticResource TagItem2Style}"
ItemsSource="{Binding SelectedFileName, Mode=TwoWay}"
SelectionMode="Single"
Style="{StaticResource Tag2Style}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectedFileNameCommand}" CommandParameter="{Binding ElementName=nameSelectedFileName, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
<CheckBox
Margin="0,20,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding IsDownloadCoverCommand}"
Content="{DynamicResource IsDownloadCover}"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding IsDownloadCover, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource OptionalFields}" />
<ListBox
Name="nameOptionalFields"
Grid.Row="1"
Grid.Column="1"
ItemContainerStyle="{StaticResource TagItem2Style}"
ItemsSource="{Binding OptionalFields, Mode=TwoWay}"
SelectedIndex="{Binding SelectedOptionalField}"
SelectionMode="Single"
Style="{StaticResource Tag2Style}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding OptionalFieldsCommand}" CommandParameter="{Binding ElementName=nameOptionalFields, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
</Grid>
</GroupBox>
</StackPanel>
</ScrollViewer>

View File

@ -558,6 +558,7 @@
<ListBox
x:Name="nameVideoSections"
Grid.Row="0"
ItemContainerStyle="{StaticResource TagItemStyle}"
ItemsSource="{Binding VideoSections, Mode=TwoWay}"
SelectionMode="Single">
<i:Interaction.Triggers>
@ -566,7 +567,7 @@
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Style BasedOn="{StaticResource TagStyle}" TargetType="{x:Type ListBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding VideoSections.Count}" Value="0">
<Setter Property="Height" Value="0" />
@ -577,56 +578,6 @@
</Style.Triggers>
</Style>
</ListBox.Style>
<ListBox.Template>
<ControlTemplate TargetType="{x:Type ListBox}">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled">
<WrapPanel
IsItemsHost="True"
Orientation="Horizontal"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border
Name="Border"
Margin="5,3"
Padding="8,2"
Background="{DynamicResource BrushPrimary}"
CornerRadius="10"
Cursor="Hand">
<ContentPresenter
Name="content"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding Title}" />
</Border>
<ControlTemplate.Triggers>
<!-- 顺序很重要,不能修改 -->
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushBackgroundGrey}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushPrimaryTranslucent}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushPrimary}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
<!-- 视频分P -->