PagePublicFavorites页面设计完成

pull/252/head
flyself 3 years ago
parent 961a5b66c3
commit 4d7e65cee0

63
src/.gitattributes vendored

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

363
src/.gitignore vendored

@ -0,0 +1,363 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

@ -69,7 +69,7 @@ namespace DownKyi.Core.Aria2cNet
}
if (status.Result.Result.ErrorCode != null && status.Result.Result.ErrorCode != "0")
{
Utils.Debug.Console.PrintLine("ErrorMessage: " + status.Result.Result.ErrorMessage);
Utils.Debugging.Console.PrintLine("ErrorMessage: " + status.Result.Result.ErrorMessage);
LogManager.Error("AriaManager", status.Result.Result.ErrorMessage);
//// 如果返回状态码不是200则继续
@ -81,7 +81,7 @@ namespace DownKyi.Core.Aria2cNet
// aira中删除记录
var ariaRemove1 = AriaClient.RemoveDownloadResultAsync(gid);
Utils.Debug.Console.PrintLine(ariaRemove1);
Utils.Debugging.Console.PrintLine(ariaRemove1);
LogManager.Debug("AriaManager", ariaRemove1.Result.Result);
// 返回回调信息,退出函数

@ -1093,7 +1093,7 @@ namespace DownKyi.Core.Aria2cNet.Client
}
catch (WebException e)
{
Utils.Debug.Console.PrintLine("Request()发生Web异常: {0}", e);
Utils.Debugging.Console.PrintLine("Request()发生Web异常: {0}", e);
LogManager.Error("AriaClient", e);
//return Request(url, parameters, retry - 1);
@ -1114,13 +1114,13 @@ namespace DownKyi.Core.Aria2cNet.Client
}
catch (IOException e)
{
Utils.Debug.Console.PrintLine("Request()发生IO异常: {0}", e);
Utils.Debugging.Console.PrintLine("Request()发生IO异常: {0}", e);
LogManager.Error("AriaClient", e);
return Request(url, parameters, retry - 1);
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("Request()发生其他异常: {0}", e);
Utils.Debugging.Console.PrintLine("Request()发生其他异常: {0}", e);
LogManager.Error("AriaClient", e);
return Request(url, parameters, retry - 1);
}

@ -71,7 +71,7 @@ namespace DownKyi.Core.Aria2cNet.Server
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("StartServerAsync()发生其他异常: {0}", e);
Utils.Debugging.Console.PrintLine("StartServerAsync()发生其他异常: {0}", e);
LogManager.Error("AriaServer", e);
}
}
@ -111,7 +111,7 @@ namespace DownKyi.Core.Aria2cNet.Server
null, (s, e) =>
{
if (e.Data == null || e.Data == "" || e.Data.Replace(" ", "") == "") { return; }
Utils.Debug.Console.PrintLine(e.Data);
Utils.Debugging.Console.PrintLine(e.Data);
LogManager.Debug("AriaServer", e.Data);
if (output != null && window != null)
@ -196,7 +196,7 @@ namespace DownKyi.Core.Aria2cNet.Server
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("KillServer()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("KillServer()发生异常: {0}", e);
LogManager.Error("AriaServer", e);
}
}

@ -27,7 +27,7 @@ namespace DownKyi.Core.BiliApi.Bangumi
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("BangumiMediaInfo()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("BangumiMediaInfo()发生异常: {0}", e);
LogManager.Error("BangumiInfo", e);
return null;
}
@ -58,7 +58,7 @@ namespace DownKyi.Core.BiliApi.Bangumi
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("BangumiSeasonInfo()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("BangumiSeasonInfo()发生异常: {0}", e);
LogManager.Error("BangumiInfo", e);
return null;
}

@ -19,7 +19,10 @@ namespace DownKyi.Core.BiliApi.BiliUtils
public static class ParseEntrance
{
public static readonly string WwwUrl = "https://www.bilibili.com";
public static readonly string ShareWwwUrl = "https://www.bilibili.com/s";
public static readonly string ShortUrl = "https://b23.tv/";
public static readonly string MobileUrl = "https://m.bilibili.com";
public static readonly string SpaceUrl = "https://space.bilibili.com";
public static readonly string VideoUrl = $"{WwwUrl}/video/";
@ -492,8 +495,18 @@ namespace DownKyi.Core.BiliApi.BiliUtils
string url = EnableHttps(input);
url = DeleteUrlParam(url);
url = url.Replace(ShareWwwUrl, WwwUrl);
url = url.Replace(MobileUrl, WwwUrl);
if (url.Contains("b23.tv/ss") || url.Contains("b23.tv/ep"))
{
url = url.Replace(ShortUrl, BangumiUrl);
}
else
{
url = url.Replace(ShortUrl, VideoUrl);
}
if (!url.StartsWith(baseUrl)) { return ""; }
return url.Replace(baseUrl, "");

@ -33,7 +33,7 @@ namespace DownKyi.Core.BiliApi.Cheese
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("CheeseViewInfo()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("CheeseViewInfo()发生异常: {0}", e);
LogManager.Error("CheeseInfo", e);
return null;
}
@ -60,7 +60,7 @@ namespace DownKyi.Core.BiliApi.Cheese
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("CheeseEpisodeList()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("CheeseEpisodeList()发生异常: {0}", e);
LogManager.Error("CheeseInfo", e);
return null;
}

@ -35,7 +35,7 @@ namespace DownKyi.Core.BiliApi.Danmaku
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("GetDanmakuProto()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("GetDanmakuProto()发生异常: {0}", e);
//Logging.LogManager.Error(e);
}
@ -72,7 +72,7 @@ namespace DownKyi.Core.BiliApi.Danmaku
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("GetDanmakuProto()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("GetDanmakuProto()发生异常: {0}", e);
//Logging.LogManager.Error(e);
return null;
}

@ -0,0 +1,142 @@
using DownKyi.Core.BiliApi.Favorites.Models;
using DownKyi.Core.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Favorites
{
public static class FavoritesInfo
{
/// <summary>
/// 获取收藏夹元数据
/// </summary>
/// <param name="mediaId"></param>
public static FavoritesMetaInfo GetFavoritesInfo(long mediaId)
{
string url = $"https://api.bilibili.com/x/v3/fav/folder/info?media_id={mediaId}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
try
{
var info = JsonConvert.DeserializeObject<FavoritesMetaInfoOrigin>(response);
if (info != null) { return info.Data; }
else { return null; }
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetFavoritesInfo()发生异常: {0}", e);
LogManager.Error("FavoritesInfo", e);
return null;
}
}
/// <summary>
/// 查询用户创建的视频收藏夹
/// </summary>
/// <param name="mid">目标用户UID</param>
/// <param name="pn">页码</param>
/// <param name="ps">每页项数</param>
/// <returns></returns>
public static List<FavoritesMetaInfo> GetCreatedFavorites(long mid, int pn, int ps)
{
string url = $"https://api.bilibili.com/x/v3/fav/folder/created/list?up_mid={mid}&pn={pn}&ps={ps}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
try
{
var favorites = JsonConvert.DeserializeObject<FavoritesListOrigin>(response);
if (favorites == null || favorites.Data == null || favorites.Data.List == null)
{ return null; }
return favorites.Data.List;
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetCreatedFavorites()发生异常: {0}", e);
LogManager.Error("FavoritesInfo", e);
return null;
}
}
/// <summary>
/// 查询所有的用户创建的视频收藏夹
/// </summary>
/// <param name="mid">目标用户UID</param>
/// <returns></returns>
public static List<FavoritesMetaInfo> GetAllCreatedFavorites(long mid)
{
List<FavoritesMetaInfo> result = new List<FavoritesMetaInfo>();
int i = 0;
while (true)
{
i++;
int ps = 50;
var data = GetCreatedFavorites(mid, i, ps);
if (data == null || data.Count == 0)
{ break; }
result.AddRange(data);
}
return result;
}
/// <summary>
/// 查询用户收藏的视频收藏夹
/// </summary>
/// <param name="mid">目标用户UID</param>
/// <param name="pn">页码</param>
/// <param name="ps">每页项数</param>
/// <returns></returns>
public static List<FavoritesMetaInfo> GetCollectedFavorites(long mid, int pn, int ps)
{
string url = $"https://api.bilibili.com/x/v3/fav/folder/collected/list?up_mid={mid}&pn={pn}&ps={ps}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
try
{
var favorites = JsonConvert.DeserializeObject<FavoritesListOrigin>(response);
if (favorites == null || favorites.Data == null || favorites.Data.List == null)
{ return null; }
return favorites.Data.List;
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("GetCollectedFavorites()发生异常: {0}", e);
LogManager.Error("FavoritesInfo", e);
return null;
}
}
/// <summary>
/// 查询所有的用户收藏的视频收藏夹
/// </summary>
/// <param name="mid">目标用户UID</param>
/// <returns></returns>
public static List<FavoritesMetaInfo> GetAllCollectedFavorites(long mid)
{
List<FavoritesMetaInfo> result = new List<FavoritesMetaInfo>();
int i = 0;
while (true)
{
i++;
int ps = 50;
var data = GetCollectedFavorites(mid, i, ps);
if (data == null || data.Count == 0)
{ break; }
result.AddRange(data);
}
return result;
}
}
}

@ -0,0 +1,91 @@
using DownKyi.Core.BiliApi.Favorites.Models;
using DownKyi.Core.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Favorites
{
public static class FavoritesResource
{
/// <summary>
/// 获取收藏夹内容明细列表
/// </summary>
/// <param name="mediaId">收藏夹ID</param>
/// <param name="pn">页码</param>
/// <param name="ps">每页项数</param>
/// <returns></returns>
public static List<FavoritesMedia> GetFavoritesMedia(long mediaId, int pn, int ps)
{
string url = $"https://api.bilibili.com/x/v3/fav/resource/list?media_id={mediaId}&pn={pn}&ps={ps}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
try
{
var resource = JsonConvert.DeserializeObject<FavoritesMediaResourceOrigin>(response);
if (resource == null || resource.Data == null || resource.Data.Medias == null)
{ return null; }
return resource.Data.Medias;
}
catch (Exception e)
{
Console.WriteLine("GetFavoritesMedia()发生异常: {0}", e);
LogManager.Error("FavoritesResource", e);
return null;
}
}
/// <summary>
/// 获取收藏夹内容明细列表(全部)
/// </summary>
/// <param name="mediaId">收藏夹ID</param>
/// <returns></returns>
public static List<FavoritesMedia> GetAllFavoritesMedia(long mediaId)
{
List<FavoritesMedia> result = new List<FavoritesMedia>();
int i = 0;
while (true)
{
i++;
int ps = 20;
var data = GetFavoritesMedia(mediaId, i, ps);
if (data == null || data.Count == 0)
{ break; }
result.AddRange(data);
}
return result;
}
/// <summary>
/// 获取收藏夹全部内容id
/// </summary>
/// <param name="mediaId"></param>
/// <returns></returns>
public static List<FavoritesMediaId> GetFavoritesMediaId(long mediaId)
{
string url = $"https://api.bilibili.com/x/v3/fav/resource/ids?media_id={mediaId}";
string referer = "https://www.bilibili.com";
string response = WebClient.RequestWeb(url, referer);
try
{
var media = JsonConvert.DeserializeObject<FavoritesMediaIdOrigin>(response);
if (media == null || media.Data == null)
{ return null; }
return media.Data;
}
catch (Exception e)
{
Console.WriteLine("GetFavoritesMediaId()发生异常: {0}", e);
LogManager.Error("FavoritesResource", e);
return null;
}
}
}
}

@ -0,0 +1,17 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.Favorites.Models
{
public class FavStatus : BaseModel
{
[JsonProperty("collect")]
public long Collect { get; set; }
[JsonProperty("play")]
public long Play { get; set; }
[JsonProperty("thumb_up")]
public long ThumbUp { get; set; }
[JsonProperty("share")]
public long Share { get; set; }
}
}

@ -0,0 +1,19 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.Favorites.Models
{
public class FavUpper : BaseModel
{
[JsonProperty("mid")]
public long Mid { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("face")]
public string Face { get; set; }
[JsonProperty("followed")]
public bool Followed { get; set; }
// vip_type
// vip_statue
}
}

@ -0,0 +1,30 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Favorites.Models
{
// https://api.bilibili.com/x/v3/fav/folder/collected/list
public class FavoritesListOrigin : 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 FavoritesList Data { get; set; }
}
public class FavoritesList : BaseModel
{
[JsonProperty("count")]
public int Count { get; set; }
[JsonProperty("list")]
public List<FavoritesMetaInfo> List { get; set; }
[JsonProperty("has_more")]
public int HasMore { get; set; }
}
}

@ -0,0 +1,43 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.Favorites.Models
{
public class FavoritesMedia : BaseModel
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("type")]
public int Type { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("cover")]
public string Cover { get; set; }
[JsonProperty("intro")]
public string Intro { get; set; }
[JsonProperty("page")]
public int Page { get; set; }
[JsonProperty("duration")]
public long Duration { get; set; }
[JsonProperty("upper")]
public FavUpper Upper { get; set; }
// attr
[JsonProperty("cnt_info")]
public MediaStatus CntInfo { get; set; }
[JsonProperty("link")]
public string Link { get; set; }
[JsonProperty("ctime")]
public long Ctime { get; set; }
[JsonProperty("pubtime")]
public long Pubtime { get; set; }
[JsonProperty("fav_time")]
public long FavTime { get; set; }
[JsonProperty("bv_id")]
public string BvId { get; set; }
[JsonProperty("bvid")]
public string Bvid { get; set; }
// season
// ogv
// ugc
}
}

@ -0,0 +1,32 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Favorites.Models
{
// https://api.bilibili.com/x/v3/fav/resource/ids
public class FavoritesMediaIdOrigin : 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 List<FavoritesMediaId> Data { get; set; }
}
public class FavoritesMediaId : BaseModel
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("type")]
public int Type { get; set; }
[JsonProperty("bv_id")]
public string BvId { get; set; }
[JsonProperty("bvid")]
public string Bvid { get; set; }
}
}

@ -0,0 +1,30 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.Favorites.Models
{
// https://api.bilibili.com/x/v3/fav/resource/list
public class FavoritesMediaResourceOrigin : 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 FavoritesMediaResource Data { get; set; }
}
public class FavoritesMediaResource : BaseModel
{
[JsonProperty("info")]
public FavoritesMetaInfo Info { get; set; }
[JsonProperty("medias")]
public List<FavoritesMedia> Medias { get; set; }
[JsonProperty("has_more")]
public bool HasMore { get; set; }
}
}

@ -0,0 +1,53 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.Favorites.Models
{
// https://api.bilibili.com/x/v3/fav/folder/info
public class FavoritesMetaInfoOrigin : 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 FavoritesMetaInfo Data { get; set; }
}
public class FavoritesMetaInfo : BaseModel
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("fid")]
public long Fid { get; set; }
[JsonProperty("mid")]
public long Mid { get; set; }
// attr
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("cover")]
public string Cover { get; set; }
[JsonProperty("upper")]
public FavUpper Upper { get; set; }
// cover_type
[JsonProperty("cnt_info")]
public FavStatus CntInfo { get; set; }
// type
[JsonProperty("intro")]
public string Intro { get; set; }
[JsonProperty("ctime")]
public long Ctime { get; set; }
[JsonProperty("mtime")]
public long Mtime { get; set; }
// state
[JsonProperty("fav_state")]
public int FavState { get; set; }
[JsonProperty("like_state")]
public int LikeState { get; set; }
[JsonProperty("media_count")]
public int MediaCount { get; set; }
}
}

@ -0,0 +1,15 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
namespace DownKyi.Core.BiliApi.Favorites.Models
{
public class MediaStatus : BaseModel
{
[JsonProperty("collect")]
public long Collect { get; set; }
[JsonProperty("play")]
public long Play { get; set; }
[JsonProperty("danmaku")]
public long Danmaku { get; set; }
}
}

@ -38,7 +38,7 @@ namespace DownKyi.Core.BiliApi.Login
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("SaveLoginInfoCookies()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("SaveLoginInfoCookies()发生异常: {0}", e);
Logging.LogManager.Error(e);
return false;
}
@ -70,7 +70,7 @@ namespace DownKyi.Core.BiliApi.Login
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("GetLoginInfoCookies()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("GetLoginInfoCookies()发生异常: {0}", e);
Logging.LogManager.Error(e);
if (File.Exists(tempFile))
{
@ -135,7 +135,7 @@ namespace DownKyi.Core.BiliApi.Login
}
catch (IOException e)
{
Utils.Debug.Console.PrintLine("Logout()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("Logout()发生异常: {0}", e);
Logging.LogManager.Error(e);
return false;
}

@ -31,7 +31,7 @@ namespace DownKyi.Core.BiliApi.Login
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("GetUserInfoForNavigation()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("GetUserInfoForNavigation()发生异常: {0}", e);
LogManager.Error("LoginInfo", e);
return null;
}

@ -31,7 +31,7 @@ namespace DownKyi.Core.BiliApi.Login
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("GetLoginUrl()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("GetLoginUrl()发生异常: {0}", e);
LogManager.Error("LoginQR", e);
return null;
}
@ -86,7 +86,7 @@ namespace DownKyi.Core.BiliApi.Login
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("GetLoginInfo()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("GetLoginInfo()发生异常: {0}", e);
LogManager.Error("LoginQR", e);
return null;
}
@ -106,7 +106,7 @@ namespace DownKyi.Core.BiliApi.Login
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("GetLoginQRCode()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("GetLoginQRCode()发生异常: {0}", e);
LogManager.Error("LoginQR", e);
return null;
}

@ -30,7 +30,7 @@ namespace DownKyi.Core.BiliApi.Video
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("RegionDynamicList()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("RegionDynamicList()发生异常: {0}", e);
LogManager.Error("Dynamic", e);
return null;
}

@ -30,7 +30,7 @@ namespace DownKyi.Core.BiliApi.Video
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("RegionRankingList()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("RegionRankingList()发生异常: {0}", e);
LogManager.Error("Ranking", e);
return null;
}

@ -33,7 +33,7 @@ namespace DownKyi.Core.BiliApi.Video
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("VideoInfo()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("VideoInfo()发生异常: {0}", e);
LogManager.Error("VideoInfo", e);
return null;
}
@ -64,7 +64,7 @@ namespace DownKyi.Core.BiliApi.Video
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("VideoDescription()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("VideoDescription()发生异常: {0}", e);
LogManager.Error("VideoInfo", e);
return null;
}
@ -95,7 +95,7 @@ namespace DownKyi.Core.BiliApi.Video
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("VideoPagelist()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("VideoPagelist()发生异常: {0}", e);
LogManager.Error("VideoInfo", e);
return null;
}

@ -91,7 +91,7 @@ namespace DownKyi.Core.BiliApi.VideoStream
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("GetPlayUrl()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("GetPlayUrl()发生异常: {0}", e);
LogManager.Error("GetPlayUrl", e);
return null;
}

@ -140,6 +140,16 @@
<Compile Include="BiliApi\Cheese\Models\CheeseView.cs" />
<Compile Include="BiliApi\Danmaku\DanmakuProtobuf.cs" />
<Compile Include="BiliApi\Danmaku\Models\BiliDanmaku.cs" />
<Compile Include="BiliApi\Favorites\FavoritesInfo.cs" />
<Compile Include="BiliApi\Favorites\FavoritesResource.cs" />
<Compile Include="BiliApi\Favorites\Models\FavoritesList.cs" />
<Compile Include="BiliApi\Favorites\Models\FavoritesMedia.cs" />
<Compile Include="BiliApi\Favorites\Models\FavoritesMediaId.cs" />
<Compile Include="BiliApi\Favorites\Models\FavoritesMediaResource.cs" />
<Compile Include="BiliApi\Favorites\Models\FavoritesMetaInfo.cs" />
<Compile Include="BiliApi\Favorites\Models\FavStatus.cs" />
<Compile Include="BiliApi\Favorites\Models\FavUpper.cs" />
<Compile Include="BiliApi\Favorites\Models\MediaStatus.cs" />
<Compile Include="BiliApi\Login\LoginHelper.cs" />
<Compile Include="BiliApi\Models\BaseModel.cs" />
<Compile Include="BiliApi\Login\LoginInfo.cs" />
@ -227,7 +237,7 @@
<Compile Include="Storage\StorageHeader.cs" />
<Compile Include="Storage\StorageManager.cs" />
<Compile Include="Storage\StorageUtils.cs" />
<Compile Include="Utils\Debug\Console.cs" />
<Compile Include="Utils\Debugging\Console.cs" />
<Compile Include="Utils\Encryptor\Encryptor.File.cs" />
<Compile Include="Utils\Encryptor\Encryptor.String.cs" />
<Compile Include="Utils\Encryptor\Hash.cs" />

@ -1,4 +1,6 @@
using System.Collections.Generic;
using DownKyi.Core.Logging;
using System;
using System.Collections.Generic;
namespace DownKyi.Core.Storage.Database
{
@ -26,8 +28,16 @@ namespace DownKyi.Core.Storage.Database
/// <param name="cover"></param>
public void Insert(Cover cover)
{
string sql = $"insert into cover values ({cover.Avid}, '{cover.Bvid}', {cover.Cid}, '{cover.Url}', '{cover.Md5}')";
dbHelper.ExecuteNonQuery(sql);
try
{
string sql = $"insert into cover values ({cover.Avid}, '{cover.Bvid}', {cover.Cid}, '{cover.Url}', '{cover.Md5}')";
dbHelper.ExecuteNonQuery(sql);
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("Insert()发生异常: {0}", e);
LogManager.Error("CoverDb", e);
}
}
/// <summary>
@ -36,8 +46,17 @@ namespace DownKyi.Core.Storage.Database
/// <param name="cover"></param>
public void Update(Cover cover)
{
string sql = $"update cover set avid={cover.Avid}, bvid='{cover.Bvid}', cid={cover.Cid}, md5='{cover.Md5}' where url glob '{cover.Url}'";
dbHelper.ExecuteNonQuery(sql);
try
{
string sql = $"update cover set avid={cover.Avid}, bvid='{cover.Bvid}', cid={cover.Cid}, md5='{cover.Md5}' where url glob '{cover.Url}'";
dbHelper.ExecuteNonQuery(sql);
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("Update()发生异常: {0}", e);
LogManager.Error("CoverDb", e);
}
}
/// <summary>

@ -1,4 +1,6 @@
using System.Collections.Generic;
using DownKyi.Core.Logging;
using System;
using System.Collections.Generic;
namespace DownKyi.Core.Storage.Database
{
@ -26,8 +28,16 @@ namespace DownKyi.Core.Storage.Database
/// <param name="header"></param>
public void Insert(Header header)
{
string sql = $"insert into header values ({header.Mid}, '{header.Name}', '{header.Url}', '{header.Md5}')";
dbHelper.ExecuteNonQuery(sql);
try
{
string sql = $"insert into header values ({header.Mid}, '{header.Name}', '{header.Url}', '{header.Md5}')";
dbHelper.ExecuteNonQuery(sql);
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("Insert()发生异常: {0}", e);
LogManager.Error("HeaderDb", e);
}
}
/// <summary>
@ -36,8 +46,16 @@ namespace DownKyi.Core.Storage.Database
/// <param name="header"></param>
public void Update(Header header)
{
string sql = $"update header set name='{header.Name}', url='{header.Url}', md5='{header.Md5}' where mid={header.Mid}";
dbHelper.ExecuteNonQuery(sql);
try
{
string sql = $"update header set name='{header.Name}', url='{header.Url}', md5='{header.Md5}' where mid={header.Mid}";
dbHelper.ExecuteNonQuery(sql);
}
catch (Exception e)
{
Utils.Debugging.Console.PrintLine("Update()发生异常: {0}", e);
LogManager.Error("HeaderDb", e);
}
}
/// <summary>
@ -89,7 +107,7 @@ namespace DownKyi.Core.Storage.Database
Mid = (long)reader["mid"],
Name = (string)reader["name"],
Url = (string)reader["url"],
Md5=(string)reader["md5"]
Md5 = (string)reader["md5"]
};
headers.Add(header);
}

@ -161,7 +161,14 @@ namespace DownKyi.Core.Storage
if (File.Exists(localFile))
{
File.Move(localFile, $"{StorageManager.GetCover()}/{md5}");
string destFile = $"{StorageManager.GetCover()}/{md5}";
// 如果不存在
if (!File.Exists(destFile))
{
// 移动到指定位置
File.Move(localFile, destFile);
}
return md5;
}
@ -172,7 +179,7 @@ namespace DownKyi.Core.Storage
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("DownloadImage()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("DownloadImage()发生异常: {0}", e);
LogManager.Error("StorageCover", e);
return null;
}

@ -151,7 +151,7 @@ namespace DownKyi.Core.Storage
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("DownloadImage()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("DownloadImage()发生异常: {0}", e);
LogManager.Error("StorageHeader", e);
return null;
}

@ -25,7 +25,7 @@ namespace DownKyi.Core.Storage
}
catch (Exception e)
{
Utils.Debug.Console.PrintLine("DownloadImage()发生异常: {0}", e);
Utils.Debugging.Console.PrintLine("DownloadImage()发生异常: {0}", e);
LogManager.Error("StorageUtils", e);
return false;
}

@ -1,4 +1,4 @@
namespace DownKyi.Core.Utils.Debug
namespace DownKyi.Core.Utils.Debugging
{
public static class Console
{

@ -32,7 +32,7 @@ namespace DownKyi.Core.Utils.Encryptor
}
catch (Exception e)
{
Debug.Console.PrintLine("EncryptString()发生异常: {0}", e);
Debugging.Console.PrintLine("EncryptString()发生异常: {0}", e);
LogManager.Error("Encryptor", e);
return encryptString;
}
@ -60,7 +60,7 @@ namespace DownKyi.Core.Utils.Encryptor
}
catch (Exception e)
{
Debug.Console.PrintLine("DecryptString()发生异常: {0}", e);
Debugging.Console.PrintLine("DecryptString()发生异常: {0}", e);
LogManager.Error("Encryptor", e);
return decryptString;
}

@ -46,7 +46,7 @@ namespace DownKyi.Core.Utils
// 添加cookie
cookieContainer.Add(new Cookie(name, value, "/", ".bilibili.com") { Expires = dateTime });
Debug.Console.PrintLine(name + ": " + value + "\t" + cookieContainer.Count);
Debugging.Console.PrintLine(name + ": " + value + "\t" + cookieContainer.Count);
}
return cookieContainer;
@ -115,24 +115,24 @@ namespace DownKyi.Core.Utils
{
using (Stream stream = File.Create(file))
{
Debug.Console.PrintLine("Writing object to disk... ");
Debugging.Console.PrintLine("Writing object to disk... ");
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
Debug.Console.PrintLine("Done.");
Debugging.Console.PrintLine("Done.");
return true;
}
}
catch (IOException e)
{
Debug.Console.PrintLine("WriteObjectToDisk()发生IO异常: {0}", e);
Debugging.Console.PrintLine("WriteObjectToDisk()发生IO异常: {0}", e);
Logging.LogManager.Error(e);
return false;
}
catch (Exception e)
{
Debug.Console.PrintLine("WriteObjectToDisk()发生异常: {0}", e);
Debugging.Console.PrintLine("WriteObjectToDisk()发生异常: {0}", e);
Logging.LogManager.Error(e);
return false;
}
@ -149,21 +149,21 @@ namespace DownKyi.Core.Utils
{
using (Stream stream = File.Open(file, FileMode.Open))
{
Debug.Console.PrintLine("Reading object from disk... ");
Debugging.Console.PrintLine("Reading object from disk... ");
BinaryFormatter formatter = new BinaryFormatter();
Debug.Console.PrintLine("Done.");
Debugging.Console.PrintLine("Done.");
return formatter.Deserialize(stream);
}
}
catch (IOException e)
{
Debug.Console.PrintLine("ReadObjectFromDisk()发生IO异常: {0}", e);
Debugging.Console.PrintLine("ReadObjectFromDisk()发生IO异常: {0}", e);
Logging.LogManager.Error(e);
return null;
}
catch (Exception e)
{
Debug.Console.PrintLine("ReadObjectFromDisk()发生异常: {0}", e);
Debugging.Console.PrintLine("ReadObjectFromDisk()发生异常: {0}", e);
Logging.LogManager.Error(e);
return null;
}

