diff --git a/Brotli.Core/Brotli.Core.csproj b/Brotli.Core/Brotli.Core.csproj index e88d1ed..aafe0ea 100644 --- a/Brotli.Core/Brotli.Core.csproj +++ b/Brotli.Core/Brotli.Core.csproj @@ -17,6 +17,7 @@ The library use the native runtime and its performance should be better than Sys For more document,please visit https://github.com/XieJJ99/brotli.net. MIT 2.1.1.0 + AnyCPU;x64;x86 diff --git a/DatabaseManager/DatabaseManager.csproj b/DatabaseManager/DatabaseManager.csproj index da46220..343a04e 100644 --- a/DatabaseManager/DatabaseManager.csproj +++ b/DatabaseManager/DatabaseManager.csproj @@ -35,6 +35,22 @@ prompt 4 + + x64 + bin\x64\Debug\ + + + x64 + bin\x64\Release\ + + + x86 + bin\x86\Debug\ + + + x86 + bin\x86\Release\ + diff --git a/DownKyi.Core.Test/DownKyi.Core.Test.csproj b/DownKyi.Core.Test/DownKyi.Core.Test.csproj index 85a7801..9a7c6c4 100644 --- a/DownKyi.Core.Test/DownKyi.Core.Test.csproj +++ b/DownKyi.Core.Test/DownKyi.Core.Test.csproj @@ -38,6 +38,22 @@ prompt 4 + + x64 + bin\x64\Debug\ + + + x64 + bin\x64\Release\ + + + x86 + bin\x86\Debug\ + + + x86 + bin\x86\Release\ + ..\packages\MSTest.TestFramework.2.2.8\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll diff --git a/DownKyi.Core/Aria2cNet/Client/Entity/AriaSendData.cs b/DownKyi.Core/Aria2cNet/Client/Entity/AriaSendData.cs index ffbe89a..e11bb49 100644 --- a/DownKyi.Core/Aria2cNet/Client/Entity/AriaSendData.cs +++ b/DownKyi.Core/Aria2cNet/Client/Entity/AriaSendData.cs @@ -36,14 +36,14 @@ namespace DownKyi.Core.Aria2cNet.Client.Entity [JsonProperty("dir")] public string Dir { get; set; } - //[JsonProperty("header")] - //public string Header { get; set; } + [JsonProperty("header")] + public string Header { get; set; } - //[JsonProperty("use-head")] - //public string UseHead { get; set; } + [JsonProperty("use-head")] + public string UseHead { get; set; } - //[JsonProperty("user-agent")] - //public string UserAgent { get; set; } + [JsonProperty("user-agent")] + public string UserAgent { get; set; } public override string ToString() { diff --git a/DownKyi.Core/Aria2cNet/Server/AriaConfigFileAllocation.cs b/DownKyi.Core/Aria2cNet/Server/AriaConfigFileAllocation.cs index e00a9aa..38bf62f 100644 --- a/DownKyi.Core/Aria2cNet/Server/AriaConfigFileAllocation.cs +++ b/DownKyi.Core/Aria2cNet/Server/AriaConfigFileAllocation.cs @@ -5,6 +5,7 @@ /// public enum AriaConfigFileAllocation { + NOT_SET = 0, NONE = 1, // 没有预分配 PREALLOC, // 预分配,默认 FALLOC // NTFS建议使用 diff --git a/DownKyi.Core/Aria2cNet/Server/AriaConfigLogLevel.cs b/DownKyi.Core/Aria2cNet/Server/AriaConfigLogLevel.cs index b1f4620..ac27188 100644 --- a/DownKyi.Core/Aria2cNet/Server/AriaConfigLogLevel.cs +++ b/DownKyi.Core/Aria2cNet/Server/AriaConfigLogLevel.cs @@ -5,6 +5,7 @@ /// public enum AriaConfigLogLevel { + NOT_SET = 0, DEBUG = 1, INFO, NOTICE, diff --git a/DownKyi.Core/BiliApi/Users/Models/SpacePublicationListType.cs b/DownKyi.Core/BiliApi/Users/Models/SpacePublicationListType.cs index 6e88c75..5a4d528 100644 --- a/DownKyi.Core/BiliApi/Users/Models/SpacePublicationListType.cs +++ b/DownKyi.Core/BiliApi/Users/Models/SpacePublicationListType.cs @@ -21,7 +21,7 @@ namespace DownKyi.Core.BiliApi.Users.Models public SpacePublicationListTypeVideoZone Technology { get; set; } [JsonProperty("188")] public SpacePublicationListTypeVideoZone Digital { get; set; } - [JsonProperty("224")] + [JsonProperty("234")] public SpacePublicationListTypeVideoZone Sports { get; set; } [JsonProperty("223")] public SpacePublicationListTypeVideoZone Car { get; set; } diff --git a/DownKyi.Core/DownKyi.Core.csproj b/DownKyi.Core/DownKyi.Core.csproj index fb65dfc..5c3361b 100644 --- a/DownKyi.Core/DownKyi.Core.csproj +++ b/DownKyi.Core/DownKyi.Core.csproj @@ -32,6 +32,22 @@ prompt 4 + + x64 + bin\x64\Debug\ + + + x64 + bin\x64\Release\ + + + x86 + bin\x86\Debug\ + + + x86 + bin\x86\Release\ + ..\packages\Brotli.NET.2.1.1\lib\net45\Brotli.Core.dll @@ -78,6 +94,9 @@ + + ..\packages\WebPSharp.0.5.1\lib\net472\WebPSharp.dll + @@ -271,6 +290,8 @@ + + @@ -333,6 +354,20 @@ Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + @@ -342,7 +377,9 @@ + + \ No newline at end of file diff --git a/DownKyi.Core/FFmpeg/FFmpegHelper.cs b/DownKyi.Core/FFmpeg/FFmpegHelper.cs index 31ae4d3..1eb34fb 100644 --- a/DownKyi.Core/FFmpeg/FFmpegHelper.cs +++ b/DownKyi.Core/FFmpeg/FFmpegHelper.cs @@ -9,6 +9,23 @@ namespace DownKyi.Core.FFmpeg { private const string Tag = "FFmpegHelper"; + private static readonly bool is64Bit = false; + private static readonly string exec = ""; + + static FFmpegHelper() + { + is64Bit = IntPtr.Size == 8; + + if (is64Bit) + { + exec = Path.Combine(Environment.CurrentDirectory, "ffmpeg.exe"); + } + else + { + exec = Path.Combine(Environment.CurrentDirectory, "ffmpeg.exe"); + } + } + /// /// 合并音频和视频 /// @@ -24,7 +41,7 @@ namespace DownKyi.Core.FFmpeg } if (video2 == null || !File.Exists(video2)) { - param = $"-y -i \"{video1}\" -acodec copy -f aac \"{destVideo}\""; + param = $"-y -i \"{video1}\" -acodec copy \"{destVideo}\""; } if (!File.Exists(video1) && !File.Exists(video2)) { return false; } @@ -37,7 +54,7 @@ namespace DownKyi.Core.FFmpeg return false; } - ExcuteProcess("ffmpeg.exe", param, null, (s, e) => Console.WriteLine(e.Data)); + ExcuteProcess(exec, param, null, (s, e) => Console.WriteLine(e.Data)); try { @@ -92,7 +109,7 @@ namespace DownKyi.Core.FFmpeg // ffmpeg -y -f concat -safe 0 -i filelist.txt -c copy output.mkv // 加上-y,表示如果有同名文件,则默认覆盖 string param = $"-y -f concat -safe 0 -i {concatFileName} -c copy \"{destVideo}\" -y"; - ExcuteProcess("ffmpeg.exe", param, workingDirectory, (s, e) => Console.WriteLine(e.Data)); + ExcuteProcess(exec, param, workingDirectory, (s, e) => Console.WriteLine(e.Data)); // 删除临时文件 try @@ -128,7 +145,7 @@ namespace DownKyi.Core.FFmpeg { // ffmpeg -y -i "video.mp4" -vf delogo=x=1670:y=50:w=180:h=70:show=1 "delogo.mp4" string param = $"-y -i \"{video}\" -vf delogo=x={x}:y={y}:w={width}:h={height}:show=0 \"{destVideo}\" -hide_banner"; - ExcuteProcess("ffmpeg.exe", param, null, (s, e) => + ExcuteProcess(exec, param, null, (s, e) => { Console.WriteLine(e.Data); action.Invoke(e.Data); @@ -147,7 +164,7 @@ namespace DownKyi.Core.FFmpeg // ffmpeg -i 3.mp4 -vn -y -acodec copy 3.aac // ffmpeg -i 3.mp4 -vn -y -acodec copy 3.m4a string param = $"-i \"{video}\" -vn -y -acodec copy \"{audio}\" -hide_banner"; - ExcuteProcess("ffmpeg.exe", param, + ExcuteProcess(exec, param, null, (s, e) => { Console.WriteLine(e.Data); @@ -166,7 +183,7 @@ namespace DownKyi.Core.FFmpeg // 提取视频 (Extract Video) // ffmpeg -i Life.of.Pi.has.subtitles.mkv -vcodec copy –an videoNoAudioSubtitle.mp4 string param = $"-i \"{video}\" -y -vcodec copy -an \"{destVideo}\" -hide_banner"; - ExcuteProcess("ffmpeg.exe", param, + ExcuteProcess(exec, param, null, (s, e) => { Console.WriteLine(e.Data); @@ -185,7 +202,7 @@ namespace DownKyi.Core.FFmpeg // 提取帧 // ffmpeg -i caiyilin.wmv -vframes 1 wm.bmp string param = $"-i \"{video}\" -y -vframes {number} \"{image}\""; - ExcuteProcess("ffmpeg.exe", param, null, (s, e) => Console.WriteLine(e.Data)); + ExcuteProcess(exec, param, null, (s, e) => Console.WriteLine(e.Data)); } diff --git a/DownKyi.Core/FFmpeg_LICENSE.txt b/DownKyi.Core/FFmpeg_LICENSE.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/DownKyi.Core/FFmpeg_LICENSE.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. + + + Copyright (C) + + 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 . + +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: + + Copyright (C) + 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 +. + + 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 +. diff --git a/DownKyi.Core/FileName/FileName.cs b/DownKyi.Core/FileName/FileName.cs index 2e8684d..356a9e0 100644 --- a/DownKyi.Core/FileName/FileName.cs +++ b/DownKyi.Core/FileName/FileName.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Text.RegularExpressions; namespace DownKyi.Core.FileName @@ -6,7 +7,7 @@ namespace DownKyi.Core.FileName public class FileName { private readonly List nameParts; - private int order = -1; + private string order = "ORDER"; private string section = "SECTION"; private string mainTitle = "MAIN_TITLE"; private string pageTitle = "PAGE_TITLE"; @@ -36,7 +37,15 @@ namespace DownKyi.Core.FileName public FileName SetOrder(int order) { - this.order = order; + this.order = order.ToString(); + return this; + } + + public FileName SetOrder(int order, int count) + { + int length = Math.Abs(count).ToString().Length; + this.order = order.ToString("D" + length); + return this; } @@ -127,14 +136,7 @@ namespace DownKyi.Core.FileName switch (part) { case FileNamePart.ORDER: - if (order != -1) - { - path += order; - } - else - { - path += "ORDER"; - } + path += order; break; case FileNamePart.SECTION: path += section; diff --git a/DownKyi.Core/Properties/AssemblyInfo.cs b/DownKyi.Core/Properties/AssemblyInfo.cs index 18b88bb..4061da8 100644 --- a/DownKyi.Core/Properties/AssemblyInfo.cs +++ b/DownKyi.Core/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("DownKyi")] [assembly: AssemblyProduct("DownKyi.Core")] -[assembly: AssemblyCopyright("Copyright © Downkyi 2020-2021")] +[assembly: AssemblyCopyright("Copyright © Downkyi 2020-2022")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 //通过使用 "*",如下所示: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.1.0.0")] -[assembly: AssemblyFileVersion("2.1.0.0")] +[assembly: AssemblyVersion("2.1.1.0")] +[assembly: AssemblyFileVersion("2.1.1.0")] diff --git a/DownKyi.Core/Settings/AfterDownloadOperation.cs b/DownKyi.Core/Settings/AfterDownloadOperation.cs index 99ac8a1..d6ebdb1 100644 --- a/DownKyi.Core/Settings/AfterDownloadOperation.cs +++ b/DownKyi.Core/Settings/AfterDownloadOperation.cs @@ -2,6 +2,7 @@ { public enum AfterDownloadOperation { + NOT_SET = 0, NONE = 1, OPEN_FOLDER, CLOSE_APP, diff --git a/DownKyi.Core/Settings/DownloadFinishedSort.cs b/DownKyi.Core/Settings/DownloadFinishedSort.cs index 6676737..9f1c773 100644 --- a/DownKyi.Core/Settings/DownloadFinishedSort.cs +++ b/DownKyi.Core/Settings/DownloadFinishedSort.cs @@ -2,7 +2,8 @@ { public enum DownloadFinishedSort { - DOWNLOAD = 0, + NOT_SET = 0, + DOWNLOAD, NUMBER } } diff --git a/DownKyi.Core/Settings/Models/AboutSettings.cs b/DownKyi.Core/Settings/Models/AboutSettings.cs index 7b6a1db..46e1543 100644 --- a/DownKyi.Core/Settings/Models/AboutSettings.cs +++ b/DownKyi.Core/Settings/Models/AboutSettings.cs @@ -5,7 +5,7 @@ /// public class AboutSettings { - public AllowStatus IsReceiveBetaVersion { get; set; } - public AllowStatus AutoUpdateWhenLaunch { get; set; } + public AllowStatus IsReceiveBetaVersion { get; set; } = AllowStatus.NONE; + public AllowStatus AutoUpdateWhenLaunch { get; set; } = AllowStatus.NONE; } } diff --git a/DownKyi.Core/Settings/Models/BasicSettings.cs b/DownKyi.Core/Settings/Models/BasicSettings.cs index 46a53e0..43eea04 100644 --- a/DownKyi.Core/Settings/Models/BasicSettings.cs +++ b/DownKyi.Core/Settings/Models/BasicSettings.cs @@ -5,10 +5,11 @@ /// public class BasicSettings { - public AfterDownloadOperation AfterDownload { get; set; } - public AllowStatus IsListenClipboard { get; set; } - public AllowStatus IsAutoParseVideo { get; set; } - public ParseScope ParseScope { get; set; } - public DownloadFinishedSort DownloadFinishedSort { get; set; } + public AfterDownloadOperation AfterDownload { get; set; } = AfterDownloadOperation.NOT_SET; + public AllowStatus IsListenClipboard { get; set; } = AllowStatus.NONE; + public AllowStatus IsAutoParseVideo { get; set; } = AllowStatus.NONE; + public ParseScope ParseScope { get; set; } = ParseScope.NOT_SET; + public AllowStatus IsAutoDownloadAll { get; set; } = AllowStatus.NONE; + public DownloadFinishedSort DownloadFinishedSort { get; set; } = DownloadFinishedSort.NOT_SET; } } diff --git a/DownKyi.Core/Settings/Models/DanmakuSettings.cs b/DownKyi.Core/Settings/Models/DanmakuSettings.cs index 64bc828..e018152 100644 --- a/DownKyi.Core/Settings/Models/DanmakuSettings.cs +++ b/DownKyi.Core/Settings/Models/DanmakuSettings.cs @@ -5,15 +5,15 @@ /// public class DanmakuSettings { - public AllowStatus DanmakuTopFilter { get; set; } - public AllowStatus DanmakuBottomFilter { get; set; } - public AllowStatus DanmakuScrollFilter { get; set; } - public AllowStatus IsCustomDanmakuResolution { get; set; } - public int DanmakuScreenWidth { get; set; } - public int DanmakuScreenHeight { get; set; } - public string DanmakuFontName { get; set; } - public int DanmakuFontSize { get; set; } - public int DanmakuLineCount { get; set; } - public DanmakuLayoutAlgorithm DanmakuLayoutAlgorithm { get; set; } + public AllowStatus DanmakuTopFilter { get; set; } = AllowStatus.NONE; + public AllowStatus DanmakuBottomFilter { get; set; } = AllowStatus.NONE; + public AllowStatus DanmakuScrollFilter { get; set; } = AllowStatus.NONE; + public AllowStatus IsCustomDanmakuResolution { get; set; } = AllowStatus.NONE; + public int DanmakuScreenWidth { get; set; } = -1; + public int DanmakuScreenHeight { get; set; } = -1; + public string DanmakuFontName { get; set; } = null; + public int DanmakuFontSize { get; set; } = -1; + public int DanmakuLineCount { get; set; } = -1; + public DanmakuLayoutAlgorithm DanmakuLayoutAlgorithm { get; set; } = DanmakuLayoutAlgorithm.NONE; } } diff --git a/DownKyi.Core/Settings/Models/NetworkSettings.cs b/DownKyi.Core/Settings/Models/NetworkSettings.cs index cdfcb5f..6b283f8 100644 --- a/DownKyi.Core/Settings/Models/NetworkSettings.cs +++ b/DownKyi.Core/Settings/Models/NetworkSettings.cs @@ -7,17 +7,17 @@ namespace DownKyi.Core.Settings.Models /// public class NetworkSettings { - public AllowStatus IsLiftingOfRegion { get; set; } - public int AriaListenPort { get; set; } - public AriaConfigLogLevel AriaLogLevel { get; set; } - public int AriaMaxConcurrentDownloads { get; set; } - public int AriaSplit { get; set; } - public int AriaMaxOverallDownloadLimit { get; set; } - public int AriaMaxDownloadLimit { get; set; } - public AriaConfigFileAllocation AriaFileAllocation { get; set; } + public AllowStatus IsLiftingOfRegion { get; set; } = AllowStatus.NONE; + public int AriaListenPort { get; set; } = -1; + public AriaConfigLogLevel AriaLogLevel { get; set; } = AriaConfigLogLevel.NOT_SET; + public int AriaMaxConcurrentDownloads { get; set; } = -1; + public int AriaSplit { get; set; } = -1; + public int AriaMaxOverallDownloadLimit { get; set; } = -1; + public int AriaMaxDownloadLimit { get; set; } = -1; + public AriaConfigFileAllocation AriaFileAllocation { get; set; } = AriaConfigFileAllocation.NOT_SET; - public AllowStatus IsAriaHttpProxy { get; set; } - public string AriaHttpProxy { get; set; } - public int AriaHttpProxyListenPort { get; set; } + public AllowStatus IsAriaHttpProxy { get; set; } = AllowStatus.NONE; + public string AriaHttpProxy { get; set; } = null; + public int AriaHttpProxyListenPort { get; set; } = -1; } } diff --git a/DownKyi.Core/Settings/Models/VideoContentSettings.cs b/DownKyi.Core/Settings/Models/VideoContentSettings.cs new file mode 100644 index 0000000..ddc26a1 --- /dev/null +++ b/DownKyi.Core/Settings/Models/VideoContentSettings.cs @@ -0,0 +1,11 @@ +namespace DownKyi.Core.Settings.Models +{ + public class VideoContentSettings + { + public bool DownloadAudio { get; set; } = true; + public bool DownloadVideo { get; set; } = true; + public bool DownloadDanmaku { get; set; } = true; + public bool DownloadSubtitle { get; set; } = true; + public bool DownloadCover { get; set; } = true; + } +} diff --git a/DownKyi.Core/Settings/Models/VideoSettings.cs b/DownKyi.Core/Settings/Models/VideoSettings.cs index d5fe834..0cf431e 100644 --- a/DownKyi.Core/Settings/Models/VideoSettings.cs +++ b/DownKyi.Core/Settings/Models/VideoSettings.cs @@ -8,13 +8,16 @@ namespace DownKyi.Core.Settings.Models /// public class VideoSettings { - public VideoCodecs VideoCodecs { get; set; } // AVC or HEVC - public int Quality { get; set; } // 画质 - public int AudioQuality { get; set; } // 音质 - public AllowStatus IsTranscodingFlvToMp4 { get; set; } // 是否将flv转为mp4 - public string SaveVideoRootPath { get; set; } // 视频保存路径 - public List HistoryVideoRootPaths { get; set; } // 历史视频保存路径 - public AllowStatus IsUseSaveVideoRootPath { get; set; } // 是否使用默认视频保存路径 - public List FileNameParts { get; set; } // 文件命名格式 + public VideoCodecs VideoCodecs { get; set; } = VideoCodecs.NONE; // AVC or HEVC + public int Quality { get; set; } = -1; // 画质 + public int AudioQuality { get; set; } = -1; // 音质 + public AllowStatus IsTranscodingFlvToMp4 { get; set; } = AllowStatus.NONE; // 是否将flv转为mp4 + public string SaveVideoRootPath { get; set; } = null; // 视频保存路径 + public List HistoryVideoRootPaths { get; set; } = null; // 历史视频保存路径 + public AllowStatus IsUseSaveVideoRootPath { get; set; } = AllowStatus.NONE; // 是否使用默认视频保存路径 + public VideoContentSettings VideoContent { get; set; } = null; // 下载内容 + public List FileNameParts { get; set; } = null; // 文件命名格式 + public string FileNamePartTimeFormat { get; set; } = null; // 文件命名中的时间格式 + public OrderFormat OrderFormat { get; set; } = OrderFormat.NOT_SET; // 文件命名中的序号格式 } } diff --git a/DownKyi.Core/Settings/OrderFormat.cs b/DownKyi.Core/Settings/OrderFormat.cs new file mode 100644 index 0000000..f496835 --- /dev/null +++ b/DownKyi.Core/Settings/OrderFormat.cs @@ -0,0 +1,9 @@ +namespace DownKyi.Core.Settings +{ + public enum OrderFormat + { + NOT_SET = 0, + NATURAL, // 自然数 + LEADING_ZEROS, // 前导零填充 + } +} diff --git a/DownKyi.Core/Settings/ParseScope.cs b/DownKyi.Core/Settings/ParseScope.cs index b028eac..d846ebf 100644 --- a/DownKyi.Core/Settings/ParseScope.cs +++ b/DownKyi.Core/Settings/ParseScope.cs @@ -2,6 +2,7 @@ { public enum ParseScope { + NOT_SET = 0, NONE = 1, SELECTED_ITEM, CURRENT_SECTION, diff --git a/DownKyi.Core/Settings/SettingsManager.About.cs b/DownKyi.Core/Settings/SettingsManager.About.cs index b4a2f75..5cb15cb 100644 --- a/DownKyi.Core/Settings/SettingsManager.About.cs +++ b/DownKyi.Core/Settings/SettingsManager.About.cs @@ -15,7 +15,7 @@ public AllowStatus IsReceiveBetaVersion() { appSettings = GetSettings(); - if (appSettings.About.IsReceiveBetaVersion == 0) + if (appSettings.About.IsReceiveBetaVersion == AllowStatus.NONE) { // 第一次获取,先设置默认值 IsReceiveBetaVersion(isReceiveBetaVersion); @@ -42,7 +42,7 @@ public AllowStatus GetAutoUpdateWhenLaunch() { appSettings = GetSettings(); - if (appSettings.About.AutoUpdateWhenLaunch == 0) + if (appSettings.About.AutoUpdateWhenLaunch == AllowStatus.NONE) { // 第一次获取,先设置默认值 SetAutoUpdateWhenLaunch(autoUpdateWhenLaunch); diff --git a/DownKyi.Core/Settings/SettingsManager.Basic.cs b/DownKyi.Core/Settings/SettingsManager.Basic.cs index d5f93e7..ccf618f 100644 --- a/DownKyi.Core/Settings/SettingsManager.Basic.cs +++ b/DownKyi.Core/Settings/SettingsManager.Basic.cs @@ -14,6 +14,9 @@ // 默认的视频解析项 private readonly ParseScope parseScope = ParseScope.NONE; + // 解析后自动下载解析视频 + private readonly AllowStatus isAutoDownloadAll = AllowStatus.NO; + // 下载完成列表排序 private readonly DownloadFinishedSort finishedSort = DownloadFinishedSort.DOWNLOAD; @@ -24,7 +27,7 @@ public AfterDownloadOperation GetAfterDownloadOperation() { appSettings = GetSettings(); - if (appSettings.Basic.AfterDownload == 0) + if (appSettings.Basic.AfterDownload == AfterDownloadOperation.NOT_SET) { // 第一次获取,先设置默认值 SetAfterDownloadOperation(afterDownload); @@ -51,7 +54,7 @@ public AllowStatus IsListenClipboard() { appSettings = GetSettings(); - if (appSettings.Basic.IsListenClipboard == 0) + if (appSettings.Basic.IsListenClipboard == AllowStatus.NONE) { // 第一次获取,先设置默认值 IsListenClipboard(isListenClipboard); @@ -78,7 +81,7 @@ public AllowStatus IsAutoParseVideo() { appSettings = GetSettings(); - if (appSettings.Basic.IsAutoParseVideo == 0) + if (appSettings.Basic.IsAutoParseVideo == AllowStatus.NONE) { // 第一次获取,先设置默认值 IsAutoParseVideo(isAutoParseVideo); @@ -105,7 +108,7 @@ public ParseScope GetParseScope() { appSettings = GetSettings(); - if (appSettings.Basic.ParseScope == 0) + if (appSettings.Basic.ParseScope == ParseScope.NOT_SET) { // 第一次获取,先设置默认值 SetParseScope(parseScope); @@ -125,6 +128,33 @@ return SetSettings(); } + /// + /// 解析后是否自动下载解析视频 + /// + /// + public AllowStatus IsAutoDownloadAll() + { + appSettings = GetSettings(); + if (appSettings.Basic.IsAutoDownloadAll == AllowStatus.NONE) + { + // 第一次获取,先设置默认值 + IsAutoDownloadAll(isAutoDownloadAll); + return isAutoDownloadAll; + } + return appSettings.Basic.IsAutoDownloadAll; + } + + /// + /// 解析后是否自动下载解析视频 + /// + /// + /// + public bool IsAutoDownloadAll(AllowStatus isAutoDownloadAll) + { + appSettings.Basic.IsAutoDownloadAll = isAutoDownloadAll; + return SetSettings(); + } + /// /// 获取下载完成列表排序 /// @@ -132,7 +162,7 @@ public DownloadFinishedSort GetDownloadFinishedSort() { appSettings = GetSettings(); - if (appSettings.Basic.DownloadFinishedSort == 0) + if (appSettings.Basic.DownloadFinishedSort == DownloadFinishedSort.NOT_SET) { // 第一次获取,先设置默认值 SetDownloadFinishedSort(finishedSort); diff --git a/DownKyi.Core/Settings/SettingsManager.Danmaku.cs b/DownKyi.Core/Settings/SettingsManager.Danmaku.cs index 34f2b95..48e9a1b 100644 --- a/DownKyi.Core/Settings/SettingsManager.Danmaku.cs +++ b/DownKyi.Core/Settings/SettingsManager.Danmaku.cs @@ -40,7 +40,7 @@ public AllowStatus GetDanmakuTopFilter() { appSettings = GetSettings(); - if (appSettings.Danmaku.DanmakuTopFilter == 0) + if (appSettings.Danmaku.DanmakuTopFilter == AllowStatus.NONE) { // 第一次获取,先设置默认值 SetDanmakuTopFilter(danmakuTopFilter); @@ -67,7 +67,7 @@ public AllowStatus GetDanmakuBottomFilter() { appSettings = GetSettings(); - if (appSettings.Danmaku.DanmakuBottomFilter == 0) + if (appSettings.Danmaku.DanmakuBottomFilter == AllowStatus.NONE) { // 第一次获取,先设置默认值 SetDanmakuBottomFilter(danmakuBottomFilter); @@ -94,7 +94,7 @@ public AllowStatus GetDanmakuScrollFilter() { appSettings = GetSettings(); - if (appSettings.Danmaku.DanmakuScrollFilter == 0) + if (appSettings.Danmaku.DanmakuScrollFilter == AllowStatus.NONE) { // 第一次获取,先设置默认值 SetDanmakuScrollFilter(danmakuScrollFilter); @@ -121,7 +121,7 @@ public AllowStatus IsCustomDanmakuResolution() { appSettings = GetSettings(); - if (appSettings.Danmaku.IsCustomDanmakuResolution == 0) + if (appSettings.Danmaku.IsCustomDanmakuResolution == AllowStatus.NONE) { // 第一次获取,先设置默认值 IsCustomDanmakuResolution(isCustomDanmakuResolution); @@ -148,7 +148,7 @@ public int GetDanmakuScreenWidth() { appSettings = GetSettings(); - if (appSettings.Danmaku.DanmakuScreenWidth == 0) + if (appSettings.Danmaku.DanmakuScreenWidth == -1) { // 第一次获取,先设置默认值 SetDanmakuScreenWidth(danmakuScreenWidth); @@ -175,7 +175,7 @@ public int GetDanmakuScreenHeight() { appSettings = GetSettings(); - if (appSettings.Danmaku.DanmakuScreenHeight == 0) + if (appSettings.Danmaku.DanmakuScreenHeight == -1) { // 第一次获取,先设置默认值 SetDanmakuScreenHeight(danmakuScreenHeight); @@ -229,7 +229,7 @@ public int GetDanmakuFontSize() { appSettings = GetSettings(); - if (appSettings.Danmaku.DanmakuFontSize == 0) + if (appSettings.Danmaku.DanmakuFontSize == -1) { // 第一次获取,先设置默认值 SetDanmakuFontSize(danmakuFontSize); @@ -256,7 +256,7 @@ public int GetDanmakuLineCount() { appSettings = GetSettings(); - if (appSettings.Danmaku.DanmakuLineCount == 0) + if (appSettings.Danmaku.DanmakuLineCount == -1) { // 第一次获取,先设置默认值 SetDanmakuLineCount(danmakuLineCount); @@ -283,7 +283,7 @@ public DanmakuLayoutAlgorithm GetDanmakuLayoutAlgorithm() { appSettings = GetSettings(); - if (appSettings.Danmaku.DanmakuLayoutAlgorithm == 0) + if (appSettings.Danmaku.DanmakuLayoutAlgorithm == DanmakuLayoutAlgorithm.NONE) { // 第一次获取,先设置默认值 SetDanmakuLayoutAlgorithm(danmakuLayoutAlgorithm); diff --git a/DownKyi.Core/Settings/SettingsManager.Network.cs b/DownKyi.Core/Settings/SettingsManager.Network.cs index 95675e2..37842de 100644 --- a/DownKyi.Core/Settings/SettingsManager.Network.cs +++ b/DownKyi.Core/Settings/SettingsManager.Network.cs @@ -8,7 +8,7 @@ namespace DownKyi.Core.Settings private readonly AllowStatus isLiftingOfRegion = AllowStatus.YES; // Aria服务器端口号 - private readonly int ariaListenPort = 6800; + private readonly int ariaListenPort = 6801; // Aria日志等级 private readonly AriaConfigLogLevel ariaLogLevel = AriaConfigLogLevel.INFO; @@ -26,7 +26,7 @@ namespace DownKyi.Core.Settings private readonly int ariaMaxDownloadLimit = 0; // Aria文件预分配 - private readonly AriaConfigFileAllocation ariaFileAllocation = AriaConfigFileAllocation.PREALLOC; + private readonly AriaConfigFileAllocation ariaFileAllocation = AriaConfigFileAllocation.NONE; // Aria HttpProxy代理 private readonly AllowStatus isAriaHttpProxy = AllowStatus.NO; @@ -40,7 +40,7 @@ namespace DownKyi.Core.Settings public AllowStatus IsLiftingOfRegion() { appSettings = GetSettings(); - if (appSettings.Network.IsLiftingOfRegion == 0) + if (appSettings.Network.IsLiftingOfRegion == AllowStatus.NONE) { // 第一次获取,先设置默认值 IsLiftingOfRegion(isLiftingOfRegion); @@ -67,7 +67,7 @@ namespace DownKyi.Core.Settings public int GetAriaListenPort() { appSettings = GetSettings(); - if (appSettings.Network.AriaListenPort == 0) + if (appSettings.Network.AriaListenPort == -1) { // 第一次获取,先设置默认值 SetAriaListenPort(ariaListenPort); @@ -94,7 +94,7 @@ namespace DownKyi.Core.Settings public AriaConfigLogLevel GetAriaLogLevel() { appSettings = GetSettings(); - if (appSettings.Network.AriaLogLevel == 0) + if (appSettings.Network.AriaLogLevel == AriaConfigLogLevel.NOT_SET) { // 第一次获取,先设置默认值 SetAriaLogLevel(ariaLogLevel); @@ -121,7 +121,7 @@ namespace DownKyi.Core.Settings public int GetAriaMaxConcurrentDownloads() { appSettings = GetSettings(); - if (appSettings.Network.AriaMaxConcurrentDownloads == 0) + if (appSettings.Network.AriaMaxConcurrentDownloads == -1) { // 第一次获取,先设置默认值 SetAriaMaxConcurrentDownloads(ariaMaxConcurrentDownloads); @@ -148,7 +148,7 @@ namespace DownKyi.Core.Settings public int GetAriaSplit() { appSettings = GetSettings(); - if (appSettings.Network.AriaSplit == 0) + if (appSettings.Network.AriaSplit == -1) { // 第一次获取,先设置默认值 SetAriaSplit(ariaSplit); @@ -175,7 +175,7 @@ namespace DownKyi.Core.Settings public int GetAriaMaxOverallDownloadLimit() { appSettings = GetSettings(); - if (appSettings.Network.AriaMaxOverallDownloadLimit == 0) + if (appSettings.Network.AriaMaxOverallDownloadLimit == -1) { // 第一次获取,先设置默认值 SetAriaMaxOverallDownloadLimit(ariaMaxOverallDownloadLimit); @@ -202,7 +202,7 @@ namespace DownKyi.Core.Settings public int GetAriaMaxDownloadLimit() { appSettings = GetSettings(); - if (appSettings.Network.AriaMaxDownloadLimit == 0) + if (appSettings.Network.AriaMaxDownloadLimit == -1) { // 第一次获取,先设置默认值 SetAriaMaxDownloadLimit(ariaMaxDownloadLimit); @@ -229,7 +229,7 @@ namespace DownKyi.Core.Settings public AriaConfigFileAllocation GetAriaFileAllocation() { appSettings = GetSettings(); - if (appSettings.Network.AriaFileAllocation == 0) + if (appSettings.Network.AriaFileAllocation == AriaConfigFileAllocation.NOT_SET) { // 第一次获取,先设置默认值 SetAriaFileAllocation(ariaFileAllocation); @@ -256,7 +256,7 @@ namespace DownKyi.Core.Settings public AllowStatus IsAriaHttpProxy() { appSettings = GetSettings(); - if (appSettings.Network.IsAriaHttpProxy == 0) + if (appSettings.Network.IsAriaHttpProxy == AllowStatus.NONE) { // 第一次获取,先设置默认值 IsAriaHttpProxy(isAriaHttpProxy); @@ -310,7 +310,7 @@ namespace DownKyi.Core.Settings public int GetAriaHttpProxyListenPort() { appSettings = GetSettings(); - if (appSettings.Network.AriaHttpProxyListenPort == 0) + if (appSettings.Network.AriaHttpProxyListenPort == -1) { // 第一次获取,先设置默认值 SetAriaHttpProxyListenPort(ariaHttpProxyListenPort); diff --git a/DownKyi.Core/Settings/SettingsManager.Video.cs b/DownKyi.Core/Settings/SettingsManager.Video.cs index aa50f59..7a88cc4 100644 --- a/DownKyi.Core/Settings/SettingsManager.Video.cs +++ b/DownKyi.Core/Settings/SettingsManager.Video.cs @@ -1,4 +1,5 @@ using DownKyi.Core.FileName; +using DownKyi.Core.Settings.Models; using System; using System.Collections.Generic; using System.IO; @@ -28,6 +29,9 @@ namespace DownKyi.Core.Settings // 是否使用默认下载目录,如果是,则每次点击下载选中项时不再询问下载目录 private readonly AllowStatus isUseSaveVideoRootPath = AllowStatus.NO; + // 下载内容 + private readonly VideoContentSettings videoContent = new VideoContentSettings(); + // 文件命名格式 private readonly List fileNameParts = new List { @@ -44,6 +48,12 @@ namespace DownKyi.Core.Settings FileNamePart.VIDEO_CODEC, }; + // 文件命名中的时间格式 + private readonly string fileNamePartTimeFormat = "yyyy-MM-dd"; + + // 文件命名中的序号格式 + private readonly OrderFormat orderFormat = OrderFormat.NATURAL; + /// /// 获取优先下载的视频编码 /// @@ -51,7 +61,7 @@ namespace DownKyi.Core.Settings public VideoCodecs GetVideoCodecs() { appSettings = GetSettings(); - if (appSettings.Video.VideoCodecs == 0) + if (appSettings.Video.VideoCodecs == VideoCodecs.NONE) { // 第一次获取,先设置默认值 SetVideoCodecs(videoCodecs); @@ -78,7 +88,7 @@ namespace DownKyi.Core.Settings public int GetQuality() { appSettings = GetSettings(); - if (appSettings.Video.Quality == 0) + if (appSettings.Video.Quality == -1) { // 第一次获取,先设置默认值 SetQuality(quality); @@ -105,7 +115,7 @@ namespace DownKyi.Core.Settings public int GetAudioQuality() { appSettings = GetSettings(); - if (appSettings.Video.AudioQuality == 0) + if (appSettings.Video.AudioQuality == -1) { // 第一次获取,先设置默认值 SetAudioQuality(audioQuality); @@ -132,7 +142,7 @@ namespace DownKyi.Core.Settings public AllowStatus IsTranscodingFlvToMp4() { appSettings = GetSettings(); - if (appSettings.Video.IsTranscodingFlvToMp4 == 0) + if (appSettings.Video.IsTranscodingFlvToMp4 == AllowStatus.NONE) { // 第一次获取,先设置默认值 IsTranscodingFlvToMp4(isTranscodingFlvToMp4); @@ -213,7 +223,7 @@ namespace DownKyi.Core.Settings public AllowStatus IsUseSaveVideoRootPath() { appSettings = GetSettings(); - if (appSettings.Video.IsUseSaveVideoRootPath == 0) + if (appSettings.Video.IsUseSaveVideoRootPath == AllowStatus.NONE) { // 第一次获取,先设置默认值 IsUseSaveVideoRootPath(isUseSaveVideoRootPath); @@ -233,6 +243,33 @@ namespace DownKyi.Core.Settings return SetSettings(); } + /// + /// 获取下载内容 + /// + /// + public VideoContentSettings GetVideoContent() + { + appSettings = GetSettings(); + if (appSettings.Video.VideoContent == null) + { + // 第一次获取,先设置默认值 + SetVideoContent(videoContent); + return videoContent; + } + return appSettings.Video.VideoContent; + } + + /// + /// 设置下载内容 + /// + /// + /// + public bool SetVideoContent(VideoContentSettings videoContent) + { + appSettings.Video.VideoContent = videoContent; + return SetSettings(); + } + /// /// 获取文件命名格式 /// @@ -260,5 +297,59 @@ namespace DownKyi.Core.Settings return SetSettings(); } + /// + /// 获取文件命名中的时间格式 + /// + /// + public string GetFileNamePartTimeFormat() + { + appSettings = GetSettings(); + if (appSettings.Video.FileNamePartTimeFormat == null || appSettings.Video.FileNamePartTimeFormat == string.Empty) + { + // 第一次获取,先设置默认值 + SetFileNamePartTimeFormat(fileNamePartTimeFormat); + return fileNamePartTimeFormat; + } + return appSettings.Video.FileNamePartTimeFormat; + } + + /// + /// 设置文件命名中的时间格式 + /// + /// + /// + public bool SetFileNamePartTimeFormat(string fileNamePartTimeFormat) + { + appSettings.Video.FileNamePartTimeFormat = fileNamePartTimeFormat; + return SetSettings(); + } + + /// + /// 获取文件命名中的序号格式 + /// + /// + public OrderFormat GetOrderFormat() + { + appSettings = GetSettings(); + if (appSettings.Video.OrderFormat == OrderFormat.NOT_SET) + { + // 第一次获取,先设置默认值 + SetOrderFormat(orderFormat); + return orderFormat; + } + return appSettings.Video.OrderFormat; + } + + /// + /// 设置文件命名中的序号格式 + /// + /// + /// + public bool SetOrderFormat(OrderFormat orderFormat) + { + appSettings.Video.OrderFormat = orderFormat; + return SetSettings(); + } + } } diff --git a/DownKyi.Core/Settings/SettingsManager.cs b/DownKyi.Core/Settings/SettingsManager.cs index a5da781..f6d19b0 100644 --- a/DownKyi.Core/Settings/SettingsManager.cs +++ b/DownKyi.Core/Settings/SettingsManager.cs @@ -57,9 +57,11 @@ namespace DownKyi.Core.Settings { try { - StreamReader streamReader = File.OpenText(settingsName); + FileStream fileStream = new FileStream(settingsName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + StreamReader streamReader = new StreamReader(fileStream, System.Text.Encoding.UTF8); string jsonWordTemplate = streamReader.ReadToEnd(); streamReader.Close(); + fileStream.Close(); #if DEBUG #else @@ -71,7 +73,8 @@ namespace DownKyi.Core.Settings } catch (Exception e) { - Logging.LogManager.Error(e); + Utils.Debugging.Console.PrintLine("GetSettings()发生异常: {0}", e); + Logging.LogManager.Error("SettingsManager", e); return new AppSettings(); } } @@ -97,7 +100,8 @@ namespace DownKyi.Core.Settings } catch (Exception e) { - Logging.LogManager.Error(e); + Utils.Debugging.Console.PrintLine("SetSettings()发生异常: {0}", e); + Logging.LogManager.Error("SettingsManager", e); return false; } } diff --git a/DownKyi.Core/Storage/Database/DbHelper.cs b/DownKyi.Core/Storage/Database/DbHelper.cs index 8b6db35..a2e753f 100644 --- a/DownKyi.Core/Storage/Database/DbHelper.cs +++ b/DownKyi.Core/Storage/Database/DbHelper.cs @@ -1,20 +1,37 @@ -using System; +using DownKyi.Core.Logging; +using System; +using System.Collections.Generic; using System.Data.SQLite; namespace DownKyi.Core.Storage.Database { public class DbHelper { + private readonly string connStr; private readonly SQLiteConnection conn; + private static readonly Dictionary database = new Dictionary(); + /// /// 创建一个数据库 /// /// public DbHelper(string dbPath) { - string connStr = $"Data Source={dbPath};Version=3;"; + connStr = $"Data Source={dbPath};Version=3;"; + + if (database.ContainsKey(connStr)) + { + conn = database[connStr]; + + if (conn != null) + { + return; + } + } + conn = new SQLiteConnection(connStr); + database.Add(connStr, conn); } /// @@ -24,9 +41,21 @@ namespace DownKyi.Core.Storage.Database /// public DbHelper(string dbPath, string secretKey) { - string connStr = $"Data Source={dbPath};Version=3;"; + connStr = $"Data Source={dbPath};Version=3;"; + + if (database.ContainsKey(connStr)) + { + conn = database[connStr]; + + if (conn != null) + { + return; + } + } + conn = new SQLiteConnection(connStr); conn.SetPassword(secretKey); + database.Add(connStr, conn); } /// @@ -43,6 +72,8 @@ namespace DownKyi.Core.Storage.Database /// public void Open() { + if (conn == null) { return; } + if (!IsOpen()) { conn.Open(); @@ -54,9 +85,13 @@ namespace DownKyi.Core.Storage.Database /// public void Close() { + if (conn == null) { return; } + if (IsOpen()) { conn.Close(); + + database.Remove(connStr); } } @@ -66,21 +101,31 @@ namespace DownKyi.Core.Storage.Database /// public void ExecuteNonQuery(string sql, Action action = null) { - lock (conn) + if (conn == null) { return; } + + try { - Open(); - using (var tr = conn.BeginTransaction()) + lock (conn) { - using (var command = conn.CreateCommand()) + Open(); + using (var tr = conn.BeginTransaction()) { - command.CommandText = sql; - // 添加参数 - action?.Invoke(command.Parameters); - command.ExecuteNonQuery(); + using (var command = conn.CreateCommand()) + { + command.CommandText = sql; + // 添加参数 + action?.Invoke(command.Parameters); + command.ExecuteNonQuery(); + } + tr.Commit(); } - tr.Commit(); } } + catch (SQLiteException e) + { + Utils.Debugging.Console.PrintLine("DbHelper ExecuteNonQuery()发生异常: {0}", e); + LogManager.Error("DbHelper ExecuteNonQuery()", e); + } } /// @@ -90,16 +135,26 @@ namespace DownKyi.Core.Storage.Database /// public void ExecuteQuery(string sql, Action action) { - lock (conn) + if (conn == null) { return; } + + try { - Open(); - using (var command = conn.CreateCommand()) + lock (conn) { - command.CommandText = sql; - var reader = command.ExecuteReader(); - action(reader); + Open(); + using (var command = conn.CreateCommand()) + { + command.CommandText = sql; + var reader = command.ExecuteReader(); + action(reader); + } } } + catch (SQLiteException e) + { + Utils.Debugging.Console.PrintLine("DbHelper ExecuteQuery()发生异常: {0}", e); + LogManager.Error("DbHelper ExecuteQuery()", e); + } } } diff --git a/DownKyi.Core/Storage/StorageCover.cs b/DownKyi.Core/Storage/StorageCover.cs index a1556aa..dee2701 100644 --- a/DownKyi.Core/Storage/StorageCover.cs +++ b/DownKyi.Core/Storage/StorageCover.cs @@ -5,6 +5,7 @@ using System; using System.Drawing; using System.IO; using System.Windows.Media.Imaging; +using WebPSharp; namespace DownKyi.Core.Storage { @@ -44,10 +45,38 @@ namespace DownKyi.Core.Storage { if (cover == null) { return null; } - Bitmap bitmap = new Bitmap(cover); - Image thumbnail = bitmap.GetThumbnailImage(width, height, null, IntPtr.Zero); + try + { + Bitmap bitmap = new Bitmap(cover); + Image thumbnail = bitmap.GetThumbnailImage(width, height, null, IntPtr.Zero); + + return StorageUtils.BitmapToBitmapImage(new Bitmap(thumbnail)); + } + catch (ArgumentException) + { + try + { + SimpleDecoder simpleDecoder = new SimpleDecoder(cover); + Bitmap bitmap = simpleDecoder.WebPtoBitmap(); + Image thumbnail = bitmap.GetThumbnailImage(width, height, null, IntPtr.Zero); - return StorageUtils.BitmapToBitmapImage(new Bitmap(thumbnail)); + return StorageUtils.BitmapToBitmapImage(new Bitmap(thumbnail)); + } + catch (Exception ex) + { + Utils.Debugging.Console.PrintLine("GetCoverThumbnail()发生异常: {0}", ex); + LogManager.Error("StorageCover.GetCoverThumbnail()", ex); + + return null; + } + } + catch (Exception e) + { + Utils.Debugging.Console.PrintLine("GetCoverThumbnail()发生异常: {0}", e); + LogManager.Error("StorageCover.GetCoverThumbnail()", e); + + return null; + } } /// @@ -90,7 +119,7 @@ namespace DownKyi.Core.Storage }; coverDb.Update(newCover); - coverDb.Close(); + //coverDb.Close(); return $"{StorageManager.GetCover()}/{cover.Md5}"; } else @@ -108,12 +137,12 @@ namespace DownKyi.Core.Storage }; coverDb.Update(newCover); - coverDb.Close(); + //coverDb.Close(); return $"{StorageManager.GetCover()}/{md5}"; } else { - coverDb.Close(); + //coverDb.Close(); return null; } } @@ -133,12 +162,12 @@ namespace DownKyi.Core.Storage }; coverDb.Insert(newCover); - coverDb.Close(); + //coverDb.Close(); return $"{StorageManager.GetCover()}/{md5}"; } else { - coverDb.Close(); + //coverDb.Close(); return null; } } diff --git a/DownKyi.Core/Storage/StorageHeader.cs b/DownKyi.Core/Storage/StorageHeader.cs index 09a768a..49e0d5a 100644 --- a/DownKyi.Core/Storage/StorageHeader.cs +++ b/DownKyi.Core/Storage/StorageHeader.cs @@ -5,6 +5,7 @@ using System; using System.Drawing; using System.IO; using System.Windows.Media.Imaging; +using WebPSharp; namespace DownKyi.Core.Storage { @@ -44,10 +45,38 @@ namespace DownKyi.Core.Storage { if (header == null) { return null; } - var bitmap = new Bitmap(header); - var thumbnail = bitmap.GetThumbnailImage(width, height, null, IntPtr.Zero); + try + { + Bitmap bitmap = new Bitmap(header); + Image thumbnail = bitmap.GetThumbnailImage(width, height, null, IntPtr.Zero); + + return StorageUtils.BitmapToBitmapImage(new Bitmap(thumbnail)); + } + catch (ArgumentException) + { + try + { + SimpleDecoder simpleDecoder = new SimpleDecoder(header); + Bitmap bitmap = simpleDecoder.WebPtoBitmap(); + Image thumbnail = bitmap.GetThumbnailImage(width, height, null, IntPtr.Zero); - return StorageUtils.BitmapToBitmapImage(new Bitmap(thumbnail)); + return StorageUtils.BitmapToBitmapImage(new Bitmap(thumbnail)); + } + catch (Exception ex) + { + Utils.Debugging.Console.PrintLine("GetHeaderThumbnail()发生异常: {0}", ex); + LogManager.Error("StorageHeader.GetHeaderThumbnail()", ex); + + return null; + } + } + catch (Exception e) + { + Utils.Debugging.Console.PrintLine("GetHeaderThumbnail()发生异常: {0}", e); + LogManager.Error("StorageHeader.GetHeaderThumbnail()", e); + + return null; + } } /// @@ -58,7 +87,7 @@ namespace DownKyi.Core.Storage public string GetHeader(long mid, string name, string url) { HeaderDb headerDb = new HeaderDb(); - var header = headerDb.QueryByMid(mid); + Header header = headerDb.QueryByMid(mid); if (header != null) { @@ -73,7 +102,7 @@ namespace DownKyi.Core.Storage Md5 = header.Md5 }; headerDb.Update(newHeader); - headerDb.Close(); + //headerDb.Close(); return $"{StorageManager.GetHeader()}/{header.Md5}"; } else @@ -89,12 +118,12 @@ namespace DownKyi.Core.Storage Md5 = md5 }; headerDb.Insert(newHeader); - headerDb.Close(); + //headerDb.Close(); return $"{StorageManager.GetHeader()}/{md5}"; } else { - headerDb.Close(); + //headerDb.Close(); return null; } } @@ -112,12 +141,12 @@ namespace DownKyi.Core.Storage Md5 = md5 }; headerDb.Insert(newHeader); - headerDb.Close(); + //headerDb.Close(); return $"{StorageManager.GetHeader()}/{md5}"; } else { - headerDb.Close(); + //headerDb.Close(); return null; } } diff --git a/DownKyi.Core/Utils/Format.cs b/DownKyi.Core/Utils/Format.cs index 910cafd..6e0faf1 100644 --- a/DownKyi.Core/Utils/Format.cs +++ b/DownKyi.Core/Utils/Format.cs @@ -199,7 +199,7 @@ namespace DownKyi.Core.Utils destName = Regex.Replace(destName, @"\p{C}+", string.Empty); // 移除前导和尾部的空白字符、dot符 - return destName.Trim().TrimStart('.').TrimEnd('.'); + return destName.Trim('.').Trim(); } } diff --git a/DownKyi.Core/Utils/MachineCode.cs b/DownKyi.Core/Utils/MachineCode.cs index 5c13cb2..faecd8f 100644 --- a/DownKyi.Core/Utils/MachineCode.cs +++ b/DownKyi.Core/Utils/MachineCode.cs @@ -20,8 +20,8 @@ namespace DownKyi.Core.Utils string machineCodeString = "PC." + machineCode.GetMainBordId() + "." + - machineCode.GetCpuInfo() + "." + - machineCode.GetDiskID();// + "." + + machineCode.GetCpuInfo();// + "." + + //machineCode.GetDiskID();// + "." + //machineCode.GetMoAddress(); return machineCodeString.Replace(" ", ""); } diff --git a/DownKyi/aria2_COPYING.txt b/DownKyi.Core/aria2_COPYING.txt similarity index 100% rename from DownKyi/aria2_COPYING.txt rename to DownKyi.Core/aria2_COPYING.txt diff --git a/DownKyi.Core/aria2c.exe b/DownKyi.Core/aria2c.exe new file mode 100644 index 0000000..97b2b5c Binary files /dev/null and b/DownKyi.Core/aria2c.exe differ diff --git a/DownKyi/ffmpeg.exe b/DownKyi.Core/ffmpeg.exe similarity index 71% rename from DownKyi/ffmpeg.exe rename to DownKyi.Core/ffmpeg.exe index 3284f06..06e8a67 100644 Binary files a/DownKyi/ffmpeg.exe and b/DownKyi.Core/ffmpeg.exe differ diff --git a/DownKyi.Core/packages.config b/DownKyi.Core/packages.config index c49a756..8f12907 100644 --- a/DownKyi.Core/packages.config +++ b/DownKyi.Core/packages.config @@ -11,4 +11,5 @@ + \ No newline at end of file diff --git a/DownKyi.sln b/DownKyi.sln index 5bc5e70..30ddbe1 100644 --- a/DownKyi.sln +++ b/DownKyi.sln @@ -19,29 +19,73 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 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}.Debug|x64.ActiveCfg = Debug|x64 + {97075FCD-6E8F-4FF9-B73A-994197F3765A}.Debug|x64.Build.0 = Debug|x64 + {97075FCD-6E8F-4FF9-B73A-994197F3765A}.Debug|x86.ActiveCfg = Debug|x86 + {97075FCD-6E8F-4FF9-B73A-994197F3765A}.Debug|x86.Build.0 = Debug|x86 {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 + {97075FCD-6E8F-4FF9-B73A-994197F3765A}.Release|x64.ActiveCfg = Release|x64 + {97075FCD-6E8F-4FF9-B73A-994197F3765A}.Release|x64.Build.0 = Release|x64 + {97075FCD-6E8F-4FF9-B73A-994197F3765A}.Release|x86.ActiveCfg = Release|x86 + {97075FCD-6E8F-4FF9-B73A-994197F3765A}.Release|x86.Build.0 = Release|x86 {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}.Debug|x64.ActiveCfg = Debug|x64 + {4FDE0364-F65B-4812-BFE8-34E886624FBD}.Debug|x64.Build.0 = Debug|x64 + {4FDE0364-F65B-4812-BFE8-34E886624FBD}.Debug|x86.ActiveCfg = Debug|x86 + {4FDE0364-F65B-4812-BFE8-34E886624FBD}.Debug|x86.Build.0 = Debug|x86 {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 + {4FDE0364-F65B-4812-BFE8-34E886624FBD}.Release|x64.ActiveCfg = Release|x64 + {4FDE0364-F65B-4812-BFE8-34E886624FBD}.Release|x64.Build.0 = Release|x64 + {4FDE0364-F65B-4812-BFE8-34E886624FBD}.Release|x86.ActiveCfg = Release|x86 + {4FDE0364-F65B-4812-BFE8-34E886624FBD}.Release|x86.Build.0 = Release|x86 {3107CD63-E257-455E-AE81-1FD3582B067A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3107CD63-E257-455E-AE81-1FD3582B067A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3107CD63-E257-455E-AE81-1FD3582B067A}.Debug|x64.ActiveCfg = Debug|x64 + {3107CD63-E257-455E-AE81-1FD3582B067A}.Debug|x64.Build.0 = Debug|x64 + {3107CD63-E257-455E-AE81-1FD3582B067A}.Debug|x86.ActiveCfg = Debug|x86 + {3107CD63-E257-455E-AE81-1FD3582B067A}.Debug|x86.Build.0 = Debug|x86 {3107CD63-E257-455E-AE81-1FD3582B067A}.Release|Any CPU.ActiveCfg = Release|Any CPU {3107CD63-E257-455E-AE81-1FD3582B067A}.Release|Any CPU.Build.0 = Release|Any CPU + {3107CD63-E257-455E-AE81-1FD3582B067A}.Release|x64.ActiveCfg = Release|x64 + {3107CD63-E257-455E-AE81-1FD3582B067A}.Release|x64.Build.0 = Release|x64 + {3107CD63-E257-455E-AE81-1FD3582B067A}.Release|x86.ActiveCfg = Release|x86 + {3107CD63-E257-455E-AE81-1FD3582B067A}.Release|x86.Build.0 = Release|x86 {81B9719E-DA29-444F-BB72-CBD5819A654D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {81B9719E-DA29-444F-BB72-CBD5819A654D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81B9719E-DA29-444F-BB72-CBD5819A654D}.Debug|x64.ActiveCfg = Debug|x64 + {81B9719E-DA29-444F-BB72-CBD5819A654D}.Debug|x64.Build.0 = Debug|x64 + {81B9719E-DA29-444F-BB72-CBD5819A654D}.Debug|x86.ActiveCfg = Debug|x86 + {81B9719E-DA29-444F-BB72-CBD5819A654D}.Debug|x86.Build.0 = Debug|x86 {81B9719E-DA29-444F-BB72-CBD5819A654D}.Release|Any CPU.ActiveCfg = Release|Any CPU {81B9719E-DA29-444F-BB72-CBD5819A654D}.Release|Any CPU.Build.0 = Release|Any CPU + {81B9719E-DA29-444F-BB72-CBD5819A654D}.Release|x64.ActiveCfg = Release|x64 + {81B9719E-DA29-444F-BB72-CBD5819A654D}.Release|x64.Build.0 = Release|x64 + {81B9719E-DA29-444F-BB72-CBD5819A654D}.Release|x86.ActiveCfg = Release|x86 + {81B9719E-DA29-444F-BB72-CBD5819A654D}.Release|x86.Build.0 = Release|x86 {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Debug|Any CPU.Build.0 = Debug|Any CPU + {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Debug|x64.ActiveCfg = Debug|x64 + {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Debug|x64.Build.0 = Debug|x64 + {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Debug|x86.ActiveCfg = Debug|x86 + {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Debug|x86.Build.0 = Debug|x86 {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Release|Any CPU.ActiveCfg = Release|Any CPU {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Release|Any CPU.Build.0 = Release|Any CPU + {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Release|x64.ActiveCfg = Release|x64 + {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Release|x64.Build.0 = Release|x64 + {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Release|x86.ActiveCfg = Release|x86 + {95F12C16-86B5-43D5-AF3E-D2489E2DB239}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/DownKyi/App.xaml.cs b/DownKyi/App.xaml.cs index 1ef4e1f..d698c99 100644 --- a/DownKyi/App.xaml.cs +++ b/DownKyi/App.xaml.cs @@ -16,6 +16,7 @@ using DownKyi.Views.Settings; using DownKyi.Views.Toolbox; using DownKyi.Views.UserSpace; using Prism.Ioc; +using Prism.Services.Dialogs; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -201,6 +202,7 @@ namespace DownKyi containerRegistry.RegisterForNavigation(ViewModels.UserSpace.ViewChannelViewModel.Tag); // dialogs + containerRegistry.RegisterDialog(ViewAlertDialogViewModel.Tag); containerRegistry.RegisterDialog(ViewDownloadSetterViewModel.Tag); containerRegistry.RegisterDialog(ViewParsingSelectorViewModel.Tag); diff --git a/DownKyi/AppConstant.cs b/DownKyi/AppConstant.cs new file mode 100644 index 0000000..cad527c --- /dev/null +++ b/DownKyi/AppConstant.cs @@ -0,0 +1,7 @@ +namespace DownKyi +{ + public class AppConstant + { + public const string ClipboardId = "32ff00b1-1a09-4b25-9ca7-dcb6914b141c"; + } +} diff --git a/DownKyi/DownKyi.csproj b/DownKyi/DownKyi.csproj index 7a7c8b2..0ed81f1 100644 --- a/DownKyi/DownKyi.csproj +++ b/DownKyi/DownKyi.csproj @@ -56,6 +56,22 @@ app.manifest + + x64 + bin\x64\Debug\ + + + x64 + bin\x64\Release\ + + + x86 + bin\x86\Debug\ + + + x86 + bin\x86\Release\ + @@ -79,6 +95,7 @@ MSBuild:Compile Designer + CustomPager.xaml @@ -97,11 +114,15 @@ + + + + @@ -170,6 +191,9 @@ + + ViewAlertDialog.xaml + ViewDownloadSetter.xaml @@ -337,6 +361,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -554,18 +582,6 @@ - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - diff --git a/DownKyi/FFmpeg_LICENSE.txt b/DownKyi/FFmpeg_LICENSE.txt deleted file mode 100644 index 65c5ca8..0000000 --- a/DownKyi/FFmpeg_LICENSE.txt +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser 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 -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/DownKyi/Images/SystemIcon.cs b/DownKyi/Images/SystemIcon.cs index b6bec27..b2b83cb 100644 --- a/DownKyi/Images/SystemIcon.cs +++ b/DownKyi/Images/SystemIcon.cs @@ -65,6 +65,34 @@ 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" }; + + Info = new VectorImage + { + Height = 20, + Width = 20, + Data = @"M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 + 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z", + Fill = "#FF00bcf2" + }; + + Warning = new VectorImage + { + Height = 20, + Width = 20, + Data = @"M12 5.99L19.53 19H4.47L12 5.99M2.74 18c-.77 1.33.19 3 1.73 3h15.06c1.54 0 2.5-1.67 1.73-3L13.73 + 4.99c-.77-1.33-2.69-1.33-3.46 0L2.74 18zM11 11v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zm0 5h2v2h-2z", + Fill = "#FFffb900" + }; + + Error = new VectorImage + { + Height = 20, + Width = 20, + Data = @"M12 7c.55 0 1 .45 1 1v4c0 .55-.45 1-1 1s-1-.45-1-1V8c0-.55.45-1 1-1zm-.01-5C6.47 2 2 6.48 2 12s4.47 + 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 + 8-3.58 8-8 8zm1-3h-2v-2h2v2z", + Fill = "#FFd83b01" + }; } public VectorImage Close { get; private set; } @@ -72,5 +100,9 @@ public VectorImage Minimize { get; private set; } public VectorImage Restore { get; private set; } public VectorImage Skin { get; private set; } + + public VectorImage Info { get; private set; } + public VectorImage Warning { get; private set; } + public VectorImage Error { get; private set; } } } diff --git a/DownKyi/Languages/Default.xaml b/DownKyi/Languages/Default.xaml index 7617c23..89d7ff0 100644 --- a/DownKyi/Languages/Default.xaml +++ b/DownKyi/Languages/Default.xaml @@ -185,6 +185,7 @@ 监听剪贴板 视频自动解析 视频解析范围: + 解析后自动下载已解析视频 网络 Aria服务器端口: @@ -224,6 +225,10 @@ UP主ID UP主昵称 恢复默认 + 时间格式: + 序号格式: + 自然数 + 前导零填充 弹幕 按类型屏蔽 @@ -293,7 +298,14 @@ 提取视频 + 信息 + 警告 + 错误 + + 确定 取消 + + 您确定要删除吗? 请选择文件夹 @@ -302,6 +314,7 @@ 浏览 盘剩余空间: 下载内容: + 下载内容 所有 音频 视频 diff --git a/DownKyi/Models/AppInfo.cs b/DownKyi/Models/AppInfo.cs index c83274f..2b9b0b0 100644 --- a/DownKyi/Models/AppInfo.cs +++ b/DownKyi/Models/AppInfo.cs @@ -3,12 +3,12 @@ public class AppInfo { public string Name { get; } = "哔哩下载姬"; - public int VersionCode { get; } = 503; + public int VersionCode { get; } = 508; #if DEBUG - public string VersionName { get; } = "1.5.0-alpha4 Debug"; + public string VersionName { get; } = "1.5.1 Debug"; #else - public string VersionName { get; } = "1.5.0-alpha4"; + public string VersionName { get; } = "1.5.1"; #endif } diff --git a/DownKyi/Models/OrderFormatDisplay.cs b/DownKyi/Models/OrderFormatDisplay.cs new file mode 100644 index 0000000..5e2a1a3 --- /dev/null +++ b/DownKyi/Models/OrderFormatDisplay.cs @@ -0,0 +1,10 @@ +using DownKyi.Core.Settings; + +namespace DownKyi.Models +{ + public class OrderFormatDisplay + { + public string Name { get; set; } + public OrderFormat OrderFormat { get; set; } + } +} diff --git a/DownKyi/Properties/AssemblyInfo.cs b/DownKyi/Properties/AssemblyInfo.cs index 557ec1b..55552dc 100644 --- a/DownKyi/Properties/AssemblyInfo.cs +++ b/DownKyi/Properties/AssemblyInfo.cs @@ -12,7 +12,7 @@ using System.Windows; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("DownKyi")] [assembly: AssemblyProduct("DownKyi")] -[assembly: AssemblyCopyright("Copyright © Downkyi 2020-2021")] +[assembly: AssemblyCopyright("Copyright © Downkyi 2020-2022")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -51,5 +51,5 @@ using System.Windows; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.5.0.0")] -[assembly: AssemblyFileVersion("1.5.0.0")] +[assembly: AssemblyVersion("1.5.1.0")] +[assembly: AssemblyFileVersion("1.5.1.0")] diff --git a/DownKyi/Services/AlertService.cs b/DownKyi/Services/AlertService.cs new file mode 100644 index 0000000..e30a9ff --- /dev/null +++ b/DownKyi/Services/AlertService.cs @@ -0,0 +1,75 @@ +using DownKyi.Images; +using DownKyi.Utils; +using DownKyi.ViewModels.Dialogs; +using Prism.Services.Dialogs; + +namespace DownKyi.Services +{ + public class AlertService + { + private readonly IDialogService dialogService; + + public AlertService(IDialogService dialogService) + { + this.dialogService = dialogService; + } + + /// + /// 显示一个信息弹窗 + /// + /// + /// + public ButtonResult ShowInfo(string message) + { + VectorImage image = SystemIcon.Instance().Info; + string title = DictionaryResource.GetString("Info"); + return ShowMessage(image, title, message); + } + + /// + /// 显示一个警告弹窗 + /// + /// + /// + public ButtonResult ShowWarning(string message) + { + VectorImage image = SystemIcon.Instance().Warning; + string title = DictionaryResource.GetString("Warning"); + return ShowMessage(image, title, message); + } + + /// + /// 显示一个错误弹窗 + /// + /// + /// + public ButtonResult ShowError(string message) + { + VectorImage image = SystemIcon.Instance().Error; + string title = DictionaryResource.GetString("Error"); + return ShowMessage(image, title, message); + } + + private ButtonResult ShowMessage(VectorImage image, string type, string message) + { + ButtonResult result = ButtonResult.None; + if (dialogService == null) + { + return result; + } + + DialogParameters param = new DialogParameters + { + { "image", image }, + { "title", type }, + { "message", message } + }; + dialogService.ShowDialog(ViewAlertDialogViewModel.Tag, param, buttonResult => + { + result = buttonResult.Result; + }); + return result; + } + + } +} diff --git a/DownKyi/Services/BangumiInfoService.cs b/DownKyi/Services/BangumiInfoService.cs index aebf31c..69f1c6d 100644 --- a/DownKyi/Services/BangumiInfoService.cs +++ b/DownKyi/Services/BangumiInfoService.cs @@ -3,6 +3,7 @@ using DownKyi.Core.BiliApi.Bangumi.Models; using DownKyi.Core.BiliApi.BiliUtils; using DownKyi.Core.BiliApi.VideoStream; using DownKyi.Core.BiliApi.VideoStream.Models; +using DownKyi.Core.Settings; using DownKyi.Core.Storage; using DownKyi.Core.Utils; using DownKyi.Utils; @@ -120,10 +121,12 @@ namespace DownKyi.Services }; } + // 文件命名中的时间格式 + string timeFormat = SettingsManager.GetInstance().GetFileNamePartTimeFormat(); // 视频发布时间 DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区 DateTime dateTime = startTime.AddSeconds(episode.PubTime); - page.PublishTime = dateTime.ToString("yyyy-MM-dd"); + page.PublishTime = dateTime.ToString(timeFormat); pages.Add(page); } @@ -135,11 +138,9 @@ namespace DownKyi.Services /// 获取视频章节与剧集 /// /// - public List GetVideoSections() + public List GetVideoSections(bool noUgc = false) { if (bangumiSeason == null) { return null; } - if (bangumiSeason.Section == null) { return null; } - if (bangumiSeason.Section.Count == 0) { return null; } List videoSections = new List { @@ -152,6 +153,15 @@ namespace DownKyi.Services } }; + // 不需要其他季或花絮内容 + if (noUgc) + { + return videoSections; + } + + if (bangumiSeason.Section == null) { return null; } + if (bangumiSeason.Section.Count == 0) { return null; } + foreach (BangumiSection section in bangumiSeason.Section) { List pages = new List(); @@ -194,10 +204,12 @@ namespace DownKyi.Services }; } + // 文件命名中的时间格式 + string timeFormat = SettingsManager.GetInstance().GetFileNamePartTimeFormat(); // 视频发布时间 DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区 DateTime dateTime = startTime.AddSeconds(episode.PubTime); - page.PublishTime = dateTime.ToString("yyyy-MM-dd"); + page.PublishTime = dateTime.ToString(timeFormat); pages.Add(page); } diff --git a/DownKyi/Services/CheeseInfoService.cs b/DownKyi/Services/CheeseInfoService.cs index a49e925..62b5520 100644 --- a/DownKyi/Services/CheeseInfoService.cs +++ b/DownKyi/Services/CheeseInfoService.cs @@ -3,6 +3,7 @@ using DownKyi.Core.BiliApi.Cheese; using DownKyi.Core.BiliApi.Cheese.Models; using DownKyi.Core.BiliApi.VideoStream; using DownKyi.Core.BiliApi.VideoStream.Models; +using DownKyi.Core.Settings; using DownKyi.Core.Storage; using DownKyi.Core.Utils; using DownKyi.Utils; @@ -88,10 +89,12 @@ namespace DownKyi.Services }; } + // 文件命名中的时间格式 + string timeFormat = SettingsManager.GetInstance().GetFileNamePartTimeFormat(); // 视频发布时间 DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区 DateTime dateTime = startTime.AddSeconds(episode.ReleaseDate); - page.PublishTime = dateTime.ToString("yyyy-MM-dd"); + page.PublishTime = dateTime.ToString(timeFormat); pages.Add(page); } @@ -103,7 +106,7 @@ namespace DownKyi.Services /// 获取视频章节与剧集 /// /// - public List GetVideoSections() + public List GetVideoSections(bool noUgc = false) { return null; } diff --git a/DownKyi/Services/Download/AddToDownloadService.cs b/DownKyi/Services/Download/AddToDownloadService.cs index f6d1273..c90519d 100644 --- a/DownKyi/Services/Download/AddToDownloadService.cs +++ b/DownKyi/Services/Download/AddToDownloadService.cs @@ -4,6 +4,7 @@ using DownKyi.Core.BiliApi.Zone; using DownKyi.Core.FileName; using DownKyi.Core.Logging; using DownKyi.Core.Settings; +using DownKyi.Core.Settings.Models; using DownKyi.Core.Utils; using DownKyi.Events; using DownKyi.Models; @@ -103,7 +104,7 @@ namespace DownKyi.Services.Download return; } - videoSections = videoInfoService.GetVideoSections(); + videoSections = videoInfoService.GetVideoSections(true); if (videoSections == null) { LogManager.Debug(Tag, "videoSections is not exist."); @@ -160,6 +161,14 @@ namespace DownKyi.Services.Download // 是否使用默认下载目录 if (SettingsManager.GetInstance().IsUseSaveVideoRootPath() == AllowStatus.YES) { + // 下载内容 + VideoContentSettings videoContent = SettingsManager.GetInstance().GetVideoContent(); + downloadAudio = videoContent.DownloadAudio; + downloadVideo = videoContent.DownloadVideo; + downloadDanmaku = videoContent.DownloadDanmaku; + downloadSubtitle = videoContent.DownloadSubtitle; + downloadCover = videoContent.DownloadCover; + directory = SettingsManager.GetInstance().GetSaveVideoRootPath(); } else @@ -196,7 +205,14 @@ namespace DownKyi.Services.Download return directory; } - public int AddToDownload(IEventAggregator eventAggregator, string directory) + /// + /// 添加到下载列表 + /// + /// 传递事件的对象 + /// 下载路径 + /// 是否下载所有,包括未选中项 + /// 添加的数量 + public int AddToDownload(IEventAggregator eventAggregator, string directory, bool isAll = false) { if (directory == null || directory == string.Empty) { return -1; } if (videoSections == null) { return -1; } @@ -212,7 +228,7 @@ namespace DownKyi.Services.Download foreach (VideoPage page in section.VideoPages) { // 只下载选中项,跳过未选中项 - if (!page.IsSelected) { continue; } + if (!isAll && !page.IsSelected) { continue; } // 没有解析的也跳过 if (page.PlayUrl == null) { continue; } @@ -288,8 +304,7 @@ namespace DownKyi.Services.Download // 文件路径 List fileNameParts = SettingsManager.GetInstance().GetFileNameParts(); - FileName fileName = FileName.Builder(fileNameParts) - .SetOrder(page.Order) + FileName fileName = FileName.Builder(fileNameParts) .SetSection(Format.FormatFileName(sectionName)) .SetMainTitle(Format.FormatFileName(videoInfoView.Title)) .SetPageTitle(Format.FormatFileName(page.Name)) @@ -302,7 +317,21 @@ namespace DownKyi.Services.Download .SetBvid(page.Bvid) .SetCid(page.Cid) .SetUpMid(page.Owner.Mid) - .SetUpName(page.Owner.Name); + .SetUpName(Format.FormatFileName(page.Owner.Name)); + + // 序号设置 + OrderFormat orderFormat = SettingsManager.GetInstance().GetOrderFormat(); + switch (orderFormat) + { + case OrderFormat.NATURAL: + fileName.SetOrder(page.Order); + break; + case OrderFormat.LEADING_ZEROS: + fileName.SetOrder(page.Order, section.VideoPages.Count); + break; + } + + // 合成绝对路径 string filePath = Path.Combine(directory, fileName.RelativePath()); // 视频类别 diff --git a/DownKyi/Services/Download/AriaDownloadService.cs b/DownKyi/Services/Download/AriaDownloadService.cs index c768fad..9981b2f 100644 --- a/DownKyi/Services/Download/AriaDownloadService.cs +++ b/DownKyi/Services/Download/AriaDownloadService.cs @@ -137,25 +137,33 @@ namespace DownKyi.Services.Download if (downloadVideo.BackupUrl != null) { urls.AddRange(downloadVideo.BackupUrl); } // 路径 + downloading.DownloadBase.FilePath = downloading.DownloadBase.FilePath.Replace("\\", "/"); string[] temp = downloading.DownloadBase.FilePath.Split('/'); - string path = downloading.DownloadBase.FilePath.Replace(temp[temp.Length - 1], ""); + //string path = downloading.DownloadBase.FilePath.Replace(temp[temp.Length - 1], ""); + string path = downloading.DownloadBase.FilePath.TrimEnd(temp[temp.Length - 1].ToCharArray()); // 下载文件名 string fileName = Guid.NewGuid().ToString("N"); - string key = $"{downloadVideo.Id}_{downloadVideo.Codecs}"; + // 老版本数据库没有这一项,会变成null if (downloading.Downloading.DownloadedFiles == null) + { downloading.Downloading.DownloadedFiles = new List(); - // 还要检查一下文件有没有被人删掉,删掉的话重新下载 - // 如果下载视频之后音频文件被人删了。此时gid还是视频的,会下错文件 - if (downloading.Downloading.DownloadedFiles.Contains(key) && File.Exists(Path.Combine(path, fileName))) - return Path.Combine(path, fileName); + } + if (downloading.Downloading.DownloadFiles.ContainsKey(key)) { // 如果存在,表示下载过, // 则继续使用上次下载的文件名 fileName = downloading.Downloading.DownloadFiles[key]; + + // 还要检查一下文件有没有被人删掉,删掉的话重新下载 + // 如果下载视频之后音频文件被人删了。此时gid还是视频的,会下错文件 + if (downloading.Downloading.DownloadedFiles.Contains(key) && File.Exists(Path.Combine(path, fileName))) + { + return Path.Combine(path, fileName); + } } else { @@ -502,6 +510,9 @@ namespace DownKyi.Services.Download /// private async Task DoWork() { + // 上次循环时正在下载的数量 + int lastDownloadingCount = 0; + while (true) { int maxDownloading = SettingsManager.GetInstance().GetAriaMaxConcurrentDownloads(); @@ -554,6 +565,13 @@ namespace DownKyi.Services.Download break; } + // 判断下载列表中的视频是否全部下载完成 + if (lastDownloadingCount > 0 && downloadingList.Count == 0 && downloadedList.Count > 0) + { + AfterDownload(); + } + lastDownloadingCount = downloadingList.Count; + // 降低CPU占用 await Task.Delay(500); } @@ -574,8 +592,11 @@ namespace DownKyi.Services.Download private async Task SingleDownload(DownloadingItem downloading) { // 路径 + downloading.DownloadBase.FilePath = downloading.DownloadBase.FilePath.Replace("\\", "/"); string[] temp = downloading.DownloadBase.FilePath.Split('/'); - string path = downloading.DownloadBase.FilePath.Replace(temp[temp.Length - 1], ""); + //string path = downloading.DownloadBase.FilePath.Replace(temp[temp.Length - 1], ""); + string path = downloading.DownloadBase.FilePath.TrimEnd(temp[temp.Length - 1].ToCharArray()); + // 路径不存在则创建 if (!Directory.Exists(path)) { @@ -815,6 +836,36 @@ namespace DownKyi.Services.Download downloading.StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); } + /// + /// 下载完成后的操作 + /// + private void AfterDownload() + { + AfterDownloadOperation operation = SettingsManager.GetInstance().GetAfterDownloadOperation(); + switch (operation) + { + case AfterDownloadOperation.NONE: + // 没有操作 + break; + case AfterDownloadOperation.OPEN_FOLDER: + // 打开文件夹 + break; + case AfterDownloadOperation.CLOSE_APP: + // 关闭程序 + App.PropertyChangeAsync(() => + { + System.Windows.Application.Current.Shutdown(); + }); + break; + case AfterDownloadOperation.CLOSE_SYSTEM: + // 关机 + System.Diagnostics.Process.Start("shutdown.exe", "-s"); + break; + default: + break; + } + } + /// /// 获取图片的扩展名 /// @@ -973,10 +1024,10 @@ namespace DownKyi.Services.Download { //HttpProxy = $"http://{Settings.GetAriaHttpProxy()}:{Settings.GetAriaHttpProxyListenPort()}", Dir = path, - Out = localFileName - //Header = $"cookie: {Login.GetLoginInfoCookiesString()}\nreferer: https://www.bilibili.com", - //UseHead = "true", - //UserAgent = Utils.GetUserAgent() + Out = localFileName, + Header = $"cookie: {LoginHelper.GetLoginInfoCookiesString()}\nreferer: https://www.bilibili.com", + UseHead = "true", + UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", }; // 如果设置了代理,则增加HttpProxy diff --git a/DownKyi/Services/Download/DownloadStorageService.cs b/DownKyi/Services/Download/DownloadStorageService.cs index d0bab9e..5421aa9 100644 --- a/DownKyi/Services/Download/DownloadStorageService.cs +++ b/DownKyi/Services/Download/DownloadStorageService.cs @@ -7,6 +7,16 @@ namespace DownKyi.Services.Download { public class DownloadStorageService { + ~DownloadStorageService() + { + DownloadingDb downloadingDb = new DownloadingDb(); + downloadingDb.Close(); + DownloadedDb downloadedDb = new DownloadedDb(); + downloadedDb.Close(); + DownloadBaseDb downloadBaseDb = new DownloadBaseDb(); + downloadBaseDb.Close(); + } + #region 下载中数据 /// @@ -25,7 +35,7 @@ namespace DownKyi.Services.Download { downloadingDb.Insert(downloadingItem.DownloadBase.Uuid, downloadingItem.Downloading); } - downloadingDb.Close(); + //downloadingDb.Close(); } /// @@ -40,7 +50,7 @@ namespace DownKyi.Services.Download DownloadingDb downloadingDb = new DownloadingDb(); downloadingDb.Delete(downloadingItem.DownloadBase.Uuid); - downloadingDb.Close(); + //downloadingDb.Close(); } /// @@ -52,7 +62,7 @@ namespace DownKyi.Services.Download // 从数据库获取数据 DownloadingDb downloadingDb = new DownloadingDb(); Dictionary dic = downloadingDb.QueryAll(); - downloadingDb.Close(); + //downloadingDb.Close(); // 遍历 List list = new List(); @@ -66,6 +76,7 @@ namespace DownKyi.Services.Download Downloading = downloading }; + if (downloadingItem.DownloadBase == null) { continue; } list.Add(downloadingItem); } } @@ -85,7 +96,7 @@ namespace DownKyi.Services.Download DownloadingDb downloadingDb = new DownloadingDb(); downloadingDb.Update(downloadingItem.DownloadBase.Uuid, downloadingItem.Downloading); - downloadingDb.Close(); + //downloadingDb.Close(); } #endregion @@ -108,7 +119,7 @@ namespace DownKyi.Services.Download { downloadedDb.Insert(downloadedItem.DownloadBase.Uuid, downloadedItem.Downloaded); } - downloadedDb.Close(); + //downloadedDb.Close(); } /// @@ -123,7 +134,7 @@ namespace DownKyi.Services.Download DownloadedDb downloadedDb = new DownloadedDb(); downloadedDb.Delete(downloadedItem.DownloadBase.Uuid); - downloadedDb.Close(); + //downloadedDb.Close(); } /// @@ -135,7 +146,7 @@ namespace DownKyi.Services.Download // 从数据库获取数据 DownloadedDb downloadedDb = new DownloadedDb(); Dictionary dic = downloadedDb.QueryAll(); - downloadedDb.Close(); + //downloadedDb.Close(); // 遍历 List list = new List(); @@ -143,13 +154,14 @@ namespace DownKyi.Services.Download { if (item.Value is Downloaded downloaded) { - DownloadedItem downloadingItem = new DownloadedItem + DownloadedItem downloadedItem = new DownloadedItem { DownloadBase = GetDownloadBase(item.Key), Downloaded = downloaded }; - list.Add(downloadingItem); + if (downloadedItem.DownloadBase == null) { continue; } + list.Add(downloadedItem); } } @@ -168,7 +180,7 @@ namespace DownKyi.Services.Download DownloadedDb downloadedDb = new DownloadedDb(); downloadedDb.Update(downloadedItem.DownloadBase.Uuid, downloadedItem.Downloaded); - downloadedDb.Close(); + //downloadedDb.Close(); } #endregion @@ -189,7 +201,7 @@ namespace DownKyi.Services.Download { downloadBaseDb.Insert(downloadBase.Uuid, downloadBase); } - downloadBaseDb.Close(); + //downloadBaseDb.Close(); } /// @@ -200,7 +212,7 @@ namespace DownKyi.Services.Download { DownloadBaseDb downloadBaseDb = new DownloadBaseDb(); downloadBaseDb.Delete(uuid); - downloadBaseDb.Close(); + //downloadBaseDb.Close(); } /// @@ -211,7 +223,7 @@ namespace DownKyi.Services.Download { DownloadBaseDb downloadBaseDb = new DownloadBaseDb(); object obj = downloadBaseDb.QueryById(uuid); - downloadBaseDb.Close(); + //downloadBaseDb.Close(); return obj is DownloadBase downloadBase ? downloadBase : null; } @@ -226,7 +238,7 @@ namespace DownKyi.Services.Download DownloadBaseDb downloadBaseDb = new DownloadBaseDb(); downloadBaseDb.Update(downloadBase.Uuid, downloadBase); - downloadBaseDb.Close(); + //downloadBaseDb.Close(); } #endregion diff --git a/DownKyi/Services/IInfoService.cs b/DownKyi/Services/IInfoService.cs index a882569..43bd09b 100644 --- a/DownKyi/Services/IInfoService.cs +++ b/DownKyi/Services/IInfoService.cs @@ -7,7 +7,7 @@ namespace DownKyi.Services { VideoInfoView GetVideoView(); - List GetVideoSections(); + List GetVideoSections(bool noUgc); List GetVideoPages(); diff --git a/DownKyi/Services/VideoInfoService.cs b/DownKyi/Services/VideoInfoService.cs index bcb3561..ed9738b 100644 --- a/DownKyi/Services/VideoInfoService.cs +++ b/DownKyi/Services/VideoInfoService.cs @@ -2,6 +2,7 @@ using DownKyi.Core.BiliApi.Video; using DownKyi.Core.BiliApi.Video.Models; using DownKyi.Core.BiliApi.VideoStream; +using DownKyi.Core.Settings; using DownKyi.Core.Storage; using DownKyi.Core.Utils; using DownKyi.ViewModels.PageViewModels; @@ -96,10 +97,12 @@ namespace DownKyi.Services }; } + // 文件命名中的时间格式 + string timeFormat = SettingsManager.GetInstance().GetFileNamePartTimeFormat(); // 视频发布时间 DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区 DateTime dateTime = startTime.AddSeconds(videoView.Pubdate); - videoPage.PublishTime = dateTime.ToString("yyyy-MM-dd"); + videoPage.PublishTime = dateTime.ToString(timeFormat); videoPages.Add(videoPage); } @@ -111,15 +114,30 @@ namespace DownKyi.Services /// 获取视频章节与剧集 /// /// - public List GetVideoSections() + public List GetVideoSections(bool noUgc = false) { if (videoView == null) { return null; } + + List videoSections = new List(); + + // 不需要ugc内容 + if (noUgc) + { + videoSections.Add(new VideoSection + { + Id = 0, + Title = "default", + IsSelected = true, + VideoPages = GetVideoPages() + }); + + return videoSections; + } + if (videoView.UgcSeason == null) { return null; } if (videoView.UgcSeason.Sections == null) { return null; } if (videoView.UgcSeason.Sections.Count == 0) { return null; } - List videoSections = new List(); - foreach (UgcSection section in videoView.UgcSeason.Sections) { List pages = new List(); @@ -151,10 +169,12 @@ namespace DownKyi.Services }; } + // 文件命名中的时间格式 + string timeFormat = SettingsManager.GetInstance().GetFileNamePartTimeFormat(); // 视频发布时间 DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区 DateTime dateTime = startTime.AddSeconds(videoView.Pubdate); - page.PublishTime = dateTime.ToString("yyyy-MM-dd"); + page.PublishTime = dateTime.ToString(timeFormat); // 这里的发布时间有问题, // 如果是合集,也会执行这里, // 但是发布时间是入口视频的,不是所有视频的 diff --git a/DownKyi/Utils/WindowAdaptation.cs b/DownKyi/Utils/WindowAdaptation.cs new file mode 100644 index 0000000..355be0d --- /dev/null +++ b/DownKyi/Utils/WindowAdaptation.cs @@ -0,0 +1,146 @@ +using System; +using System.Drawing; +using System.Windows; +using System.Windows.Forms; +using System.Windows.Interop; + +namespace DownKyi.Utils +{ + /// + /// 为窗口添加附加属性的辅助类 + /// + /// https://www.cnblogs.com/kybs0/p/9834023.html + /// + public class WindowAdaptation + { + #region 窗口宽度比例 + /// + /// 窗口宽度比例 单位:小数(0 - 1.0] + /// 窗口实际宽度=使用屏幕可显示区域(屏幕高度-任务栏高度)* 窗口宽度比例 + /// + public static readonly DependencyProperty WidthByScreenRatioProperty = DependencyProperty.RegisterAttached( + "WidthByScreenRatio", typeof(double), typeof(WindowAdaptation), new PropertyMetadata(1.0, OnWidthByScreenRatioPropertyChanged)); + + private static void OnWidthByScreenRatioPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is Window window && e.NewValue is double widthByScreenRatio) + { + if (widthByScreenRatio <= 0 || widthByScreenRatio > 1) + { + throw new ArgumentException($"屏幕比例不支持{widthByScreenRatio}"); + } + + var screenDisplayArea = GetScreenSize(window); + var screenRatioWidth = screenDisplayArea.Width * widthByScreenRatio; + + //if (!double.IsNaN(window.Width) && screenDisplayArea.Width > window.Width) + //{ + // window.Width = window.Width; + //} + //else + //{ + // window.Width = screenRatioWidth; + //} + + if (!double.IsNaN(window.Width) && screenRatioWidth > window.Width) + { + window.Width = window.Width; + } + else if (!double.IsNaN(window.MinWidth) && screenRatioWidth < window.MinWidth) + { + window.Width = screenDisplayArea.Width; + } + else + { + window.Width = screenRatioWidth; + } + } + } + + public static void SetWidthByScreenRatio(DependencyObject element, double value) + { + element.SetValue(WidthByScreenRatioProperty, value); + } + + public static double GetWidthByScreenRatio(DependencyObject element) + { + return (double)element.GetValue(WidthByScreenRatioProperty); + } + + #endregion + + #region 窗口高度比例 + /// + /// 窗口宽度比例 单位:小数(0 - 1.0] + /// 窗口实际宽度=使用屏幕可显示区域(屏幕高度-任务栏高度)* 窗口宽度比例 + /// + public static readonly DependencyProperty HeightByScreenRatioProperty = DependencyProperty.RegisterAttached( + "HeightByScreenRatio", typeof(double), typeof(WindowAdaptation), new PropertyMetadata(1.0, OnHeightByScreenRatioPropertyChanged)); + + private static void OnHeightByScreenRatioPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is Window window && e.NewValue is double heightByScreenRatio) + { + if (heightByScreenRatio <= 0 || heightByScreenRatio > 1) + { + throw new ArgumentException($"屏幕比例不支持{heightByScreenRatio}"); + } + + var screenDisplayArea = GetScreenSize(window); + var screenRatioHeight = screenDisplayArea.Height * heightByScreenRatio; + + if (!double.IsNaN(window.Height) && screenDisplayArea.Height > window.Height) + { + window.Height = window.Height; + } + else + { + window.Height = screenRatioHeight; + } + + //if (!double.IsNaN(window.Height) && screenRatioHeight > window.Height) + //{ + // window.Height = window.Height; + //} + //else if (!double.IsNaN(window.MinHeight) && screenRatioHeight < window.MinHeight) + //{ + // window.Height = screenDisplayArea.Height; + //} + //else + //{ + // window.Height = screenRatioHeight; + //} + } + } + + public static void SetHeightByScreenRatio(DependencyObject element, double value) + { + element.SetValue(HeightByScreenRatioProperty, value); + } + + public static double GetHeightByScreenRatio(DependencyObject element) + { + return (double)element.GetValue(HeightByScreenRatioProperty); + } + + #endregion + + const int DpiPercent = 96; + private static dynamic GetScreenSize(Window window) + { + var intPtr = new WindowInteropHelper(window).Handle;//获取当前窗口的句柄 + var screen = Screen.FromHandle(intPtr);//获取当前屏幕 + using (Graphics currentGraphics = Graphics.FromHwnd(intPtr)) + { + //分别获取当前屏幕X/Y方向的DPI + double dpiXRatio = currentGraphics.DpiX / DpiPercent; + double dpiYRatio = currentGraphics.DpiY / DpiPercent; + + var width = screen.WorkingArea.Width / dpiXRatio; + var height = screen.WorkingArea.Height / dpiYRatio; + + return new { Width = width, Height = height }; + } + } + } +} diff --git a/DownKyi/ViewModels/BaseViewModel.cs b/DownKyi/ViewModels/BaseViewModel.cs index 54d623f..89d5852 100644 --- a/DownKyi/ViewModels/BaseViewModel.cs +++ b/DownKyi/ViewModels/BaseViewModel.cs @@ -1,6 +1,7 @@ using Prism.Events; using Prism.Mvvm; using Prism.Regions; +using Prism.Services.Dialogs; using System; using System.Windows; @@ -9,6 +10,7 @@ namespace DownKyi.ViewModels public class BaseViewModel : BindableBase, INavigationAware { protected readonly IEventAggregator eventAggregator; + protected readonly IDialogService dialogService; protected string ParentView = string.Empty; public BaseViewModel(IEventAggregator eventAggregator) @@ -16,6 +18,12 @@ namespace DownKyi.ViewModels this.eventAggregator = eventAggregator; } + public BaseViewModel(IEventAggregator eventAggregator, IDialogService dialogService) + { + this.eventAggregator = eventAggregator; + this.dialogService = dialogService; + } + public bool IsNavigationTarget(NavigationContext navigationContext) { return true; diff --git a/DownKyi/ViewModels/Dialogs/BaseDialogViewModel.cs b/DownKyi/ViewModels/Dialogs/BaseDialogViewModel.cs index 2da4b97..287d65b 100644 --- a/DownKyi/ViewModels/Dialogs/BaseDialogViewModel.cs +++ b/DownKyi/ViewModels/Dialogs/BaseDialogViewModel.cs @@ -115,16 +115,16 @@ namespace DownKyi.ViewModels.Dialogs public event Action RequestClose; - public bool CanCloseDialog() + public virtual bool CanCloseDialog() { return true; } - public void OnDialogClosed() + public virtual void OnDialogClosed() { } - public void OnDialogOpened(IDialogParameters parameters) + public virtual void OnDialogOpened(IDialogParameters parameters) { } diff --git a/DownKyi/ViewModels/Dialogs/ViewAlertDialogViewModel.cs b/DownKyi/ViewModels/Dialogs/ViewAlertDialogViewModel.cs new file mode 100644 index 0000000..4a61093 --- /dev/null +++ b/DownKyi/ViewModels/Dialogs/ViewAlertDialogViewModel.cs @@ -0,0 +1,65 @@ +using DownKyi.Images; +using Prism.Commands; +using Prism.Services.Dialogs; + +namespace DownKyi.ViewModels.Dialogs +{ + public class ViewAlertDialogViewModel : BaseDialogViewModel + { + public const string Tag = "DialogAlert"; + + #region 页面属性申明 + + private VectorImage image; + public VectorImage Image + { + get => image; + set => SetProperty(ref image, value); + } + + private string message; + public string Message + { + get { return message; } + set { SetProperty(ref message, value); } + } + + #endregion + + public ViewAlertDialogViewModel() + { + + } + + #region 命令申明 + + // 确认事件 + private DelegateCommand allowCommand; + public DelegateCommand AllowCommand => allowCommand ?? (allowCommand = new DelegateCommand(ExecuteAllowCommand)); + + /// + /// 确认事件 + /// + private void ExecuteAllowCommand() + { + ButtonResult result = ButtonResult.OK; + RaiseRequestClose(new DialogResult(result)); + } + + #endregion + + #region 接口实现 + + public override void OnDialogOpened(IDialogParameters parameters) + { + base.OnDialogOpened(parameters); + + Image = parameters.GetValue("image"); + Title = parameters.GetValue("title"); + Message = parameters.GetValue("message"); + } + + #endregion + + } +} diff --git a/DownKyi/ViewModels/Dialogs/ViewDownloadSetterViewModel.cs b/DownKyi/ViewModels/Dialogs/ViewDownloadSetterViewModel.cs index c62b6aa..d806a42 100644 --- a/DownKyi/ViewModels/Dialogs/ViewDownloadSetterViewModel.cs +++ b/DownKyi/ViewModels/Dialogs/ViewDownloadSetterViewModel.cs @@ -1,4 +1,5 @@ using DownKyi.Core.Settings; +using DownKyi.Core.Settings.Models; using DownKyi.Core.Utils; using DownKyi.Events; using DownKyi.Images; @@ -136,14 +137,23 @@ namespace DownKyi.ViewModels.Dialogs FolderIcon = NormalIcon.Instance().Folder; FolderIcon.Fill = DictionaryResource.GetColor("ColorPrimary"); - DownloadAll = true; - DownloadAudio = true; - DownloadVideo = true; - DownloadDanmaku = true; - DownloadSubtitle = true; - DownloadCover = true; + // 下载内容 + VideoContentSettings videoContent = SettingsManager.GetInstance().GetVideoContent(); - #endregion + DownloadAudio = videoContent.DownloadAudio; + DownloadVideo = videoContent.DownloadVideo; + DownloadDanmaku = videoContent.DownloadDanmaku; + DownloadSubtitle = videoContent.DownloadSubtitle; + DownloadCover = videoContent.DownloadCover; + + if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) + { + DownloadAll = true; + } + else + { + DownloadAll = false; + } // 历史下载目录 DirectoryList = SettingsManager.GetInstance().GetHistoryVideoRootPaths(); @@ -156,6 +166,9 @@ namespace DownKyi.ViewModels.Dialogs // 是否使用默认下载目录 IsDefaultDownloadDirectory = SettingsManager.GetInstance().IsUseSaveVideoRootPath() == AllowStatus.YES; + + #endregion + } #region 命令申明 @@ -213,6 +226,8 @@ namespace DownKyi.ViewModels.Dialogs DownloadSubtitle = false; DownloadCover = false; } + + SetVideoContent(); } // 音频选择事件 @@ -227,13 +242,14 @@ namespace DownKyi.ViewModels.Dialogs if (!DownloadAudio) { DownloadAll = false; - return; } if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) { DownloadAll = true; } + + SetVideoContent(); } // 视频选择事件 @@ -248,13 +264,14 @@ namespace DownKyi.ViewModels.Dialogs if (!DownloadVideo) { DownloadAll = false; - return; } if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) { DownloadAll = true; } + + SetVideoContent(); } // 弹幕选择事件 @@ -269,13 +286,14 @@ namespace DownKyi.ViewModels.Dialogs if (!DownloadDanmaku) { DownloadAll = false; - return; } if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) { DownloadAll = true; } + + SetVideoContent(); } // 字幕选择事件 @@ -290,13 +308,14 @@ namespace DownKyi.ViewModels.Dialogs if (!DownloadSubtitle) { DownloadAll = false; - return; } if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) { DownloadAll = true; } + + SetVideoContent(); } // 封面选择事件 @@ -311,13 +330,14 @@ namespace DownKyi.ViewModels.Dialogs if (!DownloadCover) { DownloadAll = false; - return; } if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) { DownloadAll = true; } + + SetVideoContent(); } // 确认下载事件 @@ -370,6 +390,23 @@ namespace DownKyi.ViewModels.Dialogs #endregion + /// + /// 保存下载视频内容到设置 + /// + private void SetVideoContent() + { + VideoContentSettings videoContent = new VideoContentSettings + { + DownloadAudio = DownloadAudio, + DownloadVideo = DownloadVideo, + DownloadDanmaku = DownloadDanmaku, + DownloadSubtitle = DownloadSubtitle, + DownloadCover = DownloadCover + }; + + SettingsManager.GetInstance().SetVideoContent(videoContent); + } + /// /// 设置下载路径 /// diff --git a/DownKyi/ViewModels/DownloadManager/DownloadBaseItem.cs b/DownKyi/ViewModels/DownloadManager/DownloadBaseItem.cs index 4586b8a..d1f1b30 100644 --- a/DownKyi/ViewModels/DownloadManager/DownloadBaseItem.cs +++ b/DownKyi/ViewModels/DownloadManager/DownloadBaseItem.cs @@ -2,6 +2,7 @@ using DownKyi.Core.BiliApi.Zone; using DownKyi.Models; using Prism.Mvvm; +using Prism.Services.Dialogs; using System.Windows; using System.Windows.Media; @@ -9,6 +10,18 @@ namespace DownKyi.ViewModels.DownloadManager { public class DownloadBaseItem : BindableBase { + public IDialogService DialogService; + + public DownloadBaseItem() + { + DialogService = null; + } + + public DownloadBaseItem(IDialogService dialogService) + { + DialogService = dialogService; + } + // model数据 private DownloadBase downloadBase; public DownloadBase DownloadBase diff --git a/DownKyi/ViewModels/DownloadManager/DownloadedItem.cs b/DownKyi/ViewModels/DownloadManager/DownloadedItem.cs index 15fd55f..8bb6518 100644 --- a/DownKyi/ViewModels/DownloadManager/DownloadedItem.cs +++ b/DownKyi/ViewModels/DownloadManager/DownloadedItem.cs @@ -1,14 +1,20 @@ using DownKyi.Images; using DownKyi.Models; +using DownKyi.Services; using DownKyi.Utils; using Prism.Commands; +using Prism.Services.Dialogs; using System.IO; namespace DownKyi.ViewModels.DownloadManager { public class DownloadedItem : DownloadBaseItem { - public DownloadedItem() : base() + public DownloadedItem() : this(null) + { + } + + public DownloadedItem(IDialogService dialogService) : base(dialogService) { // 打开文件夹按钮 OpenFolder = ButtonIcon.Instance().Folder; @@ -131,6 +137,13 @@ namespace DownKyi.ViewModels.DownloadManager /// private void ExecuteRemoveVideoCommand() { + AlertService alertService = new AlertService(DialogService); + ButtonResult result = alertService.ShowWarning(DictionaryResource.GetString("ConfirmDelete")); + if (result != ButtonResult.OK) + { + return; + } + App.DownloadedList.Remove(this); } diff --git a/DownKyi/ViewModels/DownloadManager/DownloadingItem.cs b/DownKyi/ViewModels/DownloadManager/DownloadingItem.cs index dc51226..0f090eb 100644 --- a/DownKyi/ViewModels/DownloadManager/DownloadingItem.cs +++ b/DownKyi/ViewModels/DownloadManager/DownloadingItem.cs @@ -1,14 +1,20 @@ using DownKyi.Core.BiliApi.VideoStream.Models; using DownKyi.Images; using DownKyi.Models; +using DownKyi.Services; using DownKyi.Utils; using Prism.Commands; +using Prism.Services.Dialogs; namespace DownKyi.ViewModels.DownloadManager { public class DownloadingItem : DownloadBaseItem { - public DownloadingItem() : base() + public DownloadingItem() : this(null) + { + } + + public DownloadingItem(IDialogService dialogService) : base(dialogService) { // 暂停继续按钮 StartOrPause = ButtonIcon.Instance().Pause; @@ -211,6 +217,13 @@ namespace DownKyi.ViewModels.DownloadManager /// private void ExecuteDeleteCommand() { + AlertService alertService = new AlertService(DialogService); + ButtonResult result = alertService.ShowWarning(DictionaryResource.GetString("ConfirmDelete")); + if (result != ButtonResult.OK) + { + return; + } + App.DownloadingList.Remove(this); } diff --git a/DownKyi/ViewModels/DownloadManager/ViewDownloadFinishedViewModel.cs b/DownKyi/ViewModels/DownloadManager/ViewDownloadFinishedViewModel.cs index c4d94a1..9a081c3 100644 --- a/DownKyi/ViewModels/DownloadManager/ViewDownloadFinishedViewModel.cs +++ b/DownKyi/ViewModels/DownloadManager/ViewDownloadFinishedViewModel.cs @@ -1,9 +1,14 @@ using DownKyi.Core.Settings; +using DownKyi.Services; +using DownKyi.Utils; using Prism.Commands; using Prism.Events; +using Prism.Regions; +using Prism.Services.Dialogs; using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Collections.Specialized; using System.Linq; using System.Threading.Tasks; @@ -31,10 +36,27 @@ namespace DownKyi.ViewModels.DownloadManager #endregion - public ViewDownloadFinishedViewModel(IEventAggregator eventAggregator) : base(eventAggregator) + public ViewDownloadFinishedViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator, dialogService) { // 初始化DownloadedList DownloadedList = App.DownloadedList; + DownloadedList.CollectionChanged += new NotifyCollectionChangedEventHandler(async (object sender, NotifyCollectionChangedEventArgs e) => + { + await Task.Run(() => + { + if (e.Action == NotifyCollectionChangedAction.Add) + { + foreach (var item in DownloadedList) + { + if (item != null && item.DialogService == null) + { + item.DialogService = dialogService; + } + } + } + }); + }); + SetDialogService(); DownloadFinishedSort finishedSort = SettingsManager.GetInstance().GetDownloadFinishedSort(); switch (finishedSort) @@ -95,6 +117,13 @@ namespace DownKyi.ViewModels.DownloadManager /// private async void ExecuteClearAllDownloadedCommand() { + AlertService alertService = new AlertService(dialogService); + ButtonResult result = alertService.ShowWarning(DictionaryResource.GetString("ConfirmDelete")); + if (result != ButtonResult.OK) + { + return; + } + // 使用Clear()不能触发NotifyCollectionChangedAction.Remove事件 // 因此遍历删除 // DownloadingList中元素被删除后不能继续遍历 @@ -113,5 +142,26 @@ namespace DownKyi.ViewModels.DownloadManager #endregion + private async void SetDialogService() + { + await Task.Run(() => + { + foreach (var item in DownloadedList) + { + if (item != null && item.DialogService == null) + { + item.DialogService = dialogService; + } + } + }); + } + + public override void OnNavigatedFrom(NavigationContext navigationContext) + { + base.OnNavigatedFrom(navigationContext); + + SetDialogService(); + } + } } diff --git a/DownKyi/ViewModels/DownloadManager/ViewDownloadingViewModel.cs b/DownKyi/ViewModels/DownloadManager/ViewDownloadingViewModel.cs index a30c30b..aade091 100644 --- a/DownKyi/ViewModels/DownloadManager/ViewDownloadingViewModel.cs +++ b/DownKyi/ViewModels/DownloadManager/ViewDownloadingViewModel.cs @@ -1,11 +1,15 @@ using DownKyi.Images; using DownKyi.Models; +using DownKyi.Services; using DownKyi.Utils; using Prism.Commands; using Prism.Events; +using Prism.Regions; +using Prism.Services.Dialogs; using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Collections.Specialized; using System.Linq; using System.Threading.Tasks; @@ -26,10 +30,28 @@ namespace DownKyi.ViewModels.DownloadManager #endregion - public ViewDownloadingViewModel(IEventAggregator eventAggregator) : base(eventAggregator) + public ViewDownloadingViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator, dialogService) { // 初始化DownloadingList DownloadingList = App.DownloadingList; + DownloadingList.CollectionChanged += new NotifyCollectionChangedEventHandler(async (object sender, NotifyCollectionChangedEventArgs e) => + { + await Task.Run(() => + { + if (e.Action == NotifyCollectionChangedAction.Add) + { + foreach (var item in DownloadingList) + { + if (item != null && item.DialogService == null) + { + item.DialogService = dialogService; + } + } + } + }); + }); + SetDialogService(); + } #region 命令申明 @@ -133,6 +155,13 @@ namespace DownKyi.ViewModels.DownloadManager /// private async void ExecuteDeleteAllDownloadingCommand() { + AlertService alertService = new AlertService(dialogService); + ButtonResult result = alertService.ShowWarning(DictionaryResource.GetString("ConfirmDelete")); + if (result != ButtonResult.OK) + { + return; + } + // 使用Clear()不能触发NotifyCollectionChangedAction.Remove事件 // 因此遍历删除 // DownloadingList中元素被删除后不能继续遍历 @@ -151,5 +180,26 @@ namespace DownKyi.ViewModels.DownloadManager #endregion + private async void SetDialogService() + { + await Task.Run(() => + { + foreach (var item in DownloadingList) + { + if (item != null && item.DialogService == null) + { + item.DialogService = dialogService; + } + } + }); + } + + public override void OnNavigatedFrom(NavigationContext navigationContext) + { + base.OnNavigatedFrom(navigationContext); + + SetDialogService(); + } + } } diff --git a/DownKyi/ViewModels/MainWindowViewModel.cs b/DownKyi/ViewModels/MainWindowViewModel.cs index c806981..47714da 100644 --- a/DownKyi/ViewModels/MainWindowViewModel.cs +++ b/DownKyi/ViewModels/MainWindowViewModel.cs @@ -354,7 +354,7 @@ namespace DownKyi.ViewModels } SearchService searchService = new SearchService(); - searchService.BiliInput(input, ViewIndexViewModel.Tag, eventAggregator); + searchService.BiliInput(input + AppConstant.ClipboardId, ViewIndexViewModel.Tag, eventAggregator); } #endregion diff --git a/DownKyi/ViewModels/PageViewModels/VideoPage.cs b/DownKyi/ViewModels/PageViewModels/VideoPage.cs index b7660d0..f04787b 100644 --- a/DownKyi/ViewModels/PageViewModels/VideoPage.cs +++ b/DownKyi/ViewModels/PageViewModels/VideoPage.cs @@ -104,7 +104,7 @@ namespace DownKyi.ViewModels.PageViewModels LogManager.Error("ExecuteVideoQualitySelectedCommand", e); } - if (VideoQuality != null && VideoQuality.Quality == 126) + if (VideoQuality != null && VideoQuality.Quality == 126 && PlayUrl != null && PlayUrl.Dash != null && PlayUrl.Dash.Dolby != null) { ListHelper.AddUnique(AudioQualityFormatList, dolby); AudioQualityFormat = dolby; diff --git a/DownKyi/ViewModels/Settings/ViewBasicViewModel.cs b/DownKyi/ViewModels/Settings/ViewBasicViewModel.cs index 032e02e..eee40ca 100644 --- a/DownKyi/ViewModels/Settings/ViewBasicViewModel.cs +++ b/DownKyi/ViewModels/Settings/ViewBasicViewModel.cs @@ -67,6 +67,13 @@ namespace DownKyi.ViewModels.Settings set { SetProperty(ref selectedParseScope, value); } } + private bool autoDownloadAll; + public bool AutoDownloadAll + { + get => autoDownloadAll; + set => SetProperty(ref autoDownloadAll, value); + } + #endregion public ViewBasicViewModel(IEventAggregator eventAggregator) : base(eventAggregator) @@ -77,10 +84,10 @@ namespace DownKyi.ViewModels.Settings // 解析范围 ParseScopes = new List() { - 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} + 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 @@ -113,6 +120,10 @@ namespace DownKyi.ViewModels.Settings ParseScope parseScope = SettingsManager.GetInstance().GetParseScope(); SelectedParseScope = ParseScopes.FirstOrDefault(t => { return t.ParseScope == parseScope; }); + // 解析后是否自动下载解析视频 + AllowStatus isAutoDownloadAll = SettingsManager.GetInstance().IsAutoDownloadAll(); + AutoDownloadAll = isAutoDownloadAll == AllowStatus.YES; + isOnNavigatedTo = false; } @@ -193,6 +204,21 @@ namespace DownKyi.ViewModels.Settings PublishTip(isSucceed); } + // 解析后是否自动下载解析视频 + private DelegateCommand autoDownloadAllCommand; + public DelegateCommand AutoDownloadAllCommand => autoDownloadAllCommand ?? (autoDownloadAllCommand = new DelegateCommand(ExecuteAutoDownloadAllCommand)); + + /// + /// 解析后是否自动下载解析视频 + /// + private void ExecuteAutoDownloadAllCommand() + { + AllowStatus isAutoDownloadAll = AutoDownloadAll ? AllowStatus.YES : AllowStatus.NO; + + bool isSucceed = SettingsManager.GetInstance().IsAutoDownloadAll(isAutoDownloadAll); + PublishTip(isSucceed); + } + #endregion /// diff --git a/DownKyi/ViewModels/Settings/ViewDanmakuViewModel.cs b/DownKyi/ViewModels/Settings/ViewDanmakuViewModel.cs index c9fda5b..cdc557b 100644 --- a/DownKyi/ViewModels/Settings/ViewDanmakuViewModel.cs +++ b/DownKyi/ViewModels/Settings/ViewDanmakuViewModel.cs @@ -144,7 +144,7 @@ namespace DownKyi.ViewModels.Settings // 弹幕字体 string danmakuFont = SettingsManager.GetInstance().GetDanmakuFontName(); - if (Fonts.Contains(danmakuFont)) + if (danmakuFont != null && Fonts.Contains(danmakuFont)) { // 只有系统中存在当前设置的字体,才能显示 SelectedFont = danmakuFont; diff --git a/DownKyi/ViewModels/Settings/ViewVideoViewModel.cs b/DownKyi/ViewModels/Settings/ViewVideoViewModel.cs index 002d20f..a7ffd52 100644 --- a/DownKyi/ViewModels/Settings/ViewVideoViewModel.cs +++ b/DownKyi/ViewModels/Settings/ViewVideoViewModel.cs @@ -1,7 +1,9 @@ using DownKyi.Core.BiliApi.BiliUtils; using DownKyi.Core.FileName; using DownKyi.Core.Settings; +using DownKyi.Core.Settings.Models; using DownKyi.Events; +using DownKyi.Models; using DownKyi.Utils; using Prism.Commands; using Prism.Events; @@ -9,6 +11,7 @@ using Prism.Regions; using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Collections.Specialized; using System.Linq; namespace DownKyi.ViewModels.Settings @@ -84,6 +87,48 @@ namespace DownKyi.ViewModels.Settings set => SetProperty(ref saveVideoDirectory, value); } + private bool downloadAll; + public bool DownloadAll + { + get { return downloadAll; } + set { SetProperty(ref downloadAll, value); } + } + + private bool downloadAudio; + public bool DownloadAudio + { + get { return downloadAudio; } + set { SetProperty(ref downloadAudio, value); } + } + + private bool downloadVideo; + public bool DownloadVideo + { + get { return downloadVideo; } + set { SetProperty(ref downloadVideo, value); } + } + + private bool downloadDanmaku; + public bool DownloadDanmaku + { + get { return downloadDanmaku; } + set { SetProperty(ref downloadDanmaku, value); } + } + + private bool downloadSubtitle; + public bool DownloadSubtitle + { + get { return downloadSubtitle; } + set { SetProperty(ref downloadSubtitle, value); } + } + + private bool downloadCover; + public bool DownloadCover + { + get { return downloadCover; } + set { SetProperty(ref downloadCover, value); } + } + private ObservableCollection selectedFileName; public ObservableCollection SelectedFileName { @@ -105,8 +150,35 @@ namespace DownKyi.ViewModels.Settings set => SetProperty(ref selectedOptionalField, value); } - #endregion + private List fileNamePartTimeFormatList; + public List FileNamePartTimeFormatList + { + get => fileNamePartTimeFormatList; + set => SetProperty(ref fileNamePartTimeFormatList, value); + } + + private string selectedFileNamePartTimeFormat; + public string SelectedFileNamePartTimeFormat + { + get => selectedFileNamePartTimeFormat; + set => SetProperty(ref selectedFileNamePartTimeFormat, value); + } + + private List orderFormatList; + public List OrderFormatList + { + get => orderFormatList; + set => SetProperty(ref orderFormatList, value); + } + + private OrderFormatDisplay orderFormatDisplay; + public OrderFormatDisplay OrderFormatDisplay + { + get => orderFormatDisplay; + set => SetProperty(ref orderFormatDisplay, value); + } + #endregion public ViewVideoViewModel(IEventAggregator eventAggregator) : base(eventAggregator) { @@ -129,6 +201,20 @@ namespace DownKyi.ViewModels.Settings // 文件命名格式 SelectedFileName = new ObservableCollection(); + + SelectedFileName.CollectionChanged += new NotifyCollectionChangedEventHandler((sender, e) => + { + // 当前显示的命名格式part + List fileName = new List(); + foreach (DisplayFileNamePart item in SelectedFileName) + { + fileName.Add(item.Id); + } + + bool isSucceed = SettingsManager.GetInstance().SetFileNameParts(fileName); + PublishTip(isSucceed); + }); + OptionalFields = new ObservableCollection(); foreach (FileNamePart item in Enum.GetValues(typeof(FileNamePart))) { @@ -138,6 +224,20 @@ namespace DownKyi.ViewModels.Settings SelectedOptionalField = -1; + // 文件命名中的时间格式 + FileNamePartTimeFormatList = new List + { + "yyyy-MM-dd", + "yyyy.MM.dd", + }; + + // 文件命名中的序号格式 + OrderFormatList = new List + { + new OrderFormatDisplay{ Name = DictionaryResource.GetString("OrderFormatNatural"), OrderFormat = OrderFormat.NATURAL }, + new OrderFormatDisplay{ Name = DictionaryResource.GetString("OrderFormatLeadingZeros"), OrderFormat = OrderFormat.LEADING_ZEROS }, + }; + #endregion } @@ -175,6 +275,24 @@ namespace DownKyi.ViewModels.Settings // 默认下载目录 SaveVideoDirectory = SettingsManager.GetInstance().GetSaveVideoRootPath(); + // 下载内容 + VideoContentSettings videoContent = SettingsManager.GetInstance().GetVideoContent(); + + DownloadAudio = videoContent.DownloadAudio; + DownloadVideo = videoContent.DownloadVideo; + DownloadDanmaku = videoContent.DownloadDanmaku; + DownloadSubtitle = videoContent.DownloadSubtitle; + DownloadCover = videoContent.DownloadCover; + + if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) + { + DownloadAll = true; + } + else + { + DownloadAll = false; + } + // 文件命名格式 List fileNameParts = SettingsManager.GetInstance().GetFileNameParts(); SelectedFileName.Clear(); @@ -184,6 +302,13 @@ namespace DownKyi.ViewModels.Settings SelectedFileName.Add(new DisplayFileNamePart { Id = item, Title = display }); } + // 文件命名中的时间格式 + SelectedFileNamePartTimeFormat = SettingsManager.GetInstance().GetFileNamePartTimeFormat(); + + // 文件命名中的序号格式 + OrderFormat orderFormat = SettingsManager.GetInstance().GetOrderFormat(); + OrderFormatDisplay = OrderFormatList.FirstOrDefault(t => { return t.OrderFormat == orderFormat; }); + isOnNavigatedTo = false; } @@ -288,16 +413,157 @@ namespace DownKyi.ViewModels.Settings } } - // 选中文件名字段点击事件 - private DelegateCommand selectedFileNameCommand; - public DelegateCommand SelectedFileNameCommand => selectedFileNameCommand ?? (selectedFileNameCommand = new DelegateCommand(ExecuteSelectedFileNameCommand)); + // 所有内容选择事件 + private DelegateCommand downloadAllCommand; + public DelegateCommand DownloadAllCommand => downloadAllCommand ?? (downloadAllCommand = new DelegateCommand(ExecuteDownloadAllCommand)); + + /// + /// 所有内容选择事件 + /// + private void ExecuteDownloadAllCommand() + { + if (DownloadAll) + { + DownloadAudio = true; + DownloadVideo = true; + DownloadDanmaku = true; + DownloadSubtitle = true; + DownloadCover = true; + } + else + { + DownloadAudio = false; + DownloadVideo = false; + DownloadDanmaku = false; + DownloadSubtitle = false; + DownloadCover = false; + } + + SetVideoContent(); + } + + // 音频选择事件 + private DelegateCommand downloadAudioCommand; + public DelegateCommand DownloadAudioCommand => downloadAudioCommand ?? (downloadAudioCommand = new DelegateCommand(ExecuteDownloadAudioCommand)); + + /// + /// 音频选择事件 + /// + private void ExecuteDownloadAudioCommand() + { + if (!DownloadAudio) + { + DownloadAll = false; + } + + if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) + { + DownloadAll = true; + } + + SetVideoContent(); + } + + // 视频选择事件 + private DelegateCommand downloadVideoCommand; + public DelegateCommand DownloadVideoCommand => downloadVideoCommand ?? (downloadVideoCommand = new DelegateCommand(ExecuteDownloadVideoCommand)); + + /// + /// 视频选择事件 + /// + private void ExecuteDownloadVideoCommand() + { + if (!DownloadVideo) + { + DownloadAll = false; + } + + if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) + { + DownloadAll = true; + } + + SetVideoContent(); + } + + // 弹幕选择事件 + private DelegateCommand downloadDanmakuCommand; + public DelegateCommand DownloadDanmakuCommand => downloadDanmakuCommand ?? (downloadDanmakuCommand = new DelegateCommand(ExecuteDownloadDanmakuCommand)); + + /// + /// 弹幕选择事件 + /// + private void ExecuteDownloadDanmakuCommand() + { + if (!DownloadDanmaku) + { + DownloadAll = false; + } + + if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) + { + DownloadAll = true; + } + + SetVideoContent(); + } + + // 字幕选择事件 + private DelegateCommand downloadSubtitleCommand; + public DelegateCommand DownloadSubtitleCommand => downloadSubtitleCommand ?? (downloadSubtitleCommand = new DelegateCommand(ExecuteDownloadSubtitleCommand)); + + /// + /// 字幕选择事件 + /// + private void ExecuteDownloadSubtitleCommand() + { + if (!DownloadSubtitle) + { + DownloadAll = false; + } + + if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) + { + DownloadAll = true; + } + + SetVideoContent(); + } + + // 封面选择事件 + private DelegateCommand downloadCoverCommand; + public DelegateCommand DownloadCoverCommand => downloadCoverCommand ?? (downloadCoverCommand = new DelegateCommand(ExecuteDownloadCoverCommand)); + + /// + /// 封面选择事件 + /// + private void ExecuteDownloadCoverCommand() + { + if (!DownloadCover) + { + DownloadAll = false; + } + + if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) + { + DownloadAll = true; + } + + SetVideoContent(); + } + + // 选中文件名字段右键点击事件 + private DelegateCommand selectedFileNameRightCommand; + public DelegateCommand SelectedFileNameRightCommand => selectedFileNameRightCommand ?? (selectedFileNameRightCommand = new DelegateCommand(ExecuteSelectedFileNameRightCommand)); /// - /// 选中文件名字段点击事件 + /// 选中文件名字段右键点击事件 /// /// - private void ExecuteSelectedFileNameCommand(object parameter) + private void ExecuteSelectedFileNameRightCommand(object parameter) { + if (parameter == null) { return; } + bool isSucceed = SelectedFileName.Remove((DisplayFileNamePart)parameter); if (!isSucceed) { @@ -305,14 +571,16 @@ namespace DownKyi.ViewModels.Settings return; } - List fileName = new List(); - foreach (DisplayFileNamePart item in SelectedFileName) - { - fileName.Add(item.Id); - } + //List fileName = new List(); + //foreach (DisplayFileNamePart item in SelectedFileName) + //{ + // fileName.Add(item.Id); + //} - isSucceed = SettingsManager.GetInstance().SetFileNameParts(fileName); - PublishTip(isSucceed); + //isSucceed = SettingsManager.GetInstance().SetFileNameParts(fileName); + //PublishTip(isSucceed); + + SelectedOptionalField = -1; } // 可选文件名字段点击事件 @@ -363,8 +631,41 @@ namespace DownKyi.ViewModels.Settings string display = DisplayFileNamePart(item); SelectedFileName.Add(new DisplayFileNamePart { Id = item, Title = display }); } + + SelectedOptionalField = -1; + } + + // 文件命名中的时间格式事件 + private DelegateCommand fileNamePartTimeFormatCommand; + public DelegateCommand FileNamePartTimeFormatCommand => fileNamePartTimeFormatCommand ?? (fileNamePartTimeFormatCommand = new DelegateCommand(ExecuteFileNamePartTimeFormatCommand)); + + /// + /// 文件命名中的时间格式事件 + /// + /// + private void ExecuteFileNamePartTimeFormatCommand(object parameter) + { + if (!(parameter is string timeFormat)) { return; } + + bool isSucceed = SettingsManager.GetInstance().SetFileNamePartTimeFormat(timeFormat); + PublishTip(isSucceed); } + // 文件命名中的序号格式事件 + private DelegateCommand orderFormatCommand; + public DelegateCommand OrderFormatCommand => orderFormatCommand ?? (orderFormatCommand = new DelegateCommand(ExecuteOrderFormatCommandCommand)); + + /// + /// 文件命名中的序号格式事件 + /// + /// + private void ExecuteOrderFormatCommandCommand(object parameter) + { + if (!(parameter is OrderFormatDisplay orderFormatDisplay)) { return; } + + bool isSucceed = SettingsManager.GetInstance().SetOrderFormat(orderFormatDisplay.OrderFormat); + PublishTip(isSucceed); + } #endregion @@ -418,21 +719,21 @@ namespace DownKyi.ViewModels.Settings } /// - /// 发送需要显示的tip + /// 保存下载视频内容到设置 /// - /// - private void PublishTip(bool isSucceed) + private void SetVideoContent() { - if (isOnNavigatedTo) { return; } - - if (isSucceed) - { - eventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipSettingUpdated")); - } - else + VideoContentSettings videoContent = new VideoContentSettings { - eventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipSettingFailed")); - } + DownloadAudio = DownloadAudio, + DownloadVideo = DownloadVideo, + DownloadDanmaku = DownloadDanmaku, + DownloadSubtitle = DownloadSubtitle, + DownloadCover = DownloadCover + }; + + bool isSucceed = SettingsManager.GetInstance().SetVideoContent(videoContent); + PublishTip(isSucceed); } /// @@ -502,5 +803,23 @@ namespace DownKyi.ViewModels.Settings return display; } + /// + /// 发送需要显示的tip + /// + /// + private void PublishTip(bool isSucceed) + { + if (isOnNavigatedTo) { return; } + + if (isSucceed) + { + eventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipSettingUpdated")); + } + else + { + eventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipSettingFailed")); + } + } + } } diff --git a/DownKyi/ViewModels/Toolbox/ViewDelogoViewModel.cs b/DownKyi/ViewModels/Toolbox/ViewDelogoViewModel.cs index 000959e..ff4c6b4 100644 --- a/DownKyi/ViewModels/Toolbox/ViewDelogoViewModel.cs +++ b/DownKyi/ViewModels/Toolbox/ViewDelogoViewModel.cs @@ -68,10 +68,10 @@ namespace DownKyi.ViewModels.Toolbox VideoPath = string.Empty; - LogoWidth = -1; - LogoHeight = -1; - LogoX = -1; - LogoY = -1; + LogoWidth = 0; + LogoHeight = 0; + LogoX = 0; + LogoY = 0; #endregion } diff --git a/DownKyi/ViewModels/ViewIndexViewModel.cs b/DownKyi/ViewModels/ViewIndexViewModel.cs index ff0a93d..ee1fbc8 100644 --- a/DownKyi/ViewModels/ViewIndexViewModel.cs +++ b/DownKyi/ViewModels/ViewIndexViewModel.cs @@ -9,6 +9,7 @@ using DownKyi.Utils; using Prism.Commands; using Prism.Events; using Prism.Regions; +using Prism.Services.Dialogs; using System; using System.IO; using System.Threading.Tasks; @@ -88,7 +89,7 @@ namespace DownKyi.ViewModels #endregion - public ViewIndexViewModel(IEventAggregator eventAggregator) : base(eventAggregator) + public ViewIndexViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator, dialogService) { #region 属性初始化 @@ -207,7 +208,10 @@ namespace DownKyi.ViewModels /// private void EnterBili() { - if (InputText == null || InputText == string.Empty) { return; } + if (InputText == null || InputText == string.Empty) + { + return; + } LogManager.Debug(Tag, $"InputText: {InputText}"); @@ -227,65 +231,73 @@ namespace DownKyi.ViewModels /// private async void UpdateUserInfo() { - LoginPanelVisibility = Visibility.Hidden; - - // 检查本地是否存在login文件,没有则说明未登录 - if (!File.Exists(StorageManager.GetLogin())) + try { - LoginPanelVisibility = Visibility.Visible; - Header = new BitmapImage(new Uri("pack://application:,,,/Resources/default_header.jpg")); - UserName = null; - return; - } + LoginPanelVisibility = Visibility.Hidden; - await Task.Run(new Action(() => - { - // 获取用户信息 - var userInfo = UserInfo.GetUserInfoForNavigation(); - if (userInfo != null) + // 检查本地是否存在login文件,没有则说明未登录 + if (!File.Exists(StorageManager.GetLogin())) { - 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 - }); + LoginPanelVisibility = Visibility.Visible; + Header = new BitmapImage(new Uri("pack://application:,,,/Resources/default_header.jpg")); + UserName = null; + return; } - PropertyChangeAsync(new Action(() => + await Task.Run(new Action(() => { - LoginPanelVisibility = Visibility.Visible; - + // 获取用户信息 + var userInfo = UserInfo.GetUserInfoForNavigation(); if (userInfo != null) { - if (userInfo.Face != 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) { - Header = new StorageHeader().GetHeaderThumbnail(userInfo.Mid, userInfo.Name, userInfo.Face, 36, 36); + 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; } - UserName = userInfo.Name; - } - else - { - Header = new BitmapImage(new Uri("pack://application:,,,/Resources/default_header.jpg")); - UserName = null; - } + })); })); - })); + } + catch (Exception e) + { + Core.Utils.Debugging.Console.PrintLine("UpdateUserInfo()发生异常: {0}", e); + LogManager.Error(Tag, e); + } } #endregion diff --git a/DownKyi/ViewModels/ViewLoginViewModel.cs b/DownKyi/ViewModels/ViewLoginViewModel.cs index 6767e83..4b89904 100644 --- a/DownKyi/ViewModels/ViewLoginViewModel.cs +++ b/DownKyi/ViewModels/ViewLoginViewModel.cs @@ -98,26 +98,34 @@ namespace DownKyi.ViewModels /// private void Login() { - var loginUrl = LoginQR.GetLoginUrl(); - if (loginUrl == null) { return; } - - if (loginUrl.Status != true) + try { - ExecuteBackSpace(); - return; - } + var loginUrl = LoginQR.GetLoginUrl(); + if (loginUrl == null) { return; } - if (loginUrl.Data == null || loginUrl.Data.Url == null) - { - eventAggregator.GetEvent().Publish(DictionaryResource.GetString("GetLoginUrlFailed")); - return; - } + if (loginUrl.Status != true) + { + ExecuteBackSpace(); + return; + } - PropertyChangeAsync(new Action(() => { LoginQRCode = LoginQR.GetLoginQRCode(loginUrl.Data.Url); })); - Core.Utils.Debugging.Console.PrintLine(loginUrl.Data.Url + "\n"); - LogManager.Debug(Tag, loginUrl.Data.Url); + if (loginUrl.Data == null || loginUrl.Data.Url == null) + { + eventAggregator.GetEvent().Publish(DictionaryResource.GetString("GetLoginUrlFailed")); + return; + } + + PropertyChangeAsync(new Action(() => { LoginQRCode = LoginQR.GetLoginQRCode(loginUrl.Data.Url); })); + Core.Utils.Debugging.Console.PrintLine(loginUrl.Data.Url + "\n"); + LogManager.Debug(Tag, loginUrl.Data.Url); - GetLoginStatus(loginUrl.Data.OauthKey); + GetLoginStatus(loginUrl.Data.OauthKey); + } + catch (Exception e) + { + Core.Utils.Debugging.Console.PrintLine("Login()发生异常: {0}", e); + LogManager.Error(Tag, e); + } } /// diff --git a/DownKyi/ViewModels/ViewVideoDetailViewModel.cs b/DownKyi/ViewModels/ViewVideoDetailViewModel.cs index 10b69c8..088a7ae 100644 --- a/DownKyi/ViewModels/ViewVideoDetailViewModel.cs +++ b/DownKyi/ViewModels/ViewVideoDetailViewModel.cs @@ -27,10 +27,8 @@ namespace DownKyi.ViewModels { public const string Tag = "PageVideoDetail"; - private readonly IDialogService dialogService; - // 保存输入字符串,避免被用户修改 - private string input; + private string input = null; #region 页面属性申明 @@ -106,10 +104,8 @@ namespace DownKyi.ViewModels #endregion - public ViewVideoDetailViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator) + public ViewVideoDetailViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator, dialogService) { - this.dialogService = dialogService; - #region 属性初始化 // 初始化loading gif @@ -480,6 +476,13 @@ namespace DownKyi.ViewModels } LoadingVisibility = Visibility.Collapsed; + + // 解析后是否自动下载解析视频 + AllowStatus isAutoDownloadAll = SettingsManager.GetInstance().IsAutoDownloadAll(); + if (parseScope != ParseScope.NONE && isAutoDownloadAll == AllowStatus.YES) + { + AddToDownload(true); + } } /// @@ -498,56 +501,57 @@ namespace DownKyi.ViewModels /// /// 添加到下载列表事件 /// - private async void ExecuteAddToDownloadCommand() - { - AddToDownloadService addToDownloadService = null; - // 视频 - if (ParseEntrance.IsAvUrl(input) || ParseEntrance.IsBvUrl(input)) - { - addToDownloadService = new AddToDownloadService(PlayStreamType.VIDEO); - } - // 番剧(电影、电视剧) - else if (ParseEntrance.IsBangumiSeasonUrl(input) || ParseEntrance.IsBangumiEpisodeUrl(input) || ParseEntrance.IsBangumiMediaUrl(input)) - { - addToDownloadService = new AddToDownloadService(PlayStreamType.BANGUMI); - } - // 课程 - else if (ParseEntrance.IsCheeseSeasonUrl(input) || ParseEntrance.IsCheeseEpisodeUrl(input)) - { - addToDownloadService = new AddToDownloadService(PlayStreamType.CHEESE); - } - else - { - return; - } - - // 选择文件夹 - string directory = addToDownloadService.SetDirectory(dialogService); - - // 视频计数 - int i = 0; - await Task.Run(() => - { - // 传递video对象 - addToDownloadService.GetVideo(VideoInfoView, VideoSections.ToList()); - // 下载 - i = addToDownloadService.AddToDownload(eventAggregator, directory); - }); - - if (directory == null) - { - return; - } - - // 通知用户添加到下载列表的结果 - if (i <= 0) - { - eventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipAddDownloadingZero")); - } - else - { - eventAggregator.GetEvent().Publish($"{DictionaryResource.GetString("TipAddDownloadingFinished1")}{i}{DictionaryResource.GetString("TipAddDownloadingFinished2")}"); - } + private void ExecuteAddToDownloadCommand() + { + AddToDownload(false); + //AddToDownloadService addToDownloadService = null; + //// 视频 + //if (ParseEntrance.IsAvUrl(input) || ParseEntrance.IsBvUrl(input)) + //{ + // addToDownloadService = new AddToDownloadService(PlayStreamType.VIDEO); + //} + //// 番剧(电影、电视剧) + //else if (ParseEntrance.IsBangumiSeasonUrl(input) || ParseEntrance.IsBangumiEpisodeUrl(input) || ParseEntrance.IsBangumiMediaUrl(input)) + //{ + // addToDownloadService = new AddToDownloadService(PlayStreamType.BANGUMI); + //} + //// 课程 + //else if (ParseEntrance.IsCheeseSeasonUrl(input) || ParseEntrance.IsCheeseEpisodeUrl(input)) + //{ + // addToDownloadService = new AddToDownloadService(PlayStreamType.CHEESE); + //} + //else + //{ + // return; + //} + + //// 选择文件夹 + //string directory = addToDownloadService.SetDirectory(dialogService); + + //// 视频计数 + //int i = 0; + //await Task.Run(() => + //{ + // // 传递video对象 + // addToDownloadService.GetVideo(VideoInfoView, VideoSections.ToList()); + // // 下载 + // i = addToDownloadService.AddToDownload(eventAggregator, directory); + //}); + + //if (directory == null) + //{ + // return; + //} + + //// 通知用户添加到下载列表的结果 + //if (i <= 0) + //{ + // eventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipAddDownloadingZero")); + //} + //else + //{ + // eventAggregator.GetEvent().Publish($"{DictionaryResource.GetString("TipAddDownloadingFinished1")}{i}{DictionaryResource.GetString("TipAddDownloadingFinished2")}"); + //} } /// @@ -610,6 +614,7 @@ namespace DownKyi.ViewModels /// private void UpdateView(IInfoService videoInfoService, VideoPage param) { + // 获取视频详情 VideoInfoView = videoInfoService.GetVideoView(); if (VideoInfoView == null) { @@ -627,7 +632,16 @@ namespace DownKyi.ViewModels NoDataVisibility = Visibility.Collapsed; } - List videoSections = videoInfoService.GetVideoSections(); + // 获取视频列表 + List videoSections = videoInfoService.GetVideoSections(false); + + // 清空以前的数据 + PropertyChangeAsync(new Action(() => + { + VideoSections.Clear(); + })); + + // 添加新数据 if (videoSections == null) { LogManager.Debug(Tag, "videoSections is not exist."); @@ -663,6 +677,62 @@ namespace DownKyi.ViewModels videoInfoService.GetVideoStream(videoPage); } + /// + /// 添加到下载列表事件 + /// + /// 是否下载所有,包括未选中项 + private async void AddToDownload(bool isAll) + { + AddToDownloadService addToDownloadService = null; + // 视频 + if (ParseEntrance.IsAvUrl(input) || ParseEntrance.IsBvUrl(input)) + { + addToDownloadService = new AddToDownloadService(PlayStreamType.VIDEO); + } + // 番剧(电影、电视剧) + else if (ParseEntrance.IsBangumiSeasonUrl(input) || ParseEntrance.IsBangumiEpisodeUrl(input) || ParseEntrance.IsBangumiMediaUrl(input)) + { + addToDownloadService = new AddToDownloadService(PlayStreamType.BANGUMI); + } + // 课程 + else if (ParseEntrance.IsCheeseSeasonUrl(input) || ParseEntrance.IsCheeseEpisodeUrl(input)) + { + addToDownloadService = new AddToDownloadService(PlayStreamType.CHEESE); + } + else + { + return; + } + + // 选择文件夹 + string directory = addToDownloadService.SetDirectory(dialogService); + + // 视频计数 + int i = 0; + await Task.Run(() => + { + // 传递video对象 + addToDownloadService.GetVideo(VideoInfoView, VideoSections.ToList()); + // 下载 + i = addToDownloadService.AddToDownload(eventAggregator, directory, isAll); + }); + + if (directory == null) + { + return; + } + + // 通知用户添加到下载列表的结果 + if (i <= 0) + { + eventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipAddDownloadingZero")); + } + else + { + eventAggregator.GetEvent().Publish($"{DictionaryResource.GetString("TipAddDownloadingFinished1")}{i}{DictionaryResource.GetString("TipAddDownloadingFinished2")}"); + } + } + #endregion /// @@ -671,8 +741,6 @@ namespace DownKyi.ViewModels /// public override void OnNavigatedTo(NavigationContext navigationContext) { - base.OnNavigatedTo(navigationContext); - ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); DownloadManage = ButtonIcon.Instance().DownloadManage; @@ -683,13 +751,25 @@ namespace DownKyi.ViewModels // Parent参数为null时,表示是从下一个页面返回到本页面,不需要执行任务 if (navigationContext.Parameters.GetValue("Parent") != null) { + string param = navigationContext.Parameters.GetValue("Parameter"); + // 移除剪贴板id + string intput = param.Replace(AppConstant.ClipboardId, ""); + + // 检测是否从剪贴板传入 + if (InputText == intput && param.EndsWith(AppConstant.ClipboardId)) + { + return; + } + // 正在执行任务时不开启新任务 if (LoadingVisibility != Visibility.Visible) { - InputText = navigationContext.Parameters.GetValue("Parameter"); + InputText = intput; PropertyChangeAsync(ExecuteInputCommand); } } + + base.OnNavigatedTo(navigationContext); } } diff --git a/DownKyi/Views/Dialogs/ViewAlertDialog.xaml b/DownKyi/Views/Dialogs/ViewAlertDialog.xaml new file mode 100644 index 0000000..16de4ef --- /dev/null +++ b/DownKyi/Views/Dialogs/ViewAlertDialog.xaml @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +