Compare commits
14 Commits
3c35a8acaa
...
0.3.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9edccede4e | ||
|
|
1d7359ebdd | ||
|
|
fafff1bc5c | ||
|
|
be599991b8 | ||
|
|
48954e5206 | ||
|
|
a7c22adc05 | ||
|
|
be643a9935 | ||
|
|
64f3958d7f | ||
|
|
b562d5b5ba | ||
|
|
bf54d5a531 | ||
|
|
f9f4db3f6c | ||
|
|
880a834296 | ||
|
|
e47813765a | ||
|
|
2f0d1dc27f |
3
.gitignore
vendored
@@ -248,4 +248,5 @@ ModelManifest.xml
|
||||
[Oo]thers/
|
||||
|
||||
# Arm Build Files
|
||||
package.zip
|
||||
package.zip
|
||||
ArmPackage.zip
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.37012.4
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pkgread", "pkgread\pkgread.vcxproj", "{A7753282-AA16-43D9-8ACA-7065239DD702}"
|
||||
EndProject
|
||||
@@ -77,197 +77,281 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reader", "Reader\Reader.csp
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pugixml", "pugixml\pugixml.vcxproj", "{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PkgCLI", "PkgCLI\PkgCLI.csproj", "{8D333AF6-E901-4301-B3EE-923088E81062}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x86.Build.0 = Debug|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|ARM.Build.0 = Release|ARM
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.Build.0 = Release|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x86.Build.0 = Debug|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|ARM.Build.0 = Release|ARM
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|x86.ActiveCfg = Release|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|x86.Build.0 = Release|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|x86.Build.0 = Debug|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Release|ARM.Build.0 = Release|ARM
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Release|x86.ActiveCfg = Release|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Release|x86.Build.0 = Release|Win32
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|x86.Build.0 = Debug|Win32
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|ARM.Build.0 = Release|ARM
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|x86.Build.0 = Release|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|x86.Build.0 = Debug|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|ARM.Build.0 = Release|ARM
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|x86.Build.0 = Release|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|x86.Build.0 = Debug|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|ARM.Build.0 = Release|ARM
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|x86.ActiveCfg = Release|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|x86.Build.0 = Release|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|x86.Build.0 = Debug|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|ARM.Build.0 = Release|ARM
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|x86.ActiveCfg = Release|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|x86.Build.0 = Release|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|x86.Build.0 = Debug|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|ARM.Build.0 = Release|ARM
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|x86.ActiveCfg = Release|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|x86.Build.0 = Release|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|x86.Build.0 = Debug|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|ARM.Build.0 = Release|ARM
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|x86.ActiveCfg = Release|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|x86.Build.0 = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.Build.0 = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|ARM.Build.0 = Release|ARM
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.ActiveCfg = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.Build.0 = Release|Win32
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|x86.Build.0 = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|x86.Build.0 = Debug|x86
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|x86.ActiveCfg = Release|x86
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|x86.Build.0 = Release|x86
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Debug|x86.Build.0 = Debug|Win32
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Release|ARM.Build.0 = Release|ARM
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Release|x86.Build.0 = Release|Win32
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Release|x86.Build.0 = Release|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|x86.Build.0 = Debug|x86
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|x86.Build.0 = Release|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|x86.ActiveCfg = Release|x86
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|x86.Build.0 = Release|x86
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Release|ARM.Build.0 = Release|ARM
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Release|x86.Build.0 = Release|Win32
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Debug|x86.Build.0 = Debug|x86
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Release|x86.ActiveCfg = Release|x86
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
@@ -70,6 +74,7 @@
|
||||
<Compile Include="PriFileNative.cs" />
|
||||
<Compile Include="PriReader.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Utils.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DataUtils\DataUtils.csproj">
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace NativeWrappers
|
||||
using UINT64 = System.UInt64;
|
||||
using HRESULT = System.Int32;
|
||||
using ULONG = System.UInt32;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public static class PackageReadHelper
|
||||
{
|
||||
@@ -304,6 +306,7 @@ namespace NativeWrappers
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// ================= Manifest Reader =================
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
@@ -404,5 +407,160 @@ namespace NativeWrappers
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetManifestPrerequistieSystemVersionName (IntPtr hReader, string lpName);
|
||||
|
||||
// ========== Appx Bundle Resource Packages ==========
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
private static extern IntPtr GetAppxBundleAllResourcePackageFileNames (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
private static extern void FreeAppxBundlePayloadsFileNameList (IntPtr hStringList);
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Bundle 包中所有资源包的文件名列表。
|
||||
/// </summary>
|
||||
/// <param name="hReader">由 CreatePackageReader 创建的读取器句柄</param>
|
||||
/// <returns>资源包文件名数组,若无资源包或非 bundle 类型则返回空数组</returns>
|
||||
public static string [] GetAppxBundleAllResourcePackageFileNameList (IntPtr hReader)
|
||||
{
|
||||
IntPtr hList = GetAppxBundleAllResourcePackageFileNames (hReader);
|
||||
if (hList == IntPtr.Zero)
|
||||
return new string [0];
|
||||
|
||||
try
|
||||
{
|
||||
return ReadWStringList (hList);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FreeAppxBundlePayloadsFileNameList (hList);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
private static extern IntPtr GetAppxBundleAllLocaleResourcePackageFileNames (IntPtr hReader);
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Bundle 包中所有区域设置资源包的文件名列表。
|
||||
/// </summary>
|
||||
/// <param name="hReader">由 CreatePackageReader 创建的读取器句柄</param>
|
||||
/// <returns>区域设置资源包文件名数组,若无则返回空数组</returns>
|
||||
public static string [] GetAppxBundleAllLocaleResourcePackageFileNameList (IntPtr hReader)
|
||||
{
|
||||
IntPtr hList = GetAppxBundleAllLocaleResourcePackageFileNames (hReader);
|
||||
if (hList == IntPtr.Zero)
|
||||
return new string [0];
|
||||
|
||||
try
|
||||
{
|
||||
return ReadWStringList (hList);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FreeAppxBundlePayloadsFileNameList (hList);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
private static extern IntPtr GetAppxBundleAllFileResourcePackageFileNames (IntPtr hReader);
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Bundle 包中所有文件资源包的文件名列表。
|
||||
/// </summary>
|
||||
/// <param name="hReader">由 CreatePackageReader 创建的读取器句柄</param>
|
||||
/// <returns>文件资源包文件名数组,若无则返回空数组</returns>
|
||||
public static string [] GetAppxBundleAllFileResourcePackageFileNameList (IntPtr hReader)
|
||||
{
|
||||
IntPtr hList = GetAppxBundleAllFileResourcePackageFileNames (hReader);
|
||||
if (hList == IntPtr.Zero)
|
||||
return new string [0];
|
||||
|
||||
try
|
||||
{
|
||||
return ReadWStringList (hList);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FreeAppxBundlePayloadsFileNameList (hList);
|
||||
}
|
||||
}
|
||||
|
||||
// 用于更新应用项名称列表(设置要查询的项)
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void UpdatePackageApplicationItemGetName (
|
||||
[In] IntPtr [] lpNames, // 传入一个 IntPtr 数组,每个元素指向一个 Unicode 字符串
|
||||
uint dwArrLen
|
||||
);
|
||||
|
||||
// 回调委托声明
|
||||
[UnmanagedFunctionPointer (CallConv)]
|
||||
public delegate void IterWStringCallback ([MarshalAs (UnmanagedType.LPWStr)] string lpString);
|
||||
|
||||
// 枚举当前列表中的项(通过回调逐个返回)
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void GetPackageApplicationItemGetNameList (
|
||||
IterWStringCallback pfCallback // 回调函数指针
|
||||
);
|
||||
/// <summary>
|
||||
/// 更新内部的应用项名称列表(设置要查询的项)
|
||||
/// </summary>
|
||||
/// <param name="names">要设置的项名称集合</param>
|
||||
public static void SetApplicationItemNames (IEnumerable<string> names)
|
||||
{
|
||||
if (names == null)
|
||||
{
|
||||
// 传入空数组,清空列表
|
||||
UpdatePackageApplicationItemGetName (new IntPtr [0], 0);
|
||||
return;
|
||||
}
|
||||
|
||||
var nameList = names.ToList ();
|
||||
if (nameList.Count == 0)
|
||||
{
|
||||
UpdatePackageApplicationItemGetName (new IntPtr [0], 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// 为每个字符串分配非托管内存
|
||||
IntPtr [] ptrs = new IntPtr [nameList.Count];
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < nameList.Count; i++)
|
||||
{
|
||||
ptrs [i] = Marshal.StringToHGlobalUni (nameList [i]);
|
||||
}
|
||||
|
||||
UpdatePackageApplicationItemGetName (ptrs, (uint)nameList.Count);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 释放分配的内存
|
||||
foreach (var ptr in ptrs)
|
||||
{
|
||||
if (ptr != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal (ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取当前内部的应用项名称列表(通过回调收集所有项)
|
||||
/// </summary>
|
||||
/// <returns>应用项名称数组</returns>
|
||||
public static string [] GetApplicationItemNames ()
|
||||
{
|
||||
var result = new List<string> ();
|
||||
|
||||
// 定义回调:将收到的字符串添加到列表
|
||||
IterWStringCallback callback = (str) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty (str))
|
||||
result.Add (str);
|
||||
};
|
||||
|
||||
// 调用本机函数,传入委托
|
||||
GetPackageApplicationItemGetNameList (callback);
|
||||
|
||||
// 注意:GC 需要保持 callback 的存活直到本机调用结束,这里通过局部变量引用即可,
|
||||
// 因为本机函数是同步调用的,不会在函数返回后继续使用回调。
|
||||
return result.ToArray ();
|
||||
}
|
||||
}
|
||||
}
|
||||
67
AppxPackage/Utils.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
internal static class Utils
|
||||
{
|
||||
public static string PascalToCamel (string pascalCase)
|
||||
{
|
||||
if (string.IsNullOrEmpty (pascalCase))
|
||||
return pascalCase;
|
||||
|
||||
// 已经是小驼峰或首字母小写,直接返回
|
||||
if (char.IsLower (pascalCase [0]))
|
||||
return pascalCase;
|
||||
|
||||
// 按大写字母边界拆分单词(处理连续大写字母作为一个单词)
|
||||
// 正则解释:
|
||||
// (?<=[a-z])(?=[A-Z]) 小写后跟大写 -> 分割
|
||||
// | 或
|
||||
// (?<=[A-Z])(?=[A-Z][a-z]) 大写后跟大写+小写(如 XMLR 中的 X 和 MLR)-> 分割
|
||||
string [] words = Regex.Split (pascalCase, @"(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])");
|
||||
|
||||
StringBuilder result = new StringBuilder ();
|
||||
|
||||
for (int i = 0; i < words.Length; i++)
|
||||
{
|
||||
string word = words [i];
|
||||
if (string.IsNullOrEmpty (word))
|
||||
continue;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
// 第一个单词:全部转为小写
|
||||
result.Append (word.ToLowerInvariant ());
|
||||
}
|
||||
else
|
||||
{
|
||||
// 后续单词:首字母大写,其余小写
|
||||
result.Append (char.ToUpperInvariant (word [0]));
|
||||
if (word.Length > 1)
|
||||
result.Append (word.Substring (1).ToLowerInvariant ());
|
||||
}
|
||||
}
|
||||
|
||||
return result.ToString ();
|
||||
}
|
||||
/// <summary>
|
||||
/// 表示应用清单中用于定义文件/资源路径的属性名称
|
||||
/// </summary>
|
||||
public static readonly List<string> AppFileProperties = new List<string>
|
||||
{
|
||||
"Executable",
|
||||
"LockScreenLogo",
|
||||
"Logo",
|
||||
"SmallLogo",
|
||||
"Square150x150Logo",
|
||||
"Square30x30Logo",
|
||||
"Square310x310Logo",
|
||||
"Square44x44Logo",
|
||||
"Square70x70Logo",
|
||||
"Square71x71Logo",
|
||||
"StartPage",
|
||||
"Tall150x310Logo",
|
||||
"WideLogo",
|
||||
"Wide310x150Logo"
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net40" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
|
||||
</packages>
|
||||
41
ArmBuild.ps1
@@ -1,41 +1,51 @@
|
||||
# ArmBuild.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$root = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$staging = Join-Path $root "_staging"
|
||||
$outZip = Join-Path $root "package.zip"
|
||||
$outZip = Join-Path $root "ArmPackage.zip"
|
||||
$packageFolderName = "Desktop App Installer"
|
||||
$destRoot = Join-Path $staging $packageFolderName
|
||||
|
||||
function Copy-Binaries-ToRoot($src)
|
||||
function Copy-Binaries-ToDest($src, $dest)
|
||||
{
|
||||
if (!(Test-Path $src)) { return }
|
||||
|
||||
Get-ChildItem $src -File | Where-Object {
|
||||
$_.Extension -in ".exe", ".dll"
|
||||
} | ForEach-Object {
|
||||
Copy-Item $_.FullName $staging -Force
|
||||
Copy-Item -Path $_.FullName -Destination $dest -Force
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Preparing staging..."
|
||||
Remove-Item $staging -Recurse -Force -ErrorAction Ignore
|
||||
New-Item $staging -ItemType Directory | Out-Null
|
||||
# 清理旧的 staging
|
||||
if (Test-Path $staging) { Remove-Item $staging -Recurse -Force }
|
||||
New-Item $destRoot -ItemType Directory | Out-Null
|
||||
|
||||
# ① 先放 Release
|
||||
Copy-Binaries-ToRoot (Join-Path $root "Release")
|
||||
Copy-Binaries-ToDest (Join-Path $root "Release") $destRoot
|
||||
|
||||
# ② 再放 ARM\Release(覆盖同名)
|
||||
Copy-Binaries-ToRoot (Join-Path $root "ARM\Release")
|
||||
Copy-Binaries-ToDest (Join-Path $root "ARM\Release") $destRoot
|
||||
|
||||
# ③ shared 全部铺到根目录
|
||||
# ③ shared 全部铺到 Desktop App Installer 里
|
||||
$shared = Join-Path $root "shared"
|
||||
if (Test-Path $shared) {
|
||||
Get-ChildItem $shared -Recurse | ForEach-Object {
|
||||
$rel = $_.FullName.Substring($shared.Length).TrimStart('\')
|
||||
$dest = Join-Path $staging $rel
|
||||
$relativePath = $_.FullName.Substring($shared.Length).TrimStart('\')
|
||||
$destinationPath = Join-Path $destRoot $relativePath
|
||||
|
||||
if ($_.PSIsContainer) {
|
||||
New-Item $dest -ItemType Directory -Force | Out-Null
|
||||
if (!(Test-Path $destinationPath)) {
|
||||
New-Item -Path $destinationPath -ItemType Directory | Out-Null
|
||||
}
|
||||
} else {
|
||||
Copy-Item $_.FullName $dest -Force
|
||||
$parentDir = Split-Path $destinationPath -Parent
|
||||
if (!(Test-Path $parentDir)) {
|
||||
New-Item -Path $parentDir -ItemType Directory | Out-Null
|
||||
}
|
||||
Copy-Item -Path $_.FullName -Destination $destinationPath -Force
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,11 +53,10 @@ if (Test-Path $shared) {
|
||||
Write-Host "Creating ZIP..."
|
||||
if (Test-Path $outZip) { Remove-Item $outZip -Force }
|
||||
|
||||
Compress-Archive `
|
||||
-Path (Join-Path $staging "*") `
|
||||
-DestinationPath $outZip `
|
||||
-CompressionLevel Fastest
|
||||
# 压缩 _staging 下的 Desktop App Installer 文件夹
|
||||
Compress-Archive -Path $destRoot -DestinationPath $outZip -CompressionLevel Optimal
|
||||
|
||||
# 清理 staging
|
||||
Remove-Item $staging -Recurse -Force
|
||||
|
||||
Write-Host "Done: $outZip"
|
||||
@@ -11,6 +11,8 @@ using ModernNotice;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bridge
|
||||
{
|
||||
@@ -762,6 +764,44 @@ namespace Bridge
|
||||
}
|
||||
public bool AddApplicationItem (string itemName) => PackageReader.AddApplicationItem (itemName);
|
||||
public bool RemoveApplicationItem (string itemName) => PackageReader.RemoveApplicationItem (itemName);
|
||||
private List<object> JsArrayToList (object jsArray)
|
||||
{
|
||||
var result = new List<object> ();
|
||||
|
||||
if (jsArray == null)
|
||||
return result;
|
||||
|
||||
// JS Array 有 length 属性和数字索引器
|
||||
var type = jsArray.GetType ();
|
||||
|
||||
int length = (int)type.InvokeMember (
|
||||
"length",
|
||||
BindingFlags.GetProperty,
|
||||
null,
|
||||
jsArray,
|
||||
null);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
object value = type.InvokeMember (
|
||||
i.ToString (),
|
||||
BindingFlags.GetProperty,
|
||||
null,
|
||||
jsArray,
|
||||
null);
|
||||
|
||||
result.Add (value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
public void UpdateApplicationItems (object items)
|
||||
{
|
||||
var stritems = JsArrayToList (items).Select (e => e?.ToString ()).ToList ();
|
||||
PackageReader.UpdateApplicationItems (stritems);
|
||||
}
|
||||
public string [] GetApplicationItems () => PackageReader.GetApplicationItems ();
|
||||
public string GetApplicationItemsToJson () => JsonConvert.SerializeObject (GetApplicationItems ());
|
||||
// Cache about
|
||||
private const int MaxCacheItems = 64; // 最大缓存数量
|
||||
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes (30);
|
||||
@@ -895,6 +935,8 @@ namespace Bridge
|
||||
public _I_System System => system;
|
||||
public _I_Notice Notice => new _I_Notice ();
|
||||
public _I_Process Process => proc;
|
||||
public _I_Web Web => new _I_Web ();
|
||||
public _I_Utilities Utilities => new _I_Utilities ();
|
||||
public string CmdArgs
|
||||
{
|
||||
get
|
||||
|
||||
816
DataUtils/Calendar.cs
Normal file
@@ -0,0 +1,816 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Calendar
|
||||
{
|
||||
private DateTime _utcDateTime; // 存储 UTC 时间(所有算术的基础)
|
||||
private Calendar _calendar; // 当前日历系统
|
||||
private TimeZoneInfo _timeZone; // 当前时区
|
||||
private bool _is24HourClock; // true = 24小时制,false = 12小时制
|
||||
private List<string> _languages; // 语言优先级列表
|
||||
private string _numeralSystem = "Latn"; // 数字系统(简化实现,仅存储)
|
||||
private const long TicksPerNanosecond = 100; // 1 tick = 100 ns
|
||||
|
||||
// 缓存的本地时间(根据时区从 _utcDateTime 转换得到)
|
||||
private DateTime _localDateTime;
|
||||
|
||||
// 更新本地时间(当 UTC 时间或时区改变时调用)
|
||||
private void UpdateLocalDateTime ()
|
||||
{
|
||||
_localDateTime = TimeZoneInfo.ConvertTimeFromUtc (_utcDateTime, _timeZone);
|
||||
}
|
||||
|
||||
// 当本地时间被修改后,同步回 UTC 时间
|
||||
private void UpdateUtcDateTime ()
|
||||
{
|
||||
_utcDateTime = TimeZoneInfo.ConvertTimeToUtc (_localDateTime, _timeZone);
|
||||
}
|
||||
|
||||
// 辅助:日历字段的读取
|
||||
private int GetCalendarField (Func<Calendar, DateTime, int> fieldGetter)
|
||||
{
|
||||
return fieldGetter (_calendar, _localDateTime);
|
||||
}
|
||||
|
||||
// 辅助:日历字段的设置(返回新的本地时间)
|
||||
private DateTime SetCalendarField (DateTime currentLocal, Func<Calendar, DateTime, int, DateTime> fieldSetter, int value)
|
||||
{
|
||||
return fieldSetter (_calendar, currentLocal, value);
|
||||
}
|
||||
|
||||
// 根据日历标识符创建日历实例
|
||||
private static Calendar CreateCalendar (string calendarId)
|
||||
{
|
||||
switch (calendarId)
|
||||
{
|
||||
case "GregorianCalendar":
|
||||
return new GregorianCalendar ();
|
||||
case "HebrewCalendar":
|
||||
return new HebrewCalendar ();
|
||||
case "HijriCalendar":
|
||||
return new HijriCalendar ();
|
||||
case "JapaneseCalendar":
|
||||
return new JapaneseCalendar ();
|
||||
case "KoreanCalendar":
|
||||
return new KoreanCalendar ();
|
||||
case "TaiwanCalendar":
|
||||
return new TaiwanCalendar ();
|
||||
case "ThaiBuddhistCalendar":
|
||||
return new ThaiBuddhistCalendar ();
|
||||
case "UmAlQuraCalendar":
|
||||
return new UmAlQuraCalendar ();
|
||||
// 可根据需要增加更多日历
|
||||
default:
|
||||
return new GregorianCalendar ();
|
||||
}
|
||||
}
|
||||
|
||||
private _I_Language GetFormatCulture ()
|
||||
{
|
||||
if (_languages == null || _languages.Count == 0)
|
||||
return new _I_Language (CultureInfo.CurrentCulture.Name);
|
||||
try
|
||||
{
|
||||
return new _I_Language (_languages [0]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new _I_Language (CultureInfo.CurrentCulture.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private List<object> JsArrayToList (object jsArray)
|
||||
{
|
||||
var result = new List<object> ();
|
||||
|
||||
if (jsArray == null)
|
||||
return result;
|
||||
|
||||
// JS Array 有 length 属性和数字索引器
|
||||
var type = jsArray.GetType ();
|
||||
|
||||
int length = (int)type.InvokeMember (
|
||||
"length",
|
||||
BindingFlags.GetProperty,
|
||||
null,
|
||||
jsArray,
|
||||
null);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
object value = type.InvokeMember (
|
||||
i.ToString (),
|
||||
BindingFlags.GetProperty,
|
||||
null,
|
||||
jsArray,
|
||||
null);
|
||||
|
||||
result.Add (value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public _I_Calendar ()
|
||||
: this (new List<string> { CultureInfo.CurrentCulture.Name },
|
||||
"GregorianCalendar", "24HourClock", TimeZoneInfo.Local.Id)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_Calendar (object languages)
|
||||
: this (languages, "GregorianCalendar", "24HourClock", TimeZoneInfo.Local.Id)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_Calendar (object languages, string calendar, string clock)
|
||||
: this (languages, calendar, clock, TimeZoneInfo.Local.Id)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_Calendar (object languages, string calendar, string clock, string timeZoneId)
|
||||
{
|
||||
_languages = languages == null ? new List<string> () : new List<string> (JsArrayToList (languages).Select (e => e as string));
|
||||
if (_languages.Count == 0)
|
||||
_languages.Add (CultureInfo.CurrentCulture.Name);
|
||||
|
||||
_calendar = CreateCalendar (calendar);
|
||||
_is24HourClock = (clock == "24HourClock");
|
||||
_timeZone = TimeZoneInfo.FindSystemTimeZoneById (timeZoneId);
|
||||
_utcDateTime = DateTime.UtcNow;
|
||||
UpdateLocalDateTime ();
|
||||
}
|
||||
|
||||
public int Day
|
||||
{
|
||||
get
|
||||
{
|
||||
return _calendar.GetDayOfMonth (_localDateTime);
|
||||
}
|
||||
set
|
||||
{
|
||||
int currentDay = _calendar.GetDayOfMonth (_localDateTime);
|
||||
if (value == currentDay) return;
|
||||
// 通过加减天数来设置日期
|
||||
DateTime newLocal = _calendar.AddDays (_localDateTime, value - currentDay);
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public int DayOfWeek
|
||||
{
|
||||
get
|
||||
{
|
||||
// 返回 0-6,0 表示星期日
|
||||
return (int)_calendar.GetDayOfWeek (_localDateTime);
|
||||
}
|
||||
}
|
||||
|
||||
public int Era
|
||||
{
|
||||
get
|
||||
{
|
||||
return _calendar.GetEra (_localDateTime);
|
||||
}
|
||||
set
|
||||
{
|
||||
// 更改纪元较复杂,简化:仅当值不同时不做任何操作(可根据需求实现)
|
||||
// 这里忽略设置,或者可以抛出 NotSupportedException
|
||||
if (value != Era)
|
||||
throw new NotSupportedException ("Setting Era directly is not supported in this implementation.");
|
||||
}
|
||||
}
|
||||
|
||||
public int FirstDayInThisMonth
|
||||
{
|
||||
get { return 1; }
|
||||
}
|
||||
|
||||
public int FirstEra
|
||||
{
|
||||
get { return _calendar.GetEra (_calendar.MinSupportedDateTime); }
|
||||
}
|
||||
|
||||
public int FirstHourInThisPeriod
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_is24HourClock)
|
||||
return 0;
|
||||
else
|
||||
return (Period == 0) ? 1 : 13;
|
||||
}
|
||||
}
|
||||
|
||||
public int FirstMinuteInThisHour
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public int FirstMonthInThisYear
|
||||
{
|
||||
get { return 1; }
|
||||
}
|
||||
|
||||
public int FirstPeriodInThisDay
|
||||
{
|
||||
get { return 0; } // 0 = AM
|
||||
}
|
||||
|
||||
public int FirstSecondInThisMinute
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public int FirstYearInThisEra
|
||||
{
|
||||
get
|
||||
{
|
||||
DateTime eraStart = _calendar.MinSupportedDateTime;
|
||||
int targetEra = Era;
|
||||
while (_calendar.GetEra (eraStart) != targetEra && eraStart < DateTime.MaxValue)
|
||||
{
|
||||
eraStart = _calendar.AddYears (eraStart, 1);
|
||||
}
|
||||
return _calendar.GetYear (eraStart);
|
||||
}
|
||||
}
|
||||
|
||||
public int Hour
|
||||
{
|
||||
get
|
||||
{
|
||||
int hour24 = _calendar.GetHour (_localDateTime);
|
||||
if (_is24HourClock)
|
||||
return hour24;
|
||||
int hour12 = hour24 % 12;
|
||||
return (hour12 == 0) ? 12 : hour12;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_is24HourClock)
|
||||
{
|
||||
if (value < 0 || value > 23)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Hour must be between 0 and 23 for 24-hour clock.");
|
||||
DateTime newLocal = _localDateTime.Date.AddHours (value).AddMinutes (Minute).AddSeconds (Second);
|
||||
_localDateTime = newLocal;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value < 1 || value > 12)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Hour must be between 1 and 12 for 12-hour clock.");
|
||||
int hour24 = value % 12;
|
||||
if (Period == 1) hour24 += 12;
|
||||
DateTime newLocal = _localDateTime.Date.AddHours (hour24).AddMinutes (Minute).AddSeconds (Second);
|
||||
_localDateTime = newLocal;
|
||||
}
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDaylightSavingTime
|
||||
{
|
||||
get { return _timeZone.IsDaylightSavingTime (_localDateTime); }
|
||||
}
|
||||
|
||||
public _I_List Languages
|
||||
{
|
||||
get { return new _I_List (_languages.AsReadOnly ().Select (e => (object)e), true) ; }
|
||||
}
|
||||
|
||||
public int LastDayInThisMonth
|
||||
{
|
||||
get { return _calendar.GetDaysInMonth (_calendar.GetYear (_localDateTime), _calendar.GetMonth (_localDateTime)); }
|
||||
}
|
||||
|
||||
public int LastEra
|
||||
{
|
||||
get { return _calendar.GetEra (_calendar.MaxSupportedDateTime); }
|
||||
}
|
||||
|
||||
public int LastHourInThisPeriod
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_is24HourClock)
|
||||
return 23;
|
||||
else
|
||||
return (Period == 0) ? 11 : 23;
|
||||
}
|
||||
}
|
||||
|
||||
public int LastMinuteInThisHour
|
||||
{
|
||||
get { return 59; }
|
||||
}
|
||||
|
||||
public int LastMonthInThisYear
|
||||
{
|
||||
get { return _calendar.GetMonthsInYear (_calendar.GetYear (_localDateTime)); }
|
||||
}
|
||||
|
||||
public int LastPeriodInThisDay
|
||||
{
|
||||
get { return 1; } // 1 = PM
|
||||
}
|
||||
|
||||
public int LastSecondInThisMinute
|
||||
{
|
||||
get { return 59; }
|
||||
}
|
||||
|
||||
public int LastYearInThisEra
|
||||
{
|
||||
get
|
||||
{
|
||||
DateTime eraEnd = _calendar.MaxSupportedDateTime;
|
||||
int targetEra = Era;
|
||||
while (_calendar.GetEra (eraEnd) != targetEra && eraEnd > DateTime.MinValue)
|
||||
{
|
||||
eraEnd = _calendar.AddYears (eraEnd, -1);
|
||||
}
|
||||
return _calendar.GetYear (eraEnd);
|
||||
}
|
||||
}
|
||||
|
||||
public int Minute
|
||||
{
|
||||
get { return _calendar.GetMinute (_localDateTime); }
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > 59)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Minute must be between 0 and 59.");
|
||||
DateTime newLocal = _localDateTime.AddMinutes (value - _calendar.GetMinute (_localDateTime));
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public int Month
|
||||
{
|
||||
get { return _calendar.GetMonth (_localDateTime); }
|
||||
set
|
||||
{
|
||||
if (value < 1 || value > _calendar.GetMonthsInYear (_calendar.GetYear (_localDateTime)))
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Month is out of range for current year.");
|
||||
DateTime newLocal = SetCalendarField (_localDateTime, (cal, dt, val) => cal.AddMonths (dt, val - cal.GetMonth (dt)), value);
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public int Nanosecond
|
||||
{
|
||||
get
|
||||
{
|
||||
long ticksInSecond = _localDateTime.Ticks % TimeSpan.TicksPerSecond;
|
||||
return (int)(ticksInSecond * 100); // 1 tick = 100 ns
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > 999999999)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Nanosecond must be between 0 and 999,999,999.");
|
||||
long ticks = (_localDateTime.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond + (value / 100);
|
||||
_localDateTime = new DateTime (ticks, _localDateTime.Kind);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public int NumberOfDaysInThisMonth
|
||||
{
|
||||
get { return LastDayInThisMonth; }
|
||||
}
|
||||
|
||||
public int NumberOfEras
|
||||
{
|
||||
get { return _calendar.Eras.Length; }
|
||||
}
|
||||
|
||||
public int NumberOfHoursInThisPeriod
|
||||
{
|
||||
get { return _is24HourClock ? 24 : 12; }
|
||||
}
|
||||
|
||||
public int NumberOfMinutesInThisHour
|
||||
{
|
||||
get { return 60; }
|
||||
}
|
||||
|
||||
public int NumberOfMonthsInThisYear
|
||||
{
|
||||
get { return _calendar.GetMonthsInYear (_calendar.GetYear (_localDateTime)); }
|
||||
}
|
||||
|
||||
public int NumberOfPeriodsInThisDay
|
||||
{
|
||||
get { return 2; }
|
||||
}
|
||||
|
||||
public int NumberOfSecondsInThisMinute
|
||||
{
|
||||
get { return 60; }
|
||||
}
|
||||
|
||||
public int NumberOfYearsInThisEra
|
||||
{
|
||||
get { return LastYearInThisEra - FirstYearInThisEra + 1; }
|
||||
}
|
||||
|
||||
public string NumeralSystem
|
||||
{
|
||||
get { return _numeralSystem; }
|
||||
set { _numeralSystem = value; } // 简化:未实现实际数字转换
|
||||
}
|
||||
|
||||
public int Period
|
||||
{
|
||||
get
|
||||
{
|
||||
int hour24 = _calendar.GetHour (_localDateTime);
|
||||
return (hour24 >= 12) ? 1 : 0;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != 0 && value != 1)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Period must be 0 (AM) or 1 (PM).");
|
||||
int currentPeriod = Period;
|
||||
if (currentPeriod == value) return;
|
||||
// 切换 AM/PM:加减 12 小时
|
||||
DateTime newLocal = _localDateTime.AddHours (value == 0 ? -12 : 12);
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public string ResolvedLanguage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_languages != null && _languages.Count > 0)
|
||||
return _languages [0];
|
||||
return CultureInfo.CurrentCulture.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public int Second
|
||||
{
|
||||
get { return _calendar.GetSecond (_localDateTime); }
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > 59)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Second must be between 0 and 59.");
|
||||
DateTime newLocal = _localDateTime.AddSeconds (value - _calendar.GetSecond (_localDateTime));
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public int Year
|
||||
{
|
||||
get { return _calendar.GetYear (_localDateTime); }
|
||||
set
|
||||
{
|
||||
if (value < _calendar.GetYear (_calendar.MinSupportedDateTime) || value > _calendar.GetYear (_calendar.MaxSupportedDateTime))
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Year is out of range for this calendar.");
|
||||
DateTime newLocal = SetCalendarField (_localDateTime, (cal, dt, val) => cal.AddYears (dt, val - cal.GetYear (dt)), value);
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddDays (int days)
|
||||
{
|
||||
_localDateTime = _calendar.AddDays (_localDateTime, days);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddEras (int eras)
|
||||
{
|
||||
// 简化:每个纪元按 1000 年估算(实际应基于日历的纪元范围)
|
||||
// 大多数情况下不应频繁使用此方法
|
||||
_localDateTime = _calendar.AddYears (_localDateTime, eras * 1000);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddHours (int hours)
|
||||
{
|
||||
_localDateTime = _localDateTime.AddHours (hours);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddMinutes (int minutes)
|
||||
{
|
||||
_localDateTime = _localDateTime.AddMinutes (minutes);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddMonths (int months)
|
||||
{
|
||||
_localDateTime = _calendar.AddMonths (_localDateTime, months);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddNanoseconds (int nanoseconds)
|
||||
{
|
||||
long ticksToAdd = nanoseconds / 100;
|
||||
_localDateTime = _localDateTime.AddTicks (ticksToAdd);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddPeriods (int periods)
|
||||
{
|
||||
_localDateTime = _localDateTime.AddHours (periods * 12);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddSeconds (int seconds)
|
||||
{
|
||||
_localDateTime = _localDateTime.AddSeconds (seconds);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddWeeks (int weeks)
|
||||
{
|
||||
AddDays (weeks * 7);
|
||||
}
|
||||
|
||||
public void AddYears (int years)
|
||||
{
|
||||
_localDateTime = _calendar.AddYears (_localDateTime, years);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void ChangeCalendarSystem (string calendarId)
|
||||
{
|
||||
Calendar newCalendar = CreateCalendar (calendarId);
|
||||
// 注意:日历改变不会改变绝对时间,但会影响组件(年、月、日等)
|
||||
// 只需替换日历实例,_localDateTime 保持不变(但解释方式变了)
|
||||
_calendar = newCalendar;
|
||||
}
|
||||
|
||||
public void ChangeClock (string clock)
|
||||
{
|
||||
_is24HourClock = (clock == "24HourClock");
|
||||
}
|
||||
|
||||
public void ChangeTimeZone (string timeZoneId)
|
||||
{
|
||||
_timeZone = TimeZoneInfo.FindSystemTimeZoneById (timeZoneId);
|
||||
UpdateLocalDateTime (); // 重新计算本地时间(UTC 不变)
|
||||
}
|
||||
|
||||
public _I_Calendar Clone ()
|
||||
{
|
||||
var clone = new _I_Calendar (_languages, GetCalendarSystem (), GetClock (), GetTimeZone ());
|
||||
clone.SetDateTime (GetDateTime ());
|
||||
return clone;
|
||||
}
|
||||
|
||||
public int Compare (_I_Calendar other)
|
||||
{
|
||||
if (other == null) return 1;
|
||||
return DateTime.Compare (this.GetDateTime (), other.GetDateTime ());
|
||||
}
|
||||
|
||||
public static DateTime JsDateToDateTime (object jsDate)
|
||||
{
|
||||
if (jsDate == null)
|
||||
throw new ArgumentNullException (nameof (jsDate));
|
||||
Type type = jsDate.GetType ();
|
||||
double milliseconds = (double)type.InvokeMember (
|
||||
"getTime",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsDate,
|
||||
null);
|
||||
DateTimeOffset epoch = new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
||||
DateTimeOffset dateTimeOffset = epoch.AddMilliseconds (milliseconds);
|
||||
return dateTimeOffset.UtcDateTime;
|
||||
}
|
||||
public int CompareDateTime (object other)
|
||||
{
|
||||
return DateTime.Compare (this.GetDateTime (), JsDateToDateTime (other));
|
||||
}
|
||||
|
||||
public void CopyTo (_I_Calendar other)
|
||||
{
|
||||
if (other == null) throw new ArgumentNullException (nameof (other));
|
||||
other._utcDateTime = this._utcDateTime;
|
||||
other._localDateTime = this._localDateTime;
|
||||
other._calendar = this._calendar;
|
||||
other._timeZone = this._timeZone;
|
||||
other._is24HourClock = this._is24HourClock;
|
||||
other._languages = new List<string> (this._languages);
|
||||
other._numeralSystem = this._numeralSystem;
|
||||
}
|
||||
|
||||
public string DayAsPaddedString (int minDigits)
|
||||
{
|
||||
return Day.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string DayAsString ()
|
||||
{
|
||||
return Day.ToString ();
|
||||
}
|
||||
|
||||
public string DayOfWeekAsSoloString ()
|
||||
{
|
||||
return DayOfWeekAsString ();
|
||||
}
|
||||
|
||||
public string DayOfWeekAsSoloString (int idealLength)
|
||||
{
|
||||
// 简化:忽略 idealLength
|
||||
return DayOfWeekAsString ();
|
||||
}
|
||||
|
||||
public string DayOfWeekAsString ()
|
||||
{
|
||||
return _localDateTime.ToString ("dddd", GetFormatCulture ());
|
||||
}
|
||||
|
||||
public string DayOfWeekAsString (int idealLength)
|
||||
{
|
||||
return DayOfWeekAsString ();
|
||||
}
|
||||
|
||||
public string EraAsString ()
|
||||
{
|
||||
// 简化:返回纪元索引的字符串
|
||||
return Era.ToString ();
|
||||
}
|
||||
|
||||
public string EraAsString (int idealLength)
|
||||
{
|
||||
return EraAsString ();
|
||||
}
|
||||
|
||||
public string GetCalendarSystem ()
|
||||
{
|
||||
if (_calendar is GregorianCalendar) return "GregorianCalendar";
|
||||
if (_calendar is HebrewCalendar) return "HebrewCalendar";
|
||||
if (_calendar is HijriCalendar) return "HijriCalendar";
|
||||
if (_calendar is JapaneseCalendar) return "JapaneseCalendar";
|
||||
if (_calendar is KoreanCalendar) return "KoreanCalendar";
|
||||
if (_calendar is TaiwanCalendar) return "TaiwanCalendar";
|
||||
if (_calendar is ThaiBuddhistCalendar) return "ThaiBuddhistCalendar";
|
||||
if (_calendar is UmAlQuraCalendar) return "UmAlQuraCalendar";
|
||||
return "GregorianCalendar";
|
||||
}
|
||||
|
||||
public string GetClock ()
|
||||
{
|
||||
return _is24HourClock ? "24HourClock" : "12HourClock";
|
||||
}
|
||||
|
||||
public DateTime GetDateTime ()
|
||||
{
|
||||
// 返回 UTC 时间
|
||||
return _utcDateTime;
|
||||
}
|
||||
|
||||
public string GetTimeZone ()
|
||||
{
|
||||
return _timeZone.Id;
|
||||
}
|
||||
|
||||
public string HourAsPaddedString (int minDigits)
|
||||
{
|
||||
return Hour.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string HourAsString ()
|
||||
{
|
||||
return Hour.ToString ();
|
||||
}
|
||||
|
||||
public string MinuteAsPaddedString (int minDigits)
|
||||
{
|
||||
return Minute.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string MinuteAsString ()
|
||||
{
|
||||
return Minute.ToString ();
|
||||
}
|
||||
|
||||
public string MonthAsNumericString ()
|
||||
{
|
||||
return Month.ToString ();
|
||||
}
|
||||
|
||||
public string MonthAsPaddedNumericString (int minDigits)
|
||||
{
|
||||
return Month.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string MonthAsSoloString ()
|
||||
{
|
||||
return _localDateTime.ToString ("MMMM", GetFormatCulture ());
|
||||
}
|
||||
|
||||
public string MonthAsSoloString (int idealLength)
|
||||
{
|
||||
return MonthAsSoloString ();
|
||||
}
|
||||
|
||||
public string MonthAsString ()
|
||||
{
|
||||
return _localDateTime.ToString ("MMM", GetFormatCulture ());
|
||||
}
|
||||
|
||||
public string MonthAsString (int idealLength)
|
||||
{
|
||||
return MonthAsString ();
|
||||
}
|
||||
|
||||
public string NanosecondAsPaddedString (int minDigits)
|
||||
{
|
||||
return Nanosecond.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string NanosecondAsString ()
|
||||
{
|
||||
return Nanosecond.ToString ();
|
||||
}
|
||||
|
||||
public string PeriodAsString ()
|
||||
{
|
||||
return PeriodAsString (0);
|
||||
}
|
||||
|
||||
public string PeriodAsString (int idealLength)
|
||||
{
|
||||
return _localDateTime.ToString ("tt", GetFormatCulture ());
|
||||
}
|
||||
|
||||
public string SecondAsPaddedString (int minDigits)
|
||||
{
|
||||
return Second.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string SecondAsString ()
|
||||
{
|
||||
return Second.ToString ();
|
||||
}
|
||||
|
||||
public void SetDateTime (DateTime value)
|
||||
{
|
||||
_utcDateTime = value.ToUniversalTime ();
|
||||
UpdateLocalDateTime ();
|
||||
}
|
||||
|
||||
public void SetToMax ()
|
||||
{
|
||||
SetDateTime (DateTime.MaxValue);
|
||||
}
|
||||
|
||||
public void SetToMin ()
|
||||
{
|
||||
SetDateTime (DateTime.MinValue);
|
||||
}
|
||||
|
||||
public void SetToNow ()
|
||||
{
|
||||
SetDateTime (DateTime.UtcNow);
|
||||
}
|
||||
|
||||
public string TimeZoneAsString ()
|
||||
{
|
||||
return TimeZoneAsString (0);
|
||||
}
|
||||
|
||||
public string TimeZoneAsString (int idealLength)
|
||||
{
|
||||
// 简化:返回标准显示名称
|
||||
return _timeZone.DisplayName;
|
||||
}
|
||||
|
||||
public string YearAsPaddedString (int minDigits)
|
||||
{
|
||||
return Year.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string YearAsString ()
|
||||
{
|
||||
return Year.ToString ();
|
||||
}
|
||||
|
||||
public string YearAsTruncatedString (int remainingDigits)
|
||||
{
|
||||
string yearStr = Year.ToString ();
|
||||
if (yearStr.Length <= remainingDigits)
|
||||
return yearStr;
|
||||
return yearStr.Substring (yearStr.Length - remainingDigits);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,10 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Calendar.cs" />
|
||||
<Compile Include="DateTimeFormat.cs" />
|
||||
<Compile Include="Download.cs" />
|
||||
<Compile Include="Enumerable.cs" />
|
||||
<Compile Include="HResult.cs" />
|
||||
<Compile Include="IE.cs" />
|
||||
<Compile Include="Locale.cs" />
|
||||
@@ -61,6 +64,7 @@
|
||||
<Compile Include="Utils.cs" />
|
||||
<Compile Include="Version.cs" />
|
||||
<Compile Include="VisualElements.cs" />
|
||||
<Compile Include="Web.cs" />
|
||||
<Compile Include="WebBrowser.cs" />
|
||||
<Compile Include="Window.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
494
DataUtils/DateTimeFormat.cs
Normal file
@@ -0,0 +1,494 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public enum YearFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
Abbreviated = 2,
|
||||
Full = 3,
|
||||
}
|
||||
|
||||
public enum MonthFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
Abbreviated = 2,
|
||||
Full = 3,
|
||||
Numeric = 4,
|
||||
}
|
||||
|
||||
public enum DayFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
}
|
||||
|
||||
public enum DayOfWeekFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
Abbreviated = 2,
|
||||
Full = 3,
|
||||
}
|
||||
|
||||
public enum HourFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
}
|
||||
|
||||
public enum MinuteFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
}
|
||||
|
||||
public enum SecondFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
}
|
||||
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_DateTimeFormatter
|
||||
{
|
||||
// ---------- 私有字段 ----------
|
||||
private string _formatTemplate; // 原始模板字符串
|
||||
private string _formatPattern; // 实际用于 .NET 格式化的模式
|
||||
private List<string> _languages; // 语言优先级列表
|
||||
private string _geographicRegion; // 地理区域
|
||||
private string _calendar = "GregorianCalendar";
|
||||
private string _clock = "24HourClock";
|
||||
private string _numeralSystem = "Latn";
|
||||
private CultureInfo _culture; // 解析后的 CultureInfo
|
||||
private string _resolvedLanguage; // 实际使用的语言
|
||||
private string _resolvedGeographicRegion; // 实际使用的区域
|
||||
|
||||
// 存储构造时传入的枚举值(用于 IncludeXXX 属性)
|
||||
private YearFormat _yearFormat = YearFormat.None;
|
||||
private MonthFormat _monthFormat = MonthFormat.None;
|
||||
private DayFormat _dayFormat = DayFormat.None;
|
||||
private DayOfWeekFormat _dayOfWeekFormat = DayOfWeekFormat.None;
|
||||
private HourFormat _hourFormat = HourFormat.None;
|
||||
private MinuteFormat _minuteFormat = MinuteFormat.None;
|
||||
private SecondFormat _secondFormat = SecondFormat.None;
|
||||
|
||||
// ---------- 辅助方法 ----------
|
||||
private static string MapTemplateToPattern (string template, CultureInfo culture, string clock)
|
||||
{
|
||||
if (string.IsNullOrEmpty (template))
|
||||
return string.Empty;
|
||||
|
||||
switch (template.ToLowerInvariant ())
|
||||
{
|
||||
case "longdate":
|
||||
return culture.DateTimeFormat.LongDatePattern;
|
||||
case "shortdate":
|
||||
return culture.DateTimeFormat.ShortDatePattern;
|
||||
case "longtime":
|
||||
return culture.DateTimeFormat.LongTimePattern;
|
||||
case "shorttime":
|
||||
return culture.DateTimeFormat.ShortTimePattern;
|
||||
case "dayofweek":
|
||||
return culture.DateTimeFormat.ShortestDayNames? [0] ?? "dddd"; // 近似
|
||||
case "dayofweek.full":
|
||||
return "dddd";
|
||||
case "dayofweek.abbreviated":
|
||||
return "ddd";
|
||||
case "day":
|
||||
return "dd";
|
||||
case "month":
|
||||
return "MMMM";
|
||||
case "month.full":
|
||||
return "MMMM";
|
||||
case "month.abbreviated":
|
||||
return "MMM";
|
||||
case "month.numeric":
|
||||
return "MM";
|
||||
case "year":
|
||||
return "yyyy";
|
||||
case "year.full":
|
||||
return "yyyy";
|
||||
case "year.abbreviated":
|
||||
return "yy";
|
||||
case "hour":
|
||||
return clock == "24HourClock" ? "HH" : "hh";
|
||||
case "minute":
|
||||
return "mm";
|
||||
case "second":
|
||||
return "ss";
|
||||
case "timezone":
|
||||
return "zzz";
|
||||
default:
|
||||
// 如果不是预定义模板,则当作自定义模式直接返回
|
||||
return template;
|
||||
}
|
||||
}
|
||||
|
||||
// 根据枚举组合构建格式模式
|
||||
private static string BuildPatternFromEnums (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek,
|
||||
HourFormat hour, MinuteFormat minute, SecondFormat second,
|
||||
string clock, CultureInfo culture)
|
||||
{
|
||||
var parts = new List<string> ();
|
||||
// 日期部分
|
||||
if (dayOfWeek != DayOfWeekFormat.None)
|
||||
{
|
||||
if (dayOfWeek == DayOfWeekFormat.Abbreviated)
|
||||
parts.Add ("ddd");
|
||||
else // Full or Default
|
||||
parts.Add ("dddd");
|
||||
}
|
||||
if (year != YearFormat.None)
|
||||
{
|
||||
if (year == YearFormat.Abbreviated)
|
||||
parts.Add ("yy");
|
||||
else
|
||||
parts.Add ("yyyy");
|
||||
}
|
||||
if (month != MonthFormat.None)
|
||||
{
|
||||
switch (month)
|
||||
{
|
||||
case MonthFormat.Numeric:
|
||||
parts.Add ("MM");
|
||||
break;
|
||||
case MonthFormat.Abbreviated:
|
||||
parts.Add ("MMM");
|
||||
break;
|
||||
case MonthFormat.Full:
|
||||
parts.Add ("MMMM");
|
||||
break;
|
||||
default:
|
||||
parts.Add ("MM");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (day != DayFormat.None)
|
||||
{
|
||||
parts.Add ("dd");
|
||||
}
|
||||
string datePart = string.Join (" ", parts);
|
||||
// 时间部分
|
||||
var timeParts = new List<string> ();
|
||||
if (hour != HourFormat.None)
|
||||
{
|
||||
if (clock == "24HourClock")
|
||||
timeParts.Add ("HH");
|
||||
else
|
||||
timeParts.Add ("hh");
|
||||
}
|
||||
if (minute != MinuteFormat.None)
|
||||
{
|
||||
timeParts.Add ("mm");
|
||||
}
|
||||
if (second != SecondFormat.None)
|
||||
{
|
||||
timeParts.Add ("ss");
|
||||
}
|
||||
string timePart = timeParts.Count > 0 ? string.Join (":", timeParts) : "";
|
||||
if (!string.IsNullOrEmpty (datePart) && !string.IsNullOrEmpty (timePart))
|
||||
return datePart + " " + timePart;
|
||||
if (!string.IsNullOrEmpty (datePart))
|
||||
return datePart;
|
||||
return timePart;
|
||||
}
|
||||
|
||||
// 将 JS Date 对象转换为 DateTime
|
||||
private DateTime ConvertJsDateToDateTime (object jsDate)
|
||||
{
|
||||
if (jsDate == null)
|
||||
throw new ArgumentNullException (nameof (jsDate));
|
||||
|
||||
Type type = jsDate.GetType ();
|
||||
// 调用 getTime() 获取毫秒数 (double)
|
||||
double milliseconds = (double)type.InvokeMember (
|
||||
"getTime",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsDate,
|
||||
null);
|
||||
|
||||
// 手动计算 Unix 纪元转换(兼容低版本 .NET)
|
||||
DateTime epoch = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
DateTime utcDateTime = epoch.AddMilliseconds (milliseconds);
|
||||
// 返回本地时间(可根据需求调整)
|
||||
return utcDateTime.ToLocalTime ();
|
||||
}
|
||||
|
||||
// 初始化文化信息
|
||||
private void InitializeCulture ()
|
||||
{
|
||||
string lang = (_languages != null && _languages.Count > 0) ? _languages [0] : CultureInfo.CurrentCulture.Name;
|
||||
try
|
||||
{
|
||||
_culture = new CultureInfo (lang);
|
||||
_resolvedLanguage = _culture.Name;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_culture = CultureInfo.CurrentCulture;
|
||||
_resolvedLanguage = _culture.Name;
|
||||
}
|
||||
_resolvedGeographicRegion = _geographicRegion ?? _culture.Name;
|
||||
// 根据区域和语言更新格式模式(如果使用模板)
|
||||
if (!string.IsNullOrEmpty (_formatTemplate))
|
||||
{
|
||||
_formatPattern = MapTemplateToPattern (_formatTemplate, _culture, _clock);
|
||||
}
|
||||
else if (_yearFormat != YearFormat.None || _monthFormat != MonthFormat.None ||
|
||||
_dayFormat != DayFormat.None || _dayOfWeekFormat != DayOfWeekFormat.None ||
|
||||
_hourFormat != HourFormat.None || _minuteFormat != MinuteFormat.None ||
|
||||
_secondFormat != SecondFormat.None)
|
||||
{
|
||||
_formatPattern = BuildPatternFromEnums (_yearFormat, _monthFormat, _dayFormat, _dayOfWeekFormat,
|
||||
_hourFormat, _minuteFormat, _secondFormat, _clock, _culture);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 构造函数 ----------
|
||||
public _I_DateTimeFormatter (string formatTemplate)
|
||||
: this (formatTemplate, null, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (string formatTemplate, IEnumerable<string> languages)
|
||||
: this (formatTemplate, languages, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (string formatTemplate, IEnumerable<string> languages, string geographicRegion, string calendar, string clock)
|
||||
{
|
||||
_formatTemplate = formatTemplate;
|
||||
_languages = languages == null ? new List<string> () : new List<string> (languages);
|
||||
_geographicRegion = geographicRegion;
|
||||
if (!string.IsNullOrEmpty (calendar))
|
||||
_calendar = calendar;
|
||||
if (!string.IsNullOrEmpty (clock))
|
||||
_clock = clock;
|
||||
InitializeCulture ();
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek)
|
||||
: this (year, month, day, dayOfWeek, HourFormat.None, MinuteFormat.None, SecondFormat.None, null, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (HourFormat hour, MinuteFormat minute, SecondFormat second)
|
||||
: this (YearFormat.None, MonthFormat.None, DayFormat.None, DayOfWeekFormat.None, hour, minute, second, null, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek,
|
||||
HourFormat hour, MinuteFormat minute, SecondFormat second,
|
||||
IEnumerable<string> languages)
|
||||
: this (year, month, day, dayOfWeek, hour, minute, second, languages, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek,
|
||||
HourFormat hour, MinuteFormat minute, SecondFormat second,
|
||||
IEnumerable<string> languages, string geographicRegion, string calendar, string clock)
|
||||
{
|
||||
_yearFormat = year;
|
||||
_monthFormat = month;
|
||||
_dayFormat = day;
|
||||
_dayOfWeekFormat = dayOfWeek;
|
||||
_hourFormat = hour;
|
||||
_minuteFormat = minute;
|
||||
_secondFormat = second;
|
||||
_languages = languages == null ? new List<string> () : new List<string> (languages);
|
||||
_geographicRegion = geographicRegion;
|
||||
if (!string.IsNullOrEmpty (calendar))
|
||||
_calendar = calendar;
|
||||
if (!string.IsNullOrEmpty (clock))
|
||||
_clock = clock;
|
||||
InitializeCulture ();
|
||||
}
|
||||
|
||||
// ---------- 属性 ----------
|
||||
public string Calendar
|
||||
{
|
||||
get { return _calendar; }
|
||||
set
|
||||
{
|
||||
_calendar = value;
|
||||
// 日历更改可能需要重新初始化模式,这里简化处理
|
||||
}
|
||||
}
|
||||
|
||||
public string Clock
|
||||
{
|
||||
get { return _clock; }
|
||||
set
|
||||
{
|
||||
_clock = value;
|
||||
InitializeCulture (); // 重新生成模式(因为小时格式可能变化)
|
||||
}
|
||||
}
|
||||
|
||||
public string GeographicRegion
|
||||
{
|
||||
get { return _geographicRegion; }
|
||||
set
|
||||
{
|
||||
_geographicRegion = value;
|
||||
InitializeCulture ();
|
||||
}
|
||||
}
|
||||
|
||||
public int IncludeDay
|
||||
{
|
||||
get { return (int)_dayFormat; }
|
||||
}
|
||||
|
||||
public int IncludeDayOfWeek
|
||||
{
|
||||
get { return (int)_dayOfWeekFormat; }
|
||||
}
|
||||
|
||||
public int IncludeHour
|
||||
{
|
||||
get { return (int)_hourFormat; }
|
||||
}
|
||||
|
||||
public int IncludeMinute
|
||||
{
|
||||
get { return (int)_minuteFormat; }
|
||||
}
|
||||
|
||||
public int IncludeMonth
|
||||
{
|
||||
get { return (int)_monthFormat; }
|
||||
}
|
||||
|
||||
public int IncludeSecond
|
||||
{
|
||||
get { return (int)_secondFormat; }
|
||||
}
|
||||
|
||||
public int IncludeYear
|
||||
{
|
||||
get { return (int)_yearFormat; }
|
||||
}
|
||||
|
||||
public _I_List Languages
|
||||
{
|
||||
get { return new _I_List (_languages.AsReadOnly ().Select (e => (object)e), true); }
|
||||
}
|
||||
|
||||
public static _I_DateTimeFormatter LongDate
|
||||
{
|
||||
get
|
||||
{
|
||||
return new _I_DateTimeFormatter ("longdate");
|
||||
}
|
||||
}
|
||||
|
||||
public static _I_DateTimeFormatter LongTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return new _I_DateTimeFormatter ("longtime");
|
||||
}
|
||||
}
|
||||
|
||||
public string NumeralSystem
|
||||
{
|
||||
get { return _numeralSystem; }
|
||||
set { _numeralSystem = value; }
|
||||
}
|
||||
|
||||
public _I_List Patterns
|
||||
{
|
||||
get
|
||||
{
|
||||
return new _I_List (new List<string> { _formatPattern }.AsReadOnly ().Select (e => (object)e), true);
|
||||
}
|
||||
}
|
||||
|
||||
public string ResolvedGeographicRegion
|
||||
{
|
||||
get { return _resolvedGeographicRegion; }
|
||||
}
|
||||
|
||||
public string ResolvedLanguage
|
||||
{
|
||||
get { return _resolvedLanguage; }
|
||||
}
|
||||
|
||||
public static _I_DateTimeFormatter ShortDate
|
||||
{
|
||||
get
|
||||
{
|
||||
return new _I_DateTimeFormatter ("shortdate");
|
||||
}
|
||||
}
|
||||
|
||||
public static _I_DateTimeFormatter ShortTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return new _I_DateTimeFormatter ("shorttime");
|
||||
}
|
||||
}
|
||||
|
||||
public string Template
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty (_formatTemplate))
|
||||
return _formatTemplate;
|
||||
// 从枚举组合生成模板描述(简化)
|
||||
return _formatPattern;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 方法 ----------
|
||||
public string FormatC (DateTime dateTime)
|
||||
{
|
||||
return dateTime.ToString (_formatPattern, _culture);
|
||||
}
|
||||
|
||||
public string FormatC (DateTime dateTime, string timeZoneId)
|
||||
{
|
||||
if (!string.IsNullOrEmpty (timeZoneId))
|
||||
{
|
||||
try
|
||||
{
|
||||
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (timeZoneId);
|
||||
DateTime targetTime = TimeZoneInfo.ConvertTime (dateTime, tzi);
|
||||
return targetTime.ToString (_formatPattern, _culture);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 时区无效,回退到原始时间
|
||||
return dateTime.ToString (_formatPattern, _culture);
|
||||
}
|
||||
}
|
||||
return dateTime.ToString (_formatPattern, _culture);
|
||||
}
|
||||
|
||||
// 为方便 JS 调用,提供接受 object 的重载(自动识别 JS Date)
|
||||
public string Format (object jsDate)
|
||||
{
|
||||
DateTime dt = ConvertJsDateToDateTime (jsDate);
|
||||
return FormatC (dt);
|
||||
}
|
||||
|
||||
public string FormatWithTimeZone (object jsDate, string timeZoneId)
|
||||
{
|
||||
DateTime dt = ConvertJsDateToDateTime (jsDate);
|
||||
return FormatC (dt, timeZoneId);
|
||||
}
|
||||
}
|
||||
}
|
||||
173
DataUtils/Enumerable.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[InterfaceType (ComInterfaceType.InterfaceIsDual)]
|
||||
public interface _I_Enumerable: IDisposable
|
||||
{
|
||||
int Length { get; set; }
|
||||
object this [int index] { get; set; }
|
||||
void Add (object value); // push
|
||||
void Push (object value);
|
||||
object Pop (); // 删除并返回末尾元素
|
||||
object Shift (); // 删除并返回开头元素
|
||||
void Unshift (object value); // 在开头插入
|
||||
void RemoveAt (int index); // 删除任意索引
|
||||
void Clear (); // 清空数组
|
||||
_I_Enumerable Slice (int start, int end); // 返回子数组
|
||||
void Splice (int start, int deleteCount, object [] items); // 删除并插入
|
||||
int IndexOf (object value); // 查找索引
|
||||
bool Includes (object value); // 是否包含
|
||||
void ForEach (object callback, bool suppressExceptions = false); // 遍历,callback(item, index)
|
||||
_I_Enumerable Concat (_I_Enumerable other); // 拼接
|
||||
string Join (string separator); // 转字符串
|
||||
object GetItem (int index); // 返回 { key, data } 或直接 data
|
||||
void SetAt (int index, object value); // 替换元素
|
||||
int IndexOfKey (int key); // 按内部 key 查找
|
||||
void Move (int index, int newIndex); // 移动元素
|
||||
void PushAll (object [] items); // 一次性 push 多个
|
||||
object Get (int index);
|
||||
object Set (int index, object value);
|
||||
object At (int index);
|
||||
}
|
||||
public class _I_List: _I_Enumerable, IList
|
||||
{
|
||||
public _I_List (IEnumerable<object> initArr, bool readOnly = false, bool fixedSize = false, bool sync = true)
|
||||
{
|
||||
_list = initArr?.ToList () ?? new List<object> ();
|
||||
IsFixedSize = fixedSize;
|
||||
IsReadOnly = readOnly;
|
||||
IsSynchronized = sync;
|
||||
}
|
||||
public _I_List (bool readOnly = false, bool fixedSize = false, bool sync = true) :
|
||||
this (null, readOnly, fixedSize, sync)
|
||||
{ }
|
||||
protected List<object> _list;
|
||||
protected object _lock = new object ();
|
||||
public object this [int index] { get { return _list [index]; } set { _list [index] = value; } }
|
||||
public int Count => _list.Count;
|
||||
public bool IsFixedSize { get; }
|
||||
public bool IsReadOnly { get; }
|
||||
public bool IsSynchronized { get; }
|
||||
public int Length
|
||||
{
|
||||
get { return _list.Count; }
|
||||
set
|
||||
{
|
||||
if (!IsFixedSize && !IsReadOnly)
|
||||
{
|
||||
_list.Capacity = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public object SyncRoot => _lock;
|
||||
public void Add (object value) => _list.Add (value);
|
||||
public void Push (object value) => _list.Add (value);
|
||||
public void RemoveAt (int index) => _list.RemoveAt (index);
|
||||
public void Clear () => _list.Clear ();
|
||||
public int IndexOf (object value) => _list.IndexOf (value);
|
||||
int IList.Add (object value)
|
||||
{
|
||||
_list.Add (value);
|
||||
return _list.Count - 1;
|
||||
}
|
||||
public bool Contains (object value) => _list.Contains (value);
|
||||
public void Insert (int index, object value) => _list.Insert (index, value);
|
||||
public void Remove (object value) => _list.Remove (value);
|
||||
public void ForEach (object callback, bool suppressExceptions = false)
|
||||
{
|
||||
for (int i = 0; i < _list.Count; i++)
|
||||
{
|
||||
var item = _list [i];
|
||||
if (suppressExceptions)
|
||||
{
|
||||
try { JsUtils.Call (callback, item, i); } catch { }
|
||||
}
|
||||
else JsUtils.Call (callback, item, i);
|
||||
}
|
||||
}
|
||||
public IEnumerator GetEnumerator () => _list.GetEnumerator ();
|
||||
public _I_Enumerable Slice (int start, int end)
|
||||
{
|
||||
if (end < 0) end = _list.Count + end;
|
||||
start = Math.Max (0, start);
|
||||
end = Math.Min (_list.Count, end);
|
||||
var arr = _list.GetRange (start, Math.Max (0, end - start));
|
||||
return new _I_List (arr);
|
||||
}
|
||||
public void Splice (int start, int deleteCount, object [] items)
|
||||
{
|
||||
if (start < 0) start = Math.Max (0, _list.Count + start);
|
||||
int count = Math.Min (deleteCount, _list.Count - start);
|
||||
_list.RemoveRange (start, count);
|
||||
if (items != null && items.Length > 0)
|
||||
_list.InsertRange (start, items);
|
||||
}
|
||||
public bool Includes (object value) => _list.Contains (value);
|
||||
public _I_Enumerable Concat (_I_Enumerable other)
|
||||
{
|
||||
var newList = new List<object> (_list);
|
||||
if (other is _I_List)
|
||||
newList.AddRange ((other as _I_List)._list);
|
||||
return new _I_List (newList);
|
||||
}
|
||||
public string Join (string separator)
|
||||
{
|
||||
return string.Join (separator ?? ",", _list.Select (x => x?.ToString () ?? ""));
|
||||
}
|
||||
public object GetItem (int index) => _list [index];
|
||||
public void SetAt (int index, object value) => _list [index] = value;
|
||||
public int IndexOfKey (int key)
|
||||
{
|
||||
return key >= 0 && key < _list.Count ? key : -1;
|
||||
}
|
||||
public void Move (int index, int newIndex)
|
||||
{
|
||||
if (index < 0 || index >= _list.Count || newIndex < 0 || newIndex >= _list.Count) return;
|
||||
var item = _list [index];
|
||||
_list.RemoveAt (index);
|
||||
_list.Insert (newIndex, item);
|
||||
}
|
||||
public void PushAll (object [] items)
|
||||
{
|
||||
if (items == null || items.Length == 0) return;
|
||||
_list.AddRange (items);
|
||||
}
|
||||
public void CopyTo (Array array, int index)
|
||||
{
|
||||
if (array == null) throw new ArgumentNullException (nameof (array));
|
||||
for (int i = 0; i < _list.Count && index + i < array.Length; i++)
|
||||
array.SetValue (_list [i], index + i);
|
||||
}
|
||||
public object Pop ()
|
||||
{
|
||||
if (_list.Count == 0) return null;
|
||||
var last = _list [_list.Count - 1];
|
||||
_list.RemoveAt (_list.Count - 1);
|
||||
return last;
|
||||
}
|
||||
public object Shift ()
|
||||
{
|
||||
if (_list.Count == 0) return null;
|
||||
var first = _list [0];
|
||||
_list.RemoveAt (0);
|
||||
return first;
|
||||
}
|
||||
public void Unshift (object value) => _list.Insert (0, value);
|
||||
public void Dispose ()
|
||||
{
|
||||
_list?.Clear ();
|
||||
_list = null;
|
||||
}
|
||||
public object Get (int index) => this [index];
|
||||
public object Set (int index, object value) => this [index] = value;
|
||||
public object At (int index) => this [index];
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
public const int LOCALE_SSHORTESTSCRIPT = 0x0000004F; // 获取四字母脚本代码
|
||||
public const uint KLF_ACTIVATE = 0x00000001; // 激活键盘布局
|
||||
// GetLocaleInfoW for LCID-based queries
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int GetLocaleInfoW (int Locale, int LCType, [Out] StringBuilder lpLCData, int cchData);
|
||||
|
||||
// GetLocaleInfoEx for locale name based queries
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int GetLocaleInfoEx (string lpLocaleName, int LCType, [Out] StringBuilder lpLCData, int cchData);
|
||||
|
||||
// LocaleNameToLCID - available on Vista+; fallback is to use CultureInfo
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int LocaleNameToLCID (string lpName, uint dwFlags);
|
||||
|
||||
// LCIDToLocaleName (Vista+)
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int LCIDToLocaleName (int Locale, [Out] StringBuilder lpName, int cchName, uint dwFlags);
|
||||
[DllImport ("user32.dll")]
|
||||
public static extern IntPtr GetKeyboardLayout (uint dwLayout);
|
||||
[DllImport ("user32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern IntPtr LoadKeyboardLayout (string pwszKLID, uint Flags);
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Language: System.Globalization.CultureInfo
|
||||
{
|
||||
public _I_Language (string localeName) : base (localeName) { }
|
||||
public string AbbreviatedName => this.ThreeLetterISOLanguageName;
|
||||
public string LanguageTag => this.IetfLanguageTag ?? this.Name;
|
||||
public int LayoutDirection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (base.TextInfo.IsRightToLeft) return 1;
|
||||
string tag = this.LanguageTag;
|
||||
bool isVerticalCandidate = false;
|
||||
if (tag != null)
|
||||
{
|
||||
var scriptMatch = Regex.Match (tag, @"-([A-Za-z]{4})(?:-|$)");
|
||||
if (scriptMatch.Success)
|
||||
{
|
||||
string script = scriptMatch.Groups [1].Value;
|
||||
if (script == "Hani" || script == "Hira" || script == "Kana" || script == "Jpan" || script == "Kore" || script == "Hans" || script == "Hant")
|
||||
isVerticalCandidate = true;
|
||||
}
|
||||
if (!isVerticalCandidate)
|
||||
{
|
||||
var regionMatch = Regex.Match (tag, @"-([A-Za-z]{2})$");
|
||||
if (regionMatch.Success)
|
||||
{
|
||||
string region = regionMatch.Groups [1].Value.ToUpperInvariant ();
|
||||
if (region == "JP" || region == "CN" || region == "TW" || region == "HK" || region == "MO" || region == "KR")
|
||||
isVerticalCandidate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isVerticalCandidate)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public string Script
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder sb = new StringBuilder (10);
|
||||
if (NativeMethods.GetLocaleInfoEx (this.Name, NativeMethods.LOCALE_SSHORTESTSCRIPT, sb, sb.Capacity) > 0)
|
||||
return sb.ToString ();
|
||||
|
||||
// 如果失败,尝试从语言标记中解析脚本子标记(如 "zh-Hans-CN" 中的 "Hans")
|
||||
var match = Regex.Match (this.Name, @"-([A-Za-z]{4})(?:-|$)");
|
||||
if (match.Success)
|
||||
return match.Groups [1].Value;
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
public _I_List GetExtensionSubtags (string singleton)
|
||||
{
|
||||
if (string.IsNullOrEmpty (singleton) || singleton.Length != 1)
|
||||
throw new ArgumentException ("Singleton must be a single character", nameof (singleton));
|
||||
var subtags = new List<string> ();
|
||||
string tag = this.LanguageTag;
|
||||
string pattern = $@"-{Regex.Escape (singleton)}-([a-zA-Z0-9](?:-[a-zA-Z0-9]+)*)";
|
||||
var match = Regex.Match (tag, pattern);
|
||||
if (match.Success)
|
||||
{
|
||||
string extPart = match.Groups [1].Value;
|
||||
subtags.AddRange (extPart.Split ('-'));
|
||||
}
|
||||
return new _I_List (subtags.Select (i => (object)i));
|
||||
}
|
||||
public bool TrySetInputMethodLanguageTag (string languageTag)
|
||||
{
|
||||
int lcid = NativeMethods.LocaleNameToLCID (languageTag, 0);
|
||||
if (lcid == 0)
|
||||
return false;
|
||||
string klid = $"{lcid:X8}";
|
||||
IntPtr hkl = NativeMethods.LoadKeyboardLayout (klid, NativeMethods.KLF_ACTIVATE);
|
||||
return hkl != IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Locale
|
||||
@@ -47,7 +134,6 @@ namespace DataUtils
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Current LCID (int)
|
||||
public int CurrentLCID
|
||||
{
|
||||
@@ -63,7 +149,6 @@ namespace DataUtils
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert LCID -> locale name (e.g. 1033 -> "en-US")
|
||||
public string ToLocaleName (int lcid)
|
||||
{
|
||||
@@ -87,7 +172,6 @@ namespace DataUtils
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Convert locale name -> LCID
|
||||
public int ToLCID (string localeName)
|
||||
{
|
||||
@@ -111,7 +195,6 @@ namespace DataUtils
|
||||
// fallback: invariant culture
|
||||
return CultureInfo.InvariantCulture.LCID;
|
||||
}
|
||||
|
||||
// Return a locale info string for given LCID and LCTYPE. LCTYPE is the Win32 LOCALE_* constant.
|
||||
// Returns a string (or empty string on failure).
|
||||
public object LocaleInfo (int lcid, int lctype)
|
||||
@@ -177,7 +260,6 @@ namespace DataUtils
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
// LocaleInfoEx: query by locale name string and LCTYPE
|
||||
// Returns string if available; otherwise returns the integer result code (as int) if string empty (mimic C++ behavior).
|
||||
public object LocaleInfoEx (string localeName, int lctype)
|
||||
@@ -239,7 +321,6 @@ namespace DataUtils
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers similar to the C++: restricted (language) and elaborated (region) codes
|
||||
public string GetLocaleRestrictedCode (string localeName)
|
||||
{
|
||||
@@ -257,7 +338,6 @@ namespace DataUtils
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetLocaleElaboratedCode (string localeName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (localeName)) localeName = CurrentLocale;
|
||||
@@ -284,7 +364,6 @@ namespace DataUtils
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// LCID -> combined code like "en-US" (with configurable separator)
|
||||
public string LcidToLocaleCode (int lcid)
|
||||
{
|
||||
@@ -304,7 +383,6 @@ namespace DataUtils
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Get the user default locale name
|
||||
public string GetUserDefaultLocaleName ()
|
||||
{
|
||||
@@ -317,7 +395,6 @@ namespace DataUtils
|
||||
catch { }
|
||||
return LcidToLocaleCode (CultureInfo.CurrentCulture.LCID);
|
||||
}
|
||||
|
||||
// Get system default locale name (machine)
|
||||
public string GetSystemDefaultLocaleName ()
|
||||
{
|
||||
@@ -330,7 +407,6 @@ namespace DataUtils
|
||||
catch { }
|
||||
return LcidToLocaleCode (CultureInfo.InstalledUICulture.LCID);
|
||||
}
|
||||
|
||||
// Get computer locale code similar to C++ approach
|
||||
public string GetComputerLocaleCode ()
|
||||
{
|
||||
@@ -350,7 +426,38 @@ namespace DataUtils
|
||||
// fallback to invariant
|
||||
return CultureInfo.InvariantCulture.Name ?? string.Empty;
|
||||
}
|
||||
|
||||
public _I_List RecommendLocaleNames
|
||||
{
|
||||
get
|
||||
{
|
||||
var arr = new string [] {
|
||||
System.Threading.Thread.CurrentThread.CurrentCulture.Name,
|
||||
GetUserDefaultLocaleName (),
|
||||
GetSystemDefaultLocaleName (),
|
||||
LcidToLocaleCode (CurrentLCID),
|
||||
GetLocaleRestrictedCode (System.Threading.Thread.CurrentThread.CurrentCulture.Name),
|
||||
GetLocaleRestrictedCode (GetUserDefaultLocaleName ()),
|
||||
GetLocaleRestrictedCode (GetSystemDefaultLocaleName ()),
|
||||
"en-US",
|
||||
"en"
|
||||
};
|
||||
var list = new _I_List ();
|
||||
foreach (var loc in arr)
|
||||
{
|
||||
var lloc = loc.Trim ().ToLowerInvariant ();
|
||||
var isfind = false;
|
||||
foreach (var item in list)
|
||||
{
|
||||
var str = item as string;
|
||||
if (string.IsNullOrWhiteSpace (str)) isfind = true;
|
||||
isfind = str.Trim ().ToLowerInvariant () == lloc;
|
||||
if (isfind) break;
|
||||
}
|
||||
if (!isfind) list.Add (loc);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
// Compare two locale names; returns true if equal by name or LCID
|
||||
public bool LocaleNameCompare (string left, string right)
|
||||
{
|
||||
@@ -366,8 +473,62 @@ namespace DataUtils
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Constants
|
||||
private const int LOCALE_NAME_MAX_LENGTH = 85; // defined by Windows
|
||||
public _I_Language CreateLanguage (string localeName) => new _I_Language (localeName);
|
||||
public static string CurrentInputMethodLanguageTag
|
||||
{
|
||||
get
|
||||
{
|
||||
IntPtr hkl = NativeMethods.GetKeyboardLayout (0);
|
||||
int lcid = hkl.ToInt32 () & 0xFFFF;
|
||||
|
||||
StringBuilder sb = new StringBuilder (85);
|
||||
int result = NativeMethods.LCIDToLocaleName (lcid, sb, sb.Capacity, 0);
|
||||
if (result > 0)
|
||||
return sb.ToString ();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static bool IsWellFormed (string languageTag)
|
||||
{
|
||||
if (string.IsNullOrEmpty (languageTag))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
var _ = new CultureInfo (languageTag);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public static _I_List GetMuiCompatibleLanguageListFromLanguageTags (IEnumerable<string> languageTags)
|
||||
{
|
||||
var result = new List<string> ();
|
||||
foreach (string tag in languageTags)
|
||||
{
|
||||
if (string.IsNullOrEmpty (tag))
|
||||
continue;
|
||||
result.Add (tag);
|
||||
try
|
||||
{
|
||||
var ci = new CultureInfo (tag);
|
||||
string parent = ci.Parent.Name;
|
||||
if (!string.IsNullOrEmpty (parent) && parent != tag && !result.Contains (parent))
|
||||
result.Add (parent);
|
||||
}
|
||||
catch { }
|
||||
string neutral = Regex.Replace (tag, @"-.*$", "");
|
||||
if (neutral != tag && !result.Contains (neutral))
|
||||
result.Add (neutral);
|
||||
}
|
||||
if (!result.Contains ("neutral"))
|
||||
result.Add ("neutral");
|
||||
return new _I_List (result.Select (t => (object)t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +131,8 @@ namespace DataUtils
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Process
|
||||
{
|
||||
public Process Start (string filename, string args) => Process.Start (filename, args);
|
||||
public Process Open (string url) => Process.Start (url);
|
||||
public int Run (
|
||||
string cmdline,
|
||||
string filepath,
|
||||
|
||||
@@ -539,8 +539,7 @@ namespace DataUtils
|
||||
public void File (string filter, string initDir, object jsCallback)
|
||||
{
|
||||
IWin32Window owner = GetActiveWindowOwner ();
|
||||
Thread t = new Thread (() =>
|
||||
{
|
||||
Thread t = new Thread (() => {
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
@@ -565,8 +564,7 @@ namespace DataUtils
|
||||
public void Files (string filter, string initDir, object jsCallback)
|
||||
{
|
||||
IWin32Window owner = GetActiveWindowOwner ();
|
||||
Thread t = new Thread (() =>
|
||||
{
|
||||
Thread t = new Thread (() => {
|
||||
string result = "[]";
|
||||
try
|
||||
{
|
||||
@@ -591,8 +589,7 @@ namespace DataUtils
|
||||
public void Dir (string initDir, object jsCallback)
|
||||
{
|
||||
IWin32Window owner = GetActiveWindowOwner ();
|
||||
Thread t = new Thread (() =>
|
||||
{
|
||||
Thread t = new Thread (() => {
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
@@ -616,8 +613,7 @@ namespace DataUtils
|
||||
public void Dirs (string initDir, object jsCallback)
|
||||
{
|
||||
IWin32Window owner = GetActiveWindowOwner ();
|
||||
Thread t = new Thread (() =>
|
||||
{
|
||||
Thread t = new Thread (() => {
|
||||
string result = "[]";
|
||||
try
|
||||
{
|
||||
@@ -649,8 +645,71 @@ namespace DataUtils
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Folder
|
||||
{
|
||||
[DllImport ("shell32.dll")]
|
||||
private static extern int SHGetKnownFolderPath (
|
||||
[MarshalAs (UnmanagedType.LPStruct)] Guid rfid,
|
||||
uint dwFlags,
|
||||
IntPtr hToken,
|
||||
out IntPtr ppszPath);
|
||||
private static string KF (Guid g)
|
||||
{
|
||||
IntPtr p;
|
||||
SHGetKnownFolderPath (g, 0, IntPtr.Zero, out p);
|
||||
string s = Marshal.PtrToStringUni (p);
|
||||
Marshal.FreeCoTaskMem (p);
|
||||
return s;
|
||||
}
|
||||
private static readonly Guid FOLDERID_Downloads = new Guid ("374DE290-123F-4565-9164-39C4925E467B");
|
||||
private static readonly Guid FOLDERID_SavedPictures = new Guid ("3B193882-D3AD-4EAB-965A-69829D1FB59F");
|
||||
private static readonly Guid FOLDERID_SavedGames = new Guid ("4C5C32FF-BB9D-43B0-BF90-45A0FEEB6D0E");
|
||||
private static readonly Guid FOLDERID_Links = new Guid ("BFB9D5E0-C6A9-404C-B2B2-AE6DB6AF4968");
|
||||
private static readonly Guid FOLDERID_Contacts = new Guid ("56784854-C6CB-462B-8169-88E350ACB882");
|
||||
private static readonly Guid FOLDERID_Searches = new Guid ("7D1D3A04-DEBB-4115-95CF-2F29DA2920DA");
|
||||
public string ProgramFiles => Environment.GetFolderPath (Environment.SpecialFolder.ProgramFiles);
|
||||
public string ProgramFilesX86 => Environment.GetFolderPath (Environment.SpecialFolder.ProgramFilesX86);
|
||||
public string Windows => Environment.GetFolderPath (Environment.SpecialFolder.Windows);
|
||||
public string System32 => Environment.SystemDirectory;
|
||||
public string UserProfile => Environment.GetFolderPath (Environment.SpecialFolder.UserProfile);
|
||||
public string Desktop => Environment.GetFolderPath (Environment.SpecialFolder.Desktop);
|
||||
public string Documents => Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
|
||||
public string Pictures => Environment.GetFolderPath (Environment.SpecialFolder.MyPictures);
|
||||
public string Music => Environment.GetFolderPath (Environment.SpecialFolder.MyMusic);
|
||||
public string Videos => Environment.GetFolderPath (Environment.SpecialFolder.MyVideos);
|
||||
public string AppDataRoaming => Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
|
||||
public string AppDataLocal => Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData);
|
||||
public string AppDataLocalLow => Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData) + "\\Low";
|
||||
public string Temp => System.IO.Path.GetTempPath ();
|
||||
public string PublicDesktop => Environment.GetFolderPath (Environment.SpecialFolder.CommonDesktopDirectory);
|
||||
public string PublicDocuments => Environment.GetFolderPath (Environment.SpecialFolder.CommonDocuments);
|
||||
public string PublicPictures => Environment.GetFolderPath (Environment.SpecialFolder.CommonPictures);
|
||||
public string PublicMusic => Environment.GetFolderPath (Environment.SpecialFolder.CommonMusic);
|
||||
public string PublicVideos => Environment.GetFolderPath (Environment.SpecialFolder.CommonVideos);
|
||||
public string Downloads => KF (FOLDERID_Downloads);
|
||||
public string SavedPictures => KF (FOLDERID_SavedPictures);
|
||||
public string SavedGames => KF (FOLDERID_SavedGames);
|
||||
public string Links => KF (FOLDERID_Links);
|
||||
public string Contacts => KF (FOLDERID_Contacts);
|
||||
public string Searches => KF (FOLDERID_Searches);
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Storage
|
||||
{
|
||||
[DllImport ("user32.dll")]
|
||||
private static extern IntPtr GetForegroundWindow ();
|
||||
class WindowWrapper: IWin32Window
|
||||
{
|
||||
private IntPtr _hwnd;
|
||||
public WindowWrapper (IntPtr handle) { _hwnd = handle; }
|
||||
public IntPtr Handle { get { return _hwnd; } }
|
||||
}
|
||||
private static IWin32Window GetActiveWindowOwner ()
|
||||
{
|
||||
IntPtr hWnd = GetForegroundWindow ();
|
||||
return hWnd != IntPtr.Zero ? new WindowWrapper (hWnd) : null;
|
||||
}
|
||||
private static void CallJS (object jsFunc, params object [] args)
|
||||
{
|
||||
if (jsFunc == null) return;
|
||||
@@ -680,6 +739,35 @@ namespace DataUtils
|
||||
public _I_Directory GetDirectory (string path) { return new _I_Directory (path); }
|
||||
public _I_Directory GetDir (string path) { return GetDirectory (path); }
|
||||
public _I_Explorer Explorer => new _I_Explorer ();
|
||||
public void Save (string filter, string initDir, string defaultName, object jsCallback)
|
||||
{
|
||||
IWin32Window owner = GetActiveWindowOwner ();
|
||||
Thread t = new Thread (() => {
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
using (SaveFileDialog dlg = new SaveFileDialog ())
|
||||
{
|
||||
dlg.Filter = filter;
|
||||
dlg.InitialDirectory = string.IsNullOrEmpty (initDir)
|
||||
? Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)
|
||||
: initDir;
|
||||
if (!string.IsNullOrEmpty (defaultName))
|
||||
dlg.FileName = defaultName;
|
||||
dlg.OverwritePrompt = true;
|
||||
dlg.AddExtension = true;
|
||||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||||
result = dlg.FileName;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
CallJS (jsCallback, result);
|
||||
});
|
||||
t.IsBackground = true;
|
||||
t.SetApartmentState (ApartmentState.STA);
|
||||
t.Start ();
|
||||
}
|
||||
public _I_Folder Folders => new _I_Folder ();
|
||||
}
|
||||
// Small shell helpers that P/Invoke for folder retrieval using CSIDL or Known Folder GUIDs
|
||||
internal static class ShellHelpers
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
@@ -186,4 +192,428 @@ namespace DataUtils
|
||||
object BuildJSON ();
|
||||
}
|
||||
}
|
||||
public static class JsUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// 调用 JS 函数。第一个参数作为 this,其余作为 JS 函数参数。
|
||||
/// </summary>
|
||||
/// <param name="callback">JS 函数对象</param>
|
||||
/// <param name="args">JS 函数参数,可选</param>
|
||||
/// <returns>JS 函数返回值</returns>
|
||||
public static void Call (object jsFunc, params object [] args)
|
||||
{
|
||||
if (jsFunc == null) return;
|
||||
object [] invokeArgs = new object [(args?.Length ?? 0) + 1];
|
||||
invokeArgs [0] = jsFunc; // this
|
||||
if (args != null)
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
invokeArgs [i + 1] = args [i];
|
||||
jsFunc.GetType ().InvokeMember (
|
||||
"call",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsFunc,
|
||||
invokeArgs);
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[InterfaceType (ComInterfaceType.InterfaceIsDual)]
|
||||
public interface _I_IAsyncAction
|
||||
{
|
||||
_I_IAsyncAction Then (object resolve, object reject = null, object progress = null);
|
||||
void Done (object resolve, object reject = null);
|
||||
void Catch (object reject);
|
||||
bool IsCompleted { get; }
|
||||
bool IsCancelled { get; }
|
||||
bool IsError { get; }
|
||||
void Cancel ();
|
||||
void ReportProgress (object progress);
|
||||
object Error { get; }
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Task: _I_IAsyncAction
|
||||
{
|
||||
private object _result;
|
||||
private Exception _error;
|
||||
private bool _completed;
|
||||
private bool _cancelled;
|
||||
private List<object> _resolveCallbacks = new List<object> ();
|
||||
private List<object> _rejectCallbacks = new List<object> ();
|
||||
private List<object> _progressCallbacks = new List<object> ();
|
||||
private CancellationTokenSource _cts = new CancellationTokenSource ();
|
||||
public _I_Task (Func<object> func)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem (_ => {
|
||||
try
|
||||
{
|
||||
if (_cts.Token.IsCancellationRequested)
|
||||
{
|
||||
_cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_result = func ();
|
||||
_completed = true;
|
||||
|
||||
foreach (var cb in _resolveCallbacks)
|
||||
JsUtils.Call (cb, _result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_error = ex;
|
||||
foreach (var cb in _rejectCallbacks)
|
||||
JsUtils.Call (cb, ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
public _I_IAsyncAction Then (object resolve, object reject = null, object progress = null)
|
||||
{
|
||||
if (resolve != null) _resolveCallbacks.Add (resolve);
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
if (progress != null) _progressCallbacks.Add (progress);
|
||||
return this;
|
||||
}
|
||||
public void Done (object resolve, object reject = null)
|
||||
{
|
||||
if (resolve != null) _resolveCallbacks.Add (resolve);
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
}
|
||||
|
||||
public void Catch (object reject)
|
||||
{
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
}
|
||||
|
||||
public bool IsCompleted => _completed;
|
||||
public bool IsCancelled => _cancelled;
|
||||
public bool IsError => _error != null;
|
||||
|
||||
public object Error => _error;
|
||||
|
||||
public void Cancel ()
|
||||
{
|
||||
_cts.Cancel ();
|
||||
_cancelled = true;
|
||||
}
|
||||
|
||||
public void ReportProgress (object progress)
|
||||
{
|
||||
foreach (var cb in _progressCallbacks)
|
||||
JsUtils.Call (cb, progress);
|
||||
}
|
||||
|
||||
public object Result => _result;
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Thread: _I_IAsyncAction
|
||||
{
|
||||
private Thread _thread;
|
||||
private bool _completed;
|
||||
private bool _cancelled;
|
||||
private Exception _error;
|
||||
private List<object> _resolveCallbacks = new List<object> ();
|
||||
private List<object> _rejectCallbacks = new List<object> ();
|
||||
private List<object> _progressCallbacks = new List<object> ();
|
||||
private CancellationTokenSource _cts = new CancellationTokenSource ();
|
||||
|
||||
public _I_Thread (Action action)
|
||||
{
|
||||
_thread = new Thread (() => {
|
||||
try
|
||||
{
|
||||
if (_cts.Token.IsCancellationRequested)
|
||||
{
|
||||
_cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
action ();
|
||||
_completed = true;
|
||||
|
||||
foreach (var cb in _resolveCallbacks)
|
||||
JsUtils.Call (cb);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_error = ex;
|
||||
foreach (var cb in _rejectCallbacks)
|
||||
JsUtils.Call (cb, ex);
|
||||
}
|
||||
});
|
||||
_thread.IsBackground = true;
|
||||
_thread.Start ();
|
||||
}
|
||||
|
||||
public _I_IAsyncAction Then (object resolve, object reject = null, object progress = null)
|
||||
{
|
||||
if (resolve != null) _resolveCallbacks.Add (resolve);
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
if (progress != null) _progressCallbacks.Add (progress);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Done (object resolve, object reject = null)
|
||||
{
|
||||
if (resolve != null) _resolveCallbacks.Add (resolve);
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
}
|
||||
|
||||
public void Catch (object reject)
|
||||
{
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
}
|
||||
|
||||
public bool IsCompleted => _completed;
|
||||
public bool IsCancelled => _cancelled;
|
||||
public bool IsError => _error != null;
|
||||
public object Error => _error;
|
||||
|
||||
public void Cancel ()
|
||||
{
|
||||
_cts.Cancel ();
|
||||
_cancelled = true;
|
||||
}
|
||||
|
||||
public void ReportProgress (object progress)
|
||||
{
|
||||
foreach (var cb in _progressCallbacks)
|
||||
JsUtils.Call (cb, progress);
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Exception: Exception, IDisposable
|
||||
{
|
||||
private Exception bex = null;
|
||||
public _I_Exception (Exception ex) { bex = ex; }
|
||||
public _I_Exception (string message) { bex = new Exception (message); }
|
||||
public _I_Exception (string msg, Exception innerEx) { bex = new Exception (msg, innerEx); }
|
||||
public override IDictionary Data => bex.Data;
|
||||
public override Exception GetBaseException () => bex.GetBaseException ();
|
||||
public override void GetObjectData (SerializationInfo info, StreamingContext context) => bex.GetObjectData (info, context);
|
||||
public override string HelpLink
|
||||
{
|
||||
get { return bex.HelpLink; }
|
||||
set { bex.HelpLink = value; }
|
||||
}
|
||||
public override string Message => bex.Message;
|
||||
public override string Source
|
||||
{
|
||||
get { return bex.Source; }
|
||||
set { bex.Source = value; }
|
||||
}
|
||||
public override string StackTrace => bex.StackTrace;
|
||||
public override string ToString () => bex.ToString ();
|
||||
public override int GetHashCode () => bex.GetHashCode ();
|
||||
public override bool Equals (object obj) => bex.Equals (obj);
|
||||
public void Dispose () { bex = null; }
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_KeyValuePair: IDisposable
|
||||
{
|
||||
object key = null;
|
||||
object value = null;
|
||||
public _I_KeyValuePair (object k, object v)
|
||||
{
|
||||
key = k;
|
||||
value = v;
|
||||
}
|
||||
public object Key { get { return key; } set { key = value; } }
|
||||
public object Value { get { return value; } set { this.value = value; } }
|
||||
public void Dispose ()
|
||||
{
|
||||
key = null;
|
||||
value = null;
|
||||
}
|
||||
~_I_KeyValuePair ()
|
||||
{
|
||||
key = null;
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_WwwFormUrlDecoder
|
||||
{
|
||||
private readonly Dictionary<string, string> _params = new Dictionary<string, string> ();
|
||||
public _I_WwwFormUrlDecoder (string query)
|
||||
{
|
||||
if (string.IsNullOrEmpty (query)) return;
|
||||
if (query.StartsWith ("?")) query = query.Substring (1);
|
||||
foreach (var pair in query.Split ('&'))
|
||||
{
|
||||
var kv = pair.Split ('=');
|
||||
if (kv.Length == 2)
|
||||
_params [Uri.UnescapeDataString (kv [0])] = Uri.UnescapeDataString (kv [1]);
|
||||
}
|
||||
}
|
||||
public string GetFirstValueByName (string name)
|
||||
{
|
||||
string value = null;
|
||||
return _params.TryGetValue (name, out value) ? value : null;
|
||||
}
|
||||
public int Size => _params.Count;
|
||||
public _I_KeyValuePair GetAt (uint index)
|
||||
{
|
||||
var pair = _params.ElementAt ((int)index);
|
||||
return new _I_KeyValuePair (pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Uri: Uri
|
||||
{
|
||||
public _I_Uri (string uri): base (uri) { }
|
||||
public _I_Uri (string baseUri, string relativeUri) : base (new Uri (baseUri), relativeUri) { }
|
||||
public string AbsoluteCanonicalUri => this.GetLeftPart (UriPartial.Authority) + this.PathAndQuery + this.Fragment;
|
||||
public string DisplayIri => Uri.UnescapeDataString (this.OriginalString);
|
||||
public string DisplayUri => Uri.UnescapeDataString (this.OriginalString);
|
||||
public string Domain => ExtractDomain (this.Host);
|
||||
public string Extension => System.IO.Path.GetExtension (this.AbsolutePath)?.TrimStart ('.') ?? "";
|
||||
public string Password => ExtractPassword (this.UserInfo);
|
||||
public string Path => this.AbsolutePath;
|
||||
public object QueryParsed => new _I_WwwFormUrlDecoder (this.Query);
|
||||
public string RawUri => this.OriginalString;
|
||||
public string SchemeName => this.Scheme;
|
||||
public bool Suspicious => !Uri.IsWellFormedUriString (this.OriginalString, UriKind.Absolute);
|
||||
public string UserName => ExtractUserName (this.UserInfo);
|
||||
public _I_Uri CombineUri (string relativeUri)
|
||||
{
|
||||
return new _I_Uri (this.AbsoluteUri, relativeUri);
|
||||
}
|
||||
public static string EscapeComponent (string component)
|
||||
{
|
||||
return Uri.EscapeDataString (component);
|
||||
}
|
||||
public static string UnescapeComponent (string component)
|
||||
{
|
||||
return Uri.UnescapeDataString (component);
|
||||
}
|
||||
private static string ExtractDomain (string host)
|
||||
{
|
||||
var parts = host.Split ('.');
|
||||
if (parts.Length >= 2)
|
||||
return string.Join (".", parts.Skip (1));
|
||||
return host;
|
||||
}
|
||||
private static string ExtractUserName (string userInfo)
|
||||
{
|
||||
if (string.IsNullOrEmpty (userInfo)) return "";
|
||||
var parts = userInfo.Split (':');
|
||||
return parts [0];
|
||||
}
|
||||
private static string ExtractPassword (string userInfo)
|
||||
{
|
||||
if (string.IsNullOrEmpty (userInfo)) return "";
|
||||
var parts = userInfo.Split (':');
|
||||
return parts.Length > 1 ? parts [1] : "";
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Utilities
|
||||
{
|
||||
public _I_Uri CreateUri (string uri) => new _I_Uri (uri);
|
||||
public _I_Uri CreateUri2 (string baseUri, string relaUri) => new _I_Uri (baseUri, relaUri);
|
||||
public _I_Exception CreateException (string message) => new _I_Exception (message);
|
||||
public _I_Exception CreateException2 (string message, _I_Exception innerEx) => new _I_Exception (message, innerEx);
|
||||
public _I_Calendar CreateCalendar () => new _I_Calendar ();
|
||||
public _I_Calendar CreateCalendar2 (object list) => new _I_Calendar (list);
|
||||
public _I_Calendar CreateCalendar3 (object list, string arg1, string arg2) => new _I_Calendar (list, arg1, arg2);
|
||||
public _I_Calendar CreateCalendar4 (object list, string arg1, string arg2, string arg3) => new _I_Calendar (list, arg1, arg2, arg3);
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromTemplate (string formatTemplate)
|
||||
{
|
||||
return new _I_DateTimeFormatter (formatTemplate);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromTemplateAndLanguages (string formatTemplate, object languagesArray)
|
||||
{
|
||||
List<string> languages = JsArrayToStringList (languagesArray);
|
||||
return new _I_DateTimeFormatter (formatTemplate, languages);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromTemplateFull (string formatTemplate, object languagesArray,
|
||||
string geographicRegion, string calendar, string clock)
|
||||
{
|
||||
List<string> languages = JsArrayToStringList (languagesArray);
|
||||
return new _I_DateTimeFormatter (formatTemplate, languages, geographicRegion, calendar, clock);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromDateEnums (int year, int month, int day, int dayOfWeek)
|
||||
{
|
||||
return new _I_DateTimeFormatter (
|
||||
(YearFormat)year,
|
||||
(MonthFormat)month,
|
||||
(DayFormat)day,
|
||||
(DayOfWeekFormat)dayOfWeek
|
||||
);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromTimeEnums (int hour, int minute, int second)
|
||||
{
|
||||
return new _I_DateTimeFormatter (
|
||||
(HourFormat)hour,
|
||||
(MinuteFormat)minute,
|
||||
(SecondFormat)second
|
||||
);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromDateTimeEnums (int year, int month, int day, int dayOfWeek,
|
||||
int hour, int minute, int second, object languagesArray)
|
||||
{
|
||||
List<string> languages = JsArrayToStringList (languagesArray);
|
||||
return new _I_DateTimeFormatter (
|
||||
(YearFormat)year,
|
||||
(MonthFormat)month,
|
||||
(DayFormat)day,
|
||||
(DayOfWeekFormat)dayOfWeek,
|
||||
(HourFormat)hour,
|
||||
(MinuteFormat)minute,
|
||||
(SecondFormat)second,
|
||||
languages
|
||||
);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromDateTimeEnumsFull (int year, int month, int day, int dayOfWeek,
|
||||
int hour, int minute, int second, object languagesArray,
|
||||
string geographicRegion, string calendar, string clock)
|
||||
{
|
||||
List<string> languages = JsArrayToStringList (languagesArray);
|
||||
return new _I_DateTimeFormatter (
|
||||
(YearFormat)year,
|
||||
(MonthFormat)month,
|
||||
(DayFormat)day,
|
||||
(DayOfWeekFormat)dayOfWeek,
|
||||
(HourFormat)hour,
|
||||
(MinuteFormat)minute,
|
||||
(SecondFormat)second,
|
||||
languages,
|
||||
geographicRegion,
|
||||
calendar,
|
||||
clock
|
||||
);
|
||||
}
|
||||
private List<string> JsArrayToStringList (object jsArray)
|
||||
{
|
||||
var result = new List<string> ();
|
||||
if (jsArray == null) return result;
|
||||
|
||||
Type type = jsArray.GetType ();
|
||||
try
|
||||
{
|
||||
int length = (int)type.InvokeMember ("length", BindingFlags.GetProperty, null, jsArray, null);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
object value = type.InvokeMember (i.ToString (), BindingFlags.GetProperty, null, jsArray, null);
|
||||
if (value != null)
|
||||
result.Add (value.ToString ());
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 如果无法获取 length,则假设是单个字符串
|
||||
string single = jsArray.ToString ();
|
||||
if (!string.IsNullOrEmpty (single))
|
||||
result.Add (single);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
328
DataUtils/Web.cs
Normal file
@@ -0,0 +1,328 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[InterfaceType (ComInterfaceType.InterfaceIsDual)]
|
||||
public interface IHttpResponse: IDisposable
|
||||
{
|
||||
int Status { get; } // 兼容旧版,等同于 StatusCode
|
||||
int StatusCode { get; }
|
||||
string StatusText { get; } // 等同于 StatusDescription
|
||||
string StatusDescription { get; }
|
||||
string ResponseUrl { get; }
|
||||
Uri ResponseUri { get; }
|
||||
string ContentType { get; }
|
||||
long ContentLength { get; } // 注意:JS 中 Number 可表示 2^53 以内整数
|
||||
string CharacterSet { get; }
|
||||
string ContentEncoding { get; }
|
||||
DateTime LastModified { get; }
|
||||
string Method { get; } // 原始请求方法 (GET, POST...)
|
||||
Version ProtocolVersion { get; } // 如 1.1,JS 中可能转为字符串
|
||||
bool IsFromCache { get; }
|
||||
bool IsMutuallyAuthenticated { get; }
|
||||
string Text ();
|
||||
_I_Enumerable Bytes ();
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class HttpResponse: IHttpResponse, IDisposable
|
||||
{
|
||||
private readonly byte [] _data;
|
||||
private readonly Dictionary<string, string> _headersDict;
|
||||
private bool _disposed = false;
|
||||
public int Status => StatusCode;
|
||||
public int StatusCode { get; private set; }
|
||||
public string StatusText => StatusDescription;
|
||||
public string StatusDescription { get; private set; }
|
||||
public string ResponseUrl => ResponseUri?.ToString ();
|
||||
public Uri ResponseUri { get; private set; }
|
||||
public string ContentType { get; private set; }
|
||||
public long ContentLength { get; private set; }
|
||||
public string CharacterSet { get; private set; }
|
||||
public string ContentEncoding { get; private set; }
|
||||
public DateTime LastModified { get; private set; }
|
||||
public string Method { get; private set; }
|
||||
public Version ProtocolVersion { get; private set; }
|
||||
public bool IsFromCache { get; private set; }
|
||||
public bool IsMutuallyAuthenticated { get; private set; }
|
||||
public HttpResponse (HttpWebResponse response)
|
||||
{
|
||||
if (response == null) throw new ArgumentNullException (nameof (response));
|
||||
using (var stream = response.GetResponseStream ())
|
||||
using (var ms = new MemoryStream ())
|
||||
{
|
||||
stream.CopyTo (ms);
|
||||
_data = ms.ToArray ();
|
||||
}
|
||||
StatusCode = (int)response.StatusCode;
|
||||
StatusDescription = response.StatusDescription;
|
||||
ResponseUri = response.ResponseUri;
|
||||
Method = response.Method;
|
||||
ProtocolVersion = new Version ((ushort)response.ProtocolVersion.Major, (ushort)response.ProtocolVersion.Minor, (ushort)response.ProtocolVersion.Build, (ushort)response.ProtocolVersion.Revision);
|
||||
IsFromCache = response.IsFromCache;
|
||||
IsMutuallyAuthenticated = response.IsMutuallyAuthenticated;
|
||||
ContentType = response.ContentType ?? "";
|
||||
ContentLength = response.ContentLength;
|
||||
CharacterSet = response.CharacterSet ?? "";
|
||||
ContentEncoding = response.ContentEncoding ?? "";
|
||||
LastModified = response.LastModified;
|
||||
_headersDict = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
|
||||
foreach (string key in response.Headers.AllKeys)
|
||||
{
|
||||
if (!string.IsNullOrEmpty (key))
|
||||
_headersDict [key] = response.Headers [key];
|
||||
}
|
||||
}
|
||||
public HttpResponse (int statusCode, string statusDescription, string responseUrl, byte [] data, Dictionary<string, string> headers)
|
||||
{
|
||||
StatusCode = statusCode;
|
||||
StatusDescription = statusDescription ?? "";
|
||||
ResponseUri = string.IsNullOrEmpty (responseUrl) ? null : new Uri (responseUrl);
|
||||
_data = data ?? new byte [0];
|
||||
_headersDict = headers ?? new Dictionary<string, string> ();
|
||||
ContentType = GetHeader ("Content-Type") ?? "";
|
||||
ContentLength = _data.Length;
|
||||
CharacterSet = "";
|
||||
ContentEncoding = "";
|
||||
LastModified = DateTime.MinValue;
|
||||
Method = "";
|
||||
ProtocolVersion = new Version (0, 0);
|
||||
IsFromCache = false;
|
||||
IsMutuallyAuthenticated = false;
|
||||
}
|
||||
public string GetHeader (string sName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (sName)) return null;
|
||||
try
|
||||
{
|
||||
return _headersDict [sName];
|
||||
}
|
||||
catch { return null; }
|
||||
}
|
||||
public string GetHeadersToJson ()
|
||||
{
|
||||
return JsonConvert.SerializeObject (_headersDict);
|
||||
}
|
||||
public string Text ()
|
||||
{
|
||||
string charset = CharacterSet;
|
||||
Encoding enc = Encoding.UTF8;
|
||||
if (!string.IsNullOrEmpty (charset))
|
||||
{
|
||||
try { enc = Encoding.GetEncoding (charset); }
|
||||
catch { /* 保持 UTF-8 */ }
|
||||
}
|
||||
return enc.GetString (_data);
|
||||
}
|
||||
public _I_Enumerable Bytes ()
|
||||
{
|
||||
var list = new List<object> ();
|
||||
foreach (byte b in _data)
|
||||
list.Add (b);
|
||||
return new _I_List (list);
|
||||
}
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class HttpRequest: IDisposable
|
||||
{
|
||||
private string _method;
|
||||
private string _url;
|
||||
private Dictionary<string, string> _headers = new Dictionary<string, string> ();
|
||||
public int Timeout { get; set; } = 100000; // 毫秒,默认 100 秒
|
||||
public int ReadWriteTimeout { get; set; } = 300000; // 读写超时,默认 5 分钟
|
||||
public bool AllowAutoRedirect { get; set; } = true;
|
||||
public bool AllowWriteStreamBuffering { get; set; } = true;
|
||||
public bool KeepAlive { get; set; } = true;
|
||||
public int MaximumAutomaticRedirections { get; set; } = 50;
|
||||
public string UserAgent
|
||||
{
|
||||
get { return GetHeader ("User-Agent"); }
|
||||
set { SetHeader ("User-Agent", value); }
|
||||
}
|
||||
public string Referer
|
||||
{
|
||||
get { return GetHeader ("Referer"); }
|
||||
set { SetHeader ("Referer", value); }
|
||||
}
|
||||
public string ContentType
|
||||
{
|
||||
get { return GetHeader ("Content-Type"); }
|
||||
set { SetHeader ("Content-Type", value); }
|
||||
}
|
||||
public string Accept
|
||||
{
|
||||
get { return GetHeader ("Accept"); }
|
||||
set { SetHeader ("Accept", value); }
|
||||
}
|
||||
public IWebProxy Proxy { get; set; } = null;
|
||||
public CookieContainer CookieContainer { get; set; } = null;
|
||||
private string _httpver = "1.1";
|
||||
public string ProtocolVersion
|
||||
{
|
||||
get { return _httpver; }
|
||||
set { _httpver = value; }
|
||||
}
|
||||
public System.Version ProtVer
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (_httpver)
|
||||
{
|
||||
case "1.0": return HttpVersion.Version10;
|
||||
default:
|
||||
case "1.1": return HttpVersion.Version11;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool PreAuthenticate { get; set; } = false;
|
||||
public ICredentials Credentials { get; set; } = null;
|
||||
public bool AutomaticDecompression { get; set; } = false;
|
||||
public Action<long, long> UploadProgressCallback { get; set; } = null;
|
||||
public void Open (string sMethod, string sUrl)
|
||||
{
|
||||
_method = sMethod;
|
||||
_url = sUrl;
|
||||
}
|
||||
public void SetHeader (string sName, string sValue) => _headers [sName] = sValue;
|
||||
public string GetHeader (string sName) => _headers [sName];
|
||||
public string GetHeadersToJson () => JsonConvert.SerializeObject (_headers);
|
||||
public void RemoveHeader (string sName) => _headers.Remove (sName);
|
||||
public void ClearHeader () => _headers.Clear ();
|
||||
public IHttpResponse Send (string sBody, string encoding)
|
||||
{
|
||||
var req = (HttpWebRequest)WebRequest.Create (_url);
|
||||
req.Method = _method;
|
||||
req.Timeout = Timeout;
|
||||
req.ReadWriteTimeout = ReadWriteTimeout;
|
||||
req.AllowAutoRedirect = AllowAutoRedirect;
|
||||
req.AllowWriteStreamBuffering = AllowWriteStreamBuffering;
|
||||
req.KeepAlive = KeepAlive;
|
||||
req.MaximumAutomaticRedirections = MaximumAutomaticRedirections;
|
||||
if (Proxy != null) req.Proxy = Proxy;
|
||||
if (CookieContainer != null) req.CookieContainer = CookieContainer;
|
||||
req.ProtocolVersion = ProtVer;
|
||||
req.PreAuthenticate = PreAuthenticate;
|
||||
if (Credentials != null) req.Credentials = Credentials;
|
||||
if (AutomaticDecompression)
|
||||
req.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
||||
if (_headers.ContainsKey ("User-Agent"))
|
||||
req.UserAgent = _headers ["User-Agent"];
|
||||
foreach (var h in _headers)
|
||||
{
|
||||
if (string.Equals (h.Key, "User-Agent", StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
if (string.Equals (h.Key, "Content-Type", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string ct = h.Value;
|
||||
if (!string.IsNullOrEmpty (sBody) && !ct.Contains ("charset"))
|
||||
{
|
||||
Encoding enc = Encoding.GetEncoding (encoding);
|
||||
ct = ct + "; charset=" + enc.WebName;
|
||||
}
|
||||
req.ContentType = ct;
|
||||
}
|
||||
else if (string.Equals (h.Key, "Accept", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
req.Accept = h.Value;
|
||||
}
|
||||
else if (string.Equals (h.Key, "Referer", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
req.Referer = h.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
req.Headers [h.Key] = h.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有显式设置 Content-Type 且是 POST/PUT 且有请求体,设置默认值
|
||||
bool hasContentType = _headers.Keys.Any (k => string.Equals (k, "Content-Type", StringComparison.OrdinalIgnoreCase));
|
||||
if (!hasContentType && (string.Equals (_method, "POST", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals (_method, "PUT", StringComparison.OrdinalIgnoreCase)) &&
|
||||
!string.IsNullOrEmpty (sBody))
|
||||
{
|
||||
Encoding enc = Encoding.GetEncoding (encoding);
|
||||
req.ContentType = "application/x-www-form-urlencoded; charset=" + enc.WebName;
|
||||
}
|
||||
|
||||
// 写入请求体
|
||||
if (!string.IsNullOrEmpty (sBody))
|
||||
{
|
||||
Encoding enc = Encoding.GetEncoding (encoding);
|
||||
byte [] bytes = enc.GetBytes (sBody);
|
||||
req.ContentLength = bytes.Length;
|
||||
using (var stream = req.GetRequestStream ())
|
||||
{
|
||||
if (UploadProgressCallback != null)
|
||||
{
|
||||
int totalWritten = 0;
|
||||
int bufferSize = 8192;
|
||||
for (int offset = 0; offset < bytes.Length; offset += bufferSize)
|
||||
{
|
||||
int chunkSize = Math.Min (bufferSize, bytes.Length - offset);
|
||||
stream.Write (bytes, offset, chunkSize);
|
||||
totalWritten += chunkSize;
|
||||
UploadProgressCallback (totalWritten, bytes.Length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.Write (bytes, 0, bytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
using (var res = (HttpWebResponse)req.GetResponse ())
|
||||
{
|
||||
return new HttpResponse (res);
|
||||
}
|
||||
}
|
||||
public void SendAsync (string sBody, string encoding, object pfResolve, object pfReject)
|
||||
{
|
||||
System.Threading.ThreadPool.QueueUserWorkItem (delegate
|
||||
{
|
||||
try
|
||||
{
|
||||
JsUtils.Call (pfResolve, Send (sBody, encoding));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
JsUtils.Call (pfReject, new _I_Exception (ex));
|
||||
}
|
||||
});
|
||||
}
|
||||
public void Dispose () { }
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Http
|
||||
{
|
||||
public HttpRequest CreateHttpRequest () => new HttpRequest ();
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Web
|
||||
{
|
||||
public _I_Http Http => new _I_Http ();
|
||||
}
|
||||
}
|
||||
17
LICENSE.SharpZipLib
Normal file
@@ -0,0 +1,17 @@
|
||||
Copyright © 2000-2018 SharpZipLib Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@@ -28,7 +28,7 @@
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
@@ -51,7 +51,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
@@ -59,7 +59,7 @@
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
|
||||
83
PkgCLI/PkgCLI.csproj
Normal file
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{8D333AF6-E901-4301-B3EE-923088E81062}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PkgCLI</RootNamespace>
|
||||
<AssemblyName>PkgCLI</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AppxPackage\AppxPackage.csproj">
|
||||
<Project>{bd681a4f-eb60-4bb8-90b5-65968fc7da59}</Project>
|
||||
<Name>AppxPackage</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\PrivateInit\PrivateInit.csproj">
|
||||
<Project>{8e708d9a-6325-4aa9-b5a5-d1b5eca8eef7}</Project>
|
||||
<Name>PrivateInit</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
14
PkgCLI/Program.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace PkgCLI
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main (string [] args)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
36
PkgCLI/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle ("PkgCLI")]
|
||||
[assembly: AssemblyDescription ("")]
|
||||
[assembly: AssemblyConfiguration ("")]
|
||||
[assembly: AssemblyCompany ("")]
|
||||
[assembly: AssemblyProduct ("PkgCLI")]
|
||||
[assembly: AssemblyCopyright ("Copyright © 2026")]
|
||||
[assembly: AssemblyTrademark ("")]
|
||||
[assembly: AssemblyCulture ("")]
|
||||
|
||||
//将 ComVisible 设置为 false 将使此程序集中的类型
|
||||
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible (false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid ("8d333af6-e901-4301-b3ee-923088e81062")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
|
||||
// 方法是按如下所示使用“*”: :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion ("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion ("1.0.0.0")]
|
||||
@@ -15,7 +15,7 @@
|
||||
<h2>Attention</h2>
|
||||
<ul>
|
||||
<li><del>This program is an x86 program, not an ARM application, not cross-platform, and cannot be used on Windows RT.</del></li>
|
||||
<li>This program uses some third-party libraries and other Github projects, and is completed using AI (ChatGTP). This project can be used for learning and communication purposes.</li>
|
||||
<li>The program uses some third-party libraries and other GitHub projects, and is completed with the assistance of AI (ChatGTP). This project can be used for learning and communication purposes.</li>
|
||||
<li>(Important) Internet Explorer must support TLS 1.2 (requiring the use of IE's XMLHttpRequest to retrieve update information), especially IE10. You can do this by opening the "Advanced" tab in Control Panel/Internet Explorer's "Internet Options," finding "Use TLS 1.2" and checking the box, then clicking "OK" and saving. The settings will take effect the next time you open the browser.<br><img width="300" height="395" alt="屏幕截图 2025-12-08 103450" src="https://github.com/user-attachments/assets/69ee21ca-7f47-4d56-8dde-37e5704776c1" /></li>
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
@@ -18,10 +18,6 @@ namespace Reader
|
||||
static void Main ()
|
||||
{
|
||||
Directory.SetCurrentDirectory (AppDomain.CurrentDomain.BaseDirectory);
|
||||
AppxPackage.PackageReader.AddApplicationItem ("SmallLogo");
|
||||
AppxPackage.PackageReader.AddApplicationItem ("Square30x30Logo");
|
||||
AppxPackage.PackageReader.AddApplicationItem ("Logo");
|
||||
AppxPackage.PackageReader.AddApplicationItem ("Square44x44Logo");
|
||||
DataUtils.BrowserEmulation.SetWebBrowserEmulation ();
|
||||
Application.EnableVisualStyles ();
|
||||
Application.SetCompatibleTextRenderingDefault (false);
|
||||
|
||||
BIN
Reader/Project2.ico
Normal file
|
After Width: | Height: | Size: 359 KiB |
@@ -30,7 +30,7 @@
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
@@ -53,6 +53,27 @@
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Project2.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
@@ -152,6 +173,9 @@
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Project2.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
4
Reader/ReaderShell.Designer.cs
generated
@@ -31,14 +31,14 @@
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ReaderShell));
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// ManagerShell
|
||||
// ReaderShell
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(657, 414);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Location = new System.Drawing.Point(0, 0);
|
||||
this.Name = "ManagerShell";
|
||||
this.Name = "ReaderShell";
|
||||
this.PageScale = 125;
|
||||
this.Text = "Form1";
|
||||
this.WindowIcon = ((System.Drawing.Icon)(resources.GetObject("$this.WindowIcon")));
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Reader
|
||||
}
|
||||
catch { }
|
||||
InitSize ();
|
||||
Text = Bridge.ResXmlStore.StringRes.Get ("MANAGER_APPTITLE");
|
||||
Text = Bridge.ResXmlStore.StringRes.Get ("READER_APPTITLE");
|
||||
this.Load += Form_Load;
|
||||
}
|
||||
private void InitSize ()
|
||||
|
||||
21141
Reader/ReaderShell.resx
@@ -71,6 +71,45 @@ Original Project:
|
||||
License: MIT License
|
||||
License File: LICENSE.WinJS
|
||||
|
||||
----------------------------------------------------------------------
|
||||
CodeMirror
|
||||
----------------------------------------------------------------------
|
||||
|
||||
This product includes CodeMirror, which is licensed under the MIT License.
|
||||
|
||||
Original Project:
|
||||
Name: CodeMirror
|
||||
Author: Marijn Haverbeke and contributors
|
||||
Project Homepage: https://codemirror.net/
|
||||
License: MIT License
|
||||
License File: LICENSE.CodeMirror
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Json.NET (Newtonsoft.Json)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
This product includes Json.NET (also known as Newtonsoft.Json), which is licensed under the MIT License.
|
||||
|
||||
Original Project:
|
||||
Name: Json.NET
|
||||
Author: James Newton-King
|
||||
Project Homepage: https://www.newtonsoft.com/json
|
||||
License: MIT License
|
||||
License File: LICENSE.Newtonsoft.Json
|
||||
|
||||
----------------------------------------------------------------------
|
||||
SharpZipLib
|
||||
----------------------------------------------------------------------
|
||||
|
||||
This product includes SharpZipLib, which is licensed under the MIT License.
|
||||
|
||||
Original Project:
|
||||
Name: SharpZipLib
|
||||
Author: SharpZipLib Contributors
|
||||
Project Homepage: https://icsharpcode.github.io/SharpZipLib/
|
||||
License: MIT License
|
||||
License File: LICENSE.SharpZipLib
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
End of notices.
|
||||
|
||||
@@ -60,9 +60,9 @@ namespace WAShell
|
||||
if (!issetdpi)
|
||||
{
|
||||
issetdpi = true;
|
||||
ExecScript ("Bridge.Frame.scale = Bridge.Frame.scale * Bridge.UI.dpi");
|
||||
ExecScript ("if (typeof Bridge !== \"undefined\") Bridge.Frame.scale = Bridge.Frame.scale * Bridge.UI.dpi");
|
||||
}
|
||||
ExecScript ("Windows.UI.DPI.mode = 1");
|
||||
ExecScript ("if (typeof Windows !== \"undefined\") Windows.UI.DPI.mode = 1");
|
||||
if (e.Url.ToString () == webui.Url.ToString ())
|
||||
{
|
||||
splash.FadeOut ();
|
||||
|
||||
@@ -49,6 +49,17 @@ bool IsURI (const std::wstring &str)
|
||||
}
|
||||
catch (...) { return false; }
|
||||
}
|
||||
std::wstring TrimQuotes (const std::wstring& str) {
|
||||
if (str.empty ()) return str;
|
||||
size_t len = str.size ();
|
||||
size_t start = (str.front () == L'"') ? 1 : 0;
|
||||
size_t end = len;
|
||||
if (str.back () == L'"')
|
||||
{
|
||||
if (end > start) end = len - 1;
|
||||
}
|
||||
return str.substr (start, end - start);
|
||||
}
|
||||
enum class paramtype
|
||||
{
|
||||
string,
|
||||
@@ -87,7 +98,8 @@ void ParseCmdArgs (LPWSTR *argv, DWORD argc, std::map <cmdkey, cmdvalue> &parser
|
||||
arg = arg.trim ();
|
||||
if (IsFile (arg)) parseresult [cmdkey (arg, paramtype::file)] = cmdvalue {L"", paramtype::file, true};
|
||||
else if (IsURI (arg)) parseresult [cmdkey (arg, paramtype::uri)] = cmdvalue {L"", paramtype::uri, true};
|
||||
else
|
||||
else if (IsFile (TrimQuotes (arg))) parseresult [cmdkey (TrimQuotes (arg), paramtype::file)] = cmdvalue { L"", paramtype::file, true };
|
||||
else
|
||||
{
|
||||
for (auto &it : g_argslist)
|
||||
{
|
||||
@@ -140,6 +152,11 @@ void ParseCmdArgs (LPWSTR *argv, DWORD argc, std::map <cmdkey, cmdvalue> &parser
|
||||
auto value = rightpart.substr (valuehead);
|
||||
paramtype ptype = paramtype::string;
|
||||
if (IsFile (value)) ptype = paramtype::file;
|
||||
else if (IsFile (TrimQuotes (value)))
|
||||
{
|
||||
value = TrimQuotes (value);
|
||||
ptype = paramtype::file;
|
||||
}
|
||||
else if (IsURI (StringTrim (value))) ptype = paramtype::uri;
|
||||
parseresult [cmdkey (it.uniquelabel, paramtype::string)] = cmdvalue {value, ptype, false};
|
||||
}
|
||||
|
||||
@@ -502,6 +502,7 @@ namespace Win32
|
||||
using namespace System;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType::AutoDual)]
|
||||
public ref class Key
|
||||
{
|
||||
private:
|
||||
@@ -523,6 +524,7 @@ namespace Win32
|
||||
);
|
||||
return CStringToMPString (res);
|
||||
}
|
||||
Object ^GetWithDefault (Object ^dflt) { return Get (dflt); }
|
||||
Object ^Get ()
|
||||
{
|
||||
auto res = GetPrivateProfileStringW (
|
||||
|
||||
@@ -39,7 +39,7 @@ enum class CMDPARAM: DWORD
|
||||
{
|
||||
NONE = 0b000,
|
||||
SILENT = 0b001,
|
||||
VERYSILENT = 0b011,
|
||||
VERYSILENT = 0b010,
|
||||
MULTIPLE = 0b100
|
||||
};
|
||||
|
||||
@@ -1810,6 +1810,8 @@ std::vector <std::wstring> LoadFileListW (const std::wstring &filePath)
|
||||
{
|
||||
if (!line.empty () && line.back () == L'\r') line.pop_back ();
|
||||
if (!line.empty () && !std::wnstring::empty (line) && IsFileExists (line)) result.push_back (line);
|
||||
auto fullFile = CombinePath (GetFileDirectoryW (filePath), line);
|
||||
if (!line.empty () && !std::wnstring::empty (fullFile) && IsFileExists (fullFile)) result.push_back (fullFile);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1844,7 +1846,7 @@ DWORD CmdMapsToFlags (std::map <cmdkey, cmdvalue> cmdpairs, std::vector <std::wn
|
||||
auto &key = it.first;
|
||||
auto &value = it.second;
|
||||
if (key.key.equals (L"silent")) dwret |= (DWORD)CMDPARAM::SILENT;
|
||||
else if (key.key.equals (L"verysilent")) dwret |= (DWORD)CMDPARAM::SILENT;
|
||||
else if (key.key.equals (L"verysilent")) dwret |= (DWORD)CMDPARAM::VERYSILENT;
|
||||
else if (key.key.equals (L"multiple"))
|
||||
{
|
||||
if (value.type == paramtype::file)
|
||||
|
||||
@@ -90,7 +90,8 @@ std::map <std::string, unsigned> g_nameToId = {
|
||||
MAKENAMEIDMAP (IDS_MSGBOX_TRYAGAIN),
|
||||
MAKENAMEIDMAP (IDS_MSGBOX_CONTINUE),
|
||||
MAKENAMEIDMAP (IDS_PREINSTALL_SUPPOS),
|
||||
MAKENAMEIDMAP (IDS_PREINSTALL_NOSUPPOS)
|
||||
MAKENAMEIDMAP (IDS_PREINSTALL_NOSUPPOS),
|
||||
MAKENAMEIDMAP (IDS_PREINSTALL_SUITCONDITION)
|
||||
};
|
||||
|
||||
#ifdef MAKENAMEIDMAP
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@echo off
|
||||
cd /d "%~dp0"
|
||||
set SCRIPT_DIR=%~dp0
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%ArmBuild.ps1"
|
||||
pause
|
||||
@@ -1221,6 +1221,124 @@ void PackageReaderFreeString (LPWSTR lpStrFromThisDll)
|
||||
free (lpStrFromThisDll);
|
||||
}
|
||||
|
||||
HLIST_PVOID GetAppxBundleAllResourcePackageFileNames (_In_ HPKGREAD hReader)
|
||||
{
|
||||
auto ptr = ToPtrPackage (hReader);
|
||||
if (!ptr) return nullptr;
|
||||
if (ptr->type () == PackageType::bundle)
|
||||
{
|
||||
auto br = ptr->bundle_reader ();
|
||||
std::vector <appx_info::appx_iditem> rpi;
|
||||
br.package_id_items ().resource_packages (rpi);
|
||||
auto buf = (HLIST_PVOID)malloc (sizeof (LIST_PVOID) + sizeof (LPWSTR) * rpi.size ());
|
||||
buf->dwSize = rpi.size ();
|
||||
for (size_t i = 0; i < rpi.size (); i ++)
|
||||
{
|
||||
auto &it = rpi [i];
|
||||
buf->alpVoid [i] = _wcsdup (it.file_name ().c_str ());
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
HLIST_PVOID GetAppxBundleAllLocaleResourcePackageFileNames (_In_ HPKGREAD hReader)
|
||||
{
|
||||
auto ptr = ToPtrPackage (hReader);
|
||||
if (!ptr) return nullptr;
|
||||
if (ptr->type () == PackageType::bundle)
|
||||
{
|
||||
auto br = ptr->bundle_reader ();
|
||||
std::vector <appx_info::appx_iditem> rpi;
|
||||
br.package_id_items ().resource_packages (rpi);
|
||||
std::vector <std::wstring> localePkgNames;
|
||||
for (size_t i = 0; i < rpi.size (); i ++)
|
||||
{
|
||||
auto &it = rpi [i];
|
||||
auto qres = it.qualified_resources ();
|
||||
std::vector <std::wstring> langs;
|
||||
std::vector <UINT32> temp;
|
||||
std::vector <DX_FEATURE_LEVEL> dxt;
|
||||
qres.qualified_resources (&langs, &temp, &dxt);
|
||||
if (temp.size () > 0 || dxt.size () > 0) continue;
|
||||
localePkgNames.push_back (it.file_name ());
|
||||
}
|
||||
auto buf = (HLIST_PVOID)malloc (sizeof (LIST_PVOID) + sizeof (LPWSTR) * localePkgNames.size ());
|
||||
buf->dwSize = localePkgNames.size ();
|
||||
for (size_t i = 0; i < localePkgNames.size (); i ++)
|
||||
{
|
||||
buf->alpVoid [i] = _wcsdup (localePkgNames [i].c_str ());
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
HLIST_PVOID GetAppxBundleAllFileResourcePackageFileNames (_In_ HPKGREAD hReader)
|
||||
{
|
||||
auto ptr = ToPtrPackage (hReader);
|
||||
if (!ptr) return nullptr;
|
||||
if (ptr->type () == PackageType::bundle)
|
||||
{
|
||||
auto br = ptr->bundle_reader ();
|
||||
std::vector <appx_info::appx_iditem> rpi;
|
||||
br.package_id_items ().resource_packages (rpi);
|
||||
std::vector <std::wstring> filePkgNames;
|
||||
for (size_t i = 0; i < rpi.size (); i ++)
|
||||
{
|
||||
auto &it = rpi [i];
|
||||
auto qres = it.qualified_resources ();
|
||||
std::vector <std::wstring> langs;
|
||||
std::vector <UINT32> temp;
|
||||
std::vector <DX_FEATURE_LEVEL> dxt;
|
||||
qres.qualified_resources (&langs, &temp, &dxt);
|
||||
if (temp.size () > 0)
|
||||
filePkgNames.push_back (it.file_name ());
|
||||
}
|
||||
auto buf = (HLIST_PVOID)malloc (sizeof (LIST_PVOID) + sizeof (LPWSTR) * filePkgNames.size ());
|
||||
buf->dwSize = filePkgNames.size ();
|
||||
for (size_t i = 0; i < filePkgNames.size (); i ++)
|
||||
{
|
||||
buf->alpVoid [i] = _wcsdup (filePkgNames [i].c_str ());
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void FreeAppxBundlePayloadsFileNameList (_In_ HLIST_PVOID hStringList)
|
||||
{
|
||||
if (!hStringList) return;
|
||||
for (size_t i = 0; i < hStringList->dwSize; i ++)
|
||||
{
|
||||
auto ptr = hStringList->alpVoid [i];
|
||||
if (!ptr) continue;
|
||||
free (ptr);
|
||||
}
|
||||
free (hStringList);
|
||||
}
|
||||
void UpdatePackageApplicationItemGetName (_In_ LPCWSTR *lpNames, _In_ DWORD dwArrLen)
|
||||
{
|
||||
bool clearAll = !lpNames || !dwArrLen;
|
||||
if (clearAll)
|
||||
{
|
||||
appitems.clear ();
|
||||
return;
|
||||
}
|
||||
appitems.clear ();
|
||||
for (size_t i = 0; i < dwArrLen; i ++)
|
||||
{
|
||||
auto ptr = lpNames [i];
|
||||
if (strnull (ptr)) continue;
|
||||
push_unique (appitems, std::wstring (ptr));
|
||||
}
|
||||
}
|
||||
void GetPackageApplicationItemGetNameList (_In_ ITER_WSTRING_CALLBACK pfCallback)
|
||||
{
|
||||
if (!pfCallback) return;
|
||||
for (auto &it : appitems)
|
||||
{
|
||||
pfCallback (it.c_str ());
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 以下是对清单文件的读取 ==========
|
||||
#define ToHandleMRead(_cpp_ptr_) reinterpret_cast <HPKGMANIFESTREAD> (_cpp_ptr_)
|
||||
#define ToPtrManifest(_cpp_ptr_) reinterpret_cast <manifest *> (_cpp_ptr_)
|
||||
|
||||
@@ -290,6 +290,16 @@ extern "C"
|
||||
// 其实通过 free 释放即可,但考虑到环境问题,那么另写了个函数
|
||||
PKGREAD_API void PackageReaderFreeString (LPWSTR lpStrFromThisDll);
|
||||
|
||||
PKGREAD_API HLIST_PVOID GetAppxBundleAllResourcePackageFileNames (_In_ HPKGREAD hReader);
|
||||
|
||||
PKGREAD_API HLIST_PVOID GetAppxBundleAllLocaleResourcePackageFileNames (_In_ HPKGREAD hReader);
|
||||
|
||||
PKGREAD_API HLIST_PVOID GetAppxBundleAllFileResourcePackageFileNames (_In_ HPKGREAD hReader);
|
||||
PKGREAD_API void FreeAppxBundlePayloadsFileNameList (_In_ HLIST_PVOID hStringList);
|
||||
|
||||
PKGREAD_API void UpdatePackageApplicationItemGetName (_In_ LPCWSTR *lpNames, _In_ DWORD dwArrLen);
|
||||
typedef void (*ITER_WSTRING_CALLBACK) (LPCWSTR lpString);
|
||||
PKGREAD_API void GetPackageApplicationItemGetNameList (_In_ ITER_WSTRING_CALLBACK pfCallback);
|
||||
// ========= 以下是针对于应用清单的读取器,一些常量和类型等是复用的 =========
|
||||
|
||||
TEMPLATE_STRUCT (PKGMANIFESTREAD);
|
||||
|
||||
@@ -1055,6 +1055,10 @@ size_t GetPriScaleAndTargetSizeFileList (
|
||||
auto value = quali->Value;
|
||||
qualis->Add (type, value);
|
||||
}
|
||||
if (qualis->Count == 0 && tasktype == 1)
|
||||
{
|
||||
qualis->Add (QualifierType::Scale, 100);
|
||||
}
|
||||
if (qualis->ContainsKey (QualifierType::Language))
|
||||
{
|
||||
resc = PRI_MAKE_STRING (LocaleCodeToLcidW (MPStringToStdW (qualis [QualifierType::Language]->ToString ())));
|
||||
|
||||
BIN
reslib/reslib.rc
@@ -1,169 +0,0 @@
|
||||
#Requires -RunAsAdministrator
|
||||
|
||||
Push-Location $PSScriptRoot
|
||||
try {
|
||||
# 语言检测函数
|
||||
function Get-Language {
|
||||
$lang = [System.Globalization.CultureInfo]::CurrentUICulture.TwoLetterISOLanguageName
|
||||
if ($lang -eq "zh") { return "zh" }
|
||||
return "en"
|
||||
}
|
||||
|
||||
$lang = Get-Language
|
||||
|
||||
# 本地化消息
|
||||
$messages = @{
|
||||
en = @{
|
||||
title = "Desktop App Installer Setup"
|
||||
confirm = "Do you want to install Desktop App Installer? (y/n)"
|
||||
invalid = "Invalid input. Please enter y or n."
|
||||
cancelled = "Installation cancelled."
|
||||
arch_error = "Error: Cannot continue installation because the computer's processor architecture is not ARM."
|
||||
creating_shortcuts = "Creating shortcuts in Start Screen..."
|
||||
registering = "Registering..."
|
||||
complete = "Installation complete!"
|
||||
}
|
||||
zh = @{
|
||||
title = "Desktop App Installer 安装程序"
|
||||
confirm = "是否安装 Desktop App Installer?(y/n)"
|
||||
invalid = "无效输入,请输入 y 或 n。"
|
||||
cancelled = "安装已取消。"
|
||||
arch_error = "错误:无法继续安装,因为计算机的处理器架构不是 ARM。"
|
||||
creating_shortcuts = "正在创建开始屏幕快捷方式..."
|
||||
registering = "正在注册..."
|
||||
complete = "安装完成!"
|
||||
}
|
||||
}
|
||||
|
||||
$msg = $messages[$lang]
|
||||
|
||||
# 函数定义
|
||||
function Create-Shortcut {
|
||||
param(
|
||||
[string]$LnkPath,
|
||||
[string]$TargetPath,
|
||||
[string]$AppId
|
||||
)
|
||||
$toolShortcutPath = Join-Path $PSScriptRoot "shortcut.exe"
|
||||
if (-not (Test-Path $toolShortcutPath)) {
|
||||
throw "Error: cannot find file 'shortcut.exe' in folder '$PSScriptRoot'"
|
||||
}
|
||||
& $toolShortcutPath $LnkPath $TargetPath $AppId
|
||||
return $LASTEXITCODE
|
||||
}
|
||||
|
||||
function Set-DesktopInit {
|
||||
param(
|
||||
[string]$IniPath,
|
||||
[string]$Section,
|
||||
[string]$Key,
|
||||
[string]$Value
|
||||
)
|
||||
$toolDesktopIniPath = Join-Path $PSScriptRoot "desktopini.exe"
|
||||
if (-not (Test-Path $toolDesktopIniPath)) {
|
||||
throw "Error: cannot find file 'desktopini.exe' in folder '$PSScriptRoot'"
|
||||
}
|
||||
& $toolDesktopIniPath $IniPath $Section $Key $Value
|
||||
return $LASTEXITCODE
|
||||
}
|
||||
|
||||
# 检查处理器架构
|
||||
if ($env:PROCESSOR_ARCHITECTURE.Trim() -ne "ARM") {
|
||||
throw $msg.arch_error
|
||||
}
|
||||
|
||||
# 确认安装
|
||||
do {
|
||||
$response = Read-Host $msg.confirm
|
||||
$response = $response.ToLower()
|
||||
if ($response -eq 'y') {
|
||||
$confirmed = $true
|
||||
break
|
||||
} elseif ($response -eq 'n') {
|
||||
Write-Host $msg.cancelled
|
||||
exit 0
|
||||
} else {
|
||||
Write-Host $msg.invalid
|
||||
}
|
||||
} while ($true)
|
||||
|
||||
# 安装目录和快捷方式目录
|
||||
$appStartMenuFolder = "Desktop App Installer"
|
||||
$appPublicStartMenuFolder = [System.IO.Path]::Combine($env:ProgramData, "Microsoft\Windows\Start Menu\Programs")
|
||||
$startitemfolder = [System.IO.Path]::Combine($appPublicStartMenuFolder, $appStartMenuFolder)
|
||||
$AppFolder = $PSScriptRoot
|
||||
|
||||
Write-Output $msg.creating_shortcuts
|
||||
if (-not (Test-Path $startitemfolder)) {
|
||||
New-Item -ItemType Directory -Path $startitemfolder -Force | Out-Null
|
||||
}
|
||||
|
||||
$shortcuts = @(
|
||||
@{
|
||||
LnkPath = Join-Path $startitemfolder "App Installer.lnk"
|
||||
TargetPath = Join-Path $AppFolder "appinstaller.exe"
|
||||
AppId = "Microsoft.DesktopAppInstaller!App"
|
||||
},
|
||||
@{
|
||||
LnkPath = Join-Path $startitemfolder "Settings.lnk"
|
||||
TargetPath = Join-Path $AppFolder "settings.exe"
|
||||
AppId = "WindowsModern.PracticalToolsProject!Settings"
|
||||
},
|
||||
@{
|
||||
LnkPath = Join-Path $startitemfolder "Package Manager.lnk"
|
||||
TargetPath = Join-Path $AppFolder "Manager.exe"
|
||||
AppId = "WindowsModern.PracticalToolsProject!Manager"
|
||||
},
|
||||
@{
|
||||
LnkPath = Join-Path $startitemfolder "Update.lnk"
|
||||
TargetPath = Join-Path $AppFolder "Update.exe"
|
||||
AppId = "WindowsModern.PracticalToolsProject!Update"
|
||||
},
|
||||
@{
|
||||
LnkPath = Join-Path $startitemfolder "Package Reader.lnk"
|
||||
TargetPath = Join-Path $AppFolder "Reader.exe"
|
||||
AppId = "WindowsModern.PracticalToolsProject!Reader"
|
||||
}
|
||||
)
|
||||
|
||||
foreach ($item in $shortcuts) {
|
||||
$exitCode = Create-Shortcut -LnkPath $item.LnkPath -TargetPath $item.TargetPath -AppId $item.AppId
|
||||
}
|
||||
|
||||
# $desktopini = Join-Path $startitemfolder "desktop.ini"
|
||||
$desktopini = $startitemfolder
|
||||
Set-DesktopInit -IniPath $desktopini -Section ".ShellClassInfo" -Key "ConfirmFileOp" -Value 0
|
||||
Set-DesktopInit -IniPath $desktopini -Section "LocalizedFileNames" -Key "App Installer.lnk" -Value "@$AppFolder\appinstaller.exe,-300"
|
||||
Set-DesktopInit -IniPath $desktopini -Section "LocalizedFileNames" -Key "Settings.lnk" -Value "@$AppFolder\settings.exe,-200"
|
||||
Set-DesktopInit -IniPath $desktopini -Section "LocalizedFileNames" -Key "Update.lnk" -Value "@$AppFolder\reslib.dll,-103"
|
||||
Set-DesktopInit -IniPath $desktopini -Section "LocalizedFileNames" -Key "Package Manager.lnk" -Value "@$AppFolder\reslib.dll,-228"
|
||||
Set-DesktopInit -IniPath $desktopini -Section "LocalizedFileNames" -Key "Uninstall.lnk" -Value "@$AppFolder\reslib.dll,-131"
|
||||
Set-DesktopInit -IniPath $desktopini -Section ".ShellClassInfo" -Key "LocalizedResourceName" -Value "@$AppFolder\appinstaller.exe,-300"
|
||||
|
||||
Write-Output $msg.registering
|
||||
$reg = [Microsoft.Win32.Registry]::ClassesRoot
|
||||
$key = $reg.CreateSubKey("Microsoft.DesktopAppInstaller")
|
||||
$key.SetValue("", "Windows Store App Package")
|
||||
$key.Close()
|
||||
$subKey = $reg.CreateSubKey("Microsoft.DesktopAppInstaller\Shell\Open\Command")
|
||||
$subKey.SetValue("", "`"$AppFolder\appinstaller.exe`" `"%1`"")
|
||||
$subKey.Close()
|
||||
$subKey = $reg.CreateSubKey("Microsoft.DesktopAppInstaller\DefaultIcon")
|
||||
$subKey.SetValue("", "$AppFolder\appinstaller.exe,2")
|
||||
$subKey.Close()
|
||||
$subKey = $reg.CreateSubKey("Applications\AppInstaller.exe\DefaultIcon")
|
||||
$subKey.SetValue("", "$AppFolder\appinstaller.exe,-136")
|
||||
$subKey.Close()
|
||||
$subKey = $reg.CreateSubKey(".appx")
|
||||
$subKey.SetValue("", "Microsoft.DesktopAppInstaller")
|
||||
$subKey.Close()
|
||||
$subKey = $reg.CreateSubKey(".appxbundle")
|
||||
$subKey.SetValue("", "Microsoft.DesktopAppInstaller")
|
||||
$subKey.Close()
|
||||
|
||||
Write-Output ""
|
||||
Write-Output $msg.complete
|
||||
Start-Sleep -Seconds 5
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
BIN
shared/ArmInstaller.exe
Normal file
@@ -1,153 +0,0 @@
|
||||
#Requires -RunAsAdministrator
|
||||
|
||||
Push-Location $PSScriptRoot
|
||||
try {
|
||||
# 语言检测函数
|
||||
function Get-Language {
|
||||
$lang = [System.Globalization.CultureInfo]::CurrentUICulture.TwoLetterISOLanguageName
|
||||
if ($lang -eq "zh") { return "zh" }
|
||||
return "en"
|
||||
}
|
||||
|
||||
$lang = Get-Language
|
||||
|
||||
# 本地化消息
|
||||
$messages = @{
|
||||
en = @{
|
||||
title = "Uninstall Desktop App Installer"
|
||||
confirm = "Are you sure you want to uninstall Desktop App Installer? (y/n)"
|
||||
invalid = "Invalid input. Please enter y or n."
|
||||
removing_start = "Removing Start Menu folder..."
|
||||
removing_reg = "Removing registry entries..."
|
||||
removing_dir = "Removing installation directory..."
|
||||
confirm_dir = "Do you also want to delete the installation directory? (y/n)"
|
||||
complete = "Uninstallation complete."
|
||||
error = "Error: "
|
||||
cancelled = "Uninstall cancelled."
|
||||
}
|
||||
zh = @{
|
||||
title = "卸载 Desktop App Installer"
|
||||
confirm = "确定要卸载 Desktop App Installer 吗?(y/n)"
|
||||
invalid = "无效输入,请输入 y 或 n。"
|
||||
removing_start = "正在删除开始菜单文件夹..."
|
||||
removing_reg = "正在删除注册表项..."
|
||||
removing_dir = "正在删除安装目录..."
|
||||
confirm_dir = "是否同时删除安装目录?(y/n)"
|
||||
complete = "卸载完成。"
|
||||
error = "错误:"
|
||||
cancelled = "卸载已取消。"
|
||||
}
|
||||
}
|
||||
|
||||
$msg = $messages[$lang]
|
||||
|
||||
if ($env:PROCESSOR_ARCHITECTURE.Trim() -ne "ARM") {
|
||||
throw "Error: Cannot continue installation because the computer's processor architecture is not ARM."
|
||||
}
|
||||
|
||||
# 确认卸载(控制台交互)
|
||||
do {
|
||||
$response = Read-Host $msg.confirm
|
||||
$response = $response.ToLower()
|
||||
if ($response -eq 'y') {
|
||||
$confirmed = $true
|
||||
break
|
||||
} elseif ($response -eq 'n') {
|
||||
Write-Host $msg.cancelled
|
||||
exit 0
|
||||
} else {
|
||||
Write-Host $msg.invalid
|
||||
}
|
||||
} while ($true)
|
||||
|
||||
# 定义路径
|
||||
$appStartMenuFolder = "Desktop App Installer"
|
||||
$appPublicStartMenuFolder = [System.IO.Path]::Combine($env:ProgramData, "Microsoft\Windows\Start Menu\Programs")
|
||||
$startitemfolder = [System.IO.Path]::Combine($appPublicStartMenuFolder, $appStartMenuFolder)
|
||||
$AppFolder = $PSScriptRoot
|
||||
|
||||
# 删除开始菜单文件夹
|
||||
Write-Host $msg.removing_start
|
||||
if (Test-Path $startitemfolder) {
|
||||
Remove-Item -Path $startitemfolder -Recurse -Force -ErrorAction SilentlyContinue
|
||||
if (Test-Path $startitemfolder) {
|
||||
Write-Warning "$msg.error Could not remove $startitemfolder"
|
||||
} else {
|
||||
Write-Output "Removed $startitemfolder"
|
||||
}
|
||||
} else {
|
||||
Write-Output "Start Menu folder not found, skipping."
|
||||
}
|
||||
|
||||
# 删除注册表项
|
||||
Write-Host $msg.removing_reg
|
||||
$reg = [Microsoft.Win32.Registry]::ClassesRoot
|
||||
|
||||
$keysToDelete = @(
|
||||
"Microsoft.DesktopAppInstaller",
|
||||
".appx",
|
||||
".appxbundle"
|
||||
)
|
||||
foreach ($keyName in $keysToDelete) {
|
||||
try {
|
||||
if ($reg.OpenSubKey($keyName) -ne $null) {
|
||||
$reg.DeleteSubKeyTree($keyName)
|
||||
Write-Output "Removed registry key: HKCR\$keyName"
|
||||
} else {
|
||||
Write-Output "Registry key not found: HKCR\$keyName"
|
||||
}
|
||||
} catch {
|
||||
Write-Warning "$msg.error Could not remove HKCR\$keyName : $_"
|
||||
}
|
||||
}
|
||||
|
||||
# 删除 Applications\AppInstaller.exe 下的 DefaultIcon
|
||||
$appPath = "Applications\AppInstaller.exe"
|
||||
try {
|
||||
$appKey = $reg.OpenSubKey($appPath, $true)
|
||||
if ($appKey) {
|
||||
$subKeyNames = $appKey.GetSubKeyNames()
|
||||
if ($subKeyNames -contains "DefaultIcon") {
|
||||
$appKey.DeleteSubKey("DefaultIcon")
|
||||
Write-Output "Removed registry key: HKCR\$appPath\DefaultIcon"
|
||||
}
|
||||
$appKey.Close()
|
||||
} else {
|
||||
Write-Output "Registry key not found: HKCR\$appPath"
|
||||
}
|
||||
} catch {
|
||||
Write-Warning "$msg.error Could not process HKCR\$appPath : $_"
|
||||
}
|
||||
|
||||
# 删除安装目录
|
||||
Write-Host $msg.removing_dir
|
||||
do {
|
||||
$respDir = Read-Host $msg.confirm_dir
|
||||
$respDir = $respDir.ToLower()
|
||||
if ($respDir -eq 'y') {
|
||||
if (Test-Path $AppFolder) {
|
||||
Remove-Item -Path $AppFolder -Recurse -Force -ErrorAction SilentlyContinue
|
||||
if (Test-Path $AppFolder) {
|
||||
Write-Warning "$msg.error Could not delete $AppFolder"
|
||||
} else {
|
||||
Write-Output "Deleted installation directory."
|
||||
}
|
||||
} else {
|
||||
Write-Output "Installation directory not found."
|
||||
}
|
||||
break
|
||||
} elseif ($respDir -eq 'n') {
|
||||
Write-Output "Skipped deleting installation directory."
|
||||
break
|
||||
} else {
|
||||
Write-Host $msg.invalid
|
||||
}
|
||||
} while ($true)
|
||||
|
||||
Write-Host $msg.complete
|
||||
Start-Sleep -Seconds 3
|
||||
} catch {
|
||||
Write-Error "Uninstall failed: $_"
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
BIN
shared/ArmUninstaller.exe
Normal file
4
shared/Reader.VisualElementsManifest.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" GeneratedByTileIconifier="true">
|
||||
<VisualElements ShowNameOnSquare150x150Logo="on" Square150x150Logo="VisualElements\MediumIconReader.png" Square70x70Logo="VisualElements\SmallIconReader.png" ForegroundText="light" BackgroundColor="#004fe2" TileIconifierColorSelection="Default" TileIconifierCreatedWithUpgrade="true" />
|
||||
</Application>
|
||||
BIN
shared/VisualElements/MediumIconReader.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
9
shared/VisualElements/MediumIconReader_Metadata.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<ShortcutItemImage xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<OriginalBytes>iVBORw0KGgoAAAANSUhEUgAAANIAAADSCAYAAAA/mZ5CAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAnoSURBVHhe7d17qKR1HcdxsbKLS2WWsFBiEUoRGRUZUVhBEOZ1ddW8oKbrHyJUEkkKuRRhRekfUeHSvUgpoljX3dpatXUttYzoQkGEZkpRoNAfQSC7vX/zfGc958yZM7/nPJf5PWfeL/gyc+b53c6Z78f13OYcIUmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJG0whw4d2n7w4MHL4k1JdRGgzxKkEe7/lbo0LknDRjNvo/5GPR0PdYL1vxgZWobH/0JdFMOkYaF5r6GeiH4e4e0n43KrWPfW2GIqxvyZuiCmSGWjWT9ELQvQUlx7NIa2giW3VyvnYf8/UufFdKksNOdH1wrQUoz7XUxrhHWuiyVrY+7vqS2xlDRfNOONVFaAlmLOgVhiXZi/LZZqhHV+S50Vy0r9of+eTaUvM9cO0FLM3x1L1sK8C2KJ1rDmw9TpsYXUHfrtBVTjAC3FWnfE8lmYsrWa2Q3O85CBUiforxdTrQZoKdbdEVutiaGdhmgpzvSAgVIraKSX0VOdBWgp9vh8bLsqhvQWoqU41/0GSutC42ymh3oJ0FLsd1McYRkuzSVES3G2/QZK2eiZ3gO0FHt/OI4ywkNzD9EK9xoorYkGuT6aZa44x5XpPNwtLUSHccZ9BkpT0RyfjF6ZK85xS9wtGufca6C0KhrjE9EnvWPvndy8Kc7xWuqe6krZOOceykBpOXqj1s+wNZUCNK0RuXw1135VjSwb57zLQGkZ+qLzMK0VoJUYdxX1UEwtWp33SwuAnugkTE0ajXlXUg/GUkVr8n5qg6EfWgtTm43FOh+gHoili9bm+60BoxcahanLRmLdK6hfxFZF6/LjoIGgAdLnKE9HT2Tps3HY7nL2ur/auWx9flxUIHrgGBrg0aodpptno7DvZdSBOErR5vlxUgF48lf9/k5JjcE5LqXui6MVraSPm3rEc38CT/zfqzYouxE41yXU/jhq0dLHkZsj4+haBDzp6YVOHqEG8YKMnPNi6udVy5aJ8x0dx9Ui4Yl/jNpBD4x+rGcIOO9FVIk/evTSOKIWDQ359WiC9F/T27gZUqDeT91dnX6+OMcr4lhaRPTAxPeXBhioC6l91en7x94nxlG0qOiDqd+oHWCgzqd+Vp2+H+x3cmyvRUYj3Bw9MdXQAsVZt3Lmn44O3yH2eGtsqUVHM3w5+mKmoQWK855H7a1O3y7WfVdsI42a7fbojWwDDNS51I+r0zfHWqfF0lKFptgT/VHbAAO1pcn7mzD/3FhOegaN0fj7MQMM1DnU7ur0tWyNJaTl2gjS2AADdRZ1V3X6mQyRpmszSGMDDNSZ1K7q9KsyRFpbF0EaG2CgzqDurE5/mCHSbF0GaWyAgfog9SRnTi9w+c42KpbWRtVHkMZKDxRnO5Izfpyq9VvE07DOdyh/fGgR8ET3FqQx9iwqUJzlKM50A/W/0QEbYp0UoFNieS0CnvDegzTG3nMNFPs/n0p/O/e/1YmaYR0DtKh44ucWpDHO0Gug2GsTe15H/Wd0gIZYxwAtOhpg7kEa4yydBoq1X8QeH6GeGm3YEOt8lTJAKitIY5yp1UCx3rHU9dS/qx2aSeejDJCeQUMUF6Sx1LDcrDtQzD+OupH6R7ViM+k8lAHSJBqj2CCNpQbmJjtQjN9MpS9jH36VpCbS/pQB0nQ0SPFBGuOsN8exp2LMtdRjMaUR1jFAykOjDCZI4dNx9Am8LxfHmEYiQG+JZaXZhhYkzrszjj6Ba4/EsHVJAeKmty/DawMZYJDuiaNPWE+QmPMvA6TGNliQ0hcYPkal7xWlHzy9htrGtPRXLtL/9qUfQj2b+++j3sN9f5hU7aChNkyQpLkxSFILNlKQuHx53JX6tVqQeOxH3KTPJ4qzVpDSNSp9wcFAqV8rg8Tb6fXfnhOX03/lizIrSDEsjfsTNwZK/VjRfOn+prg0wtvPGl0sRG6QxnjsYW5qB4o5fkVP+cbNx+0vqZfEw8tw+ag0pgTpvHGsCeP3ZTVc209dGENXxfXxL/o9zhSDpHw0Tfq84jfU5nhoVTTW80YdOWfpvHGkCelaDJuKMXuoM2LKCA8fT23n8SdGgyoGSfmi+U6IN9fE2KOrHpufdN44zoR4X7Iw9p/Ut7j7veqRCQZJ+Wimk+JuFsa/MBptLlJY4igT0rUY1gaDpG7RZMdUvdY/g6QNhaY9NhquVwZJg0IjzXypXhr3uKrn+mOQNBg05B3RTDlh2hxje2GQNAg043ejkcZywvTyGNs5g6Ti0YjfjiZaaWaYGJO+F9M5g6Si0YTfjAaaJudfplfG2M4YJBWLBvxaNM8sOWF6dYzthEFSkWi+r0Tj5MoJ00kxtnUGScWh8XZE09SVE6bXxNhWGSQVhaar+y/RSjlhel2MbY1BUjFokm9UvdJYTphOjrGtMEgqAs027Uvc65UTpjfG2MYMkuaORrs9mqRtOWF6c4xtxCBprmiy70eDdCUnTKfE2HUzSJobGuyH0RxdywnT22LsuhgkzQXNtTMaoy85YXpHjK3NIKl3NNbuaIq+5YTp1Bhbi0FSr2iqvdEQ85ITpmtjbDaDpN7QUHdHM8zbmmHinCfGuGwGSZ3jyT+eZvpD1QfFWDNMMSabQVLnePLfnhqgTtF86/nXa9W11qo44gSu1WKQVCSar/bnUjG1FbFkNoOkItF8e6JxssXUVsSS2QySikTz7YrGyRZTWxFLZjNIKhLNl/4WUi0xtRWxZDaDpCLRfD+IxskWU1sRS2YzSCoSDTPtReSniqkTuLSJZr6pTlUr5mNOX0F6VSwrzUbzrXwdu5li6qq4fDX169HADvQRJNZJf6niubGsNBsNU/sX/WLqmhjWSaB6CtItsaSUh76p/WvnMTULw1sNVNdBYo3HqdfHklIemqb2i6DE1FqY1kqgugwS85+iTovlpHw0zm3RR9li6rowvVGgugoSc9MvP74hlpLqoYG+VLVSvpjaCPtexVK1A9V2kJizmzozlpDWhyb6QvRUtpjaCva/giWzA5XCElMnpGsxbCbG/oTaElOlZmimW6O3ssXUVnGOS1h6ZqBSWGLKhHQthk3FmH3UeTFFagdN9bnosWwxtROc53y2mBqoFJYYOiFdi2GruZc6O4ZK7aL5PlP1Wb6Y2inOdQ5bTQSqbpB47D7q9BgidYMm+1T0XLaY2osUAurB2Do7SNw/QL03LkndotluoNL3T7IrpvaKfd9N7aXujIcmpGvULurUeEiSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJKmuI474P9M94UzlaHRYAAAAAElFTkSuQmCC</OriginalBytes>
|
||||
<OriginalPath>E:\Profiles\Bruce\Desktop\tilesassets\medium.scale-140.png</OriginalPath>
|
||||
<Height>100</Height>
|
||||
<Width>100</Width>
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
</ShortcutItemImage>
|
||||
BIN
shared/VisualElements/SmallIconReader.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
9
shared/VisualElements/SmallIconReader_Metadata.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<ShortcutItemImage xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<OriginalBytes>iVBORw0KGgoAAAANSUhEUgAAAGIAAABiCAYAAACrpQYOAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAYaSURBVHhe7ZxrqFRVFMclSqKIqLAyMope2DuCoiJIiAj80osoKgr6Zh/K3m8lJKwsRCw0sJBQ1Ii+BPUlIoqIiiCSoAdJZIlaiGWZlff22+f8z25mzpyZPTNn3+7ss37w59yzznrctZZ35p6Z8c4wDMMwDMMwDMMwDMMwDMMwDMMwDMMIY3Jy8na0eGJiYrZMxjC4IaIrdDoQDH8u2kL8JMcfbSFDoAV4GOB8XQqmWEIrtpBA3JCyiXWB4V0nt77g+67CumILqcANJZtQHxjczQqppN8SWrGFCAbwbD6ScIi5Q+ElBllCK41dCA2vykcwHJ3L4PxQNNQSWiFHMxZCg+vzlkeHXLcq52z0vsy1QL50F0JTF+Vt1gc5F6LPdVo7yS6Epi7POqwBhrPa5eS4QAOLRpILoaGRlsEw1qALlS7DDQg9gX6QWxTIn9ZCaGbgZdD8WtS2gE64fgx6DG1VWBTIn85CaCRoGTS7Dp2vsCDwn4UeQT8pTRTIn8ZCaGBO3lIZrm1EZ8l1KIg/ilQPcdyeZ40D+cd/IRqWh/NX0Wm6XAukPYKcD6CdeZU4kH+8F8I3fht6GZ0kUxQY0uHUuB/9kk0uAuSe4DBTJccPDcf9azpOpmhQ4zB0L9qVTa8myLfP5VaZ8YQGvlAz29CT6HhdigY13Esj96Bfs0mOADn2oFlKPb7QxIfqKYPz7WgJX54gl2hQ4xBq3Yf2ZMUHhLhdaI7SjTc0Unojx4F9J3oKRX3+cFDuYOo8iP7Iq/cH3x3oFKUYf2hmn3rrCtfdc8hSjicrJBrUmUmdh9GfWfEKuL4VjfQr9rRDvfWFxt3DwDPoVIVGg3IHUudR9Fde/T+wuZ/gC+SaDnl74TCI3WgZOl0pokG5A6jzONqv2l+js3U5LVyDw8BAfkPPo7lKFRXqrKCse2s3VCcqdDzgGx4JBvQ7Wo7OVMraIL17znA/EaWHqG7g9wYa+JMn0wL1MDIMYC9agUZ+6CCHu89wd+JBv9bi9zq6SuHjiXqpDQbi7nJXonNVIhjC3WtT7r4i6M4bv9c4DPVBuGlH3lL9MKS/0Yuo70vp+ByN3MvnOxTeE/zcQ9A8haeBeosGA9uPVqFzVLIN7ItQ0Dt8+L2JLlNoWqjHKUElPQz1Y13qCX5vo0sUlibqdUpQSY/MlTD8d9Clck8b9TwlqKQHk3vbtlJyawY0PGWopNENzahgEw8F7m3HKKikh1pL0JE6bTaakWOTzs9jOJtzU71kBVuQ2T0XvIB6vrqL20H6Mk3yUeRLKGAoZ8RYhtJ7ZPZQczWHtldWOT8W+9McF8uUJjTYtoSCGMtQao/MJaj7CrqWL9176cVNXtqL6EXdy1Baj8yhNHcRjjqXoZQemUNpziJcs27wOvXUtQyl88gcSjMWwaDdJzfc4/PmWMtQKo/MoaS/CJpcmveaE2sZSuOROZS0F8Fgl6nRNmIsQyk8MoeS7iIY6HI12ZW6l6Fwj8yhpLkIBrlSDfakzmUo1CNzKOktggG6O9hg6lqGwjwyh5LWIhjcGjU2EHUsQyEemUNJZxEMbK2aGopRlyF3j8yhpLEIBrVODY1Ej2VcLJdK5OqROZTxXgQNuI+obMx7qYcey+j5IQC5eWQOZbwXwXDuQu6TElX6R42W4Jr7OxvdPs6Yietty+D8LeyVyM0jcyhpPVl3wvD2qtESbhFyCwL/DQrtitw8MoeS/CJ2q9ESQyziJYV2RW4emUNJfhE/q9ESQyziOYV2RW4emUNJfhHb1GiJzkVwPg9z5/PEog5bJUrjkTkI6lyjsDShwe/Va4nORRRgvxIN/LeaFO6ROQjqRf+vY/8rNPitei1RtYgCrs9HH8m9LwrzyNwXatytkHShyS/Vb4l+iyjA9Wr0aRbUA7l7ZK6E+p+hm+SeNjRa+ZfIQhdRgP/1vfLJzSNzCXK4G8Y75dYMaPgT9V+CawMtooC4G1HpJ02XPTJ7iPkKLdTlZkHjbX95oBWuDbWIAuJvQd8oXeUi8NmCFsjcTBjABvRdhdbLbSTI4x6yPtCpB9t76AadGoZhGIZhGIZhGIZhGIZhGIZhGIbRcGbM+BeN+q7PrwKDyAAAAABJRU5ErkJggg==</OriginalBytes>
|
||||
<OriginalPath>E:\Profiles\Bruce\Desktop\tilesassets\small.scale-140.png</OriginalPath>
|
||||
<Height>50</Height>
|
||||
<Width>50</Width>
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
</ShortcutItemImage>
|
||||
@@ -34,4 +34,11 @@
|
||||
<scale dpi="180">splash\manager\splash.scale-180.png</scale>
|
||||
<scale dpi="default">splash\manager\splash.png</scale>
|
||||
</resource>
|
||||
<resource id="reader">
|
||||
<scale dpi="80">splash\reader\splash.scale-80.png</scale>
|
||||
<scale dpi="100">splash\reader\splash.scale-100.png</scale>
|
||||
<scale dpi="140">splash\reader\splash.scale-140.png</scale>
|
||||
<scale dpi="180">splash\reader\splash.scale-180.png</scale>
|
||||
<scale dpi="default">splash\reader\splash.png</scale>
|
||||
</resource>
|
||||
</resources>
|
||||
BIN
shared/VisualElements/splash/reader/splash.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
shared/VisualElements/splash/reader/splash.scale-100.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
shared/VisualElements/splash/reader/splash.scale-140.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
shared/VisualElements/splash/reader/splash.scale-180.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
shared/VisualElements/splash/reader/splash.scale-80.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
@@ -24,6 +24,18 @@
|
||||
BackgroundColor="#159d9d" DarkModeBackgroundColor='#2e1e5c' />
|
||||
</VisualElements>
|
||||
</Application>
|
||||
<Application Id='Reader'>
|
||||
<VisualElements
|
||||
DisplayName='Package Manager'
|
||||
Logo='Settings.Assets\Logo.png'
|
||||
SmallLogo='Settings.Assets\SmallLogo.png'
|
||||
ForegroundText='light'
|
||||
BackgroundColor='#004fe2'>
|
||||
<DefaultTile ShowName='allLogos' />
|
||||
<SplashScreen Image="VisualElements\splash\reader\splash.png"
|
||||
BackgroundColor="#004fe2" DarkModeBackgroundColor='#002770' />
|
||||
</VisualElements>
|
||||
</Application>
|
||||
<Application Id='Settings'>
|
||||
<VisualElements
|
||||
DisplayName='Settings'
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
@echo off
|
||||
if exist "%SystemRoot%\SysWOW64" path %path%;%windir%\SysNative;%SystemRoot%\SysWOW64;%~dp0
|
||||
bcdedit >nul
|
||||
if '%errorlevel%' NEQ '0' (goto UACPrompt) else (goto UACAdmin)
|
||||
:UACPrompt
|
||||
%1 start "" mshta vbscript:createobject("shell.application").shellexecute("""%~0""","::",,"runas",1)(window.close)&exit
|
||||
exit /B
|
||||
:UACAdmin
|
||||
cd /d "%~dp0"
|
||||
|
||||
set SCRIPT_DIR=%~dp0
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%ArmInstall.ps1"
|
||||
pause
|
||||
@@ -1,11 +1,11 @@
|
||||
对于 Windows RT 用户,请以管理员身份运行 arm_install.bat 或 arm_uninstall.bat 进行安装或卸载。安装前请务必将压缩包中的所有文件放置在一个独立的文件夹中,该文件夹请勿随意移动或删除,不建议放置在桌面上。若需更新或移动程序,请先执行原卸载脚本,然后再进行安装操作。x86、x64 以及支持 x86 兼容层的 ARM64 系统请使用标准安装程序,本方案仅适用于 ARM 设备。
|
||||
对于 Windows RT 用户,请以管理员身份运行 ArmInstaller.exe 或 ArmUninstaller.exe 进行安装或卸载。安装前请务必将压缩包中的所有文件放置在一个独立的文件夹中,该文件夹请勿随意移动或删除,不建议放置在桌面上。若需更新或移动程序,请先执行卸载程序,然后再进行安装操作。请不要使用程序中具有的安装程序来更新。 x86、x64 以及 具有 Windows on ARM 的 ARM64 系统 请使用标准安装程序,本方案仅适用于 ARM 设备。
|
||||
感谢“冰糖XH”(主页:https://github.com/bingtangxh)帮助我完成了针对 ARM 架构的程序编译。
|
||||
|
||||
适用于 ARM 设备的项目发行:https://github.com/bingtangxh/App-Installer-For-Windows-8.x-Reset/releases
|
||||
其余设备的项目发行:https://github.com/modernw/App-Installer-For-Windows-8.x-Reset/releases
|
||||
|
||||
(Translated by DeepSeek)
|
||||
For Windows RT users, please run arm_install.bat or arm_uninstall.bat as an administrator to install or uninstall. Before installation, extract all files from the compressed package into a dedicated folder; do not move or delete this folder arbitrarily, and it is not recommended to place it on the desktop. If you need to update or relocate the program, first run the original uninstall script, then proceed with the installation. For x86, x64, and ARM64 systems that support the x86 compatibility layer, please use the standard installer; this solution is specifically for ARM devices.
|
||||
For Windows RT users, please run ArmInstaller.exe or ArmUninstaller.exe as an administrator to install or uninstall. Before installation, extract all files from the compressed package into a dedicated folder; do not move or delete this folder arbitrarily, and it is not recommended to place it on the desktop. If you need to update or relocate the program, first run the uninstaller, then proceed with the installation. Do not use the installer included in the program to update. For x86, x64, and ARM64 systems with Windows on ARM please use the standard installer; this solution is specifically for ARM devices.
|
||||
Thanks to "BingTangXH" (Homepage: https://github.com/bingtangxh) for helping me complete the program compilation for the ARM architecture.
|
||||
|
||||
Project release for ARM devices: https://github.com/bingtangxh/App-Installer-For-Windows-8.x-Reset/releases
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
@echo off
|
||||
if exist "%SystemRoot%\SysWOW64" path %path%;%windir%\SysNative;%SystemRoot%\SysWOW64;%~dp0
|
||||
bcdedit >nul
|
||||
if '%errorlevel%' NEQ '0' (goto UACPrompt) else (goto UACAdmin)
|
||||
:UACPrompt
|
||||
%1 start "" mshta vbscript:createobject("shell.application").shellexecute("""%~0""","::",,"runas",1)(window.close)&exit
|
||||
exit /B
|
||||
:UACAdmin
|
||||
cd /d "%~dp0"
|
||||
|
||||
set SCRIPT_DIR=%~dp0
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%ArmUninstall.ps1"
|
||||
pause
|
||||
@@ -626,11 +626,11 @@ progress.win-ring:indeterminate::-ms-fill {
|
||||
@keyframes scale-visible {
|
||||
from {
|
||||
transform: translateX(50px) scale(0.8);
|
||||
opacity: 0;
|
||||
/*opacity: 0;*/
|
||||
}
|
||||
to {
|
||||
transform: translateX(0) scale(1);
|
||||
opacity: 1;
|
||||
/*opacity: 1;*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
<script type="text/javascript" src="js/pages.js"></script>
|
||||
<script type="text/javascript" src="js/load.js"></script>
|
||||
<script type="text/javascript" src="js/init.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="libs/msgbox/contentdlg.css">
|
||||
<script type="text/javascript" src="libs/msgbox/contentdlg.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="libs/msgbox/msgbox.css">
|
||||
<script type="text/javascript" src="libs/msgbox/msgbox.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="theme/light/default/default.css" id="theme-style">
|
||||
@@ -141,7 +143,7 @@
|
||||
<!-- Loading... -->
|
||||
<div class="content loading">
|
||||
<span class="ring-loading"></span>
|
||||
<span data-res-byname="IDS_PLEASEWAIT">Please wait...</span>
|
||||
<span data-res-byname="IDS_PLEASEWAIT"></span>
|
||||
</div>
|
||||
<!-- Main Page -->
|
||||
<div class="content select preinstall installing installsuccess installfailed main">
|
||||
@@ -394,7 +396,7 @@
|
||||
</div>
|
||||
<div class="controls">
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="preinst-enablelaunch" class="win-checkbox">
|
||||
<input type="checkbox" id="preinst-enablelaunch" class="win-checkbox" style="margin-left: 0;">
|
||||
<label for="preinst-enablelaunch" data-res-byname="IDS_LAUNCHWHENREADY"></label>
|
||||
</div>
|
||||
<div class="command">
|
||||
|
||||
@@ -118,4 +118,12 @@
|
||||
return Bridge.String.toupper(this);
|
||||
};
|
||||
}
|
||||
if (typeof String.prototype.format !== "function") {
|
||||
String.prototype.format = function() {
|
||||
var args = arguments;
|
||||
return this.replace(/{(\d+)}/g, function(match, number) {
|
||||
return typeof args[number] !== "undefined" ? args[number] : match;
|
||||
});
|
||||
};
|
||||
}
|
||||
})(this);
|
||||
@@ -363,6 +363,19 @@
|
||||
));
|
||||
}
|
||||
};
|
||||
Object.defineProperty(this, "length", {
|
||||
get: function() {
|
||||
return _list.length;
|
||||
},
|
||||
enumerable: true,
|
||||
});
|
||||
this.getDatas = function() { return _list; }
|
||||
this.forEach = function(callback, args) {
|
||||
if (typeof callback !== "function") return;
|
||||
for (var i = 0; i < _list.length; i++) {
|
||||
callback.apply(this, [_list[i], i].concat(Array.prototype.slice.call(arguments, 1)));
|
||||
}
|
||||
};
|
||||
this._getKey = getKey;
|
||||
}
|
||||
var MAX_ANIMATE_COUNT = 100;
|
||||
@@ -609,10 +622,16 @@
|
||||
});
|
||||
PMDataListView.prototype._updateEmptyView = function() {
|
||||
if (!this._emptyView) return;
|
||||
|
||||
// container 中是否还有 item
|
||||
var hasItem = this.container.children.length > 0;
|
||||
|
||||
var itemVisibleLength = 0;
|
||||
for (var i = 0; i < this.container.children.length; i++) {
|
||||
var child = this.container.children[i];
|
||||
if (!child) continue;
|
||||
if (child.style.display !== "none" && child.style.display !== "hidden" && child.style.opacity !== 0 && child.style.visibility !== "hidden") {
|
||||
itemVisibleLength++;
|
||||
}
|
||||
}
|
||||
hasItem = hasItem && itemVisibleLength > 0;
|
||||
if (hasItem) {
|
||||
if (this._emptyView.parentNode) {
|
||||
this._emptyView.style.display = "none";
|
||||
@@ -802,6 +821,7 @@
|
||||
};
|
||||
PMDataListView.prototype.refresh = function() {
|
||||
this._refreshVisibility();
|
||||
this._updateEmptyView();
|
||||
};
|
||||
global.DataView.ChangeEvent = PMChangeEvent;
|
||||
global.DataView.DataSource = PMDataSource;
|
||||
|
||||
562
shared/html/js/dboxapi.js
Normal file
@@ -0,0 +1,562 @@
|
||||
/**
|
||||
* DBox API
|
||||
* Docs: https://dbox.tools/api/docs
|
||||
*/
|
||||
(function(global) {
|
||||
"use strict";
|
||||
|
||||
function joinUrl(url, path) {
|
||||
if (url.charAt(url.length - 1) === "/") {
|
||||
url = url.slice(0, -1);
|
||||
}
|
||||
if (path.charAt(0) === "/") {
|
||||
path = path.slice(1);
|
||||
}
|
||||
return url + "/" + path;
|
||||
}
|
||||
|
||||
function buildParams(params) {
|
||||
var queryString = "";
|
||||
var keys = Object.keys(params);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
var value = params[key];
|
||||
if (value === null || value === void 0) {
|
||||
continue;
|
||||
}
|
||||
queryString += encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&";
|
||||
}
|
||||
return queryString.slice(0, -1);
|
||||
}
|
||||
var baseUrl = "https://dbox.tools/";
|
||||
var baseApiUrl = joinUrl(baseUrl, "api");
|
||||
var dboxApi = {
|
||||
/**
|
||||
* @enum {string} DBox.API.System
|
||||
* @readonly
|
||||
*/
|
||||
System: {
|
||||
/** @type {string} Xbox */
|
||||
xbox: "XBOX",
|
||||
/** @type {string} Xbox 360 */
|
||||
xbox360: "XBOX360",
|
||||
/** @type {string} Xbox One */
|
||||
xboxOne: "XBOXONE",
|
||||
/** @type {string} Xbox Series X */
|
||||
xboxSeriesX: "XBOXSERIESX",
|
||||
/** @type {string} PC */
|
||||
pc: "PC",
|
||||
/** @type {string} PS3 */
|
||||
mobile: "MOBILE"
|
||||
},
|
||||
Discs: {
|
||||
/**
|
||||
* Get and filter discs
|
||||
* @param {string | null} name query
|
||||
* @param {DBox.API.System} system query
|
||||
* @param {integer | number} [limit] query, default: 100
|
||||
* @param {integer | number} [offset] query, default: 0
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getDiscs: function(name, system, limit, offset) {
|
||||
var params = {};
|
||||
if (name) params.name = name;
|
||||
if (system) params.system = system;
|
||||
if (limit) params.limit = limit;
|
||||
if (offset) params.offset = offset;
|
||||
|
||||
return joinUrl(baseApiUrl, "discs") +
|
||||
"?" + buildParams(params);
|
||||
},
|
||||
/**
|
||||
* Get single disc by DBox ID
|
||||
* @param {integer | number} discId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleDiscById: function(discId) {
|
||||
return joinUrl(baseApiUrl, "discs/" + discId);
|
||||
},
|
||||
/**
|
||||
* Get single disc by Redump ID
|
||||
* @param {integer | number} redumpId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleDiscByRedumpId: function(redumpId) {
|
||||
return joinUrl(baseApiUrl, "discs/redump/" + redumpId);
|
||||
},
|
||||
/**
|
||||
* Get single disc by its XMID (OG XBOX only)
|
||||
* @param {string} xmid path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleDiscByXMId: function(xmid) {
|
||||
return joinUrl(baseApiUrl, "discs/xmid/" + xmid);
|
||||
},
|
||||
/**
|
||||
* Get single disc by its XeMID (XBOX 360 only)
|
||||
* @param {string} xeMid path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleDiscByXeMId: function(xeMid) {
|
||||
return joinUrl(baseApiUrl, "discs/xemid/" + xeMid);
|
||||
},
|
||||
/**
|
||||
* Get single disc by its media ID. Media ID v1 (XBOX & XBOX 360) and Media ID v2 (XBOX One & XBOX Series) are combined in a single query
|
||||
* @param {string} mediaId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleDiscByMediaId: function(mediaId) {
|
||||
return joinUrl(baseApiUrl, "discs/media_id/" + mediaId);
|
||||
},
|
||||
/**
|
||||
* Get the dirs and files (if available) for a disc. Filetype indicates if it is a supported filetype that has further metadata available in the database.
|
||||
* @param {integer | number} discId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getDiscFiles: function(discId) {
|
||||
return joinUrl(baseApiUrl, "discs/" + discId + "/files");
|
||||
}
|
||||
},
|
||||
Releases: {
|
||||
/**
|
||||
* Get and filter releases
|
||||
* @param {string | null} name query
|
||||
* @param {string | null} edition query
|
||||
* @param {string | null} barcode query
|
||||
* @param {DBox.API.System} system query
|
||||
* @param {integer | number} limit query, default: 100
|
||||
* @param {integer | number} offset query, default: 0
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getReleases: function(name, edition, barcode, system, limit, offset) {
|
||||
var params = {};
|
||||
if (name) params.name = name;
|
||||
if (edition) params.edition = edition;
|
||||
if (barcode) params.barcode = barcode;
|
||||
if (system) params.system = system;
|
||||
if (limit) params.limit = limit;
|
||||
if (offset) params.offset = offset;
|
||||
return joinUrl(baseApiUrl, "releases") +
|
||||
"?" + buildParams(params);
|
||||
},
|
||||
/**
|
||||
* Get single release by DBox ID
|
||||
* @param {string} releaseId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleRelease: function(releaseId) {
|
||||
return joinUrl(baseApiUrl, "releases/" + releaseId);
|
||||
}
|
||||
},
|
||||
Files: {
|
||||
/**
|
||||
* Get all discs that contain a particular file. NOTE: not all discs have been parsed on file-level yet
|
||||
* @param {string} md5 path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getFiles: function(md5) {
|
||||
return joinUrl(baseApiUrl, "files/" + md5 + "/discs");
|
||||
},
|
||||
/**
|
||||
* Filter all distinct xbe files. NOTE: not all discs have been parsed on file-level yet
|
||||
* @param {string | null} titleId query
|
||||
* @param {integer | null} allowrdMedia query
|
||||
* @param {integer | null} region query, Available values: 1, 2, 3, 4, 7, 2147483648
|
||||
* @param {integer | null} gameRating query
|
||||
* @param {integer | null} discNumber query
|
||||
* @param {integer | null} version query
|
||||
* @param {integer | number} limit query, default: 100
|
||||
* @param {integer | number} offset query, default: 0
|
||||
* @returns
|
||||
*/
|
||||
getXbeFiles: function(titleId, allowrdMedia, region, gameRating, discNumber, version, limit, offset) {
|
||||
if (region !== null && region !== undefined) {
|
||||
var valid = [1, 2, 3, 4, 7, 2147483648];
|
||||
if (!valid.includes(region)) throw new Error('Invalid region');
|
||||
}
|
||||
var params = {};
|
||||
if (titleId) params.title_id = titleId;
|
||||
if (allowrdMedia) params.allowrd_media = allowrdMedia;
|
||||
if (region) params.region = region;
|
||||
if (gameRating) params.game_rating = gameRating;
|
||||
if (discNumber) params.disc_number = discNumber;
|
||||
if (version) params.version = version;
|
||||
if (limit) params.limit = limit;
|
||||
if (offset) params.offset = offset;
|
||||
return joinUrl(baseApiUrl, "files/xbe") +
|
||||
"?" + buildParams(params);
|
||||
},
|
||||
/**
|
||||
* Get xbe file by md5. NOTE: not all discs have been parsed on file-level yet
|
||||
* @param {string} md5 path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getXbeFileByMd5: function(md5) {
|
||||
return joinUrl(baseApiUrl, "files/xbe/" + md5);
|
||||
},
|
||||
/**
|
||||
* Get stfs file by md5. NOTE: not all discs have been parsed on file-level yet
|
||||
* @param {string} md5 path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getStfsFileByMd5: function(md5) {
|
||||
return joinUrl(baseApiUrl, "files/stfs/" + md5);
|
||||
},
|
||||
},
|
||||
TitleIDs: {
|
||||
/**
|
||||
* Get and filter title IDs
|
||||
* @param {string | (string | null)} name query
|
||||
* @param {DBox.API.System | null} system query
|
||||
* @param {string | (string | null)($uuid)} bingId query
|
||||
* @param {string | (string | null)($uuid)} serviceConfigId query
|
||||
* @param {integer} limit query, default: 100
|
||||
* @param {integer} offset query, default: 0
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getTitleIds: function(name, system, bingId, serviceConfigId, limit, offset) {
|
||||
var params = {};
|
||||
if (name) params.name = name;
|
||||
if (system) params.system = system;
|
||||
if (bingId) params.bing_id = bingId;
|
||||
if (serviceConfigId) params.service_config_id = serviceConfigId;
|
||||
if (limit) params.limit = limit;
|
||||
if (offset) params.offset = offset;
|
||||
return joinUrl(baseApiUrl, "title_ids") +
|
||||
"?" + buildParams(params);
|
||||
},
|
||||
/**
|
||||
* Get single title ID by its hexadecimal value
|
||||
* @param {string} titleId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleTitleId: function(titleId) {
|
||||
return joinUrl(baseApiUrl, "title_ids/" + titleId);
|
||||
}
|
||||
},
|
||||
Achievements: {
|
||||
/**
|
||||
* Get achievements for a title-id. Xbox 360/GFWL only
|
||||
* @param {string} titleId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getAchievementsV1: function(titleId) {
|
||||
return joinUrl(baseApiUrl, "achievements/v1/" + titleId);
|
||||
},
|
||||
/**
|
||||
* Get achievements for a title-id. Xbox One/Series only
|
||||
* @param {string} titleId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getAchievementsV2: function(titleId) {
|
||||
return joinUrl(baseApiUrl, "achievements/v2/" + titleId);
|
||||
},
|
||||
},
|
||||
Marketplace: {
|
||||
/**
|
||||
* Get and filter marketplace products
|
||||
* @param {integer | (integer | null)} productType query
|
||||
* @param {integer} limit query, default: 100
|
||||
* @param {integer} offset query, default: 0
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getProducts: function(productType, limit, offset) {
|
||||
var params = {};
|
||||
if (productType) params.product_type = productType;
|
||||
if (limit) params.limit = limit;
|
||||
if (offset) params.offset = offset;
|
||||
return joinUrl(baseApiUrl, "marketplace/products") +
|
||||
"?" + buildParams(params);
|
||||
},
|
||||
/**
|
||||
* Get single marketplace product by marketplace product ID
|
||||
* @param {string} productId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleProduct: function(productId) {
|
||||
return joinUrl(baseApiUrl, "marketplace/products/" + productId);
|
||||
},
|
||||
/**
|
||||
* Get children of a marketplace product
|
||||
* @param {string} productId path, required
|
||||
* @param {integer | (integer | null)} productType query
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getProductChildren: function(productId, productType) {
|
||||
var params = {};
|
||||
if (productType) params.product_type = productType;
|
||||
return joinUrl(baseApiUrl, "marketplace/products/" + productId + "/children") +
|
||||
"?" + buildParams(params);
|
||||
},
|
||||
/**
|
||||
* Get and filter marketplace product instances
|
||||
* @param {string | (string | null)($uuid)} productId query
|
||||
* @param {string | (string | null)} hexOfferId query
|
||||
* @param {integer | (integer | null)} licenseTypeId query
|
||||
* @param {integer | (integer | null)} packageType query
|
||||
* @param {integer | (integer | null)} gameRegion query
|
||||
* @param {integer} limit query, default: 100
|
||||
* @param {integer} offset query, default: 0
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getProductInstances: function(productId, hexOfferId, licenseTypeId, packageType, gameRegion, limit, offset) {
|
||||
var params = {};
|
||||
if (productId) params.product_id = productId;
|
||||
if (hexOfferId) params.hex_offer_id = hexOfferId;
|
||||
if (licenseTypeId) params.license_type_id = licenseTypeId;
|
||||
if (packageType) params.package_type = packageType;
|
||||
if (gameRegion) params.game_region = gameRegion;
|
||||
if (limit) params.limit = limit;
|
||||
if (offset) params.offset = offset;
|
||||
return joinUrl(baseApiUrl, "marketplace/product-instances") +
|
||||
"?" + buildParams(params);
|
||||
},
|
||||
/**
|
||||
* Get single marketplace product instance by marketplace product instance ID
|
||||
* @param {string} instanceId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getProductInstanceById: function(instanceId) {
|
||||
return joinUrl(baseApiUrl, "marketplace/product-instances/" + instanceId);
|
||||
},
|
||||
/**
|
||||
* Get all marketplace product types
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getProductTypes: function() {
|
||||
return joinUrl(baseApiUrl, "marketplace/product-types");
|
||||
},
|
||||
/**
|
||||
* Get single marketplace category
|
||||
* @param {integer} productTypeId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleProductType: function(productTypeId) {
|
||||
return joinUrl(baseApiUrl, "marketplace/product-types/" + productTypeId);
|
||||
},
|
||||
/**
|
||||
* Get and filter all marketplace categories
|
||||
* @param {integer | (integer | null)} parent query
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getCategories: function(parent) {
|
||||
var params = {};
|
||||
if (parent) params.parent = parent;
|
||||
return joinUrl(baseApiUrl, "marketplace/categories") +
|
||||
"?" + buildParams(params);
|
||||
},
|
||||
/**
|
||||
* Get single marketplace category
|
||||
* @param {integer} categoryId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleCategory: function(categoryId) {
|
||||
return joinUrl(baseApiUrl, "marketplace/categories/" + categoryId);
|
||||
},
|
||||
/**
|
||||
* Get all marketplace locales
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getLocales: function() {
|
||||
return joinUrl(baseApiUrl, "marketplace/locales");
|
||||
},
|
||||
/**
|
||||
* Get single marketplace locale by locale string
|
||||
* @param {string} localeId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleLocale: function(localeId) {
|
||||
return joinUrl(baseApiUrl, "marketplace/locales/" + localeId);
|
||||
},
|
||||
},
|
||||
/**
|
||||
* Enum for product types, used in store API
|
||||
* @enum {string} DBox.API.ProductType
|
||||
*/
|
||||
ProductType: {
|
||||
application: "Application",
|
||||
avatarItem: "AvatarItem",
|
||||
consumable: "Consumable",
|
||||
durable: "Durable",
|
||||
game: "Game",
|
||||
movie: "Movie",
|
||||
pass: "PASS",
|
||||
tvSeries: "TvSeries",
|
||||
tvSeason: "TvSeason",
|
||||
tvEpisode: "TVEpisode",
|
||||
unmanagedConsumable: "UnmanagedConsumable",
|
||||
},
|
||||
/**
|
||||
* Enum for product families, used in store API
|
||||
* @enum {string} DBox.API.ProductFamily
|
||||
*/
|
||||
ProductFamily: {
|
||||
apps: "Apps",
|
||||
avatars: "Avatars",
|
||||
games: "Games",
|
||||
movies: "Movies",
|
||||
passes: "Passes",
|
||||
tv: "TV",
|
||||
},
|
||||
/**
|
||||
* Enum for order by, used in store API
|
||||
* @enum {string} DBox.API.OrderBy
|
||||
*/
|
||||
OrderBy: {
|
||||
productId: "product_id",
|
||||
titleId: "title_id",
|
||||
revisionId: "revision_id",
|
||||
/** such as "23654onetwoonestudio.cctv_kdpw61jgbrs34" */
|
||||
packageFamilyName: "package_family_name",
|
||||
/** such as "23654onetwoonestudio.cctv" */
|
||||
packageIdentityName: "package_identity_name",
|
||||
},
|
||||
/**
|
||||
* Enum for order direction, used in store API
|
||||
* @enum {string} DBox.API.OrderDirection
|
||||
*/
|
||||
OrderDirection: {
|
||||
/** @type {string} 升序 */
|
||||
asc: "asc",
|
||||
/** @type {string} 降序 */
|
||||
desc: "desc",
|
||||
},
|
||||
Store: {
|
||||
/**
|
||||
* Get store products
|
||||
* @param {string | (string | null)} category query
|
||||
* @param {string | (string | null)} titleId query
|
||||
* @param {DBox.API.ProductType | null} productType query
|
||||
* @param {DBox.API.ProductFamily | null} productFamily query
|
||||
* @param {DBox.API.OrderBy | null} orderBy query, default: productId
|
||||
* @param {DBox.API.OrderDirection | null} orderDirection query, default: asc
|
||||
* @param {integer} limit query, default: 100
|
||||
* @param {integer} offset query, default: 0
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getProducts: function(category, titleId, productType, productFamily, orderBy, orderDirection, limit, offset) {
|
||||
var params = {};
|
||||
if (category) params.category = category;
|
||||
if (titleId) params.title_id = titleId;
|
||||
if (productType) params.product_type = productType;
|
||||
if (productFamily) params.product_family = productFamily;
|
||||
if (orderBy) params.order_by = orderBy;
|
||||
if (orderDirection) params.order_direction = orderDirection;
|
||||
if (limit) params.limit = limit;
|
||||
if (offset) params.offset = offset;
|
||||
return joinUrl(baseApiUrl, "store/products") +
|
||||
"?" + buildParams(params);
|
||||
},
|
||||
/**
|
||||
* Get single store product
|
||||
* @param {string} productId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleProduct: function(productId) {
|
||||
return joinUrl(baseApiUrl, "store/products/" + productId);
|
||||
},
|
||||
/**
|
||||
* Get all related products for a product id. Includes both child and parent relationships. Check the product-ids for relationship direction. The relationship_type is parent -> child direction. Same combinations can appear multiple times with different relationship types.
|
||||
* @param {string} productId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getAllReleatedProducts: function(productId) {
|
||||
return joinUrl(baseApiUrl, "store/products/" + productId + "/related");
|
||||
},
|
||||
/**
|
||||
* Get single sku for store product
|
||||
* @param {string} productId path, required
|
||||
* @param {string} skuId path, required
|
||||
* @returns {string} request URL, method: GET
|
||||
*/
|
||||
getSingleSkuFromProduct: function(productId, skuId) {
|
||||
return joinUrl(baseApiUrl, "store/products/" + productId + "/sku/" + skuId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function getXhr() {
|
||||
var xmlhttp;
|
||||
try {
|
||||
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
} catch (e) {
|
||||
try {
|
||||
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
} catch (E) {
|
||||
xmlhttp = false;
|
||||
}
|
||||
}
|
||||
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
|
||||
xmlhttp = new XMLHttpRequest();
|
||||
}
|
||||
return xmlhttp;
|
||||
}
|
||||
/**
|
||||
* Send an HTTP request to the DBox API and return a Promise that resolves with the response.
|
||||
* @param {string} api DBox API
|
||||
* @param {string} method
|
||||
* @param {[boolean]} isAsync default: true
|
||||
* @param {[string]} username
|
||||
* @param {[string]} pwd
|
||||
* @returns {Promise <XMLHttpRequest>} A Promise that resolves with the response.
|
||||
*/
|
||||
var dboxXHR = function(api, method, isAsync, username, pwd) {
|
||||
method = method || "GET";
|
||||
if (typeof isAsync === "undefined" || isAsync === null) isAsync = true;
|
||||
var xhr = getXhr();
|
||||
if (username && pwd) {
|
||||
try {
|
||||
xhr.open(method, api, isAsync, username, pwd);
|
||||
} catch (e) {
|
||||
xhr.open(method, api, isAsync);
|
||||
}
|
||||
} else {
|
||||
xhr.open(method, api, isAsync);
|
||||
}
|
||||
return new Promise(function(c, e) {
|
||||
try {
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status == 200) {
|
||||
if (c) c(xhr);
|
||||
} else {
|
||||
if (e) e(xhr.statusText + " (" + xhr.status + ")");
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send("");
|
||||
} catch (ex) {
|
||||
if (e) e(ex);
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Send an HTTP request to the DBox API and return a Promise that resolves with the response as JSON.
|
||||
* @param {string} api DBox API
|
||||
* @param {string} method
|
||||
* @param {[boolean]} isAsync default: true
|
||||
* @param {[string]} username
|
||||
* @param {[string]} pwd
|
||||
* @returns {Promise <object>} A Promise that resolves with the response as JSON.
|
||||
*/
|
||||
dboxXHR.parseJson = function(api, method, isAsync, username, pwd) {
|
||||
return dboxXHR(api, method, isAsync, username, pwd).then(function(xhr) {
|
||||
return JSON.parse(xhr.responseText);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* DBox namespace
|
||||
* @namespace {DBox}
|
||||
*/
|
||||
global.DBox = {
|
||||
/**
|
||||
* DBox API namespace
|
||||
* @namespace {DBox.API}
|
||||
*/
|
||||
API: dboxApi,
|
||||
/**
|
||||
* @function {DBox.XHR}
|
||||
*/
|
||||
xhr: dboxXHR,
|
||||
};
|
||||
})(this);
|
||||
208
shared/html/js/http.js
Normal file
@@ -0,0 +1,208 @@
|
||||
(function(global) {
|
||||
if (typeof global.Web === "undefined") global.Web = {};
|
||||
|
||||
function dataToString(obj) {
|
||||
if (typeof obj === "string") return obj;
|
||||
if (typeof obj === "object") return JSON.stringify(obj);
|
||||
return String(obj);
|
||||
}
|
||||
global.Web.Http = {
|
||||
Request: function() {
|
||||
var inst = external.Web.Http.createHttpRequest();
|
||||
this.open = function(method, url) { inst.open(method, url); };
|
||||
this.getHeaders = function() { return JSON.parse(inst.getHeadersToJson()); };
|
||||
this.getHeader = function(swName) { try { return inst.getHeader(swName); } catch (e) { return void 0; } };
|
||||
this.setHeader = function(swName, swValue) { inst.setHeader(swName, swValue); };
|
||||
this.removeHeader = function(swName) { inst.removeHeader(swName); };
|
||||
this.clearHeader = function() { inst.clearHeader(); };
|
||||
this.updateHeaders = function(headers) {
|
||||
var keys = Object.keys(headers);
|
||||
this.clearHeader();
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
this.setHeader(keys[i], dataToString(headers[keys[i]]));
|
||||
}
|
||||
};
|
||||
this.setHeaders = function(headers) {
|
||||
var keys = Object.keys(headers);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
inst.setHeader(keys[i], dataToString(headers[keys[i]]));
|
||||
}
|
||||
};
|
||||
this.send = function(body, encoding) { return inst.send(body, encoding); };
|
||||
this.sendAsync = function(body, encoding) {
|
||||
if (!encoding) encoding = "utf-8";
|
||||
return new Promise(function(c, e) {
|
||||
try {
|
||||
inst.sendAsync(body, encoding, function(resp) {
|
||||
if (c) c(resp);
|
||||
}, function(err) {
|
||||
if (e) e(err);
|
||||
});
|
||||
} catch (ex) { if (e) e(ex); }
|
||||
});
|
||||
};
|
||||
Object.defineProperty(this, "timeout", {
|
||||
get: function() { return inst.timeout; },
|
||||
set: function(value) { inst.timeout = value; }
|
||||
});
|
||||
Object.defineProperty(this, "readWriteTimeout", {
|
||||
get: function() { return inst.readWriteTimeout; },
|
||||
set: function(value) { inst.readWriteTimeout = value; }
|
||||
});
|
||||
Object.defineProperty(this, "allowAutoRedirect", {
|
||||
get: function() { return inst.allowAutoRedirect; },
|
||||
set: function(value) { inst.allowAutoRedirect = value; }
|
||||
});
|
||||
Object.defineProperty(this, "allowWriteStreamBuffering", {
|
||||
get: function() { return inst.allowWriteStreamBuffering; },
|
||||
set: function(value) { inst.allowWriteStreamBuffering = value; }
|
||||
});
|
||||
Object.defineProperty(this, "keepAlive", {
|
||||
get: function() { return inst.keepAlive; },
|
||||
set: function(value) { inst.keepAlive = value; }
|
||||
});
|
||||
Object.defineProperty(this, "maximumAutomaticRedirections", {
|
||||
get: function() { return inst.maximumAutomaticRedirections; },
|
||||
set: function(value) { inst.maximumAutomaticRedirections = value; }
|
||||
});
|
||||
Object.defineProperty(this, "userAgent", {
|
||||
get: function() { return inst.userAgent; },
|
||||
set: function(value) { inst.userAgent = value; }
|
||||
});
|
||||
Object.defineProperty(this, "referer", {
|
||||
get: function() { return inst.referer; },
|
||||
set: function(value) { inst.referer = value; }
|
||||
});
|
||||
Object.defineProperty(this, "contentType", {
|
||||
get: function() { return inst.contentType; },
|
||||
set: function(value) { inst.contentType = value; }
|
||||
});
|
||||
Object.defineProperty(this, "accept", {
|
||||
get: function() { return inst.accept; },
|
||||
set: function(value) { inst.accept = value; }
|
||||
});
|
||||
Object.defineProperty(this, "proxy", {
|
||||
get: function() { return inst.proxy; },
|
||||
set: function(value) { inst.proxy = value; }
|
||||
});
|
||||
Object.defineProperty(this, "cookieContainer", {
|
||||
get: function() { return inst.cookieContainer; },
|
||||
set: function(value) { inst.cookieContainer = value; }
|
||||
});
|
||||
Object.defineProperty(this, "protocolVersion", {
|
||||
get: function() { return inst.protocolVersion; },
|
||||
set: function(value) { inst.protocolVersion = value; }
|
||||
});
|
||||
Object.defineProperty(this, "preAuthenticate", {
|
||||
get: function() { return inst.preAuthenticate; },
|
||||
set: function(value) { inst.preAuthenticate = value; }
|
||||
});
|
||||
Object.defineProperty(this, "credentials", {
|
||||
get: function() { return inst.credentials; },
|
||||
set: function(value) { inst.credentials = value; }
|
||||
});
|
||||
Object.defineProperty(this, "automaticDecompression", {
|
||||
get: function() { return inst.automaticDecompression; },
|
||||
set: function(value) { inst.automaticDecompression = value; }
|
||||
});
|
||||
this.dispose = function() { inst.dispose(); };
|
||||
},
|
||||
Header: {
|
||||
// 通用头(既可用于请求也可用于响应)
|
||||
General: {
|
||||
cacheControl: "Cache-Control",
|
||||
connection: "Connection",
|
||||
date: "Date",
|
||||
pragma: "Pragma",
|
||||
trailer: "Trailer",
|
||||
transferEncoding: "Transfer-Encoding",
|
||||
upgrade: "Upgrade",
|
||||
via: "Via",
|
||||
warning: "Warning"
|
||||
},
|
||||
// 请求头
|
||||
Request: {
|
||||
accept: "Accept",
|
||||
acceptCharset: "Accept-Charset",
|
||||
acceptEncoding: "Accept-Encoding",
|
||||
acceptLanguage: "Accept-Language",
|
||||
authorization: "Authorization",
|
||||
expect: "Expect",
|
||||
from: "From",
|
||||
host: "Host",
|
||||
ifMatch: "If-Match",
|
||||
ifModifiedSince: "If-Modified-Since",
|
||||
ifNoneMatch: "If-None-Match",
|
||||
ifRange: "If-Range",
|
||||
ifUnmodifiedSince: "If-Unmodified-Since",
|
||||
maxForwards: "Max-Forwards",
|
||||
proxyAuthorization: "Proxy-Authorization",
|
||||
range: "Range",
|
||||
referer: "Referer",
|
||||
te: "TE",
|
||||
userAgent: "User-Agent"
|
||||
},
|
||||
// 响应头
|
||||
Response: {
|
||||
acceptRanges: "Accept-Ranges",
|
||||
age: "Age",
|
||||
allow: "Allow",
|
||||
contentEncoding: "Content-Encoding",
|
||||
contentLanguage: "Content-Language",
|
||||
contentLength: "Content-Length",
|
||||
contentLocation: "Content-Location",
|
||||
contentRange: "Content-Range",
|
||||
contentType: "Content-Type",
|
||||
etag: "ETag",
|
||||
expires: "Expires",
|
||||
lastModified: "Last-Modified",
|
||||
location: "Location",
|
||||
proxyAuthenticate: "Proxy-Authenticate",
|
||||
retryAfter: "Retry-After",
|
||||
server: "Server",
|
||||
setCookie: "Set-Cookie",
|
||||
vary: "Vary",
|
||||
wwwAuthenticate: "WWW-Authenticate"
|
||||
},
|
||||
// CORS 相关头(常单独列出,也可归入请求/响应)
|
||||
Cors: {
|
||||
accessControlAllowOrigin: "Access-Control-Allow-Origin",
|
||||
accessControlAllowCredentials: "Access-Control-Allow-Credentials",
|
||||
accessControlAllowHeaders: "Access-Control-Allow-Headers",
|
||||
accessControlAllowMethods: "Access-Control-Allow-Methods",
|
||||
accessControlExposeHeaders: "Access-Control-Expose-Headers",
|
||||
accessControlMaxAge: "Access-Control-Max-Age",
|
||||
accessControlRequestHeaders: "Access-Control-Request-Headers",
|
||||
accessControlRequestMethod: "Access-Control-Request-Method",
|
||||
origin: "Origin"
|
||||
},
|
||||
// 安全/非标准常用头
|
||||
Security: {
|
||||
xFrameOptions: "X-Frame-Options",
|
||||
xContentTypeOptions: "X-Content-Type-Options",
|
||||
xXssProtection: "X-XSS-Protection",
|
||||
strictTransportSecurity: "Strict-Transport-Security",
|
||||
contentSecurityPolicy: "Content-Security-Policy",
|
||||
referrerPolicy: "Referrer-Policy",
|
||||
xRequestedWith: "X-Requested-With",
|
||||
xForwardedFor: "X-Forwarded-For",
|
||||
xForwardedProto: "X-Forwarded-Proto",
|
||||
xRealIp: "X-Real-IP"
|
||||
}
|
||||
},
|
||||
Method: {
|
||||
get: "GET",
|
||||
post: "POST",
|
||||
put: "PUT",
|
||||
delete: "DELETE",
|
||||
head: "HEAD",
|
||||
options: "OPTIONS",
|
||||
trace: "TRACE",
|
||||
connect: "CONNECT"
|
||||
},
|
||||
Version: {
|
||||
v1_0: "1.0",
|
||||
v1_1: "1.1",
|
||||
}
|
||||
}
|
||||
})(this);
|
||||
@@ -162,15 +162,16 @@
|
||||
}
|
||||
oldTags.push(k);
|
||||
promises.push(
|
||||
anime.runAsync(p.page, [
|
||||
anime.Keyframes.Opacity.hidden
|
||||
]).then((function(page, key) {
|
||||
return function() {
|
||||
page.style.display = "none";
|
||||
page.style.opacity = 0;
|
||||
emit("unload", key);
|
||||
};
|
||||
})(p.page, k))
|
||||
(function(page, key) {
|
||||
// 返回 anime.runAsync 产生的 Promise
|
||||
return anime.runAsync(page, [anime.Keyframes.Opacity.hidden])
|
||||
.then(function() {
|
||||
page.style.display = "none";
|
||||
page.style.opacity = 0;
|
||||
page.style.height = 0;
|
||||
emit("unload", key);
|
||||
});
|
||||
})(p.page, k)
|
||||
);
|
||||
p.guide.classList.remove("selected");
|
||||
}
|
||||
|
||||
@@ -509,7 +509,7 @@
|
||||
supportDisplay.classList.add("not-support");
|
||||
supportDisplay.classList.remove("support");
|
||||
}
|
||||
supportDisplay.setAttribute("title", strutils.format("OS Min Version: {0}, Architecture: {1}", support.showOsminversionText, support.showArchitectureText));
|
||||
supportDisplay.setAttribute("title", strutils.format(Bridge.Resources.byname("IDS_PREINSTALL_SUITCONDITION"), support.showOsminversionText, support.showArchitectureText));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,13 @@
|
||||
},
|
||||
cancelAll: function() { external.Package.Reader.cancelAll(); },
|
||||
addApplicationReadItem: function(swItemName) { return external.Package.Reader.addApplicationItem(swItemName); },
|
||||
removeApplicationReadItem: function(swItemName) { return external.Package.Reader.removeApplicationItem(swItemName); }
|
||||
removeApplicationReadItem: function(swItemName) { return external.Package.Reader.removeApplicationItem(swItemName); },
|
||||
updateApplicationReadItems: function(aswArray) {
|
||||
external.Package.Reader.updateApplicationItems(aswArray);
|
||||
},
|
||||
getApplicationReadItems: function() {
|
||||
return JSON.parse(external.Package.Reader.getApplicationItemsToJson());
|
||||
},
|
||||
},
|
||||
manager: {
|
||||
add: function(swPkgPath, uOptions) {
|
||||
@@ -169,5 +175,76 @@
|
||||
cancelAll: function() { mgr.cancelAll(); },
|
||||
active: function(swAppUserModelID, swArgs) { return mgr.activeApp(swAppUserModelID, swArgs || null); }
|
||||
},
|
||||
utils: (function() {
|
||||
// 解析包全名,格式: <name>_<version>_<processorArchitecture>_<resourceId>_<publisherId>
|
||||
// resourceId 可能为空(表现为两个连续下划线)
|
||||
function parsePackageFullName(fullName) {
|
||||
var parts = fullName.split('_');
|
||||
// 按格式应有5部分: [name, version, architecture, resourceId, publisherId]
|
||||
return {
|
||||
name: parts[0],
|
||||
version: parts[1],
|
||||
architecture: parts[2],
|
||||
resourceId: parts[3],
|
||||
publisherId: parts[4]
|
||||
};
|
||||
}
|
||||
|
||||
// 解析包系列名,格式: <name>_<publisherId>
|
||||
function parsePackageFamilyName(familyName) {
|
||||
var underscoreIndex = familyName.indexOf('_');
|
||||
if (underscoreIndex === -1) {
|
||||
// 异常情况,按原字符串处理,但题目不会出现
|
||||
return { name: familyName, publisherId: '' };
|
||||
}
|
||||
return {
|
||||
name: familyName.substring(0, underscoreIndex),
|
||||
publisherId: familyName.substring(underscoreIndex + 1)
|
||||
};
|
||||
}
|
||||
|
||||
// 将对象转换为包全名字符串
|
||||
// 对象应包含 name, version, architecture, publisherId 字段,resourceId 可选
|
||||
function stringifyPackageFullName(pkg) {
|
||||
var resourcePart = (pkg.resourceId === undefined || pkg.resourceId === null) ? '' : pkg.resourceId;
|
||||
return pkg.name + '_' + pkg.version + '_' + pkg.architecture + '_' + resourcePart + '_' + pkg.publisherId;
|
||||
}
|
||||
|
||||
// 将对象转换为包系列名字符串
|
||||
// 对象应包含 name, publisherId 字段
|
||||
function stringifyPackageFamilyName(pkgFamily) {
|
||||
return pkgFamily.name + '_' + pkgFamily.publisherId;
|
||||
}
|
||||
return {
|
||||
parsePackageFullName: parsePackageFullName,
|
||||
parsePackageFamilyName: parsePackageFamilyName,
|
||||
stringifyPackageFullName: stringifyPackageFullName,
|
||||
stringifyPackageFamilyName: stringifyPackageFamilyName,
|
||||
isDependency: function(swPkgIdentityName) {
|
||||
var list = [
|
||||
"Microsoft.Net.Native.Framework",
|
||||
"Microsoft.Net.Native.Runtime",
|
||||
"Microsoft.Net.CoreRuntime",
|
||||
"WindowsPreview.Kinect",
|
||||
"Microsoft.VCLibs",
|
||||
"Microsoft.WinJS",
|
||||
"Microsoft.UI.Xaml",
|
||||
"Microsoft.WindowsAppRuntime",
|
||||
"Microsoft.Advertising.XAML",
|
||||
"Microsoft.Midi.Gmdls",
|
||||
"Microsoft.Services.Store.Engagement",
|
||||
"Microsoft.Media.PlayReadyClient"
|
||||
];
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
if (swPkgIdentityName.toLowerCase().indexOf(list[i].toLowerCase()) !== -1)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
})()
|
||||
};
|
||||
global.Package.Reader = global.Package.reader;
|
||||
global.Package.Manager = global.Package.manager;
|
||||
global.Package.Utils = global.Package.utils;
|
||||
})(this);
|
||||
@@ -215,4 +215,416 @@
|
||||
}
|
||||
};
|
||||
}
|
||||
})(this);
|
||||
(function(global) {
|
||||
if (typeof global.Map === "undefined") {
|
||||
function Map() {
|
||||
this.elements = new Array();
|
||||
// 获取Map元素个数
|
||||
this.size = function() {
|
||||
return this.elements.length;
|
||||
},
|
||||
// 判断Map是否为空
|
||||
this.isEmpty = function() {
|
||||
return (this.elements.length < 1);
|
||||
},
|
||||
// 删除Map所有元素
|
||||
this.clear = function() {
|
||||
this.elements = new Array();
|
||||
},
|
||||
// 向Map中增加元素(key, value)
|
||||
this.put = function(_key, _value) {
|
||||
if (this.containsKey(_key) == true) {
|
||||
if (this.containsValue(_value)) {
|
||||
if (this.remove(_key) == true) {
|
||||
this.elements.push({
|
||||
key: _key,
|
||||
value: _value
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.elements.push({
|
||||
key: _key,
|
||||
value: _value
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.elements.push({
|
||||
key: _key,
|
||||
value: _value
|
||||
});
|
||||
}
|
||||
},
|
||||
// 向Map中增加元素(key, value)
|
||||
this.set = function(_key, _value) {
|
||||
if (this.containsKey(_key) == true) {
|
||||
if (this.containsValue(_value)) {
|
||||
if (this.remove(_key) == true) {
|
||||
this.elements.push({
|
||||
key: _key,
|
||||
value: _value
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.elements.push({
|
||||
key: _key,
|
||||
value: _value
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.elements.push({
|
||||
key: _key,
|
||||
value: _value
|
||||
});
|
||||
}
|
||||
},
|
||||
// 删除指定key的元素,成功返回true,失败返回false
|
||||
this.remove = function(_key) {
|
||||
var bln = false;
|
||||
try {
|
||||
for (i = 0; i < this.elements.length; i++) {
|
||||
if (this.elements[i].key == _key) {
|
||||
this.elements.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
bln = false;
|
||||
}
|
||||
return bln;
|
||||
},
|
||||
|
||||
// 删除指定key的元素,成功返回true,失败返回false
|
||||
this.delete = function(_key) {
|
||||
var bln = false;
|
||||
try {
|
||||
for (i = 0; i < this.elements.length; i++) {
|
||||
if (this.elements[i].key == _key) {
|
||||
this.elements.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
bln = false;
|
||||
}
|
||||
return bln;
|
||||
},
|
||||
|
||||
// 获取指定key的元素值value,失败返回null
|
||||
this.get = function(_key) {
|
||||
try {
|
||||
for (i = 0; i < this.elements.length; i++) {
|
||||
if (this.elements[i].key == _key) {
|
||||
return this.elements[i].value;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
// set指定key的元素值value
|
||||
this.setValue = function(_key, _value) {
|
||||
var bln = false;
|
||||
try {
|
||||
for (i = 0; i < this.elements.length; i++) {
|
||||
if (this.elements[i].key == _key) {
|
||||
this.elements[i].value = _value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
bln = false;
|
||||
}
|
||||
return bln;
|
||||
},
|
||||
|
||||
// 获取指定索引的元素(使用element.key,element.value获取key和value),失败返回null
|
||||
this.element = function(_index) {
|
||||
if (_index < 0 || _index >= this.elements.length) {
|
||||
return null;
|
||||
}
|
||||
return this.elements[_index];
|
||||
},
|
||||
|
||||
// 判断Map中是否含有指定key的元素
|
||||
this.containsKey = function(_key) {
|
||||
var bln = false;
|
||||
try {
|
||||
for (i = 0; i < this.elements.length; i++) {
|
||||
if (this.elements[i].key == _key) {
|
||||
bln = true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
bln = false;
|
||||
}
|
||||
return bln;
|
||||
},
|
||||
|
||||
// 判断Map中是否含有指定key的元素
|
||||
this.has = function(_key) {
|
||||
var bln = false;
|
||||
try {
|
||||
for (i = 0; i < this.elements.length; i++) {
|
||||
if (this.elements[i].key == _key) {
|
||||
bln = true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
bln = false;
|
||||
}
|
||||
return bln;
|
||||
},
|
||||
|
||||
// 判断Map中是否含有指定value的元素
|
||||
this.containsValue = function(_value) {
|
||||
var bln = false;
|
||||
try {
|
||||
for (i = 0; i < this.elements.length; i++) {
|
||||
if (this.elements[i].value == _value) {
|
||||
bln = true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
bln = false;
|
||||
}
|
||||
return bln;
|
||||
},
|
||||
|
||||
// 获取Map中所有key的数组(array)
|
||||
this.keys = function() {
|
||||
var arr = new Array();
|
||||
for (i = 0; i < this.elements.length; i++) {
|
||||
arr.push(this.elements[i].key);
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
|
||||
// 获取Map中所有value的数组(array)
|
||||
this.values = function() {
|
||||
var arr = new Array();
|
||||
for (i = 0; i < this.elements.length; i++) {
|
||||
arr.push(this.elements[i].value);
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
/**
|
||||
* map遍历数组
|
||||
* @param callback [function] 回调函数;
|
||||
* @param context [object] 上下文;
|
||||
*/
|
||||
this.forEach = function forEach(callback, context) {
|
||||
context = context || window;
|
||||
|
||||
//IE6-8下自己编写回调函数执行的逻辑
|
||||
var newAry = new Array();
|
||||
for (var i = 0; i < this.elements.length; i++) {
|
||||
if (typeof callback === 'function') {
|
||||
var val = callback.call(context, this.elements[i].value, this.elements[i].key, this.elements);
|
||||
newAry.push(this.elements[i].value);
|
||||
}
|
||||
}
|
||||
return newAry;
|
||||
}
|
||||
|
||||
}
|
||||
global.Map = Map;
|
||||
}
|
||||
})(this);
|
||||
(function(global) {
|
||||
if (typeof global.Set === "undefined") {
|
||||
function Set() {
|
||||
var items = {};
|
||||
this.size = 0;
|
||||
// 实现has方法
|
||||
// has(val)方法
|
||||
this.has = function(val) {
|
||||
// 对象都有hasOwnProperty方法,判断是否拥有特定属性
|
||||
return items.hasOwnProperty(val);
|
||||
};
|
||||
|
||||
// 实现add
|
||||
this.add = function(val) {
|
||||
if (!this.has(val)) {
|
||||
items[val] = val;
|
||||
this.size++; // 累加集合成员数量
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// delete(val)方法
|
||||
this.delete = function(val) {
|
||||
if (this.has(val)) {
|
||||
delete items[val]; // 将items对象上的属性删掉
|
||||
this.size--;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// clear方法
|
||||
this.clear = function() {
|
||||
items = {}; // 直接将集合赋一个空对象即可
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
// keys()方法
|
||||
this.keys = function() {
|
||||
return Object.keys(items); // 返回遍历集合的所有键名的数组
|
||||
};
|
||||
// values()方法
|
||||
this.values = function() {
|
||||
return Object.values(items); // 返回遍历集合的所有键值的数组
|
||||
};
|
||||
|
||||
// forEach(fn, context)方法
|
||||
this.forEach = function(fn, context) {
|
||||
for (var i = 0; i < this.size; i++) {
|
||||
var item = Object.keys(items)[i];
|
||||
fn.call(context, item, item, items);
|
||||
}
|
||||
};
|
||||
|
||||
// 并集
|
||||
this.union = function(other) {
|
||||
var union = new Set();
|
||||
var values = this.values();
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
union.add(values[i]);
|
||||
}
|
||||
values = other.values(); // 将values重新赋值为新的集合
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
union.add(values[i]);
|
||||
}
|
||||
|
||||
return union;
|
||||
};
|
||||
// 交集
|
||||
this.intersect = function(other) {
|
||||
var intersect = new Set();
|
||||
var values = this.values();
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (other.has(values[i])) { // 查看是否也存在于other中
|
||||
intersect.add(values[i]); // 存在的话就像intersect中添加元素
|
||||
}
|
||||
}
|
||||
return intersect;
|
||||
};
|
||||
|
||||
// 差集
|
||||
this.difference = function(other) {
|
||||
var difference = new Set();
|
||||
var values = this.values();
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (!other.has(values[i])) { // 将不存在于other集合中的添加到新的集合中
|
||||
difference.add(values[i]);
|
||||
}
|
||||
}
|
||||
return difference;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
global.Set = Set;
|
||||
}
|
||||
})(this);
|
||||
(function(global) {
|
||||
// 如果原生 WeakMap 已存在,则不覆盖
|
||||
if (typeof global.WeakMap !== "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
function WeakMap(iterable) {
|
||||
// 必须使用 new 调用
|
||||
if (!(this instanceof WeakMap)) {
|
||||
throw new TypeError('Constructor WeakMap requires "new"');
|
||||
}
|
||||
|
||||
// 私有存储:每个实例独立维护一个键值对数组
|
||||
var entries = [];
|
||||
|
||||
// 验证 key 必须是对象或函数(不能是 null 或原始值)
|
||||
function validateKey(key) {
|
||||
if (key === null || (typeof key !== 'object' && typeof key !== 'function')) {
|
||||
throw new TypeError('WeakMap key must be an object');
|
||||
}
|
||||
}
|
||||
|
||||
// 设置键值对
|
||||
this.set = function(key, value) {
|
||||
validateKey(key);
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
if (entries[i][0] === key) {
|
||||
entries[i][1] = value;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
entries.push([key, value]);
|
||||
return this;
|
||||
};
|
||||
|
||||
// 获取键对应的值
|
||||
this.get = function(key) {
|
||||
validateKey(key);
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
if (entries[i][0] === key) {
|
||||
return entries[i][1];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
// 判断是否存在指定键
|
||||
this.has = function(key) {
|
||||
validateKey(key);
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
if (entries[i][0] === key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// 删除指定键及其值
|
||||
this.delete = function(key) {
|
||||
validateKey(key);
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
if (entries[i][0] === key) {
|
||||
entries.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// 处理可选的初始化参数(iterable,例如 [[key1, value1], [key2, value2]])
|
||||
if (iterable !== null && iterable !== undefined) {
|
||||
// 支持数组或类数组(具备 forEach 方法的对象)
|
||||
if (typeof iterable.forEach === 'function') {
|
||||
var self = this;
|
||||
iterable.forEach(function(item) {
|
||||
if (!Array.isArray(item) || item.length < 2) {
|
||||
throw new TypeError('Iterator value is not an entry object');
|
||||
}
|
||||
self.set(item[0], item[1]);
|
||||
});
|
||||
} else if (typeof iterable.length === 'number') {
|
||||
// 类数组对象(如 arguments)
|
||||
for (var i = 0; i < iterable.length; i++) {
|
||||
var item = iterable[i];
|
||||
if (!Array.isArray(item) || item.length < 2) {
|
||||
throw new TypeError('Iterator value is not an entry object');
|
||||
}
|
||||
this.set(item[0], item[1]);
|
||||
}
|
||||
} else {
|
||||
throw new TypeError('WeakMap iterable is not iterable');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 挂载到全局对象
|
||||
global.WeakMap = WeakMap;
|
||||
})(this);
|
||||
285
shared/html/js/polyfill-winrt.js
Normal file
@@ -0,0 +1,285 @@
|
||||
(function(global) {
|
||||
function isString(obj) {
|
||||
return typeof obj === "string" || obj instanceof String;
|
||||
}
|
||||
|
||||
function isFunction(obj) {
|
||||
return typeof obj === "function";
|
||||
}
|
||||
|
||||
function isBool(obj) {
|
||||
return typeof obj === "boolean" || obj instanceof Boolean;
|
||||
}
|
||||
|
||||
function isNumber(obj) {
|
||||
return typeof obj === "number" || obj instanceof Number;
|
||||
}
|
||||
|
||||
function isDate(obj) {
|
||||
return obj instanceof Date;
|
||||
}
|
||||
|
||||
function isDevToolsOpen() {
|
||||
if (window.__IE_DEVTOOLBAR_CONSOLE_COMMAND_LINE) {
|
||||
return true; // IE10 或更早版本
|
||||
}
|
||||
if (window.__BROWSERTOOLS_CONSOLE) {
|
||||
return true; // IE11
|
||||
}
|
||||
if (window.__BROWSERTOOLS_DOMEXPLORER_ADDED) {
|
||||
return true; // IE11
|
||||
}
|
||||
return false;
|
||||
}
|
||||
var APIs = [
|
||||
"Windows.ApplicationModel.DesignMode.designModeEnabled",
|
||||
"Windows.ApplicationModel.Resources.Core.ResourceContext",
|
||||
"Windows.ApplicationModel.Resources.Core.ResourceManager",
|
||||
"Windows.ApplicationModel.Search.Core.SearchSuggestionManager",
|
||||
"Windows.ApplicationModel.Search.SearchQueryLinguisticDetails",
|
||||
"Windows.Data.Text.SemanticTextQuery",
|
||||
"Windows.Foundation.Collections.CollectionChange",
|
||||
"Windows.Foundation.Uri",
|
||||
"Windows.Globalization.ApplicationLanguages",
|
||||
"Windows.Globalization.Calendar",
|
||||
"Windows.Globalization.DateTimeFormatting",
|
||||
"Windows.Globalization.Language",
|
||||
"Windows.Phone.UI.Input.HardwareButtons",
|
||||
"Windows.Storage.ApplicationData",
|
||||
"Windows.Storage.CreationCollisionOption",
|
||||
"Windows.Storage.BulkAccess.FileInformationFactory",
|
||||
"Windows.Storage.FileIO",
|
||||
"Windows.Storage.FileProperties.ThumbnailType",
|
||||
"Windows.Storage.FileProperties.ThumbnailMode",
|
||||
"Windows.Storage.FileProperties.ThumbnailOptions",
|
||||
"Windows.Storage.KnownFolders",
|
||||
"Windows.Storage.Search.FolderDepth",
|
||||
"Windows.Storage.Search.IndexerOption",
|
||||
"Windows.Storage.Streams.RandomAccessStreamReference",
|
||||
"Windows.UI.ApplicationSettings.SettingsEdgeLocation",
|
||||
"Windows.UI.ApplicationSettings.SettingsCommand",
|
||||
"Windows.UI.ApplicationSettings.SettingsPane",
|
||||
"Windows.UI.Core.AnimationMetrics",
|
||||
"Windows.UI.Input.EdgeGesture",
|
||||
"Windows.UI.Input.EdgeGestureKind",
|
||||
"Windows.UI.Input.PointerPoint",
|
||||
"Windows.UI.ViewManagement.HandPreference",
|
||||
"Windows.UI.ViewManagement.InputPane",
|
||||
"Windows.UI.ViewManagement.UISettings",
|
||||
"Windows.UI.WebUI.Core.WebUICommandBar",
|
||||
"Windows.UI.WebUI.Core.WebUICommandBarBitmapIcon",
|
||||
"Windows.UI.WebUI.Core.WebUICommandBarClosedDisplayMode",
|
||||
"Windows.UI.WebUI.Core.WebUICommandBarIconButton",
|
||||
"Windows.UI.WebUI.Core.WebUICommandBarSymbolIcon",
|
||||
"Windows.UI.WebUI.WebUIApplication",
|
||||
];
|
||||
for (var i = 0; i < APIs.length; i++) {
|
||||
var api = APIs[i];
|
||||
apiNs = api.split(".");
|
||||
var lastNs = global;
|
||||
for (var j = 0; j < apiNs.length - 1; j++) {
|
||||
var ns = apiNs[j];
|
||||
if (typeof lastNs[ns] === "undefined") lastNs[ns] = {};
|
||||
lastNs = lastNs[ns];
|
||||
}
|
||||
var leaf = apiNs[apiNs.length - 1];
|
||||
if ("abcdefghijklmnopqrstuvwxyz".indexOf(leaf[0]) < 0) {
|
||||
lastNs[leaf] = {};
|
||||
Object.defineProperty(lastNs[leaf], "current", {
|
||||
get: function() { return null; },
|
||||
enumerable: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
Object.defineProperty(Windows.ApplicationModel.DesignMode, "designModeEnabled", {
|
||||
get: isDevToolsOpen,
|
||||
enumerable: true,
|
||||
});
|
||||
Windows.Foundation.Collections.CollectionChange = {
|
||||
reset: 0,
|
||||
itemInserted: 1,
|
||||
itemRemoved: 2,
|
||||
itemChanged: 3
|
||||
};
|
||||
Windows.Foundation.Uri = function(uri) {
|
||||
var inst = null;
|
||||
if (arguments.length === 2) {
|
||||
inst = external.Utilities.createUri2(uri, arguments[1]);
|
||||
} else {
|
||||
inst = external.Utilities.createUri(uri);
|
||||
}
|
||||
inst.jsType = this;
|
||||
return inst;
|
||||
};
|
||||
Windows.Globalization.ApplicationLanguages = {};
|
||||
Object.defineProperty(Windows.Globalization.ApplicationLanguages, "languages", {
|
||||
get: function() {
|
||||
try {
|
||||
var list = [];
|
||||
var langs = external.System.Locale.recommendLocaleNames;
|
||||
langs.forEach(function(item) {
|
||||
list.push(item);
|
||||
});
|
||||
return list;
|
||||
} catch (e) {
|
||||
return navigator.languages;
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
});
|
||||
Object.defineProperty(Windows.Globalization.ApplicationLanguages, "Languages", {
|
||||
get: function() {
|
||||
return Windows.Globalization.ApplicationLanguages.languages;
|
||||
},
|
||||
enumerable: true,
|
||||
});
|
||||
Windows.Globalization.LanguageLayoutDirection = {
|
||||
ltr: 0,
|
||||
rtl: 1,
|
||||
ttbLtr: 2,
|
||||
ttbRtl: 3
|
||||
};
|
||||
Windows.Globalization.Language = function(languageTag) {
|
||||
var inst = external.System.Locale.createLanguage(languageTag);
|
||||
inst.jsType = this;
|
||||
return inst;
|
||||
};
|
||||
Object.defineProperty(Windows.Globalization.Language, "currentInputMethodLanguageTag", {
|
||||
get: function() {
|
||||
return external.System.Locale.currentInputMethodLanguageTag;
|
||||
},
|
||||
enumerable: true,
|
||||
});
|
||||
Windows.Globalization.Language.isWellFormed = external.System.Locale.isWellFormed;
|
||||
Windows.Globalization.Language.getMuiCompatibleLanguageListFromLanguageTags = external.System.Locale.getMuiCompatibleLanguageListFromLanguageTags;
|
||||
Windows.Globalization.Calendar = function(args) {
|
||||
var inst = null;
|
||||
if (arguments.length === 0) {
|
||||
inst = external.Utilities.createCalendar(args);
|
||||
} else if (arguments.length === 1) {
|
||||
inst = external.Utilities.createCalendar2(args);
|
||||
} else if (arguments.length === 3) {
|
||||
inst = external.Utilities.createCalendar3(args, arguments[1], arguments[2], arguments[3]);
|
||||
} else if (arguments.length === 4) {
|
||||
inst = external.Utilities.createCalendar4(args, arguments[1], arguments[2], arguments[3], arguments[4]);
|
||||
}
|
||||
return inst;
|
||||
};
|
||||
Windows.Globalization.DateTimeFormatting = {};
|
||||
Windows.Globalization.DateTimeFormatting.DayFormat = {
|
||||
default: 1,
|
||||
none: 0
|
||||
};
|
||||
Windows.Globalization.DateTimeFormatting.DayOfWeekFormat = {
|
||||
none: 0,
|
||||
default: 1,
|
||||
abberviated: 2,
|
||||
full: 3
|
||||
};
|
||||
Windows.Globalization.DateTimeFormatting.HourFormat = {
|
||||
none: 0,
|
||||
default: 1
|
||||
};
|
||||
Windows.Globalization.DateTimeFormatting.MinuteFormat = {
|
||||
none: 0,
|
||||
default: 1
|
||||
};
|
||||
Windows.Globalization.DateTimeFormatting.MonthFormat = {
|
||||
none: 0,
|
||||
default: 1,
|
||||
abberviated: 2,
|
||||
full: 3,
|
||||
numeric: 4
|
||||
};
|
||||
Windows.Globalization.DateTimeFormatting.SecondFormat = {
|
||||
default: 1,
|
||||
none: 0
|
||||
};
|
||||
Windows.Globalization.DateTimeFormatting.YearFormat = {
|
||||
default: 1,
|
||||
none: 0,
|
||||
abberviated: 2,
|
||||
full: 3,
|
||||
};
|
||||
Windows.Globalization.DateTimeFormatting.DateTimeFormatter = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var inst = null;
|
||||
if (args.length === 1) inst = external.Utilities.createDateTimeFormatterFromTemplate(args[0]);
|
||||
else if (args.length === 2) inst = external.Utilities.CreateDateTimeFormatterFromTemplateAndLanguages(args[0], args[1]);
|
||||
else if (args.length === 3) inst = external.Utilities.CreateDateTimeFormatterFromTimeEnums(args[0], args[1], args[2]);
|
||||
else if (args.length === 4) inst = external.Utilities.CreateDateTimeFormatterFromDateEnums(args[0], args[1], args[2], args[3]);
|
||||
else if (args.length === 5) inst = external.Utilities.CreateDateTimeFormatterFromTemplateFull(args[0], args[1], args[2], args[3], args[4]);
|
||||
else if (args.length === 8) inst = external.Utilities.CreateDateTimeFormatterFromDateTimeEnums(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
|
||||
else if (args.length === 11) inst = external.Utilities.CreateDateTimeFormatterFromDateTimeEnumsFull(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]);
|
||||
return inst;
|
||||
};
|
||||
Windows.Storage.CreationCollisionOption = {
|
||||
generateUniqueName: 0,
|
||||
replaceExisting: 1,
|
||||
failIfExists: 2,
|
||||
openIfExists: 3
|
||||
};
|
||||
Windows.Storage.FileProperties = {
|
||||
ThumbnailType: {
|
||||
image: 0,
|
||||
icon: 1
|
||||
},
|
||||
ThumbnailMode: {
|
||||
pictureView: 0,
|
||||
videosView: 1,
|
||||
musicView: 2,
|
||||
documentsView: 3,
|
||||
listView: 4,
|
||||
singleItem: 5
|
||||
},
|
||||
ThumbnailType: {
|
||||
image: 0,
|
||||
icon: 1
|
||||
},
|
||||
VideoOrientation: {
|
||||
normal: 0,
|
||||
rotate90: 90,
|
||||
rotate180: 180,
|
||||
rotate270: 270
|
||||
},
|
||||
PhotoOrientation: {
|
||||
unspecified: 0,
|
||||
normal: 1,
|
||||
flipHorizontal: 2,
|
||||
rotate180: 3,
|
||||
flipVertical: 4,
|
||||
transpose: 5,
|
||||
rotate270: 6,
|
||||
transverse: 7,
|
||||
rotate90: 8
|
||||
},
|
||||
};
|
||||
Windows.Storage.Search = {
|
||||
FolderDepth: function() {},
|
||||
IndexerOption: function() {}
|
||||
};
|
||||
Windows.Storage.Search.FolderDepth.deep = 1;
|
||||
Windows.Storage.Search.FolderDepth.shallow = 0;
|
||||
Windows.Storage.Search.IndexerOption.useIndexerWhenAvailable = 0;
|
||||
Windows.Storage.Search.IndexerOption.onlyUseIndexer = 1;
|
||||
Windows.Storage.Search.IndexerOption.doNotUseIndexer = 2;
|
||||
Windows.Storage.Search.IndexerOption.onlyUseIndexerAndOptimizeForIndexedProperties = 3;
|
||||
Windows.UI.ApplicationSettings.SettingsEdgeLocation = {
|
||||
right: 0,
|
||||
left: 1
|
||||
};
|
||||
Windows.UI.Input.EdgeGestureKind = {
|
||||
touch: 0,
|
||||
keyboard: 1,
|
||||
mouse: 2
|
||||
};
|
||||
Windows.UI.ViewManagement.HandPreference = {
|
||||
leftHanded: 0,
|
||||
rightHanded: 1
|
||||
};
|
||||
Windows.UI.WebUI.Core.WebUICommandBarClosedDisplayMode = {
|
||||
default: 0,
|
||||
minimal: 1,
|
||||
compact: 2
|
||||
};
|
||||
})(this);
|
||||
@@ -502,6 +502,22 @@
|
||||
if (!p.removeEventListener) p.removeEventListener = PromisePolyfill.removeEventListener;
|
||||
if (!p.dispatchEvent) p.dispatchEvent = PromisePolyfill.dispatchEvent;
|
||||
if (!p.onerror) p.onerror = null;
|
||||
if (typeof p.prototype.then !== "function") {
|
||||
p.prototype.then = function(onFulfilled, onRejected) {
|
||||
return new p(function(resolve, reject) {
|
||||
this.then(resolve, reject);
|
||||
}).then(onFulfilled, onRejected);
|
||||
};
|
||||
}
|
||||
if (typeof p.prototype.done !== "function") {
|
||||
p.prototype.done = function(onFulfilled, onRejected) {
|
||||
this.then(onFulfilled, onRejected)["catch"](function(ex) {
|
||||
setTimeout(function() {
|
||||
throw ex;
|
||||
}, 0);
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
if (typeof global.WinJS !== "undefined" && typeof global.WinJS.Promise !== "undefined") {
|
||||
var wp = global.WinJS.Promise;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
var strres = external.StringResources;
|
||||
var conf = external.Config.current;
|
||||
var set = conf.getSection("Settings");
|
||||
var metadata = conf.getSection("PackageReader:AppMetadatas");
|
||||
|
||||
function createLocalizedCompare(locale) {
|
||||
return function(a, b) {
|
||||
@@ -15,6 +16,26 @@
|
||||
};
|
||||
}
|
||||
var pagemgr = new PageManager();
|
||||
(function() {
|
||||
var nstrutil = Bridge.NString;
|
||||
var boolTrue = ["true", "1", "yes", "on", "y", "t", "zhen", "真"];
|
||||
var boolFalse = ["false", "0", "no", "off", "n", "f", "jia", "假"];
|
||||
global.parseBool = function(str) {
|
||||
if (typeof str === "boolean") return str;
|
||||
str = "" + str;
|
||||
for (var i = 0; i < boolTrue.length; i++) {
|
||||
if (nstrutil.equals(str, boolTrue[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < boolFalse.length; i++) {
|
||||
if (nstrutil.equals(str, boolFalse[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
})();
|
||||
OnLoad.add(function() {
|
||||
var mgr = Package.manager;
|
||||
var nstr = Bridge.NString;
|
||||
@@ -25,6 +46,8 @@
|
||||
});
|
||||
var themeColor = Bridge.UI.themeColor;
|
||||
pagemgr.register("reader", document.getElementById("tag-reader"), document.getElementById("page-reader"));
|
||||
pagemgr.register("acquire", document.getElementById("tag-acquire"), document.getElementById("page-acquire"));
|
||||
pagemgr.register("search", document.getElementById("tag-search"), document.getElementById("page-search"));
|
||||
pagemgr.go("reader");
|
||||
});
|
||||
})(this);
|
||||
@@ -57,6 +57,7 @@
|
||||
try {
|
||||
var obj = nodes[i].getAttribute('data-res-resxml');
|
||||
var strres = external.StringResources;
|
||||
if (!strres) strres = Bridge.External.WinJsStringRes;
|
||||
if (strres) {
|
||||
try {
|
||||
nodes[i].textContent = strres.get(obj);
|
||||
|
||||
227
shared/html/js/storergapi.js
Normal file
@@ -0,0 +1,227 @@
|
||||
/**
|
||||
* Microsoft Store - Generation Project (v1.2.3) [by @rgadguard & mkuba50]
|
||||
* Website: https://store.rg-adguard.net/
|
||||
* This API is not publicly available and is currently restricted by the website, meaning it's only useful after a webpage is opened. Therefore, this JS file is only for documenting its usage; it will remain unusable unless a specific method is used to address this issue.
|
||||
*/
|
||||
(function(global) {
|
||||
"use strict";
|
||||
|
||||
function joinUrl(url, path) {
|
||||
if (url.charAt(url.length - 1) === "/") {
|
||||
url = url.slice(0, -1);
|
||||
}
|
||||
if (path.charAt(0) === "/") {
|
||||
path = path.slice(1);
|
||||
}
|
||||
return url + "/" + path;
|
||||
}
|
||||
|
||||
function buildParams(params) {
|
||||
var queryString = "";
|
||||
var keys = Object.keys(params);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
var value = params[key];
|
||||
if (value === null || value === void 0) {
|
||||
continue;
|
||||
}
|
||||
queryString += encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&";
|
||||
}
|
||||
return queryString.slice(0, -1);
|
||||
}
|
||||
var baseUrl = "https://store.rg-adguard.net/";
|
||||
var getFilesApi = joinUrl(baseUrl, "api/GetFiles");
|
||||
var proxyPrefix = "https://api.allorigins.win/get?url=";
|
||||
var proxyApi = proxyPrefix + encodeURIComponent(getFilesApi);
|
||||
var reqMethod = "POST";
|
||||
|
||||
function getXHR() {
|
||||
var xmlhttp;
|
||||
try {
|
||||
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
} catch (e) {
|
||||
try {
|
||||
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
} catch (E) {
|
||||
xmlhttp = false;
|
||||
}
|
||||
}
|
||||
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
|
||||
xmlhttp = new XMLHttpRequest();
|
||||
}
|
||||
return xmlhttp;
|
||||
}
|
||||
/**
|
||||
* file structure: QueryFileItem
|
||||
* @param {string} file
|
||||
* @param {string} expire
|
||||
* @param {string} sha1
|
||||
* @param {string} size
|
||||
* @param {string} url
|
||||
*/
|
||||
function QueryFileItem(file, expire, sha1, size, url) {
|
||||
/**
|
||||
* class name.
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = "QueryFileItem";
|
||||
this.file = file;
|
||||
this.expire = expire;
|
||||
this.sha1 = sha1;
|
||||
this.size = size;
|
||||
this.url = url;
|
||||
}
|
||||
/**
|
||||
* the type of value which will be send.
|
||||
* @enum {string}
|
||||
*/
|
||||
var ValueType = {
|
||||
url: "url",
|
||||
productId: "ProductId",
|
||||
packageFamilyName: "PackageFamilyName",
|
||||
categoryId: "CategoryId"
|
||||
};
|
||||
/**
|
||||
* the channel of the store.
|
||||
* @enum {string}
|
||||
*/
|
||||
var Channel = {
|
||||
fast: "WIF",
|
||||
slow: "WIS",
|
||||
releasePreview: "RP",
|
||||
retail: "Retail"
|
||||
};
|
||||
/**
|
||||
* fetch and get the response.
|
||||
* @param {string} value
|
||||
* @param {StoreRG.ValueType} type
|
||||
* @param {StoreRG.Channel} channel
|
||||
* @param {[boolean]} isAsync default is true.
|
||||
* @returns {Promise <XMLHttpRequest>} the response.
|
||||
*/
|
||||
function queryFiles(value, type, channel, isAsync) {
|
||||
if (typeof isAsync === "undefined" || isAsync === null) {
|
||||
isAsync = true;
|
||||
}
|
||||
var xhr = getXHR();
|
||||
xhr.open(reqMethod, getFilesApi, isAsync);
|
||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||
var params = "type={type}&url={url}&ring={ring}&lang={lang}"
|
||||
.replace("{type}", type)
|
||||
.replace("{url}", encodeURIComponent(value))
|
||||
.replace("{ring}", channel)
|
||||
.replace("{lang}", navigator.language);
|
||||
return new Promise(function(c, e) {
|
||||
try {
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status == 200) {
|
||||
if (c) c(xhr);
|
||||
} else {
|
||||
if (e) e(xhr.statusText + " (" + xhr.status + ")");
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send(params);
|
||||
} catch (ex) {
|
||||
if (e) e(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* fetch and get the response. And parse the response to get the QueryFileItem array.
|
||||
* @param {string} value
|
||||
* @param {StoreRG.ValueType} type
|
||||
* @param {StoreRG.Channel} channel
|
||||
* @param {[boolean]} isAsync default is true.
|
||||
* @returns {Promise <{categoryId: string, datas: QueryFileItem[]}>} the QueryFileItem array.
|
||||
*/
|
||||
queryFiles.parse = function(value, type, channel, isAsync) {
|
||||
return queryFiles(value, type, channel, isAsync).then(function(resp) {
|
||||
var tempcontainer = document.createElement("div");
|
||||
tempcontainer.innerHTML = resp.responseText;
|
||||
var styles = tempcontainer.querySelectorAll("style");
|
||||
var scripts = tempcontainer.querySelectorAll("script");
|
||||
for (var i = 0; i < styles.length; i++) {
|
||||
styles[i].parentNode.removeChild(styles[i]);
|
||||
}
|
||||
for (var i = 0; i < scripts.length; i++) {
|
||||
scripts[i].parentNode.removeChild(scripts[i]);
|
||||
}
|
||||
var categoryId = "";
|
||||
try {
|
||||
categoryId = tempcontainer.querySelector("i").textContent;
|
||||
} catch (e) {}
|
||||
var datas = [];
|
||||
var table = tempcontainer.querySelector("table");
|
||||
if (table) {
|
||||
var rows = table.querySelectorAll("tr");
|
||||
for (var i = 1; i < rows.length; i++) {
|
||||
var cells = rows[i].querySelectorAll("td");
|
||||
datas.push(new QueryFileItem(
|
||||
cells[0].textContent,
|
||||
cells[1].textContent,
|
||||
cells[2].textContent,
|
||||
cells[3].textContent,
|
||||
cells[0].querySelector("a").href
|
||||
));
|
||||
}
|
||||
}
|
||||
return {
|
||||
categoryId: categoryId,
|
||||
datas: datas
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
function smartMatch(input) {
|
||||
if (!input) return null;
|
||||
var str = String(input);
|
||||
var reCategoryId = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
|
||||
var rePFN = /[A-Za-z0-9.-]{3,50}_[a-z0-9]{13}/i;
|
||||
var reProductId = /(^|[^a-z0-9])([a-z0-9]{12})(?=$|[^a-z0-9])/i;
|
||||
var m;
|
||||
m = str.match(reCategoryId);
|
||||
if (m) {
|
||||
return {
|
||||
type: ValueType.categoryId,
|
||||
match: m[0].toLowerCase()
|
||||
};
|
||||
}
|
||||
m = str.match(rePFN);
|
||||
if (m) {
|
||||
return {
|
||||
type: ValueType.packageFamilyName,
|
||||
match: m[0]
|
||||
};
|
||||
}
|
||||
m = str.match(reProductId);
|
||||
if (m) {
|
||||
return {
|
||||
type: ValueType.productId,
|
||||
match: m[2].toLowerCase()
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: ValueType.url,
|
||||
match: str
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 自动查询,无需设置其余参数。
|
||||
* @param {string} value 传入的查询值。
|
||||
* @returns {Promise <{categoryId: string, datas: QueryFileItem[]}>}
|
||||
*/
|
||||
queryFiles.smartQuery = function(value) {
|
||||
var match = smartMatch(value);
|
||||
return queryFiles.parse(match.match, match.type, Channel.retail);
|
||||
};
|
||||
/**
|
||||
* @namespace StoreRG
|
||||
*/
|
||||
global.StoreRG = {
|
||||
ValueType: ValueType,
|
||||
Channel: Channel,
|
||||
xhr: queryFiles,
|
||||
};
|
||||
})(this);
|
||||
@@ -1,110 +0,0 @@
|
||||
.win-contentdialog {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
transition: all 0.15s linear;
|
||||
opacity: 1;
|
||||
z-index: 100;
|
||||
}
|
||||
.win-contentdialog.hide {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.win-contentdialog .win-contentdialog-dialog {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 20px 0;
|
||||
background-color: rgb(31, 0, 104);
|
||||
transition: all 0.5s cubic-bezier(0.1, 0.9, 0.2, 1);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-title {
|
||||
font-size: 20pt;
|
||||
font-weight: normal;
|
||||
padding: 0 172px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content {
|
||||
padding: 0 172px;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
max-height: calc(100vh - 200px);
|
||||
margin: 10px 0 20px 0;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-commands {
|
||||
padding: 0 172px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-commands > button {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content dl dt,
|
||||
.win-contentdialog .win-contentdialog-content dl dd {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content dl {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
box-sizing: border-box;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content dl dt {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
text-align: left;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content dl dd {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content dl dd * {
|
||||
max-width: 100%;
|
||||
}
|
||||
.win-contentdialog-dialog-template {
|
||||
display: none;
|
||||
}
|
||||
.win-contentdialog .win-contentdialog-content .win-contentdialog-dialog-template {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.win-ui-light .win-contentdialog .win-contentdialog-dialog,
|
||||
.win-contentdialog.win-ui-light .win-contentdialog-dialog {
|
||||
background-color: white;
|
||||
}
|
||||
.win-ui-dark .win-contentdialog .win-contentdialog-dialog,
|
||||
.win-contentdialog.win-ui-dark .win-contentdialog-dialog {
|
||||
background-color: rgb(31, 0, 104);
|
||||
}
|
||||
120
shared/html/libs/msgbox/contentdlg.css
Normal file
@@ -0,0 +1,120 @@
|
||||
.win-contentdialog {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
transition: all 0.15s linear;
|
||||
opacity: 1;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.win-contentdialog.hide {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-dialog {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 20px 0;
|
||||
background-color: rgb(31, 0, 104);
|
||||
/*transition: all 0.5s cubic-bezier(0.1, 0.9, 0.2, 1);*/
|
||||
transition: height, max-height, min-height 0.5s cubic-bezier(0.1, 0.9, 0.2, 1);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-title {
|
||||
width: 100%;
|
||||
font-size: 20pt;
|
||||
font-weight: normal;
|
||||
padding: 0 172px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content {
|
||||
width: 100%;
|
||||
padding: 0 172px;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
max-height: calc(100vh - 200px);
|
||||
margin: 10px 0 20px 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-commands {
|
||||
width: 100%;
|
||||
padding: 0 172px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-commands>button {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content dl dt,
|
||||
.win-contentdialog .win-contentdialog-content dl dd {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content dl {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
box-sizing: border-box;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content dl dt {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
text-align: left;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content dl dd {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content dl dd * {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.win-contentdialog-dialog-template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.win-contentdialog .win-contentdialog-content .win-contentdialog-dialog-template {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.win-ui-light .win-contentdialog .win-contentdialog-dialog,
|
||||
.win-contentdialog.win-ui-light .win-contentdialog-dialog {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.win-ui-dark .win-contentdialog .win-contentdialog-dialog,
|
||||
.win-contentdialog.win-ui-dark .win-contentdialog-dialog {
|
||||
background-color: rgb(31, 0, 104);
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
(function (global) {
|
||||
"use strict";
|
||||
|
||||
if (typeof global.toStaticHTML === "undefined") global.toStaticHTML = function (str) { return str; };
|
||||
if (typeof global.WinJS === "undefined" || !global.WinJS) global.WinJS = {};
|
||||
if (typeof global.WinJS.UI === "undefined" || !global.WinJS.UI) global.WinJS.UI = {};
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* 表示 ContentDialog 中的一个按钮命令。
|
||||
* @class
|
||||
* @param {string} label 按钮显示文本
|
||||
* @param {function(Event=): (boolean|void)} [handler] 按钮点击处理函数
|
||||
* @param {string} [commandId] 命令唯一标识
|
||||
*/
|
||||
* 表示 ContentDialog 中的一个按钮命令。
|
||||
* @class
|
||||
* @param {string} label 按钮显示文本
|
||||
* @param {function(Event=): (boolean|void)} [handler] 按钮点击处理函数
|
||||
* @param {string} [commandId] 命令唯一标识
|
||||
*/
|
||||
function ContentDialogCommand(label, handler, commandId) {
|
||||
this.label = label;
|
||||
this.handler = handler;
|
||||
@@ -30,16 +30,17 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟 WinRT ContentDialog 的对话框
|
||||
* @class
|
||||
* @memberof WinJS.UI
|
||||
* @param {HTMLElement} element 容器
|
||||
* @param {Object} [options] 初始化选项
|
||||
*/
|
||||
* 模拟 WinRT ContentDialog 的对话框
|
||||
* @class
|
||||
* @memberof WinJS.UI
|
||||
* @param {HTMLElement} element 容器
|
||||
* @param {Object} [options] 初始化选项
|
||||
*/
|
||||
function ContentDialog(element, options) {
|
||||
var container = element;
|
||||
container.innerHTML = toStaticHTML('<div class="win-contentdialog-dialog"><div class="win-contentdialog-title"></div><div class="win-contentdialog-content"></div><div class="win-contentdialog-commands"></div></div>');
|
||||
container.innerHTML = toStaticHTML('<div class="win-contentdialog-dialog notice-body"><div class="win-contentdialog-title notice-title"></div><div class="win-contentdialog-content notice-text"></div><div class="win-contentdialog-commands notice-controls"></div></div>');
|
||||
container.classList.add("win-contentdialog");
|
||||
container.classList.add("notice-back");
|
||||
container.classList.add("hide");
|
||||
|
||||
var title = container.querySelector(".win-contentdialog-title");
|
||||
@@ -62,6 +63,7 @@
|
||||
}
|
||||
self._commands.forEach(function (cmd, index) {
|
||||
var btn = document.createElement("button");
|
||||
btn.classList.add ("notice-btn");
|
||||
btn.textContent = cmd.label;
|
||||
btn.setAttribute("data-command-id", cmd.commandId || index);
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
.notice-back {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: auto;
|
||||
width: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
display: -ms-flexbox;
|
||||
-ms-flex-direction: column;
|
||||
-ms-flex-wrap: nowrap;
|
||||
-ms-flex-line-pack: center;
|
||||
/* align-content: center */
|
||||
-ms-flex-pack: center;
|
||||
/* justify-content: center */
|
||||
transition: all 0.15s linear;
|
||||
opacity: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.notice-body {
|
||||
background: #0078d7;
|
||||
padding: 25px 172px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: auto;
|
||||
bottom: auto;
|
||||
max-height: 80%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
display: -ms-flexbox;
|
||||
-ms-flex-direction: column;
|
||||
-ms-flex-wrap: nowrap;
|
||||
min-height: 0 !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.notice-body>h1,
|
||||
.notice-body>h2,
|
||||
.notice-body>h3,
|
||||
.notice-body>h4,
|
||||
.notice-body>h5,
|
||||
.notice-body>h6,
|
||||
.notice-body>p,
|
||||
.notice-body>a,
|
||||
.notice-body>span {
|
||||
font-family: "Microsoft YaHei", "Segoe UI", "Ebrima", "Nirmala", "Gadugi", "Segoe UI Emoji", "Segoe UI Symbol", "Meiryo", "Leelawadee", "Microsoft JhengHei", "Malgun Gothic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math";
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.notice-title {
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.notice-text {
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
white-space: pre-wrap;
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
||||
}
|
||||
|
||||
.notice-controls {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-content: center;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
display: -ms-flexbox;
|
||||
-ms-flex-direction: row;
|
||||
-ms-flex-wrap: nowrap;
|
||||
-ms-flex-line-pack: center;
|
||||
/* align-content: center(几乎无效,保留即可) */
|
||||
-ms-flex-pack: end;
|
||||
/* justify-content: flex-end */
|
||||
-ms-flex-align: center;
|
||||
/* align-items: center */
|
||||
margin-top: 10px;
|
||||
/*gap: 20px;*/
|
||||
}
|
||||
|
||||
.notice-btn {
|
||||
margin-left: 20px;
|
||||
}
|
||||
95
shared/html/libs/msgbox/msgbox.elder.css
Normal file
@@ -0,0 +1,95 @@
|
||||
.notice-back {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: auto;
|
||||
width: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
display: -ms-flexbox;
|
||||
-ms-flex-direction: column;
|
||||
-ms-flex-wrap: nowrap;
|
||||
-ms-flex-line-pack: center;
|
||||
/* align-content: center */
|
||||
-ms-flex-pack: center;
|
||||
/* justify-content: center */
|
||||
transition: all 0.15s linear;
|
||||
opacity: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.notice-body {
|
||||
background: #0078d7;
|
||||
padding: 25px 172px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: auto;
|
||||
bottom: auto;
|
||||
max-height: 80%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
display: -ms-flexbox;
|
||||
-ms-flex-direction: column;
|
||||
-ms-flex-wrap: nowrap;
|
||||
min-height: 0 !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.notice-body>h1,
|
||||
.notice-body>h2,
|
||||
.notice-body>h3,
|
||||
.notice-body>h4,
|
||||
.notice-body>h5,
|
||||
.notice-body>h6,
|
||||
.notice-body>p,
|
||||
.notice-body>a,
|
||||
.notice-body>span {
|
||||
font-family: "Microsoft YaHei", "Segoe UI", "Ebrima", "Nirmala", "Gadugi", "Segoe UI Emoji", "Segoe UI Symbol", "Meiryo", "Leelawadee", "Microsoft JhengHei", "Malgun Gothic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math";
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.notice-title {
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.notice-text {
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
white-space: pre-wrap;
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
||||
}
|
||||
|
||||
.notice-controls {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-content: center;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
display: -ms-flexbox;
|
||||
-ms-flex-direction: row;
|
||||
-ms-flex-wrap: nowrap;
|
||||
-ms-flex-line-pack: center;
|
||||
/* align-content: center(几乎无效,保留即可) */
|
||||
-ms-flex-pack: end;
|
||||
/* justify-content: flex-end */
|
||||
-ms-flex-align: center;
|
||||
/* align-items: center */
|
||||
margin-top: 10px;
|
||||
/*gap: 20px;*/
|
||||
}
|
||||
|
||||
.notice-btn {
|
||||
margin-left: 20px;
|
||||
}
|
||||
532
shared/html/libs/msgbox/msgbox.elder.js
Normal file
@@ -0,0 +1,532 @@
|
||||
function IsBlackLabel(text) {
|
||||
if (text === null || text === undefined) return true;
|
||||
var trimmed = String(text).replace(/^\s+|\s+$/g, '');
|
||||
return trimmed === '';
|
||||
}
|
||||
|
||||
var MBFLAGS = {
|
||||
MB_OK: 0x00000000,
|
||||
MB_OKCANCEL: 0x00000001,
|
||||
MB_ABORTRETRYIGNORE: 0x00000002,
|
||||
MB_YESNOCANCEL: 0x00000003,
|
||||
MB_YESNO: 0x00000004,
|
||||
MB_RETRYCANCEL: 0x00000005,
|
||||
MB_CANCELTRYCONTINUE: 0x00000006,
|
||||
MB_HELP: 0x00004000,
|
||||
MB_DEFBUTTON1: 0x00000000,
|
||||
MB_DEFBUTTON2: 0x00000100,
|
||||
MB_DEFBUTTON3: 0x00000200,
|
||||
MB_DEFBUTTON4: 0x00000300,
|
||||
MB_ICONERROR: 0x00000010,
|
||||
MB_ICONWARNING: 0x00000030,
|
||||
MB_ICONINFORMATION: 0x00000040
|
||||
};
|
||||
|
||||
var MBRET = {
|
||||
IDOK: 1,
|
||||
IDCANCEL: 2,
|
||||
IDABORT: 3,
|
||||
IDRETRY: 4,
|
||||
IDIGNORE: 5,
|
||||
IDYES: 6,
|
||||
IDNO: 7,
|
||||
IDCLOSE: 8,
|
||||
IDHELP: 9,
|
||||
IDTRYAGAIN: 10,
|
||||
IDCONTINUE: 11
|
||||
};
|
||||
|
||||
Object.freeze(MBFLAGS);
|
||||
Object.freeze(MBRET);
|
||||
|
||||
(function(global) {
|
||||
try {
|
||||
var storage = Bridge.External.Storage;
|
||||
var path = storage.path;
|
||||
var root = path.getDir(path.program);
|
||||
var respath = path.combine(root, "reslib.dll");
|
||||
var res = Bridge.Resources;
|
||||
global.respath = respath;
|
||||
global.getPublicRes = function(resId) {
|
||||
return res.fromfile(respath, resId);
|
||||
}
|
||||
} catch (e) {}
|
||||
})(this);
|
||||
|
||||
function GetLocaleStringFromResId(resId) { try { return getPublicRes(resId); } catch (e) {} }
|
||||
var msgboxResult = {};
|
||||
|
||||
function MessageBox(_lpText, _lpCaption, _uType, _objColor) {
|
||||
var id = MessageBoxForJS(_lpText, _lpCaption, _uType, _objColor, function(valueReturn) {
|
||||
getRes = valueReturn;
|
||||
msgboxResult[id] = valueReturn;
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
function GetMessageBoxResult(msgboxId) {
|
||||
var result = msgboxResult[msgboxId];
|
||||
if (result === undefined || result === null) return null;
|
||||
msgboxResult[msgboxId] = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
function ClearAllMessageBoxResults() {
|
||||
msgboxResult = null;
|
||||
msgboxResult = {};
|
||||
}
|
||||
|
||||
// 注意:callback 函数无返回值,传入参数:整数型 按下的按钮值。
|
||||
/*
|
||||
使用示例:
|
||||
MessageBoxForJS("请选择一个按钮", "", MBFLAGS.MB_OKCANCEL, "#0078d7", function(value) {
|
||||
console.log("MessageBoxForJS callback value: " + value);
|
||||
})
|
||||
*/
|
||||
function MessageBoxForJS(_lpText, _lpCaption, _uType, _objColor, _callback) {
|
||||
var msgbox = document.createElement("div");
|
||||
msgbox.classList.add("notice-back");
|
||||
msgbox.classList.add("win-ui-dark");
|
||||
var uniqueId = "msgbox_" + new Date().getTime();
|
||||
msgbox.id = uniqueId;
|
||||
var msgbody = document.createElement("div");
|
||||
msgbody.classList.add("notice-body");
|
||||
if (!IsBlackLabel(_objColor)) {
|
||||
msgbody.style.backgroundColor = _objColor;
|
||||
}
|
||||
msgbox.appendChild(msgbody);
|
||||
var msgcontainter = document.createElement("div");
|
||||
msgcontainter.style.height = "100%";
|
||||
msgcontainter.style.width = "100%";
|
||||
msgcontainter.style.maxHeight = "100%";
|
||||
msgcontainter.style.minHeight = "0px";
|
||||
msgcontainter.style.boxSizing = "border-box";
|
||||
msgbody.appendChild(msgcontainter);
|
||||
var msgcaption = document.createElement("div");
|
||||
msgcontainter.appendChild(msgcaption);
|
||||
msgcontainter.style.display = "flex";
|
||||
msgcontainter.style.flexDirection = "column";
|
||||
var msgcontent = document.createElement("div");
|
||||
msgcontent.style.flex = "1 1 auto";
|
||||
msgcontent.style.marginRight = "3px";
|
||||
msgcontent.style.overflowX = "hidden";
|
||||
msgcontent.style.overflowY = "auto";
|
||||
msgcontent.style.minHeight = "0px";
|
||||
msgcontainter.appendChild(msgcontent);
|
||||
if (_lpCaption instanceof HTMLElement) {
|
||||
msgcaption.appendChild(_lpCaption);
|
||||
msgcaption.classList.add("notice-title");
|
||||
} else {
|
||||
if (!IsBlackLabel(_lpCaption)) {
|
||||
var msgtitle = document.createElement("h2");
|
||||
msgtitle.textContent = _lpCaption;
|
||||
msgtitle.classList.add("notice-title");
|
||||
msgcaption.appendChild(msgtitle);
|
||||
} else {
|
||||
var msgtitle = document.createElement("h2");
|
||||
msgtitle.textContent = "";
|
||||
msgtitle.classList.add("notice-title");
|
||||
msgcaption.appendChild(msgtitle);
|
||||
}
|
||||
}
|
||||
if (_lpText instanceof HTMLElement || _lpText instanceof HTMLDivElement || typeof _lpText !== "string") {
|
||||
try {
|
||||
_lpText.classList.add("notice-text");
|
||||
msgcontent.appendChild(_lpText);
|
||||
} catch (e) {
|
||||
if (!IsBlackLabel(_lpText)) {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.textContent = _lpText;
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
} else {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.innerText = "";
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!IsBlackLabel(_lpText)) {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.textContent = _lpText;
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
} else {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.innerText = "";
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
}
|
||||
}
|
||||
var msgctrls = document.createElement("div");
|
||||
msgctrls.classList.add("notice-controls");
|
||||
msgcontainter.appendChild(msgctrls);
|
||||
var cnt = 0;
|
||||
var cbFuncPress = function(valueReturn) {
|
||||
getRes = valueReturn;
|
||||
msgbox.style.opacity = 0;
|
||||
setTimeout(function() {
|
||||
document.body.removeChild(msgbox);
|
||||
}, 500);
|
||||
if (_callback) {
|
||||
_callback(valueReturn);
|
||||
}
|
||||
};
|
||||
var pfCreateButton = function(displayNameResId, valueReturn) {
|
||||
var btn = document.createElement("button");
|
||||
btn.innerHTML = GetLocaleStringFromResId(displayNameResId);
|
||||
btn.classList.add("notice-btn");
|
||||
btn.addEventListener("click", function() {
|
||||
cbFuncPress(valueReturn);
|
||||
});
|
||||
msgctrls.appendChild(btn);
|
||||
};
|
||||
if ((_uType & MBFLAGS.MB_HELP) === MBFLAGS.MB_HELP) {
|
||||
pfCreateButton(808, MBRET.IDHELP);
|
||||
}
|
||||
for (cnt = 0; cnt <= MBFLAGS.MB_RETRYCANCEL; cnt++) {
|
||||
if ((_uType & 0xF) === cnt) {
|
||||
switch (cnt) {
|
||||
case MBFLAGS.MB_OK:
|
||||
{
|
||||
pfCreateButton(800, MBRET.IDOK);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_OKCANCEL:
|
||||
{
|
||||
pfCreateButton(800, MBRET.IDOK);
|
||||
pfCreateButton(801, MBRET.IDCANCEL);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_ABORTRETRYIGNORE:
|
||||
{
|
||||
pfCreateButton(802, MBRET.IDABORT);
|
||||
pfCreateButton(803, MBRET.IDRETRY);
|
||||
pfCreateButton(804, MBRET.IDIGNORE);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_YESNOCANCEL:
|
||||
{
|
||||
pfCreateButton(805, MBRET.IDYES);
|
||||
pfCreateButton(806, MBRET.IDNO);
|
||||
pfCreateButton(801, MBRET.IDCANCEL);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_YESNO:
|
||||
{
|
||||
pfCreateButton(805, MBRET.IDYES);
|
||||
pfCreateButton(806, MBRET.IDNO);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_RETRYCANCEL:
|
||||
{
|
||||
pfCreateButton(803, MBRET.IDRETRY);
|
||||
pfCreateButton(801, MBRET.IDCANCEL);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_CANCELTRYCONTINUE:
|
||||
{
|
||||
pfCreateButton(801, MBRET.IDCANCEL);
|
||||
pfCreateButton(803, MBRET.IDRETRY);
|
||||
pfCreateButton(810, MBRET.IDCONTINUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
var btns = msgctrls.querySelectorAll("button");
|
||||
var defaultBtnCnt = 0;
|
||||
if ((_uType & MBFLAGS.MB_DEFBUTTON1) === MBFLAGS.MB_DEFBUTTON1) defaultBtnCnt = 0;
|
||||
if ((_uType & MBFLAGS.MB_DEFBUTTON2) === MBFLAGS.MB_DEFBUTTON2) defaultBtnCnt = 1;
|
||||
if ((_uType & MBFLAGS.MB_DEFBUTTON3) === MBFLAGS.MB_DEFBUTTON3) defaultBtnCnt = 2;
|
||||
if ((_uType & MBFLAGS.MB_DEFBUTTON4) === MBFLAGS.MB_DEFBUTTON4) defaultBtnCnt = 3;
|
||||
for (cnt = 0; cnt < btns.length; cnt++) {
|
||||
if (cnt === defaultBtnCnt) {
|
||||
btns[cnt].focus();
|
||||
break;
|
||||
}
|
||||
}
|
||||
document.body.appendChild(msgbox);
|
||||
setTimeout(function() {
|
||||
msgbox.style.opacity = 1;
|
||||
}, 1);
|
||||
return msgbox.id;
|
||||
}
|
||||
|
||||
function MsgBoxObj() {
|
||||
this.elementId = "";
|
||||
this.callback = null;
|
||||
this.type = MBFLAGS.MB_OK;
|
||||
this._boundCallback = this._internalCallback.bind(this);
|
||||
this._text = "";
|
||||
this._title = "";
|
||||
this._color = "#0078d7";
|
||||
this.show = function() {
|
||||
this.elementId = MessageBoxForJS(
|
||||
this._text,
|
||||
this._title,
|
||||
this.type,
|
||||
this._color,
|
||||
this._boundCallback
|
||||
);
|
||||
setTimeout(function() {
|
||||
var element = document.getElementById(this.elementId);
|
||||
if (element) {
|
||||
var bodyElement = element.querySelector(".notice-body");
|
||||
if (bodyElement) {
|
||||
bodyElement.style.transition = "all 0.5s linear";
|
||||
}
|
||||
}
|
||||
}.bind(this), 100);
|
||||
}
|
||||
Object.defineProperty(this, "text", {
|
||||
get: function() {
|
||||
return this._text;
|
||||
},
|
||||
set: function(value) {
|
||||
this._text = value;
|
||||
if (this.elementId) {
|
||||
var element = document.getElementById(this.elementId);
|
||||
if (element) {
|
||||
var textElement = element.querySelector(".notice-text");
|
||||
if (textElement) {
|
||||
if (value instanceof HTMLElement) {
|
||||
value.classList.add("notice-text");
|
||||
textElement.parentNode.replaceChild(value, textElement);
|
||||
} else {
|
||||
textElement.innerHTML = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.defineProperty(this, "title", {
|
||||
get: function() {
|
||||
return this._title;
|
||||
},
|
||||
set: function(value) {
|
||||
this._title = value;
|
||||
if (this.elementId) {
|
||||
var element = document.getElementById(this.elementId);
|
||||
if (element) {
|
||||
var titleElement = element.querySelector(".notice-title");
|
||||
if (titleElement) {
|
||||
titleElement.innerHTML = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.defineProperty(this, "color", {
|
||||
get: function() {
|
||||
return this._color;
|
||||
},
|
||||
set: function(value) {
|
||||
this._color = value;
|
||||
if (this.elementId) {
|
||||
var element = document.getElementById(this.elementId);
|
||||
if (element) {
|
||||
var bodyElement = element.querySelector(".notice-body");
|
||||
if (bodyElement) {
|
||||
bodyElement.style.backgroundColor = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this.getElement = function() {
|
||||
return document.getElementById(this.elementId);
|
||||
};
|
||||
}
|
||||
|
||||
MsgBoxObj.prototype._internalCallback = function(returnValue) {
|
||||
if (typeof this.callback === "function") {
|
||||
this.callback(returnValue);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 异步显示消息框,返回一个 Promise 对象。
|
||||
* @param {string | HTMLElement} swText 内容
|
||||
* @param {string} swTitle 标题
|
||||
* @param {MBFLAGS} uType 标志,使用 MBFLAGS 常量
|
||||
* @param {string} swColor 背景颜色文本。
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function messageBoxAsync(swText, swTitle, uType, swColor, pfCallback) {
|
||||
if (typeof Promise === "undefined") {
|
||||
console.error("Promise is not supported in this environment.");
|
||||
MessageBoxForJS(swText, swTitle, uType, swColor, pfCallback);
|
||||
}
|
||||
return new Promise(function(resolve, reject) {
|
||||
try {
|
||||
MessageBoxForJS(swText, swTitle, uType, swColor, function(valueReturn) {
|
||||
if (resolve) resolve(valueReturn);
|
||||
});
|
||||
} catch (ex) {
|
||||
if (reject) reject(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function MessageBoxButton(swDisplayName, nValueReturn) {
|
||||
this.displayName = swDisplayName;
|
||||
this.value = nValueReturn;
|
||||
}
|
||||
|
||||
function messageBoxAdvance(swText, swCaption, aCommands, swColor, pfCallback) {
|
||||
var _lpText = swText;
|
||||
var _lpCaption = swCaption;
|
||||
var msgbox = document.createElement("div");
|
||||
msgbox.classList.add("notice-back");
|
||||
msgbox.classList.add("win-ui-dark");
|
||||
var uniqueId = "msgbox_" + new Date().getTime();
|
||||
msgbox.id = uniqueId;
|
||||
var msgbody = document.createElement("div");
|
||||
msgbody.classList.add("notice-body");
|
||||
if (!IsBlackLabel(swColor)) {
|
||||
msgbody.style.backgroundColor = swColor;
|
||||
}
|
||||
msgbox.appendChild(msgbody);
|
||||
var msgcontainter = document.createElement("div");
|
||||
msgcontainter.style.height = "100%";
|
||||
msgcontainter.style.width = "100%";
|
||||
msgcontainter.style.maxHeight = "100%";
|
||||
msgcontainter.style.minHeight = "0px";
|
||||
msgcontainter.style.boxSizing = "border-box";
|
||||
msgbody.appendChild(msgcontainter);
|
||||
var msgcaption = document.createElement("div");
|
||||
msgcontainter.appendChild(msgcaption);
|
||||
msgcontainter.style.display = "flex";
|
||||
msgcontainter.style.flexDirection = "column";
|
||||
var msgcontent = document.createElement("div");
|
||||
msgcontent.style.flex = "1 1 auto";
|
||||
msgcontent.style.marginRight = "3px";
|
||||
msgcontent.style.overflowX = "hidden";
|
||||
msgcontent.style.overflowY = "auto";
|
||||
msgcontent.style.minHeight = "0px";
|
||||
msgcontainter.appendChild(msgcontent);
|
||||
if (_lpCaption instanceof HTMLElement) {
|
||||
msgcaption.appendChild(_lpCaption);
|
||||
msgcaption.classList.add("notice-title");
|
||||
} else {
|
||||
if (!IsBlackLabel(_lpCaption)) {
|
||||
var msgtitle = document.createElement("h2");
|
||||
msgtitle.textContent = _lpCaption;
|
||||
msgtitle.classList.add("notice-title");
|
||||
msgcaption.appendChild(msgtitle);
|
||||
} else {
|
||||
var msgtitle = document.createElement("h2");
|
||||
msgtitle.textContent = "";
|
||||
msgtitle.classList.add("notice-title");
|
||||
msgcaption.appendChild(msgtitle);
|
||||
}
|
||||
}
|
||||
if (_lpText instanceof HTMLElement || _lpText instanceof HTMLDivElement || typeof _lpText !== "string") {
|
||||
try {
|
||||
_lpText.classList.add("notice-text");
|
||||
msgcontent.appendChild(_lpText);
|
||||
} catch (e) {
|
||||
if (!IsBlackLabel(_lpText)) {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.textContent = _lpText;
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
} else {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.innerText = "";
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!IsBlackLabel(_lpText)) {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.textContent = _lpText;
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
} else {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.innerText = "";
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
}
|
||||
}
|
||||
var msgctrls = document.createElement("div");
|
||||
msgctrls.classList.add("notice-controls");
|
||||
msgcontainter.appendChild(msgctrls);
|
||||
if (aCommands.length <= 0) {
|
||||
aCommands.push(new MessageBoxButton(GetLocaleStringFromResId(800) || "OK", MBRET.IDOK));
|
||||
}
|
||||
for (var i = 0; i < aCommands.length; i++) {
|
||||
var cmd = aCommands[i];
|
||||
var btn = document.createElement("button");
|
||||
btn.textContent = cmd.displayName;
|
||||
btn.setAttribute("data-msgbox-value", cmd.value);
|
||||
Windows.UI.Event.Util.addEvent(btn, "click", function(event) {
|
||||
var btns = this.parentNode.querySelectorAll("button");
|
||||
var lastbtnstatus = [];
|
||||
for (var j = 0; j < btns.length; j++) {
|
||||
lastbtnstatus.push(btns[j].disabled);
|
||||
btns[j].disabled = true;
|
||||
}
|
||||
try {
|
||||
pfCallback(this.getAttribute("data-msgbox-value"));
|
||||
} catch (e) {}
|
||||
msgbox.style.opacity = 0;
|
||||
setTimeout(function(nodes, laststatus) {
|
||||
for (var k = 0; k < nodes.length; k++) {
|
||||
nodes[k].disabled = laststatus[k];
|
||||
}
|
||||
document.body.removeChild(msgbox);
|
||||
}, 500, btns, lastbtnstatus);
|
||||
});
|
||||
msgctrls.appendChild(btn);
|
||||
}
|
||||
document.body.appendChild(msgbox);
|
||||
setTimeout(function() {
|
||||
msgbox.style.opacity = 1;
|
||||
}, 1);
|
||||
return msgbox.id;
|
||||
}
|
||||
|
||||
function messageBoxAdvanceAsync(swText, swCaption, aCommands, swColor) {
|
||||
if (typeof Promise === "undefined") {
|
||||
console.error("Promise is not supported in this environment.");
|
||||
messageBoxAdvance(swText, swCaption, aCommands, swColor);
|
||||
}
|
||||
return new Promise(function(resolve, reject) {
|
||||
try {
|
||||
messageBoxAdvance(swText, swCaption, aCommands, swColor, function(valueReturn) {
|
||||
if (resolve) resolve(valueReturn);
|
||||
});
|
||||
} catch (ex) {
|
||||
if (reject) reject(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -39,6 +39,7 @@ var MBRET = {
|
||||
Object.freeze(MBFLAGS);
|
||||
Object.freeze(MBRET);
|
||||
|
||||
// ==================== 资源加载部分(保持不变) ====================
|
||||
(function(global) {
|
||||
try {
|
||||
var storage = Bridge.External.Storage;
|
||||
@@ -53,15 +54,197 @@ Object.freeze(MBRET);
|
||||
} catch (e) {}
|
||||
})(this);
|
||||
|
||||
function GetLocaleStringFromResId(resId) { try { return getPublicRes(resId); } catch (e) {} }
|
||||
function GetLocaleStringFromResId(resId) {
|
||||
try { return getPublicRes(resId); } catch (e) { return ""; }
|
||||
}
|
||||
|
||||
// ==================== 全局结果存储 ====================
|
||||
var msgboxResult = {};
|
||||
|
||||
function MessageBox(_lpText, _lpCaption, _uType, _objColor) {
|
||||
var id = MessageBoxForJS(_lpText, _lpCaption, _uType, _objColor, function(valueReturn) {
|
||||
getRes = valueReturn;
|
||||
msgboxResult[id] = valueReturn;
|
||||
function ClearAllMessageBoxResults() {
|
||||
msgboxResult = {};
|
||||
}
|
||||
|
||||
// ==================== 辅助函数 ====================
|
||||
var _msgboxIdCounter = 0;
|
||||
|
||||
function _generateMsgBoxId() {
|
||||
return "msgbox_" + new Date().getTime() + "_" + (++_msgboxIdCounter);
|
||||
}
|
||||
|
||||
// 根据 MBFLAGS 生成命令列表(返回 { commands, defaultIndex })
|
||||
function _buildCommandsFromFlags(uType) {
|
||||
var commands = [];
|
||||
var baseType = uType & 0xF;
|
||||
var defaultIndex = 0;
|
||||
var hasHelp = (uType & MBFLAGS.MB_HELP) === MBFLAGS.MB_HELP;
|
||||
|
||||
// 辅助添加命令
|
||||
function addCommand(resId, returnValue) {
|
||||
var label = GetLocaleStringFromResId(resId);
|
||||
if (!label) label = "Button";
|
||||
commands.push({ label: label, value: returnValue });
|
||||
}
|
||||
|
||||
// 先处理帮助按钮(原实现中帮助按钮总是在最前面)
|
||||
if (hasHelp) {
|
||||
addCommand(808, MBRET.IDHELP);
|
||||
}
|
||||
|
||||
// 根据基础类型添加按钮
|
||||
switch (baseType) {
|
||||
case MBFLAGS.MB_OK:
|
||||
addCommand(800, MBRET.IDOK);
|
||||
break;
|
||||
case MBFLAGS.MB_OKCANCEL:
|
||||
addCommand(800, MBRET.IDOK);
|
||||
addCommand(801, MBRET.IDCANCEL);
|
||||
break;
|
||||
case MBFLAGS.MB_ABORTRETRYIGNORE:
|
||||
addCommand(802, MBRET.IDABORT);
|
||||
addCommand(803, MBRET.IDRETRY);
|
||||
addCommand(804, MBRET.IDIGNORE);
|
||||
break;
|
||||
case MBFLAGS.MB_YESNOCANCEL:
|
||||
addCommand(805, MBRET.IDYES);
|
||||
addCommand(806, MBRET.IDNO);
|
||||
addCommand(801, MBRET.IDCANCEL);
|
||||
break;
|
||||
case MBFLAGS.MB_YESNO:
|
||||
addCommand(805, MBRET.IDYES);
|
||||
addCommand(806, MBRET.IDNO);
|
||||
break;
|
||||
case MBFLAGS.MB_RETRYCANCEL:
|
||||
addCommand(803, MBRET.IDRETRY);
|
||||
addCommand(801, MBRET.IDCANCEL);
|
||||
break;
|
||||
case MBFLAGS.MB_CANCELTRYCONTINUE:
|
||||
addCommand(801, MBRET.IDCANCEL);
|
||||
addCommand(803, MBRET.IDRETRY);
|
||||
addCommand(810, MBRET.IDCONTINUE);
|
||||
break;
|
||||
default:
|
||||
addCommand(800, MBRET.IDOK);
|
||||
break;
|
||||
}
|
||||
|
||||
// 确定默认按钮索引(考虑帮助按钮占位)
|
||||
var defFlag = uType & 0x300; // MB_DEFBUTTON1~4
|
||||
var defButtonNumber = 0;
|
||||
if (defFlag === MBFLAGS.MB_DEFBUTTON2) defButtonNumber = 1;
|
||||
else if (defFlag === MBFLAGS.MB_DEFBUTTON3) defButtonNumber = 2;
|
||||
else if (defFlag === MBFLAGS.MB_DEFBUTTON4) defButtonNumber = 3;
|
||||
else defButtonNumber = 0;
|
||||
|
||||
// 默认索引需要加上帮助按钮的偏移
|
||||
var finalDefaultIndex = (hasHelp ? 1 : 0) + defButtonNumber;
|
||||
if (finalDefaultIndex >= commands.length) finalDefaultIndex = commands.length - 1;
|
||||
if (finalDefaultIndex < 0) finalDefaultIndex = 0;
|
||||
|
||||
return { commands: commands, defaultIndex: finalDefaultIndex };
|
||||
}
|
||||
|
||||
// 创建 ContentDialog 并应用公共属性
|
||||
function _createContentDialog(title, content, bgColor, commands, defaultIndex, callback) {
|
||||
var container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
|
||||
var dialog = new WinJS.UI.ContentDialog(container, {
|
||||
//title: typeof title === "string" ? title : "",
|
||||
//content: typeof content === "string" ? content : "",
|
||||
autoShow: false
|
||||
});
|
||||
return id;
|
||||
dialog.title = title;
|
||||
dialog.content = content;
|
||||
// 处理标题为 HTMLElement
|
||||
if (title instanceof HTMLElement) {
|
||||
var titleContainer = container.querySelector(".win-contentdialog-title");
|
||||
if (titleContainer) {
|
||||
while (titleContainer.firstChild) titleContainer.removeChild(titleContainer.firstChild);
|
||||
titleContainer.appendChild(title);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理内容为 HTMLElement
|
||||
if (content instanceof HTMLElement) {
|
||||
var contentContainer = container.querySelector(".win-contentdialog-content");
|
||||
if (contentContainer) {
|
||||
while (contentContainer.firstChild) contentContainer.removeChild(contentContainer.firstChild);
|
||||
contentContainer.appendChild(content);
|
||||
}
|
||||
}
|
||||
|
||||
// 背景色
|
||||
if (!IsBlackLabel(bgColor)) {
|
||||
dialog.backgroundColor = bgColor;
|
||||
}
|
||||
|
||||
// 添加命令
|
||||
for (var i = 0; i < commands.length; i++) {
|
||||
var cmd = commands[i];
|
||||
var dialogCmd = new WinJS.UI.ContentDialogCommand(cmd.label, function(evt) {
|
||||
// 阻止多次点击
|
||||
if (dialog._isClosing) return;
|
||||
dialog._isClosing = true;
|
||||
|
||||
// 调用回调传递返回值
|
||||
if (callback) callback(cmd.value);
|
||||
|
||||
// 关闭并移除对话框
|
||||
dialog.hide().then(function() {
|
||||
try { document.body.removeChild(container); } catch (e) {}
|
||||
dialog._isClosing = false;
|
||||
});
|
||||
|
||||
// 返回 false 会阻止关闭,但我们手动关闭,所以返回 undefined 即可
|
||||
}, cmd.value.toString());
|
||||
dialog.commands.push(dialogCmd);
|
||||
}
|
||||
|
||||
// 设置默认按钮
|
||||
if (defaultIndex >= 0 && defaultIndex < dialog.commands.length) {
|
||||
dialog.primaryCommandIndex = defaultIndex;
|
||||
}
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
// ==================== 核心 API 实现 ====================
|
||||
|
||||
// 新版 MessageBoxForJS(完全基于 ContentDialog)
|
||||
function MessageBoxForJS(_lpText, _lpCaption, _uType, _objColor, _callback) {
|
||||
var dialogId = _generateMsgBoxId();
|
||||
var commandsInfo = _buildCommandsFromFlags(_uType);
|
||||
|
||||
var dialog = _createContentDialog(
|
||||
_lpCaption,
|
||||
_lpText,
|
||||
_objColor,
|
||||
commandsInfo.commands,
|
||||
commandsInfo.defaultIndex,
|
||||
function(returnValue) {
|
||||
if (_callback) _callback(returnValue);
|
||||
}
|
||||
);
|
||||
|
||||
// 存储 dialog 引用以便可能的后续操作(如 GetMessageBoxResult 不需要,但保留)
|
||||
if (!window._activeDialogs) window._activeDialogs = {};
|
||||
window._activeDialogs[dialogId] = dialog;
|
||||
dialog.element.id = dialogId;
|
||||
// 显示对话框
|
||||
dialog.show().then(null, function(err) { console.error("ContentDialog show error:", err); });
|
||||
|
||||
return dialogId;
|
||||
}
|
||||
|
||||
// MessageBox:返回 ID,结果通过 GetMessageBoxResult 获取
|
||||
function MessageBox(_lpText, _lpCaption, _uType, _objColor) {
|
||||
var msgboxId = _generateMsgBoxId();
|
||||
MessageBoxForJS(_lpText, _lpCaption, _uType, _objColor, function(valueReturn) {
|
||||
msgboxResult[msgboxId] = valueReturn;
|
||||
if (window._activeDialogs) delete window._activeDialogs[msgboxId];
|
||||
});
|
||||
return msgboxId;
|
||||
}
|
||||
|
||||
function GetMessageBoxResult(msgboxId) {
|
||||
@@ -71,201 +254,84 @@ function GetMessageBoxResult(msgboxId) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function ClearAllMessageBoxResults() {
|
||||
msgboxResult = null;
|
||||
msgboxResult = {};
|
||||
}
|
||||
|
||||
// 注意:callback 函数无返回值,传入参数:整数型 按下的按钮值。
|
||||
/*
|
||||
使用示例:
|
||||
MessageBoxForJS("请选择一个按钮", "", MBFLAGS.MB_OKCANCEL, "#0078d7", function(value) {
|
||||
console.log("MessageBoxForJS callback value: " + value);
|
||||
})
|
||||
*/
|
||||
function MessageBoxForJS(_lpText, _lpCaption, _uType, _objColor, _callback) {
|
||||
var msgbox = document.createElement("div");
|
||||
msgbox.classList.add("notice-back");
|
||||
msgbox.classList.add("win-ui-dark");
|
||||
var uniqueId = "msgbox_" + new Date().getTime();
|
||||
msgbox.id = uniqueId;
|
||||
var msgbody = document.createElement("div");
|
||||
msgbody.classList.add("notice-body");
|
||||
if (!IsBlackLabel(_objColor)) {
|
||||
msgbody.style.backgroundColor = _objColor;
|
||||
// 异步版本(返回 Promise)
|
||||
function messageBoxAsync(swText, swTitle, uType, swColor, pfCallback) {
|
||||
if (typeof Promise === "undefined") {
|
||||
console.error("Promise is not supported in this environment.");
|
||||
MessageBoxForJS(swText, swTitle, uType, swColor, pfCallback);
|
||||
return null;
|
||||
}
|
||||
msgbox.appendChild(msgbody);
|
||||
var msgcontainter = document.createElement("div");
|
||||
msgcontainter.style.height = "100%";
|
||||
msgcontainter.style.width = "100%";
|
||||
msgcontainter.style.maxHeight = "100%";
|
||||
msgcontainter.style.minHeight = "0px";
|
||||
msgcontainter.style.boxSizing = "border-box";
|
||||
msgbody.appendChild(msgcontainter);
|
||||
var msgcaption = document.createElement("div");
|
||||
msgcontainter.appendChild(msgcaption);
|
||||
msgcontainter.style.display = "flex";
|
||||
msgcontainter.style.flexDirection = "column";
|
||||
var msgcontent = document.createElement("div");
|
||||
msgcontent.style.flex = "1 1 auto";
|
||||
msgcontent.style.marginRight = "3px";
|
||||
msgcontent.style.overflowX = "hidden";
|
||||
msgcontent.style.overflowY = "auto";
|
||||
msgcontent.style.minHeight = "0px";
|
||||
msgcontainter.appendChild(msgcontent);
|
||||
if (_lpCaption instanceof HTMLElement) {
|
||||
msgcaption.appendChild(_lpCaption);
|
||||
msgcaption.classList.add("notice-title");
|
||||
} else {
|
||||
if (!IsBlackLabel(_lpCaption)) {
|
||||
var msgtitle = document.createElement("h2");
|
||||
msgtitle.textContent = _lpCaption;
|
||||
msgtitle.classList.add("notice-title");
|
||||
msgcaption.appendChild(msgtitle);
|
||||
} else {
|
||||
var msgtitle = document.createElement("h2");
|
||||
msgtitle.textContent = "";
|
||||
msgtitle.classList.add("notice-title");
|
||||
msgcaption.appendChild(msgtitle);
|
||||
}
|
||||
}
|
||||
if (_lpText instanceof HTMLElement || _lpText instanceof HTMLDivElement || typeof _lpText !== "string") {
|
||||
return new Promise(function(resolve, reject) {
|
||||
try {
|
||||
_lpText.classList.add("notice-text");
|
||||
msgcontent.appendChild(_lpText);
|
||||
} catch (e) {
|
||||
if (!IsBlackLabel(_lpText)) {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.textContent = _lpText;
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
} else {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.innerText = "";
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
}
|
||||
MessageBoxForJS(swText, swTitle, uType, swColor, function(valueReturn) {
|
||||
if (pfCallback) pfCallback(valueReturn);
|
||||
resolve(valueReturn);
|
||||
});
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
} else {
|
||||
if (!IsBlackLabel(_lpText)) {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.textContent = _lpText;
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
} else {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.innerText = "";
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
}
|
||||
}
|
||||
var msgctrls = document.createElement("div");
|
||||
msgctrls.classList.add("notice-controls");
|
||||
msgcontainter.appendChild(msgctrls);
|
||||
var cnt = 0;
|
||||
var cbFuncPress = function(valueReturn) {
|
||||
getRes = valueReturn;
|
||||
msgbox.style.opacity = 0;
|
||||
setTimeout(function() {
|
||||
document.body.removeChild(msgbox);
|
||||
}, 500);
|
||||
if (_callback) {
|
||||
_callback(valueReturn);
|
||||
}
|
||||
};
|
||||
var pfCreateButton = function(displayNameResId, valueReturn) {
|
||||
var btn = document.createElement("button");
|
||||
btn.innerHTML = GetLocaleStringFromResId(displayNameResId);
|
||||
btn.classList.add("notice-btn");
|
||||
btn.addEventListener("click", function() {
|
||||
cbFuncPress(valueReturn);
|
||||
});
|
||||
msgctrls.appendChild(btn);
|
||||
};
|
||||
if ((_uType & MBFLAGS.MB_HELP) === MBFLAGS.MB_HELP) {
|
||||
pfCreateButton(808, MBRET.IDHELP);
|
||||
}
|
||||
for (cnt = 0; cnt <= MBFLAGS.MB_RETRYCANCEL; cnt++) {
|
||||
if ((_uType & 0xF) === cnt) {
|
||||
switch (cnt) {
|
||||
case MBFLAGS.MB_OK:
|
||||
{
|
||||
pfCreateButton(800, MBRET.IDOK);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_OKCANCEL:
|
||||
{
|
||||
pfCreateButton(800, MBRET.IDOK);
|
||||
pfCreateButton(801, MBRET.IDCANCEL);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_ABORTRETRYIGNORE:
|
||||
{
|
||||
pfCreateButton(802, MBRET.IDABORT);
|
||||
pfCreateButton(803, MBRET.IDRETRY);
|
||||
pfCreateButton(804, MBRET.IDIGNORE);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_YESNOCANCEL:
|
||||
{
|
||||
pfCreateButton(805, MBRET.IDYES);
|
||||
pfCreateButton(806, MBRET.IDNO);
|
||||
pfCreateButton(801, MBRET.IDCANCEL);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_YESNO:
|
||||
{
|
||||
pfCreateButton(805, MBRET.IDYES);
|
||||
pfCreateButton(806, MBRET.IDNO);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_RETRYCANCEL:
|
||||
{
|
||||
pfCreateButton(803, MBRET.IDRETRY);
|
||||
pfCreateButton(801, MBRET.IDCANCEL);
|
||||
}
|
||||
break;
|
||||
case MBFLAGS.MB_CANCELTRYCONTINUE:
|
||||
{
|
||||
pfCreateButton(801, MBRET.IDCANCEL);
|
||||
pfCreateButton(803, MBRET.IDRETRY);
|
||||
pfCreateButton(810, MBRET.IDCONTINUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
var btns = msgctrls.querySelectorAll("button");
|
||||
var defaultBtnCnt = 0;
|
||||
if ((_uType & MBFLAGS.MB_DEFBUTTON1) === MBFLAGS.MB_DEFBUTTON1) defaultBtnCnt = 0;
|
||||
if ((_uType & MBFLAGS.MB_DEFBUTTON2) === MBFLAGS.MB_DEFBUTTON2) defaultBtnCnt = 1;
|
||||
if ((_uType & MBFLAGS.MB_DEFBUTTON3) === MBFLAGS.MB_DEFBUTTON3) defaultBtnCnt = 2;
|
||||
if ((_uType & MBFLAGS.MB_DEFBUTTON4) === MBFLAGS.MB_DEFBUTTON4) defaultBtnCnt = 3;
|
||||
for (cnt = 0; cnt < btns.length; cnt++) {
|
||||
if (cnt === defaultBtnCnt) {
|
||||
btns[cnt].focus();
|
||||
break;
|
||||
}
|
||||
}
|
||||
document.body.appendChild(msgbox);
|
||||
setTimeout(function() {
|
||||
msgbox.style.opacity = 1;
|
||||
}, 1);
|
||||
return msgbox.id;
|
||||
});
|
||||
}
|
||||
|
||||
// MessageBoxButton 类(保持不变)
|
||||
function MessageBoxButton(swDisplayName, nValueReturn) {
|
||||
this.displayName = swDisplayName;
|
||||
this.value = nValueReturn;
|
||||
}
|
||||
|
||||
// 高级自定义按钮对话框
|
||||
function messageBoxAdvance(swText, swCaption, aCommands, swColor, pfCallback) {
|
||||
var dialogId = _generateMsgBoxId();
|
||||
|
||||
// 转换 aCommands 为内部格式
|
||||
var commands = [];
|
||||
for (var i = 0; i < aCommands.length; i++) {
|
||||
var cmd = aCommands[i];
|
||||
commands.push({
|
||||
label: cmd.displayName,
|
||||
value: cmd.value
|
||||
});
|
||||
}
|
||||
if (commands.length === 0) {
|
||||
commands.push({ label: GetLocaleStringFromResId(800) || "OK", value: MBRET.IDOK });
|
||||
}
|
||||
|
||||
var dialog = _createContentDialog(
|
||||
swCaption,
|
||||
swText,
|
||||
swColor,
|
||||
commands,
|
||||
0, // 默认第一个按钮为默认
|
||||
function(returnValue) {
|
||||
if (pfCallback) pfCallback(returnValue);
|
||||
}
|
||||
);
|
||||
dialog.element.id = dialogId;
|
||||
if (!window._activeDialogs) window._activeDialogs = {};
|
||||
window._activeDialogs[dialogId] = dialog;
|
||||
|
||||
dialog.show();
|
||||
return dialogId;
|
||||
}
|
||||
|
||||
function messageBoxAdvanceAsync(swText, swCaption, aCommands, swColor) {
|
||||
if (typeof Promise === "undefined") {
|
||||
console.error("Promise is not supported in this environment.");
|
||||
messageBoxAdvance(swText, swCaption, aCommands, swColor);
|
||||
return null;
|
||||
}
|
||||
return new Promise(function(resolve, reject) {
|
||||
try {
|
||||
messageBoxAdvance(swText, swCaption, aCommands, swColor, function(valueReturn) {
|
||||
resolve(valueReturn);
|
||||
});
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== MsgBoxObj 类(保持原接口,内部已适配) ====================
|
||||
function MsgBoxObj() {
|
||||
this.elementId = "";
|
||||
this.callback = null;
|
||||
@@ -274,28 +340,31 @@ function MsgBoxObj() {
|
||||
this._text = "";
|
||||
this._title = "";
|
||||
this._color = "#0078d7";
|
||||
|
||||
this.show = function() {
|
||||
var self = this;
|
||||
this.elementId = MessageBoxForJS(
|
||||
this._text,
|
||||
this._title,
|
||||
this.type,
|
||||
this._color,
|
||||
this._boundCallback
|
||||
function(valueReturn) {
|
||||
self._boundCallback(valueReturn);
|
||||
}
|
||||
);
|
||||
setTimeout(function() {
|
||||
var element = document.getElementById(this.elementId);
|
||||
var element = document.getElementById(self.elementId);
|
||||
if (element) {
|
||||
var bodyElement = element.querySelector(".notice-body");
|
||||
if (bodyElement) {
|
||||
bodyElement.style.transition = "all 0.5s linear";
|
||||
}
|
||||
}
|
||||
}.bind(this), 100);
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
|
||||
Object.defineProperty(this, "text", {
|
||||
get: function() {
|
||||
return this._text;
|
||||
},
|
||||
get: function() { return this._text; },
|
||||
set: function(value) {
|
||||
this._text = value;
|
||||
if (this.elementId) {
|
||||
@@ -314,10 +383,9 @@ function MsgBoxObj() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(this, "title", {
|
||||
get: function() {
|
||||
return this._title;
|
||||
},
|
||||
get: function() { return this._title; },
|
||||
set: function(value) {
|
||||
this._title = value;
|
||||
if (this.elementId) {
|
||||
@@ -331,10 +399,9 @@ function MsgBoxObj() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(this, "color", {
|
||||
get: function() {
|
||||
return this._color;
|
||||
},
|
||||
get: function() { return this._color; },
|
||||
set: function(value) {
|
||||
this._color = value;
|
||||
if (this.elementId) {
|
||||
@@ -348,6 +415,7 @@ function MsgBoxObj() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.getElement = function() {
|
||||
return document.getElementById(this.elementId);
|
||||
};
|
||||
@@ -357,176 +425,4 @@ MsgBoxObj.prototype._internalCallback = function(returnValue) {
|
||||
if (typeof this.callback === "function") {
|
||||
this.callback(returnValue);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 异步显示消息框,返回一个 Promise 对象。
|
||||
* @param {string | HTMLElement} swText 内容
|
||||
* @param {string} swTitle 标题
|
||||
* @param {MBFLAGS} uType 标志,使用 MBFLAGS 常量
|
||||
* @param {string} swColor 背景颜色文本。
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function messageBoxAsync(swText, swTitle, uType, swColor, pfCallback) {
|
||||
if (typeof Promise === "undefined") {
|
||||
console.error("Promise is not supported in this environment.");
|
||||
MessageBoxForJS(swText, swTitle, uType, swColor, pfCallback);
|
||||
}
|
||||
return new Promise(function(resolve, reject) {
|
||||
try {
|
||||
MessageBoxForJS(swText, swTitle, uType, swColor, function(valueReturn) {
|
||||
if (resolve) resolve(valueReturn);
|
||||
});
|
||||
} catch (ex) {
|
||||
if (reject) reject(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function MessageBoxButton(swDisplayName, nValueReturn) {
|
||||
this.displayName = swDisplayName;
|
||||
this.value = nValueReturn;
|
||||
}
|
||||
|
||||
function messageBoxAdvance(swText, swCaption, aCommands, swColor, pfCallback) {
|
||||
var _lpText = swText;
|
||||
var _lpCaption = swCaption;
|
||||
var msgbox = document.createElement("div");
|
||||
msgbox.classList.add("notice-back");
|
||||
msgbox.classList.add("win-ui-dark");
|
||||
var uniqueId = "msgbox_" + new Date().getTime();
|
||||
msgbox.id = uniqueId;
|
||||
var msgbody = document.createElement("div");
|
||||
msgbody.classList.add("notice-body");
|
||||
if (!IsBlackLabel(swColor)) {
|
||||
msgbody.style.backgroundColor = swColor;
|
||||
}
|
||||
msgbox.appendChild(msgbody);
|
||||
var msgcontainter = document.createElement("div");
|
||||
msgcontainter.style.height = "100%";
|
||||
msgcontainter.style.width = "100%";
|
||||
msgcontainter.style.maxHeight = "100%";
|
||||
msgcontainter.style.minHeight = "0px";
|
||||
msgcontainter.style.boxSizing = "border-box";
|
||||
msgbody.appendChild(msgcontainter);
|
||||
var msgcaption = document.createElement("div");
|
||||
msgcontainter.appendChild(msgcaption);
|
||||
msgcontainter.style.display = "flex";
|
||||
msgcontainter.style.flexDirection = "column";
|
||||
var msgcontent = document.createElement("div");
|
||||
msgcontent.style.flex = "1 1 auto";
|
||||
msgcontent.style.marginRight = "3px";
|
||||
msgcontent.style.overflowX = "hidden";
|
||||
msgcontent.style.overflowY = "auto";
|
||||
msgcontent.style.minHeight = "0px";
|
||||
msgcontainter.appendChild(msgcontent);
|
||||
if (_lpCaption instanceof HTMLElement) {
|
||||
msgcaption.appendChild(_lpCaption);
|
||||
msgcaption.classList.add("notice-title");
|
||||
} else {
|
||||
if (!IsBlackLabel(_lpCaption)) {
|
||||
var msgtitle = document.createElement("h2");
|
||||
msgtitle.textContent = _lpCaption;
|
||||
msgtitle.classList.add("notice-title");
|
||||
msgcaption.appendChild(msgtitle);
|
||||
} else {
|
||||
var msgtitle = document.createElement("h2");
|
||||
msgtitle.textContent = "";
|
||||
msgtitle.classList.add("notice-title");
|
||||
msgcaption.appendChild(msgtitle);
|
||||
}
|
||||
}
|
||||
if (_lpText instanceof HTMLElement || _lpText instanceof HTMLDivElement || typeof _lpText !== "string") {
|
||||
try {
|
||||
_lpText.classList.add("notice-text");
|
||||
msgcontent.appendChild(_lpText);
|
||||
} catch (e) {
|
||||
if (!IsBlackLabel(_lpText)) {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.textContent = _lpText;
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
} else {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.innerText = "";
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!IsBlackLabel(_lpText)) {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.textContent = _lpText;
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
} else {
|
||||
var msgtext = document.createElement("p");
|
||||
msgtext.innerText = "";
|
||||
msgtext.classList.add("notice-text");
|
||||
if (IsBlackLabel(_lpCaption)) {
|
||||
msgtext.style.marginTop = "0";
|
||||
}
|
||||
msgcontent.appendChild(msgtext);
|
||||
}
|
||||
}
|
||||
var msgctrls = document.createElement("div");
|
||||
msgctrls.classList.add("notice-controls");
|
||||
msgcontainter.appendChild(msgctrls);
|
||||
if (aCommands.length <= 0) {
|
||||
aCommands.push(new MessageBoxButton(GetLocaleStringFromResId(800) || "OK", MBRET.IDOK));
|
||||
}
|
||||
for (var i = 0; i < aCommands.length; i++) {
|
||||
var cmd = aCommands[i];
|
||||
var btn = document.createElement("button");
|
||||
btn.textContent = cmd.displayName;
|
||||
btn.setAttribute("data-msgbox-value", cmd.value);
|
||||
Windows.UI.Event.Util.addEvent(btn, "click", function(event) {
|
||||
var btns = this.parentNode.querySelectorAll("button");
|
||||
var lastbtnstatus = [];
|
||||
for (var j = 0; j < btns.length; j++) {
|
||||
lastbtnstatus.push(btns[j].disabled);
|
||||
btns[j].disabled = true;
|
||||
}
|
||||
try {
|
||||
pfCallback(this.getAttribute("data-msgbox-value"));
|
||||
} catch (e) {}
|
||||
msgbox.style.opacity = 0;
|
||||
setTimeout(function(nodes, laststatus) {
|
||||
for (var k = 0; k < nodes.length; k++) {
|
||||
nodes[k].disabled = laststatus[k];
|
||||
}
|
||||
document.body.removeChild(msgbox);
|
||||
}, 500, btns, lastbtnstatus);
|
||||
});
|
||||
msgctrls.appendChild(btn);
|
||||
}
|
||||
document.body.appendChild(msgbox);
|
||||
setTimeout(function() {
|
||||
msgbox.style.opacity = 1;
|
||||
}, 1);
|
||||
return msgbox.id;
|
||||
}
|
||||
|
||||
function messageBoxAdvanceAsync(swText, swCaption, aCommands, swColor) {
|
||||
if (typeof Promise === "undefined") {
|
||||
console.error("Promise is not supported in this environment.");
|
||||
messageBoxAdvance(swText, swCaption, aCommands, swColor);
|
||||
}
|
||||
return new Promise(function(resolve, reject) {
|
||||
try {
|
||||
messageBoxAdvance(swText, swCaption, aCommands, swColor, function(valueReturn) {
|
||||
if (resolve) resolve(valueReturn);
|
||||
});
|
||||
} catch (ex) {
|
||||
if (reject) reject(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
BIN
shared/html/libs/winjs/3.0.7z
Normal file
@@ -1,7 +0,0 @@
|
||||
Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||
35
shared/html/libs/winjs/3.0/js/WinJS.min.js
vendored
12
shared/html/libs/winjs/3.0/js/base.min.js
vendored
@@ -1,460 +0,0 @@
|
||||
/*!
|
||||
Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
Build: 3.0.0.winjs.2014.10.2
|
||||
Version: WinJS.3.0
|
||||
*/
|
||||
|
||||
(function (global) {
|
||||
global.strings = global.strings || {};
|
||||
|
||||
var appxVersion = "WinJS.3.0";
|
||||
var developerPrefix = "Developer.";
|
||||
if (appxVersion.indexOf(developerPrefix) === 0) {
|
||||
appxVersion = appxVersion.substring(developerPrefix.length);
|
||||
}
|
||||
|
||||
function addStrings(keyPrefix, strings) {
|
||||
Object.keys(strings).forEach(function (key) {
|
||||
global.strings[keyPrefix + key.replace("\\", "/")] = strings[key];
|
||||
});
|
||||
}
|
||||
addStrings("ms-resource://"+appxVersion+"/ui/",
|
||||
{
|
||||
"appBarAriaLabel": "App Bar",
|
||||
"appBarCommandAriaLabel": "App Bar Item",
|
||||
"averageRating": "Average Rating",
|
||||
"backbuttonarialabel": "Back",
|
||||
"clearYourRating" : "Clear your rating",
|
||||
"closeOverlay" : "Close",
|
||||
"datePicker": "Date Picker",
|
||||
"flipViewPanningContainerAriaLabel": "Scrolling Container",
|
||||
"flyoutAriaLabel": "Flyout",
|
||||
"hubViewportAriaLabel": "Scrolling Container",
|
||||
"listViewViewportAriaLabel": "Scrolling Container",
|
||||
"menuCommandAriaLabel": "Menu Item",
|
||||
"menuAriaLabel": "Menu",
|
||||
"navBarContainerViewportAriaLabel": "Scrolling Container",
|
||||
"off" : "Off",
|
||||
"on" : "On",
|
||||
"pivotAriaLabel": "Pivot",
|
||||
"pivotViewportAriaLabel": "Scrolling Container",
|
||||
"searchBoxAriaLabel": "Searchbox",
|
||||
"searchBoxAriaLabelInputNoPlaceHolder": "Searchbox, enter to submit query, esc to clear text",
|
||||
"searchBoxAriaLabelInputPlaceHolder": "Searchbox, {0}, enter to submit query, esc to clear text",
|
||||
"searchBoxAriaLabelButton": "Click to submit query",
|
||||
"searchBoxAriaLabelQuery": "Suggestion: {0}",
|
||||
"_searchBoxAriaLabelQuery.comment": "Suggestion: query text (example: Suggestion: contoso)",
|
||||
"searchBoxAriaLabelSeparator": "Separator: {0}",
|
||||
"_searchBoxAriaLabelSeparator.comment": "Separator: separator text (example: Separator: People or Separator: Apps)",
|
||||
"searchBoxAriaLabelResult": "Result: {0}, {1}",
|
||||
"_searchBoxAriaLabelResult.comment": "Result: text, detailed text (example: Result: contoso, www.contoso.com)",
|
||||
"selectAMPM": "Select A.M P.M",
|
||||
"selectDay": "Select Day",
|
||||
"selectHour": "Select Hour",
|
||||
"selectMinute": "Select Minute",
|
||||
"selectMonth": "Select Month",
|
||||
"selectYear": "Select Year",
|
||||
"settingsFlyoutAriaLabel": "Settings Flyout",
|
||||
"tentativeRating": "Tentative Rating",
|
||||
"timePicker": "Time Picker",
|
||||
"unrated": "Unrated",
|
||||
"userRating": "User Rating",
|
||||
// AppBar Icons follow, the format of the ui.js and ui.resjson differ for
|
||||
// the AppBarIcon namespace. The remainder of the file therefore differs.
|
||||
// Code point comments are the icon glyphs in the 'Segoe UI Symbol' font.
|
||||
"appBarIcons\\previous": "\uE100", // group:Media
|
||||
"_appBarIcons\\previous.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\next": "\uE101", // group:Media
|
||||
"_appBarIcons\\next.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\play": "\uE102", // group:Media
|
||||
"_appBarIcons\\play.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\pause": "\uE103", // group:Media
|
||||
"_appBarIcons\\pause.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\edit": "\uE104", // group:File
|
||||
"_appBarIcons\\edit.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\save": "\uE105", // group:File
|
||||
"_appBarIcons\\save.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\clear": "\uE106", // group:File
|
||||
"_appBarIcons\\clear.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\delete": "\uE107", // group:File
|
||||
"_appBarIcons\\delete.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\remove": "\uE108", // group:File
|
||||
"_appBarIcons\\remove.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\add": "\uE109", // group:File
|
||||
"_appBarIcons\\add.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\cancel": "\uE10A", // group:Editing
|
||||
"_appBarIcons\\cancel.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\accept": "\uE10B", // group:General
|
||||
"_appBarIcons\\accept.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\more": "\uE10C", // group:General
|
||||
"_appBarIcons\\more.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\redo": "\uE10D", // group:Editing
|
||||
"_appBarIcons\\redo.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\undo": "\uE10E", // group:Editing
|
||||
"_appBarIcons\\undo.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\home": "\uE10F", // group:General
|
||||
"_appBarIcons\\home.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\up": "\uE110", // group:General
|
||||
"_appBarIcons\\up.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\forward": "\uE111", // group:General
|
||||
"_appBarIcons\\forward.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\right": "\uE111", // group:General
|
||||
"_appBarIcons\\right.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\back": "\uE112", // group:General
|
||||
"_appBarIcons\\back.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\left": "\uE112", // group:General
|
||||
"_appBarIcons\\left.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\favorite": "\uE113", // group:Media
|
||||
"_appBarIcons\\favorite.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\camera": "\uE114", // group:System
|
||||
"_appBarIcons\\camera.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\settings": "\uE115", // group:System
|
||||
"_appBarIcons\\settings.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\video": "\uE116", // group:Media
|
||||
"_appBarIcons\\video.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\sync": "\uE117", // group:Media
|
||||
"_appBarIcons\\sync.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\download": "\uE118", // group:Media
|
||||
"_appBarIcons\\download.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\mail": "\uE119", // group:Mail and calendar
|
||||
"_appBarIcons\\mail.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\find": "\uE11A", // group:Data
|
||||
"_appBarIcons\\find.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\help": "\uE11B", // group:General
|
||||
"_appBarIcons\\help.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\upload": "\uE11C", // group:Media
|
||||
"_appBarIcons\\upload.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\emoji": "\uE11D", // group:Communications
|
||||
"_appBarIcons\\emoji.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\twopage": "\uE11E", // group:Layout
|
||||
"_appBarIcons\\twopage.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\leavechat": "\uE11F", // group:Communications
|
||||
"_appBarIcons\\leavechat.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\mailforward": "\uE120", // group:Mail and calendar
|
||||
"_appBarIcons\\mailforward.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\clock": "\uE121", // group:General
|
||||
"_appBarIcons\\clock.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\send": "\uE122", // group:Mail and calendar
|
||||
"_appBarIcons\\send.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\crop": "\uE123", // group:Editing
|
||||
"_appBarIcons\\crop.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\rotatecamera": "\uE124", // group:System
|
||||
"_appBarIcons\\rotatecamera.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\people": "\uE125", // group:Communications
|
||||
"_appBarIcons\\people.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\closepane": "\uE126", // group:Layout
|
||||
"_appBarIcons\\closepane.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\openpane": "\uE127", // group:Layout
|
||||
"_appBarIcons\\openpane.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\world": "\uE128", // group:General
|
||||
"_appBarIcons\\world.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\flag": "\uE129", // group:Mail and calendar
|
||||
"_appBarIcons\\flag.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\previewlink": "\uE12A", // group:General
|
||||
"_appBarIcons\\previewlink.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\globe": "\uE12B", // group:Communications
|
||||
"_appBarIcons\\globe.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\trim": "\uE12C", // group:Editing
|
||||
"_appBarIcons\\trim.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\attachcamera": "\uE12D", // group:System
|
||||
"_appBarIcons\\attachcamera.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\zoomin": "\uE12E", // group:Layout
|
||||
"_appBarIcons\\zoomin.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\bookmarks": "\uE12F", // group:Editing
|
||||
"_appBarIcons\\bookmarks.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\document": "\uE130", // group:File
|
||||
"_appBarIcons\\document.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\protecteddocument": "\uE131", // group:File
|
||||
"_appBarIcons\\protecteddocument.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\page": "\uE132", // group:Layout
|
||||
"_appBarIcons\\page.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\bullets": "\uE133", // group:Editing
|
||||
"_appBarIcons\\bullets.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\comment": "\uE134", // group:Communications
|
||||
"_appBarIcons\\comment.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\mail2": "\uE135", // group:Mail and calendar
|
||||
"_appBarIcons\\mail2.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\contactinfo": "\uE136", // group:Communications
|
||||
"_appBarIcons\\contactinfo.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\hangup": "\uE137", // group:Communications
|
||||
"_appBarIcons\\hangup.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\viewall": "\uE138", // group:Data
|
||||
"_appBarIcons\\viewall.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\mappin": "\uE139", // group:General
|
||||
"_appBarIcons\\mappin.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\phone": "\uE13A", // group:Communications
|
||||
"_appBarIcons\\phone.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\videochat": "\uE13B", // group:Communications
|
||||
"_appBarIcons\\videochat.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\switch": "\uE13C", // group:Communications
|
||||
"_appBarIcons\\switch.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\contact": "\uE13D", // group:Communications
|
||||
"_appBarIcons\\contact.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\rename": "\uE13E", // group:File
|
||||
"_appBarIcons\\rename.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\pin": "\uE141", // group:System
|
||||
"_appBarIcons\\pin.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\musicinfo": "\uE142", // group:Media
|
||||
"_appBarIcons\\musicinfo.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\go": "\uE143", // group:General
|
||||
"_appBarIcons\\go.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\keyboard": "\uE144", // group:System
|
||||
"_appBarIcons\\keyboard.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\dockleft": "\uE145", // group:Layout
|
||||
"_appBarIcons\\dockleft.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\dockright": "\uE146", // group:Layout
|
||||
"_appBarIcons\\dockright.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\dockbottom": "\uE147", // group:Layout
|
||||
"_appBarIcons\\dockbottom.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\remote": "\uE148", // group:System
|
||||
"_appBarIcons\\remote.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\refresh": "\uE149", // group:Data
|
||||
"_appBarIcons\\refresh.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\rotate": "\uE14A", // group:Layout
|
||||
"_appBarIcons\\rotate.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\shuffle": "\uE14B", // group:Media
|
||||
"_appBarIcons\\shuffle.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\list": "\uE14C", // group:Editing
|
||||
"_appBarIcons\\list.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\shop": "\uE14D", // group:General
|
||||
"_appBarIcons\\shop.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\selectall": "\uE14E", // group:Data
|
||||
"_appBarIcons\\selectall.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\orientation": "\uE14F", // group:Layout
|
||||
"_appBarIcons\\orientation.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\import": "\uE150", // group:Data
|
||||
"_appBarIcons\\import.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\importall": "\uE151", // group:Data
|
||||
"_appBarIcons\\importall.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\browsephotos": "\uE155", // group:Media
|
||||
"_appBarIcons\\browsephotos.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\webcam": "\uE156", // group:System
|
||||
"_appBarIcons\\webcam.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\pictures": "\uE158", // group:Media
|
||||
"_appBarIcons\\pictures.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\savelocal": "\uE159", // group:File
|
||||
"_appBarIcons\\savelocal.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\caption": "\uE15A", // group:Media
|
||||
"_appBarIcons\\caption.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\stop": "\uE15B", // group:Media
|
||||
"_appBarIcons\\stop.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\showresults": "\uE15C", // group:Data
|
||||
"_appBarIcons\\showresults.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\volume": "\uE15D", // group:Media
|
||||
"_appBarIcons\\volume.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\repair": "\uE15E", // group:System
|
||||
"_appBarIcons\\repair.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\message": "\uE15F", // group:Communications
|
||||
"_appBarIcons\\message.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\page2": "\uE160", // group:Layout
|
||||
"_appBarIcons\\page2.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\calendarday": "\uE161", // group:Mail and calendar
|
||||
"_appBarIcons\\calendarday.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\calendarweek": "\uE162", // group:Mail and calendar
|
||||
"_appBarIcons\\calendarweek.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\calendar": "\uE163", // group:Mail and calendar
|
||||
"_appBarIcons\\calendar.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\characters": "\uE164", // group:Editing
|
||||
"_appBarIcons\\characters.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\mailreplyall": "\uE165", // group:Mail and calendar
|
||||
"_appBarIcons\\mailreplyall.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\read": "\uE166", // group:Mail and calendar
|
||||
"_appBarIcons\\read.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\link": "\uE167", // group:Communications
|
||||
"_appBarIcons\\link.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\accounts": "\uE168", // group:Communications
|
||||
"_appBarIcons\\accounts.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\showbcc": "\uE169", // group:Mail and calendar
|
||||
"_appBarIcons\\showbcc.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\hidebcc": "\uE16A", // group:Mail and calendar
|
||||
"_appBarIcons\\hidebcc.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\cut": "\uE16B", // group:Editing
|
||||
"_appBarIcons\\cut.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\attach": "\uE16C", // group:Mail and calendar
|
||||
"_appBarIcons\\attach.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\paste": "\uE16D", // group:Editing
|
||||
"_appBarIcons\\paste.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\filter": "\uE16E", // group:Data
|
||||
"_appBarIcons\\filter.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\copy": "\uE16F", // group:Editing
|
||||
"_appBarIcons\\copy.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\emoji2": "\uE170", // group:Mail and calendar
|
||||
"_appBarIcons\\emoji2.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\important": "\uE171", // group:Mail and calendar
|
||||
"_appBarIcons\\important.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\mailreply": "\uE172", // group:Mail and calendar
|
||||
"_appBarIcons\\mailreply.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\slideshow": "\uE173", // group:Media
|
||||
"_appBarIcons\\slideshow.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\sort": "\uE174", // group:Data
|
||||
"_appBarIcons\\sort.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\manage": "\uE178", // group:System
|
||||
"_appBarIcons\\manage.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\allapps": "\uE179", // group:System
|
||||
"_appBarIcons\\allapps.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\disconnectdrive": "\uE17A", // group:System
|
||||
"_appBarIcons\\disconnectdrive.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\mapdrive": "\uE17B", // group:System
|
||||
"_appBarIcons\\mapdrive.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\newwindow": "\uE17C", // group:System
|
||||
"_appBarIcons\\newwindow.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\openwith": "\uE17D", // group:System
|
||||
"_appBarIcons\\openwith.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\contactpresence": "\uE181", // group:Communications
|
||||
"_appBarIcons\\contactpresence.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\priority": "\uE182", // group:Mail and calendar
|
||||
"_appBarIcons\\priority.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\uploadskydrive": "\uE183", // group:File
|
||||
"_appBarIcons\\uploadskydrive.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\gototoday": "\uE184", // group:Mail and calendar
|
||||
"_appBarIcons\\gototoday.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\font": "\uE185", // group:Editing
|
||||
"_appBarIcons\\font.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\fontcolor": "\uE186", // group:Editing
|
||||
"_appBarIcons\\fontcolor.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\contact2": "\uE187", // group:Communications
|
||||
"_appBarIcons\\contact2.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\folder": "\uE188", // group:File
|
||||
"_appBarIcons\\folder.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\audio": "\uE189", // group:Media
|
||||
"_appBarIcons\\audio.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\placeholder": "\uE18A", // group:General
|
||||
"_appBarIcons\\placeholder.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\view": "\uE18B", // group:Layout
|
||||
"_appBarIcons\\view.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\setlockscreen": "\uE18C", // group:System
|
||||
"_appBarIcons\\setlockscreen.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\settile": "\uE18D", // group:System
|
||||
"_appBarIcons\\settile.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\cc": "\uE190", // group:Media
|
||||
"_appBarIcons\\cc.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\stopslideshow": "\uE191", // group:Media
|
||||
"_appBarIcons\\stopslideshow.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\permissions": "\uE192", // group:System
|
||||
"_appBarIcons\\permissions.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\highlight": "\uE193", // group:Editing
|
||||
"_appBarIcons\\highlight.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\disableupdates": "\uE194", // group:System
|
||||
"_appBarIcons\\disableupdates.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\unfavorite": "\uE195", // group:Media
|
||||
"_appBarIcons\\unfavorite.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\unpin": "\uE196", // group:System
|
||||
"_appBarIcons\\unpin.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\openlocal": "\uE197", // group:File
|
||||
"_appBarIcons\\openlocal.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\mute": "\uE198", // group:Media
|
||||
"_appBarIcons\\mute.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\italic": "\uE199", // group:Editing
|
||||
"_appBarIcons\\italic.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\underline": "\uE19A", // group:Editing
|
||||
"_appBarIcons\\underline.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\bold": "\uE19B", // group:Editing
|
||||
"_appBarIcons\\bold.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\movetofolder": "\uE19C", // group:File
|
||||
"_appBarIcons\\movetofolder.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\likedislike": "\uE19D", // group:Data
|
||||
"_appBarIcons\\likedislike.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\dislike": "\uE19E", // group:Data
|
||||
"_appBarIcons\\dislike.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\like": "\uE19F", // group:Data
|
||||
"_appBarIcons\\like.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\alignright": "\uE1A0", // group:Editing
|
||||
"_appBarIcons\\alignright.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\aligncenter": "\uE1A1", // group:Editing
|
||||
"_appBarIcons\\aligncenter.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\alignleft": "\uE1A2", // group:Editing
|
||||
"_appBarIcons\\alignleft.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\zoom": "\uE1A3", // group:Layout
|
||||
"_appBarIcons\\zoom.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\zoomout": "\uE1A4", // group:Layout
|
||||
"_appBarIcons\\zoomout.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\openfile": "\uE1A5", // group:File
|
||||
"_appBarIcons\\openfile.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\otheruser": "\uE1A6", // group:System
|
||||
"_appBarIcons\\otheruser.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\admin": "\uE1A7", // group:System
|
||||
"_appBarIcons\\admin.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\street": "\uE1C3", // group:General
|
||||
"_appBarIcons\\street.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\map": "\uE1C4", // group:General
|
||||
"_appBarIcons\\map.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\clearselection": "\uE1C5", // group:Data
|
||||
"_appBarIcons\\clearselection.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\fontdecrease": "\uE1C6", // group:Editing
|
||||
"_appBarIcons\\fontdecrease.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\fontincrease": "\uE1C7", // group:Editing
|
||||
"_appBarIcons\\fontincrease.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\fontsize": "\uE1C8", // group:Editing
|
||||
"_appBarIcons\\fontsize.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\cellphone": "\uE1C9", // group:Communications
|
||||
"_appBarIcons\\cellphone.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\reshare": "\uE1CA", // group:Communications
|
||||
"_appBarIcons\\reshare.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\tag": "\uE1CB", // group:Data
|
||||
"_appBarIcons\\tag.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\repeatone": "\uE1CC", // group:Media
|
||||
"_appBarIcons\\repeatone.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\repeatall": "\uE1CD", // group:Media
|
||||
"_appBarIcons\\repeatall.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\outlinestar": "\uE1CE", // group:Data
|
||||
"_appBarIcons\\outlinestar.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\solidstar": "\uE1CF", // group:Data
|
||||
"_appBarIcons\\solidstar.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\calculator": "\uE1D0", // group:General
|
||||
"_appBarIcons\\calculator.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\directions": "\uE1D1", // group:General
|
||||
"_appBarIcons\\directions.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\target": "\uE1D2", // group:General
|
||||
"_appBarIcons\\target.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\library": "\uE1D3", // group:Media
|
||||
"_appBarIcons\\library.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\phonebook": "\uE1D4", // group:Communications
|
||||
"_appBarIcons\\phonebook.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\memo": "\uE1D5", // group:Communications
|
||||
"_appBarIcons\\memo.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\microphone": "\uE1D6", // group:System
|
||||
"_appBarIcons\\microphone.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\postupdate": "\uE1D7", // group:Communications
|
||||
"_appBarIcons\\postupdate.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\backtowindow": "\uE1D8", // group:Layout
|
||||
"_appBarIcons\\backtowindow.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\fullscreen": "\uE1D9", // group:Layout
|
||||
"_appBarIcons\\fullscreen.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\newfolder": "\uE1DA", // group:File
|
||||
"_appBarIcons\\newfolder.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\calendarreply": "\uE1DB", // group:Mail and calendar
|
||||
"_appBarIcons\\calendarreply.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\unsyncfolder": "\uE1DD", // group:File
|
||||
"_appBarIcons\\unsyncfolder.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\reporthacked": "\uE1DE", // group:Communications
|
||||
"_appBarIcons\\reporthacked.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\syncfolder": "\uE1DF", // group:File
|
||||
"_appBarIcons\\syncfolder.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\blockcontact": "\uE1E0", // group:Communications
|
||||
"_appBarIcons\\blockcontact.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\switchapps": "\uE1E1", // group:System
|
||||
"_appBarIcons\\switchapps.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\addfriend": "\uE1E2", // group:Communications
|
||||
"_appBarIcons\\addfriend.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\touchpointer": "\uE1E3", // group:System
|
||||
"_appBarIcons\\touchpointer.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\gotostart": "\uE1E4", // group:System
|
||||
"_appBarIcons\\gotostart.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\zerobars": "\uE1E5", // group:System
|
||||
"_appBarIcons\\zerobars.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\onebar": "\uE1E6", // group:System
|
||||
"_appBarIcons\\onebar.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\twobars": "\uE1E7", // group:System
|
||||
"_appBarIcons\\twobars.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\threebars": "\uE1E8", // group:System
|
||||
"_appBarIcons\\threebars.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\fourbars": "\uE1E9", // group:System
|
||||
"_appBarIcons\\fourbars.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\scan": "\uE294", // group:General
|
||||
"_appBarIcons\\scan.comment": "{Locked:qps-ploc,qps-plocm}",
|
||||
"appBarIcons\\preview": "\uE295", // group:General
|
||||
"_appBarIcons\\preview.comment": "{Locked:qps-ploc,qps-plocm}"
|
||||
}
|
||||
|
||||
);
|
||||
}(this));
|
||||