@ -63,7 +63,7 @@ namespace DownKyi
containerRegistry.RegisterForNavigation<ViewExtractMedia>(ViewExtractMediaViewModel.Tag);
// dialogs
containerRegistry.RegisterDialog<ViewDirectorySelector>(ViewDirectorySelectorViewModel.Tag);
containerRegistry.RegisterDialog<ViewDownloadSetter>(ViewDownloadSetterViewModel.Tag);
containerRegistry.RegisterDialog<ViewParsingSelector>(ViewParsingSelectorViewModel.Tag);
}

@ -87,6 +87,8 @@
<Compile Include="Images\LogoIcon.cs" />
<Compile Include="Images\NavigationIcon.cs" />
<Compile Include="Images\NormalIcon.cs" />
<Compile Include="Models\Favorites.cs" />
<Compile Include="Models\FavoritesMedia.cs" />
<Compile Include="Models\ParseScopeDisplay.cs" />
<Compile Include="Models\Resolution.cs" />
<Compile Include="Models\TabHeader.cs" />
@ -96,6 +98,8 @@
<Compile Include="Models\VideoSection.cs" />
<Compile Include="Services\BangumiInfoService.cs" />
<Compile Include="Services\CheeseInfoService.cs" />
<Compile Include="Services\FavoritesService.cs" />
<Compile Include="Services\IFavoritesService.cs" />
<Compile Include="Services\IInfoService.cs" />
<Compile Include="Services\IResolutionService.cs" />
<Compile Include="Services\ResolutionService.cs" />
@ -104,8 +108,9 @@
<Compile Include="Utils\ClipboardHooker.cs" />
<Compile Include="Utils\DialogUtils.cs" />
<Compile Include="Utils\DictionaryResource.cs" />
<Compile Include="Utils\NavigateToView.cs" />
<Compile Include="ViewModels\BaseViewModel.cs" />
<Compile Include="ViewModels\Dialogs\ViewDirectorySelectorViewModel.cs" />
<Compile Include="ViewModels\Dialogs\ViewDownloadSetterViewModel.cs" />
<Compile Include="ViewModels\Dialogs\BaseDialogViewModel.cs" />
<Compile Include="ViewModels\Settings\ViewBasicViewModel.cs" />
<Compile Include="ViewModels\Settings\ViewAboutViewModel.cs" />
@ -127,8 +132,8 @@
<Compile Include="ViewModels\ViewUserSpaceViewModel.cs" />
<Compile Include="ViewModels\ViewVideoDetailViewModel.cs" />
<Compile Include="ViewModels\Settings\ViewVideoViewModel.cs" />
<Compile Include="Views\Dialogs\ViewDirectorySelector.xaml.cs">
<DependentUpon>ViewDirectorySelector.xaml</DependentUpon>
<Compile Include="Views\Dialogs\ViewDownloadSetter.xaml.cs">
<DependentUpon>ViewDownloadSetter.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Dialogs\ViewParsingSelector.xaml.cs">
<DependentUpon>ViewParsingSelector.xaml</DependentUpon>
@ -254,7 +259,7 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Dialogs\ViewDirectorySelector.xaml">
<Page Include="Views\Dialogs\ViewDownloadSetter.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
@ -435,6 +440,7 @@
<Content Include="FFmpeg_LICENSE.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Resource Include="Resources\checked.png" />
<Content Include="打不开DownKyi请点我.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishUrlHistory />
<InstallUrlHistory />
<SupportUrlHistory />
<UpdateUrlHistory />
<BootstrapperUrlHistory />
<ErrorReportUrlHistory />
<FallbackCulture>zh-CN</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
</PropertyGroup>
</Project>

@ -14,6 +14,54 @@
public NormalIcon()
{
Play = new VectorImage
{
Height = 16,
Width = 14.75,
Data = @"M869.03 707.93 l-465.29 281.31 q-86.66 49.32 -178.65 28.65 q-91.99 -20.66 -146.65 -103.31 q-36 -56 -36 -121.33
l0 -562.61 q2.67 -97.32 69.33 -162.64 q66.66 -65.32 167.98 -67.99 q66.66 0 123.99 34.66 l465.29 281.31
q83.99 53.33 105.99 143.32 q22 89.99 -30 173.98 q-29.33 46.66 -75.99 74.66 Z",
Fill = "#FF000000"
};
Like = new VectorImage
{
Height = 14,
Width = 16,
Data = @"M291.53 894.6 l0 -642.53 l4.66 0 l179.59 -220.4 q29.15 -29.15 69.97 -31.49 q40.81 -2.33 72.29 24.5
q16.33 16.32 25.66 37.31 q9.33 20.99 7 45.48 l-7 144.6 l274.04 0 q25.65 0 48.39 11.08 q22.74 11.08 39.07 32.07
q13.99 19.82 17.49 44.31 q3.5 24.49 -2.33 46.64 l-116.62 382.49 q-15.16 54.81 -57.14 88.63 q-41.98 33.81 -100.28 37.31
l-454.79 0 ZM225.06 894.6 l-93.29 0 q-34.98 2.33 -65.3 -14 q-30.32 -16.33 -47.81 -47.81 q-17.49 -31.49 -18.66 -64.13
l0 -385.99 q0 -36.15 17.49 -65.89 q17.49 -29.73 48.98 -46.05 q16.32 -8.17 32.65 -12.25 q16.33 -4.08 32.65 -6.41 l93.29 0
l0 642.53 Z",
Fill = "#FF000000"
};
Favorite = new VectorImage
{
Height = 16,
Width = 16,
Data = @"M772.12 303.28 q-37.33 -5.83 -66.49 -28 q-29.16 -22.16 -44.32 -55.99 l-83.99 -176.13 q-22.16 -43.16 -65.91 -43.16
q-43.74 0 -69.4 43.16 l-79.32 176.13 q-17.49 33.83 -46.07 55.99 q-28.58 22.17 -64.74 28 l-188.97 29.16
q-45.49 9.33 -58.9 48.99 q-13.42 39.66 18.09 75.82 l142.31 146.98 q25.66 24.49 35.57 58.32 q9.91 33.83 5.25 69.99
l-32.66 204.13 q-5.83 48.99 29.75 73.49 q35.57 24.5 79.9 3.5 l159.8 -87.48 q33.83 -19.83 71.74 -19.83
q37.91 0 71.74 19.83 l160.97 87.48 q43.16 21 77.57 -3.5 q34.41 -24.5 32.08 -73.49 l-37.33 -204.13
q-4.67 -36.16 5.25 -69.99 q9.91 -33.83 35.57 -58.32 l142.31 -146.98 q31.5 -36.16 18.09 -75.82
q-13.42 -39.66 -58.91 -48.99 l-188.97 -29.16 Z",
Fill = "#FF000000"
};
Share = new VectorImage
{
Height = 14,
Width = 16,
Data = @"M453.23 283.64 l0 -219.44 q1.16 -26.85 18.67 -45.53 q17.51 -18.68 44.36 -18.68 q23.34 0 40.85 15.17 l441.21 375.85
q25.68 22.18 25.68 56.61 q0 34.43 -25.68 57.78 l-441.21 375.85 q-19.84 16.34 -46.11 14 q-26.26 -2.34 -42.61 -22.18
q-15.17 -18.67 -15.17 -42.02 l0 -201.93 q-156.41 0 -249.79 61.87 q-93.38 61.87 -178.58 183.25 q-4.67 5.84 -14.01 5.25
q-9.34 -0.59 -10.51 -19.25 q-5.83 -241.62 87.54 -405.62 q93.38 -164 365.35 -171 Z",
Fill = "#FF000000"
};
CloudDownload = new VectorImage
{
Height = 32,
@ -60,6 +108,11 @@
}
public VectorImage Play { get; private set; }
public VectorImage Like { get; private set; }
public VectorImage Favorite { get; private set; }
public VectorImage Share { get; private set; }
public VectorImage CloudDownload { get; private set; }
public VectorImage Folder { get; private set; }
public VectorImage Downloading { get; private set; }

@ -62,6 +62,7 @@
<system:String x:Key="Parse">解析</system:String>
<system:String x:Key="ParseVideo">解析视频</system:String>
<system:String x:Key="DownloadSelected">下载选中项</system:String>
<system:String x:Key="AddAllToDownload">下载全部</system:String>
<!-- DownloadManager -->
<system:String x:Key="Downloading">正在下载</system:String>
@ -173,19 +174,29 @@
<system:String x:Key="ExtractAudio">提取音频</system:String>
<system:String x:Key="ExtractVideo">提取视频</system:String>
<!-- PublicFavorites -->
<system:String x:Key="Favorites">收藏夹</system:String>
<system:String x:Key="FavoritesMediaCount">个内容</system:String>
<!-- Dialog -->
<system:String x:Key="Cancel">取消</system:String>
<system:String x:Key="SelectDirectory">请选择文件夹</system:String>
<!-- ViewDirectorySelector -->
<system:String x:Key="DownloadDirectorySelector">设置下载文件夹</system:String>
<!-- ViewDownloadSetter -->
<system:String x:Key="DownloadSetter">下载设置</system:String>
<system:String x:Key="Location">位置:</system:String>
<system:String x:Key="Browse">浏览</system:String>
<system:String x:Key="HardDiskFreeSpace">盘剩余空间:</system:String>
<system:String x:Key="DownloadContent">下载内容:</system:String>
<system:String x:Key="DownloadAll">所有</system:String>
<system:String x:Key="DownloadAudio">音频</system:String>
<system:String x:Key="DownloadVideo">视频</system:String>
<system:String x:Key="DownloadDanmaku">弹幕</system:String>
<system:String x:Key="DownloadSubtitle">字幕</system:String>
<system:String x:Key="DownloadCover">封面</system:String>
<system:String x:Key="IsDefaultDownloadDirectory">设此文件夹为默认下载文件夹</system:String>
<system:String x:Key="IsDefaultDownloadDirectoryTip">选中后下次将不会弹出此窗口</system:String>
<system:String x:Key="Download">下载</system:String>
<system:String x:Key="WarningNullDirectory">文件夹路径不能为空</system:String>
<!-- ViewParsingSelector -->

@ -0,0 +1,88 @@
using Prism.Mvvm;
using System.Windows.Media.Imaging;
namespace DownKyi.Models
{
public class Favorites : BindableBase
{
public string CoverUrl { get; set; }
public long UpperMid { get; set; }
private BitmapImage cover;
public BitmapImage Cover
{
get { return cover; }
set { SetProperty(ref cover, value); }
}
private string title;
public string Title
{
get { return title; }
set { SetProperty(ref title, value); }
}
private string createTime;
public string CreateTime
{
get { return createTime; }
set { SetProperty(ref createTime, value); }
}
private string playNumber;
public string PlayNumber
{
get { return playNumber; }
set { SetProperty(ref playNumber, value); }
}
private string likeNumber;
public string LikeNumber
{
get { return likeNumber; }
set { SetProperty(ref likeNumber, value); }
}
private string favoriteNumber;
public string FavoriteNumber
{
get { return favoriteNumber; }
set { SetProperty(ref favoriteNumber, value); }
}
private string shareNumber;
public string ShareNumber
{
get { return shareNumber; }
set { SetProperty(ref shareNumber, value); }
}
private string description;
public string Description
{
get { return description; }
set { SetProperty(ref description, value); }
}
private int mediaCount;
public int MediaCount
{
get { return mediaCount; }
set { SetProperty(ref mediaCount, value); }
}
private string upName;
public string UpName
{
get { return upName; }
set { SetProperty(ref upName, value); }
}
private BitmapImage upHeader;
public BitmapImage UpHeader
{
get { return upHeader; }
set { SetProperty(ref upHeader, value); }
}
}
}

@ -0,0 +1,126 @@
using DownKyi.Core.BiliApi.BiliUtils;
using DownKyi.Utils;
using DownKyi.ViewModels;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System.Windows.Media.Imaging;
namespace DownKyi.Models
{
public class FavoritesMedia : BindableBase
{
protected readonly IEventAggregator eventAggregator;
public FavoritesMedia(IEventAggregator eventAggregator)
{
this.eventAggregator = eventAggregator;
}
public long Avid { get; set; }
public string Bvid { get; set; }
public long UpperMid { get; set; }
#region 页面属性申明
private bool isSelected;
public bool IsSelected
{
get { return isSelected; }
set { SetProperty(ref isSelected, value); }
}
private int order;
public int Order
{
get { return order; }
set { SetProperty(ref order, value); }
}
private BitmapImage cover;
public BitmapImage Cover
{
get { return cover; }
set { SetProperty(ref cover, value); }
}
private string title;
public string Title
{
get { return title; }
set { SetProperty(ref title, value); }
}
private string playNumber;
public string PlayNumber
{
get { return playNumber; }
set { SetProperty(ref playNumber, value); }
}
private string danmakuNumber;
public string DanmakuNumber
{
get { return danmakuNumber; }
set { SetProperty(ref danmakuNumber, value); }
}
private string favoriteNumber;
public string FavoriteNumber
{
get { return favoriteNumber; }
set { SetProperty(ref favoriteNumber, value); }
}
private string duration;
public string Duration
{
get { return duration; }
set { SetProperty(ref duration, value); }
}
private string upName;
public string UpName
{
get { return upName; }
set { SetProperty(ref upName, value); }
}
#endregion
#region 命令申明
// 视频标题点击事件
private DelegateCommand<object> titleCommand;
public DelegateCommand<object> TitleCommand => titleCommand ?? (titleCommand = new DelegateCommand<object>(ExecuteTitleCommand));
/// <summary>
/// 视频标题点击事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteTitleCommand(object parameter)
{
if (!(parameter is string tag)) { return; }
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, tag, $"{ParseEntrance.VideoUrl}{Bvid}");
}
// 视频的UP主点击事件
private DelegateCommand<object> videoUpperCommand;
public DelegateCommand<object> VideoUpperCommand => videoUpperCommand ?? (videoUpperCommand = new DelegateCommand<object>(ExecuteVideoUpperCommand));
/// <summary>
/// 视频的UP主点击事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteVideoUpperCommand(object parameter)
{
if (!(parameter is string tag)) { return; }
NavigateToView.NavigateToViewUserSpace(eventAggregator, tag, UpperMid);
}
#endregion
}
}

