mirror of
https://github.com/leiurayer/downkyi.git
synced 2025-04-27 05:30:47 +08:00
DownKyi主程序部分代码
This commit is contained in:
parent
56f24eb4a1
commit
961a5b66c3
src
DownKyi.Core/obj/Debug
DownKyi.slnDownKyi
App.xamlApp.xaml.cs
CustomControl
DownKyi.csprojDownKyi.csproj.userEvents
FFmpeg_LICENSE.txtImages
Languages
Models
AppInfo.csParseScopeDisplay.csResolution.csTabHeader.csVideoInfoView.csVideoPage.csVideoQuality.csVideoSection.cs
Properties
Resources
Services
BangumiInfoService.csCheeseInfoService.csIInfoService.csIResolutionService.csResolutionService.csUtils.csVideoInfoService.cs
Themes
ColorBrush.xaml
Colors
Styles
StyleBtn.xamlStyleCheckBox.xamlStyleImageBtn.xamlStyleListBox.xamlStyleListView.xamlStyleRadio.xamlStyleSystemBtn.xaml
ThemeDefault.xamlThemeDiy.xamlUtils
ViewModels
BaseViewModel.cs
Dialogs
DownloadManager
MainWindowViewModel.csSettings
ViewAboutViewModel.csViewBasicViewModel.csViewDanmakuViewModel.csViewNetworkViewModel.csViewVideoViewModel.cs
Toolbox
ViewDownloadManagerViewModel.csViewIndexViewModel.csViewLoginViewModel.csViewMySpaceViewModel.csViewPublicFavoritesViewModel.csViewSettingsViewModel.csViewToolboxViewModel.csViewUserSpaceViewModel.csViewVideoDetailViewModel.csViews
Binary file not shown.
34
src/DownKyi.sln
Normal file
34
src/DownKyi.sln
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31019.35
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DownKyi", "DownKyi\DownKyi.csproj", "{97075FCD-6E8F-4FF9-B73A-994197F3765A}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{4FDE0364-F65B-4812-BFE8-34E886624FBD} = {4FDE0364-F65B-4812-BFE8-34E886624FBD}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DownKyi.Core", "DownKyi.Core\DownKyi.Core.csproj", "{4FDE0364-F65B-4812-BFE8-34E886624FBD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{97075FCD-6E8F-4FF9-B73A-994197F3765A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{97075FCD-6E8F-4FF9-B73A-994197F3765A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{97075FCD-6E8F-4FF9-B73A-994197F3765A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{97075FCD-6E8F-4FF9-B73A-994197F3765A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4FDE0364-F65B-4812-BFE8-34E886624FBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4FDE0364-F65B-4812-BFE8-34E886624FBD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4FDE0364-F65B-4812-BFE8-34E886624FBD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4FDE0364-F65B-4812-BFE8-34E886624FBD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {B8FC6858-6EAD-46C9-AC9A-01E6DEBA32BC}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
15
src/DownKyi/App.xaml
Normal file
15
src/DownKyi/App.xaml
Normal file
@ -0,0 +1,15 @@
|
||||
<prism:PrismApplication
|
||||
x:Class="DownKyi.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi"
|
||||
xmlns:prism="http://prismlibrary.com/">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Themes/ThemeDefault.xaml" />
|
||||
<ResourceDictionary Source="Languages/Default.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</prism:PrismApplication>
|
81
src/DownKyi/App.xaml.cs
Normal file
81
src/DownKyi/App.xaml.cs
Normal file
@ -0,0 +1,81 @@
|
||||
using DownKyi.Utils;
|
||||
using DownKyi.ViewModels;
|
||||
using DownKyi.ViewModels.Dialogs;
|
||||
using DownKyi.ViewModels.DownloadManager;
|
||||
using DownKyi.ViewModels.Settings;
|
||||
using DownKyi.ViewModels.Toolbox;
|
||||
using DownKyi.Views;
|
||||
using DownKyi.Views.Dialogs;
|
||||
using DownKyi.Views.DownloadManager;
|
||||
using DownKyi.Views.Settings;
|
||||
using DownKyi.Views.Toolbox;
|
||||
using Prism.Ioc;
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace DownKyi
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App
|
||||
{
|
||||
protected override Window CreateShell()
|
||||
{
|
||||
// 设置主题
|
||||
DictionaryResource.LoadTheme("ThemeDefault");
|
||||
//DictionaryResource.LoadTheme("ThemeDiy");
|
||||
|
||||
// 切换语言
|
||||
DictionaryResource.LoadLanguage("Default");
|
||||
//DictionaryResource.LoadLanguage("en_US");
|
||||
|
||||
return Container.Resolve<MainWindow>();
|
||||
}
|
||||
|
||||
protected override void RegisterTypes(IContainerRegistry containerRegistry)
|
||||
{
|
||||
// pages
|
||||
containerRegistry.RegisterForNavigation<ViewIndex>(ViewIndexViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewLogin>(ViewLoginViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewVideoDetail>(ViewVideoDetailViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewSettings>(ViewSettingsViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewDownloadManager>(ViewDownloadManagerViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewToolbox>(ViewToolboxViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewUserSpace>(ViewUserSpaceViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewMySpace>(ViewMySpaceViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewPublicFavorites>(ViewPublicFavoritesViewModel.Tag);
|
||||
|
||||
// downloadManager pages
|
||||
containerRegistry.RegisterForNavigation<ViewDownloading>(ViewDownloadingViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewDownloadFinished>(ViewDownloadFinishedViewModel.Tag);
|
||||
|
||||
// settings pages
|
||||
containerRegistry.RegisterForNavigation<ViewBasic>(ViewBasicViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewNetwork>(ViewNetworkViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewVideo>(ViewVideoViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewDanmaku>(ViewDanmakuViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewAbout>(ViewAboutViewModel.Tag);
|
||||
|
||||
// tools pages
|
||||
containerRegistry.RegisterForNavigation<ViewBiliHelper>(ViewBiliHelperViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewDelogo>(ViewDelogoViewModel.Tag);
|
||||
containerRegistry.RegisterForNavigation<ViewExtractMedia>(ViewExtractMediaViewModel.Tag);
|
||||
|
||||
// dialogs
|
||||
containerRegistry.RegisterDialog<ViewDirectorySelector>(ViewDirectorySelectorViewModel.Tag);
|
||||
containerRegistry.RegisterDialog<ViewParsingSelector>(ViewParsingSelectorViewModel.Tag);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步修改绑定到UI的属性
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
public static void PropertyChangeAsync(Action callback)
|
||||
{
|
||||
Current.Dispatcher.Invoke(callback);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
103
src/DownKyi/CustomControl/GifImage.cs
Normal file
103
src/DownKyi/CustomControl/GifImage.cs
Normal file
@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace DownKyi.CustomControl
|
||||
{
|
||||
public class GifImage : System.Windows.Controls.Image
|
||||
{
|
||||
/// <summary>
|
||||
/// gif动画的System.Drawing.Bitmap
|
||||
/// </summary>
|
||||
private Bitmap gifBitmap;
|
||||
|
||||
/// <summary>
|
||||
/// 用于显示每一帧的BitmapSource
|
||||
/// </summary>
|
||||
private BitmapSource bitmapSource;
|
||||
|
||||
public GifImage(string gifPath)
|
||||
{
|
||||
gifBitmap = new Bitmap(gifPath);
|
||||
bitmapSource = GetBitmapSource();
|
||||
Source = bitmapSource;
|
||||
}
|
||||
|
||||
public GifImage(Bitmap gifBitmap)
|
||||
{
|
||||
this.gifBitmap = gifBitmap;
|
||||
bitmapSource = GetBitmapSource();
|
||||
Source = bitmapSource;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从System.Drawing.Bitmap中获得用于显示的那一帧图像的BitmapSource
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private BitmapSource GetBitmapSource()
|
||||
{
|
||||
IntPtr handle = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
handle = gifBitmap.GetHbitmap();
|
||||
bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (handle != IntPtr.Zero)
|
||||
{
|
||||
DeleteObject(handle);
|
||||
}
|
||||
}
|
||||
return bitmapSource;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start animation
|
||||
/// </summary>
|
||||
public void StartAnimate()
|
||||
{
|
||||
ImageAnimator.Animate(gifBitmap, OnFrameChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop animation
|
||||
/// </summary>
|
||||
public void StopAnimate()
|
||||
{
|
||||
ImageAnimator.StopAnimate(gifBitmap, OnFrameChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler for the frame changed
|
||||
/// </summary>
|
||||
private void OnFrameChanged(object sender, EventArgs e)
|
||||
{
|
||||
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
ImageAnimator.UpdateFrames(); // 更新到下一帧
|
||||
if (bitmapSource != null)
|
||||
{
|
||||
bitmapSource.Freeze();
|
||||
}
|
||||
|
||||
//// Convert the bitmap to BitmapSource that can be display in WPF Visual Tree
|
||||
bitmapSource = GetBitmapSource();
|
||||
Source = bitmapSource;
|
||||
InvalidateVisual();
|
||||
}));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete local bitmap resource
|
||||
/// Reference: http://msdn.microsoft.com/en-us/library/dd183539(VS.85).aspx
|
||||
/// </summary>
|
||||
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
static extern bool DeleteObject(IntPtr hObject);
|
||||
}
|
||||
}
|
447
src/DownKyi/DownKyi.csproj
Normal file
447
src/DownKyi/DownKyi.csproj
Normal file
@ -0,0 +1,447 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{97075FCD-6E8F-4FF9-B73A-994197F3765A}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DownKyi</RootNamespace>
|
||||
<AssemblyName>DownKyi</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Resources\favicon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="CustomControl\GifImage.cs" />
|
||||
<Compile Include="Events\MessageEvent.cs" />
|
||||
<Compile Include="Events\NavigationEvent.cs" />
|
||||
<Compile Include="Events\NavigationParam.cs" />
|
||||
<Compile Include="Images\ButtonIcon.cs" />
|
||||
<Compile Include="Images\LogoIcon.cs" />
|
||||
<Compile Include="Images\NavigationIcon.cs" />
|
||||
<Compile Include="Images\NormalIcon.cs" />
|
||||
<Compile Include="Models\ParseScopeDisplay.cs" />
|
||||
<Compile Include="Models\Resolution.cs" />
|
||||
<Compile Include="Models\TabHeader.cs" />
|
||||
<Compile Include="Models\VideoQuality.cs" />
|
||||
<Compile Include="Models\VideoInfoView.cs" />
|
||||
<Compile Include="Models\VideoPage.cs" />
|
||||
<Compile Include="Models\VideoSection.cs" />
|
||||
<Compile Include="Services\BangumiInfoService.cs" />
|
||||
<Compile Include="Services\CheeseInfoService.cs" />
|
||||
<Compile Include="Services\IInfoService.cs" />
|
||||
<Compile Include="Services\IResolutionService.cs" />
|
||||
<Compile Include="Services\ResolutionService.cs" />
|
||||
<Compile Include="Services\Utils.cs" />
|
||||
<Compile Include="Services\VideoInfoService.cs" />
|
||||
<Compile Include="Utils\ClipboardHooker.cs" />
|
||||
<Compile Include="Utils\DialogUtils.cs" />
|
||||
<Compile Include="Utils\DictionaryResource.cs" />
|
||||
<Compile Include="ViewModels\BaseViewModel.cs" />
|
||||
<Compile Include="ViewModels\Dialogs\ViewDirectorySelectorViewModel.cs" />
|
||||
<Compile Include="ViewModels\Dialogs\BaseDialogViewModel.cs" />
|
||||
<Compile Include="ViewModels\Settings\ViewBasicViewModel.cs" />
|
||||
<Compile Include="ViewModels\Settings\ViewAboutViewModel.cs" />
|
||||
<Compile Include="ViewModels\Settings\ViewDanmakuViewModel.cs" />
|
||||
<Compile Include="ViewModels\DownloadManager\ViewDownloadFinishedViewModel.cs" />
|
||||
<Compile Include="ViewModels\DownloadManager\ViewDownloadingViewModel.cs" />
|
||||
<Compile Include="ViewModels\Toolbox\ViewBiliHelperViewModel.cs" />
|
||||
<Compile Include="ViewModels\Toolbox\ViewDelogoViewModel.cs" />
|
||||
<Compile Include="ViewModels\ViewDownloadManagerViewModel.cs" />
|
||||
<Compile Include="ViewModels\Toolbox\ViewExtractMediaViewModel.cs" />
|
||||
<Compile Include="ViewModels\ViewIndexViewModel.cs" />
|
||||
<Compile Include="ViewModels\ViewLoginViewModel.cs" />
|
||||
<Compile Include="ViewModels\Settings\ViewNetworkViewModel.cs" />
|
||||
<Compile Include="ViewModels\Dialogs\ViewParsingSelectorViewModel.cs" />
|
||||
<Compile Include="ViewModels\ViewMySpaceViewModel.cs" />
|
||||
<Compile Include="ViewModels\ViewPublicFavoritesViewModel.cs" />
|
||||
<Compile Include="ViewModels\ViewSettingsViewModel.cs" />
|
||||
<Compile Include="ViewModels\ViewToolboxViewModel.cs" />
|
||||
<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>
|
||||
<Compile Include="Views\Dialogs\ViewParsingSelector.xaml.cs">
|
||||
<DependentUpon>ViewParsingSelector.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\DownloadManager\ViewDownloadFinished.xaml.cs">
|
||||
<DependentUpon>ViewDownloadFinished.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\DownloadManager\ViewDownloading.xaml.cs">
|
||||
<DependentUpon>ViewDownloading.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Settings\ViewAbout.xaml.cs">
|
||||
<DependentUpon>ViewAbout.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Settings\ViewBasic.xaml.cs">
|
||||
<DependentUpon>ViewBasic.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Settings\ViewDanmaku.xaml.cs">
|
||||
<DependentUpon>ViewDanmaku.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Settings\ViewNetwork.xaml.cs">
|
||||
<DependentUpon>ViewNetwork.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Settings\ViewVideo.xaml.cs">
|
||||
<DependentUpon>ViewVideo.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Toolbox\ViewBiliHelper.xaml.cs">
|
||||
<DependentUpon>ViewBiliHelper.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Toolbox\ViewDelogo.xaml.cs">
|
||||
<DependentUpon>ViewDelogo.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Toolbox\ViewExtractMedia.xaml.cs">
|
||||
<DependentUpon>ViewExtractMedia.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ViewDownloadManager.xaml.cs">
|
||||
<DependentUpon>ViewDownloadManager.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ViewIndex.xaml.cs">
|
||||
<DependentUpon>ViewIndex.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ViewLogin.xaml.cs">
|
||||
<DependentUpon>ViewLogin.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ViewMySpace.xaml.cs">
|
||||
<DependentUpon>ViewMySpace.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ViewPublicFavorites.xaml.cs">
|
||||
<DependentUpon>ViewPublicFavorites.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ViewSettings.xaml.cs">
|
||||
<DependentUpon>ViewSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ViewToolbox.xaml.cs">
|
||||
<DependentUpon>ViewToolbox.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ViewUserSpace.xaml.cs">
|
||||
<DependentUpon>ViewUserSpace.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ViewVideoDetail.xaml.cs">
|
||||
<DependentUpon>ViewVideoDetail.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="Languages\en_US.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Languages\zh_TW.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Languages\zh_CN.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Languages\Default.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\ColorBrush.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Colors\ColorDiy.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Themes\Colors\ColorDefault.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Styles\StyleListBox.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Styles\StyleListView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Themes\Styles\StyleCheckBox.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Themes\Styles\StyleBtn.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Themes\Styles\StyleImageBtn.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Styles\StyleRadio.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Styles\StyleSystemBtn.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\ThemeDiy.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Themes\ThemeDefault.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Dialogs\ViewDirectorySelector.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Dialogs\ViewParsingSelector.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\DownloadManager\ViewDownloadFinished.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\DownloadManager\ViewDownloading.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Images\SystemIcon.cs" />
|
||||
<Compile Include="Images\VectorImage.cs" />
|
||||
<Compile Include="Models\AppInfo.cs" />
|
||||
<Compile Include="ViewModels\MainWindowViewModel.cs" />
|
||||
<Compile Include="Views\MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Page Include="Views\Settings\ViewAbout.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Settings\ViewBasic.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Settings\ViewDanmaku.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Settings\ViewNetwork.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Settings\ViewVideo.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Toolbox\ViewBiliHelper.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Toolbox\ViewDelogo.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Toolbox\ViewExtractMedia.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ViewDownloadManager.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ViewIndex.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ViewLogin.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ViewMySpace.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ViewPublicFavorites.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ViewSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ViewToolbox.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ViewUserSpace.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ViewVideoDetail.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="app.config" />
|
||||
<None Include="app.manifest" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Prism.DryIoc" Version="8.1.97" />
|
||||
<PackageReference Include="System.Data.SQLite.Core">
|
||||
<Version>1.0.112.2</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\favicon.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\default_header.jpg" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DownKyi.Core\DownKyi.Core.csproj">
|
||||
<Project>{4fde0364-f65b-4812-bfe8-34e886624fbd}</Project>
|
||||
<Name>DownKyi.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\login\login_top_bar.png" />
|
||||
<Resource Include="Resources\login\qrcode_login_2233.png" />
|
||||
<Resource Include="Resources\login\qrcode_login_tip.png" />
|
||||
<Resource Include="Resources\login\scan_succeed.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.7.2 %28x86 和 x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\loading\loading.gif" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\no-data.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="aria2c.exe">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="aria2_COPYING.txt">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="ffmpeg.exe">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="FFmpeg_LICENSE.txt">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="打不开DownKyi请点我.txt">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="AfterCompile">
|
||||
<Exec Command="echo """ />
|
||||
</Target>
|
||||
</Project>
|
13
src/DownKyi/DownKyi.csproj.user
Normal file
13
src/DownKyi/DownKyi.csproj.user
Normal file
@ -0,0 +1,13 @@
|
||||
<?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>
|
6
src/DownKyi/Events/MessageEvent.cs
Normal file
6
src/DownKyi/Events/MessageEvent.cs
Normal file
@ -0,0 +1,6 @@
|
||||
using Prism.Events;
|
||||
|
||||
namespace DownKyi.Events
|
||||
{
|
||||
public class MessageEvent : PubSubEvent<string> { }
|
||||
}
|
6
src/DownKyi/Events/NavigationEvent.cs
Normal file
6
src/DownKyi/Events/NavigationEvent.cs
Normal file
@ -0,0 +1,6 @@
|
||||
using Prism.Events;
|
||||
|
||||
namespace DownKyi.Events
|
||||
{
|
||||
public class NavigationEvent : PubSubEvent<NavigationParam> { }
|
||||
}
|
9
src/DownKyi/Events/NavigationParam.cs
Normal file
9
src/DownKyi/Events/NavigationParam.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace DownKyi.Events
|
||||
{
|
||||
public class NavigationParam
|
||||
{
|
||||
public string ViewName { get; set; }
|
||||
public string ParentViewName { get; set; }
|
||||
public object Parameter { get; set; }
|
||||
}
|
||||
}
|
674
src/DownKyi/FFmpeg_LICENSE.txt
Normal file
674
src/DownKyi/FFmpeg_LICENSE.txt
Normal file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
79
src/DownKyi/Images/ButtonIcon.cs
Normal file
79
src/DownKyi/Images/ButtonIcon.cs
Normal file
@ -0,0 +1,79 @@
|
||||
namespace DownKyi.Images
|
||||
{
|
||||
public class ButtonIcon
|
||||
{
|
||||
private static ButtonIcon instance;
|
||||
public static ButtonIcon Instance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new ButtonIcon();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public ButtonIcon()
|
||||
{
|
||||
GeneralSearch = new VectorImage
|
||||
{
|
||||
Height = 20,
|
||||
Width = 20,
|
||||
Data = @"M697.91 755.7 q-132.36 103.48 -290.59 98.06 q-158.23 -5.41 -278.56 -120.92 q-127.54 -133.56 -128.75 -304.43
|
||||
q-1.21 -170.86 120.33 -304.43 q127.55 -126.34 297.21 -123.94 q169.66 2.41 303.22 123.94 q110.71 114.31 122.14 263.52
|
||||
q11.43 149.21 -75.21 275.55 l238.25 239.45 q18.05 18.05 18.05 42.12 q0 24.06 -18.05 41.51 q-18.05 17.45 -42.12 17.45
|
||||
q-24.07 0 -42.12 -16.85 l-223.81 -231.03 ZM643.76 647.41 q92.66 -96.26 92.66 -219 q0 -122.73 -92.66 -218.99 q-96.26 -92.66 -219 -92.66
|
||||
q-122.74 0 -218.99 92.66 q-92.65 96.26 -92.65 218.99 q0 122.74 92.65 219 q96.26 92.65 218.99 90.25 q122.74 -2.4 219 -90.25 Z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
|
||||
Settings = new VectorImage
|
||||
{
|
||||
Height = 32,
|
||||
Width = 32,
|
||||
Data = @"M19.4,13c0-0.3,0.1-0.6,0.1-1s0-0.7-0.1-1l2.1-1.7c0.2-0.2,0.2-0.4,0.1-0.6l-2-3.5C19.5,5,19.3,5,19,5l-2.5,1
|
||||
c-0.5-0.4-1.1-0.7-1.7-1l-0.4-2.7C14.5,2.2,14.3,2,14,2h-4C9.8,2,9.5,2.2,9.5,2.4L9.1,5.1C8.5,5.3,8,5.7,7.4,6L5,5
|
||||
C4.7,5,4.5,5,4.3,5.3l-2,3.5C2.2,9,2.3,9.2,2.5,9.4L4.6,11c0,0.3-0.1,0.6-0.1,1s0,0.7,0.1,1l-2.1,1.7c-0.2,0.1-0.2,0.4-0.1,0.6
|
||||
l2,3.5C4.5,19,4.7,19,5,19l2.5-1c0.5,0.4,1.1,0.7,1.7,1l0.4,2.7c0,0.2,0.2,0.4,0.5,0.4h4c0.3,0,0.5-0.2,0.5-0.4l0.4-2.7
|
||||
c0.6-0.3,1.2-0.6,1.7-1l2.5,1c0.2,0.1,0.5,0,0.6-0.2l2-3.5c0.1-0.2,0.1-0.5-0.1-0.6L19.4,13z M12,15.5c-1.9,0-3.5-1.6-3.5-3.5
|
||||
s1.6-3.5,3.5-3.5s3.5,1.6,3.5,3.5S13.9,15.5,12,15.5z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
|
||||
DownloadManage = new VectorImage
|
||||
{
|
||||
Height = 27,
|
||||
Width = 32,
|
||||
//Height = 20,
|
||||
//Width = 24,
|
||||
Data = @"M24,34c-2.4,0-4.9,0-7.3,0c-2.8,0-4.6-1.9-4.6-4.7c0-3.5,0-7,0-10.5c0-2.9,1.9-4.7,4.6-4.7c1.3,0,2.6,0,3.9,0
|
||||
c1.1-0.1,2,0.4,2.7,1.3c1.1,1.7,2.6,2.3,4.6,2.1c1.3-0.2,2.6-0.1,4,0c2.5,0.2,4,1.7,4.2,4.3c0.2,2.7,0.2,5.5,0,8.3
|
||||
c-0.2,2.4-2,4-4.3,4C29,34,26.5,34,24,34L24,34z
|
||||
M23.9,32.6c2.5,0,5,0,7.5,0c1.7,0,2.9-1,3-2.7c0.2-2.8,0.2-5.6,0-8.5
|
||||
c-0.1-1.5-1.1-2.4-2.5-2.6c-1.3-0.2-2.6-0.1-3.9-0.1c-4.1-0.1-3,0.5-6-2.6c-0.5-0.5-1-0.8-1.7-0.8c-1.3,0-2.5,0-3.8,0
|
||||
c-2,0-3.2,1.2-3.3,3.2c0,3.6,0,7.1,0,10.7c0,2,1.2,3.2,3.2,3.2C19,32.6,21.5,32.6,23.9,32.6L23.9,32.6z
|
||||
M29.9,14.2h3.3c0.5,0,0.9,0,0.9,0.7c0,0.7-0.4,0.8-0.9,0.8c-2.2,0-4.5,0-6.7,0c-0.5,0-0.9-0.1-0.9-0.7
|
||||
s0.4-0.7,0.9-0.7C27.6,14.2,28.7,14.2,29.9,14.2L29.9,14.2z M23.3,27.6v-5.4c0-0.5,0-1.1,0.7-1.1c0.7,0,0.6,0.6,0.6,1v5.2
|
||||
c0.7-0.7,1.2-1.2,1.7-1.7c0.3-0.4,0.7-0.7,1.2-0.2c0.5,0.5,0.1,0.9-0.2,1.2c-0.9,1-1.8,1.9-2.7,2.8c-0.4,0.5-0.8,0.5-1.3,0.1
|
||||
c-1-1-2-2.1-3-3.1c-0.3-0.3-0.4-0.7-0.1-1c0.3-0.4,0.7-0.3,1,0.1C22,26.1,22.6,26.7,23.3,27.6L23.3,27.6z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
|
||||
Toolbox = new VectorImage
|
||||
{
|
||||
Height = 28, // 21
|
||||
Width = 32, // 24
|
||||
Data = @"M20.2,14.5c-0.8,2.3-3.4,3.6-5.7,2.7c-1.3-0.5-2.3-1.5-2.7-2.7H5.5V13h21v1.5H20.2z M18.6,14.5h-5.2
|
||||
c0.8,1.4,2.7,1.9,4.1,1.1C18,15.3,18.3,15,18.6,14.5L18.6,14.5z M10,8.5V7c0-0.8,0.7-1.5,1.5-1.5h9C21.3,5.5,22,6.2,22,7v1.5h4.5
|
||||
c0.8,0,1.5,0.7,1.5,1.5v15c0,0.8-0.7,1.5-1.5,1.5l0,0h-21C4.7,26.5,4,25.8,4,25l0,0V10c0-0.8,0.7-1.5,1.5-1.5H10z M11.5,8.5h9V7h-9
|
||||
V8.5z M5.5,10v15h21V10H5.5z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
}
|
||||
|
||||
public VectorImage GeneralSearch { get; private set; }
|
||||
public VectorImage Settings { get; private set; }
|
||||
public VectorImage DownloadManage { get; private set; }
|
||||
public VectorImage Toolbox { get; private set; }
|
||||
|
||||
}
|
||||
}
|
54
src/DownKyi/Images/LogoIcon.cs
Normal file
54
src/DownKyi/Images/LogoIcon.cs
Normal file
@ -0,0 +1,54 @@
|
||||
namespace DownKyi.Images
|
||||
{
|
||||
class LogoIcon
|
||||
{
|
||||
private static LogoIcon instance;
|
||||
public static LogoIcon Instance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new LogoIcon();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private LogoIcon()
|
||||
{
|
||||
TextLogo = new VectorImage
|
||||
{
|
||||
Height = 100,
|
||||
Width = 336,
|
||||
Data = @"M602.247902 495.326917q0-146.045116 60.22479-219.820484a198.13956 198.13956 0 0 1 308.953174 0q61.73041
|
||||
74.076492 62.031534 213.798005 0 150.561976-60.22479 225.54184a198.13956 198.13956 0 0 1-309.254298 0Q602.247902 640.468662
|
||||
602.247902 495.326917z m80.098971 0A273.721671 273.721671 0 0 0 722.697482 657.331603a120.44958 120.44958 0 0 0 98.467532
|
||||
53.298939 115.029349 115.029349 0 0 0 94.251797-53.901187 273.420548 273.420548 0 0 0 39.447238-161.703562 271.011556
|
||||
271.011556 0 0 0-39.748362-162.004685 120.44958 120.44958 0 0 0-98.467532-53.29894A114.125977 114.125977 0 0 0 722.697482
|
||||
333.322232a271.011556 271.011556 0 0 0-39.748361 161.703561zM1212.023903 776.275564L1070.194522 214.077147h80.701219l73.474244
|
||||
324.611619 27.101155 120.449581 24.391041-116.836093L1349.035301 214.077147h80.701218l68.656261 326.117239 23.186545 107.501251
|
||||
26.498907-108.705747L1626.069336 214.077147h76.184359l-143.335001 562.198417h-81.303466l-73.474244-336.656578-17.46519-95.757416L1294.832989
|
||||
776.275564zM1768.500964 776.275564V214.077147h70.463005v79.496723a180.674371 180.674371 0 0 1 62.031534-69.258509 154.476587
|
||||
154.476587 0 0 1 84.314706-22.88542 161.703562 161.703562 0 0 1 68.355137 14.45395 140.624885 140.624885 0 0 1 50.588824
|
||||
38.242742 153.874339 153.874339 0 0 1 30.112395 60.22479 509.802849 509.802849 0 0 1 9.635966
|
||||
115.330473v346.593668h-79.195599V433.897631a279.141903 279.141903 0 0 0-10.539338-90.337185 87.62707 87.62707 0 0
|
||||
0-85.218078-60.22479 109.00687 109.00687 0 0 0-90.337186 41.856229q-33.424759 42.157353-33.424758 143.636125v307.447554zM2270.775715
|
||||
776.275564V0.279142h84.314706v384.836409L2670.969446 0.279142h114.427101l-267.096945 314.674529 278.539655
|
||||
461.321893h-111.114738l-225.842963-391.461137-104.791135 123.46082v268.903689zM2853.149436 993.98818l-8.732595-90.337185a146.34624
|
||||
146.34624 0 0 0 44.566345 8.431471 78.292227 78.292227 0 0 0 41.253981-9.937091 76.786608 76.786608 0 0 0 26.498908-30.112395c2.710116-5.119107
|
||||
12.94833-36.134874 30.112395-93.348425L2812.196579 214.077147h84.314706l96.359664 325.514991c12.044958 40.350609
|
||||
22.88542 83.712458 33.123635 130.085547 9.033719-43.662973 19.573057-86.422574 31.919139-127.977679l98.467532-327.622859h78.292227l-174.953016
|
||||
572.135507a1012.679847 1012.679847 0 0 1-54.202311 147.550736 141.227133 141.227133 0 0 1-45.168592 53.600063 103.285515 103.285515 0 0
|
||||
1-56.912427 16.561818 132.494538 132.494538 0 0 1-50.2877-9.937091zM3300.318503 109.88826V0.279142h77.68998v109.609118z
|
||||
m0 666.387304V214.077147h77.68998v562.198417zM0 776.275564V0.279142h219.51936a417.357796 417.357796 0 0 1 124.063068
|
||||
14.152826 210.786766 210.786766 0 0 1 96.359664 67.752889 358.337502 358.337502 0 0 1 63.537154 124.364191 616.400728 616.400728 0 0 1
|
||||
22.584296 177.362008 579.663606 579.663606 0 0 1-38.543865 223.735095 273.420548 273.420548 0 0 1-99.370904 130.386671 294.1981
|
||||
294.1981 0 0 1-158.391198 38.242742zM463.730885 391.740278q10.840462-7.528099
|
||||
0-16.260693l-51.79332-30.112395q-136.40915-82.507963-276.431787-150.561976l-13.249454-6.624727a22.283172 22.283172
|
||||
0 0 0-16.561817 0v405.613962a18.669685 18.669685 0 0 0 14.755073-4.817983q148.152984-76.786608 296.607092-164.413677c15.357322-10.238214
|
||||
31.015767-21.379801 46.674213-32.822511z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
}
|
||||
|
||||
public VectorImage TextLogo { get; private set; }
|
||||
}
|
||||
}
|
29
src/DownKyi/Images/NavigationIcon.cs
Normal file
29
src/DownKyi/Images/NavigationIcon.cs
Normal file
@ -0,0 +1,29 @@
|
||||
namespace DownKyi.Images
|
||||
{
|
||||
public class NavigationIcon
|
||||
{
|
||||
private static NavigationIcon instance;
|
||||
public static NavigationIcon Instance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new NavigationIcon();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public NavigationIcon()
|
||||
{
|
||||
ArrowBack = new VectorImage
|
||||
{
|
||||
Height = 24,
|
||||
Width = 24,
|
||||
Data = @"M16.62 2.99c-.49-.49-1.28-.49-1.77 0L6.54 11.3c-.39.39-.39 1.02 0 1.41l8.31 8.31c.49.49 1.28.49 1.77
|
||||
0s.49-1.28 0-1.77L9.38 12l7.25-7.25c.48-.48.48-1.28-.01-1.76z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
}
|
||||
|
||||
public VectorImage ArrowBack { get; private set; }
|
||||
}
|
||||
}
|
68
src/DownKyi/Images/NormalIcon.cs
Normal file
68
src/DownKyi/Images/NormalIcon.cs
Normal file
@ -0,0 +1,68 @@
|
||||
namespace DownKyi.Images
|
||||
{
|
||||
public class NormalIcon
|
||||
{
|
||||
private static NormalIcon instance;
|
||||
public static NormalIcon Instance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new NormalIcon();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public NormalIcon()
|
||||
{
|
||||
CloudDownload = new VectorImage
|
||||
{
|
||||
Height = 32,
|
||||
Width = 48,
|
||||
Data = @"M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.3,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5
|
||||
C24,12.4,22,10.2,19.4,10z M19,18H6c-2.2,0-4-1.8-4-4c0-2.1,1.5-3.8,3.6-4l1.1-0.1L7.1,9C8.1,7.1,9.9,6,12,6c2.6,0,4.9,1.9,5.4,4.4
|
||||
l0.3,1.5l1.5,0.1c1.6,0.1,2.8,1.4,2.8,3C22,16.6,20.6,18,19,18z M13.4,10h-2.9v3H8l4,4l4-4h-2.6V10z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
|
||||
Folder = new VectorImage
|
||||
{
|
||||
Height = 32,
|
||||
Width = 40,
|
||||
Data = @"M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
|
||||
Downloading = new VectorImage
|
||||
{
|
||||
Height = 16,
|
||||
Width = 16,
|
||||
Data = @"M1,11.7c0.6,0,1,0.5,1,1V24H1.4C0.6,24,0,23.4,0,22.6c0,0,0,0,0,0v-9.9C0,12.1,0.5,11.7,1,11.7C1,11.7,1,11.7,1,11.7z
|
||||
M0,21.9h24v0.7c0,0.8-0.6,1.4-1.3,1.4H1.4C0.6,24,0,23.4,0,22.6V21.9z
|
||||
M23,11.7c0.6,0,1,0.5,1,1v9.9c0,0.8-0.6,1.4-1.3,1.4H22V12.7C22,12.1,22.5,11.7,23,11.7C23,11.7,23,11.7,23,11.7z M13,17.4
|
||||
h-2V1c0-0.6,0.4-1,1-1s1,0.5,1,1c0,0,0,0,0,0V17.4z
|
||||
M6.9,12.5c0.4-0.4,1-0.4,1.4,0l4.9,5.1L12.8,18c-0.5,0.5-1.4,0.5-1.9,0l-4-4.1C6.5,13.5,6.5,12.9,6.9,12.5L6.9,12.5z
|
||||
M16.8,12.5c0.4,0.4,0.4,1.1,0,1.5l-4,4.1c-0.5,0.5-1.4,0.5-1.9,0l-0.5-0.5l4.9-5.1C15.8,12.1,16.4,12.1,16.8,12.5L16.8,12.5z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
|
||||
DownloadFinished = new VectorImage
|
||||
{
|
||||
Height = 16,
|
||||
Width = 16,
|
||||
Data = @"M12,0C8.6,0.1,5.8,1.3,3.5,3.5S0.1,8.6,0,12c0.1,3.4,1.3,6.2,3.5,8.5S8.6,23.9,12,24c3.4-0.1,6.2-1.3,8.5-3.5
|
||||
s3.4-5.1,3.5-8.5c-0.1-3.4-1.3-6.2-3.5-8.5S15.4,0.1,12,0z M12,22.5c-3-0.1-5.5-1.1-7.4-3.1S1.6,15,1.5,12c0.1-3,1.1-5.5,3.1-7.4
|
||||
S9,1.6,12,1.5c3,0.1,5.5,1.1,7.4,3.1s3,4.4,3.1,7.4c-0.1,3-1.1,5.5-3.1,7.4S15,22.4,12,22.5z
|
||||
M16.5,8.1c0.2-0.2,0.4-0.2,0.6-0.2c0.5,0,0.9,0.4,0.9,0.9c0,0.2-0.1,0.5-0.2,0.6l-6.5,6.5
|
||||
c-0.2,0.2-0.4,0.3-0.6,0.3c-0.2,0-0.5-0.1-0.7-0.3l-3.8-3.7C6.1,12,6,11.7,6,11.5c0-0.2,0.1-0.5,0.3-0.6c0.2-0.2,0.4-0.3,0.6-0.3
|
||||
c0.2,0,0.5,0.1,0.6,0.2l3.1,3.1L16.5,8.1L16.5,8.1z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public VectorImage CloudDownload { get; private set; }
|
||||
public VectorImage Folder { get; private set; }
|
||||
public VectorImage Downloading { get; private set; }
|
||||
public VectorImage DownloadFinished { get; private set; }
|
||||
}
|
||||
}
|
76
src/DownKyi/Images/SystemIcon.cs
Normal file
76
src/DownKyi/Images/SystemIcon.cs
Normal file
@ -0,0 +1,76 @@
|
||||
namespace DownKyi.Images
|
||||
{
|
||||
public class SystemIcon
|
||||
{
|
||||
private static SystemIcon instance;
|
||||
public static SystemIcon Instance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new SystemIcon();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private SystemIcon()
|
||||
{
|
||||
Close = new VectorImage
|
||||
{
|
||||
Height = 12,
|
||||
Width = 12,
|
||||
Data = @"M25,23.9l-6.6-6.6c-0.3-0.3-0.9-0.3-1.1,0c-0.3,0.3-0.3,0.9,0,1.1l0,0l6.6,6.6l-6.6,6.6c-0.3,0.3-0.3,0.9,0,1.1
|
||||
c0.3,0.3,0.9,0.3,1.1,0l0,0l6.6-6.6l6.6,6.6c0.3,0.3,0.9,0.3,1.1,0.1c0.3-0.3,0.3-0.9,0.1-1.1c0,0,0,0-0.1-0.1L26.1,25l6.6-6.6
|
||||
c0.3-0.3,0.3-0.9,0-1.1c-0.3-0.3-0.9-0.3-1.1,0l0,0L25,23.9L25,23.9z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
|
||||
Maximize = new VectorImage
|
||||
{
|
||||
Height = 12,
|
||||
Width = 12,
|
||||
Data = @"M31.1,33H18.9c-1,0-1.9-0.9-1.9-1.9V18.9c0-1,0.9-1.9,1.9-1.9h12.3c1,0,1.9,0.9,1.9,1.9v12.3C33,32.1,32.1,33,31.1,33z
|
||||
M18.9,18.3c-0.3,0-0.6,0.3-0.6,0.6v12.3c0,0.3,0.3,0.6,0.6,0.6h12.3c0.3,0,0.6-0.3,0.6-0.6V18.9c0-0.3-0.3-0.6-0.6-0.6
|
||||
C31.1,18.3,18.9,18.3,18.9,18.3z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
|
||||
Minimize = new VectorImage
|
||||
{
|
||||
Height = 1.2,
|
||||
Width = 12,
|
||||
Data = @"M17.8,25.8c-0.5,0-0.8-0.3-0.8-0.8s0.3-0.8,0.8-0.8h14.4c0.5,0,0.8,0.3,0.8,0.8s-0.3,0.8-0.8,0.8H17.8z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
|
||||
Restore = new VectorImage
|
||||
{
|
||||
Height = 12,
|
||||
Width = 12,
|
||||
Data = @"M29,33H18.3c-0.7,0-1.3-0.6-1.3-1.3V21c0-0.7,0.6-1.3,1.3-1.3H29c0.7,0,1.3,0.6,1.3,1.3v10.7C30.4,32.4,29.8,33,29,33z
|
||||
M18.3,20.9c-0.1,0-0.1,0.1-0.1,0.1v10.7c0,0.1,0.1,0.1,0.1,0.1H29c0.1,0,0.1-0.1,0.1-0.1V21c0-0.1-0.1-0.1-0.1-0.1H18.3z
|
||||
M31.7,30.4h-1.9v-1.2h1.9c0.1,0,0.1-0.1,0.1-0.1V18.3c0-0.1-0.1-0.1-0.1-0.1H21c-0.1,0-0.1,0.1-0.1,0.1v1.9h-1.2v-1.9
|
||||
c0-0.7,0.6-1.3,1.3-1.3h10.7c0.7,0,1.3,0.6,1.3,1.3v10.7C33,29.8,32.4,30.4,31.7,30.4z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
|
||||
Skin = new VectorImage
|
||||
{
|
||||
Height = 12,
|
||||
Width = 12,
|
||||
Data = @"M29.1,18.1l2.7,3.2l-1.3,1.6c-0.1-0.1-0.3-0.1-0.5-0.1c-0.6,0-1,0.5-1,1.2v8.1h-8.2v-8.1c0-0.7-0.5-1.2-1-1.2
|
||||
c-0.1,0-0.3,0-0.5,0.1l-1.3-1.6l2.7-3.2h0.8c0.7,0.9,2.4,1.5,3.3,1.5c0.9,0,2.6-0.4,3.3-1.5H29.1 M29.2,17h-0.9
|
||||
c-0.2,0-0.5,0.1-0.7,0.4c-0.5,0.5-1.8,1.1-2.6,1.1c-0.8,0-2.2-0.5-2.6-1.2c-0.2-0.1-0.5-0.3-0.7-0.3h-0.9c-0.2,0-0.5,0.1-0.6,0.3
|
||||
l-3.1,3.6c-0.1,0.3-0.1,0.7,0,0.8l1.8,2.2C19,24,19.3,24,19.4,24s0.2,0,0.3-0.1v-0.1h0.1c0,0,0.1,0,0.1,0.1v8.2
|
||||
c0,0.5,0.3,0.9,0.8,0.9h8.6c0.5,0,0.8-0.4,0.8-0.9v-8.2c0-0.1,0-0.1,0.1-0.1h0.1l0.1,0.1c0.1,0.1,0.2,0.1,0.3,0.1s0.2,0,0.3-0.1
|
||||
l1.8-2.2c0-0.1,0-0.5-0.1-0.8l-3.1-3.6C29.7,17.1,29.5,17,29.2,17z",
|
||||
Fill = "#FF000000"
|
||||
};
|
||||
}
|
||||
|
||||
public VectorImage Close { get; private set; }
|
||||
public VectorImage Maximize { get; private set; }
|
||||
public VectorImage Minimize { get; private set; }
|
||||
public VectorImage Restore { get; private set; }
|
||||
public VectorImage Skin { get; private set; }
|
||||
}
|
||||
}
|
36
src/DownKyi/Images/VectorImage.cs
Normal file
36
src/DownKyi/Images/VectorImage.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using Prism.Mvvm;
|
||||
|
||||
namespace DownKyi.Images
|
||||
{
|
||||
public class VectorImage : BindableBase
|
||||
{
|
||||
private double width;
|
||||
public double Width
|
||||
{
|
||||
get { return width; }
|
||||
set { SetProperty(ref width, value); }
|
||||
}
|
||||
|
||||
private double height;
|
||||
public double Height
|
||||
{
|
||||
get { return height; }
|
||||
set { SetProperty(ref height, value); }
|
||||
}
|
||||
|
||||
private string data;
|
||||
public string Data
|
||||
{
|
||||
get { return data; }
|
||||
set { SetProperty(ref data, value); }
|
||||
}
|
||||
|
||||
private string fill;
|
||||
public string Fill
|
||||
{
|
||||
get { return fill; }
|
||||
set { SetProperty(ref fill, value); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
199
src/DownKyi/Languages/Default.xaml
Normal file
199
src/DownKyi/Languages/Default.xaml
Normal file
@ -0,0 +1,199 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Languages"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<!-- App -->
|
||||
<system:String x:Key="AppName">哔哩下载姬</system:String>
|
||||
<system:String x:Key="Unknown">未知</system:String>
|
||||
|
||||
<!-- 系统 -->
|
||||
<system:String x:Key="Close">关闭</system:String>
|
||||
<system:String x:Key="Maximize">最大化</system:String>
|
||||
<system:String x:Key="Minimize">最小化</system:String>
|
||||
<system:String x:Key="Restore">还原</system:String>
|
||||
<system:String x:Key="Skin">皮肤</system:String>
|
||||
|
||||
<!-- Index -->
|
||||
<system:String x:Key="Login">登录</system:String>
|
||||
<system:String x:Key="IndexHintText">请输入B站网址链接或av、BV号等……</system:String>
|
||||
<system:String x:Key="IndexHintTextSimple">请输入B站视频播放地址……</system:String>
|
||||
<system:String x:Key="Settings">设置</system:String>
|
||||
<system:String x:Key="DownloadManager">下载管理</system:String>
|
||||
<system:String x:Key="Toolbox">工具箱</system:String>
|
||||
|
||||
<!-- Login -->
|
||||
<system:String x:Key="ScanToLogin">扫描二维码登录</system:String>
|
||||
<system:String x:Key="ScanLoginTip" xml:space="preserve">请使用哔哩哔哩客户端
扫码登录
或扫码下载APP</system:String>
|
||||
<system:String x:Key="GetLoginUrlFailed">获取登录链接失败!</system:String>
|
||||
<system:String x:Key="LoginKeyError">密钥错误!尝试重新获取!</system:String>
|
||||
<system:String x:Key="LoginTimeOut">已超时!尝试重新获取二维码!</system:String>
|
||||
<system:String x:Key="LoginSuccessful">登录成功!(3秒后自动回到主页)</system:String>
|
||||
<system:String x:Key="LoginFailed">未保存登录信息!(3秒后自动回到主页)</system:String>
|
||||
|
||||
<!-- VideoDetail -->
|
||||
<system:String x:Key="CopyCover">复制封面图片</system:String>
|
||||
<system:String x:Key="CopyCoverUrl">复制封面URL</system:String>
|
||||
<system:String x:Key="Play">播放</system:String>
|
||||
<system:String x:Key="Danmaku">弹幕</system:String>
|
||||
<system:String x:Key="Like">点赞</system:String>
|
||||
<system:String x:Key="Coin">投币</system:String>
|
||||
<system:String x:Key="Favorite">收藏</system:String>
|
||||
<system:String x:Key="Share">分享</system:String>
|
||||
<system:String x:Key="Reply">评论</system:String>
|
||||
|
||||
<system:String x:Key="Anime">番剧</system:String>
|
||||
<system:String x:Key="Movie">电影</system:String>
|
||||
<system:String x:Key="Documentary">纪录片</system:String>
|
||||
<system:String x:Key="Guochuang">国创</system:String>
|
||||
<system:String x:Key="TV">电视剧</system:String>
|
||||
<system:String x:Key="Entertainment">综艺</system:String>
|
||||
<system:String x:Key="Cheese">课程</system:String>
|
||||
|
||||
<system:String x:Key="Order">序号</system:String>
|
||||
<system:String x:Key="Name">名称</system:String>
|
||||
<system:String x:Key="Duration">时长</system:String>
|
||||
<system:String x:Key="AudioQuality">音质</system:String>
|
||||
<system:String x:Key="VideoQuality">画质</system:String>
|
||||
<system:String x:Key="VideoCodec">视频编码</system:String>
|
||||
|
||||
<system:String x:Key="SelectAll">全选</system:String>
|
||||
<system:String x:Key="Parse">解析</system:String>
|
||||
<system:String x:Key="ParseVideo">解析视频</system:String>
|
||||
<system:String x:Key="DownloadSelected">下载选中项</system:String>
|
||||
|
||||
<!-- DownloadManager -->
|
||||
<system:String x:Key="Downloading">正在下载</system:String>
|
||||
<system:String x:Key="DownloadFinished">已下载</system:String>
|
||||
|
||||
<!-- Settings -->
|
||||
<system:String x:Key="PressEnterToApplySettingTip">按回车键应用设置</system:String>
|
||||
|
||||
<system:String x:Key="Basic">基本</system:String>
|
||||
<system:String x:Key="AfterDownloadOperation">下载完成后的动作:</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationNone">无</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationCloseApp">关闭程序</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationCloseSystem">关闭计算机</system:String>
|
||||
<system:String x:Key="ListenClipboard">监听剪贴板</system:String>
|
||||
<system:String x:Key="VideoAutoParse">视频自动解析</system:String>
|
||||
<system:String x:Key="VideoParseScope">视频解析范围:</system:String>
|
||||
|
||||
<system:String x:Key="Network">网络</system:String>
|
||||
<system:String x:Key="AriaServerPort">Aria服务器端口:</system:String>
|
||||
<system:String x:Key="AriaLogLevel">Aria日志等级:</system:String>
|
||||
<system:String x:Key="AriaMaxConcurrentDownloads">Aria同时下载数:</system:String>
|
||||
<system:String x:Key="AriaSplit">Aria最大线程数:</system:String>
|
||||
<system:String x:Key="AriaDownloadLimit">Aria下载速度限制(KB/s)</system:String>
|
||||
<system:String x:Key="AriaMaxOverallDownloadLimit">全局下载速度限制[0: 无限制]</system:String>
|
||||
<system:String x:Key="AriaMaxDownloadLimit">单任务下载速度限制[0: 无限制]</system:String>
|
||||
<system:String x:Key="IsAriaHttpProxy">使用Http代理</system:String>
|
||||
<system:String x:Key="AriaHttpProxy">代理地址:</system:String>
|
||||
<system:String x:Key="AriaHttpProxyPort">端口:</system:String>
|
||||
<system:String x:Key="AriaFileAllocation">Aria文件预分配:</system:String>
|
||||
|
||||
<system:String x:Key="Video">视频</system:String>
|
||||
<system:String x:Key="FirstVideoCodecs">优先下载的视频编码:</system:String>
|
||||
<system:String x:Key="FirstVideoQuality">优先下载的视频画质:</system:String>
|
||||
<system:String x:Key="IsAddVideoOrder">启用视频编号</system:String>
|
||||
<system:String x:Key="IsAddVideoOrderTip">勾选后,将为下载完成的视频的文件名添加上序号</system:String>
|
||||
<system:String x:Key="IsTranscodingFlvToMp4">下载FLV视频后转码为mp4</system:String>
|
||||
<system:String x:Key="IsUseDefaultDirectory">使用默认下载目录</system:String>
|
||||
<system:String x:Key="DefaultDirectory">默认下载目录:</system:String>
|
||||
<system:String x:Key="DefaultDirectoryTip">默认将文件下载到该文件夹中</system:String>
|
||||
<system:String x:Key="ChangeDirectory">更改目录</system:String>
|
||||
<system:String x:Key="IsCreateFolderForMedia">为不同视频分别创建文件夹</system:String>
|
||||
<system:String x:Key="IsDownloadDanmaku">在下载视频的同时下载弹幕</system:String>
|
||||
<system:String x:Key="IsDownloadCover">在下载视频的同时下载封面</system:String>
|
||||
|
||||
<system:String x:Key="SettingDanmaku">弹幕</system:String>
|
||||
<system:String x:Key="FilterType">按类型屏蔽</system:String>
|
||||
<system:String x:Key="TopFilter">顶部</system:String>
|
||||
<system:String x:Key="BottomFilter">底部</system:String>
|
||||
<system:String x:Key="ScrollFilter">滚动</system:String>
|
||||
<system:String x:Key="Resolution">分辨率:</system:String>
|
||||
<system:String x:Key="FontName">字体名称:</system:String>
|
||||
<system:String x:Key="FontSize">字体大小:</system:String>
|
||||
<system:String x:Key="LineCount">限制行数:</system:String>
|
||||
<system:String x:Key="LayoutAlgorithm">布局算法:</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmSync">速度同步</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmSyncTip">每一条滚动弹幕的移动速度都是相同的</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmAsync">速度异步</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmAsyncTip">弹幕滚动速度取决于它的文本长度</system:String>
|
||||
|
||||
<system:String x:Key="About">关于</system:String>
|
||||
<system:String x:Key="GotoHomepage">访问主页</system:String>
|
||||
<system:String x:Key="CurrentAppVersion">当前版本:</system:String>
|
||||
<system:String x:Key="CheckUpdate">检查更新</system:String>
|
||||
<system:String x:Key="Feedback">意见反馈</system:String>
|
||||
<system:String x:Key="ReceiveBetaVersion">接收测试版更新</system:String>
|
||||
<system:String x:Key="AutoUpdateWhenLaunch">启动时检查更新</system:String>
|
||||
<system:String x:Key="TipSettingUpdated">设置已更新~</system:String>
|
||||
<system:String x:Key="TipSettingFailed">设置失败!</system:String>
|
||||
<system:String x:Key="ThirdParty">第三方</system:String>
|
||||
<system:String x:Key="ThirdPartyName">名称</system:String>
|
||||
<system:String x:Key="ThirdPartyAuthor">作者</system:String>
|
||||
<system:String x:Key="ThirdPartyVersion">版本</system:String>
|
||||
<system:String x:Key="ThirdPartyLicense">许可证</system:String>
|
||||
<system:String x:Key="Disclaimer">免责申明</system:String>
|
||||
<system:String x:Key="Disclaimer1">1. 本软件只提供视频解析,不提供任何资源上传、存储到服务器的功能。</system:String>
|
||||
<system:String x:Key="Disclaimer2">2. 本软件仅解析来自B站的内容,不会对解析到的音视频进行二次编码,部分视频会进行有限的格式转换、拼接等操作。</system:String>
|
||||
<system:String x:Key="Disclaimer3">3. 本软件解析得到的所有内容均来自B站UP主上传、分享,其版权均归原作者所有。内容提供者、上传者(UP主)应对其提供、上传的内容承担全部责任。</system:String>
|
||||
<system:String x:Key="Disclaimer4">4. 本软件提供的所有资源,仅可用作学习交流使用,未经原作者授权,禁止用于其他用途。请在下载24小时内删除。为尊重作者版权,请前往资源的原始发布网站观看,支持原创,谢谢。</system:String>
|
||||
<system:String x:Key="Disclaimer5">5. 任何涉及商业盈利目的均不得使用,否则产生的一切后果将由您自己承担。</system:String>
|
||||
<system:String x:Key="Disclaimer6">6. 因使用本软件产生的版权问题,软件作者概不负责。</system:String>
|
||||
|
||||
<!-- Toolbox -->
|
||||
<system:String x:Key="BiliHelper">B站助手</system:String>
|
||||
<system:String x:Key="AvidAndBvidConversion">AV和BV互转</system:String>
|
||||
<system:String x:Key="AvidAndBvidConversionTip">AV号形如"av123",BV号形如"BVxxx"。</system:String>
|
||||
<system:String x:Key="Avid">AVID:</system:String>
|
||||
<system:String x:Key="Bvid">BVID:</system:String>
|
||||
<system:String x:Key="GotoWeb">访问网页</system:String>
|
||||
<system:String x:Key="DanmakuUserID">弹幕中的userID:</system:String>
|
||||
<system:String x:Key="FindDanmakuSender">查询弹幕发送者-></system:String>
|
||||
|
||||
<system:String x:Key="Delogo">去水印</system:String>
|
||||
<system:String x:Key="VideoFilePath">视频地址:</system:String>
|
||||
<system:String x:Key="SelectVideo">选择视频</system:String>
|
||||
<system:String x:Key="LogoSizeAndLocation">水印尺寸与位置(左上角为原点,单位:像素)</system:String>
|
||||
<system:String x:Key="LogoWidth">宽:</system:String>
|
||||
<system:String x:Key="LogoHeight">高:</system:String>
|
||||
<system:String x:Key="LogoX">X:</system:String>
|
||||
<system:String x:Key="LogoY">Y:</system:String>
|
||||
<system:String x:Key="TipWaitTaskFinished">请等待当前任务完成!</system:String>
|
||||
<system:String x:Key="TipNoSeletedVideo">没有选择视频!</system:String>
|
||||
<system:String x:Key="TipInputRightLogoWidth">请输入正确的宽度(正整数)!</system:String>
|
||||
<system:String x:Key="TipInputRightLogoHeight">请输入正确的高度(正整数)!</system:String>
|
||||
<system:String x:Key="TipInputRightLogoX">请输入正确的X(正整数)!</system:String>
|
||||
<system:String x:Key="TipInputRightLogoY">请输入正确的Y(正整数)!</system:String>
|
||||
<system:String x:Key="OutputInfo">输出信息:</system:String>
|
||||
|
||||
<system:String x:Key="ExtractMedia">音视频分离</system:String>
|
||||
<system:String x:Key="ExtractAudio">提取音频</system:String>
|
||||
<system:String x:Key="ExtractVideo">提取视频</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>
|
||||
<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="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 -->
|
||||
<system:String x:Key="ParsingSelector">选择解析项</system:String>
|
||||
<system:String x:Key="ParseNone">无</system:String>
|
||||
<system:String x:Key="ParseSelectedItem">解析选中项</system:String>
|
||||
<system:String x:Key="ParseCurrentSection">解析当前页视频</system:String>
|
||||
<system:String x:Key="ParseAll">解析所有视频</system:String>
|
||||
<system:String x:Key="SetParseDefault">设为默认,下次不再弹出</system:String>
|
||||
|
||||
</ResourceDictionary>
|
173
src/DownKyi/Languages/en_US.xaml
Normal file
173
src/DownKyi/Languages/en_US.xaml
Normal file
@ -0,0 +1,173 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Languages"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<!-- App -->
|
||||
<system:String x:Key="AppName">DownKyi</system:String>
|
||||
<system:String x:Key="Unknown">Unknown</system:String>
|
||||
|
||||
<!-- 系统 -->
|
||||
<system:String x:Key="Close">Close</system:String>
|
||||
<system:String x:Key="Maximize">Maximize</system:String>
|
||||
<system:String x:Key="Minimize">Minimize</system:String>
|
||||
<system:String x:Key="Restore">Restore</system:String>
|
||||
<system:String x:Key="Skin">Skin</system:String>
|
||||
|
||||
<!-- Index -->
|
||||
<system:String x:Key="Login">Login</system:String>
|
||||
<system:String x:Key="IndexHintText">Please input the Bilibili url, av id, and BV id etc.</system:String>
|
||||
<system:String x:Key="Settings">Settings</system:String>
|
||||
<system:String x:Key="DownloadManager">Download Manager</system:String>
|
||||
<system:String x:Key="Toolbox">Toolbox</system:String>
|
||||
|
||||
<!-- Login -->
|
||||
<system:String x:Key="ScanToLogin">Scan to Login</system:String>
|
||||
<system:String x:Key="ScanLoginTip" xml:space="preserve">请使用哔哩哔哩客户端
扫码登录
或扫码下载APP</system:String>
|
||||
<system:String x:Key="GetLoginUrlFailed">获取登录链接失败!</system:String>
|
||||
<system:String x:Key="LoginKeyError">密钥错误!尝试重新获取!</system:String>
|
||||
<system:String x:Key="LoginTimeOut">已超时!尝试重新获取二维码!</system:String>
|
||||
<system:String x:Key="LoginSuccessful">登录成功!(3秒后自动回到主页)</system:String>
|
||||
<system:String x:Key="LoginFailed">未保存登录信息!(3秒后自动回到主页)</system:String>
|
||||
|
||||
<!-- VideoDetail -->
|
||||
<system:String x:Key="CopyCover">复制封面图片</system:String>
|
||||
<system:String x:Key="CopyCoverUrl">复制封面URL</system:String>
|
||||
<system:String x:Key="Play">播放</system:String>
|
||||
<system:String x:Key="Danmaku">弹幕</system:String>
|
||||
<system:String x:Key="Like">点赞</system:String>
|
||||
<system:String x:Key="Coin">投币</system:String>
|
||||
<system:String x:Key="Favorite">收藏</system:String>
|
||||
<system:String x:Key="Share">分享</system:String>
|
||||
<system:String x:Key="Reply">评论</system:String>
|
||||
|
||||
<system:String x:Key="Anime">番剧</system:String>
|
||||
<system:String x:Key="Movie">电影</system:String>
|
||||
<system:String x:Key="Documentary">纪录片</system:String>
|
||||
<system:String x:Key="Guochuang">国创</system:String>
|
||||
<system:String x:Key="TV">电视剧</system:String>
|
||||
<system:String x:Key="Entertainment">综艺</system:String>
|
||||
<system:String x:Key="Cheese">课程</system:String>
|
||||
|
||||
<system:String x:Key="Order">序号</system:String>
|
||||
<system:String x:Key="Name">名称</system:String>
|
||||
<system:String x:Key="Duration">时长</system:String>
|
||||
<system:String x:Key="AudioQuality">音质</system:String>
|
||||
<system:String x:Key="VideoQuality">画质</system:String>
|
||||
<system:String x:Key="VideoCodec">视频编码</system:String>
|
||||
|
||||
<system:String x:Key="SelectAll">全选</system:String>
|
||||
<system:String x:Key="Parse">解析</system:String>
|
||||
<system:String x:Key="ParseVideo">解析视频</system:String>
|
||||
<system:String x:Key="DownloadSelected">下载选中项</system:String>
|
||||
|
||||
<!-- DownloadManager -->
|
||||
<system:String x:Key="Downloading">正在下载</system:String>
|
||||
<system:String x:Key="DownloadFinished">已下载</system:String>
|
||||
|
||||
<!-- Settings -->
|
||||
<system:String x:Key="PressEnterToApplySettingTip">按回车键应用设置</system:String>
|
||||
|
||||
<system:String x:Key="Basic">基本</system:String>
|
||||
<system:String x:Key="AfterDownloadOperation">下载完成后的动作:</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationNone">无</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationCloseApp">关闭程序</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationCloseSystem">关闭计算机</system:String>
|
||||
<system:String x:Key="ListenClipboard">监听剪贴板</system:String>
|
||||
<system:String x:Key="VideoAutoParse">视频自动解析</system:String>
|
||||
<system:String x:Key="VideoParseScope">视频解析范围:</system:String>
|
||||
|
||||
<system:String x:Key="Network">网络</system:String>
|
||||
<system:String x:Key="AriaServerPort">Aria服务器端口:</system:String>
|
||||
<system:String x:Key="AriaLogLevel">Aria日志等级:</system:String>
|
||||
<system:String x:Key="AriaMaxConcurrentDownloads">Aria同时下载数:</system:String>
|
||||
<system:String x:Key="AriaSplit">Aria最大线程数:</system:String>
|
||||
<system:String x:Key="AriaDownloadLimit">Aria下载速度限制(KB/s)</system:String>
|
||||
<system:String x:Key="AriaMaxOverallDownloadLimit">全局下载速度限制[0: 无限制]</system:String>
|
||||
<system:String x:Key="AriaMaxDownloadLimit">单任务下载速度限制[0: 无限制]</system:String>
|
||||
<system:String x:Key="IsAriaHttpProxy">使用Http代理</system:String>
|
||||
<system:String x:Key="AriaHttpProxy">代理地址:</system:String>
|
||||
<system:String x:Key="AriaHttpProxyPort">端口:</system:String>
|
||||
<system:String x:Key="AriaFileAllocation">Aria文件预分配:</system:String>
|
||||
|
||||
<system:String x:Key="Video">视频</system:String>
|
||||
<system:String x:Key="FirstVideoCodecs">优先下载的视频编码:</system:String>
|
||||
<system:String x:Key="FirstVideoQuality">优先下载的视频画质:</system:String>
|
||||
<system:String x:Key="IsAddVideoOrder">启用视频编号</system:String>
|
||||
<system:String x:Key="IsAddVideoOrderTip">勾选后,将为下载完成的视频的文件名添加上序号</system:String>
|
||||
<system:String x:Key="IsTranscodingFlvToMp4">下载FLV视频后转码为mp4</system:String>
|
||||
<system:String x:Key="IsUseDefaultDirectory">使用默认下载目录</system:String>
|
||||
<system:String x:Key="DefaultDirectory">默认下载目录:</system:String>
|
||||
<system:String x:Key="DefaultDirectoryTip">默认将文件下载到该文件夹中</system:String>
|
||||
<system:String x:Key="ChangeDirectory">更改目录</system:String>
|
||||
<system:String x:Key="IsCreateFolderForMedia">为不同视频分别创建文件夹</system:String>
|
||||
<system:String x:Key="IsDownloadDanmaku">在下载视频的同时下载弹幕</system:String>
|
||||
<system:String x:Key="IsDownloadCover">在下载视频的同时下载封面</system:String>
|
||||
|
||||
<system:String x:Key="SettingDanmaku">弹幕</system:String>
|
||||
<system:String x:Key="FilterType">按类型屏蔽</system:String>
|
||||
<system:String x:Key="TopFilter">顶部</system:String>
|
||||
<system:String x:Key="BottomFilter">底部</system:String>
|
||||
<system:String x:Key="ScrollFilter">滚动</system:String>
|
||||
<system:String x:Key="Resolution">分辨率:</system:String>
|
||||
<system:String x:Key="FontName">字体名称:</system:String>
|
||||
<system:String x:Key="FontSize">字体大小:</system:String>
|
||||
<system:String x:Key="LineCount">限制行数:</system:String>
|
||||
<system:String x:Key="LayoutAlgorithm">布局算法:</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmSync">速度同步</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmSyncTip">每一条滚动弹幕的移动速度都是相同的</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmAsync">速度异步</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmAsyncTip">弹幕滚动速度取决于它的文本长度</system:String>
|
||||
|
||||
<system:String x:Key="About">关于</system:String>
|
||||
<system:String x:Key="GotoHomepage">访问主页</system:String>
|
||||
<system:String x:Key="CurrentAppVersion">当前版本:</system:String>
|
||||
<system:String x:Key="CheckUpdate">检查更新</system:String>
|
||||
<system:String x:Key="Feedback">意见反馈</system:String>
|
||||
<system:String x:Key="ReceiveBetaVersion">接收测试版更新</system:String>
|
||||
<system:String x:Key="AutoUpdateWhenLaunch">启动时检查更新</system:String>
|
||||
<system:String x:Key="TipSettingUpdated">设置已更新~</system:String>
|
||||
<system:String x:Key="TipSettingFailed">设置失败!</system:String>
|
||||
<system:String x:Key="ThirdParty">第三方</system:String>
|
||||
<system:String x:Key="ThirdPartyName">名称</system:String>
|
||||
<system:String x:Key="ThirdPartyAuthor">作者</system:String>
|
||||
<system:String x:Key="ThirdPartyVersion">版本</system:String>
|
||||
<system:String x:Key="ThirdPartyLicense">许可证</system:String>
|
||||
<system:String x:Key="Disclaimer">免责申明</system:String>
|
||||
<system:String x:Key="Disclaimer1">1. 本软件只提供视频解析,不提供任何资源上传、存储到服务器的功能。</system:String>
|
||||
<system:String x:Key="Disclaimer2">2. 本软件仅解析来自B站的内容,不会对解析到的音视频进行二次编码,部分视频会进行有限的格式转换、拼接等操作。</system:String>
|
||||
<system:String x:Key="Disclaimer3">3. 本软件解析得到的所有内容均来自B站UP主上传、分享,其版权均归原作者所有。内容提供者、上传者(UP主)应对其提供、上传的内容承担全部责任。</system:String>
|
||||
<system:String x:Key="Disclaimer4">4. 本软件提供的所有资源,仅可用作学习交流使用,未经原作者授权,禁止用于其他用途。请在下载24小时内删除。为尊重作者版权,请前往资源的原始发布网站观看,支持原创,谢谢。</system:String>
|
||||
<system:String x:Key="Disclaimer5">5. 任何涉及商业盈利目的均不得使用,否则产生的一切后果将由您自己承担。</system:String>
|
||||
<system:String x:Key="Disclaimer6">6. 因使用本软件产生的版权问题,软件作者概不负责。</system:String>
|
||||
|
||||
<!-- Tools -->
|
||||
<system:String x:Key="BiliHelper">B站助手</system:String>
|
||||
<system:String x:Key="Delogo">去水印</system:String>
|
||||
<system:String x:Key="ExtractMedia">音视频分离</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>
|
||||
<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="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 -->
|
||||
<system:String x:Key="ParsingSelector">选择解析项</system:String>
|
||||
<system:String x:Key="ParseNone">无</system:String>
|
||||
<system:String x:Key="ParseSelectedItem">解析选中项</system:String>
|
||||
<system:String x:Key="ParseCurrentSection">解析当前页视频</system:String>
|
||||
<system:String x:Key="ParseAll">解析所有视频</system:String>
|
||||
<system:String x:Key="SetParseDefault">设为默认,下次不再弹出</system:String>
|
||||
|
||||
</ResourceDictionary>
|
174
src/DownKyi/Languages/zh_CN.xaml
Normal file
174
src/DownKyi/Languages/zh_CN.xaml
Normal file
@ -0,0 +1,174 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Languages"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<!-- App -->
|
||||
<system:String x:Key="AppName">哔哩下载姬</system:String>
|
||||
<system:String x:Key="Unknown">未知</system:String>
|
||||
|
||||
<!-- 系统 -->
|
||||
<system:String x:Key="Close">关闭</system:String>
|
||||
<system:String x:Key="Maximize">最大化</system:String>
|
||||
<system:String x:Key="Minimize">最小化</system:String>
|
||||
<system:String x:Key="Restore">还原</system:String>
|
||||
<system:String x:Key="Skin">皮肤</system:String>
|
||||
|
||||
<!-- Index -->
|
||||
<system:String x:Key="Login">登录</system:String>
|
||||
<system:String x:Key="IndexHintText">请输入B站网址链接或av、BV号等……</system:String>
|
||||
<system:String x:Key="IndexHintTextSimple">请输入B站视频播放地址……</system:String>
|
||||
<system:String x:Key="Settings">设置</system:String>
|
||||
<system:String x:Key="DownloadManager">下载管理</system:String>
|
||||
<system:String x:Key="Toolbox">工具箱</system:String>
|
||||
|
||||
<!-- Login -->
|
||||
<system:String x:Key="ScanToLogin">扫描二维码登录</system:String>
|
||||
<system:String x:Key="ScanLoginTip" xml:space="preserve">请使用哔哩哔哩客户端
扫码登录
或扫码下载APP</system:String>
|
||||
<system:String x:Key="GetLoginUrlFailed">获取登录链接失败!</system:String>
|
||||
<system:String x:Key="LoginKeyError">密钥错误!尝试重新获取!</system:String>
|
||||
<system:String x:Key="LoginTimeOut">已超时!尝试重新获取二维码!</system:String>
|
||||
<system:String x:Key="LoginSuccessful">登录成功!(3秒后自动回到主页)</system:String>
|
||||
<system:String x:Key="LoginFailed">未保存登录信息!(3秒后自动回到主页)</system:String>
|
||||
|
||||
<!-- VideoDetail -->
|
||||
<system:String x:Key="CopyCover">复制封面图片</system:String>
|
||||
<system:String x:Key="CopyCoverUrl">复制封面URL</system:String>
|
||||
<system:String x:Key="Play">播放</system:String>
|
||||
<system:String x:Key="Danmaku">弹幕</system:String>
|
||||
<system:String x:Key="Like">点赞</system:String>
|
||||
<system:String x:Key="Coin">投币</system:String>
|
||||
<system:String x:Key="Favorite">收藏</system:String>
|
||||
<system:String x:Key="Share">分享</system:String>
|
||||
<system:String x:Key="Reply">评论</system:String>
|
||||
|
||||
<system:String x:Key="Anime">番剧</system:String>
|
||||
<system:String x:Key="Movie">电影</system:String>
|
||||
<system:String x:Key="Documentary">纪录片</system:String>
|
||||
<system:String x:Key="Guochuang">国创</system:String>
|
||||
<system:String x:Key="TV">电视剧</system:String>
|
||||
<system:String x:Key="Entertainment">综艺</system:String>
|
||||
<system:String x:Key="Cheese">课程</system:String>
|
||||
|
||||
<system:String x:Key="Order">序号</system:String>
|
||||
<system:String x:Key="Name">名称</system:String>
|
||||
<system:String x:Key="Duration">时长</system:String>
|
||||
<system:String x:Key="AudioQuality">音质</system:String>
|
||||
<system:String x:Key="VideoQuality">画质</system:String>
|
||||
<system:String x:Key="VideoCodec">视频编码</system:String>
|
||||
|
||||
<system:String x:Key="SelectAll">全选</system:String>
|
||||
<system:String x:Key="Parse">解析</system:String>
|
||||
<system:String x:Key="ParseVideo">解析视频</system:String>
|
||||
<system:String x:Key="DownloadSelected">下载选中项</system:String>
|
||||
|
||||
<!-- DownloadManager -->
|
||||
<system:String x:Key="Downloading">正在下载</system:String>
|
||||
<system:String x:Key="DownloadFinished">已下载</system:String>
|
||||
|
||||
<!-- Settings -->
|
||||
<system:String x:Key="PressEnterToApplySettingTip">按回车键应用设置</system:String>
|
||||
|
||||
<system:String x:Key="Basic">基本</system:String>
|
||||
<system:String x:Key="AfterDownloadOperation">下载完成后的动作:</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationNone">无</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationCloseApp">关闭程序</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationCloseSystem">关闭计算机</system:String>
|
||||
<system:String x:Key="ListenClipboard">监听剪贴板</system:String>
|
||||
<system:String x:Key="VideoAutoParse">视频自动解析</system:String>
|
||||
<system:String x:Key="VideoParseScope">视频解析范围:</system:String>
|
||||
|
||||
<system:String x:Key="Network">网络</system:String>
|
||||
<system:String x:Key="AriaServerPort">Aria服务器端口:</system:String>
|
||||
<system:String x:Key="AriaLogLevel">Aria日志等级:</system:String>
|
||||
<system:String x:Key="AriaMaxConcurrentDownloads">Aria同时下载数:</system:String>
|
||||
<system:String x:Key="AriaSplit">Aria最大线程数:</system:String>
|
||||
<system:String x:Key="AriaDownloadLimit">Aria下载速度限制(KB/s)</system:String>
|
||||
<system:String x:Key="AriaMaxOverallDownloadLimit">全局下载速度限制[0: 无限制]</system:String>
|
||||
<system:String x:Key="AriaMaxDownloadLimit">单任务下载速度限制[0: 无限制]</system:String>
|
||||
<system:String x:Key="IsAriaHttpProxy">使用Http代理</system:String>
|
||||
<system:String x:Key="AriaHttpProxy">代理地址:</system:String>
|
||||
<system:String x:Key="AriaHttpProxyPort">端口:</system:String>
|
||||
<system:String x:Key="AriaFileAllocation">Aria文件预分配:</system:String>
|
||||
|
||||
<system:String x:Key="Video">视频</system:String>
|
||||
<system:String x:Key="FirstVideoCodecs">优先下载的视频编码:</system:String>
|
||||
<system:String x:Key="FirstVideoQuality">优先下载的视频画质:</system:String>
|
||||
<system:String x:Key="IsAddVideoOrder">启用视频编号</system:String>
|
||||
<system:String x:Key="IsAddVideoOrderTip">勾选后,将为下载完成的视频的文件名添加上序号</system:String>
|
||||
<system:String x:Key="IsTranscodingFlvToMp4">下载FLV视频后转码为mp4</system:String>
|
||||
<system:String x:Key="IsUseDefaultDirectory">使用默认下载目录</system:String>
|
||||
<system:String x:Key="DefaultDirectory">默认下载目录:</system:String>
|
||||
<system:String x:Key="DefaultDirectoryTip">默认将文件下载到该文件夹中</system:String>
|
||||
<system:String x:Key="ChangeDirectory">更改目录</system:String>
|
||||
<system:String x:Key="IsCreateFolderForMedia">为不同视频分别创建文件夹</system:String>
|
||||
<system:String x:Key="IsDownloadDanmaku">在下载视频的同时下载弹幕</system:String>
|
||||
<system:String x:Key="IsDownloadCover">在下载视频的同时下载封面</system:String>
|
||||
|
||||
<system:String x:Key="SettingDanmaku">弹幕</system:String>
|
||||
<system:String x:Key="FilterType">按类型屏蔽</system:String>
|
||||
<system:String x:Key="TopFilter">顶部</system:String>
|
||||
<system:String x:Key="BottomFilter">底部</system:String>
|
||||
<system:String x:Key="ScrollFilter">滚动</system:String>
|
||||
<system:String x:Key="Resolution">分辨率:</system:String>
|
||||
<system:String x:Key="FontName">字体名称:</system:String>
|
||||
<system:String x:Key="FontSize">字体大小:</system:String>
|
||||
<system:String x:Key="LineCount">限制行数:</system:String>
|
||||
<system:String x:Key="LayoutAlgorithm">布局算法:</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmSync">速度同步</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmSyncTip">每一条滚动弹幕的移动速度都是相同的</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmAsync">速度异步</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmAsyncTip">弹幕滚动速度取决于它的文本长度</system:String>
|
||||
|
||||
<system:String x:Key="About">关于</system:String>
|
||||
<system:String x:Key="GotoHomepage">访问主页</system:String>
|
||||
<system:String x:Key="CurrentAppVersion">当前版本:</system:String>
|
||||
<system:String x:Key="CheckUpdate">检查更新</system:String>
|
||||
<system:String x:Key="Feedback">意见反馈</system:String>
|
||||
<system:String x:Key="ReceiveBetaVersion">接收测试版更新</system:String>
|
||||
<system:String x:Key="AutoUpdateWhenLaunch">启动时检查更新</system:String>
|
||||
<system:String x:Key="TipSettingUpdated">设置已更新~</system:String>
|
||||
<system:String x:Key="TipSettingFailed">设置失败!</system:String>
|
||||
<system:String x:Key="ThirdParty">第三方</system:String>
|
||||
<system:String x:Key="ThirdPartyName">名称</system:String>
|
||||
<system:String x:Key="ThirdPartyAuthor">作者</system:String>
|
||||
<system:String x:Key="ThirdPartyVersion">版本</system:String>
|
||||
<system:String x:Key="ThirdPartyLicense">许可证</system:String>
|
||||
<system:String x:Key="Disclaimer">免责申明</system:String>
|
||||
<system:String x:Key="Disclaimer1">1. 本软件只提供视频解析,不提供任何资源上传、存储到服务器的功能。</system:String>
|
||||
<system:String x:Key="Disclaimer2">2. 本软件仅解析来自B站的内容,不会对解析到的音视频进行二次编码,部分视频会进行有限的格式转换、拼接等操作。</system:String>
|
||||
<system:String x:Key="Disclaimer3">3. 本软件解析得到的所有内容均来自B站UP主上传、分享,其版权均归原作者所有。内容提供者、上传者(UP主)应对其提供、上传的内容承担全部责任。</system:String>
|
||||
<system:String x:Key="Disclaimer4">4. 本软件提供的所有资源,仅可用作学习交流使用,未经原作者授权,禁止用于其他用途。请在下载24小时内删除。为尊重作者版权,请前往资源的原始发布网站观看,支持原创,谢谢。</system:String>
|
||||
<system:String x:Key="Disclaimer5">5. 任何涉及商业盈利目的均不得使用,否则产生的一切后果将由您自己承担。</system:String>
|
||||
<system:String x:Key="Disclaimer6">6. 因使用本软件产生的版权问题,软件作者概不负责。</system:String>
|
||||
|
||||
<!-- Tools -->
|
||||
<system:String x:Key="BiliHelper">B站助手</system:String>
|
||||
<system:String x:Key="Delogo">去水印</system:String>
|
||||
<system:String x:Key="ExtractMedia">音视频分离</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>
|
||||
<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="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 -->
|
||||
<system:String x:Key="ParsingSelector">选择解析项</system:String>
|
||||
<system:String x:Key="ParseNone">无</system:String>
|
||||
<system:String x:Key="ParseSelectedItem">解析选中项</system:String>
|
||||
<system:String x:Key="ParseCurrentSection">解析当前页视频</system:String>
|
||||
<system:String x:Key="ParseAll">解析所有视频</system:String>
|
||||
<system:String x:Key="SetParseDefault">设为默认,下次不再弹出</system:String>
|
||||
|
||||
</ResourceDictionary>
|
174
src/DownKyi/Languages/zh_TW.xaml
Normal file
174
src/DownKyi/Languages/zh_TW.xaml
Normal file
@ -0,0 +1,174 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Languages"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<!-- App -->
|
||||
<system:String x:Key="AppName">哔哩下载姬</system:String>
|
||||
<system:String x:Key="Unknown">未知</system:String>
|
||||
|
||||
<!-- 系统 -->
|
||||
<system:String x:Key="Close">关闭</system:String>
|
||||
<system:String x:Key="Maximize">最大化</system:String>
|
||||
<system:String x:Key="Minimize">最小化</system:String>
|
||||
<system:String x:Key="Restore">还原</system:String>
|
||||
<system:String x:Key="Skin">皮肤</system:String>
|
||||
|
||||
<!-- Index -->
|
||||
<system:String x:Key="Login">登录</system:String>
|
||||
<system:String x:Key="IndexHintText">请输入B站网址链接或av、BV号等……</system:String>
|
||||
<system:String x:Key="IndexHintTextSimple">请输入B站视频播放地址……</system:String>
|
||||
<system:String x:Key="Settings">设置</system:String>
|
||||
<system:String x:Key="DownloadManager">下载管理</system:String>
|
||||
<system:String x:Key="Toolbox">工具箱</system:String>
|
||||
|
||||
<!-- Login -->
|
||||
<system:String x:Key="ScanToLogin">扫描二维码登录</system:String>
|
||||
<system:String x:Key="ScanLoginTip" xml:space="preserve">请使用哔哩哔哩客户端
扫码登录
或扫码下载APP</system:String>
|
||||
<system:String x:Key="GetLoginUrlFailed">获取登录链接失败!</system:String>
|
||||
<system:String x:Key="LoginKeyError">密钥错误!尝试重新获取!</system:String>
|
||||
<system:String x:Key="LoginTimeOut">已超时!尝试重新获取二维码!</system:String>
|
||||
<system:String x:Key="LoginSuccessful">登录成功!(3秒后自动回到主页)</system:String>
|
||||
<system:String x:Key="LoginFailed">未保存登录信息!(3秒后自动回到主页)</system:String>
|
||||
|
||||
<!-- VideoDetail -->
|
||||
<system:String x:Key="CopyCover">复制封面图片</system:String>
|
||||
<system:String x:Key="CopyCoverUrl">复制封面URL</system:String>
|
||||
<system:String x:Key="Play">播放</system:String>
|
||||
<system:String x:Key="Danmaku">弹幕</system:String>
|
||||
<system:String x:Key="Like">点赞</system:String>
|
||||
<system:String x:Key="Coin">投币</system:String>
|
||||
<system:String x:Key="Favorite">收藏</system:String>
|
||||
<system:String x:Key="Share">分享</system:String>
|
||||
<system:String x:Key="Reply">评论</system:String>
|
||||
|
||||
<system:String x:Key="Anime">番剧</system:String>
|
||||
<system:String x:Key="Movie">电影</system:String>
|
||||
<system:String x:Key="Documentary">纪录片</system:String>
|
||||
<system:String x:Key="Guochuang">国创</system:String>
|
||||
<system:String x:Key="TV">电视剧</system:String>
|
||||
<system:String x:Key="Entertainment">综艺</system:String>
|
||||
<system:String x:Key="Cheese">课程</system:String>
|
||||
|
||||
<system:String x:Key="Order">序号</system:String>
|
||||
<system:String x:Key="Name">名称</system:String>
|
||||
<system:String x:Key="Duration">时长</system:String>
|
||||
<system:String x:Key="AudioQuality">音质</system:String>
|
||||
<system:String x:Key="VideoQuality">画质</system:String>
|
||||
<system:String x:Key="VideoCodec">视频编码</system:String>
|
||||
|
||||
<system:String x:Key="SelectAll">全选</system:String>
|
||||
<system:String x:Key="Parse">解析</system:String>
|
||||
<system:String x:Key="ParseVideo">解析视频</system:String>
|
||||
<system:String x:Key="DownloadSelected">下载选中项</system:String>
|
||||
|
||||
<!-- DownloadManager -->
|
||||
<system:String x:Key="Downloading">正在下载</system:String>
|
||||
<system:String x:Key="DownloadFinished">已下载</system:String>
|
||||
|
||||
<!-- Settings -->
|
||||
<system:String x:Key="PressEnterToApplySettingTip">按回车键应用设置</system:String>
|
||||
|
||||
<system:String x:Key="Basic">基本</system:String>
|
||||
<system:String x:Key="AfterDownloadOperation">下载完成后的动作:</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationNone">无</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationCloseApp">关闭程序</system:String>
|
||||
<system:String x:Key="AfterDownloadOperationCloseSystem">关闭计算机</system:String>
|
||||
<system:String x:Key="ListenClipboard">监听剪贴板</system:String>
|
||||
<system:String x:Key="VideoAutoParse">视频自动解析</system:String>
|
||||
<system:String x:Key="VideoParseScope">视频解析范围:</system:String>
|
||||
|
||||
<system:String x:Key="Network">网络</system:String>
|
||||
<system:String x:Key="AriaServerPort">Aria服务器端口:</system:String>
|
||||
<system:String x:Key="AriaLogLevel">Aria日志等级:</system:String>
|
||||
<system:String x:Key="AriaMaxConcurrentDownloads">Aria同时下载数:</system:String>
|
||||
<system:String x:Key="AriaSplit">Aria最大线程数:</system:String>
|
||||
<system:String x:Key="AriaDownloadLimit">Aria下载速度限制(KB/s)</system:String>
|
||||
<system:String x:Key="AriaMaxOverallDownloadLimit">全局下载速度限制[0: 无限制]</system:String>
|
||||
<system:String x:Key="AriaMaxDownloadLimit">单任务下载速度限制[0: 无限制]</system:String>
|
||||
<system:String x:Key="IsAriaHttpProxy">使用Http代理</system:String>
|
||||
<system:String x:Key="AriaHttpProxy">代理地址:</system:String>
|
||||
<system:String x:Key="AriaHttpProxyPort">端口:</system:String>
|
||||
<system:String x:Key="AriaFileAllocation">Aria文件预分配:</system:String>
|
||||
|
||||
<system:String x:Key="Video">视频</system:String>
|
||||
<system:String x:Key="FirstVideoCodecs">优先下载的视频编码:</system:String>
|
||||
<system:String x:Key="FirstVideoQuality">优先下载的视频画质:</system:String>
|
||||
<system:String x:Key="IsAddVideoOrder">启用视频编号</system:String>
|
||||
<system:String x:Key="IsAddVideoOrderTip">勾选后,将为下载完成的视频的文件名添加上序号</system:String>
|
||||
<system:String x:Key="IsTranscodingFlvToMp4">下载FLV视频后转码为mp4</system:String>
|
||||
<system:String x:Key="IsUseDefaultDirectory">使用默认下载目录</system:String>
|
||||
<system:String x:Key="DefaultDirectory">默认下载目录:</system:String>
|
||||
<system:String x:Key="DefaultDirectoryTip">默认将文件下载到该文件夹中</system:String>
|
||||
<system:String x:Key="ChangeDirectory">更改目录</system:String>
|
||||
<system:String x:Key="IsCreateFolderForMedia">为不同视频分别创建文件夹</system:String>
|
||||
<system:String x:Key="IsDownloadDanmaku">在下载视频的同时下载弹幕</system:String>
|
||||
<system:String x:Key="IsDownloadCover">在下载视频的同时下载封面</system:String>
|
||||
|
||||
<system:String x:Key="SettingDanmaku">弹幕</system:String>
|
||||
<system:String x:Key="FilterType">按类型屏蔽</system:String>
|
||||
<system:String x:Key="TopFilter">顶部</system:String>
|
||||
<system:String x:Key="BottomFilter">底部</system:String>
|
||||
<system:String x:Key="ScrollFilter">滚动</system:String>
|
||||
<system:String x:Key="Resolution">分辨率:</system:String>
|
||||
<system:String x:Key="FontName">字体名称:</system:String>
|
||||
<system:String x:Key="FontSize">字体大小:</system:String>
|
||||
<system:String x:Key="LineCount">限制行数:</system:String>
|
||||
<system:String x:Key="LayoutAlgorithm">布局算法:</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmSync">速度同步</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmSyncTip">每一条滚动弹幕的移动速度都是相同的</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmAsync">速度异步</system:String>
|
||||
<system:String x:Key="LayoutAlgorithmAsyncTip">弹幕滚动速度取决于它的文本长度</system:String>
|
||||
|
||||
<system:String x:Key="About">关于</system:String>
|
||||
<system:String x:Key="GotoHomepage">访问主页</system:String>
|
||||
<system:String x:Key="CurrentAppVersion">当前版本:</system:String>
|
||||
<system:String x:Key="CheckUpdate">检查更新</system:String>
|
||||
<system:String x:Key="Feedback">意见反馈</system:String>
|
||||
<system:String x:Key="ReceiveBetaVersion">接收测试版更新</system:String>
|
||||
<system:String x:Key="AutoUpdateWhenLaunch">启动时检查更新</system:String>
|
||||
<system:String x:Key="TipSettingUpdated">设置已更新~</system:String>
|
||||
<system:String x:Key="TipSettingFailed">设置失败!</system:String>
|
||||
<system:String x:Key="ThirdParty">第三方</system:String>
|
||||
<system:String x:Key="ThirdPartyName">名称</system:String>
|
||||
<system:String x:Key="ThirdPartyAuthor">作者</system:String>
|
||||
<system:String x:Key="ThirdPartyVersion">版本</system:String>
|
||||
<system:String x:Key="ThirdPartyLicense">许可证</system:String>
|
||||
<system:String x:Key="Disclaimer">免责申明</system:String>
|
||||
<system:String x:Key="Disclaimer1">1. 本软件只提供视频解析,不提供任何资源上传、存储到服务器的功能。</system:String>
|
||||
<system:String x:Key="Disclaimer2">2. 本软件仅解析来自B站的内容,不会对解析到的音视频进行二次编码,部分视频会进行有限的格式转换、拼接等操作。</system:String>
|
||||
<system:String x:Key="Disclaimer3">3. 本软件解析得到的所有内容均来自B站UP主上传、分享,其版权均归原作者所有。内容提供者、上传者(UP主)应对其提供、上传的内容承担全部责任。</system:String>
|
||||
<system:String x:Key="Disclaimer4">4. 本软件提供的所有资源,仅可用作学习交流使用,未经原作者授权,禁止用于其他用途。请在下载24小时内删除。为尊重作者版权,请前往资源的原始发布网站观看,支持原创,谢谢。</system:String>
|
||||
<system:String x:Key="Disclaimer5">5. 任何涉及商业盈利目的均不得使用,否则产生的一切后果将由您自己承担。</system:String>
|
||||
<system:String x:Key="Disclaimer6">6. 因使用本软件产生的版权问题,软件作者概不负责。</system:String>
|
||||
|
||||
<!-- Tools -->
|
||||
<system:String x:Key="BiliHelper">B站助手</system:String>
|
||||
<system:String x:Key="Delogo">去水印</system:String>
|
||||
<system:String x:Key="ExtractMedia">音视频分离</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>
|
||||
<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="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 -->
|
||||
<system:String x:Key="ParsingSelector">选择解析项</system:String>
|
||||
<system:String x:Key="ParseNone">无</system:String>
|
||||
<system:String x:Key="ParseSelectedItem">解析选中项</system:String>
|
||||
<system:String x:Key="ParseCurrentSection">解析当前页视频</system:String>
|
||||
<system:String x:Key="ParseAll">解析所有视频</system:String>
|
||||
<system:String x:Key="SetParseDefault">设为默认,下次不再弹出</system:String>
|
||||
|
||||
</ResourceDictionary>
|
9
src/DownKyi/Models/AppInfo.cs
Normal file
9
src/DownKyi/Models/AppInfo.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace DownKyi.Models
|
||||
{
|
||||
public class AppInfo
|
||||
{
|
||||
public string Name { get; } = "哔哩下载姬";
|
||||
public string VersionName { get; } = "1.5.0-alpha1";
|
||||
public int VersionCode { get; } = 500;
|
||||
}
|
||||
}
|
10
src/DownKyi/Models/ParseScopeDisplay.cs
Normal file
10
src/DownKyi/Models/ParseScopeDisplay.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using DownKyi.Core.Settings;
|
||||
|
||||
namespace DownKyi.Models
|
||||
{
|
||||
public class ParseScopeDisplay
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public ParseScope ParseScope { get; set; }
|
||||
}
|
||||
}
|
8
src/DownKyi/Models/Resolution.cs
Normal file
8
src/DownKyi/Models/Resolution.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace DownKyi.Models
|
||||
{
|
||||
public class Resolution
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Id { get; set; }
|
||||
}
|
||||
}
|
37
src/DownKyi/Models/TabHeader.cs
Normal file
37
src/DownKyi/Models/TabHeader.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using DownKyi.Images;
|
||||
using Prism.Mvvm;
|
||||
|
||||
namespace DownKyi.Models
|
||||
{
|
||||
public class TabHeader : BindableBase
|
||||
{
|
||||
private int id;
|
||||
public int Id
|
||||
{
|
||||
get { return id; }
|
||||
set { SetProperty(ref id, value); }
|
||||
}
|
||||
|
||||
private VectorImage image;
|
||||
public VectorImage Image
|
||||
{
|
||||
get { return image; }
|
||||
set { SetProperty(ref image, value); }
|
||||
}
|
||||
|
||||
private string title;
|
||||
public string Title
|
||||
{
|
||||
get { return title; }
|
||||
set { SetProperty(ref title, value); }
|
||||
}
|
||||
|
||||
private string subTitle;
|
||||
public string SubTitle
|
||||
{
|
||||
get { return subTitle; }
|
||||
set { SetProperty(ref subTitle, value); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
111
src/DownKyi/Models/VideoInfoView.cs
Normal file
111
src/DownKyi/Models/VideoInfoView.cs
Normal file
@ -0,0 +1,111 @@
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace DownKyi.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class VideoInfoView : BindableBase
|
||||
{
|
||||
public string CoverUrl { 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 videoZone;
|
||||
public string VideoZone
|
||||
{
|
||||
get { return videoZone; }
|
||||
set { SetProperty(ref videoZone, 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 danmakuNumber;
|
||||
public string DanmakuNumber
|
||||
{
|
||||
get { return danmakuNumber; }
|
||||
set { SetProperty(ref danmakuNumber, value); }
|
||||
}
|
||||
|
||||
private string likeNumber;
|
||||
public string LikeNumber
|
||||
{
|
||||
get { return likeNumber; }
|
||||
set { SetProperty(ref likeNumber, value); }
|
||||
}
|
||||
|
||||
private string coinNumber;
|
||||
public string CoinNumber
|
||||
{
|
||||
get { return coinNumber; }
|
||||
set { SetProperty(ref coinNumber, 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 replyNumber;
|
||||
public string ReplyNumber
|
||||
{
|
||||
get { return replyNumber; }
|
||||
set { SetProperty(ref replyNumber, value); }
|
||||
}
|
||||
|
||||
private string description;
|
||||
public string Description
|
||||
{
|
||||
get { return description; }
|
||||
set { SetProperty(ref description, 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); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
73
src/DownKyi/Models/VideoPage.cs
Normal file
73
src/DownKyi/Models/VideoPage.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using DownKyi.Core.BiliApi.VideoStream.Models;
|
||||
using Prism.Mvvm;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DownKyi.Models
|
||||
{
|
||||
public class VideoPage : BindableBase
|
||||
{
|
||||
public PlayUrl PlayUrl { get; set; }
|
||||
|
||||
public long Avid { get; set; }
|
||||
public string Bvid { get; set; }
|
||||
public long Cid { get; set; }
|
||||
public long EpisodeId { get; set; }
|
||||
|
||||
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 string name;
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
set { SetProperty(ref name, value); }
|
||||
}
|
||||
|
||||
private string duration;
|
||||
public string Duration
|
||||
{
|
||||
get { return duration; }
|
||||
set { SetProperty(ref duration, value); }
|
||||
}
|
||||
|
||||
private List<string> audioQualityFormatList;
|
||||
public List<string> AudioQualityFormatList
|
||||
{
|
||||
get { return audioQualityFormatList; }
|
||||
set { SetProperty(ref audioQualityFormatList, value); }
|
||||
}
|
||||
|
||||
private string audioQualityFormat;
|
||||
public string AudioQualityFormat
|
||||
{
|
||||
get { return audioQualityFormat; }
|
||||
set { SetProperty(ref audioQualityFormat, value); }
|
||||
}
|
||||
|
||||
private List<VideoQuality> videoQualityList;
|
||||
public List<VideoQuality> VideoQualityList
|
||||
{
|
||||
get { return videoQualityList; }
|
||||
set { SetProperty(ref videoQualityList, value); }
|
||||
}
|
||||
|
||||
private VideoQuality videoQuality;
|
||||
public VideoQuality VideoQuality
|
||||
{
|
||||
get { return videoQuality; }
|
||||
set { SetProperty(ref videoQuality, value); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
37
src/DownKyi/Models/VideoQuality.cs
Normal file
37
src/DownKyi/Models/VideoQuality.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using Prism.Mvvm;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DownKyi.Models
|
||||
{
|
||||
public class VideoQuality : BindableBase
|
||||
{
|
||||
private int quality;
|
||||
public int Quality
|
||||
{
|
||||
get { return quality; }
|
||||
set { SetProperty(ref quality, value); }
|
||||
}
|
||||
|
||||
private string qualityFormat;
|
||||
public string QualityFormat
|
||||
{
|
||||
get { return qualityFormat; }
|
||||
set { SetProperty(ref qualityFormat, value); }
|
||||
}
|
||||
|
||||
private List<string> videoCodecList;
|
||||
public List<string> VideoCodecList
|
||||
{
|
||||
get { return videoCodecList; }
|
||||
set { SetProperty(ref videoCodecList, value); }
|
||||
}
|
||||
|
||||
private string selectedVideoCodec;
|
||||
public string SelectedVideoCodec
|
||||
{
|
||||
get { return selectedVideoCodec; }
|
||||
set { SetProperty(ref selectedVideoCodec, value); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
31
src/DownKyi/Models/VideoSection.cs
Normal file
31
src/DownKyi/Models/VideoSection.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using Prism.Mvvm;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DownKyi.Models
|
||||
{
|
||||
public class VideoSection : BindableBase
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
private string title;
|
||||
public string Title
|
||||
{
|
||||
get { return title; }
|
||||
set { SetProperty(ref title, value); }
|
||||
}
|
||||
|
||||
private bool isSelected;
|
||||
public bool IsSelected
|
||||
{
|
||||
get { return isSelected; }
|
||||
set { SetProperty(ref isSelected, value); }
|
||||
}
|
||||
|
||||
private List<VideoPage> videoPages;
|
||||
public List<VideoPage> VideoPages
|
||||
{
|
||||
get { return videoPages; }
|
||||
set { SetProperty(ref videoPages, value); }
|
||||
}
|
||||
}
|
||||
}
|
55
src/DownKyi/Properties/AssemblyInfo.cs
Normal file
55
src/DownKyi/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("DownKyi")]
|
||||
[assembly: AssemblyDescription("DownKyi")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("DownKyi")]
|
||||
[assembly: AssemblyProduct("DownKyi")]
|
||||
[assembly: AssemblyCopyright("Copyright © Downkyi 2020-2021")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.5.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.5.0.0")]
|
73
src/DownKyi/Properties/Resources.Designer.cs
generated
Normal file
73
src/DownKyi/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace DownKyi.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 一个强类型的资源类,用于查找本地化的字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DownKyi.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap loading {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("loading", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
124
src/DownKyi/Properties/Resources.resx
Normal file
124
src/DownKyi/Properties/Resources.resx
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="loading" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\resources\loading\loading.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
30
src/DownKyi/Properties/Settings.Designer.cs
generated
Normal file
30
src/DownKyi/Properties/Settings.Designer.cs
generated
Normal file
@ -0,0 +1,30 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace DownKyi.Properties
|
||||
{
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
7
src/DownKyi/Properties/Settings.settings
Normal file
7
src/DownKyi/Properties/Settings.settings
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
BIN
src/DownKyi/Resources/default_header.jpg
Normal file
BIN
src/DownKyi/Resources/default_header.jpg
Normal file
Binary file not shown.
After ![]() (image error) Size: 8.8 KiB |
BIN
src/DownKyi/Resources/favicon.ico
Normal file
BIN
src/DownKyi/Resources/favicon.ico
Normal file
Binary file not shown.
After Width: 128px | Height: 128px | Size: 66 KiB |
BIN
src/DownKyi/Resources/loading/loading.gif
Normal file
BIN
src/DownKyi/Resources/loading/loading.gif
Normal file
Binary file not shown.
After ![]() (image error) Size: 2.2 KiB |
BIN
src/DownKyi/Resources/login/login_top_bar.png
Normal file
BIN
src/DownKyi/Resources/login/login_top_bar.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 20 KiB |
BIN
src/DownKyi/Resources/login/qrcode_login_2233.png
Normal file
BIN
src/DownKyi/Resources/login/qrcode_login_2233.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 44 KiB |
BIN
src/DownKyi/Resources/login/qrcode_login_tip.png
Normal file
BIN
src/DownKyi/Resources/login/qrcode_login_tip.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 52 KiB |
BIN
src/DownKyi/Resources/login/scan_succeed.png
Normal file
BIN
src/DownKyi/Resources/login/scan_succeed.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 3.4 KiB |
BIN
src/DownKyi/Resources/no-data.png
Normal file
BIN
src/DownKyi/Resources/no-data.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 62 KiB |
240
src/DownKyi/Services/BangumiInfoService.cs
Normal file
240
src/DownKyi/Services/BangumiInfoService.cs
Normal file
@ -0,0 +1,240 @@
|
||||
using DownKyi.Core.BiliApi.Bangumi;
|
||||
using DownKyi.Core.BiliApi.Bangumi.Models;
|
||||
using DownKyi.Core.BiliApi.BiliUtils;
|
||||
using DownKyi.Core.BiliApi.VideoStream;
|
||||
using DownKyi.Core.Storage;
|
||||
using DownKyi.Core.Utils;
|
||||
using DownKyi.Models;
|
||||
using DownKyi.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace DownKyi.Services
|
||||
{
|
||||
public class BangumiInfoService : IInfoService
|
||||
{
|
||||
private readonly BangumiSeason bangumiSeason;
|
||||
|
||||
public BangumiInfoService(string input)
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ParseEntrance.IsBangumiSeasonId(input) || ParseEntrance.IsBangumiSeasonUrl(input))
|
||||
{
|
||||
long seasonId = ParseEntrance.GetBangumiSeasonId(input);
|
||||
bangumiSeason = BangumiInfo.BangumiSeasonInfo(seasonId);
|
||||
}
|
||||
|
||||
if (ParseEntrance.IsBangumiEpisodeId(input) || ParseEntrance.IsBangumiEpisodeUrl(input))
|
||||
{
|
||||
long episodeId = ParseEntrance.GetBangumiEpisodeId(input);
|
||||
bangumiSeason = BangumiInfo.BangumiSeasonInfo(-1, episodeId);
|
||||
}
|
||||
|
||||
if (ParseEntrance.IsBangumiMediaId(input) || ParseEntrance.IsBangumiMediaUrl(input))
|
||||
{
|
||||
long mediaId = ParseEntrance.GetBangumiMediaId(input);
|
||||
var bangumiMedia = BangumiInfo.BangumiMediaInfo(mediaId);
|
||||
bangumiSeason = BangumiInfo.BangumiSeasonInfo(bangumiMedia.SeasonId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频剧集
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<VideoPage> GetVideoPages()
|
||||
{
|
||||
List<VideoPage> pages = new List<VideoPage>();
|
||||
if (bangumiSeason == null) { return pages; }
|
||||
if (bangumiSeason.Episodes == null) { return pages; }
|
||||
if (bangumiSeason.Episodes.Count == 0) { return pages; }
|
||||
|
||||
int order = 0;
|
||||
foreach (var episode in bangumiSeason.Episodes)
|
||||
{
|
||||
order++;
|
||||
|
||||
// 标题
|
||||
string name;
|
||||
|
||||
// 判断title是否为数字,如果是,则将share_copy作为name,否则将title作为name
|
||||
if (int.TryParse(episode.Title, out int result))
|
||||
{
|
||||
name = episode.ShareCopy;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (episode.LongTitle != null && episode.LongTitle != "")
|
||||
{
|
||||
name = $"{episode.Title} {episode.LongTitle}";
|
||||
}
|
||||
else
|
||||
{
|
||||
name = episode.Title;
|
||||
}
|
||||
}
|
||||
|
||||
VideoPage page = new VideoPage
|
||||
{
|
||||
Avid = episode.Aid,
|
||||
Bvid = episode.Bvid,
|
||||
Cid = episode.Cid,
|
||||
EpisodeId = -1,
|
||||
Order = order,
|
||||
Name = name,
|
||||
Duration = "N/A"
|
||||
};
|
||||
pages.Add(page);
|
||||
}
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频章节与剧集
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<VideoSection> GetVideoSections()
|
||||
{
|
||||
if (bangumiSeason == null) { return null; }
|
||||
if (bangumiSeason.Section == null) { return null; }
|
||||
if (bangumiSeason.Section.Count == 0) { return null; }
|
||||
|
||||
List<VideoSection> videoSections = new List<VideoSection>
|
||||
{
|
||||
new VideoSection
|
||||
{
|
||||
Id = bangumiSeason.Positive.Id,
|
||||
Title = bangumiSeason.Positive.Title,
|
||||
IsSelected = true,
|
||||
VideoPages = GetVideoPages()
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var section in bangumiSeason.Section)
|
||||
{
|
||||
List<VideoPage> pages = new List<VideoPage>();
|
||||
int order = 0;
|
||||
foreach (var episode in section.Episodes)
|
||||
{
|
||||
order++;
|
||||
|
||||
// 标题
|
||||
string name;
|
||||
if (episode.LongTitle != null && episode.LongTitle != "")
|
||||
{
|
||||
name = $"{episode.Title} {episode.LongTitle}";
|
||||
}
|
||||
else
|
||||
{
|
||||
name = episode.Title;
|
||||
}
|
||||
|
||||
VideoPage page = new VideoPage
|
||||
{
|
||||
Avid = episode.Aid,
|
||||
Bvid = episode.Bvid,
|
||||
Cid = episode.Cid,
|
||||
EpisodeId = -1,
|
||||
Order = order,
|
||||
Name = name,
|
||||
Duration = "N/A"
|
||||
};
|
||||
pages.Add(page);
|
||||
}
|
||||
|
||||
VideoSection videoSection = new VideoSection
|
||||
{
|
||||
Id = section.Id,
|
||||
Title = section.Title,
|
||||
VideoPages = pages
|
||||
};
|
||||
videoSections.Add(videoSection);
|
||||
}
|
||||
|
||||
return videoSections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频流的信息,从VideoPage返回
|
||||
/// </summary>
|
||||
/// <param name="page"></param>
|
||||
public void GetVideoStream(VideoPage page)
|
||||
{
|
||||
var playUrl = VideoStream.GetBangumiPlayUrl(page.Avid, page.Bvid, page.Cid);
|
||||
Utils.VideoPageInfo(playUrl, page);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public VideoInfoView GetVideoView()
|
||||
{
|
||||
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 upName;
|
||||
string header;
|
||||
if (bangumiSeason.UpInfo != null)
|
||||
{
|
||||
upName = bangumiSeason.UpInfo.Name;
|
||||
|
||||
StorageHeader storageHeader = new StorageHeader();
|
||||
header = storageHeader.GetHeader(bangumiSeason.UpInfo.Mid, bangumiSeason.UpInfo.Name, bangumiSeason.UpInfo.Avatar);
|
||||
}
|
||||
else
|
||||
{
|
||||
upName = "";
|
||||
header = null;
|
||||
}
|
||||
|
||||
// 为videoInfoView赋值
|
||||
VideoInfoView videoInfoView = new VideoInfoView();
|
||||
App.PropertyChangeAsync(new Action(() =>
|
||||
{
|
||||
videoInfoView.CoverUrl = coverUrl;
|
||||
|
||||
videoInfoView.Cover = new BitmapImage(new Uri(cover));
|
||||
videoInfoView.Title = bangumiSeason.Title;
|
||||
|
||||
videoInfoView.VideoZone = DictionaryResource.GetString(BangumiType.Type[bangumiSeason.Type]);
|
||||
|
||||
videoInfoView.PlayNumber = Format.FormatNumber(bangumiSeason.Stat.Views);
|
||||
videoInfoView.DanmakuNumber = Format.FormatNumber(bangumiSeason.Stat.Danmakus);
|
||||
videoInfoView.LikeNumber = Format.FormatNumber(bangumiSeason.Stat.Likes);
|
||||
videoInfoView.CoinNumber = Format.FormatNumber(bangumiSeason.Stat.Coins);
|
||||
videoInfoView.FavoriteNumber = Format.FormatNumber(bangumiSeason.Stat.Favorites);
|
||||
videoInfoView.ShareNumber = Format.FormatNumber(bangumiSeason.Stat.Share);
|
||||
videoInfoView.ReplyNumber = Format.FormatNumber(bangumiSeason.Stat.Reply);
|
||||
videoInfoView.Description = bangumiSeason.Evaluate;
|
||||
|
||||
videoInfoView.UpName = upName;
|
||||
if (header != null)
|
||||
{
|
||||
StorageHeader storageHeader = new StorageHeader();
|
||||
videoInfoView.UpHeader = storageHeader.GetHeaderThumbnail(header, 48, 48);
|
||||
}
|
||||
else
|
||||
{
|
||||
videoInfoView.UpHeader = null;
|
||||
}
|
||||
}));
|
||||
|
||||
return videoInfoView;
|
||||
}
|
||||
}
|
||||
}
|
160
src/DownKyi/Services/CheeseInfoService.cs
Normal file
160
src/DownKyi/Services/CheeseInfoService.cs
Normal file
@ -0,0 +1,160 @@
|
||||
using DownKyi.Core.BiliApi.BiliUtils;
|
||||
using DownKyi.Core.BiliApi.Cheese;
|
||||
using DownKyi.Core.BiliApi.Cheese.Models;
|
||||
using DownKyi.Core.BiliApi.VideoStream;
|
||||
using DownKyi.Core.Storage;
|
||||
using DownKyi.Core.Utils;
|
||||
using DownKyi.Models;
|
||||
using DownKyi.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace DownKyi.Services
|
||||
{
|
||||
public class CheeseInfoService : IInfoService
|
||||
{
|
||||
private readonly CheeseView cheeseView;
|
||||
|
||||
public CheeseInfoService(string input)
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ParseEntrance.IsCheeseSeasonUrl(input))
|
||||
{
|
||||
long seasonId = ParseEntrance.GetCheeseSeasonId(input);
|
||||
cheeseView = CheeseInfo.CheeseViewInfo(seasonId);
|
||||
}
|
||||
|
||||
if (ParseEntrance.IsCheeseEpisodeUrl(input))
|
||||
{
|
||||
long episodeId = ParseEntrance.GetCheeseEpisodeId(input);
|
||||
cheeseView = CheeseInfo.CheeseViewInfo(-1, episodeId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频剧集
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<VideoPage> GetVideoPages()
|
||||
{
|
||||
List<VideoPage> pages = new List<VideoPage>();
|
||||
if (cheeseView == null) { return pages; }
|
||||
if (cheeseView.Episodes == null) { return pages; }
|
||||
if (cheeseView.Episodes.Count == 0) { return pages; }
|
||||
|
||||
int order = 0;
|
||||
foreach (var episode in cheeseView.Episodes)
|
||||
{
|
||||
order++;
|
||||
string name = episode.Title;
|
||||
|
||||
string duration = Format.FormatDuration(episode.Duration - 1);
|
||||
|
||||
VideoPage page = new VideoPage
|
||||
{
|
||||
Avid = episode.Aid,
|
||||
Bvid = null,
|
||||
Cid = episode.Cid,
|
||||
EpisodeId = episode.Id,
|
||||
Order = order,
|
||||
Name = name,
|
||||
Duration = "N/A"
|
||||
};
|
||||
pages.Add(page);
|
||||
}
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频章节与剧集
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<VideoSection> GetVideoSections()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频流的信息,从VideoPage返回
|
||||
/// </summary>
|
||||
/// <param name="page"></param>
|
||||
public void GetVideoStream(VideoPage page)
|
||||
{
|
||||
var playUrl = VideoStream.GetCheesePlayUrl(page.Avid, page.Bvid, page.Cid, page.EpisodeId);
|
||||
Utils.VideoPageInfo(playUrl, page);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public VideoInfoView GetVideoView()
|
||||
{
|
||||
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 upName;
|
||||
string header;
|
||||
if (cheeseView.UpInfo != null)
|
||||
{
|
||||
upName = cheeseView.UpInfo.Name;
|
||||
StorageHeader storageHeader = new StorageHeader();
|
||||
header = storageHeader.GetHeader(cheeseView.UpInfo.Mid, cheeseView.UpInfo.Name, cheeseView.UpInfo.Avatar);
|
||||
}
|
||||
else
|
||||
{
|
||||
upName = "";
|
||||
header = null;
|
||||
}
|
||||
|
||||
// 为videoInfoView赋值
|
||||
VideoInfoView videoInfoView = new VideoInfoView();
|
||||
App.PropertyChangeAsync(new Action(() =>
|
||||
{
|
||||
videoInfoView.CoverUrl = coverUrl;
|
||||
|
||||
videoInfoView.Cover = new BitmapImage(new Uri(cover));
|
||||
videoInfoView.Title = cheeseView.Title;
|
||||
|
||||
videoInfoView.VideoZone = DictionaryResource.GetString("Cheese");
|
||||
videoInfoView.CreateTime = "";
|
||||
|
||||
videoInfoView.PlayNumber = Format.FormatNumber(cheeseView.Stat.Play);
|
||||
videoInfoView.DanmakuNumber = Format.FormatNumber(0);
|
||||
videoInfoView.LikeNumber = Format.FormatNumber(0);
|
||||
videoInfoView.CoinNumber = Format.FormatNumber(0);
|
||||
videoInfoView.FavoriteNumber = Format.FormatNumber(0);
|
||||
videoInfoView.ShareNumber = Format.FormatNumber(0);
|
||||
videoInfoView.ReplyNumber = Format.FormatNumber(0);
|
||||
videoInfoView.Description = cheeseView.Subtitle;
|
||||
|
||||
videoInfoView.UpName = upName;
|
||||
if (header != null)
|
||||
{
|
||||
StorageHeader storageHeader = new StorageHeader();
|
||||
videoInfoView.UpHeader = storageHeader.GetHeaderThumbnail(header, 48, 48);
|
||||
}
|
||||
else
|
||||
{
|
||||
videoInfoView.UpHeader = null;
|
||||
}
|
||||
}));
|
||||
|
||||
return videoInfoView;
|
||||
}
|
||||
}
|
||||
}
|
16
src/DownKyi/Services/IInfoService.cs
Normal file
16
src/DownKyi/Services/IInfoService.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using DownKyi.Models;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DownKyi.Services
|
||||
{
|
||||
public interface IInfoService
|
||||
{
|
||||
VideoInfoView GetVideoView();
|
||||
|
||||
List<VideoSection> GetVideoSections();
|
||||
|
||||
List<VideoPage> GetVideoPages();
|
||||
|
||||
void GetVideoStream(VideoPage page);
|
||||
}
|
||||
}
|
10
src/DownKyi/Services/IResolutionService.cs
Normal file
10
src/DownKyi/Services/IResolutionService.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using DownKyi.Models;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DownKyi.Services
|
||||
{
|
||||
public interface IResolutionService
|
||||
{
|
||||
List<Resolution> GetResolution();
|
||||
}
|
||||
}
|
26
src/DownKyi/Services/ResolutionService.cs
Normal file
26
src/DownKyi/Services/ResolutionService.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using DownKyi.Models;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DownKyi.Services
|
||||
{
|
||||
public class ResolutionService : IResolutionService
|
||||
{
|
||||
public List<Resolution> GetResolution()
|
||||
{
|
||||
List<Resolution> resolutions = new List<Resolution>
|
||||
{
|
||||
new Resolution { Name = "HDR 真彩", Id = 125 },
|
||||
new Resolution { Name = "4K 超清", Id = 120 },
|
||||
new Resolution { Name = "1080P 60帧", Id = 116 },
|
||||
new Resolution { Name = "1080P 高码率", Id = 112 },
|
||||
new Resolution { Name = "1080P 高清", Id = 80 },
|
||||
new Resolution { Name = "720P 60帧", Id = 74 },
|
||||
new Resolution { Name = "720P 高清", Id = 64 },
|
||||
new Resolution { Name = "480P 清晰", Id = 32 },
|
||||
new Resolution { Name = "360P 流畅", Id = 16 }
|
||||
};
|
||||
|
||||
return resolutions;
|
||||
}
|
||||
}
|
||||
}
|
210
src/DownKyi/Services/Utils.cs
Normal file
210
src/DownKyi/Services/Utils.cs
Normal file
@ -0,0 +1,210 @@
|
||||
using DownKyi.Core.BiliApi.VideoStream.Models;
|
||||
using DownKyi.Core.Settings;
|
||||
using DownKyi.Core.Settings.Models;
|
||||
using DownKyi.Core.Utils;
|
||||
using DownKyi.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DownKyi.Services
|
||||
{
|
||||
internal static class Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// 从视频流更新VideoPage
|
||||
/// </summary>
|
||||
/// <param name="playUrl"></param>
|
||||
/// <param name="page"></param>
|
||||
internal static void VideoPageInfo(PlayUrl playUrl, VideoPage page)
|
||||
{
|
||||
if (playUrl == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 视频流信息
|
||||
page.PlayUrl = playUrl;
|
||||
|
||||
// 获取设置
|
||||
var userInfo = SettingsManager.GetInstance().GetUserInfo();
|
||||
int defaultQuality = SettingsManager.GetInstance().GetQuality();
|
||||
var videoCodecs = SettingsManager.GetInstance().GetVideoCodecs();
|
||||
int defaultAudioQuality = SettingsManager.GetInstance().GetAudioQuality();
|
||||
|
||||
// 未登录时,最高仅720P
|
||||
if (userInfo.Mid == -1)
|
||||
{
|
||||
if (defaultQuality > 64)
|
||||
{
|
||||
defaultQuality = 64;
|
||||
}
|
||||
}
|
||||
|
||||
// 非大会员账户登录时,如果设置的画质高于1080P,则这里限制为1080P
|
||||
if (!userInfo.IsVip)
|
||||
{
|
||||
if (defaultQuality > 80)
|
||||
{
|
||||
defaultQuality = 80;
|
||||
}
|
||||
}
|
||||
|
||||
if (playUrl.Durl != null)
|
||||
{
|
||||
// 音质
|
||||
|
||||
// 画质
|
||||
|
||||
// 视频编码
|
||||
|
||||
// 时长
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (playUrl.Dash != null)
|
||||
{
|
||||
// 如果video列表或者audio列表没有内容,则返回false
|
||||
if (playUrl.Dash.Video == null) { return; }
|
||||
if (playUrl.Dash.Video.Count == 0) { return; }
|
||||
|
||||
// 音质
|
||||
page.AudioQualityFormatList = GetAudioQualityFormatList(playUrl, defaultAudioQuality);
|
||||
if (page.AudioQualityFormatList.Count > 0)
|
||||
{
|
||||
page.AudioQualityFormat = page.AudioQualityFormatList[0];
|
||||
}
|
||||
|
||||
// 画质 & 视频编码
|
||||
page.VideoQualityList = GetVideoQualityList(playUrl, userInfo, defaultQuality, videoCodecs);
|
||||
if (page.VideoQualityList.Count > 0)
|
||||
{
|
||||
page.VideoQuality = page.VideoQualityList[0];
|
||||
}
|
||||
|
||||
// 时长
|
||||
page.Duration = Format.FormatDuration(playUrl.Dash.Duration);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置音质
|
||||
/// </summary>
|
||||
/// <param name="playUrl"></param>
|
||||
/// <param name="defaultAudioQuality"></param>
|
||||
/// <returns></returns>
|
||||
private static List<string> GetAudioQualityFormatList(PlayUrl playUrl, int defaultAudioQuality)
|
||||
{
|
||||
List<string> audioQualityFormatList = new List<string>();
|
||||
foreach (var audio in playUrl.Dash.Audio)
|
||||
{
|
||||
// 音质id大于设置画质时,跳过
|
||||
if (audio.Id > defaultAudioQuality) { continue; }
|
||||
|
||||
if (Core.BiliApi.BiliUtils.Constant.AudioQuality.ContainsKey(audio.Id))
|
||||
{
|
||||
ListHelper.AddUnique(audioQualityFormatList, Core.BiliApi.BiliUtils.Constant.AudioQuality[audio.Id]);
|
||||
}
|
||||
}
|
||||
|
||||
audioQualityFormatList.Sort(new StringLogicalComparer<string>());
|
||||
audioQualityFormatList.Reverse();
|
||||
|
||||
return audioQualityFormatList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置画质 & 视频编码
|
||||
/// </summary>
|
||||
/// <param name="playUrl"></param>
|
||||
/// <param name="defaultQuality"></param>
|
||||
/// <param name="userInfo"></param>
|
||||
/// <param name="videoCodecs"></param>
|
||||
/// <returns></returns>
|
||||
private static List<VideoQuality> GetVideoQualityList(PlayUrl playUrl, UserInfoSettings userInfo, int defaultQuality, VideoCodecs videoCodecs)
|
||||
{
|
||||
List<VideoQuality> videoQualityList = new List<VideoQuality>();
|
||||
foreach (var video in playUrl.Dash.Video)
|
||||
{
|
||||
// 画质id大于设置画质时,跳过
|
||||
if (video.Id > defaultQuality) { continue; }
|
||||
|
||||
// 非大会员账户登录时
|
||||
if (!userInfo.IsVip)
|
||||
{
|
||||
// 如果画质为720P60,跳过
|
||||
if (video.Id == 74) { continue; }
|
||||
}
|
||||
|
||||
string qualityFormat = string.Empty;
|
||||
var selectedQuality = playUrl.SupportFormats.FirstOrDefault(t => t.Quality == video.Id);
|
||||
if (selectedQuality != null)
|
||||
{
|
||||
qualityFormat = selectedQuality.NewDescription;
|
||||
}
|
||||
|
||||
// 寻找是否已存在这个画质
|
||||
// 不存在则添加,存在则修改
|
||||
string codecName = GetVideoCodecName(video.Codecs);
|
||||
var videoQualityExist = videoQualityList.FirstOrDefault(t => t.Quality == video.Id);
|
||||
if (videoQualityExist == null)
|
||||
{
|
||||
var videoCodecList = new List<string>();
|
||||
ListHelper.AddUnique(videoCodecList, codecName);
|
||||
|
||||
var videoQuality = new VideoQuality()
|
||||
{
|
||||
Quality = video.Id,
|
||||
QualityFormat = qualityFormat,
|
||||
VideoCodecList = videoCodecList
|
||||
};
|
||||
videoQualityList.Add(videoQuality);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!videoQualityList[videoQualityList.IndexOf(videoQualityExist)].VideoCodecList.Exists(t => t.Equals(codecName)))
|
||||
{
|
||||
videoQualityList[videoQualityList.IndexOf(videoQualityExist)].VideoCodecList.Add(codecName);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置选中的视频编码
|
||||
var selectedVideoQuality = videoQualityList.FirstOrDefault(t => t.Quality == video.Id);
|
||||
switch (videoCodecs)
|
||||
{
|
||||
case VideoCodecs.AVC:
|
||||
if (videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList.Contains("H.264/AVC"))
|
||||
{
|
||||
videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].SelectedVideoCodec = "H.264/AVC";
|
||||
}
|
||||
break;
|
||||
case VideoCodecs.HEVC:
|
||||
if (videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList.Contains("H.265/HEVC"))
|
||||
{
|
||||
videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].SelectedVideoCodec = "H.265/HEVC";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList.Count == 1)
|
||||
{
|
||||
// 当获取的视频没有设置的视频编码时,执行
|
||||
videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].SelectedVideoCodec = videoQualityList[videoQualityList.IndexOf(selectedVideoQuality)].VideoCodecList[0];
|
||||
}
|
||||
}
|
||||
|
||||
return videoQualityList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据输入的字符串判断是AVC还是HEVC
|
||||
/// </summary>
|
||||
/// <param name="origin"></param>
|
||||
/// <returns></returns>
|
||||
private static string GetVideoCodecName(string origin)
|
||||
{
|
||||
return origin.Contains("avc") ? "H.264/AVC" : origin.Contains("hev") ? "H.265/HEVC" : "";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
236
src/DownKyi/Services/VideoInfoService.cs
Normal file
236
src/DownKyi/Services/VideoInfoService.cs
Normal file
@ -0,0 +1,236 @@
|
||||
using DownKyi.Core.BiliApi.BiliUtils;
|
||||
using DownKyi.Core.BiliApi.Video;
|
||||
using DownKyi.Core.BiliApi.Video.Models;
|
||||
using DownKyi.Core.BiliApi.VideoStream;
|
||||
using DownKyi.Core.Storage;
|
||||
using DownKyi.Core.Utils;
|
||||
using DownKyi.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace DownKyi.Services
|
||||
{
|
||||
public class VideoInfoService : IInfoService
|
||||
{
|
||||
private readonly VideoView videoView;
|
||||
|
||||
public VideoInfoService(string input)
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ParseEntrance.IsAvId(input) || ParseEntrance.IsAvUrl(input))
|
||||
{
|
||||
long avid = ParseEntrance.GetAvId(input);
|
||||
videoView = VideoInfo.VideoViewInfo(null, avid);
|
||||
}
|
||||
|
||||
if (ParseEntrance.IsBvId(input) || ParseEntrance.IsBvUrl(input))
|
||||
{
|
||||
string bvid = ParseEntrance.GetBvId(input);
|
||||
videoView = VideoInfo.VideoViewInfo(bvid);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频剧集
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<Models.VideoPage> GetVideoPages()
|
||||
{
|
||||
if (videoView == null) { return null; }
|
||||
if (videoView.Pages == null) { return null; }
|
||||
if (videoView.Pages.Count == 0) { return null; }
|
||||
|
||||
List<Models.VideoPage> videoPages = new List<Models.VideoPage>();
|
||||
|
||||
int order = 0;
|
||||
foreach (var page in videoView.Pages)
|
||||
{
|
||||
order++;
|
||||
|
||||
// 标题
|
||||
string name;
|
||||
if (videoView.Pages.Count == 1)
|
||||
{
|
||||
name = videoView.Title;
|
||||
}
|
||||
else
|
||||
{
|
||||
//name = page.part;
|
||||
if (page.Part == "")
|
||||
{
|
||||
// 如果page.part为空字符串
|
||||
name = $"{videoView.Title}-P{order}";
|
||||
}
|
||||
else
|
||||
{
|
||||
name = page.Part;
|
||||
}
|
||||
}
|
||||
|
||||
Models.VideoPage videoPage = new Models.VideoPage
|
||||
{
|
||||
Avid = videoView.Aid,
|
||||
Bvid = videoView.Bvid,
|
||||
Cid = page.Cid,
|
||||
EpisodeId = -1,
|
||||
Order = order,
|
||||
Name = name,
|
||||
Duration = "N/A"
|
||||
};
|
||||
videoPages.Add(videoPage);
|
||||
}
|
||||
|
||||
return videoPages;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频章节与剧集
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<VideoSection> GetVideoSections()
|
||||
{
|
||||
if (videoView == null) { return null; }
|
||||
if (videoView.UgcSeason == null) { return null; }
|
||||
if (videoView.UgcSeason.Sections == null) { return null; }
|
||||
if (videoView.UgcSeason.Sections.Count == 0) { return null; }
|
||||
|
||||
List<VideoSection> videoSections = new List<VideoSection>();
|
||||
|
||||
foreach (var section in videoView.UgcSeason.Sections)
|
||||
{
|
||||
List<Models.VideoPage> pages = new List<Models.VideoPage>();
|
||||
int order = 0;
|
||||
foreach (var episode in section.Episodes)
|
||||
{
|
||||
order++;
|
||||
Models.VideoPage page = new Models.VideoPage
|
||||
{
|
||||
Avid = episode.Aid,
|
||||
Bvid = episode.Bvid,
|
||||
Cid = episode.Cid,
|
||||
EpisodeId = -1,
|
||||
Order = order,
|
||||
Name = episode.Title,
|
||||
Duration = "N/A"
|
||||
};
|
||||
pages.Add(page);
|
||||
}
|
||||
|
||||
VideoSection videoSection = new VideoSection
|
||||
{
|
||||
Id = section.Id,
|
||||
Title = section.Title,
|
||||
VideoPages = pages
|
||||
};
|
||||
videoSections.Add(videoSection);
|
||||
}
|
||||
|
||||
videoSections[0].IsSelected = true;
|
||||
|
||||
return videoSections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频流的信息,从VideoPage返回
|
||||
/// </summary>
|
||||
/// <param name="page"></param>
|
||||
public void GetVideoStream(Models.VideoPage page)
|
||||
{
|
||||
var playUrl = VideoStream.GetVideoPlayUrl(page.Avid, page.Bvid, page.Cid);
|
||||
Utils.VideoPageInfo(playUrl, page);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取视频信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public VideoInfoView GetVideoView()
|
||||
{
|
||||
if (videoView == null) { return null; }
|
||||
|
||||
// 查询、保存封面
|
||||
StorageCover storageCover = new StorageCover();
|
||||
string coverUrl = videoView.Pic;
|
||||
string cover = storageCover.GetCover(videoView.Aid, videoView.Bvid, videoView.Cid, coverUrl);
|
||||
|
||||
// 分区
|
||||
string videoZone = string.Empty;
|
||||
var zoneList = Core.BiliApi.Zone.VideoZone.Instance().GetZone();
|
||||
var zone = zoneList.Find(it => it.Id == videoView.Tid);
|
||||
if (zone != null)
|
||||
{
|
||||
var zoneParent = zoneList.Find(it => it.Id == zone.ParentId);
|
||||
if (zoneParent != null)
|
||||
{
|
||||
videoZone = zoneParent.Name + ">" + zone.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
videoZone = zone.Name;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
videoZone = videoView.Tname;
|
||||
}
|
||||
|
||||
// 获取用户头像
|
||||
string upName;
|
||||
string header;
|
||||
if (videoView.Owner != null)
|
||||
{
|
||||
upName = videoView.Owner.Name;
|
||||
StorageHeader storageHeader = new StorageHeader();
|
||||
header = storageHeader.GetHeader(videoView.Owner.Mid, videoView.Owner.Name, videoView.Owner.Face);
|
||||
}
|
||||
else
|
||||
{
|
||||
upName = "";
|
||||
header = null;
|
||||
}
|
||||
|
||||
// 为videoInfoView赋值
|
||||
VideoInfoView videoInfoView = new VideoInfoView();
|
||||
App.PropertyChangeAsync(new Action(() =>
|
||||
{
|
||||
videoInfoView.CoverUrl = coverUrl;
|
||||
|
||||
videoInfoView.Cover = new BitmapImage(new Uri(cover));
|
||||
videoInfoView.Title = videoView.Title;
|
||||
|
||||
videoInfoView.VideoZone = videoZone;
|
||||
|
||||
DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区
|
||||
DateTime dateTime = startTime.AddSeconds(videoView.Pubdate);
|
||||
videoInfoView.CreateTime = dateTime.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
videoInfoView.PlayNumber = Format.FormatNumber(videoView.Stat.View);
|
||||
videoInfoView.DanmakuNumber = Format.FormatNumber(videoView.Stat.Danmaku);
|
||||
videoInfoView.LikeNumber = Format.FormatNumber(videoView.Stat.Like);
|
||||
videoInfoView.CoinNumber = Format.FormatNumber(videoView.Stat.Coin);
|
||||
videoInfoView.FavoriteNumber = Format.FormatNumber(videoView.Stat.Favorite);
|
||||
videoInfoView.ShareNumber = Format.FormatNumber(videoView.Stat.Share);
|
||||
videoInfoView.ReplyNumber = Format.FormatNumber(videoView.Stat.Reply);
|
||||
videoInfoView.Description = videoView.Desc;
|
||||
|
||||
videoInfoView.UpName = upName;
|
||||
if (header != null)
|
||||
{
|
||||
StorageHeader storageHeader = new StorageHeader();
|
||||
videoInfoView.UpHeader = storageHeader.GetHeaderThumbnail(header, 48, 48);
|
||||
}
|
||||
else
|
||||
{
|
||||
videoInfoView.UpHeader = null;
|
||||
}
|
||||
}));
|
||||
|
||||
return videoInfoView;
|
||||
}
|
||||
}
|
||||
}
|
43
src/DownKyi/Themes/ColorBrush.xaml
Normal file
43
src/DownKyi/Themes/ColorBrush.xaml
Normal file
@ -0,0 +1,43 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Themes">
|
||||
|
||||
<SolidColorBrush x:Key="BrushWindowBorder" Color="{DynamicResource ColorWindowBorder}" />
|
||||
<SolidColorBrush x:Key="BrushCaptionForeground" Color="{DynamicResource ColorCaptionForeground}" />
|
||||
<SolidColorBrush x:Key="BrushCaptionBackground" Color="{DynamicResource ColorCaptionBackground}" />
|
||||
|
||||
<SolidColorBrush x:Key="BrushSystemBtnTint" Color="{DynamicResource ColorSystemBtnTint}" />
|
||||
<SolidColorBrush x:Key="BrushSystemBtnTintDark" Color="{DynamicResource ColorSystemBtnTintDark}" />
|
||||
<SolidColorBrush x:Key="BrushSystemBtnHover" Color="{DynamicResource ColorSystemBtnHover}" />
|
||||
<SolidColorBrush x:Key="BrushSystemBtnPressed" Color="{DynamicResource ColorSystemBtnPressed}" />
|
||||
<SolidColorBrush x:Key="BrushCloseBtnHover" Color="{DynamicResource ColorCloseBtnHover}" />
|
||||
<SolidColorBrush x:Key="BrushCloseBtnPressed" Color="{DynamicResource ColorCloseBtnPressed}" />
|
||||
|
||||
<SolidColorBrush x:Key="BrushPrimary" Color="{DynamicResource ColorPrimary}" />
|
||||
<SolidColorBrush x:Key="BrushPrimaryTranslucent" Color="{DynamicResource ColorPrimaryTranslucent}" />
|
||||
<SolidColorBrush x:Key="BrushPrimaryTranslucent2" Color="{DynamicResource ColorPrimaryTranslucent2}" />
|
||||
<SolidColorBrush x:Key="BrushPrimaryTranslucent3" Color="{DynamicResource ColorPrimaryTranslucent3}" />
|
||||
<SolidColorBrush x:Key="BrushForeground" Color="{DynamicResource ColorForeground}" />
|
||||
<SolidColorBrush x:Key="BrushBackground" Color="{DynamicResource ColorBackground}" />
|
||||
<SolidColorBrush x:Key="BrushForegroundDark" Color="{DynamicResource ColorForegroundDark}" />
|
||||
<SolidColorBrush x:Key="BrushBackgroundDark" Color="{DynamicResource ColorBackgroundDark}" />
|
||||
<SolidColorBrush x:Key="BrushForegroundGrey" Color="{DynamicResource ColorForegroundGrey}" />
|
||||
<SolidColorBrush x:Key="BrushBackgroundGrey" Color="{DynamicResource ColorBackgroundGrey}" />
|
||||
<SolidColorBrush x:Key="BrushBackgroundGreyTranslucent" Color="{DynamicResource ColorBackgroundGreyTranslucent}" />
|
||||
<SolidColorBrush x:Key="BrushBackgroundGreyTranslucent2" Color="{DynamicResource ColorBackgroundGreyTranslucent2}" />
|
||||
<SolidColorBrush x:Key="BrushBackgroundGreyTranslucent3" Color="{DynamicResource ColorBackgroundGreyTranslucent3}" />
|
||||
|
||||
<SolidColorBrush x:Key="BrushTabHeaderGrey" Color="{DynamicResource ColorTabHeaderGrey}" />
|
||||
|
||||
<SolidColorBrush x:Key="BrushHeaderGrey" Color="{DynamicResource ColorHeaderGrey}" />
|
||||
<SolidColorBrush x:Key="BrushBorder" Color="{DynamicResource ColorBorder}" />
|
||||
|
||||
<SolidColorBrush x:Key="BrushImageBorder" Color="{DynamicResource ColorImageBorder}" />
|
||||
<SolidColorBrush x:Key="BrushImageBackground" Color="{DynamicResource ColorImageBackground}" />
|
||||
|
||||
<SolidColorBrush x:Key="BrushText" Color="{DynamicResource ColorText}" />
|
||||
<SolidColorBrush x:Key="BrushTextDark" Color="{DynamicResource ColorTextDark}" />
|
||||
<SolidColorBrush x:Key="BrushTextGrey" Color="{DynamicResource ColorTextGrey}" />
|
||||
|
||||
</ResourceDictionary>
|
43
src/DownKyi/Themes/Colors/ColorDefault.xaml
Normal file
43
src/DownKyi/Themes/Colors/ColorDefault.xaml
Normal file
@ -0,0 +1,43 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Themes.Colors">
|
||||
|
||||
<Color x:Key="ColorWindowBorder">Black</Color>
|
||||
<Color x:Key="ColorCaptionForeground">Black</Color>
|
||||
<Color x:Key="ColorCaptionBackground">white</Color>
|
||||
|
||||
<Color x:Key="ColorSystemBtnTint">white</Color>
|
||||
<Color x:Key="ColorSystemBtnTintDark">black</Color>
|
||||
<Color x:Key="ColorSystemBtnHover">#FF6ECEF8</Color>
|
||||
<Color x:Key="ColorSystemBtnPressed">#FF30B8F6</Color>
|
||||
<Color x:Key="ColorCloseBtnHover">#FFE81123</Color>
|
||||
<Color x:Key="ColorCloseBtnPressed">#FFF1707A</Color>
|
||||
|
||||
<Color x:Key="ColorPrimary">#FF00A1D6</Color>
|
||||
<Color x:Key="ColorPrimaryTranslucent">#C800A1D6</Color>
|
||||
<Color x:Key="ColorPrimaryTranslucent2">#7F00A1D6</Color>
|
||||
<Color x:Key="ColorPrimaryTranslucent3">#3300A1D6</Color>
|
||||
<Color x:Key="ColorForeground">#FF00A1D6</Color>
|
||||
<Color x:Key="ColorBackground">#FFFFFFFF</Color>
|
||||
<Color x:Key="ColorForegroundDark">#FFFFFFFF</Color>
|
||||
<Color x:Key="ColorBackgroundDark">#FF00A1D6</Color>
|
||||
<Color x:Key="ColorForegroundGrey">#FFBDBDBD</Color>
|
||||
<Color x:Key="ColorBackgroundGrey">#FFBDBDBD</Color>
|
||||
<Color x:Key="ColorBackgroundGreyTranslucent">#C8BDBDBD</Color>
|
||||
<Color x:Key="ColorBackgroundGreyTranslucent2">#7FBDBDBD</Color>
|
||||
<Color x:Key="ColorBackgroundGreyTranslucent3">#33BDBDBD</Color>
|
||||
|
||||
<Color x:Key="ColorTabHeaderGrey">#FFF4F4F4</Color>
|
||||
|
||||
<Color x:Key="ColorHeaderGrey">#FFF4F4F4</Color>
|
||||
<Color x:Key="ColorBorder">#FF999999</Color>
|
||||
|
||||
<Color x:Key="ColorImageBorder">#7FD0D0D0</Color>
|
||||
<Color x:Key="ColorImageBackground">#7FD0D0D0</Color>
|
||||
|
||||
<Color x:Key="ColorText">white</Color>
|
||||
<Color x:Key="ColorTextDark">black</Color>
|
||||
<Color x:Key="ColorTextGrey">#FF999999</Color>
|
||||
|
||||
</ResourceDictionary>
|
29
src/DownKyi/Themes/Colors/ColorDiy.xaml
Normal file
29
src/DownKyi/Themes/Colors/ColorDiy.xaml
Normal file
@ -0,0 +1,29 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Themes.Colors">
|
||||
|
||||
<Color x:Key="ColorWindowBorder">Black</Color>
|
||||
<Color x:Key="ColorCaptionForeground">Black</Color>
|
||||
<Color x:Key="ColorCaptionBackground">#7FD0D0D0</Color>
|
||||
|
||||
<Color x:Key="ColorSystemBtnTint">white</Color>
|
||||
<Color x:Key="ColorSystemBtnTintDark">black</Color>
|
||||
<Color x:Key="ColorSystemBtnHover">#FF6ECEF8</Color>
|
||||
<Color x:Key="ColorSystemBtnPressed">#FF30B8F6</Color>
|
||||
<Color x:Key="ColorCloseBtnHover">#FFF1707A</Color>
|
||||
<Color x:Key="ColorCloseBtnPressed">#FFE81123</Color>
|
||||
|
||||
<Color x:Key="ColorPrimary">#FF00A1D6</Color>
|
||||
<Color x:Key="ColorForeground">#FF00A1D6</Color>
|
||||
<Color x:Key="ColorBackground">#FFFFFFFF</Color>
|
||||
<Color x:Key="ColorForegroundDark">#FFFFFFFF</Color>
|
||||
<Color x:Key="ColorBackgroundDark">#FF00A1D6</Color>
|
||||
|
||||
<Color x:Key="ColorImageBorder">#7FD0D0D0</Color>
|
||||
<Color x:Key="ColorImageBackground">#7FD0D0D0</Color>
|
||||
|
||||
<Color x:Key="ColorText">white</Color>
|
||||
<Color x:Key="ColorTextDark">black</Color>
|
||||
|
||||
</ResourceDictionary>
|
73
src/DownKyi/Themes/Styles/StyleBtn.xaml
Normal file
73
src/DownKyi/Themes/Styles/StyleBtn.xaml
Normal file
@ -0,0 +1,73 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Themes.Styles">
|
||||
|
||||
<Style x:Key="BtnStyle" TargetType="{x:Type Button}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="BorderBrush" Value="{x:Null}" />
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border
|
||||
Padding="10,5"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="5">
|
||||
<ContentPresenter
|
||||
Name="content"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</Border>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource BrushPrimaryTranslucent}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="False">
|
||||
<Setter Property="Background" Value="{DynamicResource BrushPrimary}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="BtnBorderStyle" TargetType="{x:Type Button}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Background" Value="{DynamicResource BrushBackground}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="BorderBrush" Value="{x:Null}" />
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border
|
||||
Padding="10,5"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{DynamicResource BrushPrimary}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="5">
|
||||
<ContentPresenter
|
||||
Name="content"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</Border>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource BrushPrimaryTranslucent3}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
78
src/DownKyi/Themes/Styles/StyleCheckBox.xaml
Normal file
78
src/DownKyi/Themes/Styles/StyleCheckBox.xaml
Normal file
@ -0,0 +1,78 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Themes.Styles">
|
||||
<DrawingImage x:Key="CheckBox.UncheckedDrawingImage">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
|
||||
<DrawingGroup.Transform>
|
||||
<TranslateTransform X="4.2632564145606011E-14" Y="4.2632564145606011E-14" />
|
||||
</DrawingGroup.Transform>
|
||||
<GeometryDrawing Brush="#FF000000" Geometry="F1 M1024,1024z M0,0z M170.67,85.33Q134.67,86.67 110.67,110.67 86.67,134.67 85.33,170.67L85.33,853.33Q86.67,889.33 110.67,913.33 134.67,937.33 170.67,938.67L853.33,938.67Q889.33,937.33 913.33,913.33 937.33,889.33 938.67,853.33L938.67,170.67Q937.33,134.67 913.33,110.67 889.33,86.67 853.33,85.33L170.67,85.33z M170.67,0L853.33,0Q925.33,1.33 974,50 1022.67,98.67 1024,170.67L1024,853.33Q1022.67,925.33 974,974 925.33,1022.67 853.33,1024L170.67,1024Q98.67,1022.67 50,974 1.32999999999996,925.33 -4.2632564145606E-14,853.33L-4.2632564145606E-14,170.67Q1.32999999999996,98.67 50,50 98.67,1.32999999999996 170.67,-4.2632564145606E-14z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
|
||||
<DrawingImage x:Key="CheckBox.CheckedDrawingImage">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
|
||||
<DrawingGroup.Transform>
|
||||
<TranslateTransform X="4.2632564145606011E-14" Y="4.2632564145606011E-14" />
|
||||
</DrawingGroup.Transform>
|
||||
<GeometryDrawing Brush="#FF00A1D6" Geometry="F1 M1024,1024z M0,0z M384,608L306.67,530.67Q286.67,512 259.34,512 232,512 212,531.34 192,550.67 192,576.67 192,602.67 210.67,626.67L333.33,749.33Q354.67,769.33 384,769.33 413.33,769.33 434.67,749.33L813.33,370.67Q832,350.67 832,323.34 832,296 812,276 792,256 764.66,256 737.33,256 717.33,274.67L384,608z M170.67,0L853.33,0Q925.33,1.33 974,50 1022.67,98.67 1024,170.67L1024,853.33Q1022.67,925.33 974,974 925.33,1022.67 853.33,1024L170.67,1024Q98.67,1022.67 50,974 1.32999999999996,925.33 -4.2632564145606E-14,853.33L-4.2632564145606E-14,170.67Q1.32999999999996,98.67 50,50 98.67,1.32999999999996 170.67,-4.2632564145606E-14z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
|
||||
<Style x:Key="CheckBoxStyle" TargetType="{x:Type CheckBox}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="BorderBrush" Value="{x:Null}" />
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type CheckBox}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
Padding="0,0,5,0"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<Image
|
||||
x:Name="nameIcon"
|
||||
Width="14"
|
||||
Height="14"
|
||||
Margin="0,3"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center" />
|
||||
</Border>
|
||||
|
||||
<ContentPresenter
|
||||
Name="content"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter TargetName="nameIcon" Property="Source" Value="{StaticResource CheckBox.CheckedDrawingImage}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsChecked" Value="False">
|
||||
<Setter TargetName="nameIcon" Property="Source" Value="{StaticResource CheckBox.UncheckedDrawingImage}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
30
src/DownKyi/Themes/Styles/StyleImageBtn.xaml
Normal file
30
src/DownKyi/Themes/Styles/StyleImageBtn.xaml
Normal file
@ -0,0 +1,30 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Themes.Styles">
|
||||
|
||||
<Style x:Key="ImageBtnStyle" TargetType="{x:Type Button}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="BorderBrush" Value="{x:Null}" />
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<ContentPresenter
|
||||
Name="content"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
84
src/DownKyi/Themes/Styles/StyleListBox.xaml
Normal file
84
src/DownKyi/Themes/Styles/StyleListBox.xaml
Normal file
@ -0,0 +1,84 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<Style x:Key="LeftTabHeaderItemStyle" TargetType="{x:Type ListBoxItem}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ListBoxItem}">
|
||||
<Grid x:Name="panel" Height="60">
|
||||
<StackPanel
|
||||
Margin="20,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<ContentControl
|
||||
Width="24"
|
||||
Height="24"
|
||||
Margin="0,0,5,0">
|
||||
<ContentControl.Style>
|
||||
<Style TargetType="{x:Type ContentControl}">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Image}" Value="{x:Null}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ContentControl.Style>
|
||||
|
||||
<Path
|
||||
x:Name="image"
|
||||
Width="{Binding Image.Width}"
|
||||
Height="{Binding Image.Height}"
|
||||
Data="{Binding Image.Data}"
|
||||
Fill="{Binding Image.Fill}"
|
||||
Stretch="UniformToFill" />
|
||||
</ContentControl>
|
||||
<TextBlock
|
||||
x:Name="text"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Text="{Binding Title}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="False">
|
||||
<Setter TargetName="panel" Property="Background" Value="{DynamicResource BrushTabHeaderGrey}" />
|
||||
<Setter TargetName="text" Property="Foreground" Value="{DynamicResource BrushTextDark}" />
|
||||
<Setter TargetName="image" Property="Fill" Value="{Binding Image.Fill}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter TargetName="panel" Property="Background" Value="{DynamicResource BrushBackgroundGreyTranslucent2}" />
|
||||
<Setter TargetName="text" Property="Foreground" Value="{DynamicResource BrushPrimary}" />
|
||||
<Setter TargetName="image" Property="Fill" Value="{DynamicResource BrushPrimary}" />
|
||||
</Trigger>
|
||||
<Trigger Property="Selector.IsSelected" Value="true">
|
||||
<Setter TargetName="panel" Property="Background" Value="{DynamicResource BrushBackground}" />
|
||||
<Setter TargetName="text" Property="Foreground" Value="{DynamicResource BrushPrimary}" />
|
||||
<Setter TargetName="image" Property="Fill" Value="{DynamicResource BrushPrimary}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="LeftTabHeaderStyle" TargetType="{x:Type ListBox}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ListBox">
|
||||
<Border
|
||||
Padding="0"
|
||||
Background="{DynamicResource BrushTabHeaderGrey}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<ScrollViewer Focusable="False">
|
||||
<ItemsPresenter />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
4
src/DownKyi/Themes/Styles/StyleListView.xaml
Normal file
4
src/DownKyi/Themes/Styles/StyleListView.xaml
Normal file
@ -0,0 +1,4 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Themes.Styles" />
|
69
src/DownKyi/Themes/Styles/StyleRadio.xaml
Normal file
69
src/DownKyi/Themes/Styles/StyleRadio.xaml
Normal file
@ -0,0 +1,69 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<DrawingImage x:Key="Radio.UnselectedDrawingImage">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#FF000000" Geometry="F1 M1024,1024z M0,0z M512,0Q295,6 150.5,150.5 6,295 0,512 6,729 150.5,873.5 295,1018 512,1024 729,1018 873.5,873.5 1018,729 1024,512 1018,295 873.5,150.5 729,6 512,0z M512,960Q320,955 194.5,829.5 69,704 64,512 69,320 194.5,194.5 320,69 512,64 704,69 829.5,194.5 955,320 960,512 955,704 829.5,829.5 704,955 512,960z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
|
||||
<DrawingImage x:Key="Radio.SelectedDrawingImage">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#FF00A1D6" Geometry="F1 M1024,1024z M0,0z M512,0Q295,6 150.5,150.5 6,295 0,512 6,729 150.5,873.5 295,1018 512,1024 729,1018 873.5,873.5 1018,729 1024,512 1018,295 873.5,150.5 729,6 512,0z M512,960Q320,955 194.5,829.5 69,704 64,512 69,320 194.5,194.5 320,69 512,64 704,69 829.5,194.5 955,320 960,512 955,704 829.5,829.5 704,955 512,960z M256,512Q259,621 331,693 403,765 512,768 621,765 693,693 765,621 768,512 765,403 693,331 621,259 512,256 403,259 331,331 259,403 256,512z" />
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
|
||||
<Style x:Key="RadioStyle" TargetType="{x:Type RadioButton}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="BorderBrush" Value="{x:Null}" />
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type RadioButton}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
Padding="0,0,5,0"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<Image
|
||||
x:Name="nameIcon"
|
||||
Width="14"
|
||||
Height="14"
|
||||
Margin="0,3"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center" />
|
||||
</Border>
|
||||
|
||||
<ContentPresenter
|
||||
Name="content"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter TargetName="nameIcon" Property="Source" Value="{StaticResource Radio.SelectedDrawingImage}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsChecked" Value="False">
|
||||
<Setter TargetName="nameIcon" Property="Source" Value="{StaticResource Radio.UnselectedDrawingImage}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
68
src/DownKyi/Themes/Styles/StyleSystemBtn.xaml
Normal file
68
src/DownKyi/Themes/Styles/StyleSystemBtn.xaml
Normal file
@ -0,0 +1,68 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Themes.Styles">
|
||||
|
||||
<Style x:Key="SystemBtnStyle" TargetType="{x:Type Button}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="BorderBrush" Value="{x:Null}" />
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<ContentPresenter
|
||||
Name="content"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</Border>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource BrushSystemBtnHover}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource BrushSystemBtnPressed}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style
|
||||
x:Key="CloseBtnStyle"
|
||||
BasedOn="{StaticResource SystemBtnStyle}"
|
||||
TargetType="{x:Type Button}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<ContentPresenter
|
||||
Name="content"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</Border>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource BrushCloseBtnHover}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource BrushCloseBtnPressed}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
28
src/DownKyi/Themes/ThemeDefault.xaml
Normal file
28
src/DownKyi/Themes/ThemeDefault.xaml
Normal file
@ -0,0 +1,28 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Themes">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<!-- 每个主题都相同 -->
|
||||
<ResourceDictionary Source="ColorBrush.xaml" />
|
||||
|
||||
<!-- 根据实际需要调整 -->
|
||||
<ResourceDictionary Source="Colors/ColorDefault.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleBtn.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleImageBtn.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleSystemBtn.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleCheckBox.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleListBox.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleListView.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleRadio.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<!-- 设置字体 -->
|
||||
<Style TargetType="{x:Type TextElement}">
|
||||
<Setter Property="FontFamily" Value="Microsoft YaHei UI, Source Han Sans Normal" />
|
||||
</Style>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="FontFamily" Value="Microsoft YaHei UI, Source Han Sans Normal" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
28
src/DownKyi/Themes/ThemeDiy.xaml
Normal file
28
src/DownKyi/Themes/ThemeDiy.xaml
Normal file
@ -0,0 +1,28 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DownKyi.Themes">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<!-- 每个主题都相同 -->
|
||||
<ResourceDictionary Source="ColorBrush.xaml" />
|
||||
|
||||
<!-- 根据实际需要调整 -->
|
||||
<ResourceDictionary Source="Colors/ColorDiy.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleBtn.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleImageBtn.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleSystemBtn.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleCheckBox.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleListBox.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleListView.xaml" />
|
||||
<ResourceDictionary Source="Styles/StyleRadio.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<!-- 设置字体 -->
|
||||
<Style TargetType="{x:Type TextElement}">
|
||||
<Setter Property="FontFamily" Value="Microsoft YaHei UI, Source Han Sans Normal" />
|
||||
</Style>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="FontFamily" Value="Microsoft YaHei UI, Source Han Sans Normal" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
45
src/DownKyi/Utils/ClipboardHooker.cs
Normal file
45
src/DownKyi/Utils/ClipboardHooker.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
|
||||
namespace DownKyi.Utils
|
||||
{
|
||||
public class ClipboardHooker : IDisposable
|
||||
{
|
||||
private const int WM_CLIPBOARDUPDATE = 0x031D;
|
||||
|
||||
[DllImport("User32.dll")]
|
||||
private static extern bool AddClipboardFormatListener(IntPtr hwnd);
|
||||
|
||||
private readonly HwndSource _hwndSource = null;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_hwndSource?.Dispose();
|
||||
}
|
||||
|
||||
public ClipboardHooker(Window window)
|
||||
{
|
||||
WindowInteropHelper helper = new WindowInteropHelper(window);
|
||||
_hwndSource = HwndSource.FromHwnd(helper.Handle);
|
||||
bool r = AddClipboardFormatListener(_hwndSource.Handle);
|
||||
if (r)
|
||||
{
|
||||
_hwndSource.AddHook(new HwndSourceHook(OnHooked));
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr OnHooked(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||
{
|
||||
if (msg == WM_CLIPBOARDUPDATE)
|
||||
{
|
||||
ClipboardUpdated?.Invoke(this, EventArgs.Empty);
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
public event EventHandler ClipboardUpdated;
|
||||
}
|
||||
}
|
26
src/DownKyi/Utils/DialogUtils.cs
Normal file
26
src/DownKyi/Utils/DialogUtils.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DownKyi.Utils
|
||||
{
|
||||
public static class DialogUtils
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 弹出选择文件夹弹窗
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string SetDownloadDirectory()
|
||||
{
|
||||
// 选择文件夹
|
||||
FolderBrowserDialog dialog = new FolderBrowserDialog
|
||||
{
|
||||
Description = DictionaryResource.GetString("SelectDirectory")
|
||||
};
|
||||
|
||||
DialogResult showDialog = dialog.ShowDialog();
|
||||
return showDialog == DialogResult.OK || showDialog == DialogResult.Yes
|
||||
? string.IsNullOrEmpty(dialog.SelectedPath) ? "" : dialog.SelectedPath : "";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
83
src/DownKyi/Utils/DictionaryResource.cs
Normal file
83
src/DownKyi/Utils/DictionaryResource.cs
Normal file
@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace DownKyi.Utils
|
||||
{
|
||||
public static class DictionaryResource
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 从资源获取颜色的16进制字符串
|
||||
/// </summary>
|
||||
/// <param name="resourceKey"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetColor(string resourceKey)
|
||||
{
|
||||
Color color = (Color)Application.Current.Resources[resourceKey];
|
||||
return color.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从资源获取字符串
|
||||
/// </summary>
|
||||
/// <param name="resourceKey"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetString(string resourceKey)
|
||||
{
|
||||
return (string)Application.Current.Resources[resourceKey];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据languageCode切换界面语言
|
||||
/// </summary>
|
||||
/// <param name="languageCode">语言-国家代码</param>
|
||||
public static void LoadLanguage(string languageCode)
|
||||
{
|
||||
LoadXamlDictionary(languageCode, "Languages");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换主题
|
||||
/// </summary>
|
||||
/// <param name="theme">主题</param>
|
||||
public static void LoadTheme(string theme)
|
||||
{
|
||||
LoadXamlDictionary(theme, "Themes");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更换xaml资源字典
|
||||
/// </summary>
|
||||
/// <param name="fileName">xaml文件名,不包含扩展名</param>
|
||||
/// <param name="package">文件所在包(路径)</param>
|
||||
private static void LoadXamlDictionary(string fileName, string package)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fileName) == false)
|
||||
{
|
||||
var dictionariesToRemove = new List<ResourceDictionary>();
|
||||
|
||||
foreach (var dictionary in Application.Current.Resources.MergedDictionaries)
|
||||
{
|
||||
if (dictionary.Source.ToString().Contains($"{package}"))
|
||||
{
|
||||
dictionariesToRemove.Add(dictionary);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var item in dictionariesToRemove)
|
||||
{
|
||||
Application.Current.Resources.MergedDictionaries.Remove(item);
|
||||
}
|
||||
|
||||
var languageDictionary = new ResourceDictionary()
|
||||
{
|
||||
Source = new Uri($"pack://application:,,,/DownKyi;component/{package}/{fileName}.xaml")
|
||||
};
|
||||
|
||||
Application.Current.Resources.MergedDictionaries.Add(languageDictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
48
src/DownKyi/ViewModels/BaseViewModel.cs
Normal file
48
src/DownKyi/ViewModels/BaseViewModel.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Regions;
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace DownKyi.ViewModels
|
||||
{
|
||||
public class BaseViewModel : BindableBase, INavigationAware
|
||||
{
|
||||
protected readonly IEventAggregator eventAggregator;
|
||||
protected string ParentView = string.Empty;
|
||||
|
||||
public BaseViewModel(IEventAggregator eventAggregator)
|
||||
{
|
||||
this.eventAggregator = eventAggregator;
|
||||
}
|
||||
|
||||
public bool IsNavigationTarget(NavigationContext navigationContext)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void OnNavigatedFrom(NavigationContext navigationContext)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
string viewName = navigationContext.Parameters.GetValue<string>("Parent");
|
||||
if (viewName != null)
|
||||
{
|
||||
ParentView = viewName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 异步修改绑定到UI的属性
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
protected void PropertyChangeAsync(Action callback)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(callback);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
134
src/DownKyi/ViewModels/Dialogs/BaseDialogViewModel.cs
Normal file
134
src/DownKyi/ViewModels/Dialogs/BaseDialogViewModel.cs
Normal file
@ -0,0 +1,134 @@
|
||||
using DownKyi.Images;
|
||||
using DownKyi.Models;
|
||||
using DownKyi.Utils;
|
||||
using Prism.Commands;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Services.Dialogs;
|
||||
using System;
|
||||
|
||||
namespace DownKyi.ViewModels.Dialogs
|
||||
{
|
||||
public class BaseDialogViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
#region 页面属性申明
|
||||
|
||||
private string title;
|
||||
public string Title
|
||||
{
|
||||
get { return title; }
|
||||
set { SetProperty(ref title, value); }
|
||||
}
|
||||
|
||||
private VectorImage closeIcon;
|
||||
public VectorImage CloseIcon
|
||||
{
|
||||
get { return closeIcon; }
|
||||
set { SetProperty(ref closeIcon, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public BaseDialogViewModel()
|
||||
{
|
||||
#region 属性初始化
|
||||
|
||||
Title = new AppInfo().Name;
|
||||
CloseIcon = new VectorImage
|
||||
{
|
||||
Height = SystemIcon.Instance().Close.Height,
|
||||
Width = SystemIcon.Instance().Close.Width,
|
||||
Data = SystemIcon.Instance().Close.Data,
|
||||
Fill = SystemIcon.Instance().Close.Fill
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// 鼠标进入关闭按钮事件
|
||||
private DelegateCommand closeEnterCommand;
|
||||
public DelegateCommand CloseEnterCommand => closeEnterCommand ?? (closeEnterCommand = new DelegateCommand(ExecuteCloseEnterCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 鼠标进入关闭按钮事件
|
||||
/// </summary>
|
||||
private void ExecuteCloseEnterCommand()
|
||||
{
|
||||
SetEnterStyle(CloseIcon);
|
||||
}
|
||||
|
||||
// 鼠标离开关闭按钮事件
|
||||
private DelegateCommand closeLeaveCommand;
|
||||
public DelegateCommand CloseLeaveCommand => closeLeaveCommand ?? (closeLeaveCommand = new DelegateCommand(ExecuteCloseLeaveCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 鼠标离开关闭按钮事件
|
||||
/// </summary>
|
||||
private void ExecuteCloseLeaveCommand()
|
||||
{
|
||||
SetLeaveStyle(CloseIcon);
|
||||
}
|
||||
|
||||
// 关闭窗口事件
|
||||
private DelegateCommand closeCommand;
|
||||
public DelegateCommand CloseCommand => closeCommand ?? (closeCommand = new DelegateCommand(ExecuteCloseCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 关闭窗口事件
|
||||
/// </summary>
|
||||
private void ExecuteCloseCommand()
|
||||
{
|
||||
ButtonResult result = ButtonResult.Cancel;
|
||||
RaiseRequestClose(new DialogResult(result));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 鼠标进入系统按钮时的图标样式
|
||||
/// </summary>
|
||||
/// <param name="icon">图标</param>
|
||||
private void SetEnterStyle(VectorImage icon)
|
||||
{
|
||||
icon.Fill = DictionaryResource.GetColor("ColorSystemBtnTint");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 鼠标离开系统按钮时的图标样式
|
||||
/// </summary>
|
||||
/// <param name="icon">图标</param>
|
||||
private void SetLeaveStyle(VectorImage icon)
|
||||
{
|
||||
icon.Fill = DictionaryResource.GetColor("ColorSystemBtnTintDark");
|
||||
}
|
||||
|
||||
#region 接口实现
|
||||
|
||||
//触发窗体关闭事件
|
||||
public virtual void RaiseRequestClose(IDialogResult dialogResult)
|
||||
{
|
||||
RequestClose?.Invoke(dialogResult);
|
||||
}
|
||||
|
||||
public event Action<IDialogResult> RequestClose;
|
||||
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
203
src/DownKyi/ViewModels/Dialogs/ViewDirectorySelectorViewModel.cs
Normal file
203
src/DownKyi/ViewModels/Dialogs/ViewDirectorySelectorViewModel.cs
Normal file
@ -0,0 +1,203 @@
|
||||
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 ViewDirectorySelectorViewModel : BaseDialogViewModel
|
||||
{
|
||||
public const string Tag = "DialogDirectorySelector";
|
||||
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);
|
||||
|
||||
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); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewDirectorySelectorViewModel(IEventAggregator eventAggregator)
|
||||
{
|
||||
this.eventAggregator = eventAggregator;
|
||||
|
||||
#region 属性初始化
|
||||
|
||||
Title = DictionaryResource.GetString("DownloadDirectorySelector");
|
||||
|
||||
CloudDownloadIcon = NormalIcon.Instance().CloudDownload;
|
||||
CloudDownloadIcon.Fill = DictionaryResource.GetColor("ColorPrimary");
|
||||
|
||||
FolderIcon = NormalIcon.Instance().Folder;
|
||||
FolderIcon.Fill = DictionaryResource.GetColor("ColorPrimary");
|
||||
|
||||
#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 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 }
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
120
src/DownKyi/ViewModels/Dialogs/ViewParsingSelectorViewModel.cs
Normal file
120
src/DownKyi/ViewModels/Dialogs/ViewParsingSelectorViewModel.cs
Normal file
@ -0,0 +1,120 @@
|
||||
using DownKyi.Core.Settings;
|
||||
using DownKyi.Utils;
|
||||
using Prism.Commands;
|
||||
using Prism.Services.Dialogs;
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace DownKyi.ViewModels.Dialogs
|
||||
{
|
||||
public class ViewParsingSelectorViewModel : BaseDialogViewModel
|
||||
{
|
||||
public const string Tag = "DialogParsingSelector";
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private bool isParseDefault;
|
||||
public bool IsParseDefault
|
||||
{
|
||||
get { return isParseDefault; }
|
||||
set { SetProperty(ref isParseDefault, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewParsingSelectorViewModel()
|
||||
{
|
||||
#region 属性初始化
|
||||
|
||||
Title = DictionaryResource.GetString("ParsingSelector");
|
||||
|
||||
// 解析范围
|
||||
ParseScope parseScope = SettingsManager.GetInstance().GetParseScope();
|
||||
IsParseDefault = parseScope != ParseScope.NONE;
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// 解析当前项事件
|
||||
private DelegateCommand parseSelectedItemCommand;
|
||||
public DelegateCommand ParseSelectedItemCommand => parseSelectedItemCommand ?? (parseSelectedItemCommand = new DelegateCommand(ExecuteParseSelectedItemCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 解析当前项事件
|
||||
/// </summary>
|
||||
private void ExecuteParseSelectedItemCommand()
|
||||
{
|
||||
SetParseScopeSetting(ParseScope.SELECTED_ITEM);
|
||||
|
||||
ButtonResult result = ButtonResult.OK;
|
||||
IDialogParameters parameters = new DialogParameters
|
||||
{
|
||||
{ "parseScope", ParseScope.SELECTED_ITEM }
|
||||
};
|
||||
|
||||
RaiseRequestClose(new DialogResult(result, parameters));
|
||||
}
|
||||
|
||||
// 解析当前页视频事件
|
||||
private DelegateCommand parseCurrentSectionCommand;
|
||||
public DelegateCommand ParseCurrentSectionCommand => parseCurrentSectionCommand ?? (parseCurrentSectionCommand = new DelegateCommand(ExecuteParseCurrentSectionCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 解析当前页视频事件
|
||||
/// </summary>
|
||||
private void ExecuteParseCurrentSectionCommand()
|
||||
{
|
||||
SetParseScopeSetting(ParseScope.CURRENT_SECTION);
|
||||
|
||||
ButtonResult result = ButtonResult.OK;
|
||||
IDialogParameters parameters = new DialogParameters
|
||||
{
|
||||
{ "parseScope", ParseScope.CURRENT_SECTION }
|
||||
};
|
||||
|
||||
RaiseRequestClose(new DialogResult(result, parameters));
|
||||
}
|
||||
|
||||
// 解析所有视频事件
|
||||
private DelegateCommand parseAllCommand;
|
||||
public DelegateCommand ParseAllCommand => parseAllCommand ?? (parseAllCommand = new DelegateCommand(ExecuteParseAllCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 解析所有视频事件
|
||||
/// </summary>
|
||||
private void ExecuteParseAllCommand()
|
||||
{
|
||||
SetParseScopeSetting(ParseScope.ALL);
|
||||
|
||||
ButtonResult result = ButtonResult.OK;
|
||||
IDialogParameters parameters = new DialogParameters
|
||||
{
|
||||
{ "parseScope", ParseScope.ALL }
|
||||
};
|
||||
|
||||
RaiseRequestClose(new DialogResult(result, parameters));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 写入设置
|
||||
/// </summary>
|
||||
/// <param name="parseScope"></param>
|
||||
private void SetParseScopeSetting(ParseScope parseScope)
|
||||
{
|
||||
if (IsParseDefault)
|
||||
{
|
||||
SettingsManager.GetInstance().SetParseScope(parseScope);
|
||||
}
|
||||
else
|
||||
{
|
||||
SettingsManager.GetInstance().SetParseScope(ParseScope.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DownKyi.ViewModels.DownloadManager
|
||||
{
|
||||
public class ViewDownloadFinishedViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageDownloadManagerDownloadFinished";
|
||||
|
||||
public ViewDownloadFinishedViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DownKyi.ViewModels.DownloadManager
|
||||
{
|
||||
public class ViewDownloadingViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageDownloadManagerDownloading";
|
||||
|
||||
public ViewDownloadingViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
385
src/DownKyi/ViewModels/MainWindowViewModel.cs
Normal file
385
src/DownKyi/ViewModels/MainWindowViewModel.cs
Normal file
@ -0,0 +1,385 @@
|
||||
using DownKyi.Core.BiliApi.BiliUtils;
|
||||
using DownKyi.Core.Logging;
|
||||
using DownKyi.Core.Settings;
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Images;
|
||||
using DownKyi.Utils;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Regions;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace DownKyi.ViewModels
|
||||
{
|
||||
public class MainWindowViewModel : BindableBase
|
||||
{
|
||||
private readonly IEventAggregator eventAggregator;
|
||||
private ClipboardHooker clipboardHooker;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private string title;
|
||||
public string Title
|
||||
{
|
||||
get { return title; }
|
||||
set { SetProperty(ref title, value); }
|
||||
}
|
||||
|
||||
private WindowState winState;
|
||||
public WindowState WinState
|
||||
{
|
||||
get { return winState; }
|
||||
set
|
||||
{
|
||||
if (value == WindowState.Maximized)
|
||||
{
|
||||
ResizeIcon = SystemIcon.Instance().Restore;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResizeIcon = SystemIcon.Instance().Maximize;
|
||||
}
|
||||
SetLeaveStyle(ResizeIcon);
|
||||
|
||||
SetProperty(ref winState, value);
|
||||
}
|
||||
}
|
||||
|
||||
private VectorImage minimizeIcon;
|
||||
public VectorImage MinimizeIcon
|
||||
{
|
||||
get { return minimizeIcon; }
|
||||
set { SetProperty(ref minimizeIcon, value); }
|
||||
}
|
||||
|
||||
private VectorImage resizeIcon;
|
||||
public VectorImage ResizeIcon
|
||||
{
|
||||
get { return resizeIcon; }
|
||||
set { SetProperty(ref resizeIcon, value); }
|
||||
}
|
||||
|
||||
private VectorImage closeIcon;
|
||||
public VectorImage CloseIcon
|
||||
{
|
||||
get { return closeIcon; }
|
||||
set { SetProperty(ref closeIcon, value); }
|
||||
}
|
||||
|
||||
private VectorImage skinIcon;
|
||||
public VectorImage SkinIcon
|
||||
{
|
||||
get { return skinIcon; }
|
||||
set { SetProperty(ref skinIcon, value); }
|
||||
}
|
||||
|
||||
private Visibility messageVisibility = Visibility.Hidden;
|
||||
public Visibility MessageVisibility
|
||||
{
|
||||
get { return messageVisibility; }
|
||||
set { SetProperty(ref messageVisibility, value); }
|
||||
}
|
||||
|
||||
private string message;
|
||||
public string Message
|
||||
{
|
||||
get { return message; }
|
||||
set { SetProperty(ref message, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public MainWindowViewModel(IRegionManager regionManager, IEventAggregator eventAggregator)
|
||||
{
|
||||
this.eventAggregator = eventAggregator;
|
||||
|
||||
#region 属性初始化
|
||||
|
||||
Window mainWindow = Application.Current.MainWindow;
|
||||
|
||||
WinState = WindowState.Normal;
|
||||
|
||||
MinimizeIcon = SystemIcon.Instance().Minimize;
|
||||
ResizeIcon = SystemIcon.Instance().Maximize;
|
||||
CloseIcon = SystemIcon.Instance().Close;
|
||||
SkinIcon = SystemIcon.Instance().Skin;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 订阅
|
||||
|
||||
// 订阅导航事件
|
||||
eventAggregator.GetEvent<NavigationEvent>().Subscribe((view) =>
|
||||
{
|
||||
var param = new NavigationParameters
|
||||
{
|
||||
{ "Parent", view.ParentViewName },
|
||||
{ "Parameter", view.Parameter }
|
||||
};
|
||||
regionManager.RequestNavigate("ContentRegion", view.ViewName, param);
|
||||
});
|
||||
|
||||
// 订阅消息发送事件
|
||||
string oldMessage;
|
||||
eventAggregator.GetEvent<MessageEvent>().Subscribe((message) =>
|
||||
{
|
||||
MessageVisibility = Visibility.Visible;
|
||||
|
||||
oldMessage = Message;
|
||||
Message = message;
|
||||
int sleep = 2000;
|
||||
if (oldMessage == Message) { sleep = 1500; }
|
||||
|
||||
Thread.Sleep(sleep);
|
||||
|
||||
MessageVisibility = Visibility.Hidden;
|
||||
}, ThreadOption.BackgroundThread);
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令定义
|
||||
|
||||
// window加载后执行的事件
|
||||
LoadedCommand = new DelegateCommand(() =>
|
||||
{
|
||||
clipboardHooker = new ClipboardHooker(Application.Current.MainWindow);
|
||||
clipboardHooker.ClipboardUpdated += OnClipboardUpdated;
|
||||
|
||||
var param = new NavigationParameters
|
||||
{
|
||||
{ "Parent", "" },
|
||||
{ "Parameter", "start" }
|
||||
};
|
||||
regionManager.RequestNavigate("ContentRegion", ViewIndexViewModel.Tag, param);
|
||||
});
|
||||
|
||||
// 顶部caption栏的点击事件,包括双击和拖动
|
||||
int times = 0;
|
||||
DragMoveCommand = new DelegateCommand(() =>
|
||||
{
|
||||
// caption 双击事件
|
||||
times += 1;
|
||||
DispatcherTimer timer = new DispatcherTimer
|
||||
{
|
||||
Interval = new TimeSpan(0, 0, 0, 0, 300)
|
||||
};
|
||||
timer.Tick += (s, e) => { timer.IsEnabled = false; times = 0; };
|
||||
timer.IsEnabled = true;
|
||||
|
||||
if (times % 2 == 0)
|
||||
{
|
||||
timer.IsEnabled = false;
|
||||
times = 0;
|
||||
WinState = WinState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
|
||||
}
|
||||
|
||||
// caption 拖动事件
|
||||
try
|
||||
{
|
||||
mainWindow.DragMove();
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
|
||||
// 最小化窗口事件
|
||||
MinimizeCommand = new DelegateCommand(() =>
|
||||
{
|
||||
mainWindow.WindowState = WindowState.Minimized;
|
||||
});
|
||||
MinimizeEnterCommand = new DelegateCommand(() =>
|
||||
{
|
||||
SetEnterStyle(MinimizeIcon);
|
||||
});
|
||||
MinimizeLeaveCommand = new DelegateCommand(() =>
|
||||
{
|
||||
SetLeaveStyle(MinimizeIcon);
|
||||
});
|
||||
|
||||
// 最大化/还原窗口事件
|
||||
ResizeCommand = new DelegateCommand(() =>
|
||||
{
|
||||
WinState = WinState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
|
||||
});
|
||||
ResizeEnterCommand = new DelegateCommand(() =>
|
||||
{
|
||||
SetEnterStyle(ResizeIcon);
|
||||
});
|
||||
ResizeLeaveCommand = new DelegateCommand(() =>
|
||||
{
|
||||
SetLeaveStyle(ResizeIcon);
|
||||
});
|
||||
|
||||
// 关闭窗口事件
|
||||
CloseCommand = new DelegateCommand(() =>
|
||||
{
|
||||
if (clipboardHooker != null)
|
||||
{
|
||||
clipboardHooker.ClipboardUpdated -= OnClipboardUpdated;
|
||||
clipboardHooker.Dispose();
|
||||
}
|
||||
|
||||
mainWindow.Close();
|
||||
});
|
||||
CloseEnterCommand = new DelegateCommand(() =>
|
||||
{
|
||||
SetEnterStyle(CloseIcon);
|
||||
});
|
||||
CloseLeaveCommand = new DelegateCommand(() =>
|
||||
{
|
||||
SetLeaveStyle(CloseIcon);
|
||||
});
|
||||
|
||||
// 皮肤按钮点击事件
|
||||
SkinCommand = new DelegateCommand(() =>
|
||||
{
|
||||
// 设置主题
|
||||
DictionaryResource.LoadTheme("ThemeDiy");
|
||||
|
||||
// 切换语言
|
||||
DictionaryResource.LoadLanguage("en_US");
|
||||
});
|
||||
SkinEnterCommand = new DelegateCommand(() =>
|
||||
{
|
||||
SetEnterStyle(SkinIcon);
|
||||
});
|
||||
SkinLeaveCommand = new DelegateCommand(() =>
|
||||
{
|
||||
SetLeaveStyle(SkinIcon);
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
#region 命令申明
|
||||
|
||||
public DelegateCommand LoadedCommand { get; private set; }
|
||||
public DelegateCommand DragMoveCommand { get; private set; }
|
||||
public DelegateCommand MinimizeCommand { get; private set; }
|
||||
public DelegateCommand MinimizeEnterCommand { get; private set; }
|
||||
public DelegateCommand MinimizeLeaveCommand { get; private set; }
|
||||
public DelegateCommand ResizeCommand { get; private set; }
|
||||
public DelegateCommand ResizeEnterCommand { get; private set; }
|
||||
public DelegateCommand ResizeLeaveCommand { get; private set; }
|
||||
public DelegateCommand CloseCommand { get; private set; }
|
||||
public DelegateCommand CloseEnterCommand { get; private set; }
|
||||
public DelegateCommand CloseLeaveCommand { get; private set; }
|
||||
public DelegateCommand SkinCommand { get; private set; }
|
||||
public DelegateCommand SkinEnterCommand { get; private set; }
|
||||
public DelegateCommand SkinLeaveCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 鼠标进入系统按钮时的图标样式
|
||||
/// </summary>
|
||||
/// <param name="icon">图标</param>
|
||||
private void SetEnterStyle(VectorImage icon)
|
||||
{
|
||||
icon.Fill = DictionaryResource.GetColor("ColorSystemBtnTint");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 鼠标离开系统按钮时的图标样式
|
||||
/// </summary>
|
||||
/// <param name="icon">图标</param>
|
||||
private void SetLeaveStyle(VectorImage icon)
|
||||
{
|
||||
icon.Fill = DictionaryResource.GetColor("ColorSystemBtnTintDark");
|
||||
}
|
||||
|
||||
private void OnClipboardUpdated(object sender, EventArgs e)
|
||||
{
|
||||
AllowStatus isListenClipboard = SettingsManager.GetInstance().IsListenClipboard();
|
||||
if (isListenClipboard != AllowStatus.YES)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string input;
|
||||
try
|
||||
{
|
||||
IDataObject data = Clipboard.GetDataObject();
|
||||
string[] fs = data.GetFormats();
|
||||
input = data.GetData(fs[0]).ToString();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Console.WriteLine("OnClipboardUpdated()发生异常: {0}", exc);
|
||||
LogManager.Error("OnClipboardUpdated", exc);
|
||||
return;
|
||||
}
|
||||
|
||||
// 视频
|
||||
if (ParseEntrance.IsAvId(input))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.VideoUrl}{input.ToLower()}");
|
||||
}
|
||||
else if (ParseEntrance.IsAvUrl(input))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, input);
|
||||
}
|
||||
else if (ParseEntrance.IsBvId(input))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.VideoUrl}{input}");
|
||||
}
|
||||
else if (ParseEntrance.IsBvUrl(input))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, input);
|
||||
}
|
||||
// 番剧(电影、电视剧)
|
||||
else if (ParseEntrance.IsBangumiSeasonId(input))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiUrl}{input.ToLower()}");
|
||||
}
|
||||
else if (ParseEntrance.IsBangumiSeasonUrl(input))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, input);
|
||||
}
|
||||
else if (ParseEntrance.IsBangumiEpisodeId(input))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiUrl}{input.ToLower()}");
|
||||
}
|
||||
else if (ParseEntrance.IsBangumiEpisodeUrl(input))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, input);
|
||||
}
|
||||
else if (ParseEntrance.IsBangumiMediaId(input))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiMediaUrl}{input.ToLower()}");
|
||||
}
|
||||
else if (ParseEntrance.IsBangumiMediaUrl(input))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, input);
|
||||
}
|
||||
// 课程
|
||||
else if (ParseEntrance.IsCheeseSeasonUrl(input) || ParseEntrance.IsCheeseEpisodeUrl(input))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.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
|
||||
{
|
||||
ViewName = viewName,
|
||||
ParentViewName = ViewIndexViewModel.Tag,
|
||||
Parameter = param
|
||||
};
|
||||
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
269
src/DownKyi/ViewModels/Settings/ViewAboutViewModel.cs
Normal file
269
src/DownKyi/ViewModels/Settings/ViewAboutViewModel.cs
Normal file
@ -0,0 +1,269 @@
|
||||
using DownKyi.Core.Settings;
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Models;
|
||||
using DownKyi.Utils;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
|
||||
namespace DownKyi.ViewModels.Settings
|
||||
{
|
||||
public class ViewAboutViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageSettingsAbout";
|
||||
|
||||
private bool isOnNavigatedTo;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private string appName;
|
||||
public string AppName
|
||||
{
|
||||
get { return appName; }
|
||||
set { SetProperty(ref appName, value); }
|
||||
}
|
||||
|
||||
private string appVersion;
|
||||
public string AppVersion
|
||||
{
|
||||
get { return appVersion; }
|
||||
set { SetProperty(ref appVersion, value); }
|
||||
}
|
||||
|
||||
private bool isReceiveBetaVersion;
|
||||
public bool IsReceiveBetaVersion
|
||||
{
|
||||
get { return isReceiveBetaVersion; }
|
||||
set { SetProperty(ref isReceiveBetaVersion, value); }
|
||||
}
|
||||
|
||||
private bool autoUpdateWhenLaunch;
|
||||
public bool AutoUpdateWhenLaunch
|
||||
{
|
||||
get { return autoUpdateWhenLaunch; }
|
||||
set { SetProperty(ref autoUpdateWhenLaunch, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewAboutViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
|
||||
#region 属性初始化
|
||||
|
||||
AppInfo app = new AppInfo();
|
||||
AppName = app.Name;
|
||||
AppVersion = app.VersionName;
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导航到VideoDetail页面时执行
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
isOnNavigatedTo = true;
|
||||
|
||||
// 是否接收测试版更新
|
||||
var isReceiveBetaVersion = SettingsManager.GetInstance().IsReceiveBetaVersion();
|
||||
IsReceiveBetaVersion = isReceiveBetaVersion == AllowStatus.YES;
|
||||
|
||||
// 是否在启动时自动检查更新
|
||||
var isAutoUpdateWhenLaunch = SettingsManager.GetInstance().GetAutoUpdateWhenLaunch();
|
||||
AutoUpdateWhenLaunch = isAutoUpdateWhenLaunch == AllowStatus.YES;
|
||||
|
||||
isOnNavigatedTo = false;
|
||||
}
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// 访问主页事件
|
||||
private DelegateCommand appNameCommand;
|
||||
public DelegateCommand AppNameCommand => appNameCommand ?? (appNameCommand = new DelegateCommand(ExecuteAppNameCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 访问主页事件
|
||||
/// </summary>
|
||||
private void ExecuteAppNameCommand()
|
||||
{
|
||||
System.Diagnostics.Process.Start("https://github.com/leiurayer/downkyi");
|
||||
}
|
||||
|
||||
// 检查更新事件
|
||||
private DelegateCommand checkUpdateCommand;
|
||||
public DelegateCommand CheckUpdateCommand => checkUpdateCommand ?? (checkUpdateCommand = new DelegateCommand(ExecuteCheckUpdateCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 检查更新事件
|
||||
/// </summary>
|
||||
private void ExecuteCheckUpdateCommand()
|
||||
{
|
||||
//eventAggregator.GetEvent<MessageEvent>().Publish("开始查找更新,请稍后~");
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish("请前往主页下载最新版~");
|
||||
}
|
||||
|
||||
// 意见反馈事件
|
||||
private DelegateCommand feedbackCommand;
|
||||
public DelegateCommand FeedbackCommand => feedbackCommand ?? (feedbackCommand = new DelegateCommand(ExecuteFeedbackCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 意见反馈事件
|
||||
/// </summary>
|
||||
private void ExecuteFeedbackCommand()
|
||||
{
|
||||
System.Diagnostics.Process.Start("https://github.com/leiurayer/downkyi/issues");
|
||||
}
|
||||
|
||||
// 是否接收测试版更新事件
|
||||
private DelegateCommand receiveBetaVersionCommand;
|
||||
public DelegateCommand ReceiveBetaVersionCommand => receiveBetaVersionCommand ?? (receiveBetaVersionCommand = new DelegateCommand(ExecuteReceiveBetaVersionCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 是否接收测试版更新事件
|
||||
/// </summary>
|
||||
private void ExecuteReceiveBetaVersionCommand()
|
||||
{
|
||||
AllowStatus isReceiveBetaVersion = IsReceiveBetaVersion ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().IsReceiveBetaVersion(isReceiveBetaVersion);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 是否在启动时自动检查更新事件
|
||||
private DelegateCommand autoUpdateWhenLaunchCommand;
|
||||
public DelegateCommand AutoUpdateWhenLaunchCommand => autoUpdateWhenLaunchCommand ?? (autoUpdateWhenLaunchCommand = new DelegateCommand(ExecuteAutoUpdateWhenLaunchCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 是否在启动时自动检查更新事件
|
||||
/// </summary>
|
||||
private void ExecuteAutoUpdateWhenLaunchCommand()
|
||||
{
|
||||
AllowStatus isAutoUpdateWhenLaunch = AutoUpdateWhenLaunch ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAutoUpdateWhenLaunch(isAutoUpdateWhenLaunch);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Brotli.NET许可证查看事件
|
||||
private DelegateCommand brotliLicenseCommand;
|
||||
public DelegateCommand BrotliLicenseCommand => brotliLicenseCommand ?? (brotliLicenseCommand = new DelegateCommand(ExecuteBrotliLicenseCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Brotli.NET许可证查看事件
|
||||
/// </summary>
|
||||
private void ExecuteBrotliLicenseCommand()
|
||||
{
|
||||
System.Diagnostics.Process.Start("https://licenses.nuget.org/MIT");
|
||||
}
|
||||
|
||||
// Google.Protobuf许可证查看事件
|
||||
private DelegateCommand protobufLicenseCommand;
|
||||
public DelegateCommand ProtobufLicenseCommand => protobufLicenseCommand ?? (protobufLicenseCommand = new DelegateCommand(ExecuteProtobufLicenseCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Google.Protobuf许可证查看事件
|
||||
/// </summary>
|
||||
private void ExecuteProtobufLicenseCommand()
|
||||
{
|
||||
System.Diagnostics.Process.Start("https://github.com/protocolbuffers/protobuf/blob/master/LICENSE");
|
||||
}
|
||||
|
||||
// Newtonsoft.Json许可证查看事件
|
||||
private DelegateCommand newtonsoftLicenseCommand;
|
||||
public DelegateCommand NewtonsoftLicenseCommand => newtonsoftLicenseCommand ?? (newtonsoftLicenseCommand = new DelegateCommand(ExecuteNewtonsoftLicenseCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Newtonsoft.Json许可证查看事件
|
||||
/// </summary>
|
||||
private void ExecuteNewtonsoftLicenseCommand()
|
||||
{
|
||||
System.Diagnostics.Process.Start("https://licenses.nuget.org/MIT");
|
||||
}
|
||||
|
||||
// Prism.DryIoc许可证查看事件
|
||||
private DelegateCommand prismLicenseCommand;
|
||||
public DelegateCommand PrismLicenseCommand => prismLicenseCommand ?? (prismLicenseCommand = new DelegateCommand(ExecutePrismLicenseCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Prism.DryIoc许可证查看事件
|
||||
/// </summary>
|
||||
private void ExecutePrismLicenseCommand()
|
||||
{
|
||||
System.Diagnostics.Process.Start("https://www.nuget.org/packages/Prism.DryIoc/8.1.97/license");
|
||||
}
|
||||
|
||||
// QRCoder许可证查看事件
|
||||
private DelegateCommand qRCoderLicenseCommand;
|
||||
public DelegateCommand QRCoderLicenseCommand => qRCoderLicenseCommand ?? (qRCoderLicenseCommand = new DelegateCommand(ExecuteQRCoderLicenseCommand));
|
||||
|
||||
/// <summary>
|
||||
/// QRCoder许可证查看事件
|
||||
/// </summary>
|
||||
private void ExecuteQRCoderLicenseCommand()
|
||||
{
|
||||
System.Diagnostics.Process.Start("https://licenses.nuget.org/MIT");
|
||||
}
|
||||
|
||||
// System.Data.SQLite.Core许可证查看事件
|
||||
private DelegateCommand sQLiteLicenseCommand;
|
||||
public DelegateCommand SQLiteLicenseCommand => sQLiteLicenseCommand ?? (sQLiteLicenseCommand = new DelegateCommand(ExecuteSQLiteLicenseCommand));
|
||||
|
||||
/// <summary>
|
||||
/// System.Data.SQLite.Core许可证查看事件
|
||||
/// </summary>
|
||||
private void ExecuteSQLiteLicenseCommand()
|
||||
{
|
||||
System.Diagnostics.Process.Start("https://www.sqlite.org/copyright.html");
|
||||
}
|
||||
|
||||
// Aria2c许可证查看事件
|
||||
private DelegateCommand ariaLicenseCommand;
|
||||
public DelegateCommand AriaLicenseCommand => ariaLicenseCommand ?? (ariaLicenseCommand = new DelegateCommand(ExecuteAriaLicenseCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria2c许可证查看事件
|
||||
/// </summary>
|
||||
private void ExecuteAriaLicenseCommand()
|
||||
{
|
||||
System.Diagnostics.Process.Start("aria2_COPYING.txt");
|
||||
}
|
||||
|
||||
// FFmpeg许可证查看事件
|
||||
private DelegateCommand fFmpegLicenseCommand;
|
||||
public DelegateCommand FFmpegLicenseCommand => fFmpegLicenseCommand ?? (fFmpegLicenseCommand = new DelegateCommand(ExecuteFFmpegLicenseCommand));
|
||||
|
||||
/// <summary>
|
||||
/// FFmpeg许可证查看事件
|
||||
/// </summary>
|
||||
private void ExecuteFFmpegLicenseCommand()
|
||||
{
|
||||
System.Diagnostics.Process.Start("FFmpeg_LICENSE.txt");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 发送需要显示的tip
|
||||
/// </summary>
|
||||
/// <param name="isSucceed"></param>
|
||||
private void PublishTip(bool isSucceed)
|
||||
{
|
||||
if (isOnNavigatedTo) { return; }
|
||||
|
||||
if (isSucceed)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipSettingUpdated"));
|
||||
}
|
||||
else
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipSettingFailed"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
239
src/DownKyi/ViewModels/Settings/ViewBasicViewModel.cs
Normal file
239
src/DownKyi/ViewModels/Settings/ViewBasicViewModel.cs
Normal file
@ -0,0 +1,239 @@
|
||||
using DownKyi.Core.Settings;
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Models;
|
||||
using DownKyi.Utils;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DownKyi.ViewModels.Settings
|
||||
{
|
||||
public class ViewBasicViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageSettingsBasic";
|
||||
|
||||
private bool isOnNavigatedTo;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private bool none;
|
||||
public bool None
|
||||
{
|
||||
get { return none; }
|
||||
set { SetProperty(ref none, value); }
|
||||
}
|
||||
|
||||
private bool closeApp;
|
||||
public bool CloseApp
|
||||
{
|
||||
get { return closeApp; }
|
||||
set { SetProperty(ref closeApp, value); }
|
||||
}
|
||||
|
||||
private bool closeSystem;
|
||||
public bool CloseSystem
|
||||
{
|
||||
get { return closeSystem; }
|
||||
set { SetProperty(ref closeSystem, value); }
|
||||
}
|
||||
|
||||
private bool listenClipboard;
|
||||
public bool ListenClipboard
|
||||
{
|
||||
get { return listenClipboard; }
|
||||
set { SetProperty(ref listenClipboard, value); }
|
||||
}
|
||||
|
||||
private bool autoParseVideo;
|
||||
public bool AutoParseVideo
|
||||
{
|
||||
get { return autoParseVideo; }
|
||||
set { SetProperty(ref autoParseVideo, value); }
|
||||
}
|
||||
|
||||
private List<ParseScopeDisplay> parseScopes;
|
||||
public List<ParseScopeDisplay> ParseScopes
|
||||
{
|
||||
get { return parseScopes; }
|
||||
set { SetProperty(ref parseScopes, value); }
|
||||
}
|
||||
|
||||
private ParseScopeDisplay selectedParseScope;
|
||||
public ParseScopeDisplay SelectedParseScope
|
||||
{
|
||||
get { return selectedParseScope; }
|
||||
set { SetProperty(ref selectedParseScope, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewBasicViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
|
||||
#region 属性初始化
|
||||
|
||||
// 解析范围
|
||||
ParseScopes = new List<ParseScopeDisplay>()
|
||||
{
|
||||
new ParseScopeDisplay{ Name =DictionaryResource.GetString("ParseNone"),ParseScope=ParseScope.NONE},
|
||||
new ParseScopeDisplay{ Name =DictionaryResource.GetString("ParseSelectedItem"),ParseScope=ParseScope.SELECTED_ITEM},
|
||||
new ParseScopeDisplay{ Name =DictionaryResource.GetString("ParseCurrentSection"),ParseScope=ParseScope.CURRENT_SECTION},
|
||||
new ParseScopeDisplay{ Name =DictionaryResource.GetString("ParseAll"),ParseScope=ParseScope.ALL}
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导航到VideoDetail页面时执行
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
isOnNavigatedTo = true;
|
||||
|
||||
// 下载完成后的操作
|
||||
AfterDownloadOperation afterDownload = SettingsManager.GetInstance().GetAfterDownloadOperation();
|
||||
SetAfterDownloadOperation(afterDownload);
|
||||
|
||||
// 是否监听剪贴板
|
||||
AllowStatus isListenClipboard = SettingsManager.GetInstance().IsListenClipboard();
|
||||
ListenClipboard = isListenClipboard == AllowStatus.YES;
|
||||
|
||||
// 是否自动解析视频
|
||||
AllowStatus isAutoParseVideo = SettingsManager.GetInstance().IsAutoParseVideo();
|
||||
AutoParseVideo = isAutoParseVideo == AllowStatus.YES;
|
||||
|
||||
// 解析范围
|
||||
ParseScope parseScope = SettingsManager.GetInstance().GetParseScope();
|
||||
SelectedParseScope = ParseScopes.FirstOrDefault(t => { return t.ParseScope == parseScope; });
|
||||
|
||||
isOnNavigatedTo = false;
|
||||
}
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// 下载完成后的操作事件
|
||||
private DelegateCommand<string> afterDownloadOperationCommand;
|
||||
public DelegateCommand<string> AfterDownloadOperationCommand => afterDownloadOperationCommand ?? (afterDownloadOperationCommand = new DelegateCommand<string>(ExecuteAfterDownloadOperationCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 下载完成后的操作事件
|
||||
/// </summary>
|
||||
private void ExecuteAfterDownloadOperationCommand(string parameter)
|
||||
{
|
||||
AfterDownloadOperation afterDownload;
|
||||
switch (parameter)
|
||||
{
|
||||
case "None":
|
||||
afterDownload = AfterDownloadOperation.NONE;
|
||||
break;
|
||||
case "CloseApp":
|
||||
afterDownload = AfterDownloadOperation.CLOSE_APP;
|
||||
break;
|
||||
case "CloseSystem":
|
||||
afterDownload = AfterDownloadOperation.CLOSE_SYSTEM;
|
||||
break;
|
||||
default:
|
||||
afterDownload = AfterDownloadOperation.NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAfterDownloadOperation(afterDownload);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 是否监听剪贴板事件
|
||||
private DelegateCommand listenClipboardCommand;
|
||||
public DelegateCommand ListenClipboardCommand => listenClipboardCommand ?? (listenClipboardCommand = new DelegateCommand(ExecuteListenClipboardCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 是否监听剪贴板事件
|
||||
/// </summary>
|
||||
private void ExecuteListenClipboardCommand()
|
||||
{
|
||||
AllowStatus isListenClipboard = ListenClipboard ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().IsListenClipboard(isListenClipboard);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
private DelegateCommand autoParseVideoCommand;
|
||||
public DelegateCommand AutoParseVideoCommand => autoParseVideoCommand ?? (autoParseVideoCommand = new DelegateCommand(ExecuteAutoParseVideoCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 是否自动解析视频
|
||||
/// </summary>
|
||||
private void ExecuteAutoParseVideoCommand()
|
||||
{
|
||||
AllowStatus isAutoParseVideo = AutoParseVideo ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().IsAutoParseVideo(isAutoParseVideo);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 解析范围事件
|
||||
private DelegateCommand<object> parseScopesCommand;
|
||||
public DelegateCommand<object> ParseScopesCommand => parseScopesCommand ?? (parseScopesCommand = new DelegateCommand<object>(ExecuteParseScopesCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 解析范围事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteParseScopesCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is ParseScopeDisplay parseScope)) { return; }
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetParseScope(parseScope.ParseScope);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 设置下载完成后的操作
|
||||
/// </summary>
|
||||
/// <param name="afterDownload"></param>
|
||||
private void SetAfterDownloadOperation(AfterDownloadOperation afterDownload)
|
||||
{
|
||||
switch (afterDownload)
|
||||
{
|
||||
case AfterDownloadOperation.NONE:
|
||||
None = true;
|
||||
break;
|
||||
case AfterDownloadOperation.OPEN_FOLDER:
|
||||
break;
|
||||
case AfterDownloadOperation.CLOSE_APP:
|
||||
CloseApp = true;
|
||||
break;
|
||||
case AfterDownloadOperation.CLOSE_SYSTEM:
|
||||
CloseSystem = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送需要显示的tip
|
||||
/// </summary>
|
||||
/// <param name="isSucceed"></param>
|
||||
private void PublishTip(bool isSucceed)
|
||||
{
|
||||
if (isOnNavigatedTo) { return; }
|
||||
|
||||
if (isSucceed)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipSettingUpdated"));
|
||||
}
|
||||
else
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipSettingFailed"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
374
src/DownKyi/ViewModels/Settings/ViewDanmakuViewModel.cs
Normal file
374
src/DownKyi/ViewModels/Settings/ViewDanmakuViewModel.cs
Normal file
@ -0,0 +1,374 @@
|
||||
using DownKyi.Core.Settings;
|
||||
using DownKyi.Core.Utils.Validator;
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Utils;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Text;
|
||||
|
||||
namespace DownKyi.ViewModels.Settings
|
||||
{
|
||||
public class ViewDanmakuViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageSettingsDanmaku";
|
||||
|
||||
private bool isOnNavigatedTo;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private bool topFilter;
|
||||
public bool TopFilter
|
||||
{
|
||||
get { return topFilter; }
|
||||
set { SetProperty(ref topFilter, value); }
|
||||
}
|
||||
|
||||
private bool bottomFilter;
|
||||
public bool BottomFilter
|
||||
{
|
||||
get { return bottomFilter; }
|
||||
set { SetProperty(ref bottomFilter, value); }
|
||||
}
|
||||
|
||||
private bool scrollFilter;
|
||||
public bool ScrollFilter
|
||||
{
|
||||
get { return scrollFilter; }
|
||||
set { SetProperty(ref scrollFilter, value); }
|
||||
}
|
||||
|
||||
private int screenWidth;
|
||||
public int ScreenWidth
|
||||
{
|
||||
get { return screenWidth; }
|
||||
set { SetProperty(ref screenWidth, value); }
|
||||
}
|
||||
|
||||
private int screenHeight;
|
||||
public int ScreenHeight
|
||||
{
|
||||
get { return screenHeight; }
|
||||
set { SetProperty(ref screenHeight, value); }
|
||||
}
|
||||
|
||||
private List<string> fonts;
|
||||
public List<string> Fonts
|
||||
{
|
||||
get { return fonts; }
|
||||
set { SetProperty(ref fonts, value); }
|
||||
}
|
||||
|
||||
private string selectedFont;
|
||||
public string SelectedFont
|
||||
{
|
||||
get { return selectedFont; }
|
||||
set { SetProperty(ref selectedFont, value); }
|
||||
}
|
||||
|
||||
private int fontSize;
|
||||
public int FontSize
|
||||
{
|
||||
get { return fontSize; }
|
||||
set { SetProperty(ref fontSize, value); }
|
||||
}
|
||||
|
||||
private int lineCount;
|
||||
public int LineCount
|
||||
{
|
||||
get { return lineCount; }
|
||||
set { SetProperty(ref lineCount, value); }
|
||||
}
|
||||
|
||||
private bool sync;
|
||||
public bool Sync
|
||||
{
|
||||
get { return sync; }
|
||||
set { SetProperty(ref sync, value); }
|
||||
}
|
||||
|
||||
private bool async;
|
||||
public bool Async
|
||||
{
|
||||
get { return async; }
|
||||
set { SetProperty(ref async, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewDanmakuViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
|
||||
#region 属性初始化
|
||||
|
||||
// 弹幕字体
|
||||
Fonts = new List<string>();
|
||||
var fontCollection = new InstalledFontCollection();
|
||||
foreach (var font in fontCollection.Families)
|
||||
{
|
||||
Fonts.Add(font.Name);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导航到VideoDetail页面时执行
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
isOnNavigatedTo = true;
|
||||
|
||||
// 屏蔽顶部弹幕
|
||||
AllowStatus danmakuTopFilter = SettingsManager.GetInstance().GetDanmakuTopFilter();
|
||||
TopFilter = danmakuTopFilter == AllowStatus.YES;
|
||||
|
||||
// 屏蔽底部弹幕
|
||||
AllowStatus danmakuBottomFilter = SettingsManager.GetInstance().GetDanmakuBottomFilter();
|
||||
BottomFilter = danmakuBottomFilter == AllowStatus.YES;
|
||||
|
||||
// 屏蔽滚动弹幕
|
||||
AllowStatus danmakuScrollFilter = SettingsManager.GetInstance().GetDanmakuScrollFilter();
|
||||
ScrollFilter = danmakuScrollFilter == AllowStatus.YES;
|
||||
|
||||
// 分辨率-宽
|
||||
ScreenWidth = SettingsManager.GetInstance().GetDanmakuScreenWidth();
|
||||
|
||||
// 分辨率-高
|
||||
ScreenHeight = SettingsManager.GetInstance().GetDanmakuScreenHeight();
|
||||
|
||||
// 弹幕字体
|
||||
string danmakuFont = SettingsManager.GetInstance().GetDanmakuFontName();
|
||||
if (Fonts.Contains(danmakuFont))
|
||||
{
|
||||
// 只有系统中存在当前设置的字体,才能显示
|
||||
SelectedFont = danmakuFont;
|
||||
}
|
||||
|
||||
// 弹幕字体大小
|
||||
FontSize = SettingsManager.GetInstance().GetDanmakuFontSize();
|
||||
|
||||
// 弹幕限制行数
|
||||
LineCount = SettingsManager.GetInstance().GetDanmakuLineCount();
|
||||
|
||||
// 弹幕布局算法
|
||||
DanmakuLayoutAlgorithm layoutAlgorithm = SettingsManager.GetInstance().GetDanmakuLayoutAlgorithm();
|
||||
SetLayoutAlgorithm(layoutAlgorithm);
|
||||
|
||||
isOnNavigatedTo = false;
|
||||
}
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// 屏蔽顶部弹幕事件
|
||||
private DelegateCommand topFilterCommand;
|
||||
public DelegateCommand TopFilterCommand => topFilterCommand ?? (topFilterCommand = new DelegateCommand(ExecuteTopFilterCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 屏蔽顶部弹幕事件
|
||||
/// </summary>
|
||||
private void ExecuteTopFilterCommand()
|
||||
{
|
||||
AllowStatus isTopFilter = TopFilter ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetDanmakuTopFilter(isTopFilter);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 屏蔽底部弹幕事件
|
||||
private DelegateCommand bottomFilterCommand;
|
||||
public DelegateCommand BottomFilterCommand => bottomFilterCommand ?? (bottomFilterCommand = new DelegateCommand(ExecuteBottomFilterCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 屏蔽底部弹幕事件
|
||||
/// </summary>
|
||||
private void ExecuteBottomFilterCommand()
|
||||
{
|
||||
AllowStatus isBottomFilter = BottomFilter ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetDanmakuBottomFilter(isBottomFilter);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 屏蔽滚动弹幕事件
|
||||
private DelegateCommand scrollFilterCommand;
|
||||
public DelegateCommand ScrollFilterCommand => scrollFilterCommand ?? (scrollFilterCommand = new DelegateCommand(ExecuteScrollFilterCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 屏蔽滚动弹幕事件
|
||||
/// </summary>
|
||||
private void ExecuteScrollFilterCommand()
|
||||
{
|
||||
AllowStatus isScrollFilter = ScrollFilter ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetDanmakuScrollFilter(isScrollFilter);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 设置分辨率-宽事件
|
||||
private DelegateCommand<string> screenWidthCommand;
|
||||
public DelegateCommand<string> ScreenWidthCommand => screenWidthCommand ?? (screenWidthCommand = new DelegateCommand<string>(ExecuteScreenWidthCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 设置分辨率-宽事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteScreenWidthCommand(string parameter)
|
||||
{
|
||||
int width = (int)Number.GetInt(parameter);
|
||||
ScreenWidth = width;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetDanmakuScreenWidth(ScreenWidth);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 设置分辨率-高事件
|
||||
private DelegateCommand<string> screenHeightCommand;
|
||||
public DelegateCommand<string> ScreenHeightCommand => screenHeightCommand ?? (screenHeightCommand = new DelegateCommand<string>(ExecuteScreenHeightCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 设置分辨率-高事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteScreenHeightCommand(string parameter)
|
||||
{
|
||||
int height = (int)Number.GetInt(parameter);
|
||||
ScreenHeight = height;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetDanmakuScreenHeight(ScreenHeight);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 弹幕字体选择事件
|
||||
private DelegateCommand<string> fontSelectCommand;
|
||||
public DelegateCommand<string> FontSelectCommand => fontSelectCommand ?? (fontSelectCommand = new DelegateCommand<string>(ExecuteFontSelectCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 弹幕字体选择事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteFontSelectCommand(string parameter)
|
||||
{
|
||||
bool isSucceed = SettingsManager.GetInstance().SetDanmakuFontName(parameter);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 弹幕字体大小事件
|
||||
private DelegateCommand<string> fontSizeCommand;
|
||||
public DelegateCommand<string> FontSizeCommand => fontSizeCommand ?? (fontSizeCommand = new DelegateCommand<string>(ExecuteFontSizeCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 弹幕字体大小事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteFontSizeCommand(string parameter)
|
||||
{
|
||||
int fontSize = (int)Number.GetInt(parameter);
|
||||
FontSize = fontSize;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetDanmakuFontSize(FontSize);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 弹幕限制行数事件
|
||||
private DelegateCommand<string> lineCountCommand;
|
||||
public DelegateCommand<string> LineCountCommand => lineCountCommand ?? (lineCountCommand = new DelegateCommand<string>(ExecuteLineCountCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 弹幕限制行数事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteLineCountCommand(string parameter)
|
||||
{
|
||||
int lineCount = (int)Number.GetInt(parameter);
|
||||
LineCount = lineCount;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetDanmakuLineCount(LineCount);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 弹幕布局算法事件
|
||||
private DelegateCommand<string> layoutAlgorithmCommand;
|
||||
public DelegateCommand<string> LayoutAlgorithmCommand => layoutAlgorithmCommand ?? (layoutAlgorithmCommand = new DelegateCommand<string>(ExecuteLayoutAlgorithmCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 弹幕布局算法事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteLayoutAlgorithmCommand(string parameter)
|
||||
{
|
||||
DanmakuLayoutAlgorithm layoutAlgorithm;
|
||||
switch (parameter)
|
||||
{
|
||||
case "Sync":
|
||||
layoutAlgorithm = DanmakuLayoutAlgorithm.SYNC;
|
||||
break;
|
||||
case "Async":
|
||||
layoutAlgorithm = DanmakuLayoutAlgorithm.ASYNC;
|
||||
break;
|
||||
default:
|
||||
layoutAlgorithm = DanmakuLayoutAlgorithm.SYNC;
|
||||
break;
|
||||
}
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetDanmakuLayoutAlgorithm(layoutAlgorithm);
|
||||
PublishTip(isSucceed);
|
||||
|
||||
if (isSucceed)
|
||||
{
|
||||
SetLayoutAlgorithm(layoutAlgorithm);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 设置弹幕同步算法
|
||||
/// </summary>
|
||||
/// <param name="layoutAlgorithm"></param>
|
||||
private void SetLayoutAlgorithm(DanmakuLayoutAlgorithm layoutAlgorithm)
|
||||
{
|
||||
switch (layoutAlgorithm)
|
||||
{
|
||||
case DanmakuLayoutAlgorithm.SYNC:
|
||||
Sync = true;
|
||||
Async = false;
|
||||
break;
|
||||
case DanmakuLayoutAlgorithm.ASYNC:
|
||||
Sync = false;
|
||||
Async = true;
|
||||
break;
|
||||
case DanmakuLayoutAlgorithm.NONE:
|
||||
Sync = false;
|
||||
Async = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送需要显示的tip
|
||||
/// </summary>
|
||||
/// <param name="isSucceed"></param>
|
||||
private void PublishTip(bool isSucceed)
|
||||
{
|
||||
if (isOnNavigatedTo) { return; }
|
||||
|
||||
if (isSucceed)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipSettingUpdated"));
|
||||
}
|
||||
else
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipSettingFailed"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
422
src/DownKyi/ViewModels/Settings/ViewNetworkViewModel.cs
Normal file
422
src/DownKyi/ViewModels/Settings/ViewNetworkViewModel.cs
Normal file
@ -0,0 +1,422 @@
|
||||
using DownKyi.Core.Aria2cNet.Server;
|
||||
using DownKyi.Core.Settings;
|
||||
using DownKyi.Core.Utils.Validator;
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Utils;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DownKyi.ViewModels.Settings
|
||||
{
|
||||
public class ViewNetworkViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageSettingsNetwork";
|
||||
|
||||
private bool isOnNavigatedTo;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private int ariaListenPort;
|
||||
public int AriaListenPort
|
||||
{
|
||||
get { return ariaListenPort; }
|
||||
set { SetProperty(ref ariaListenPort, value); }
|
||||
}
|
||||
|
||||
private List<string> ariaLogLevels;
|
||||
public List<string> AriaLogLevels
|
||||
{
|
||||
get { return ariaLogLevels; }
|
||||
set { SetProperty(ref ariaLogLevels, value); }
|
||||
}
|
||||
|
||||
private string selectedAriaLogLevel;
|
||||
public string SelectedAriaLogLevel
|
||||
{
|
||||
get { return selectedAriaLogLevel; }
|
||||
set { SetProperty(ref selectedAriaLogLevel, value); }
|
||||
}
|
||||
|
||||
private List<int> ariaMaxConcurrentDownloads;
|
||||
public List<int> AriaMaxConcurrentDownloads
|
||||
{
|
||||
get { return ariaMaxConcurrentDownloads; }
|
||||
set { SetProperty(ref ariaMaxConcurrentDownloads, value); }
|
||||
}
|
||||
|
||||
private int selectedAriaMaxConcurrentDownload;
|
||||
public int SelectedAriaMaxConcurrentDownload
|
||||
{
|
||||
get { return selectedAriaMaxConcurrentDownload; }
|
||||
set { SetProperty(ref selectedAriaMaxConcurrentDownload, value); }
|
||||
}
|
||||
|
||||
private List<int> ariaSplits;
|
||||
public List<int> AriaSplits
|
||||
{
|
||||
get { return ariaSplits; }
|
||||
set { SetProperty(ref ariaSplits, value); }
|
||||
}
|
||||
|
||||
private int selectedAriaSplit;
|
||||
public int SelectedAriaSplit
|
||||
{
|
||||
get { return selectedAriaSplit; }
|
||||
set { SetProperty(ref selectedAriaSplit, value); }
|
||||
}
|
||||
|
||||
private int ariaMaxOverallDownloadLimit;
|
||||
public int AriaMaxOverallDownloadLimit
|
||||
{
|
||||
get { return ariaMaxOverallDownloadLimit; }
|
||||
set { SetProperty(ref ariaMaxOverallDownloadLimit, value); }
|
||||
}
|
||||
|
||||
private int ariaMaxDownloadLimit;
|
||||
public int AriaMaxDownloadLimit
|
||||
{
|
||||
get { return ariaMaxDownloadLimit; }
|
||||
set { SetProperty(ref ariaMaxDownloadLimit, value); }
|
||||
}
|
||||
|
||||
private bool isAriaHttpProxy;
|
||||
public bool IsAriaHttpProxy
|
||||
{
|
||||
get { return isAriaHttpProxy; }
|
||||
set { SetProperty(ref isAriaHttpProxy, value); }
|
||||
}
|
||||
|
||||
private string ariaHttpProxy;
|
||||
public string AriaHttpProxy
|
||||
{
|
||||
get { return ariaHttpProxy; }
|
||||
set { SetProperty(ref ariaHttpProxy, value); }
|
||||
}
|
||||
|
||||
private int ariaHttpProxyPort;
|
||||
public int AriaHttpProxyPort
|
||||
{
|
||||
get { return ariaHttpProxyPort; }
|
||||
set { SetProperty(ref ariaHttpProxyPort, value); }
|
||||
}
|
||||
|
||||
private List<string> ariaFileAllocations;
|
||||
public List<string> AriaFileAllocations
|
||||
{
|
||||
get { return ariaFileAllocations; }
|
||||
set { SetProperty(ref ariaFileAllocations, value); }
|
||||
}
|
||||
|
||||
private string selectedAriaFileAllocation;
|
||||
public string SelectedAriaFileAllocation
|
||||
{
|
||||
get { return selectedAriaFileAllocation; }
|
||||
set { SetProperty(ref selectedAriaFileAllocation, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewNetworkViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
|
||||
#region 属性初始化
|
||||
|
||||
// Aria的日志等级
|
||||
AriaLogLevels = new List<string>
|
||||
{
|
||||
"DEBUG",
|
||||
"INFO",
|
||||
"NOTICE",
|
||||
"WARN",
|
||||
"ERROR"
|
||||
};
|
||||
|
||||
// Aria同时下载数
|
||||
AriaMaxConcurrentDownloads = new List<int>();
|
||||
for (int i = 1; i <= 10; i++) { AriaMaxConcurrentDownloads.Add(i); }
|
||||
|
||||
// Aria最大线程数
|
||||
AriaSplits = new List<int>();
|
||||
for (int i = 1; i <= 10; i++) { AriaSplits.Add(i); }
|
||||
|
||||
// Aria文件预分配
|
||||
AriaFileAllocations = new List<string>
|
||||
{
|
||||
"NONE",
|
||||
"PREALLOC",
|
||||
"FALLOC"
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导航到VideoDetail页面时执行
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
isOnNavigatedTo = true;
|
||||
|
||||
// Aria服务器端口
|
||||
AriaListenPort = SettingsManager.GetInstance().GetAriaListenPort();
|
||||
|
||||
// Aria的日志等级
|
||||
AriaConfigLogLevel ariaLogLevel = SettingsManager.GetInstance().GetAriaLogLevel();
|
||||
SelectedAriaLogLevel = ariaLogLevel.ToString("G");
|
||||
|
||||
// Aria同时下载数
|
||||
SelectedAriaMaxConcurrentDownload = SettingsManager.GetInstance().GetAriaMaxConcurrentDownloads();
|
||||
|
||||
// Aria最大线程数
|
||||
SelectedAriaSplit = SettingsManager.GetInstance().GetAriaSplit();
|
||||
|
||||
// Aria下载速度限制
|
||||
AriaMaxOverallDownloadLimit = SettingsManager.GetInstance().GetAriaMaxOverallDownloadLimit();
|
||||
|
||||
// Aria下载单文件速度限制
|
||||
AriaMaxDownloadLimit = SettingsManager.GetInstance().GetAriaMaxDownloadLimit();
|
||||
|
||||
// 是否开启Aria http代理
|
||||
AllowStatus isAriaHttpProxy = SettingsManager.GetInstance().IsAriaHttpProxy();
|
||||
IsAriaHttpProxy = isAriaHttpProxy == AllowStatus.YES;
|
||||
|
||||
// Aria的http代理的地址
|
||||
AriaHttpProxy = SettingsManager.GetInstance().GetAriaHttpProxy();
|
||||
|
||||
// Aria的http代理的端口
|
||||
AriaHttpProxyPort = SettingsManager.GetInstance().GetAriaHttpProxyListenPort();
|
||||
|
||||
// Aria文件预分配
|
||||
AriaConfigFileAllocation ariaFileAllocation = SettingsManager.GetInstance().GetAriaFileAllocation();
|
||||
SelectedAriaFileAllocation = ariaFileAllocation.ToString("G");
|
||||
|
||||
isOnNavigatedTo = false;
|
||||
}
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// Aria服务器端口事件
|
||||
private DelegateCommand<string> ariaListenPortCommand;
|
||||
public DelegateCommand<string> AriaListenPortCommand => ariaListenPortCommand ?? (ariaListenPortCommand = new DelegateCommand<string>(ExecuteAriaListenPortCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria服务器端口事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteAriaListenPortCommand(string parameter)
|
||||
{
|
||||
int listenPort = (int)Number.GetInt(parameter);
|
||||
AriaListenPort = listenPort;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAriaListenPort(AriaListenPort);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria的日志等级事件
|
||||
private DelegateCommand<string> ariaLogLevelsCommand;
|
||||
public DelegateCommand<string> AriaLogLevelsCommand => ariaLogLevelsCommand ?? (ariaLogLevelsCommand = new DelegateCommand<string>(ExecuteAriaLogLevelsCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria的日志等级事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteAriaLogLevelsCommand(string parameter)
|
||||
{
|
||||
AriaConfigLogLevel ariaLogLevel;
|
||||
switch (parameter)
|
||||
{
|
||||
case "DEBUG":
|
||||
ariaLogLevel = AriaConfigLogLevel.DEBUG;
|
||||
break;
|
||||
case "INFO":
|
||||
ariaLogLevel = AriaConfigLogLevel.INFO;
|
||||
break;
|
||||
case "NOTICE":
|
||||
ariaLogLevel = AriaConfigLogLevel.NOTICE;
|
||||
break;
|
||||
case "WARN":
|
||||
ariaLogLevel = AriaConfigLogLevel.WARN;
|
||||
break;
|
||||
case "ERROR":
|
||||
ariaLogLevel = AriaConfigLogLevel.ERROR;
|
||||
break;
|
||||
default:
|
||||
ariaLogLevel = AriaConfigLogLevel.INFO;
|
||||
break;
|
||||
}
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAriaLogLevel(ariaLogLevel);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria同时下载数事件
|
||||
private DelegateCommand<object> ariaMaxConcurrentDownloadsCommand;
|
||||
public DelegateCommand<object> AriaMaxConcurrentDownloadsCommand => ariaMaxConcurrentDownloadsCommand ?? (ariaMaxConcurrentDownloadsCommand = new DelegateCommand<object>(ExecuteAriaMaxConcurrentDownloadsCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria同时下载数事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteAriaMaxConcurrentDownloadsCommand(object parameter)
|
||||
{
|
||||
SelectedAriaMaxConcurrentDownload = (int)parameter;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAriaMaxConcurrentDownloads(SelectedAriaMaxConcurrentDownload);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria最大线程数事件
|
||||
private DelegateCommand<object> ariaSplitsCommand;
|
||||
public DelegateCommand<object> AriaSplitsCommand => ariaSplitsCommand ?? (ariaSplitsCommand = new DelegateCommand<object>(ExecuteAriaSplitsCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria最大线程数事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteAriaSplitsCommand(object parameter)
|
||||
{
|
||||
SelectedAriaSplit = (int)parameter;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAriaSplit(SelectedAriaSplit);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria下载速度限制事件
|
||||
private DelegateCommand<string> ariaMaxOverallDownloadLimitCommand;
|
||||
public DelegateCommand<string> AriaMaxOverallDownloadLimitCommand => ariaMaxOverallDownloadLimitCommand ?? (ariaMaxOverallDownloadLimitCommand = new DelegateCommand<string>(ExecuteAriaMaxOverallDownloadLimitCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria下载速度限制事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteAriaMaxOverallDownloadLimitCommand(string parameter)
|
||||
{
|
||||
int downloadLimit = (int)Number.GetInt(parameter);
|
||||
AriaMaxOverallDownloadLimit = downloadLimit;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAriaMaxOverallDownloadLimit(AriaMaxOverallDownloadLimit);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria下载单文件速度限制事件
|
||||
private DelegateCommand<string> ariaMaxDownloadLimitCommand;
|
||||
public DelegateCommand<string> AriaMaxDownloadLimitCommand => ariaMaxDownloadLimitCommand ?? (ariaMaxDownloadLimitCommand = new DelegateCommand<string>(ExecuteAriaMaxDownloadLimitCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria下载单文件速度限制事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteAriaMaxDownloadLimitCommand(string parameter)
|
||||
{
|
||||
int downloadLimit = (int)Number.GetInt(parameter);
|
||||
AriaMaxDownloadLimit = downloadLimit;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAriaMaxDownloadLimit(AriaMaxDownloadLimit);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 是否开启Aria http代理事件
|
||||
private DelegateCommand isAriaHttpProxyCommand;
|
||||
public DelegateCommand IsAriaHttpProxyCommand => isAriaHttpProxyCommand ?? (isAriaHttpProxyCommand = new DelegateCommand(ExecuteIsAriaHttpProxyCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 是否开启Aria http代理事件
|
||||
/// </summary>
|
||||
private void ExecuteIsAriaHttpProxyCommand()
|
||||
{
|
||||
AllowStatus isAriaHttpProxy = IsAriaHttpProxy ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().IsAriaHttpProxy(isAriaHttpProxy);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria的http代理的地址事件
|
||||
private DelegateCommand<string> ariaHttpProxyCommand;
|
||||
public DelegateCommand<string> AriaHttpProxyCommand => ariaHttpProxyCommand ?? (ariaHttpProxyCommand = new DelegateCommand<string>(ExecuteAriaHttpProxyCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria的http代理的地址事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteAriaHttpProxyCommand(string parameter)
|
||||
{
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAriaHttpProxy(parameter);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria的http代理的端口事件
|
||||
private DelegateCommand<string> ariaHttpProxyPortCommand;
|
||||
public DelegateCommand<string> AriaHttpProxyPortCommand => ariaHttpProxyPortCommand ?? (ariaHttpProxyPortCommand = new DelegateCommand<string>(ExecuteAriaHttpProxyPortCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria的http代理的端口事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteAriaHttpProxyPortCommand(string parameter)
|
||||
{
|
||||
int httpProxyPort = (int)Number.GetInt(parameter);
|
||||
AriaHttpProxyPort = httpProxyPort;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAriaHttpProxyListenPort(AriaHttpProxyPort);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria文件预分配事件
|
||||
private DelegateCommand<string> ariaFileAllocationsCommand;
|
||||
public DelegateCommand<string> AriaFileAllocationsCommand => ariaFileAllocationsCommand ?? (ariaFileAllocationsCommand = new DelegateCommand<string>(ExecuteAriaFileAllocationsCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria文件预分配事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteAriaFileAllocationsCommand(string parameter)
|
||||
{
|
||||
AriaConfigFileAllocation ariaFileAllocation;
|
||||
switch (parameter)
|
||||
{
|
||||
case "NONE":
|
||||
ariaFileAllocation = AriaConfigFileAllocation.NONE;
|
||||
break;
|
||||
case "PREALLOC":
|
||||
ariaFileAllocation = AriaConfigFileAllocation.PREALLOC;
|
||||
break;
|
||||
case "FALLOC":
|
||||
ariaFileAllocation = AriaConfigFileAllocation.FALLOC;
|
||||
break;
|
||||
default:
|
||||
ariaFileAllocation = AriaConfigFileAllocation.PREALLOC;
|
||||
break;
|
||||
}
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAriaFileAllocation(ariaFileAllocation);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 发送需要显示的tip
|
||||
/// </summary>
|
||||
/// <param name="isSucceed"></param>
|
||||
private void PublishTip(bool isSucceed)
|
||||
{
|
||||
if (isOnNavigatedTo) { return; }
|
||||
|
||||
if (isSucceed)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipSettingUpdated"));
|
||||
}
|
||||
else
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipSettingFailed"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
383
src/DownKyi/ViewModels/Settings/ViewVideoViewModel.cs
Normal file
383
src/DownKyi/ViewModels/Settings/ViewVideoViewModel.cs
Normal file
@ -0,0 +1,383 @@
|
||||
using DownKyi.Core.Settings;
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Models;
|
||||
using DownKyi.Services;
|
||||
using DownKyi.Utils;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DownKyi.ViewModels.Settings
|
||||
{
|
||||
public class ViewVideoViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageSettingsVideo";
|
||||
|
||||
private bool isOnNavigatedTo;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private List<string> videoCodecs;
|
||||
public List<string> VideoCodecs
|
||||
{
|
||||
get { return videoCodecs; }
|
||||
set { SetProperty(ref videoCodecs, value); }
|
||||
}
|
||||
|
||||
private string selectedVideoCodec;
|
||||
public string SelectedVideoCodec
|
||||
{
|
||||
get { return selectedVideoCodec; }
|
||||
set { SetProperty(ref selectedVideoCodec, value); }
|
||||
}
|
||||
|
||||
private List<Resolution> videoQualityList;
|
||||
public List<Resolution> VideoQualityList
|
||||
{
|
||||
get { return videoQualityList; }
|
||||
set { SetProperty(ref videoQualityList, value); }
|
||||
}
|
||||
|
||||
private Resolution selectedVideoQuality;
|
||||
public Resolution SelectedVideoQuality
|
||||
{
|
||||
get { return selectedVideoQuality; }
|
||||
set { SetProperty(ref selectedVideoQuality, value); }
|
||||
}
|
||||
|
||||
private bool isAddVideoOrder;
|
||||
public bool IsAddVideoOrder
|
||||
{
|
||||
get { return isAddVideoOrder; }
|
||||
set { SetProperty(ref isAddVideoOrder, value); }
|
||||
}
|
||||
|
||||
private bool isTranscodingFlvToMp4;
|
||||
public bool IsTranscodingFlvToMp4
|
||||
{
|
||||
get { return isTranscodingFlvToMp4; }
|
||||
set { SetProperty(ref isTranscodingFlvToMp4, value); }
|
||||
}
|
||||
|
||||
private bool isUseDefaultDirectory;
|
||||
public bool IsUseDefaultDirectory
|
||||
{
|
||||
get { return isUseDefaultDirectory; }
|
||||
set { SetProperty(ref isUseDefaultDirectory, value); }
|
||||
}
|
||||
|
||||
private string saveVideoDirectory;
|
||||
public string SaveVideoDirectory
|
||||
{
|
||||
get { return saveVideoDirectory; }
|
||||
set { SetProperty(ref saveVideoDirectory, value); }
|
||||
}
|
||||
|
||||
private bool isCreateFolderForMedia;
|
||||
public bool IsCreateFolderForMedia
|
||||
{
|
||||
get { return isCreateFolderForMedia; }
|
||||
set { SetProperty(ref isCreateFolderForMedia, value); }
|
||||
}
|
||||
|
||||
private bool isDownloadDanmaku;
|
||||
public bool IsDownloadDanmaku
|
||||
{
|
||||
get { return isDownloadDanmaku; }
|
||||
set { SetProperty(ref isDownloadDanmaku, value); }
|
||||
}
|
||||
|
||||
private bool isDownloadCover;
|
||||
public bool IsDownloadCover
|
||||
{
|
||||
get { return isDownloadCover; }
|
||||
set { SetProperty(ref isDownloadCover, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewVideoViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
|
||||
#region 属性初始化
|
||||
|
||||
// 优先下载的视频编码
|
||||
VideoCodecs = new List<string>
|
||||
{
|
||||
"H.264/AVC",
|
||||
"H.265/HEVC"
|
||||
};
|
||||
|
||||
// 优先下载画质
|
||||
VideoQualityList = new ResolutionService().GetResolution();
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导航到VideoDetail页面时执行
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
isOnNavigatedTo = true;
|
||||
|
||||
// 优先下载的视频编码
|
||||
VideoCodecs videoCodecs = SettingsManager.GetInstance().GetVideoCodecs();
|
||||
SelectedVideoCodec = GetVideoCodecsString(videoCodecs);
|
||||
|
||||
// 优先下载画质
|
||||
int quality = SettingsManager.GetInstance().GetQuality();
|
||||
SelectedVideoQuality = VideoQualityList.FirstOrDefault(t => { return t.Id == quality; });
|
||||
|
||||
// 是否在下载的视频前增加序号
|
||||
AllowStatus isAddOrder = SettingsManager.GetInstance().IsAddOrder();
|
||||
IsAddVideoOrder = isAddOrder == AllowStatus.YES;
|
||||
|
||||
// 是否下载flv视频后转码为mp4
|
||||
AllowStatus isTranscodingFlvToMp4 = SettingsManager.GetInstance().IsTranscodingFlvToMp4();
|
||||
IsTranscodingFlvToMp4 = isTranscodingFlvToMp4 == AllowStatus.YES;
|
||||
|
||||
// 是否使用默认下载目录
|
||||
AllowStatus isUseSaveVideoRootPath = SettingsManager.GetInstance().IsUseSaveVideoRootPath();
|
||||
IsUseDefaultDirectory = isUseSaveVideoRootPath == AllowStatus.YES;
|
||||
|
||||
// 默认下载目录
|
||||
SaveVideoDirectory = SettingsManager.GetInstance().GetSaveVideoRootPath();
|
||||
|
||||
// 是否为不同视频分别创建文件夹
|
||||
AllowStatus isCreateFolderForMedia = SettingsManager.GetInstance().IsCreateFolderForMedia();
|
||||
IsCreateFolderForMedia = isCreateFolderForMedia == AllowStatus.YES;
|
||||
|
||||
// 是否在下载视频的同时下载弹幕
|
||||
AllowStatus isDownloadDanmaku = SettingsManager.GetInstance().IsDownloadDanmaku();
|
||||
IsDownloadDanmaku = isDownloadDanmaku == AllowStatus.YES;
|
||||
|
||||
// 是否在下载视频的同时下载封面
|
||||
AllowStatus isDownloadCover = SettingsManager.GetInstance().IsDownloadCover();
|
||||
IsDownloadCover = isDownloadCover == AllowStatus.YES;
|
||||
|
||||
isOnNavigatedTo = false;
|
||||
}
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// 优先下载的视频编码事件
|
||||
private DelegateCommand<string> videoCodecsCommand;
|
||||
public DelegateCommand<string> VideoCodecsCommand => videoCodecsCommand ?? (videoCodecsCommand = new DelegateCommand<string>(ExecuteVideoCodecsCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 优先下载的视频编码事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteVideoCodecsCommand(string parameter)
|
||||
{
|
||||
VideoCodecs videoCodecs = GetVideoCodecs(parameter);
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetVideoCodecs(videoCodecs);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 优先下载画质事件
|
||||
private DelegateCommand<object> videoQualityCommand;
|
||||
public DelegateCommand<object> VideoQualityCommand => videoQualityCommand ?? (videoQualityCommand = new DelegateCommand<object>(ExecuteVideoQualityCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 优先下载画质事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteVideoQualityCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is Resolution resolution)) { return; }
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetQuality(resolution.Id);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 是否在下载的视频前增加序号事件
|
||||
private DelegateCommand IisAddVideoOrderCommand;
|
||||
public DelegateCommand IsAddVideoOrderCommand => IisAddVideoOrderCommand ?? (IisAddVideoOrderCommand = new DelegateCommand(ExecuteIsAddVideoOrderCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 是否在下载的视频前增加序号事件
|
||||
/// </summary>
|
||||
private void ExecuteIsAddVideoOrderCommand()
|
||||
{
|
||||
AllowStatus isAddOrder = IsAddVideoOrder ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().IsAddOrder(isAddOrder);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 是否下载flv视频后转码为mp4事件
|
||||
private DelegateCommand isTranscodingFlvToMp4Command;
|
||||
public DelegateCommand IsTranscodingFlvToMp4Command => isTranscodingFlvToMp4Command ?? (isTranscodingFlvToMp4Command = new DelegateCommand(ExecuteIsTranscodingFlvToMp4Command));
|
||||
|
||||
/// <summary>
|
||||
/// 是否下载flv视频后转码为mp4事件
|
||||
/// </summary>
|
||||
private void ExecuteIsTranscodingFlvToMp4Command()
|
||||
{
|
||||
AllowStatus isTranscodingFlvToMp4 = IsTranscodingFlvToMp4 ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().IsTranscodingFlvToMp4(isTranscodingFlvToMp4);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 是否使用默认下载目录事件
|
||||
private DelegateCommand isUseDefaultDirectoryCommand;
|
||||
public DelegateCommand IsUseDefaultDirectoryCommand => isUseDefaultDirectoryCommand ?? (isUseDefaultDirectoryCommand = new DelegateCommand(ExecuteIsUseDefaultDirectoryCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 是否使用默认下载目录事件
|
||||
/// </summary>
|
||||
private void ExecuteIsUseDefaultDirectoryCommand()
|
||||
{
|
||||
AllowStatus isUseDefaultDirectory = IsUseDefaultDirectory ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().IsUseSaveVideoRootPath(isUseDefaultDirectory);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 修改默认下载目录事件
|
||||
private DelegateCommand changeSaveVideoDirectoryCommand;
|
||||
public DelegateCommand ChangeSaveVideoDirectoryCommand => changeSaveVideoDirectoryCommand ?? (changeSaveVideoDirectoryCommand = new DelegateCommand(ExecuteChangeSaveVideoDirectoryCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 修改默认下载目录事件
|
||||
/// </summary>
|
||||
private void ExecuteChangeSaveVideoDirectoryCommand()
|
||||
{
|
||||
string directory = DialogUtils.SetDownloadDirectory();
|
||||
if (directory == "") { return; }
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().SetSaveVideoRootPath(directory);
|
||||
PublishTip(isSucceed);
|
||||
|
||||
if (isSucceed)
|
||||
{
|
||||
SaveVideoDirectory = directory;
|
||||
}
|
||||
}
|
||||
|
||||
// 是否为不同视频分别创建文件夹事件
|
||||
private DelegateCommand isCreateFolderForMediaCommand;
|
||||
public DelegateCommand IsCreateFolderForMediaCommand => isCreateFolderForMediaCommand ?? (isCreateFolderForMediaCommand = new DelegateCommand(ExecuteIsCreateFolderForMediaCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 是否为不同视频分别创建文件夹事件
|
||||
/// </summary>
|
||||
private void ExecuteIsCreateFolderForMediaCommand()
|
||||
{
|
||||
AllowStatus isCreateFolderForMedia = IsCreateFolderForMedia ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().IsCreateFolderForMedia(isCreateFolderForMedia);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 是否在下载视频的同时下载弹幕事件
|
||||
private DelegateCommand isDownloadDanmakuCommand;
|
||||
public DelegateCommand IsDownloadDanmakuCommand => isDownloadDanmakuCommand ?? (isDownloadDanmakuCommand = new DelegateCommand(ExecuteIsDownloadDanmakuCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 是否在下载视频的同时下载弹幕事件
|
||||
/// </summary>
|
||||
private void ExecuteIsDownloadDanmakuCommand()
|
||||
{
|
||||
AllowStatus isDownloadDanmaku = IsDownloadDanmaku ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().IsDownloadDanmaku(isDownloadDanmaku);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// 是否在下载视频的同时下载封面事件
|
||||
private DelegateCommand isDownloadCoverCommand;
|
||||
public DelegateCommand IsDownloadCoverCommand => isDownloadCoverCommand ?? (isDownloadCoverCommand = new DelegateCommand(ExecuteIsDownloadCoverCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 是否在下载视频的同时下载封面事件
|
||||
/// </summary>
|
||||
private void ExecuteIsDownloadCoverCommand()
|
||||
{
|
||||
AllowStatus isDownloadCover = IsDownloadCover ? AllowStatus.YES : AllowStatus.NO;
|
||||
|
||||
bool isSucceed = SettingsManager.GetInstance().IsDownloadCover(isDownloadCover);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 返回VideoCodecs的字符串
|
||||
/// </summary>
|
||||
/// <param name="videoCodecs"></param>
|
||||
/// <returns></returns>
|
||||
private string GetVideoCodecsString(VideoCodecs videoCodecs)
|
||||
{
|
||||
string codec;
|
||||
switch (videoCodecs)
|
||||
{
|
||||
case Core.Settings.VideoCodecs.NONE:
|
||||
codec = "";
|
||||
break;
|
||||
case Core.Settings.VideoCodecs.AVC:
|
||||
codec = "H.264/AVC";
|
||||
break;
|
||||
case Core.Settings.VideoCodecs.HEVC:
|
||||
codec = "H.265/HEVC";
|
||||
break;
|
||||
default:
|
||||
codec = "";
|
||||
break;
|
||||
}
|
||||
return codec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回VideoCodecs
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
private VideoCodecs GetVideoCodecs(string str)
|
||||
{
|
||||
VideoCodecs videoCodecs;
|
||||
switch (str)
|
||||
{
|
||||
case "H.264/AVC":
|
||||
videoCodecs = Core.Settings.VideoCodecs.AVC;
|
||||
break;
|
||||
case "H.265/HEVC":
|
||||
videoCodecs = Core.Settings.VideoCodecs.HEVC;
|
||||
break;
|
||||
default:
|
||||
videoCodecs = Core.Settings.VideoCodecs.NONE;
|
||||
break;
|
||||
}
|
||||
return videoCodecs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送需要显示的tip
|
||||
/// </summary>
|
||||
/// <param name="isSucceed"></param>
|
||||
private void PublishTip(bool isSucceed)
|
||||
{
|
||||
if (isOnNavigatedTo) { return; }
|
||||
|
||||
if (isSucceed)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipSettingUpdated"));
|
||||
}
|
||||
else
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipSettingFailed"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
151
src/DownKyi/ViewModels/Toolbox/ViewBiliHelperViewModel.cs
Normal file
151
src/DownKyi/ViewModels/Toolbox/ViewBiliHelperViewModel.cs
Normal file
@ -0,0 +1,151 @@
|
||||
using DownKyi.Core.BiliApi.BiliUtils;
|
||||
using DownKyi.Core.Logging;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DownKyi.ViewModels.Toolbox
|
||||
{
|
||||
public class ViewBiliHelperViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageToolboxBiliHelper";
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private string avid;
|
||||
public string Avid
|
||||
{
|
||||
get { return avid; }
|
||||
set { SetProperty(ref avid, value); }
|
||||
}
|
||||
|
||||
private string bvid;
|
||||
public string Bvid
|
||||
{
|
||||
get { return bvid; }
|
||||
set { SetProperty(ref bvid, value); }
|
||||
}
|
||||
|
||||
private string danmakuUserID;
|
||||
public string DanmakuUserID
|
||||
{
|
||||
get { return danmakuUserID; }
|
||||
set { SetProperty(ref danmakuUserID, value); }
|
||||
}
|
||||
|
||||
private string userMid;
|
||||
public string UserMid
|
||||
{
|
||||
get { return userMid; }
|
||||
set { SetProperty(ref userMid, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewBiliHelperViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
#region 属性初始化
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// 输入avid事件
|
||||
private DelegateCommand<string> avidCommand;
|
||||
public DelegateCommand<string> AvidCommand => avidCommand ?? (avidCommand = new DelegateCommand<string>(ExecuteAvidCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 输入avid事件
|
||||
/// </summary>
|
||||
private async void ExecuteAvidCommand(string parameter)
|
||||
{
|
||||
if (parameter == null) { return; }
|
||||
if (!ParseEntrance.IsAvId(parameter)) { return; }
|
||||
|
||||
long avid = ParseEntrance.GetAvId(parameter);
|
||||
if (avid == -1) { return; }
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
Bvid = BvId.Av2Bv((ulong)avid);
|
||||
});
|
||||
}
|
||||
|
||||
// 输入bvid事件
|
||||
private DelegateCommand<string> bvidCommand;
|
||||
public DelegateCommand<string> BvidCommand => bvidCommand ?? (bvidCommand = new DelegateCommand<string>(ExecuteBvidCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 输入bvid事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private async void ExecuteBvidCommand(string parameter)
|
||||
{
|
||||
if (parameter == null) { return; }
|
||||
if (!ParseEntrance.IsBvId(parameter)) { return; }
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
ulong avid = BvId.Bv2Av(parameter);
|
||||
Avid = $"av{avid}";
|
||||
});
|
||||
}
|
||||
|
||||
// 访问网页事件
|
||||
private DelegateCommand gotoWebCommand;
|
||||
public DelegateCommand GotoWebCommand => gotoWebCommand ?? (gotoWebCommand = new DelegateCommand(ExecuteGotoWebCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 访问网页事件
|
||||
/// </summary>
|
||||
private void ExecuteGotoWebCommand()
|
||||
{
|
||||
string baseUrl = "https://www.bilibili.com/video/";
|
||||
System.Diagnostics.Process.Start(baseUrl + Bvid);
|
||||
}
|
||||
|
||||
// 查询弹幕发送者事件
|
||||
private DelegateCommand findDanmakuSenderCommand;
|
||||
public DelegateCommand FindDanmakuSenderCommand => findDanmakuSenderCommand ?? (findDanmakuSenderCommand = new DelegateCommand(ExecuteFindDanmakuSenderCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 查询弹幕发送者事件
|
||||
/// </summary>
|
||||
private async void ExecuteFindDanmakuSenderCommand()
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
UserMid = DanmakuSender.FindDanmakuSender(DanmakuUserID);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UserMid = null;
|
||||
|
||||
Core.Utils.Debug.Console.PrintLine("FindDanmakuSenderCommand()发生异常: {0}", e);
|
||||
LogManager.Error(Tag, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 访问用户空间事件
|
||||
private DelegateCommand visitUserSpaceCommand;
|
||||
public DelegateCommand VisitUserSpaceCommand => visitUserSpaceCommand ?? (visitUserSpaceCommand = new DelegateCommand(ExecuteVisitUserSpaceCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 访问用户空间事件
|
||||
/// </summary>
|
||||
private void ExecuteVisitUserSpaceCommand()
|
||||
{
|
||||
if (UserMid == null) { return; }
|
||||
|
||||
string baseUrl = "https://space.bilibili.com/";
|
||||
System.Diagnostics.Process.Start(baseUrl + UserMid);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
195
src/DownKyi/ViewModels/Toolbox/ViewDelogoViewModel.cs
Normal file
195
src/DownKyi/ViewModels/Toolbox/ViewDelogoViewModel.cs
Normal file
@ -0,0 +1,195 @@
|
||||
using DownKyi.Core.FFmpeg;
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Utils;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace DownKyi.ViewModels.Toolbox
|
||||
{
|
||||
public class ViewDelogoViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageToolboxDelogo";
|
||||
|
||||
// 是否正在执行去水印任务
|
||||
private bool isDelogo = false;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private string videoPath;
|
||||
public string VideoPath
|
||||
{
|
||||
get { return videoPath; }
|
||||
set { SetProperty(ref videoPath, value); }
|
||||
}
|
||||
|
||||
private int logoWidth;
|
||||
public int LogoWidth
|
||||
{
|
||||
get { return logoWidth; }
|
||||
set { SetProperty(ref logoWidth, value); }
|
||||
}
|
||||
|
||||
private int logoHeight;
|
||||
public int LogoHeight
|
||||
{
|
||||
get { return logoHeight; }
|
||||
set { SetProperty(ref logoHeight, value); }
|
||||
}
|
||||
|
||||
private int logoX;
|
||||
public int LogoX
|
||||
{
|
||||
get { return logoX; }
|
||||
set { SetProperty(ref logoX, value); }
|
||||
}
|
||||
|
||||
private int logoY;
|
||||
public int LogoY
|
||||
{
|
||||
get { return logoY; }
|
||||
set { SetProperty(ref logoY, value); }
|
||||
}
|
||||
|
||||
private string status;
|
||||
public string Status
|
||||
{
|
||||
get { return status; }
|
||||
set { SetProperty(ref status, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewDelogoViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
#region 属性初始化
|
||||
|
||||
VideoPath = string.Empty;
|
||||
|
||||
LogoWidth = -1;
|
||||
LogoHeight = -1;
|
||||
LogoX = -1;
|
||||
LogoY = -1;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// 选择视频事件
|
||||
private DelegateCommand selectVideoCommand;
|
||||
public DelegateCommand SelectVideoCommand => selectVideoCommand ?? (selectVideoCommand = new DelegateCommand(ExecuteSelectVideoCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 选择视频事件
|
||||
/// </summary>
|
||||
private void ExecuteSelectVideoCommand()
|
||||
{
|
||||
if (isDelogo)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipWaitTaskFinished"));
|
||||
return;
|
||||
}
|
||||
|
||||
VideoPath = SelectVideoFile();
|
||||
}
|
||||
|
||||
// 去水印事件
|
||||
private DelegateCommand delogoCommand;
|
||||
public DelegateCommand DelogoCommand => delogoCommand ?? (delogoCommand = new DelegateCommand(ExecuteDelogoCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 去水印事件
|
||||
/// </summary>
|
||||
private async void ExecuteDelogoCommand()
|
||||
{
|
||||
if (isDelogo)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipWaitTaskFinished"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (VideoPath == "")
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipNoSeletedVideo"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (LogoWidth == -1)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipInputRightLogoWidth"));
|
||||
return;
|
||||
}
|
||||
if (LogoHeight == -1)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipInputRightLogoHeight"));
|
||||
return;
|
||||
}
|
||||
if (LogoX == -1)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipInputRightLogoX"));
|
||||
return;
|
||||
}
|
||||
if (LogoY == -1)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipInputRightLogoY"));
|
||||
return;
|
||||
}
|
||||
|
||||
// 新文件名
|
||||
string newFileName = VideoPath.Insert(VideoPath.Length - 4, "_delogo");
|
||||
Status = string.Empty;
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
// 执行去水印程序
|
||||
isDelogo = true;
|
||||
FFmpegHelper.Delogo(VideoPath, newFileName, LogoX, LogoY, LogoWidth, LogoHeight, new Action<string>((output) =>
|
||||
{
|
||||
Status += output + "\n";
|
||||
}));
|
||||
isDelogo = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Status改变事件
|
||||
private DelegateCommand<object> statusCommand;
|
||||
public DelegateCommand<object> StatusCommand => statusCommand ?? (statusCommand = new DelegateCommand<object>(ExecuteStatusCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Status改变事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteStatusCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is TextBox output)) { return; }
|
||||
|
||||
// TextBox滚动到底部
|
||||
output.ScrollToEnd();
|
||||
}
|
||||
|
||||
#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 ""; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
178
src/DownKyi/ViewModels/Toolbox/ViewExtractMediaViewModel.cs
Normal file
178
src/DownKyi/ViewModels/Toolbox/ViewExtractMediaViewModel.cs
Normal file
@ -0,0 +1,178 @@
|
||||
using DownKyi.Core.FFmpeg;
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Utils;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace DownKyi.ViewModels.Toolbox
|
||||
{
|
||||
public class ViewExtractMediaViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageToolboxExtractMedia";
|
||||
|
||||
// 是否正在执行任务
|
||||
private bool isExtracting = false;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private string videoPath;
|
||||
public string VideoPath
|
||||
{
|
||||
get { return videoPath; }
|
||||
set { SetProperty(ref videoPath, value); }
|
||||
}
|
||||
|
||||
private string status;
|
||||
public string Status
|
||||
{
|
||||
get { return status; }
|
||||
set { SetProperty(ref status, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewExtractMediaViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
#region 属性初始化
|
||||
|
||||
VideoPath = string.Empty;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// 选择视频事件
|
||||
private DelegateCommand selectVideoCommand;
|
||||
public DelegateCommand SelectVideoCommand => selectVideoCommand ?? (selectVideoCommand = new DelegateCommand(ExecuteSelectVideoCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 选择视频事件
|
||||
/// </summary>
|
||||
private void ExecuteSelectVideoCommand()
|
||||
{
|
||||
if (isExtracting)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipWaitTaskFinished"));
|
||||
return;
|
||||
}
|
||||
|
||||
VideoPath = SelectVideoFile();
|
||||
}
|
||||
|
||||
// 提取音频事件
|
||||
private DelegateCommand extractAudioCommand;
|
||||
public DelegateCommand ExtractAudioCommand => extractAudioCommand ?? (extractAudioCommand = new DelegateCommand(ExecuteExtractAudioCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 提取音频事件
|
||||
/// </summary>
|
||||
private async void ExecuteExtractAudioCommand()
|
||||
{
|
||||
if (isExtracting)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipWaitTaskFinished"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (VideoPath == "")
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipNoSeletedVideo"));
|
||||
return;
|
||||
}
|
||||
|
||||
// 音频文件名
|
||||
string audioFileName = VideoPath.Remove(VideoPath.Length - 4, 4) + ".aac";
|
||||
Status = string.Empty;
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
// 执行提取音频程序
|
||||
isExtracting = true;
|
||||
FFmpegHelper.ExtractAudio(VideoPath, audioFileName, new Action<string>((output) =>
|
||||
{
|
||||
Status += output + "\n";
|
||||
}));
|
||||
isExtracting = false;
|
||||
});
|
||||
}
|
||||
|
||||
// 提取视频事件
|
||||
private DelegateCommand extractVideoCommand;
|
||||
public DelegateCommand ExtractVideoCommand => extractVideoCommand ?? (extractVideoCommand = new DelegateCommand(ExecuteExtractVideoCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 提取视频事件
|
||||
/// </summary>
|
||||
private async void ExecuteExtractVideoCommand()
|
||||
{
|
||||
if (isExtracting)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipWaitTaskFinished"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (VideoPath == "")
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipNoSeletedVideo"));
|
||||
return;
|
||||
}
|
||||
|
||||
// 视频文件名
|
||||
string videoFileName = VideoPath.Remove(VideoPath.Length - 4, 4) + "_onlyVideo.mp4";
|
||||
Status = string.Empty;
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
// 执行提取视频程序
|
||||
isExtracting = true;
|
||||
FFmpegHelper.ExtractVideo(VideoPath, videoFileName, new Action<string>((output) =>
|
||||
{
|
||||
Status += output + "\n";
|
||||
}));
|
||||
isExtracting = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Status改变事件
|
||||
private DelegateCommand<object> statusCommand;
|
||||
public DelegateCommand<object> StatusCommand => statusCommand ?? (statusCommand = new DelegateCommand<object>(ExecuteStatusCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Status改变事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteStatusCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is TextBox output)) { return; }
|
||||
|
||||
// TextBox滚动到底部
|
||||
output.ScrollToEnd();
|
||||
}
|
||||
|
||||
#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 ""; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
125
src/DownKyi/ViewModels/ViewDownloadManagerViewModel.cs
Normal file
125
src/DownKyi/ViewModels/ViewDownloadManagerViewModel.cs
Normal file
@ -0,0 +1,125 @@
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Images;
|
||||
using DownKyi.Models;
|
||||
using DownKyi.Utils;
|
||||
using DownKyi.ViewModels.DownloadManager;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DownKyi.ViewModels
|
||||
{
|
||||
public class ViewDownloadManagerViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageDownloadManager";
|
||||
|
||||
private readonly IRegionManager regionManager;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private VectorImage arrowBack;
|
||||
public VectorImage ArrowBack
|
||||
{
|
||||
get { return arrowBack; }
|
||||
set { SetProperty(ref arrowBack, value); }
|
||||
}
|
||||
|
||||
private List<TabHeader> tabHeaders;
|
||||
public List<TabHeader> TabHeaders
|
||||
{
|
||||
get { return tabHeaders; }
|
||||
set { SetProperty(ref tabHeaders, value); }
|
||||
}
|
||||
|
||||
private int selectTabId;
|
||||
public int SelectTabId
|
||||
{
|
||||
get { return selectTabId; }
|
||||
set { SetProperty(ref selectTabId, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewDownloadManagerViewModel(IRegionManager regionManager, IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
this.regionManager = regionManager;
|
||||
|
||||
#region 属性初始化
|
||||
|
||||
ArrowBack = NavigationIcon.Instance().ArrowBack;
|
||||
ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark");
|
||||
|
||||
TabHeaders = new List<TabHeader>
|
||||
{
|
||||
new TabHeader { Id = 0, Image = NormalIcon.Instance().Downloading, Title = DictionaryResource.GetString("Downloading") },
|
||||
new TabHeader { Id = 1, Image = NormalIcon.Instance().DownloadFinished, Title = DictionaryResource.GetString("DownloadFinished") }
|
||||
};
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
// 左侧tab点击事件
|
||||
private DelegateCommand<object> leftTabHeadersCommand;
|
||||
public DelegateCommand<object> LeftTabHeadersCommand => leftTabHeadersCommand ?? (leftTabHeadersCommand = new DelegateCommand<object>(ExecuteLeftTabHeadersCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 左侧tab点击事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteLeftTabHeadersCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is TabHeader tabHeader)) { return; }
|
||||
|
||||
NavigationParameters param = new NavigationParameters();
|
||||
|
||||
switch (tabHeader.Id)
|
||||
{
|
||||
case 0:
|
||||
regionManager.RequestNavigate("DownloadManagerContentRegion", ViewDownloadingViewModel.Tag, param);
|
||||
break;
|
||||
case 1:
|
||||
regionManager.RequestNavigate("DownloadManagerContentRegion", ViewDownloadFinishedViewModel.Tag, param);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 导航到VideoDetail页面时执行
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
//// 进入设置页面时显示的设置项
|
||||
SelectTabId = 0;
|
||||
regionManager.RequestNavigate("DownloadManagerContentRegion", ViewDownloadingViewModel.Tag, new NavigationParameters());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
439
src/DownKyi/ViewModels/ViewIndexViewModel.cs
Normal file
439
src/DownKyi/ViewModels/ViewIndexViewModel.cs
Normal file
@ -0,0 +1,439 @@
|
||||
using DownKyi.Core.BiliApi.BiliUtils;
|
||||
using DownKyi.Core.BiliApi.Login;
|
||||
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;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace DownKyi.ViewModels
|
||||
{
|
||||
public class ViewIndexViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageIndex";
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private Visibility loginPanelVisibility;
|
||||
public Visibility LoginPanelVisibility
|
||||
{
|
||||
get { return loginPanelVisibility; }
|
||||
set { SetProperty(ref loginPanelVisibility, value); }
|
||||
}
|
||||
|
||||
private string userName;
|
||||
public string UserName
|
||||
{
|
||||
get { return userName; }
|
||||
set { SetProperty(ref userName, value); }
|
||||
}
|
||||
|
||||
private BitmapImage header;
|
||||
public BitmapImage Header
|
||||
{
|
||||
get { return header; }
|
||||
set { SetProperty(ref header, value); }
|
||||
}
|
||||
|
||||
private VectorImage textLogo;
|
||||
public VectorImage TextLogo
|
||||
{
|
||||
get { return textLogo; }
|
||||
set { SetProperty(ref textLogo, value); }
|
||||
}
|
||||
|
||||
private string inputText;
|
||||
public string InputText
|
||||
{
|
||||
get { return inputText; }
|
||||
set { SetProperty(ref inputText, value); }
|
||||
}
|
||||
|
||||
private VectorImage generalSearch;
|
||||
public VectorImage GeneralSearch
|
||||
{
|
||||
get { return generalSearch; }
|
||||
set { SetProperty(ref generalSearch, value); }
|
||||
}
|
||||
|
||||
private VectorImage settings;
|
||||
public VectorImage Settings
|
||||
{
|
||||
get { return settings; }
|
||||
set { SetProperty(ref settings, value); }
|
||||
}
|
||||
|
||||
private VectorImage downloadManager;
|
||||
public VectorImage DownloadManager
|
||||
{
|
||||
get { return downloadManager; }
|
||||
set { SetProperty(ref downloadManager, value); }
|
||||
}
|
||||
|
||||
private VectorImage toolbox;
|
||||
public VectorImage Toolbox
|
||||
{
|
||||
get { return toolbox; }
|
||||
set { SetProperty(ref toolbox, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public ViewIndexViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
#region 属性初始化
|
||||
|
||||
Header = new BitmapImage(new Uri("pack://application:,,,/Resources/default_header.jpg"));
|
||||
|
||||
TextLogo = LogoIcon.Instance().TextLogo;
|
||||
TextLogo.Fill = DictionaryResource.GetColor("ColorPrimary");
|
||||
|
||||
GeneralSearch = ButtonIcon.Instance().GeneralSearch;
|
||||
GeneralSearch.Fill = DictionaryResource.GetColor("ColorPrimary");
|
||||
|
||||
Settings = ButtonIcon.Instance().Settings;
|
||||
Settings.Fill = DictionaryResource.GetColor("ColorPrimary");
|
||||
|
||||
DownloadManager = ButtonIcon.Instance().DownloadManage;
|
||||
DownloadManager.Fill = DictionaryResource.GetColor("ColorPrimary");
|
||||
|
||||
Toolbox = ButtonIcon.Instance().Toolbox;
|
||||
Toolbox.Fill = DictionaryResource.GetColor("ColorPrimary");
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// View加载后执行的事件
|
||||
public DelegateCommand loadedCommand;
|
||||
public DelegateCommand LoadedCommand => loadedCommand ?? (loadedCommand = new DelegateCommand(ExecuteViewLoaded));
|
||||
|
||||
/// <summary>
|
||||
/// View加载后执行
|
||||
/// </summary>
|
||||
private void ExecuteViewLoaded() { }
|
||||
|
||||
// 输入确认事件
|
||||
public DelegateCommand inputCommand;
|
||||
public DelegateCommand InputCommand => inputCommand ?? (inputCommand = new DelegateCommand(ExecuteInput));
|
||||
|
||||
/// <summary>
|
||||
/// 处理输入事件
|
||||
/// </summary>
|
||||
private void ExecuteInput()
|
||||
{
|
||||
EnterBili();
|
||||
}
|
||||
|
||||
// 登录事件
|
||||
private DelegateCommand loginCommand;
|
||||
public DelegateCommand LoginCommand => loginCommand ?? (loginCommand = new DelegateCommand(ExecuteLogin));
|
||||
|
||||
/// <summary>
|
||||
/// 进入登录页面
|
||||
/// </summary>
|
||||
private void ExecuteLogin()
|
||||
{
|
||||
if (UserName == null)
|
||||
{
|
||||
NavigationView(ViewLoginViewModel.Tag, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 进入用户空间
|
||||
var userInfo = SettingsManager.GetInstance().GetUserInfo();
|
||||
if (userInfo != null && userInfo.Mid != -1)
|
||||
{
|
||||
NavigationView(ViewMySpaceViewModel.Tag, userInfo.Mid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 进入设置页面
|
||||
private DelegateCommand settingsCommand;
|
||||
public DelegateCommand SettingsCommand => settingsCommand ?? (settingsCommand = new DelegateCommand(ExecuteSettingsCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 进入设置页面
|
||||
/// </summary>
|
||||
private void ExecuteSettingsCommand()
|
||||
{
|
||||
NavigationView(ViewSettingsViewModel.Tag, null);
|
||||
}
|
||||
|
||||
// 进入下载管理页面
|
||||
private DelegateCommand downloadManagerCommand;
|
||||
public DelegateCommand DownloadManagerCommand => downloadManagerCommand ?? (downloadManagerCommand = new DelegateCommand(ExecuteDownloadManagerCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 进入下载管理页面
|
||||
/// </summary>
|
||||
private void ExecuteDownloadManagerCommand()
|
||||
{
|
||||
NavigationView(ViewDownloadManagerViewModel.Tag, null);
|
||||
}
|
||||
|
||||
// 进入工具箱页面
|
||||
private DelegateCommand toolboxCommand;
|
||||
public DelegateCommand ToolboxCommand => toolboxCommand ?? (toolboxCommand = new DelegateCommand(ExecuteToolboxCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 进入工具箱页面
|
||||
/// </summary>
|
||||
private void ExecuteToolboxCommand()
|
||||
{
|
||||
NavigationView(ViewToolboxViewModel.Tag, null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 业务逻辑
|
||||
|
||||
/// <summary>
|
||||
/// 进入B站链接的处理逻辑,
|
||||
/// 只负责处理输入,并跳转到视频详情页。<para/>
|
||||
/// 不是支持的格式,则进入搜索页面。
|
||||
/// 支持的格式有:<para/>
|
||||
/// av号:av170001, AV170001, https://www.bilibili.com/video/av170001 <para/>
|
||||
/// BV号:BV17x411w7KC, https://www.bilibili.com/video/BV17x411w7KC <para/>
|
||||
/// 番剧(电影、电视剧)ss号:ss32982, SS32982, https://www.bilibili.com/bangumi/play/ss32982 <para/>
|
||||
/// 番剧(电影、电视剧)ep号:ep317925, EP317925, https://www.bilibili.com/bangumi/play/ep317925 <para/>
|
||||
/// 番剧(电影、电视剧)md号:md28228367, MD28228367, https://www.bilibili.com/bangumi/media/md28228367 <para/>
|
||||
/// 课程ss号:https://www.bilibili.com/cheese/play/ss205 <para/>
|
||||
/// 课程ep号:https://www.bilibili.com/cheese/play/ep3489 <para/>
|
||||
/// 收藏夹:ml1329019876, ML1329019876, https://www.bilibili.com/medialist/detail/ml1329019876 <para/>
|
||||
/// 用户空间:uid928123, UID928123, uid:928123, UID:928123, https://space.bilibili.com/928123
|
||||
/// </summary>
|
||||
private void EnterBili()
|
||||
{
|
||||
if (InputText == null || InputText == string.Empty) { return; }
|
||||
|
||||
LogManager.Debug(Tag, $"InputText: {InputText}");
|
||||
|
||||
// 视频
|
||||
if (ParseEntrance.IsAvId(InputText))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.VideoUrl}{InputText.ToLower()}");
|
||||
}
|
||||
else if (ParseEntrance.IsAvUrl(InputText))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
|
||||
}
|
||||
else if (ParseEntrance.IsBvId(InputText))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.VideoUrl}{InputText}");
|
||||
}
|
||||
else if (ParseEntrance.IsBvUrl(InputText))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
|
||||
}
|
||||
// 番剧(电影、电视剧)
|
||||
else if (ParseEntrance.IsBangumiSeasonId(InputText))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiUrl}{InputText.ToLower()}");
|
||||
}
|
||||
else if (ParseEntrance.IsBangumiSeasonUrl(InputText))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
|
||||
}
|
||||
else if (ParseEntrance.IsBangumiEpisodeId(InputText))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiUrl}{InputText.ToLower()}");
|
||||
}
|
||||
else if (ParseEntrance.IsBangumiEpisodeUrl(InputText))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
|
||||
}
|
||||
else if (ParseEntrance.IsBangumiMediaId(InputText))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, $"{ParseEntrance.BangumiMediaUrl}{InputText.ToLower()}");
|
||||
}
|
||||
else if (ParseEntrance.IsBangumiMediaUrl(InputText))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
|
||||
}
|
||||
// 课程
|
||||
else if (ParseEntrance.IsCheeseSeasonUrl(InputText) || ParseEntrance.IsCheeseEpisodeUrl(InputText))
|
||||
{
|
||||
NavigationView(ViewVideoDetailViewModel.Tag, InputText);
|
||||
}
|
||||
// 用户(参数传入mid)
|
||||
else if (ParseEntrance.IsUserId(InputText))
|
||||
{
|
||||
NavigateToViewUserSpace(ParseEntrance.GetUserId(InputText));
|
||||
}
|
||||
else if (ParseEntrance.IsUserUrl(InputText))
|
||||
{
|
||||
NavigateToViewUserSpace(ParseEntrance.GetUserId(InputText));
|
||||
}
|
||||
// 收藏夹
|
||||
else if (ParseEntrance.IsFavoritesId(InputText))
|
||||
{
|
||||
NavigationView(ViewPublicFavoritesViewModel.Tag, ParseEntrance.GetFavoritesId(InputText));
|
||||
}
|
||||
else if (ParseEntrance.IsFavoritesUrl(InputText))
|
||||
{
|
||||
NavigationView(ViewPublicFavoritesViewModel.Tag, ParseEntrance.GetFavoritesId(InputText));
|
||||
}
|
||||
// TODO 关键词搜索
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
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>
|
||||
private async void UpdateUserInfo()
|
||||
{
|
||||
LoginPanelVisibility = Visibility.Hidden;
|
||||
|
||||
// 检查本地是否存在login文件,没有则说明未登录
|
||||
if (!File.Exists(StorageManager.GetLogin()))
|
||||
{
|
||||
LoginPanelVisibility = Visibility.Visible;
|
||||
Header = new BitmapImage(new Uri("pack://application:,,,/Resources/default_header.jpg"));
|
||||
UserName = null;
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Run(new Action(() =>
|
||||
{
|
||||
// 获取用户信息
|
||||
var userInfo = LoginInfo.GetUserInfoForNavigation();
|
||||
if (userInfo != null)
|
||||
{
|
||||
SettingsManager.GetInstance().SetUserInfo(new UserInfoSettings
|
||||
{
|
||||
Mid = userInfo.Mid,
|
||||
Name = userInfo.Name,
|
||||
IsLogin = userInfo.IsLogin,
|
||||
IsVip = userInfo.VipStatus == 1
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
SettingsManager.GetInstance().SetUserInfo(new UserInfoSettings
|
||||
{
|
||||
Mid = -1,
|
||||
Name = "",
|
||||
IsLogin = false,
|
||||
IsVip = false
|
||||
});
|
||||
}
|
||||
|
||||
PropertyChangeAsync(new Action(() =>
|
||||
{
|
||||
LoginPanelVisibility = Visibility.Visible;
|
||||
|
||||
if (userInfo != null)
|
||||
{
|
||||
if (userInfo.Face != null)
|
||||
{
|
||||
Header = new StorageHeader().GetHeaderThumbnail(userInfo.Mid, userInfo.Name, userInfo.Face, 36, 36);
|
||||
}
|
||||
else
|
||||
{
|
||||
Header = new BitmapImage(new Uri("pack://application:,,,/Resources/default_header.jpg"));
|
||||
}
|
||||
UserName = userInfo.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
Header = new BitmapImage(new Uri("pack://application:,,,/Resources/default_header.jpg"));
|
||||
UserName = null;
|
||||
}
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
DownloadManager = ButtonIcon.Instance().DownloadManage;
|
||||
DownloadManager.Height = 27;
|
||||
DownloadManager.Width = 32;
|
||||
DownloadManager.Fill = DictionaryResource.GetColor("ColorPrimary");
|
||||
|
||||
// 根据传入参数不同执行不同任务
|
||||
string parameter = navigationContext.Parameters.GetValue<string>("Parameter");
|
||||
if (parameter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// 启动
|
||||
if (parameter == "start")
|
||||
{
|
||||
UpdateUserInfo();
|
||||
}
|
||||
// 从登录页面返回
|
||||
if (parameter == "login")
|
||||
{
|
||||
UpdateUserInfo();
|
||||
}
|
||||
// 注销
|
||||
if (parameter == "logout")
|
||||
{
|
||||
UpdateUserInfo();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
251
src/DownKyi/ViewModels/ViewLoginViewModel.cs
Normal file
251
src/DownKyi/ViewModels/ViewLoginViewModel.cs
Normal file
@ -0,0 +1,251 @@
|
||||
using DownKyi.Core.BiliApi.Login;
|
||||
using DownKyi.Core.Logging;
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Images;
|
||||
using DownKyi.Utils;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace DownKyi.ViewModels
|
||||
{
|
||||
public class ViewLoginViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageLogin";
|
||||
|
||||
private CancellationTokenSource tokenSource;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private VectorImage arrowBack;
|
||||
public VectorImage ArrowBack
|
||||
{
|
||||
get { return arrowBack; }
|
||||
set { SetProperty(ref arrowBack, value); }
|
||||
}
|
||||
|
||||
private BitmapImage loginQRCode;
|
||||
public BitmapImage LoginQRCode
|
||||
{
|
||||
get { return loginQRCode; }
|
||||
set { SetProperty(ref loginQRCode, value); }
|
||||
}
|
||||
|
||||
private double loginQRCodeOpacity;
|
||||
public double LoginQRCodeOpacity
|
||||
{
|
||||
get { return loginQRCodeOpacity; }
|
||||
set { SetProperty(ref loginQRCodeOpacity, value); }
|
||||
}
|
||||
|
||||
private Visibility loginQRCodeStatus;
|
||||
public Visibility LoginQRCodeStatus
|
||||
{
|
||||
get { return loginQRCodeStatus; }
|
||||
set { SetProperty(ref loginQRCodeStatus, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public ViewLoginViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
#region 属性初始化
|
||||
|
||||
ArrowBack = NavigationIcon.Instance().ArrowBack;
|
||||
ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark");
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// 返回
|
||||
private DelegateCommand backSpaceCommand;
|
||||
public DelegateCommand BackSpaceCommand => backSpaceCommand ?? (backSpaceCommand = new DelegateCommand(ExecuteBackSpace));
|
||||
|
||||
/// <summary>
|
||||
/// 返回
|
||||
/// </summary>
|
||||
private void ExecuteBackSpace()
|
||||
{
|
||||
// 初始化状态
|
||||
InitStatus();
|
||||
|
||||
// 结束任务
|
||||
tokenSource.Cancel();
|
||||
|
||||
NavigationParam parameter = new NavigationParam
|
||||
{
|
||||
ViewName = ParentView,
|
||||
ParentViewName = null,
|
||||
Parameter = "login"
|
||||
};
|
||||
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 业务逻辑
|
||||
|
||||
/// <summary>
|
||||
/// 登录
|
||||
/// </summary>
|
||||
private void Login()
|
||||
{
|
||||
var loginUrl = LoginQR.GetLoginUrl();
|
||||
if (loginUrl == null) { return; }
|
||||
|
||||
if (loginUrl.Status != true)
|
||||
{
|
||||
ExecuteBackSpace();
|
||||
return;
|
||||
}
|
||||
|
||||
if (loginUrl.Data == null || loginUrl.Data.Url == null)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("GetLoginUrlFailed"));
|
||||
return;
|
||||
}
|
||||
|
||||
PropertyChangeAsync(new Action(() => { LoginQRCode = LoginQR.GetLoginQRCode(loginUrl.Data.Url); }));
|
||||
Core.Utils.Debug.Console.PrintLine(loginUrl.Data.Url + "\n");
|
||||
LogManager.Debug(Tag, loginUrl.Data.Url);
|
||||
|
||||
GetLoginStatus(loginUrl.Data.OauthKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 循环查询登录状态
|
||||
/// </summary>
|
||||
/// <param name="oauthKey"></param>
|
||||
private void GetLoginStatus(string oauthKey)
|
||||
{
|
||||
CancellationToken cancellationToken = tokenSource.Token;
|
||||
while (true)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
var loginStatus = LoginQR.GetLoginStatus(oauthKey);
|
||||
if (loginStatus == null) { continue; }
|
||||
|
||||
Core.Utils.Debug.Console.PrintLine(loginStatus.Code + "\n" + loginStatus.Message + "\n" + loginStatus.Url + "\n");
|
||||
|
||||
switch (loginStatus.Code)
|
||||
{
|
||||
case -1:
|
||||
// 没有这个oauthKey
|
||||
|
||||
// 发送通知
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("LoginKeyError"));
|
||||
LogManager.Info(Tag, DictionaryResource.GetString("LoginKeyError"));
|
||||
|
||||
// 取消任务
|
||||
tokenSource.Cancel();
|
||||
|
||||
// 创建新任务
|
||||
PropertyChangeAsync(new Action(() => { Task.Run(Login, (tokenSource = new CancellationTokenSource()).Token); }));
|
||||
break;
|
||||
case -2:
|
||||
// 不匹配的oauthKey,超时或已确认的oauthKey
|
||||
|
||||
// 发送通知
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("LoginTimeOut"));
|
||||
LogManager.Info(Tag, DictionaryResource.GetString("LoginTimeOut"));
|
||||
|
||||
// 取消任务
|
||||
tokenSource.Cancel();
|
||||
|
||||
// 创建新任务
|
||||
PropertyChangeAsync(new Action(() => { Task.Run(Login, (tokenSource = new CancellationTokenSource()).Token); }));
|
||||
break;
|
||||
case -4:
|
||||
// 未扫码
|
||||
break;
|
||||
case -5:
|
||||
// 已扫码,未确认
|
||||
PropertyChangeAsync(new Action(() =>
|
||||
{
|
||||
LoginQRCodeStatus = Visibility.Visible;
|
||||
LoginQRCodeOpacity = 0.3;
|
||||
}));
|
||||
break;
|
||||
case 0:
|
||||
// 确认登录
|
||||
|
||||
// 发送通知
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("LoginSuccessful"));
|
||||
LogManager.Info(Tag, DictionaryResource.GetString("LoginSuccessful"));
|
||||
|
||||
// 保存登录信息
|
||||
try
|
||||
{
|
||||
bool isSucceed = LoginHelper.SaveLoginInfoCookies(loginStatus.Url);
|
||||
if (!isSucceed)
|
||||
{
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("LoginFailed"));
|
||||
LogManager.Error(Tag, DictionaryResource.GetString("LoginFailed"));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Core.Utils.Debug.Console.PrintLine("PageLogin 保存登录信息发生异常: {0}", e);
|
||||
LogManager.Error(e);
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("LoginFailed"));
|
||||
}
|
||||
|
||||
// TODO 其他操作
|
||||
|
||||
|
||||
// 取消任务
|
||||
Thread.Sleep(3000);
|
||||
PropertyChangeAsync(new Action(() => { ExecuteBackSpace(); }));
|
||||
break;
|
||||
}
|
||||
|
||||
// 判断是否该结束线程,若为true,跳出while循环
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
Core.Utils.Debug.Console.PrintLine("停止Login线程,跳出while循环");
|
||||
LogManager.Debug(Tag, "登录操作结束");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化状态
|
||||
/// </summary>
|
||||
private void InitStatus()
|
||||
{
|
||||
LoginQRCode = null;
|
||||
LoginQRCodeOpacity = 1;
|
||||
LoginQRCodeStatus = Visibility.Hidden;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 导航到Login页面时执行
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
// 初始化状态
|
||||
InitStatus();
|
||||
|
||||
Task.Run(Login, (tokenSource = new CancellationTokenSource()).Token);
|
||||
//await loginTask;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
40
src/DownKyi/ViewModels/ViewMySpaceViewModel.cs
Normal file
40
src/DownKyi/ViewModels/ViewMySpaceViewModel.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Regions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DownKyi.ViewModels
|
||||
{
|
||||
public class ViewMySpaceViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageMySpace";
|
||||
|
||||
// mid
|
||||
private long mid;
|
||||
|
||||
public ViewMySpaceViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收mid参数
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
// 根据传入参数不同执行不同任务
|
||||
long parameter = navigationContext.Parameters.GetValue<long>("Parameter");
|
||||
if (parameter == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mid = parameter;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
39
src/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs
Normal file
39
src/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Regions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DownKyi.ViewModels
|
||||
{
|
||||
public class ViewPublicFavoritesViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PagePublicFavorites";
|
||||
|
||||
// 收藏夹id
|
||||
private long favoritesId;
|
||||
|
||||
public ViewPublicFavoritesViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收收藏夹id参数
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
// 根据传入参数不同执行不同任务
|
||||
long parameter = navigationContext.Parameters.GetValue<long>("Parameter");
|
||||
if (parameter == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
favoritesId = parameter;
|
||||
}
|
||||
}
|
||||
}
|
137
src/DownKyi/ViewModels/ViewSettingsViewModel.cs
Normal file
137
src/DownKyi/ViewModels/ViewSettingsViewModel.cs
Normal file
@ -0,0 +1,137 @@
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Images;
|
||||
using DownKyi.Models;
|
||||
using DownKyi.Utils;
|
||||
using DownKyi.ViewModels.Settings;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DownKyi.ViewModels
|
||||
{
|
||||
public class ViewSettingsViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageSettings";
|
||||
|
||||
private readonly IRegionManager regionManager;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private VectorImage arrowBack;
|
||||
public VectorImage ArrowBack
|
||||
{
|
||||
get { return arrowBack; }
|
||||
set { SetProperty(ref arrowBack, value); }
|
||||
}
|
||||
|
||||
private List<TabHeader> tabHeaders;
|
||||
public List<TabHeader> TabHeaders
|
||||
{
|
||||
get { return tabHeaders; }
|
||||
set { SetProperty(ref tabHeaders, value); }
|
||||
}
|
||||
|
||||
private int selectTabId;
|
||||
public int SelectTabId
|
||||
{
|
||||
get { return selectTabId; }
|
||||
set { SetProperty(ref selectTabId, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public ViewSettingsViewModel(IRegionManager regionManager, IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
this.regionManager = regionManager;
|
||||
|
||||
#region 属性初始化
|
||||
|
||||
ArrowBack = NavigationIcon.Instance().ArrowBack;
|
||||
ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark");
|
||||
|
||||
TabHeaders = new List<TabHeader>
|
||||
{
|
||||
new TabHeader { Id = 0, Title = DictionaryResource.GetString("Basic") },
|
||||
new TabHeader { Id = 1, Title = DictionaryResource.GetString("Network") },
|
||||
new TabHeader { Id = 2, Title = DictionaryResource.GetString("Video") },
|
||||
new TabHeader { Id = 3, Title = DictionaryResource.GetString("SettingDanmaku") },
|
||||
new TabHeader { Id = 4, Title = DictionaryResource.GetString("About") }
|
||||
};
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
// 左侧tab点击事件
|
||||
private DelegateCommand<object> leftTabHeadersCommand;
|
||||
public DelegateCommand<object> LeftTabHeadersCommand => leftTabHeadersCommand ?? (leftTabHeadersCommand = new DelegateCommand<object>(ExecuteLeftTabHeadersCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 左侧tab点击事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteLeftTabHeadersCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is TabHeader tabHeader)) { return; }
|
||||
|
||||
NavigationParameters param = new NavigationParameters();
|
||||
|
||||
switch (tabHeader.Id)
|
||||
{
|
||||
case 0:
|
||||
regionManager.RequestNavigate("SettingsContentRegion", ViewBasicViewModel.Tag, param);
|
||||
break;
|
||||
case 1:
|
||||
regionManager.RequestNavigate("SettingsContentRegion", ViewNetworkViewModel.Tag, param);
|
||||
break;
|
||||
case 2:
|
||||
regionManager.RequestNavigate("SettingsContentRegion", ViewVideoViewModel.Tag, param);
|
||||
break;
|
||||
case 3:
|
||||
regionManager.RequestNavigate("SettingsContentRegion", ViewDanmakuViewModel.Tag, param);
|
||||
break;
|
||||
case 4:
|
||||
regionManager.RequestNavigate("SettingsContentRegion", ViewAboutViewModel.Tag, param);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 导航到VideoDetail页面时执行
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
// 进入设置页面时显示的设置项
|
||||
SelectTabId = 0;
|
||||
regionManager.RequestNavigate("SettingsContentRegion", ViewBasicViewModel.Tag, new NavigationParameters());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
128
src/DownKyi/ViewModels/ViewToolboxViewModel.cs
Normal file
128
src/DownKyi/ViewModels/ViewToolboxViewModel.cs
Normal file
@ -0,0 +1,128 @@
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Images;
|
||||
using DownKyi.Models;
|
||||
using DownKyi.Utils;
|
||||
using DownKyi.ViewModels.Toolbox;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DownKyi.ViewModels
|
||||
{
|
||||
public class ViewToolboxViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageToolbox";
|
||||
|
||||
private readonly IRegionManager regionManager;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private VectorImage arrowBack;
|
||||
public VectorImage ArrowBack
|
||||
{
|
||||
get { return arrowBack; }
|
||||
set { SetProperty(ref arrowBack, value); }
|
||||
}
|
||||
|
||||
private List<TabHeader> tabHeaders;
|
||||
public List<TabHeader> TabHeaders
|
||||
{
|
||||
get { return tabHeaders; }
|
||||
set { SetProperty(ref tabHeaders, value); }
|
||||
}
|
||||
|
||||
private int selectTabId;
|
||||
public int SelectTabId
|
||||
{
|
||||
get { return selectTabId; }
|
||||
set { SetProperty(ref selectTabId, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ViewToolboxViewModel(IRegionManager regionManager, IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
this.regionManager = regionManager;
|
||||
|
||||
#region 属性初始化
|
||||
|
||||
ArrowBack = NavigationIcon.Instance().ArrowBack;
|
||||
ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark");
|
||||
|
||||
TabHeaders = new List<TabHeader>
|
||||
{
|
||||
new TabHeader { Id = 0, Title = DictionaryResource.GetString("BiliHelper") },
|
||||
new TabHeader { Id = 1, Title = DictionaryResource.GetString("Delogo") },
|
||||
new TabHeader { Id = 2, Title = DictionaryResource.GetString("ExtractMedia") }
|
||||
};
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
// 左侧tab点击事件
|
||||
private DelegateCommand<object> leftTabHeadersCommand;
|
||||
public DelegateCommand<object> LeftTabHeadersCommand => leftTabHeadersCommand ?? (leftTabHeadersCommand = new DelegateCommand<object>(ExecuteLeftTabHeadersCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 左侧tab点击事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteLeftTabHeadersCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is TabHeader tabHeader)) { return; }
|
||||
|
||||
NavigationParameters param = new NavigationParameters();
|
||||
|
||||
switch (tabHeader.Id)
|
||||
{
|
||||
case 0:
|
||||
regionManager.RequestNavigate("ToolboxContentRegion", ViewBiliHelperViewModel.Tag, param);
|
||||
break;
|
||||
case 1:
|
||||
regionManager.RequestNavigate("ToolboxContentRegion", ViewDelogoViewModel.Tag, param);
|
||||
break;
|
||||
case 2:
|
||||
regionManager.RequestNavigate("ToolboxContentRegion", ViewExtractMediaViewModel.Tag, param);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 导航到VideoDetail页面时执行
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
// 进入设置页面时显示的设置项
|
||||
SelectTabId = 0;
|
||||
regionManager.RequestNavigate("ToolboxContentRegion", ViewBiliHelperViewModel.Tag, new NavigationParameters());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
40
src/DownKyi/ViewModels/ViewUserSpaceViewModel.cs
Normal file
40
src/DownKyi/ViewModels/ViewUserSpaceViewModel.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Regions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DownKyi.ViewModels
|
||||
{
|
||||
public class ViewUserSpaceViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageUserSpace";
|
||||
|
||||
// mid
|
||||
private long mid;
|
||||
|
||||
public ViewUserSpaceViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收mid参数
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
// 根据传入参数不同执行不同任务
|
||||
long parameter = navigationContext.Parameters.GetValue<long>("Parameter");
|
||||
if (parameter == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mid = parameter;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
664
src/DownKyi/ViewModels/ViewVideoDetailViewModel.cs
Normal file
664
src/DownKyi/ViewModels/ViewVideoDetailViewModel.cs
Normal file
@ -0,0 +1,664 @@
|
||||
using DownKyi.Core.BiliApi.BiliUtils;
|
||||
using DownKyi.Core.Logging;
|
||||
using DownKyi.Core.Settings;
|
||||
using DownKyi.CustomControl;
|
||||
using DownKyi.Events;
|
||||
using DownKyi.Images;
|
||||
using DownKyi.Models;
|
||||
using DownKyi.Services;
|
||||
using DownKyi.Utils;
|
||||
using DownKyi.ViewModels.Dialogs;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
using Prism.Services.Dialogs;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace DownKyi.ViewModels
|
||||
{
|
||||
public class ViewVideoDetailViewModel : BaseViewModel
|
||||
{
|
||||
public const string Tag = "PageVideoDetail";
|
||||
|
||||
private readonly IDialogService dialogService;
|
||||
|
||||
#region 页面属性申明
|
||||
|
||||
private VectorImage arrowBack;
|
||||
public VectorImage ArrowBack
|
||||
{
|
||||
get { return arrowBack; }
|
||||
set { SetProperty(ref arrowBack, value); }
|
||||
}
|
||||
|
||||
private string inputText;
|
||||
public string InputText
|
||||
{
|
||||
get { return inputText; }
|
||||
set { SetProperty(ref inputText, value); }
|
||||
}
|
||||
|
||||
private GifImage loading;
|
||||
public GifImage Loading
|
||||
{
|
||||
get { return loading; }
|
||||
set { SetProperty(ref loading, value); }
|
||||
}
|
||||
|
||||
private Visibility loadingVisibility;
|
||||
public Visibility LoadingVisibility
|
||||
{
|
||||
get { return loadingVisibility; }
|
||||
set { SetProperty(ref loadingVisibility, value); }
|
||||
}
|
||||
|
||||
private VectorImage downloadManage;
|
||||
public VectorImage DownloadManage
|
||||
{
|
||||
get { return downloadManage; }
|
||||
set { SetProperty(ref downloadManage, value); }
|
||||
}
|
||||
|
||||
private VideoInfoView videoInfoView;
|
||||
public VideoInfoView VideoInfoView
|
||||
{
|
||||
get { return videoInfoView; }
|
||||
set { SetProperty(ref videoInfoView, value); }
|
||||
}
|
||||
|
||||
private ObservableCollection<VideoSection> videoSections;
|
||||
public ObservableCollection<VideoSection> VideoSections
|
||||
{
|
||||
get { return videoSections; }
|
||||
set { SetProperty(ref videoSections, value); }
|
||||
}
|
||||
|
||||
private bool isSelectAll;
|
||||
public bool IsSelectAll
|
||||
{
|
||||
get { return isSelectAll; }
|
||||
set { SetProperty(ref isSelectAll, 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 ViewVideoDetailViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator)
|
||||
{
|
||||
this.dialogService = dialogService;
|
||||
|
||||
#region 属性初始化
|
||||
|
||||
Loading = new GifImage(Properties.Resources.loading);
|
||||
Loading.StartAnimate();
|
||||
LoadingVisibility = Visibility.Collapsed;
|
||||
|
||||
ArrowBack = NavigationIcon.Instance().ArrowBack;
|
||||
ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark");
|
||||
|
||||
DownloadManage = ButtonIcon.Instance().DownloadManage;
|
||||
DownloadManage.Height = 24;
|
||||
DownloadManage.Width = 24;
|
||||
DownloadManage.Fill = DictionaryResource.GetColor("ColorPrimary");
|
||||
|
||||
VideoSections = new ObservableCollection<VideoSection>();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
#region 命令申明
|
||||
|
||||
// 返回
|
||||
private DelegateCommand backSpaceCommand;
|
||||
public DelegateCommand BackSpaceCommand => backSpaceCommand ?? (backSpaceCommand = new DelegateCommand(ExecuteBackSpace));
|
||||
|
||||
/// <summary>
|
||||
/// 返回
|
||||
/// </summary>
|
||||
private void ExecuteBackSpace()
|
||||
{
|
||||
InitView();
|
||||
|
||||
NavigationParam parameter = new NavigationParam
|
||||
{
|
||||
ViewName = ParentView,
|
||||
ParentViewName = null,
|
||||
Parameter = null
|
||||
};
|
||||
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
|
||||
}
|
||||
|
||||
// 前往下载管理页面
|
||||
private DelegateCommand downloadManagerCommand;
|
||||
public DelegateCommand DownloadManagerCommand => downloadManagerCommand ?? (downloadManagerCommand = new DelegateCommand(ExecuteDownloadManagerCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 前往下载管理页面
|
||||
/// </summary>
|
||||
private void ExecuteDownloadManagerCommand()
|
||||
{
|
||||
NavigationParam parameter = new NavigationParam
|
||||
{
|
||||
ViewName = ViewDownloadManagerViewModel.Tag,
|
||||
ParentViewName = Tag,
|
||||
Parameter = null
|
||||
};
|
||||
eventAggregator.GetEvent<NavigationEvent>().Publish(parameter);
|
||||
}
|
||||
|
||||
// 输入确认事件
|
||||
private DelegateCommand inputCommand;
|
||||
public DelegateCommand InputCommand => inputCommand ?? (inputCommand = new DelegateCommand(ExecuteInputCommand, CanExecuteInputCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 处理输入事件
|
||||
/// </summary>
|
||||
private async void ExecuteInputCommand()
|
||||
{
|
||||
InitView();
|
||||
try
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
if (InputText == null || InputText == string.Empty) { return; }
|
||||
|
||||
LogManager.Debug(Tag, $"InputText: {InputText}");
|
||||
|
||||
// 更新页面
|
||||
UnityUpdateView(UpdateView, InputText, null);
|
||||
|
||||
// 是否自动解析视频
|
||||
if (SettingsManager.GetInstance().IsAutoParseVideo() == AllowStatus.YES)
|
||||
{
|
||||
PropertyChangeAsync(ExecuteParseAllVideoCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Core.Utils.Debug.Console.PrintLine("InputCommand()发生异常: {0}", e);
|
||||
LogManager.Error(Tag, e);
|
||||
|
||||
LoadingVisibility = Visibility.Collapsed;
|
||||
ContentVisibility = Visibility.Collapsed;
|
||||
NoDataVisibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输入事件是否允许执行
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool CanExecuteInputCommand()
|
||||
{
|
||||
return LoadingVisibility != Visibility.Visible;
|
||||
}
|
||||
|
||||
// 复制封面事件
|
||||
private DelegateCommand copyCoverCommand;
|
||||
public DelegateCommand CopyCoverCommand => copyCoverCommand ?? (copyCoverCommand = new DelegateCommand(ExecuteCopyCoverCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 复制封面事件
|
||||
/// </summary>
|
||||
private void ExecuteCopyCoverCommand()
|
||||
{
|
||||
// 复制封面图片到剪贴板
|
||||
Clipboard.SetImage(VideoInfoView.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(VideoInfoView.CoverUrl);
|
||||
LogManager.Info(Tag, "复制封面url到剪贴板");
|
||||
}
|
||||
|
||||
// 视频章节选择事件
|
||||
private DelegateCommand<object> videoSectionsCommand;
|
||||
public DelegateCommand<object> VideoSectionsCommand => videoSectionsCommand ?? (videoSectionsCommand = new DelegateCommand<object>(ExecuteVideoSectionsCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 视频章节选择事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteVideoSectionsCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is VideoSection section)) { return; }
|
||||
|
||||
bool isSelectAll = true;
|
||||
foreach (var page in section.VideoPages)
|
||||
{
|
||||
if (!page.IsSelected)
|
||||
{
|
||||
isSelectAll = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
IsSelectAll = section.VideoPages.Count != 0 && isSelectAll;
|
||||
}
|
||||
|
||||
// 视频page选择事件
|
||||
private DelegateCommand<object> videoPagesCommand;
|
||||
public DelegateCommand<object> VideoPagesCommand => videoPagesCommand ?? (videoPagesCommand = new DelegateCommand<object>(ExecuteVideoPagesCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 视频page选择事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteVideoPagesCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is ObservableCollection<object> videoPages)) { return; }
|
||||
|
||||
VideoSection section = VideoSections.FirstOrDefault(item => item.IsSelected);
|
||||
if (section == null) { return; }
|
||||
IsSelectAll = section.VideoPages.Count == videoPages.Count && section.VideoPages.Count != 0;
|
||||
}
|
||||
|
||||
// Ctrl+A 全选事件
|
||||
private DelegateCommand<object> keySelectAllCommand;
|
||||
public DelegateCommand<object> KeySelectAllCommand => keySelectAllCommand ?? (keySelectAllCommand = new DelegateCommand<object>(ExecuteKeySelectAllCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Ctrl+A 全选事件
|
||||
/// </summary>
|
||||
private void ExecuteKeySelectAllCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is VideoSection section)) { return; }
|
||||
foreach (var page in section.VideoPages)
|
||||
{
|
||||
page.IsSelected = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 全选事件
|
||||
private DelegateCommand<object> selectAllCommand;
|
||||
public DelegateCommand<object> SelectAllCommand => selectAllCommand ?? (selectAllCommand = new DelegateCommand<object>(ExecuteSelectAllCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 全选事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteSelectAllCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is VideoSection section)) { return; }
|
||||
if (IsSelectAll)
|
||||
{
|
||||
foreach (var page in section.VideoPages)
|
||||
{
|
||||
page.IsSelected = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var page in section.VideoPages)
|
||||
{
|
||||
page.IsSelected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 解析视频流事件
|
||||
private DelegateCommand<object> parseCommand;
|
||||
public DelegateCommand<object> ParseCommand => parseCommand ?? (parseCommand = new DelegateCommand<object>(ExecuteParseCommand, CanExecuteParseCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 解析视频流事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private async void ExecuteParseCommand(object parameter)
|
||||
{
|
||||
if (!(parameter is VideoPage videoPage))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LoadingVisibility = Visibility.Visible;
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
LogManager.Debug(Tag, $"Video Page: {videoPage.Cid}");
|
||||
|
||||
UnityUpdateView(ParseVideo, null, videoPage);
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Core.Utils.Debug.Console.PrintLine("ParseCommand()发生异常: {0}", e);
|
||||
LogManager.Error(Tag, e);
|
||||
|
||||
LoadingVisibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
LoadingVisibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析视频流事件是否允许执行
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
/// <returns></returns>
|
||||
private bool CanExecuteParseCommand(object parameter)
|
||||
{
|
||||
return LoadingVisibility != Visibility.Visible;
|
||||
}
|
||||
|
||||
// 解析所有视频流事件
|
||||
private DelegateCommand parseAllVideoCommand;
|
||||
public DelegateCommand ParseAllVideoCommand => parseAllVideoCommand ?? (parseAllVideoCommand = new DelegateCommand(ExecuteParseAllVideoCommand, CanExecuteParseAllVideoCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 解析所有视频流事件
|
||||
/// </summary>
|
||||
private async void ExecuteParseAllVideoCommand()
|
||||
{
|
||||
LoadingVisibility = Visibility.Visible;
|
||||
|
||||
// 解析范围
|
||||
ParseScope parseScope = SettingsManager.GetInstance().GetParseScope();
|
||||
|
||||
// 是否选择了解析范围
|
||||
if (parseScope == ParseScope.NONE)
|
||||
{
|
||||
// 打开解析选择器
|
||||
dialogService.ShowDialog(ViewParsingSelectorViewModel.Tag, null, result =>
|
||||
{
|
||||
if (result.Result == ButtonResult.OK)
|
||||
{
|
||||
// 选择的解析范围
|
||||
parseScope = result.Parameters.GetValue<ParseScope>("parseScope");
|
||||
}
|
||||
});
|
||||
}
|
||||
LogManager.Debug(Tag, $"ParseScope: {parseScope:G}");
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
LogManager.Debug(Tag, "Parse video");
|
||||
|
||||
switch (parseScope)
|
||||
{
|
||||
case ParseScope.NONE:
|
||||
break;
|
||||
case ParseScope.SELECTED_ITEM:
|
||||
foreach (var section in VideoSections)
|
||||
{
|
||||
foreach (var page in section.VideoPages)
|
||||
{
|
||||
var videoPage = section.VideoPages.FirstOrDefault(t => t == page);
|
||||
|
||||
if (videoPage.IsSelected)
|
||||
{
|
||||
// 执行解析任务
|
||||
UnityUpdateView(ParseVideo, null, videoPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ParseScope.CURRENT_SECTION:
|
||||
foreach (var section in VideoSections)
|
||||
{
|
||||
if (section.IsSelected)
|
||||
{
|
||||
foreach (var page in section.VideoPages)
|
||||
{
|
||||
var videoPage = section.VideoPages.FirstOrDefault(t => t == page);
|
||||
|
||||
// 执行解析任务
|
||||
UnityUpdateView(ParseVideo, null, videoPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ParseScope.ALL:
|
||||
foreach (var section in VideoSections)
|
||||
{
|
||||
foreach (var page in section.VideoPages)
|
||||
{
|
||||
var videoPage = section.VideoPages.FirstOrDefault(t => t == page);
|
||||
|
||||
// 执行解析任务
|
||||
UnityUpdateView(ParseVideo, null, videoPage);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Core.Utils.Debug.Console.PrintLine("ParseCommand()发生异常: {0}", e);
|
||||
LogManager.Error(Tag, e);
|
||||
|
||||
LoadingVisibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
LoadingVisibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析所有视频流事件是否允许执行
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool CanExecuteParseAllVideoCommand()
|
||||
{
|
||||
return LoadingVisibility != Visibility.Visible;
|
||||
}
|
||||
|
||||
// 添加到下载列表事件
|
||||
private DelegateCommand addToDownloadCommand;
|
||||
public DelegateCommand AddToDownloadCommand => addToDownloadCommand ?? (addToDownloadCommand = new DelegateCommand(ExecuteAddToDownloadCommand, CanExecuteAddToDownloadCommand));
|
||||
|
||||
/// <summary>
|
||||
/// 添加到下载列表事件
|
||||
/// </summary>
|
||||
private void ExecuteAddToDownloadCommand()
|
||||
{
|
||||
// 选择的下载文件夹
|
||||
string directory = string.Empty;
|
||||
|
||||
// 是否使用默认下载目录
|
||||
if (SettingsManager.GetInstance().IsUseSaveVideoRootPath() == AllowStatus.YES)
|
||||
{
|
||||
directory = SettingsManager.GetInstance().GetSaveVideoRootPath();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 打开文件夹选择器
|
||||
dialogService.ShowDialog(ViewDirectorySelectorViewModel.Tag, null, result =>
|
||||
{
|
||||
if (result.Result == ButtonResult.OK)
|
||||
{
|
||||
// 选择的下载文件夹
|
||||
directory = result.Parameters.GetValue<string>("directory");
|
||||
|
||||
// 文件夹不存在则创建
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
// 添加到下载
|
||||
eventAggregator.GetEvent<MessageEvent>().Publish(directory);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加到下载列表事件是否允许执行
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool CanExecuteAddToDownloadCommand()
|
||||
{
|
||||
return LoadingVisibility != Visibility.Visible;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 业务逻辑
|
||||
|
||||
/// <summary>
|
||||
/// 初始化页面元素
|
||||
/// </summary>
|
||||
private void InitView()
|
||||
{
|
||||
LogManager.Debug(Tag, "初始化页面元素");
|
||||
|
||||
LoadingVisibility = Visibility.Visible;
|
||||
ContentVisibility = Visibility.Collapsed;
|
||||
NoDataVisibility = Visibility.Collapsed;
|
||||
|
||||
VideoSections.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新页面的统一方法
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
/// <param name="input"></param>
|
||||
/// <param name="page"></param>
|
||||
private void UnityUpdateView(Action<IInfoService, VideoPage> action, string input, VideoPage page)
|
||||
{
|
||||
// 视频
|
||||
if (ParseEntrance.IsAvUrl(InputText) || ParseEntrance.IsBvUrl(InputText))
|
||||
{
|
||||
action(new VideoInfoService(input), page);
|
||||
}
|
||||
|
||||
// 番剧(电影、电视剧)
|
||||
if (ParseEntrance.IsBangumiSeasonUrl(InputText) || ParseEntrance.IsBangumiEpisodeUrl(InputText) || ParseEntrance.IsBangumiMediaUrl(InputText))
|
||||
{
|
||||
action(new BangumiInfoService(input), page);
|
||||
}
|
||||
|
||||
// 课程
|
||||
if (ParseEntrance.IsCheeseSeasonUrl(InputText) || ParseEntrance.IsCheeseEpisodeUrl(InputText))
|
||||
{
|
||||
action(new CheeseInfoService(input), page);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新页面
|
||||
/// </summary>
|
||||
/// <param name="videoInfoService"></param>
|
||||
private void UpdateView(IInfoService videoInfoService, VideoPage param)
|
||||
{
|
||||
VideoInfoView = videoInfoService.GetVideoView();
|
||||
if (VideoInfoView == null)
|
||||
{
|
||||
LogManager.Debug(Tag, "VideoInfoView is null.");
|
||||
|
||||
LoadingVisibility = Visibility.Collapsed;
|
||||
ContentVisibility = Visibility.Collapsed;
|
||||
NoDataVisibility = Visibility.Visible;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadingVisibility = Visibility.Collapsed;
|
||||
ContentVisibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
var videoSections = videoInfoService.GetVideoSections();
|
||||
if (videoSections == null)
|
||||
{
|
||||
LogManager.Debug(Tag, "videoSections is not exist.");
|
||||
|
||||
var pages = videoInfoService.GetVideoPages();
|
||||
|
||||
PropertyChangeAsync(new Action(() =>
|
||||
{
|
||||
VideoSections.Add(new VideoSection
|
||||
{
|
||||
Id = 0,
|
||||
Title = "default",
|
||||
IsSelected = true,
|
||||
VideoPages = pages
|
||||
});
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
PropertyChangeAsync(new Action(() =>
|
||||
{
|
||||
VideoSections.AddRange(videoSections);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析视频流
|
||||
/// </summary>
|
||||
/// <param name="videoInfoService"></param>
|
||||
private void ParseVideo(IInfoService videoInfoService, VideoPage videoPage)
|
||||
{
|
||||
videoInfoService.GetVideoStream(videoPage);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 导航到VideoDetail页面时执行
|
||||
/// </summary>
|
||||
/// <param name="navigationContext"></param>
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
|
||||
DownloadManage = ButtonIcon.Instance().DownloadManage;
|
||||
DownloadManage.Height = 24;
|
||||
DownloadManage.Width = 24;
|
||||
DownloadManage.Fill = DictionaryResource.GetColor("ColorPrimary");
|
||||
|
||||
// Parent参数为null时,表示是从下一个页面返回到本页面,不需要执行任务
|
||||
if (navigationContext.Parameters.GetValue<string>("Parent") != null)
|
||||
{
|
||||
// 正在执行任务时不开启新任务
|
||||
if (LoadingVisibility != Visibility.Visible)
|
||||
{
|
||||
InputText = navigationContext.Parameters.GetValue<string>("Parameter");
|
||||
PropertyChangeAsync(ExecuteInputCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
240
src/DownKyi/Views/Dialogs/ViewDirectorySelector.xaml
Normal file
240
src/DownKyi/Views/Dialogs/ViewDirectorySelector.xaml
Normal file
@ -0,0 +1,240 @@
|
||||
<UserControl
|
||||
x:Class="DownKyi.Views.Dialogs.ViewDirectorySelector"
|
||||
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 />
|
||||
</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=">>>>>>>>>>>>>>>>" />
|
||||
|
||||
<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 />
|
||||
<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>
|
15
src/DownKyi/Views/Dialogs/ViewDirectorySelector.xaml.cs
Normal file
15
src/DownKyi/Views/Dialogs/ViewDirectorySelector.xaml.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace DownKyi.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ViewDirectorySelector
|
||||
/// </summary>
|
||||
public partial class ViewDirectorySelector : UserControl
|
||||
{
|
||||
public ViewDirectorySelector()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
126
src/DownKyi/Views/Dialogs/ViewParsingSelector.xaml
Normal file
126
src/DownKyi/Views/Dialogs/ViewParsingSelector.xaml
Normal file
@ -0,0 +1,126 @@
|
||||
<UserControl
|
||||
x:Class="DownKyi.Views.Dialogs.ViewParsingSelector"
|
||||
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>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
MinWidth="250"
|
||||
Margin="15,10"
|
||||
Orientation="Vertical">
|
||||
|
||||
<Button
|
||||
Width="160"
|
||||
Height="35"
|
||||
Margin="0,10,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding ParseSelectedItemCommand}"
|
||||
Content="{DynamicResource ParseSelectedItem}"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushText}"
|
||||
Style="{StaticResource BtnStyle}" />
|
||||
|
||||
<Button
|
||||
Width="160"
|
||||
Height="35"
|
||||
Margin="0,30,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding ParseCurrentSectionCommand}"
|
||||
Content="{DynamicResource ParseCurrentSection}"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushText}"
|
||||
Style="{StaticResource BtnStyle}" />
|
||||
|
||||
<Button
|
||||
Width="160"
|
||||
Height="35"
|
||||
Margin="0,30,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding ParseAllCommand}"
|
||||
Content="{DynamicResource ParseAll}"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushText}"
|
||||
Style="{StaticResource BtnStyle}" />
|
||||
|
||||
<CheckBox
|
||||
Margin="0,30,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Content="{DynamicResource SetParseDefault}"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
IsChecked="{Binding IsParseDefault, Mode=TwoWay}"
|
||||
Style="{StaticResource CheckBoxStyle}" />
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
15
src/DownKyi/Views/Dialogs/ViewParsingSelector.xaml.cs
Normal file
15
src/DownKyi/Views/Dialogs/ViewParsingSelector.xaml.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace DownKyi.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ViewParsingSelector
|
||||
/// </summary>
|
||||
public partial class ViewParsingSelector : UserControl
|
||||
{
|
||||
public ViewParsingSelector()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
10
src/DownKyi/Views/DownloadManager/ViewDownloadFinished.xaml
Normal file
10
src/DownKyi/Views/DownloadManager/ViewDownloadFinished.xaml
Normal file
@ -0,0 +1,10 @@
|
||||
<UserControl
|
||||
x:Class="DownKyi.Views.DownloadManager.ViewDownloadFinished"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True">
|
||||
<Grid>
|
||||
<TextBlock>已下载</TextBlock>
|
||||
</Grid>
|
||||
</UserControl>
|
@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace DownKyi.Views.DownloadManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ViewDownloadFinished
|
||||
/// </summary>
|
||||
public partial class ViewDownloadFinished : UserControl
|
||||
{
|
||||
public ViewDownloadFinished()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
10
src/DownKyi/Views/DownloadManager/ViewDownloading.xaml
Normal file
10
src/DownKyi/Views/DownloadManager/ViewDownloading.xaml
Normal file
@ -0,0 +1,10 @@
|
||||
<UserControl
|
||||
x:Class="DownKyi.Views.DownloadManager.ViewDownloading"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True">
|
||||
<Grid>
|
||||
<TextBlock>正在下载</TextBlock>
|
||||
</Grid>
|
||||
</UserControl>
|
15
src/DownKyi/Views/DownloadManager/ViewDownloading.xaml.cs
Normal file
15
src/DownKyi/Views/DownloadManager/ViewDownloading.xaml.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace DownKyi.Views.DownloadManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ViewDownloading
|
||||
/// </summary>
|
||||
public partial class ViewDownloading : UserControl
|
||||
{
|
||||
public ViewDownloading()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
203
src/DownKyi/Views/MainWindow.xaml
Normal file
203
src/DownKyi/Views/MainWindow.xaml
Normal file
@ -0,0 +1,203 @@
|
||||
<Window
|
||||
x:Class="DownKyi.Views.MainWindow"
|
||||
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/"
|
||||
Title="{DynamicResource AppName}"
|
||||
Width="1100"
|
||||
Height="750"
|
||||
MinWidth="1100"
|
||||
MinHeight="750"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
ResizeMode="CanResize"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
WindowState="{Binding WinState}">
|
||||
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome
|
||||
CaptionHeight="0"
|
||||
CornerRadius="0"
|
||||
GlassFrameThickness="0"
|
||||
NonClientFrameEdges="None"
|
||||
ResizeBorderThickness="4"
|
||||
UseAeroCaptionButtons="False" />
|
||||
</WindowChrome.WindowChrome>
|
||||
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Loaded">
|
||||
<i:InvokeCommandAction Command="{Binding LoadedCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
|
||||
<Border BorderBrush="{DynamicResource BrushWindowBorder}" BorderThickness="1">
|
||||
<Border.Style>
|
||||
<Style TargetType="{x:Type Border}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}" Value="Maximized">
|
||||
<Setter Property="Margin" Value="7,7" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}" Value="Normal">
|
||||
<Setter Property="Margin" Value="0" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
|
||||
<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="50" />
|
||||
<ColumnDefinition Width="50" />
|
||||
<ColumnDefinition Width="50" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel
|
||||
Grid.Column="0"
|
||||
Margin="10,0"
|
||||
Orientation="Horizontal">
|
||||
<Image
|
||||
Width="20"
|
||||
Height="20"
|
||||
Source="/DownKyi;component/Resources/favicon.ico" />
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="10,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushCaptionForeground}"
|
||||
Text="{DynamicResource AppName}" />
|
||||
</StackPanel>
|
||||
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Command="{Binding SkinCommand}"
|
||||
Style="{StaticResource SystemBtnStyle}"
|
||||
ToolTip="{DynamicResource Skin}"
|
||||
Visibility="Collapsed">
|
||||
<Path
|
||||
Width="{Binding SkinIcon.Width}"
|
||||
Height="{Binding SkinIcon.Height}"
|
||||
Data="{Binding SkinIcon.Data}"
|
||||
Fill="{Binding SkinIcon.Fill}"
|
||||
Stretch="UniformToFill" />
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseEnter">
|
||||
<i:InvokeCommandAction Command="{Binding SkinEnterCommand}" />
|
||||
</i:EventTrigger>
|
||||
<i:EventTrigger EventName="MouseLeave">
|
||||
<i:InvokeCommandAction Command="{Binding SkinLeaveCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Command="{Binding MinimizeCommand}"
|
||||
Style="{StaticResource SystemBtnStyle}"
|
||||
ToolTip="{DynamicResource Minimize}">
|
||||
<Path
|
||||
Width="{Binding MinimizeIcon.Width}"
|
||||
Height="{Binding MinimizeIcon.Height}"
|
||||
Data="{Binding MinimizeIcon.Data}"
|
||||
Fill="{Binding MinimizeIcon.Fill}"
|
||||
Stretch="UniformToFill" />
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseEnter">
|
||||
<i:InvokeCommandAction Command="{Binding MinimizeEnterCommand}" />
|
||||
</i:EventTrigger>
|
||||
<i:EventTrigger EventName="MouseLeave">
|
||||
<i:InvokeCommandAction Command="{Binding MinimizeLeaveCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Grid.Column="3" Command="{Binding ResizeCommand}">
|
||||
<Path
|
||||
Width="{Binding ResizeIcon.Width}"
|
||||
Height="{Binding ResizeIcon.Height}"
|
||||
Data="{Binding ResizeIcon.Data}"
|
||||
Fill="{Binding ResizeIcon.Fill}"
|
||||
Stretch="UniformToFill" />
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseEnter">
|
||||
<i:InvokeCommandAction Command="{Binding ResizeEnterCommand}" />
|
||||
</i:EventTrigger>
|
||||
<i:EventTrigger EventName="MouseLeave">
|
||||
<i:InvokeCommandAction Command="{Binding ResizeLeaveCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
|
||||
<Button.Style>
|
||||
<Style BasedOn="{StaticResource SystemBtnStyle}" TargetType="{x:Type Button}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}" Value="Maximized">
|
||||
<Setter Property="ToolTip" Value="{DynamicResource Restore}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}" Value="Normal">
|
||||
<Setter Property="ToolTip" Value="{DynamicResource Maximize}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
<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>
|
||||
|
||||
<ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" />
|
||||
|
||||
<Border
|
||||
Grid.Row="1"
|
||||
MinHeight="30"
|
||||
Margin="0,0,0,20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="{DynamicResource BrushBackgroundDark}"
|
||||
CornerRadius="15"
|
||||
Visibility="{Binding MessageVisibility}">
|
||||
<TextBlock
|
||||
Margin="15,5,15,5"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Background="{x:Null}"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushForegroundDark}"
|
||||
Text="{Binding Message}"
|
||||
TextAlignment="Center" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
16
src/DownKyi/Views/MainWindow.xaml.cs
Normal file
16
src/DownKyi/Views/MainWindow.xaml.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace DownKyi.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
408
src/DownKyi/Views/Settings/ViewAbout.xaml
Normal file
408
src/DownKyi/Views/Settings/ViewAbout.xaml
Normal file
@ -0,0 +1,408 @@
|
||||
<UserControl
|
||||
x:Class="DownKyi.Views.Settings.ViewAbout"
|
||||
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">
|
||||
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="50,0" Orientation="Vertical">
|
||||
|
||||
<StackPanel Margin="0,20,0,0" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
FontSize="18"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource About}" />
|
||||
<TextBlock
|
||||
Cursor="Hand"
|
||||
FontSize="18"
|
||||
Foreground="{DynamicResource BrushPrimary}"
|
||||
Text="{Binding AppName}"
|
||||
ToolTip="{DynamicResource GotoHomepage}">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseLeftButtonUp">
|
||||
<i:InvokeCommandAction Command="{Binding AppNameCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,20,0,0" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource CurrentAppVersion}" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{Binding AppVersion}" />
|
||||
|
||||
<Button
|
||||
Width="75"
|
||||
Margin="30,0,0,0"
|
||||
Command="{Binding CheckUpdateCommand}"
|
||||
Content="{DynamicResource CheckUpdate}"
|
||||
FontSize="12"
|
||||
Style="{StaticResource BtnBorderStyle}" />
|
||||
<Button
|
||||
Width="75"
|
||||
Margin="20,0,0,0"
|
||||
Command="{Binding FeedbackCommand}"
|
||||
Content="{DynamicResource Feedback}"
|
||||
FontSize="12"
|
||||
Style="{StaticResource BtnBorderStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<CheckBox
|
||||
Grid.Column="0"
|
||||
Margin="0,20,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Command="{Binding ReceiveBetaVersionCommand}"
|
||||
Content="{DynamicResource ReceiveBetaVersion}"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
IsChecked="{Binding IsReceiveBetaVersion, Mode=TwoWay}"
|
||||
Style="{StaticResource CheckBoxStyle}" />
|
||||
<CheckBox
|
||||
Grid.Column="0"
|
||||
Margin="0,20,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Command="{Binding AutoUpdateWhenLaunchCommand}"
|
||||
Content="{DynamicResource AutoUpdateWhenLaunch}"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
IsChecked="{Binding AutoUpdateWhenLaunch, Mode=TwoWay}"
|
||||
Style="{StaticResource CheckBoxStyle}" />
|
||||
|
||||
<StackPanel Margin="0,20,0,0" Orientation="Vertical">
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
FontSize="14"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource ThirdParty}" />
|
||||
|
||||
<Border
|
||||
Padding="5"
|
||||
HorizontalAlignment="Left"
|
||||
BorderBrush="{DynamicResource BrushBorder}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5">
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</Grid.Resources>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="30" />
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="20" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200" />
|
||||
<ColumnDefinition Width="200" />
|
||||
<ColumnDefinition Width="100" />
|
||||
<ColumnDefinition Width="100" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
FontSize="12"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource ThirdPartyName}" />
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
FontSize="12"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource ThirdPartyAuthor}" />
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
FontSize="12"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource ThirdPartyVersion}" />
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Grid.Column="3"
|
||||
FontSize="12"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource ThirdPartyLicense}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="Brotli.NET" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="Jinjun Xie" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="2.1.1" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="3"
|
||||
FontSize="12">
|
||||
<Hyperlink Command="{Binding BrotliLicenseCommand}">
|
||||
<TextBlock Text="MIT" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="Google.Protobuf" />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="Google Inc." />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="3.17.3" />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="3"
|
||||
FontSize="12">
|
||||
<Hyperlink Command="{Binding ProtobufLicenseCommand}">
|
||||
<TextBlock Text="LICENSE" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="Newtonsoft.Json" />
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="James Newton-King" />
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="2"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="13.0.1" />
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="3"
|
||||
FontSize="12">
|
||||
<Hyperlink Command="{Binding NewtonsoftLicenseCommand}">
|
||||
<TextBlock Text="MIT" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="Prism.DryIoc" />
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="Brian Lagunas,Dan Siegel" />
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="8.1.97" />
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="3"
|
||||
FontSize="12">
|
||||
<Hyperlink Command="{Binding PrismLicenseCommand}">
|
||||
<TextBlock Text="LICENSE" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="QRCoder" />
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="Raffael Herrmann" />
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="2"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="1.4.1" />
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="3"
|
||||
FontSize="12">
|
||||
<Hyperlink Command="{Binding QRCoderLicenseCommand}">
|
||||
<TextBlock Text="MIT" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="6"
|
||||
Grid.Column="0"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="System.Data.SQLite.Core" />
|
||||
<TextBlock
|
||||
Grid.Row="6"
|
||||
Grid.Column="1"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="SQLite Development Team" />
|
||||
<TextBlock
|
||||
Grid.Row="6"
|
||||
Grid.Column="2"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="1.0.112.2" />
|
||||
<TextBlock
|
||||
Grid.Row="6"
|
||||
Grid.Column="3"
|
||||
FontSize="12">
|
||||
<Hyperlink Command="{Binding SQLiteLicenseCommand}">
|
||||
<TextBlock Text="LICENSE" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="7"
|
||||
Grid.Column="0"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="Aria2c" />
|
||||
<TextBlock
|
||||
Grid.Row="7"
|
||||
Grid.Column="1"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="Aria2" />
|
||||
<TextBlock
|
||||
Grid.Row="7"
|
||||
Grid.Column="2"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="1.35.0" />
|
||||
<TextBlock
|
||||
Grid.Row="7"
|
||||
Grid.Column="3"
|
||||
FontSize="12">
|
||||
<Hyperlink Command="{Binding AriaLicenseCommand}">
|
||||
<TextBlock Text="GPL 2.0" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="0"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="FFmpeg" />
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="1"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="FFmpeg" />
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="2"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="4.3.1" />
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="3"
|
||||
FontSize="12">
|
||||
<Hyperlink Command="{Binding FFmpegLicenseCommand}">
|
||||
<TextBlock Text="GPL 3.0" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 免责申明 -->
|
||||
<StackPanel Margin="0,20,0,0" Orientation="Vertical">
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
FontSize="14"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource Disclaimer}" />
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource Disclaimer1}"
|
||||
TextWrapping="WrapWithOverflow" />
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource Disclaimer2}"
|
||||
TextWrapping="WrapWithOverflow" />
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource Disclaimer3}"
|
||||
TextWrapping="WrapWithOverflow" />
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource Disclaimer4}"
|
||||
TextWrapping="WrapWithOverflow" />
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource Disclaimer5}"
|
||||
TextWrapping="WrapWithOverflow" />
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource Disclaimer6}"
|
||||
TextWrapping="WrapWithOverflow" />
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
15
src/DownKyi/Views/Settings/ViewAbout.xaml.cs
Normal file
15
src/DownKyi/Views/Settings/ViewAbout.xaml.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace DownKyi.Views.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ViewAbout
|
||||
/// </summary>
|
||||
public partial class ViewAbout : UserControl
|
||||
{
|
||||
public ViewAbout()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user