@ -8,6 +8,7 @@ namespace DownKyi.Models
public class VideoInfoView : BindableBase
{
public string CoverUrl { get; set; }
public long UpperMid { get; set; }
private BitmapImage cover;
public BitmapImage Cover

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

@ -178,13 +178,12 @@ namespace DownKyi.Services
{
if (bangumiSeason == null) { return null; }
// 查询、保存封面
// 将SeasonId保存到avid字段中
// 每集封面的cid保存到cid字段EpisodeId保存到bvid字段中
StorageCover storageCover = new StorageCover();
string coverUrl = bangumiSeason.Cover;
string cover = storageCover.GetCover(bangumiSeason.SeasonId, "", -1, coverUrl);
string cover = storageCover.GetCover(bangumiSeason.SeasonId, "bangumi", -1, coverUrl);
// 获取用户头像
string upName;
@ -208,7 +207,7 @@ namespace DownKyi.Services
{
videoInfoView.CoverUrl = coverUrl;
videoInfoView.Cover = new BitmapImage(new Uri(cover));
videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover));
videoInfoView.Title = bangumiSeason.Title;
videoInfoView.VideoZone = DictionaryResource.GetString(BangumiType.Type[bangumiSeason.Type]);
@ -227,6 +226,8 @@ namespace DownKyi.Services
{
StorageHeader storageHeader = new StorageHeader();
videoInfoView.UpHeader = storageHeader.GetHeaderThumbnail(header, 48, 48);
videoInfoView.UpperMid = bangumiSeason.UpInfo.Mid;
}
else
{

@ -98,13 +98,12 @@ namespace DownKyi.Services
{
if (cheeseView == null) { return null; }
// 查询、保存封面
// 将SeasonId保存到avid字段中
// 每集封面的cid保存到cid字段EpisodeId保存到bvid字段中
StorageCover storageCover = new StorageCover();
string coverUrl = cheeseView.Cover;
string cover = storageCover.GetCover(cheeseView.SeasonId, "", -1, coverUrl);
string cover = storageCover.GetCover(cheeseView.SeasonId, "cheese", -1, coverUrl);
// 获取用户头像
string upName;
@ -127,7 +126,7 @@ namespace DownKyi.Services
{
videoInfoView.CoverUrl = coverUrl;
videoInfoView.Cover = new BitmapImage(new Uri(cover));
videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover));
videoInfoView.Title = cheeseView.Title;
videoInfoView.VideoZone = DictionaryResource.GetString("Cheese");
@ -147,6 +146,8 @@ namespace DownKyi.Services
{
StorageHeader storageHeader = new StorageHeader();
videoInfoView.UpHeader = storageHeader.GetHeaderThumbnail(header, 48, 48);
videoInfoView.UpperMid = cheeseView.UpInfo.Mid;
}
else
{

@ -0,0 +1,129 @@
using DownKyi.Core.BiliApi.Favorites;
using DownKyi.Core.Storage;
using DownKyi.Core.Utils;
using DownKyi.Models;
using Prism.Events;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Windows.Media.Imaging;
namespace DownKyi.Services
{
public class FavoritesService : IFavoritesService
{
/// <summary>
/// 获取收藏夹元数据
/// </summary>
/// <param name="mediaId"></param>
/// <returns></returns>
public Favorites GetFavorites(long mediaId)
{
var favoritesMetaInfo = FavoritesInfo.GetFavoritesInfo(mediaId);
if (favoritesMetaInfo == null) { return null; }
// 查询、保存封面
StorageCover storageCover = new StorageCover();
string coverUrl = favoritesMetaInfo.Cover;
string cover = storageCover.GetCover(favoritesMetaInfo.Id, "Favorites", favoritesMetaInfo.Mid, coverUrl);
// 获取用户头像
string upName;
string header;
if (favoritesMetaInfo.Upper != null)
{
upName = favoritesMetaInfo.Upper.Name;
StorageHeader storageHeader = new StorageHeader();
header = storageHeader.GetHeader(favoritesMetaInfo.Upper.Mid, favoritesMetaInfo.Upper.Name, favoritesMetaInfo.Upper.Face);
}
else
{
upName = "";
header = null;
}
// 为Favorites赋值
Favorites favorites = new Favorites();
App.PropertyChangeAsync(new Action(() =>
{
favorites.CoverUrl = coverUrl;
favorites.Cover = cover == null ? null : new BitmapImage(new Uri(cover));
favorites.Title = favoritesMetaInfo.Title;
DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区
DateTime dateTime = startTime.AddSeconds(favoritesMetaInfo.Ctime);
favorites.CreateTime = dateTime.ToString("yyyy-MM-dd HH:mm:ss");
favorites.PlayNumber = Format.FormatNumber(favoritesMetaInfo.CntInfo.Play);
favorites.LikeNumber = Format.FormatNumber(favoritesMetaInfo.CntInfo.ThumbUp);
favorites.FavoriteNumber = Format.FormatNumber(favoritesMetaInfo.CntInfo.Collect);
favorites.ShareNumber = Format.FormatNumber(favoritesMetaInfo.CntInfo.Share);
favorites.Description = favoritesMetaInfo.Intro;
favorites.MediaCount = favoritesMetaInfo.MediaCount;
favorites.UpName = upName;
if (header != null)
{
StorageHeader storageHeader = new StorageHeader();
favorites.UpHeader = storageHeader.GetHeaderThumbnail(header, 48, 48);
favorites.UpperMid = favoritesMetaInfo.Upper.Mid;
}
else
{
favorites.UpHeader = null;
}
}));
return favorites;
}
/// <summary>
/// 获取收藏夹内容明细列表
/// </summary>
/// <param name="mediaId"></param>
/// <returns></returns>
public void GetFavoritesMediaList(long mediaId, ObservableCollection<FavoritesMedia> result, IEventAggregator eventAggregator)
{
var medias = FavoritesResource.GetAllFavoritesMedia(mediaId);
if (medias.Count == 0) { return; }
int order = 0;
foreach (var media in medias)
{
order++;
// 查询、保存封面
StorageCover storageCover = new StorageCover();
string coverUrl = media.Cover;
string cover = storageCover.GetCover(media.Id, media.Bvid, -1, coverUrl);
App.PropertyChangeAsync(new Action(() =>
{
FavoritesMedia newMedia = new FavoritesMedia(eventAggregator)
{
Avid = media.Id,
Bvid = media.Bvid,
Order = order,
Cover = cover == null ? null : new BitmapImage(new Uri(cover)),
Title = media.Title,
PlayNumber = media.CntInfo != null ? Format.FormatNumber(media.CntInfo.Play) : "0",
DanmakuNumber = media.CntInfo != null ? Format.FormatNumber(media.CntInfo.Danmaku) : "0",
FavoriteNumber = media.CntInfo != null ? Format.FormatNumber(media.CntInfo.Collect) : "0",
Duration = Format.FormatDuration2(media.Duration),
UpName = media.Upper != null ? media.Upper.Name : string.Empty,
UpperMid = media.Upper != null ? media.Upper.Mid : -1
};
if (!result.ToList().Exists(t => t.Avid == newMedia.Avid))
{
result.Add(newMedia);
Thread.Sleep(50);
}
}));
}
}
}
}

@ -0,0 +1,12 @@
using DownKyi.Models;
using Prism.Events;
using System.Collections.ObjectModel;
namespace DownKyi.Services
{
public interface IFavoritesService
{
Favorites GetFavorites(long mediaId);
void GetFavoritesMediaList(long mediaId, ObservableCollection<FavoritesMedia> result, IEventAggregator eventAggregator);
}
}

@ -200,7 +200,7 @@ namespace DownKyi.Services
{
videoInfoView.CoverUrl = coverUrl;
videoInfoView.Cover = new BitmapImage(new Uri(cover));
videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover));
videoInfoView.Title = videoView.Title;
videoInfoView.VideoZone = videoZone;
@ -223,6 +223,8 @@ namespace DownKyi.Services
{
StorageHeader storageHeader = new StorageHeader();
videoInfoView.UpHeader = storageHeader.GetHeaderThumbnail(header, 48, 48);
videoInfoView.UpperMid = videoView.Owner.Mid;
}
else
{

@ -28,6 +28,8 @@
<SolidColorBrush x:Key="BrushBackgroundGreyTranslucent2" Color="{DynamicResource ColorBackgroundGreyTranslucent2}" />
<SolidColorBrush x:Key="BrushBackgroundGreyTranslucent3" Color="{DynamicResource ColorBackgroundGreyTranslucent3}" />
<SolidColorBrush x:Key="BrushMask" Color="{DynamicResource ColorMask}" />
<SolidColorBrush x:Key="BrushTabHeaderGrey" Color="{DynamicResource ColorTabHeaderGrey}" />
<SolidColorBrush x:Key="BrushHeaderGrey" Color="{DynamicResource ColorHeaderGrey}" />
@ -39,5 +41,6 @@
<SolidColorBrush x:Key="BrushText" Color="{DynamicResource ColorText}" />
<SolidColorBrush x:Key="BrushTextDark" Color="{DynamicResource ColorTextDark}" />
<SolidColorBrush x:Key="BrushTextGrey" Color="{DynamicResource ColorTextGrey}" />
<SolidColorBrush x:Key="BrushTextGrey2" Color="{DynamicResource ColorTextGrey2}" />
</ResourceDictionary>

@ -28,6 +28,8 @@
<Color x:Key="ColorBackgroundGreyTranslucent2">#7FBDBDBD</Color>
<Color x:Key="ColorBackgroundGreyTranslucent3">#33BDBDBD</Color>
<Color x:Key="ColorMask">#7F000000</Color>
<Color x:Key="ColorTabHeaderGrey">#FFF4F4F4</Color>
<Color x:Key="ColorHeaderGrey">#FFF4F4F4</Color>
@ -39,5 +41,6 @@
<Color x:Key="ColorText">white</Color>
<Color x:Key="ColorTextDark">black</Color>
<Color x:Key="ColorTextGrey">#FF999999</Color>
<Color x:Key="ColorTextGrey2">#FF757575</Color>
</ResourceDictionary>

@ -22,5 +22,24 @@ namespace DownKyi.Utils
? string.IsNullOrEmpty(dialog.SelectedPath) ? "" : dialog.SelectedPath : "";
}
/// <summary>
/// 选择视频dialog
/// </summary>
/// <returns></returns>
public static string SelectVideoFile()
{
// 选择文件
var dialog = new Microsoft.Win32.OpenFileDialog
{
Filter = "mp4 (*.mp4)|*.mp4"
};
var showDialog = dialog.ShowDialog();
if (showDialog == true)
{
return dialog.FileName;
}
else { return ""; }
}
}
}

@ -0,0 +1,52 @@
using DownKyi.Core.Logging;
using DownKyi.Core.Settings;
using DownKyi.Core.Settings.Models;
using DownKyi.Events;
using DownKyi.ViewModels;
using Prism.Events;
namespace DownKyi.Utils
{
public static class NavigateToView
{
public static string Tag = "NavigateToView";
/// <summary>
/// 导航到用户空间,
/// 如果传入的mid与本地登录的mid一致
/// 则进入我的用户空间。
/// </summary>
/// <param name="mid"></param>
public static void NavigateToViewUserSpace(IEventAggregator eventAggregator, string parentViewName, long mid)
{
UserInfoSettings userInfo = SettingsManager.GetInstance().GetUserInfo();
if (userInfo != null && userInfo.Mid == mid)
{
NavigationView(eventAggregator, ViewMySpaceViewModel.Tag, parentViewName, mid);
}
else
{
NavigationView(eventAggregator, ViewUserSpaceViewModel.Tag, parentViewName, mid);
}
}
/// <summary>
/// 导航到其他页面
/// </summary>
/// <param name="viewName"></param>
/// <param name="param"></param>
public static void NavigationView(IEventAggregator eventAggregator, string viewName, string parentViewName, object param)
{
LogManager.Debug(Tag, $"NavigationView: {viewName}, Parameter: {param}");
NavigationParam parameter = new NavigationParam
{
ViewName = viewName,
ParentViewName = parentViewName,
Parameter = param
};
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
}
}
}

@ -0,0 +1,393 @@
using DownKyi.Core.Settings;
using DownKyi.Core.Utils;
using DownKyi.Events;
using DownKyi.Images;
using DownKyi.Utils;
using Prism.Commands;
using Prism.Events;
using Prism.Services.Dialogs;
using System.Collections.Generic;
namespace DownKyi.ViewModels.Dialogs
{
public class ViewDownloadSetterViewModel : BaseDialogViewModel
{
public const string Tag = "DialogDownloadSetter";
private readonly IEventAggregator eventAggregator;
// 历史文件夹的数量
private readonly int maxDirectoryListCount = 20;
#region 页面属性申明
private VectorImage cloudDownloadIcon;
public VectorImage CloudDownloadIcon
{
get { return cloudDownloadIcon; }
set { SetProperty(ref cloudDownloadIcon, value); }
}
private VectorImage folderIcon;
public VectorImage FolderIcon
{
get { return folderIcon; }
set { SetProperty(ref folderIcon, value); }
}
private bool isDefaultDownloadDirectory;
public bool IsDefaultDownloadDirectory
{
get { return isDefaultDownloadDirectory; }
set { SetProperty(ref isDefaultDownloadDirectory, value); }
}
private List<string> directoryList;
public List<string> DirectoryList
{
get { return directoryList; }
set { SetProperty(ref directoryList, value); }
}
private string directory;
public string Directory
{
get { return directory; }
set
{
SetProperty(ref directory, value);
if (directory != string.Empty)
{
DriveName = directory.Substring(0, 1).ToUpper();
DriveNameFreeSpace = Format.FormatFileSize(HardDisk.GetHardDiskFreeSpace(DriveName));
}
}
}
private string driveName;
public string DriveName
{
get { return driveName; }
set { SetProperty(ref driveName, value); }
}
private string driveNameFreeSpace;
public string DriveNameFreeSpace
{
get { return driveNameFreeSpace; }
set { SetProperty(ref driveNameFreeSpace, value); }
}
private bool downloadAll;
public bool DownloadAll
{
get { return downloadAll; }
set { SetProperty(ref downloadAll, value); }
}
private bool downloadAudio;
public bool DownloadAudio
{
get { return downloadAudio; }
set { SetProperty(ref downloadAudio, value); }
}
private bool downloadVideo;
public bool DownloadVideo
{
get { return downloadVideo; }
set { SetProperty(ref downloadVideo, value); }
}
private bool downloadDanmaku;
public bool DownloadDanmaku
{
get { return downloadDanmaku; }
set { SetProperty(ref downloadDanmaku, value); }
}
private bool downloadSubtitle;
public bool DownloadSubtitle
{
get { return downloadSubtitle; }
set { SetProperty(ref downloadSubtitle, value); }
}
private bool downloadCover;
public bool DownloadCover
{
get { return downloadCover; }
set { SetProperty(ref downloadCover, value); }
}
#endregion
public ViewDownloadSetterViewModel(IEventAggregator eventAggregator)
{
this.eventAggregator = eventAggregator;
#region 属性初始化
Title = DictionaryResource.GetString("DownloadSetter");
CloudDownloadIcon = NormalIcon.Instance().CloudDownload;
CloudDownloadIcon.Fill = DictionaryResource.GetColor("ColorPrimary");
FolderIcon = NormalIcon.Instance().Folder;
FolderIcon.Fill = DictionaryResource.GetColor("ColorPrimary");
DownloadAll = true;
DownloadAudio = true;
DownloadVideo = true;
DownloadDanmaku = true;
DownloadSubtitle = true;
DownloadCover = true;
#endregion
// 历史下载目录
DirectoryList = SettingsManager.GetInstance().GetHistoryVideoRootPaths();
string directory = SettingsManager.GetInstance().GetSaveVideoRootPath();
if (!DirectoryList.Contains(directory))
{
ListHelper.InsertUnique(DirectoryList, directory, 0);
}
Directory = directory;
// 是否使用默认下载目录
IsDefaultDownloadDirectory = SettingsManager.GetInstance().IsUseSaveVideoRootPath() == AllowStatus.YES;
}
#region 命令申明
// 浏览文件夹事件
private DelegateCommand browseCommand;
public DelegateCommand BrowseCommand => browseCommand ?? (browseCommand = new DelegateCommand(ExecuteBrowseCommand));
/// <summary>
/// 浏览文件夹事件
/// </summary>
private void ExecuteBrowseCommand()
{
string directory = SetDirectory();
if (directory == null)
{
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("WarningNullDirectory"));
Directory = string.Empty;
}
else
{
ListHelper.InsertUnique(DirectoryList, directory, 0);
Directory = directory;
if (DirectoryList.Count > maxDirectoryListCount)
{
DirectoryList.RemoveAt(maxDirectoryListCount);
}
}
}
// 所有内容选择事件
private DelegateCommand downloadAllCommand;
public DelegateCommand DownloadAllCommand => downloadAllCommand ?? (downloadAllCommand = new DelegateCommand(ExecuteDownloadAllCommand));
/// <summary>
/// 所有内容选择事件
/// </summary>
private void ExecuteDownloadAllCommand()
{
if (DownloadAll)
{
DownloadAudio = true;
DownloadVideo = true;
DownloadDanmaku = true;
DownloadSubtitle = true;
DownloadCover = true;
}
else
{
DownloadAudio = false;
DownloadVideo = false;
DownloadDanmaku = false;
DownloadSubtitle = false;
DownloadCover = false;
}
}
// 音频选择事件
private DelegateCommand downloadAudioCommand;
public DelegateCommand DownloadAudioCommand => downloadAudioCommand ?? (downloadAudioCommand = new DelegateCommand(ExecuteDownloadAudioCommand));
/// <summary>
/// 音频选择事件
/// </summary>
private void ExecuteDownloadAudioCommand()
{
if (!DownloadAudio)
{
DownloadAll = false;
return;
}
if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover)
{
DownloadAll = true;
}
}
// 视频选择事件
private DelegateCommand downloadVideoCommand;
public DelegateCommand DownloadVideoCommand => downloadVideoCommand ?? (downloadVideoCommand = new DelegateCommand(ExecuteDownloadVideoCommand));
/// <summary>
/// 视频选择事件
/// </summary>
private void ExecuteDownloadVideoCommand()
{
if (!DownloadVideo)
{
DownloadAll = false;
return;
}
if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover)
{
DownloadAll = true;
}
}
// 弹幕选择事件
private DelegateCommand downloadDanmakuCommand;
public DelegateCommand DownloadDanmakuCommand => downloadDanmakuCommand ?? (downloadDanmakuCommand = new DelegateCommand(ExecuteDownloadDanmakuCommand));
/// <summary>
/// 弹幕选择事件
/// </summary>
private void ExecuteDownloadDanmakuCommand()
{
if (!DownloadDanmaku)
{
DownloadAll = false;
return;
}
if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover)
{
DownloadAll = true;
}
}
// 字幕选择事件
private DelegateCommand downloadSubtitleCommand;
public DelegateCommand DownloadSubtitleCommand => downloadSubtitleCommand ?? (downloadSubtitleCommand = new DelegateCommand(ExecuteDownloadSubtitleCommand));
/// <summary>
/// 字幕选择事件
/// </summary>
private void ExecuteDownloadSubtitleCommand()
{
if (!DownloadSubtitle)
{
DownloadAll = false;
return;
}
if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover)
{
DownloadAll = true;
}
}
// 封面选择事件
private DelegateCommand downloadCoverCommand;
public DelegateCommand DownloadCoverCommand => downloadCoverCommand ?? (downloadCoverCommand = new DelegateCommand(ExecuteDownloadCoverCommand));
/// <summary>
/// 封面选择事件
/// </summary>
private void ExecuteDownloadCoverCommand()
{
if (!DownloadCover)
{
DownloadAll = false;
return;
}
if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover)
{
DownloadAll = true;
}
}
// 确认下载事件
private DelegateCommand downloadCommand;
public DelegateCommand DownloadCommand => downloadCommand ?? (downloadCommand = new DelegateCommand(ExecuteDownloadCommand));
/// <summary>
/// 确认下载事件
/// </summary>
private void ExecuteDownloadCommand()
{
if (Directory == null || Directory == string.Empty)
{
return;
}
// 设此文件夹为默认下载文件夹
if (IsDefaultDownloadDirectory)
{
SettingsManager.GetInstance().IsUseSaveVideoRootPath(AllowStatus.YES);
}
else
{
SettingsManager.GetInstance().IsUseSaveVideoRootPath(AllowStatus.NO);
}
// 将Directory移动到第一项
// 如果直接在ComboBox中选择的就需要
// 否则选中项不会在下次出现在第一项
ListHelper.InsertUnique(DirectoryList, Directory, 0);
// 将更新后的DirectoryList写入历史中
SettingsManager.GetInstance().SetSaveVideoRootPath(Directory);
SettingsManager.GetInstance().SetHistoryVideoRootPaths(DirectoryList);
// 返回数据
ButtonResult result = ButtonResult.OK;
IDialogParameters parameters = new DialogParameters
{
{ "directory", Directory },
{ "downloadAudio", DownloadAudio },
{ "downloadVideo", DownloadVideo },
{ "downloadDanmaku", DownloadDanmaku },
{ "downloadSubtitle", DownloadSubtitle },
{ "downloadCover", DownloadCover }
};
RaiseRequestClose(new DialogResult(result, parameters));
}
#endregion
/// <summary>
/// 设置下载路径
/// </summary>
/// <returns></returns>
private string SetDirectory()
{
// 下载目录
string path;
// 弹出选择下载目录的窗口
path = DialogUtils.SetDownloadDirectory();
if (path == null || path == "")
{
return null;
}
return path;
}
}
}

@ -149,6 +149,7 @@ namespace DownKyi.ViewModels
clipboardHooker = new ClipboardHooker(Application.Current.MainWindow);
clipboardHooker.ClipboardUpdated += OnClipboardUpdated;
// 进入首页
var param = new NavigationParameters
{
{ "Parent", "" },
@ -292,8 +293,32 @@ namespace DownKyi.ViewModels
icon.Fill = DictionaryResource.GetColor("ColorSystemBtnTintDark");
}
#region 剪贴板
private int times = 0;
/// <summary>
/// 监听剪贴板更新事件,会执行两遍以上
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnClipboardUpdated(object sender, EventArgs e)
{
times += 1;
DispatcherTimer timer = new DispatcherTimer
{
Interval = new TimeSpan(0, 0, 0, 0, 300)
};
timer.Tick += (s, ex) => { timer.IsEnabled = false; times = 0; };
timer.IsEnabled = true;
if (times % 2 == 0)
{
timer.IsEnabled = false;
times = 0;
return;
}
AllowStatus isListenClipboard = SettingsManager.GetInstance().IsListenClipboard();
if (isListenClipboard != AllowStatus.YES)
{
@ -317,69 +342,71 @@ namespace DownKyi.ViewModels
// 视频
if (ParseEntrance.IsAvId(input))
{
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.VideoUrl}{input.ToLower()}");
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, ViewIndexViewModel.Tag, $"{ParseEntrance.VideoUrl}{input.ToLower()}");
}
else if (ParseEntrance.IsAvUrl(input))
{
NavigationView(ViewVideoDetailViewModel.Tag, input);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, ViewIndexViewModel.Tag, input);
}
else if (ParseEntrance.IsBvId(input))
{
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.VideoUrl}{input}");
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, ViewIndexViewModel.Tag, $"{ParseEntrance.VideoUrl}{input}");
}
else if (ParseEntrance.IsBvUrl(input))
{
NavigationView(ViewVideoDetailViewModel.Tag, input);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, ViewIndexViewModel.Tag, input);
}
// 番剧(电影、电视剧)
else if (ParseEntrance.IsBangumiSeasonId(input))
{
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiUrl}{input.ToLower()}");
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, ViewIndexViewModel.Tag, $"{ParseEntrance.BangumiUrl}{input.ToLower()}");
}
else if (ParseEntrance.IsBangumiSeasonUrl(input))
{
NavigationView(ViewVideoDetailViewModel.Tag, input);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, ViewIndexViewModel.Tag, input);
}
else if (ParseEntrance.IsBangumiEpisodeId(input))
{
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiUrl}{input.ToLower()}");
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, ViewIndexViewModel.Tag, $"{ParseEntrance.BangumiUrl}{input.ToLower()}");
}
else if (ParseEntrance.IsBangumiEpisodeUrl(input))
{
NavigationView(ViewVideoDetailViewModel.Tag, input);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, ViewIndexViewModel.Tag, input);
}
else if (ParseEntrance.IsBangumiMediaId(input))
{
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiMediaUrl}{input.ToLower()}");
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, ViewIndexViewModel.Tag, $"{ParseEntrance.BangumiMediaUrl}{input.ToLower()}");
}
else if (ParseEntrance.IsBangumiMediaUrl(input))
{
NavigationView(ViewVideoDetailViewModel.Tag, input);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, ViewIndexViewModel.Tag, input);
}
// 课程
else if (ParseEntrance.IsCheeseSeasonUrl(input) || ParseEntrance.IsCheeseEpisodeUrl(input))
{
NavigationView(ViewVideoDetailViewModel.Tag, input);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, ViewIndexViewModel.Tag, input);
}
}
/// <summary>
/// 导航到其他页面
/// </summary>
/// <param name="viewName"></param>
/// <param name="param"></param>
private void NavigationView(string viewName, string param)
{
LogManager.Debug("OnClipboardUpdated", $"NavigationView: {viewName}, Parameter: {param}");
NavigationParam parameter = new NavigationParam
// 用户参数传入mid
else if (ParseEntrance.IsUserId(input))
{
ViewName = viewName,
ParentViewName = ViewIndexViewModel.Tag,
Parameter = param
};
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
NavigateToView.NavigateToViewUserSpace(eventAggregator, ViewIndexViewModel.Tag, ParseEntrance.GetUserId(input));
}
else if (ParseEntrance.IsUserUrl(input))
{
NavigateToView.NavigateToViewUserSpace(eventAggregator, ViewIndexViewModel.Tag, ParseEntrance.GetUserId(input));
}
// 收藏夹
else if (ParseEntrance.IsFavoritesId(input))
{
NavigateToView.NavigationView(eventAggregator, ViewPublicFavoritesViewModel.Tag, ViewIndexViewModel.Tag, ParseEntrance.GetFavoritesId(input));
}
else if (ParseEntrance.IsFavoritesUrl(input))
{
NavigateToView.NavigationView(eventAggregator, ViewPublicFavoritesViewModel.Tag, ViewIndexViewModel.Tag, ParseEntrance.GetFavoritesId(input));
}
}
#endregion
}
}

@ -124,7 +124,7 @@ namespace DownKyi.ViewModels.Toolbox
{
UserMid = null;
Core.Utils.Debug.Console.PrintLine("FindDanmakuSenderCommand()发生异常: {0}", e);
Core.Utils.Debugging.Console.PrintLine("FindDanmakuSenderCommand()发生异常: {0}", e);
LogManager.Error(Tag, e);
}
});

@ -93,7 +93,7 @@ namespace DownKyi.ViewModels.Toolbox
return;
}
VideoPath = SelectVideoFile();
VideoPath = DialogUtils.SelectVideoFile();
}
// 去水印事件
@ -172,24 +172,5 @@ namespace DownKyi.ViewModels.Toolbox
#endregion
/// <summary>
/// 选择视频dialog
/// </summary>
/// <returns></returns>
private string SelectVideoFile()
{
// 选择文件
var dialog = new Microsoft.Win32.OpenFileDialog
{
Filter = "mp4 (*.mp4)|*.mp4"
};
var showDialog = dialog.ShowDialog();
if (showDialog == true)
{
return dialog.FileName;
}
else { return ""; }
}
}
}

@ -60,7 +60,7 @@ namespace DownKyi.ViewModels.Toolbox
return;
}
VideoPath = SelectVideoFile();
VideoPath = DialogUtils.SelectVideoFile();
}
// 提取音频事件
@ -155,24 +155,5 @@ namespace DownKyi.ViewModels.Toolbox
#endregion
/// <summary>
/// 选择视频dialog
/// </summary>
/// <returns></returns>
private string SelectVideoFile()
{
// 选择文件
var dialog = new Microsoft.Win32.OpenFileDialog
{
Filter = "mp4 (*.mp4)|*.mp4"
};
var showDialog = dialog.ShowDialog();
if (showDialog == true)
{
return dialog.FileName;
}
else { return ""; }
}
}
}

@ -4,7 +4,6 @@ using DownKyi.Core.Logging;
using DownKyi.Core.Settings;
using DownKyi.Core.Settings.Models;
using DownKyi.Core.Storage;
using DownKyi.Events;
using DownKyi.Images;
using DownKyi.Utils;
using Prism.Commands;
@ -149,7 +148,7 @@ namespace DownKyi.ViewModels
{
if (UserName == null)
{
NavigationView(ViewLoginViewModel.Tag, null);
NavigateToView.NavigationView(eventAggregator, ViewLoginViewModel.Tag, Tag, null);
}
else
{
@ -157,7 +156,7 @@ namespace DownKyi.ViewModels
var userInfo = SettingsManager.GetInstance().GetUserInfo();
if (userInfo != null && userInfo.Mid != -1)
{
NavigationView(ViewMySpaceViewModel.Tag, userInfo.Mid);
NavigateToView.NavigationView(eventAggregator, ViewMySpaceViewModel.Tag, Tag, userInfo.Mid);
}
}
}
@ -171,7 +170,7 @@ namespace DownKyi.ViewModels
/// </summary>
private void ExecuteSettingsCommand()
{
NavigationView(ViewSettingsViewModel.Tag, null);
NavigateToView.NavigationView(eventAggregator, ViewSettingsViewModel.Tag, Tag, null);
}
// 进入下载管理页面
@ -183,7 +182,7 @@ namespace DownKyi.ViewModels
/// </summary>
private void ExecuteDownloadManagerCommand()
{
NavigationView(ViewDownloadManagerViewModel.Tag, null);
NavigateToView.NavigationView(eventAggregator, ViewDownloadManagerViewModel.Tag, Tag, null);
}
// 进入工具箱页面
@ -195,7 +194,7 @@ namespace DownKyi.ViewModels
/// </summary>
private void ExecuteToolboxCommand()
{
NavigationView(ViewToolboxViewModel.Tag, null);
NavigateToView.NavigationView(eventAggregator, ViewToolboxViewModel.Tag, Tag, null);
}
#endregion
@ -227,67 +226,67 @@ namespace DownKyi.ViewModels
// 视频
if (ParseEntrance.IsAvId(InputText))
{
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.VideoUrl}{InputText.ToLower()}");
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, Tag, $"{ParseEntrance.VideoUrl}{InputText.ToLower()}");
}
else if (ParseEntrance.IsAvUrl(InputText))
{
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, Tag, InputText);
}
else if (ParseEntrance.IsBvId(InputText))
{
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.VideoUrl}{InputText}");
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, Tag, $"{ParseEntrance.VideoUrl}{InputText}");
}
else if (ParseEntrance.IsBvUrl(InputText))
{
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, Tag, InputText);
}
// 番剧(电影、电视剧)
else if (ParseEntrance.IsBangumiSeasonId(InputText))
{
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiUrl}{InputText.ToLower()}");
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, Tag, $"{ParseEntrance.BangumiUrl}{InputText.ToLower()}");
}
else if (ParseEntrance.IsBangumiSeasonUrl(InputText))
{
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, Tag, InputText);
}
else if (ParseEntrance.IsBangumiEpisodeId(InputText))
{
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiUrl}{InputText.ToLower()}");
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, Tag, $"{ParseEntrance.BangumiUrl}{InputText.ToLower()}");
}
else if (ParseEntrance.IsBangumiEpisodeUrl(InputText))
{
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, Tag, InputText);
}
else if (ParseEntrance.IsBangumiMediaId(InputText))
{
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiMediaUrl}{InputText.ToLower()}");
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, Tag, $"{ParseEntrance.BangumiMediaUrl}{InputText.ToLower()}");
}
else if (ParseEntrance.IsBangumiMediaUrl(InputText))
{
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, Tag, InputText);
}
// 课程
else if (ParseEntrance.IsCheeseSeasonUrl(InputText) || ParseEntrance.IsCheeseEpisodeUrl(InputText))
{
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, Tag, InputText);
}
// 用户参数传入mid
else if (ParseEntrance.IsUserId(InputText))
{
NavigateToViewUserSpace(ParseEntrance.GetUserId(InputText));
NavigateToView.NavigateToViewUserSpace(eventAggregator, Tag, ParseEntrance.GetUserId(InputText));
}
else if (ParseEntrance.IsUserUrl(InputText))
{
NavigateToViewUserSpace(ParseEntrance.GetUserId(InputText));
NavigateToView.NavigateToViewUserSpace(eventAggregator, Tag, ParseEntrance.GetUserId(InputText));
}
// 收藏夹
else if (ParseEntrance.IsFavoritesId(InputText))
{
NavigationView(ViewPublicFavoritesViewModel.Tag, ParseEntrance.GetFavoritesId(InputText));
NavigateToView.NavigationView(eventAggregator, ViewPublicFavoritesViewModel.Tag, Tag, ParseEntrance.GetFavoritesId(InputText));
}
else if (ParseEntrance.IsFavoritesUrl(InputText))
{
NavigationView(ViewPublicFavoritesViewModel.Tag, ParseEntrance.GetFavoritesId(InputText));
NavigateToView.NavigationView(eventAggregator, ViewPublicFavoritesViewModel.Tag, Tag, ParseEntrance.GetFavoritesId(InputText));
}
// TODO 关键词搜索
else
@ -297,43 +296,6 @@ namespace DownKyi.ViewModels
InputText = string.Empty;
}
/// <summary>
/// 导航到用户空间,
/// 如果传入的mid与本地登录的mid一致
/// 则进入我的用户空间。
/// </summary>
/// <param name="mid"></param>
private void NavigateToViewUserSpace(long mid)
{
var userInfo = SettingsManager.GetInstance().GetUserInfo();
if (userInfo != null && userInfo.Mid == mid)
{
NavigationView(ViewMySpaceViewModel.Tag, mid);
}
else
{
NavigationView(ViewUserSpaceViewModel.Tag, mid);
}
}
/// <summary>
/// 导航到其他页面
/// </summary>
/// <param name="viewName"></param>
/// <param name="param"></param>
private void NavigationView(string viewName, object param)
{
LogManager.Debug(Tag, $"NavigationView: {viewName}, Parameter: {param}");
NavigationParam parameter = new NavigationParam
{
ViewName = viewName,
ParentViewName = Tag,
Parameter = param
};
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
}
/// <summary>
/// 更新用户登录信息
/// </summary>

@ -116,7 +116,7 @@ namespace DownKyi.ViewModels
}
PropertyChangeAsync(new Action(() => { LoginQRCode = LoginQR.GetLoginQRCode(loginUrl.Data.Url); }));
Core.Utils.Debug.Console.PrintLine(loginUrl.Data.Url + "\n");
Core.Utils.Debugging.Console.PrintLine(loginUrl.Data.Url + "\n");
LogManager.Debug(Tag, loginUrl.Data.Url);
GetLoginStatus(loginUrl.Data.OauthKey);
@ -135,7 +135,7 @@ namespace DownKyi.ViewModels
var loginStatus = LoginQR.GetLoginStatus(oauthKey);
if (loginStatus == null) { continue; }
Core.Utils.Debug.Console.PrintLine(loginStatus.Code + "\n" + loginStatus.Message + "\n" + loginStatus.Url + "\n");
Core.Utils.Debugging.Console.PrintLine(loginStatus.Code + "\n" + loginStatus.Message + "\n" + loginStatus.Url + "\n");
switch (loginStatus.Code)
{
@ -195,7 +195,7 @@ namespace DownKyi.ViewModels
}
catch (Exception e)
{
Core.Utils.Debug.Console.PrintLine("PageLogin 保存登录信息发生异常: {0}", e);
Core.Utils.Debugging.Console.PrintLine("PageLogin 保存登录信息发生异常: {0}", e);
LogManager.Error(e);
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("LoginFailed"));
}
@ -212,7 +212,7 @@ namespace DownKyi.ViewModels
// 判断是否该结束线程若为true跳出while循环
if (cancellationToken.IsCancellationRequested)
{
Core.Utils.Debug.Console.PrintLine("停止Login线程跳出while循环");
Core.Utils.Debugging.Console.PrintLine("停止Login线程跳出while循环");
LogManager.Debug(Tag, "登录操作结束");
break;
}

@ -1,10 +1,16 @@
using Prism.Commands;
using DownKyi.Core.Logging;
using DownKyi.Events;
using DownKyi.Images;
using DownKyi.Models;
using DownKyi.Services;
using DownKyi.Utils;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows;
namespace DownKyi.ViewModels
{
@ -12,18 +18,241 @@ namespace DownKyi.ViewModels
{
public const string Tag = "PagePublicFavorites";
// 收藏夹id
private long favoritesId;
#region 页面属性申明
private string pageName = Tag;
public string PageName
{
get { return pageName; }
set { SetProperty(ref pageName, value); }
}
private VectorImage arrowBack;
public VectorImage ArrowBack
{
get { return arrowBack; }
set { SetProperty(ref arrowBack, value); }
}
private VectorImage play;
public VectorImage Play
{
get { return play; }
set { SetProperty(ref play, value); }
}
private VectorImage like;
public VectorImage Like
{
get { return like; }
set { SetProperty(ref like, value); }
}
private VectorImage favorite;
public VectorImage Favorite
{
get { return favorite; }
set { SetProperty(ref favorite, value); }
}
private VectorImage share;
public VectorImage Share
{
get { return share; }
set { SetProperty(ref share, value); }
}
private Favorites favorites;
public Favorites Favorites
{
get { return favorites; }
set { SetProperty(ref favorites, value); }
}
private ObservableCollection<FavoritesMedia> favoritesMedias;
public ObservableCollection<FavoritesMedia> FavoritesMedias
{
get { return favoritesMedias; }
set { SetProperty(ref favoritesMedias, value); }
}
private Visibility contentVisibility;
public Visibility ContentVisibility
{
get { return contentVisibility; }
set { SetProperty(ref contentVisibility, value); }
}
private Visibility noDataVisibility;
public Visibility NoDataVisibility
{
get { return noDataVisibility; }
set { SetProperty(ref noDataVisibility, value); }
}
#endregion
public ViewPublicFavoritesViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
{
#region 属性初始化
ArrowBack = NavigationIcon.Instance().ArrowBack;
ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark");
Play = NormalIcon.Instance().Play;
Play.Fill = DictionaryResource.GetColor("ColorTextGrey2");
Like = NormalIcon.Instance().Like;
Like.Fill = DictionaryResource.GetColor("ColorTextGrey2");
Favorite = NormalIcon.Instance().Favorite;
Favorite.Fill = DictionaryResource.GetColor("ColorTextGrey2");
Share = NormalIcon.Instance().Share;
Share.Fill = DictionaryResource.GetColor("ColorTextGrey2");
FavoritesMedias = new ObservableCollection<FavoritesMedia>();
#endregion
}
#region 命令申明
// 返回
private DelegateCommand backSpaceCommand;
public DelegateCommand BackSpaceCommand => backSpaceCommand ?? (backSpaceCommand = new DelegateCommand(ExecuteBackSpace));
/// <summary>
/// 返回
/// </summary>
private void ExecuteBackSpace()
{
NavigationParam parameter = new NavigationParam
{
ViewName = ParentView,
ParentViewName = null,
Parameter = null
};
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
}
// 复制封面事件
private DelegateCommand copyCoverCommand;
public DelegateCommand CopyCoverCommand => copyCoverCommand ?? (copyCoverCommand = new DelegateCommand(ExecuteCopyCoverCommand));
/// <summary>
/// 复制封面事件
/// </summary>
private void ExecuteCopyCoverCommand()
{
// 复制封面图片到剪贴板
Clipboard.SetImage(Favorites.Cover);
LogManager.Info(Tag, "复制封面图片到剪贴板");
}
// 复制封面URL事件
private DelegateCommand copyCoverUrlCommand;
public DelegateCommand CopyCoverUrlCommand => copyCoverUrlCommand ?? (copyCoverUrlCommand = new DelegateCommand(ExecuteCopyCoverUrlCommand));
/// <summary>
/// 复制封面URL事件
/// </summary>
private void ExecuteCopyCoverUrlCommand()
{
// 复制封面url到剪贴板
Clipboard.SetText(Favorites.CoverUrl);
LogManager.Info(Tag, "复制封面url到剪贴板");
}
// 前往UP主页事件
private DelegateCommand upperCommand;
public DelegateCommand UpperCommand => upperCommand ?? (upperCommand = new DelegateCommand(ExecuteUpperCommand));
/// <summary>
/// 前往UP主页事件
/// </summary>
private void ExecuteUpperCommand()
{
NavigateToView.NavigateToViewUserSpace(eventAggregator, Tag, Favorites.UpperMid);
}
// 添加选中项到下载列表事件
private DelegateCommand addToDownloadCommand;
public DelegateCommand AddToDownloadCommand => addToDownloadCommand ?? (addToDownloadCommand = new DelegateCommand(ExecuteAddToDownloadCommand));
/// <summary>
/// 添加选中项到下载列表事件
/// </summary>
private void ExecuteAddToDownloadCommand()
{
}
// 添加所有视频到下载列表事件
private DelegateCommand addAllToDownloadCommand;
public DelegateCommand AddAllToDownloadCommand => addAllToDownloadCommand ?? (addAllToDownloadCommand = new DelegateCommand(ExecuteAddAllToDownloadCommand));
/// <summary>
/// 添加所有视频到下载列表事件
/// </summary>
private void ExecuteAddAllToDownloadCommand()
{
}
// 列表选择事件
private DelegateCommand<object> favoritesMediasCommand;
public DelegateCommand<object> FavoritesMediasCommand => favoritesMediasCommand ?? (favoritesMediasCommand = new DelegateCommand<object>(ExecuteFavoritesMediasCommand));
/// <summary>
/// 列表选择事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteFavoritesMediasCommand(object parameter)
{
}
#endregion
/// <summary>
/// 初始化页面元素
/// </summary>
private void InitView()
{
LogManager.Debug(Tag, "初始化页面元素");
ContentVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Collapsed;
FavoritesMedias.Clear();
}
/// <summary>
/// 更新页面
/// </summary>
private void UpdateView(IFavoritesService favoritesService, long favoritesId)
{
Favorites = favoritesService.GetFavorites(favoritesId);
if (Favorites == null)
{
LogManager.Debug(Tag, "Favorites is null.");
ContentVisibility = Visibility.Collapsed;
NoDataVisibility = Visibility.Visible;
return;
}
else
{
ContentVisibility = Visibility.Visible;
NoDataVisibility = Visibility.Collapsed;
}
favoritesService.GetFavoritesMediaList(favoritesId, FavoritesMedias, eventAggregator);
}
/// <summary>
/// 接收收藏夹id参数
/// </summary>
/// <param name="navigationContext"></param>
public override void OnNavigatedTo(NavigationContext navigationContext)
public override async void OnNavigatedTo(NavigationContext navigationContext)
{
base.OnNavigatedTo(navigationContext);
@ -33,7 +262,13 @@ namespace DownKyi.ViewModels
{
return;
}
favoritesId = parameter;
InitView();
await Task.Run(new Action(() =>
{
UpdateView(new FavoritesService(), parameter);
}));
}
}
}

@ -137,8 +137,6 @@ namespace DownKyi.ViewModels
/// </summary>
private void ExecuteBackSpace()
{
InitView();
NavigationParam parameter = new NavigationParam
{
ViewName = ParentView,
@ -196,7 +194,7 @@ namespace DownKyi.ViewModels
}
catch (Exception e)
{
Core.Utils.Debug.Console.PrintLine("InputCommand()发生异常: {0}", e);
Core.Utils.Debugging.Console.PrintLine("InputCommand()发生异常: {0}", e);
LogManager.Error(Tag, e);
LoadingVisibility = Visibility.Collapsed;
@ -242,6 +240,18 @@ namespace DownKyi.ViewModels
LogManager.Info(Tag, "复制封面url到剪贴板");
}
// 前往UP主页事件
private DelegateCommand upperCommand;
public DelegateCommand UpperCommand => upperCommand ?? (upperCommand = new DelegateCommand(ExecuteUpperCommand));
/// <summary>
/// 前往UP主页事件
/// </summary>
private void ExecuteUpperCommand()
{
NavigateToView.NavigateToViewUserSpace(eventAggregator, Tag, VideoInfoView.UpperMid);
}
// 视频章节选择事件
private DelegateCommand<object> videoSectionsCommand;
public DelegateCommand<object> VideoSectionsCommand => videoSectionsCommand ?? (videoSectionsCommand = new DelegateCommand<object>(ExecuteVideoSectionsCommand));
@ -355,7 +365,7 @@ namespace DownKyi.ViewModels
}
catch (Exception e)
{
Core.Utils.Debug.Console.PrintLine("ParseCommand()发生异常: {0}", e);
Core.Utils.Debugging.Console.PrintLine("ParseCommand()发生异常: {0}", e);
LogManager.Error(Tag, e);
LoadingVisibility = Visibility.Collapsed;
@ -462,7 +472,7 @@ namespace DownKyi.ViewModels
}
catch (Exception e)
{
Core.Utils.Debug.Console.PrintLine("ParseCommand()发生异常: {0}", e);
Core.Utils.Debugging.Console.PrintLine("ParseCommand()发生异常: {0}", e);
LogManager.Error(Tag, e);
LoadingVisibility = Visibility.Collapsed;
@ -492,6 +502,13 @@ namespace DownKyi.ViewModels
// 选择的下载文件夹
string directory = string.Empty;
// 下载内容
bool downloadAudio = true;
bool downloadVideo = true;
bool downloadDanmaku = true;
bool downloadSubtitle = true;
bool downloadCover = true;
// 是否使用默认下载目录
if (SettingsManager.GetInstance().IsUseSaveVideoRootPath() == AllowStatus.YES)
{
@ -500,24 +517,36 @@ namespace DownKyi.ViewModels
else
{
// 打开文件夹选择器
dialogService.ShowDialog(ViewDirectorySelectorViewModel.Tag, null, result =>
dialogService.ShowDialog(ViewDownloadSetterViewModel.Tag, null, result =>
{
if (result.Result == ButtonResult.OK)
{
// 选择的下载文件夹
directory = result.Parameters.GetValue<string>("directory");
// 下载内容
downloadAudio = result.Parameters.GetValue<bool>("downloadAudio");
downloadVideo = result.Parameters.GetValue<bool>("downloadVideo");
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);
}
// 添加到下载
eventAggregator.GetEvent<MessageEvent>().Publish(directory);
}
});
}
// 下载设置dialog中如果点击取消或者关闭窗口
// 会返回空字符串,
// 这时直接退出
if (directory == string.Empty) { return; }
// 添加到下载
eventAggregator.GetEvent<MessageEvent>().Publish(directory);
}
/// <summary>
@ -595,6 +624,7 @@ namespace DownKyi.ViewModels
{
LoadingVisibility = Visibility.Collapsed;
ContentVisibility = Visibility.Visible;
NoDataVisibility = Visibility.Collapsed;
}
var videoSections = videoInfoService.GetVideoSections();

@ -0,0 +1,321 @@
<UserControl
x:Class="DownKyi.Views.Dialogs.ViewDownloadSetter"
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">
<prism:Dialog.WindowStyle>
<Style TargetType="Window">
<Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterOwner" />
<Setter Property="ResizeMode" Value="NoResize" />
<Setter Property="ShowInTaskbar" Value="False" />
<Setter Property="SizeToContent" Value="WidthAndHeight" />
<Setter Property="WindowStyle" Value="None" />
</Style>
</prism:Dialog.WindowStyle>
<Border BorderBrush="{DynamicResource BrushWindowBorder}" BorderThickness="1,1,1,0.6">
<Grid Background="{DynamicResource BrushBackground}">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid
Grid.Row="0"
Background="{DynamicResource BrushCaptionBackground}"
KeyboardNavigation.TabNavigation="None">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding DragMoveCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Margin="10,0"
VerticalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushCaptionForeground}"
Text="{Binding Title}" />
<Button
Grid.Column="4"
Command="{Binding CloseCommand}"
Style="{StaticResource CloseBtnStyle}"
ToolTip="{DynamicResource Close}">
<Path
Width="{Binding CloseIcon.Width}"
Height="{Binding CloseIcon.Height}"
Data="{Binding CloseIcon.Data}"
Fill="{Binding CloseIcon.Fill}"
Stretch="UniformToFill" />
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:InvokeCommandAction Command="{Binding CloseEnterCommand}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave">
<i:InvokeCommandAction Command="{Binding CloseLeaveCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
<Grid
Grid.Row="1"
MinWidth="600"
Margin="15,10">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="0,30,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ContentControl
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Bottom">
<Path
Width="{Binding CloudDownloadIcon.Width}"
Height="{Binding CloudDownloadIcon.Height}"
Data="{Binding CloudDownloadIcon.Data}"
Fill="{Binding CloudDownloadIcon.Fill}"
Stretch="UniformToFill" />
</ContentControl>
<TextBlock
Grid.Column="2"
VerticalAlignment="Center"
FontSize="18"
Foreground="{DynamicResource BrushPrimary}"
Text="&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;" />
<ContentControl
Grid.Column="3"
HorizontalAlignment="Center"
VerticalAlignment="Bottom">
<Path
Width="{Binding FolderIcon.Width}"
Height="{Binding FolderIcon.Height}"
Data="{Binding FolderIcon.Data}"
Fill="{Binding FolderIcon.Fill}"
Stretch="UniformToFill" />
</ContentControl>
</Grid>
<Grid Grid.Row="1" Margin="0,30,0,0">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource Location}" />
<ComboBox
Grid.Row="0"
Grid.Column="1"
Height="25"
Margin="10,0"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
ItemsSource="{Binding DirectoryList, Mode=TwoWay}"
SelectedValue="{Binding Directory, Mode=TwoWay}" />
<Button
Grid.Row="0"
Grid.Column="2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Command="{Binding BrowseCommand}"
Content="{DynamicResource Browse}"
FontSize="12"
Foreground="{DynamicResource BrushText}"
Style="{StaticResource BtnStyle}" />
<StackPanel
Grid.Row="1"
Grid.Column="1"
Margin="10,10,10,0"
Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding Directory}" Value="">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
<DataTrigger Binding="{Binding Directory}" Value="{x:Null}">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{Binding DriveName}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource HardDiskFreeSpace}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{Binding DriveNameFreeSpace}" />
</StackPanel>
</Grid>
<Grid Grid.Row="2" Margin="0,30,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="75" />
<ColumnDefinition Width="75" />
<ColumnDefinition Width="75" />
<ColumnDefinition Width="75" />
<ColumnDefinition Width="75" />
<ColumnDefinition Width="75" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
VerticalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource DownloadContent}" />
<CheckBox
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding DownloadAllCommand}"
Content="{DynamicResource DownloadAll}"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding DownloadAll, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
<CheckBox
Grid.Column="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding DownloadAudioCommand}"
Content="{DynamicResource DownloadAudio}"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding DownloadAudio, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
<CheckBox
Grid.Column="3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding DownloadVideoCommand}"
Content="{DynamicResource DownloadVideo}"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding DownloadVideo, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
<CheckBox
Grid.Column="4"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding DownloadDanmakuCommand}"
Content="{DynamicResource DownloadDanmaku}"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding DownloadDanmaku, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
<CheckBox
Grid.Column="5"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding DownloadSubtitleCommand}"
Content="{DynamicResource DownloadSubtitle}"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding DownloadSubtitle, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
<CheckBox
Grid.Column="6"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding DownloadCoverCommand}"
Content="{DynamicResource DownloadCover}"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding DownloadCover, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}" />
</Grid>
<Grid Grid.Row="3" Margin="0,30,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<CheckBox
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Content="{DynamicResource IsDefaultDownloadDirectory}"
Foreground="{DynamicResource BrushTextDark}"
IsChecked="{Binding IsDefaultDownloadDirectory, Mode=TwoWay}"
Style="{StaticResource CheckBoxStyle}"
ToolTip="{DynamicResource IsDefaultDownloadDirectoryTip}" />
<Button
Grid.Column="2"
Width="75"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Command="{Binding DownloadCommand}"
Content="{DynamicResource Download}"
FontSize="12"
Foreground="{DynamicResource BrushText}"
Style="{StaticResource BtnStyle}" />
<Button
Grid.Column="3"
Width="75"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Command="{Binding CloseCommand}"
Content="{DynamicResource Cancel}"
FontSize="12"
Foreground="{DynamicResource BrushText}"
Style="{StaticResource BtnStyle}" />
</Grid>
</Grid>
</Grid>
</Border>
</UserControl>

@ -0,0 +1,15 @@
using System.Windows.Controls;
namespace DownKyi.Views.Dialogs
{
/// <summary>
/// Interaction logic for ViewDownloadSetter
/// </summary>
public partial class ViewDownloadSetter : UserControl
{
public ViewDownloadSetter()
{
InitializeComponent();
}
}
}

@ -2,9 +2,481 @@
x:Class="DownKyi.Views.ViewPublicFavorites"
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">
<Grid>
<TextBlock>公开访问的收藏夹</TextBlock>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="1" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="0"
Margin="10,5,0,5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding BackSpaceCommand}"
Style="{StaticResource ImageBtnStyle}">
<StackPanel Orientation="Horizontal">
<ContentControl Width="24" Height="24">
<Path
Width="{Binding ArrowBack.Width}"
Height="{Binding ArrowBack.Height}"
Data="{Binding ArrowBack.Data}"
Fill="{Binding ArrowBack.Fill}"
Stretch="None" />
</ContentControl>
<TextBlock
VerticalAlignment="Center"
FontSize="16"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource Favorites}" />
</StackPanel>
</Button>
</Grid>
<TextBlock Grid.Row="1" Background="{DynamicResource BrushBorder}" />
<Grid Grid.Row="2" Visibility="{Binding ContentVisibility}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="320" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- 左侧 -->
<StackPanel
Grid.Column="0"
Margin="10,10,10,10"
Orientation="Vertical">
<Image Source="{Binding Favorites.Cover}">
<Image.ContextMenu>
<ContextMenu>
<MenuItem Command="{Binding CopyCoverCommand}" Header="{DynamicResource CopyCover}" />
<MenuItem Command="{Binding CopyCoverUrlCommand}" Header="{DynamicResource CopyCoverUrl}" />
<!-- TODO 复制封面到文件 -->
</ContextMenu>
</Image.ContextMenu>
</Image>
<TextBlock
Margin="0,10,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="18"
FontWeight="Bold"
Foreground="{DynamicResource BrushTextDark}"
Text="{Binding Favorites.Title}"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding Favorites.Title}" />
<ScrollViewer
MaxHeight="80"
Margin="0,10,0,0"
VerticalScrollBarVisibility="Auto">
<TextBox
Background="{x:Null}"
BorderBrush="{x:Null}"
BorderThickness="0"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
IsReadOnly="True"
Text="{Binding Favorites.Description}"
TextWrapping="WrapWithOverflow" />
</ScrollViewer>
<Grid Margin="0,15,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
HorizontalAlignment="Left"
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding Favorites.CreateTime}" />
<StackPanel
Grid.Column="1"
HorizontalAlignment="Right"
Orientation="Horizontal">
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding Favorites.MediaCount}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource FavoritesMediaCount}" />
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding Favorites.MediaCount}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding Favorites.MediaCount}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
</Grid>
<Grid Margin="0,15,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel
Grid.Column="0"
HorizontalAlignment="Center"
Orientation="Vertical">
<ContentControl Width="16" Height="16">
<Path
Width="{Binding Play.Width}"
Height="{Binding Play.Height}"
Data="{Binding Play.Data}"
Fill="{Binding Play.Fill}"
Stretch="UniformToFill" />
</ContentControl>
<TextBlock
Margin="0,5,0,0"
HorizontalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextGrey2}"
Text="{Binding Favorites.PlayNumber}" />
</StackPanel>
<StackPanel
Grid.Column="1"
HorizontalAlignment="Center"
Orientation="Vertical">
<ContentControl Width="16" Height="16">
<Path
Width="{Binding Like.Width}"
Height="{Binding Like.Height}"
Data="{Binding Like.Data}"
Fill="{Binding Like.Fill}"
Stretch="UniformToFill" />
</ContentControl>
<TextBlock
Margin="0,5,0,0"
HorizontalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextGrey2}"
Text="{Binding Favorites.LikeNumber}" />
</StackPanel>
<StackPanel
Grid.Column="2"
HorizontalAlignment="Center"
Orientation="Vertical">
<ContentControl Width="16" Height="16">
<Path
Width="{Binding Favorite.Width}"
Height="{Binding Favorite.Height}"
Data="{Binding Favorite.Data}"
Fill="{Binding Favorite.Fill}"
Stretch="UniformToFill" />
</ContentControl>
<TextBlock
Margin="0,5,0,0"
HorizontalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextGrey2}"
Text="{Binding Favorites.FavoriteNumber}" />
</StackPanel>
<StackPanel
Grid.Column="3"
HorizontalAlignment="Center"
Orientation="Vertical">
<ContentControl Width="16" Height="16">
<Path
Width="{Binding Share.Width}"
Height="{Binding Share.Height}"
Data="{Binding Share.Data}"
Fill="{Binding Share.Fill}"
Stretch="UniformToFill" />
</ContentControl>
<TextBlock
Margin="0,5,0,0"
HorizontalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextGrey2}"
Text="{Binding Favorites.ShareNumber}" />
</StackPanel>
</Grid>
<StackPanel
Margin="0,20,0,0"
Cursor="Hand"
Orientation="Horizontal"
ToolTip="{Binding Favorites.UpName}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding UpperCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Image
Width="48"
Height="48"
Source="{Binding Favorites.UpHeader}">
<Image.Clip>
<EllipseGeometry
Center="24,24"
RadiusX="24"
RadiusY="24" />
</Image.Clip>
</Image>
<TextBlock
Margin="15,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource BrushPrimary}"
Text="{Binding Favorites.UpName}"
TextTrimming="CharacterEllipsis" />
</StackPanel>
<TextBlock
Height="1"
Margin="0,20,0,0"
Background="{DynamicResource BrushBorder}" />
<Button
Height="40"
Margin="0,20,0,0"
HorizontalAlignment="Stretch"
Command="{Binding AddToDownloadCommand}"
Content="{DynamicResource DownloadSelected}"
FontSize="12"
Foreground="{DynamicResource BrushText}"
Style="{StaticResource BtnStyle}" />
<Button
Height="40"
Margin="0,20,0,0"
HorizontalAlignment="Stretch"
Command="{Binding AddAllToDownloadCommand}"
Content="{DynamicResource AddAllToDownload}"
FontSize="12"
Foreground="{DynamicResource BrushText}"
Style="{StaticResource BtnStyle}" />
</StackPanel>
<!-- 右侧内容区 -->
<ListBox
x:Name="nameFavoritesMedias"
Grid.Column="1"
Margin="30,0,0,0"
ItemsSource="{Binding FavoritesMedias, Mode=TwoWay}"
SelectionMode="Extended">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding FavoritesMediasCommand}" CommandParameter="{Binding ElementName=nameFavoritesMedias, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.Template>
<ControlTemplate TargetType="{x:Type ListBox}">
<ScrollViewer
CanContentScroll="False"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<StackPanel IsItemsHost="True" Orientation="Vertical" />
</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}">
<Grid Margin="0,10" Background="{DynamicResource BrushBackground}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Width="35"
Margin="0,0,5,0"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource BrushTextDark}"
Text="{Binding Order}" />
<Image Grid.Column="1" Source="{Binding Cover}" />
<Border
x:Name="nameInfoPanel"
Grid.Column="1"
Width="150"
Height="95"
Background="{DynamicResource BrushMask}"
Visibility="Hidden">
<TextBlock
Margin="5,0,0,5"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
FontSize="12"
Foreground="{DynamicResource BrushText}"
Text="{Binding Duration}" />
</Border>
<Image
x:Name="nameIsSelected"
Grid.Column="1"
Width="24"
Height="24"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Source="/DownKyi;component/Resources/checked.png" />
<Grid Grid.Column="2" Margin="20,0">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Cursor="Hand"
FontSize="14"
Text="{Binding Title}"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding Title}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding TitleCommand}" CommandParameter="{Binding DataContext.PageName, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{DynamicResource BrushTextDark}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{DynamicResource BrushPrimary}" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding PlayNumber}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource Play}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text=" · " />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding DanmakuNumber}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource Danmaku}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text=" · " />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding FavoriteNumber}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource Favorite}" />
</StackPanel>
<TextBlock
Grid.Row="2"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Cursor="Hand"
FontSize="12"
Text="{Binding UpName, StringFormat={}UP: {0}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding VideoUpperCommand}" CommandParameter="{Binding DataContext.PageName, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{DynamicResource BrushTextGrey}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{DynamicResource BrushPrimary}" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="nameInfoPanel" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="nameIsSelected" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="nameIsSelected" Property="Visibility" Value="Collapsed" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid>
<!-- 没有数据提示 -->
<Image
Grid.Row="2"
Width="256"
Height="256"
Source="/DownKyi;component/Resources/no-data.png"
Visibility="{Binding NoDataVisibility}" />
</Grid>
</UserControl>

@ -243,7 +243,7 @@
VerticalAlignment="Center"
Command="{Binding DownloadManagerCommand}"
Style="{StaticResource ImageBtnStyle}"
ToolTip="{DynamicResource DownloadManage}">
ToolTip="{DynamicResource DownloadManager}">
<ContentControl>
<Path
Width="{Binding DownloadManage.Width}"
@ -281,7 +281,7 @@
<ContextMenu>
<MenuItem Command="{Binding CopyCoverCommand}" Header="{DynamicResource CopyCover}" />
<MenuItem Command="{Binding CopyCoverUrlCommand}" Header="{DynamicResource CopyCoverUrl}" />
<!-- 复制封面到文件 -->
<!-- TODO 复制封面到文件 -->
</ContextMenu>
</Image.ContextMenu>
</Image>
@ -335,12 +335,17 @@
Grid.Row="2"
VerticalAlignment="Center"
Orientation="Horizontal">
<TextBlock
Margin="0,0,10,0"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.PlayNumber, StringFormat={}{0}播放}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<StackPanel Margin="0,0,10,0" Orientation="Horizontal">
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.PlayNumber}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource Play}" />
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding VideoInfoView.PlayNumber}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
@ -350,14 +355,20 @@
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock
Margin="0,0,10,0"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.DanmakuNumber, StringFormat={}{0}弹幕}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
</StackPanel.Style>
</StackPanel>
<StackPanel Margin="0,0,10,0" Orientation="Horizontal">
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.DanmakuNumber}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource Danmaku}" />
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding VideoInfoView.DanmakuNumber}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
@ -367,14 +378,20 @@
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock
Margin="0,0,10,0"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.LikeNumber, StringFormat={}{0}点赞}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
</StackPanel.Style>
</StackPanel>
<StackPanel Margin="0,0,10,0" Orientation="Horizontal">
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.LikeNumber}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource Like}" />
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding VideoInfoView.LikeNumber}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
@ -384,14 +401,20 @@
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock
Margin="0,0,10,0"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.CoinNumber, StringFormat={}{0}投币}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
</StackPanel.Style>
</StackPanel>
<StackPanel Margin="0,0,10,0" Orientation="Horizontal">
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.CoinNumber}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource Coin}" />
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding VideoInfoView.CoinNumber}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
@ -401,14 +424,20 @@
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock
Margin="0,0,10,0"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.FavoriteNumber, StringFormat={}{0}收藏}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
</StackPanel.Style>
</StackPanel>
<StackPanel Margin="0,0,10,0" Orientation="Horizontal">
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.FavoriteNumber}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource Favorite}" />
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding VideoInfoView.FavoriteNumber}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
@ -418,14 +447,20 @@
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock
Margin="0,0,10,0"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.ShareNumber, StringFormat={}{0}分享}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
</StackPanel.Style>
</StackPanel>
<StackPanel Margin="0,0,10,0" Orientation="Horizontal">
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.ShareNumber}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource Share}" />
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding VideoInfoView.ShareNumber}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
@ -435,14 +470,20 @@
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock
Margin="0,0,10,0"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.ReplyNumber, StringFormat={}{0}评论}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
</StackPanel.Style>
</StackPanel>
<StackPanel Margin="0,0,10,0" Orientation="Horizontal">
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{Binding VideoInfoView.ReplyNumber}" />
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextGrey}"
Text="{DynamicResource Reply}" />
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding VideoInfoView.ReplyNumber}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
@ -452,8 +493,8 @@
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel.Style>
</StackPanel>
</StackPanel>
</Grid>
@ -464,7 +505,7 @@
ToolTip="{Binding VideoInfoView.UpName}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding}" />
<i:InvokeCommandAction Command="{Binding UpperCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
@ -482,6 +523,7 @@
<TextBlock
Margin="0,2,0,0"
HorizontalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{Binding VideoInfoView.UpName}"
TextTrimming="CharacterEllipsis" />
@ -496,6 +538,7 @@
Background="{x:Null}"
BorderBrush="{x:Null}"
BorderThickness="0"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
IsReadOnly="True"
Text="{Binding VideoInfoView.Description}"

Loading…
Cancel
Save