Update Settings Shell.

This commit is contained in:
Bruce
2025-12-01 22:51:46 +08:00
parent 5796fb40e1
commit 98c0f91b8c
28 changed files with 38814 additions and 382 deletions

Binary file not shown.

View File

@@ -2,7 +2,15 @@
#include <Windows.h> #include <Windows.h>
#include "mpstr.h" #include "mpstr.h"
#include "nstring.h" #include "nstring.h"
#include "filepath.h"
#include <combaseapi.h> #include <combaseapi.h>
#include <rapidjson\document.h>
#include <rapidjson\writer.h>
#include <rapidjson\stringbuffer.h>
#include <codecvt>
#include <locale>
#include "mpstr.h"
#include "strcode.h"
using namespace System; using namespace System;
using namespace System::Runtime::InteropServices; using namespace System::Runtime::InteropServices;
@@ -86,3 +94,297 @@ public ref class _I_String
return Format (pih, newargs); return Format (pih, newargs);
} }
}; };
String ^StringArrayToJson (array <String ^> ^strs)
{
using namespace rapidjson;
Document doc;
doc.SetArray ();
Document::AllocatorType &allocator = doc.GetAllocator ();
for each (String ^s in strs)
{
std::wstring ws = MPStringToStdW (s); // String^ → std::wstring
std::string utf8 = WStringToString (ws, CP_UTF8); // 简易宽转 UTF-8如需更严谨可用 WideCharToMultiByte
doc.PushBack (Value (utf8.c_str (), allocator), allocator);
}
StringBuffer buffer;
Writer <StringBuffer> writer (buffer);
doc.Accept (writer);
std::string json = buffer.GetString ();
std::wstring wjson = StringToWString (json, CP_UTF8);
return CStringToMPString (wjson);
}
std::wstring StringArrayToJson (const std::vector<std::wstring>& arr)
{
using namespace rapidjson;
Document doc;
doc.SetArray ();
auto &allocator = doc.GetAllocator ();
for (const auto &ws : arr)
{
std::string utf8 = WStringToUtf8 (ws);
doc.PushBack (Value (utf8.c_str (), allocator), allocator);
}
StringBuffer buffer;
Writer <StringBuffer> writer (buffer);
doc.Accept (writer);
return Utf8ToWString (buffer.GetString ());
}
[ComVisible (true)]
public ref class _I_Path
{
public:
property String ^Current
{
String ^get () { return CStringToMPString (GetCurrentDirectoryW ()); }
void set (String ^dir) { SetCurrentDirectoryW (MPStringToStdW (dir).c_str ()); }
}
property String ^Program { String ^get () { return CStringToMPString (GetCurrentProgramPathW ()); } }
property String ^Root { String ^get () { return CStringToMPString (GetFileDirectoryW (GetCurrentProgramPathW ())); }}
String ^Combine (String ^l, String ^r) { return CStringToMPString (CombinePath (MPStringToStdW (l), MPStringToStdW (r))); }
String ^GetName (String ^path)
{
std::wstring cpath = MPStringToStdW (path);
LPWSTR lp = PathFindFileNameW (cpath.c_str ());
return lp ? CStringToMPString (lp) : String::Empty;
}
String ^GetDirectory (String ^path) { return CStringToMPString (GetFileDirectoryW (MPStringToStdW (path))); }
String ^GetDir (String ^path) { return GetDirectory (path); }
bool Exist (String ^path) { return IsPathExists (MPStringToStdW (path)); }
bool FileExist (String ^filepath) { return IsFileExists (MPStringToStdW (filepath)); }
bool DirectoryExist (String ^dirpath) { return IsDirectoryExists (MPStringToStdW (dirpath)); }
bool DirExist (String ^dirpath) { return DirectoryExist (dirpath); }
String ^GetEnvironmentString (String ^str) { return CStringToMPString (ProcessEnvVars (MPStringToStdW (str))); }
bool ValidName (String ^filename) { return IsValidWindowsName (MPStringToStdW (filename)); }
// 过滤器用"\"分隔每个类型
String ^EnumFilesToJson (String ^dir, String ^filter, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
::EnumFiles (MPStringToStdW (dir), MPStringToStdW (filter), res, withpath, sort, includesub);
return CStringToMPString (StringArrayToJson (res));
}
String ^EnumDirsToJson (String ^dir, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
EnumDirectory (MPStringToStdW (dir), res, withpath, sort, includesub);
return CStringToMPString (StringArrayToJson (res));
}
String ^EnumSubDirsToJson (String ^dir, bool withpath)
{
std::vector <std::wstring> res = EnumSubdirectories (MPStringToStdW (dir), withpath);
return CStringToMPString (StringArrayToJson (res));
}
array <String ^> ^EnumFiles (String ^dir, String ^filter, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
::EnumFiles (MPStringToStdW (dir), MPStringToStdW (filter), res, withpath, sort, includesub);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
array <String ^> ^EnumDirs (String ^dir, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
EnumDirectory (MPStringToStdW (dir), res, withpath, sort, includesub);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
array <String ^> ^EnumSubDirs (String ^dir, bool withpath)
{
std::vector <std::wstring> res = EnumSubdirectories (MPStringToStdW (dir), withpath);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
String ^CommonPrefix (String ^path1, String ^path2) { return CStringToMPString (PathCommonPrefix (MPStringToStdW (path1), MPStringToStdW (path2))); }
String ^EnsureDirSlash (String ^dir) { return CStringToMPString (EnsureTrailingSlash (MPStringToStdW (dir))); }
String ^Normalize (String ^path) { return CStringToMPString (NormalizePath (MPStringToStdW (path))); }
String ^FullPathName (String ^path) { return CStringToMPString (GetFullPathName (MPStringToStdW (path))); }
String ^FullPath (String ^path) { return FullPathName (path); }
String ^Expand (String ^path) { return CStringToMPString (ProcessEnvVars (MPStringToStdW (path))); }
bool PEquals (String ^l, String ^r) { return PathEquals (MPStringToStdW (l), MPStringToStdW (r)); }
};
[ComVisible (true)]
public ref class _I_Entry
{
protected:
String ^path;
public:
_I_Entry (String ^path): path (path) {}
_I_Entry (): path (String::Empty) {}
property String ^Path { String ^get () { return path; } void set (String ^file) { path = file; } }
property String ^Name
{
String ^get ()
{
std::wstring file = MPStringToStdW (path);
LPWSTR lpstr = PathFindFileNameW (file.c_str ());
return lpstr ? CStringToMPString (lpstr) : String::Empty;
}
}
property String ^Directory { String ^get () { return CStringToMPString (GetFileDirectoryW (MPStringToStdW (path))); }}
property String ^Root { String ^get () { return Directory; }}
property bool Exist { virtual bool get () { return IsPathExists (MPStringToStdW (path)); }}
property String ^Uri
{
String ^get ()
{
using namespace System;
try
{
auto uri = gcnew System::Uri (System::IO::Path::GetFullPath (path));
auto uriText = uri->AbsoluteUri;
return uriText;
}
catch (...) { return String::Empty; }
}
}
property String ^FullPath { String ^get () { return System::IO::Path::GetFullPath (path); }}
};
[ComVisible (true)]
public ref class _I_File: public _I_Entry
{
protected:
System::Text::Encoding ^lastEncoding;
public:
_I_File (String ^filepath): _I_Entry (filepath) {}
_I_File (): _I_Entry (String::Empty) {}
String ^Get ()
{
using namespace System::IO;
if (String::IsNullOrEmpty (path)) return String::Empty;
FileStream ^fs = nullptr;
StreamReader ^sr = nullptr;
try
{
fs = gcnew FileStream (
path,
FileMode::OpenOrCreate,
FileAccess::ReadWrite,
FileShare::ReadWrite
);
sr = gcnew StreamReader (fs, Encoding::UTF8, true);
String ^text = sr->ReadToEnd ();
auto lastEncoding = sr->CurrentEncoding;
return text;
}
finally
{
if (sr) delete sr;
if (fs) delete fs;
}
}
void Set (String ^content)
{
using namespace System::IO;
if (String::IsNullOrEmpty (path)) return;
Encoding ^enc = lastEncoding ? lastEncoding : Encoding::UTF8;
FileStream ^fs = nullptr;
StreamWriter ^sw = nullptr;
try
{
fs = gcnew FileStream (
path,
FileMode::Create,
FileAccess::ReadWrite,
FileShare::ReadWrite
);
sw = gcnew StreamWriter (fs, enc);
sw->Write (content);
sw->Flush ();
}
finally
{
if (sw) delete sw;
if (fs) delete fs;
}
}
property String ^Content
{
String ^get () { return Get (); }
void set (String ^value) { Set (value); }
}
property bool Exist { bool get () override { return IsFileExists (MPStringToStdW (path)); }}
property String ^FilePath { String ^get () { return this->Path; } void set (String ^value) { this->Path = value; }}
};
[ComVisible (true)]
public ref class _I_Directory: public _I_Entry
{
public:
_I_Directory (String ^dirpath): _I_Entry (dirpath) {}
_I_Directory (_I_Entry ^file): _I_Entry (file->Directory) {}
_I_Directory (): _I_Entry (String::Empty) {}
property String ^DirectoryPath { String ^get () { return this->Path; } void set (String ^value) { this->Path = value; } }
property String ^DirPath { String ^get () { return this->DirectoryPath; } void set (String ^value) { this->DirectoryPath = value; } }
property bool Exist { bool get () override { return IsDirectoryExists (MPStringToStdW (path)); }}
String ^EnumFilesToJson (String ^filter, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
::EnumFiles (MPStringToStdW (DirPath), MPStringToStdW (filter), res, withpath, sort, includesub);
return CStringToMPString (StringArrayToJson (res));
}
String ^EnumDirsToJson (bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
EnumDirectory (MPStringToStdW (DirPath), res, withpath, sort, includesub);
return CStringToMPString (StringArrayToJson (res));
}
String ^EnumSubDirsToJson (bool withpath)
{
std::vector <std::wstring> res = EnumSubdirectories (MPStringToStdW (DirPath), withpath);
return CStringToMPString (StringArrayToJson (res));
}
array <String ^> ^EnumFiles (String ^filter, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
::EnumFiles (MPStringToStdW (DirPath), MPStringToStdW (filter), res, withpath, sort, includesub);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
array <String ^> ^EnumDirs (bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
EnumDirectory (MPStringToStdW (DirPath), res, withpath, sort, includesub);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
array <String ^> ^EnumSubDirs (bool withpath)
{
std::vector <std::wstring> res = EnumSubdirectories (MPStringToStdW (DirPath), withpath);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
};
[ComVisible (true)]
public ref class _I_Storage
{
protected:
_I_Path ^path = gcnew _I_Path ();
public:
property _I_Path ^Path { _I_Path ^get () { return path; }}
_I_File ^GetFile (String ^path) { return gcnew _I_File (path); }
_I_Directory ^GetDirectory (String ^path) { return gcnew _I_Directory (path); }
_I_Directory ^GetDir (String ^path) { return GetDirectory (path); }
};

View File

@@ -869,306 +869,3 @@ bool PathEquals (const std::wstring &path1, const std::wstring &path2)
PathCanonicalizeW (buf2.data (), path2.c_str ()); PathCanonicalizeW (buf2.data (), path2.c_str ());
return IsNormalizeStringEquals (buf1.data (), buf2.data ()); return IsNormalizeStringEquals (buf1.data (), buf2.data ());
} }
#ifdef __cplusplus_cli
#include <rapidjson\document.h>
#include <rapidjson\writer.h>
#include <rapidjson\stringbuffer.h>
#include <codecvt>
#include <locale>
#include "mpstr.h"
#include "strcode.h"
using namespace System;
using namespace System::Runtime::InteropServices;
String ^StringArrayToJson (array <String ^> ^strs)
{
using namespace rapidjson;
Document doc;
doc.SetArray ();
Document::AllocatorType &allocator = doc.GetAllocator ();
for each (String ^s in strs)
{
std::wstring ws = MPStringToStdW (s); // String^ → std::wstring
std::string utf8 = WStringToString (ws, CP_UTF8); // 简易宽转 UTF-8如需更严谨可用 WideCharToMultiByte
doc.PushBack (Value (utf8.c_str (), allocator), allocator);
}
StringBuffer buffer;
Writer <StringBuffer> writer (buffer);
doc.Accept (writer);
std::string json = buffer.GetString ();
std::wstring wjson = StringToWString (json, CP_UTF8);
return CStringToMPString (wjson);
}
std::wstring StringArrayToJson (const std::vector<std::wstring>& arr)
{
using namespace rapidjson;
Document doc;
doc.SetArray ();
auto &allocator = doc.GetAllocator ();
for (const auto &ws : arr)
{
std::string utf8 = WStringToUtf8 (ws);
doc.PushBack (Value (utf8.c_str (), allocator), allocator);
}
StringBuffer buffer;
Writer <StringBuffer> writer (buffer);
doc.Accept (writer);
return Utf8ToWString (buffer.GetString ());
}
[ComVisible (true)]
public ref class _I_Path
{
public:
property String ^Current
{
String ^get () { return CStringToMPString (GetCurrentDirectoryW ()); }
void set (String ^dir) { SetCurrentDirectoryW (MPStringToStdW (dir).c_str ()); }
}
property String ^Program { String ^get () { return CStringToMPString (GetCurrentProgramPathW ()); } }
property String ^Root { String ^get () { return CStringToMPString (GetFileDirectoryW (GetCurrentProgramPathW ())); }}
String ^Combine (String ^l, String ^r) { return CStringToMPString (CombinePath (MPStringToStdW (l), MPStringToStdW (r))); }
String ^GetName (String ^path)
{
std::wstring cpath = MPStringToStdW (path);
LPWSTR lp = PathFindFileNameW (cpath.c_str ());
return lp ? CStringToMPString (lp) : String::Empty;
}
String ^GetDirectory (String ^path) { return CStringToMPString (GetFileDirectoryW (MPStringToStdW (path))); }
String ^GetDir (String ^path) { return GetDirectory (path); }
bool Exist (String ^path) { return IsPathExists (MPStringToStdW (path)); }
bool FileExist (String ^filepath) { return IsFileExists (MPStringToStdW (filepath)); }
bool DirectoryExist (String ^dirpath) { return IsDirectoryExists (MPStringToStdW (dirpath)); }
bool DirExist (String ^dirpath) { return DirectoryExist (dirpath); }
String ^GetEnvironmentString (String ^str) { return CStringToMPString (ProcessEnvVars (MPStringToStdW (str))); }
bool ValidName (String ^filename) { return IsValidWindowsName (MPStringToStdW (filename)); }
// 过滤器用"\"分隔每个类型
String ^EnumFilesToJson (String ^dir, String ^filter, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
::EnumFiles (MPStringToStdW (dir), MPStringToStdW (filter), res, withpath, sort, includesub);
return CStringToMPString (StringArrayToJson (res));
}
String ^EnumDirsToJson (String ^dir, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
EnumDirectory (MPStringToStdW (dir), res, withpath, sort, includesub);
return CStringToMPString (StringArrayToJson (res));
}
String ^EnumSubDirsToJson (String ^dir, bool withpath)
{
std::vector <std::wstring> res = EnumSubdirectories (MPStringToStdW (dir), withpath);
return CStringToMPString (StringArrayToJson (res));
}
array <String ^> ^EnumFiles (String ^dir, String ^filter, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
::EnumFiles (MPStringToStdW (dir), MPStringToStdW (filter), res, withpath, sort, includesub);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
array <String ^> ^EnumDirs (String ^dir, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
EnumDirectory (MPStringToStdW (dir), res, withpath, sort, includesub);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
array <String ^> ^EnumSubDirs (String ^dir, bool withpath)
{
std::vector <std::wstring> res = EnumSubdirectories (MPStringToStdW (dir), withpath);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
String ^CommonPrefix (String ^path1, String ^path2) { return CStringToMPString (PathCommonPrefix (MPStringToStdW (path1), MPStringToStdW (path2))); }
String ^EnsureDirSlash (String ^dir) { return CStringToMPString (EnsureTrailingSlash (MPStringToStdW (dir))); }
String ^Normalize (String ^path) { return CStringToMPString (NormalizePath (MPStringToStdW (path))); }
String ^FullPathName (String ^path) { return CStringToMPString (GetFullPathName (MPStringToStdW (path))); }
bool PEquals (String ^l, String ^r) { return PathEquals (MPStringToStdW (l), MPStringToStdW (r)); }
};
[ComVisible (true)]
public ref class _I_Entry
{
protected:
String ^path;
public:
_I_Entry (String ^path): path (path) {}
_I_Entry (): path (String::Empty) {}
property String ^Path { String ^get () { return path; } void set (String ^file) { path = file; } }
property String ^Name
{
String ^get ()
{
std::wstring file = MPStringToStdW (path);
LPWSTR lpstr = PathFindFileNameW (file.c_str ());
return lpstr ? CStringToMPString (lpstr) : String::Empty;
}
}
property String ^Directory { String ^get () { return CStringToMPString (GetFileDirectoryW (MPStringToStdW (path))); }}
property String ^Root { String ^get () { return Directory; }}
property bool Exist { virtual bool get () { return IsPathExists (MPStringToStdW (path)); }}
property String ^Uri
{
String ^get ()
{
using namespace System;
try
{
auto uri = gcnew System::Uri (System::IO::Path::GetFullPath (path));
auto uriText = uri->AbsoluteUri;
return uriText;
}
catch (...) { return String::Empty; }
}
}
property String ^FullPath { String ^get () { return System::IO::Path::GetFullPath (path); }}
};
[ComVisible (true)]
public ref class _I_File: public _I_Entry
{
protected:
System::Text::Encoding ^lastEncoding;
public:
_I_File (String ^filepath): _I_Entry (filepath) {}
_I_File (): _I_Entry (String::Empty) {}
String ^Get ()
{
using namespace System::IO;
if (String::IsNullOrEmpty (path)) return String::Empty;
FileStream ^fs = nullptr;
StreamReader ^sr = nullptr;
try
{
fs = gcnew FileStream (
path,
FileMode::OpenOrCreate,
FileAccess::ReadWrite,
FileShare::ReadWrite
);
sr = gcnew StreamReader (fs, Encoding::UTF8, true);
String ^text = sr->ReadToEnd ();
auto lastEncoding = sr->CurrentEncoding;
return text;
}
finally
{
if (sr) delete sr;
if (fs) delete fs;
}
}
void Set (String ^content)
{
using namespace System::IO;
if (String::IsNullOrEmpty (path)) return;
Encoding ^enc = lastEncoding ? lastEncoding : Encoding::UTF8;
FileStream ^fs = nullptr;
StreamWriter ^sw = nullptr;
try
{
fs = gcnew FileStream (
path,
FileMode::Create,
FileAccess::ReadWrite,
FileShare::ReadWrite
);
sw = gcnew StreamWriter (fs, enc);
sw->Write (content);
sw->Flush ();
}
finally
{
if (sw) delete sw;
if (fs) delete fs;
}
}
property String ^Content
{
String ^get () { return Get (); }
void set (String ^value) { Set (value); }
}
property bool Exist { bool get () override { return IsFileExists (MPStringToStdW (path)); }}
property String ^FilePath { String ^get () { return this->Path; } void set (String ^value) { this->Path = value; }}
};
[ComVisible (true)]
public ref class _I_Directory: public _I_Entry
{
public:
_I_Directory (String ^dirpath): _I_Entry (dirpath) {}
_I_Directory (_I_Entry ^file): _I_Entry (file->Directory) {}
_I_Directory (): _I_Entry (String::Empty) {}
property String ^DirectoryPath { String ^get () { return this->Path; } void set (String ^value) { this->Path = value; } }
property String ^DirPath { String ^get () { return this->DirectoryPath; } void set (String ^value) { this->DirectoryPath = value; } }
property bool Exist { bool get () override { return IsDirectoryExists (MPStringToStdW (path)); }}
String ^EnumFilesToJson (String ^filter, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
::EnumFiles (MPStringToStdW (DirPath), MPStringToStdW (filter), res, withpath, sort, includesub);
return CStringToMPString (StringArrayToJson (res));
}
String ^EnumDirsToJson (bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
EnumDirectory (MPStringToStdW (DirPath), res, withpath, sort, includesub);
return CStringToMPString (StringArrayToJson (res));
}
String ^EnumSubDirsToJson (bool withpath)
{
std::vector <std::wstring> res = EnumSubdirectories (MPStringToStdW (DirPath), withpath);
return CStringToMPString (StringArrayToJson (res));
}
array <String ^> ^EnumFiles (String ^filter, bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
::EnumFiles (MPStringToStdW (DirPath), MPStringToStdW (filter), res, withpath, sort, includesub);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
array <String ^> ^EnumDirs (bool withpath, bool sort, bool includesub)
{
std::vector <std::wstring> res;
EnumDirectory (MPStringToStdW (DirPath), res, withpath, sort, includesub);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
array <String ^> ^EnumSubDirs (bool withpath)
{
std::vector <std::wstring> res = EnumSubdirectories (MPStringToStdW (DirPath), withpath);
auto retarr = gcnew array <String ^> (res.size ());
for (size_t i = 0; i < res.size (); i ++)
{
retarr [i] = CStringToMPString (res [i]);
}
return retarr;
}
};
[ComVisible (true)]
public ref class _I_Storage
{
protected:
_I_Path ^path = gcnew _I_Path ();
public:
property _I_Path ^Path { _I_Path ^get () { return path; }}
_I_File ^GetFile (String ^path) { return gcnew _I_File (path); }
_I_Directory ^GetDirectory (String ^path) { return gcnew _I_Directory (path); }
_I_Directory ^GetDir (String ^path) { return GetDirectory (path); }
};
#endif

View File

@@ -22,6 +22,7 @@
#include "notice.h" #include "notice.h"
#include "certmgr.h" #include "certmgr.h"
#include "bridge.h" #include "bridge.h"
#include "filepath.h"
using namespace System; using namespace System;
using namespace System::Runtime::InteropServices; using namespace System::Runtime::InteropServices;
@@ -170,11 +171,13 @@ public ref class _I_Bridge_Base
protected: protected:
_I_String ^str = gcnew _I_String (); _I_String ^str = gcnew _I_String ();
_I_InitConfig ^initconfig = gcnew _I_InitConfig (); _I_InitConfig ^initconfig = gcnew _I_InitConfig ();
_I_Storage ^storage; _I_Storage ^storage = gcnew _I_Storage ();
_I_Package ^pkg = gcnew _I_Package ();
public: public:
property _I_String ^String { _I_String ^get () { return str; }} property _I_String ^String { _I_String ^get () { return str; }}
property _I_InitConfig ^Config { _I_InitConfig ^get () { return initconfig; }} property _I_InitConfig ^Config { _I_InitConfig ^get () { return initconfig; }}
property _I_Storage ^Storage { _I_Storage ^get () { return storage; }} property _I_Storage ^Storage { _I_Storage ^get () { return storage; }}
property _I_Package ^Package { _I_Package ^get () { return pkg; }}
}; };
[ComVisible (true)] [ComVisible (true)]
public interface class IScriptBridge public interface class IScriptBridge

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4857
others/buildsetup.suf Normal file

File diff suppressed because it is too large Load Diff

BIN
others/uninstall_icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Binary file not shown.

239
settings/download.h Normal file
View File

@@ -0,0 +1,239 @@
#pragma once
#include <Windows.h>
#include <WinInet.h>
#include <string>
#include "strcode.h"
#include "mpstr.h"
#include <chrono>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
// Generated by ChatGTP
using namespace System;
using namespace System::Threading;
using namespace System::Reflection;
#include <Windows.h>
#include <string>
std::wstring GetLastErrorString ()
{
DWORD errCode = GetLastError ();
if (errCode == 0)
return L"No error";
wchar_t* msgBuffer = nullptr;
// FORMAT_MESSAGE_ALLOCATE_BUFFER: 让系统分配缓冲区
// FORMAT_MESSAGE_FROM_SYSTEM: 从系统获取错误信息
// FORMAT_MESSAGE_IGNORE_INSERTS: 忽略 %1 %2
DWORD size = FormatMessageW (
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
errCode,
0, // 默认语言
(LPWSTR)&msgBuffer,
0,
nullptr
);
std::wstring msg;
if (size && msgBuffer)
{
msg = msgBuffer;
LocalFree (msgBuffer); // 释放缓冲区
}
else
{
msg = L"Unknown error code: " + std::to_wstring (errCode);
}
return msg;
}
public ref class DownloadHelper
{
public:
static void DownloadFile (
String^ httpUrl,
String^ savePath,
Object^ onProgress,
Object^ onComplete,
Object^ onError)
{
DownloadHelper^ obj = gcnew DownloadHelper ();
obj->m_url = httpUrl;
obj->m_savePath = savePath;
obj->cbProgress = onProgress;
obj->cbComplete = onComplete;
obj->cbError = onError;
Thread^ th = gcnew Thread (gcnew ThreadStart (obj, &DownloadHelper::Worker));
th->IsBackground = true;
th->Start ();
}
private:
void Worker ()
{
std::wstring url = MPStringToStdW (m_url);
std::wstring outPath = MPStringToStdW (m_savePath);
HINTERNET hInternet = InternetOpenW (L"MyDownloader",
INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (!hInternet)
{
ReportError (outPath, L"InternetOpenW Failed: " + GetLastErrorString ());
return;
}
HINTERNET hFile = InternetOpenUrlW (
hInternet,
url.c_str (),
NULL,
0,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE,
0
);
if (!hFile)
{
InternetCloseHandle (hInternet);
ReportError (outPath, L"InternetOpenUrlW Failed: " + GetLastErrorString ());
return;
}
DWORD fileSize = 0;
DWORD len = sizeof (fileSize);
HttpQueryInfoW (hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
&fileSize, &len, NULL);
HANDLE hOut = CreateFileW (outPath.c_str (), GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hOut == INVALID_HANDLE_VALUE)
{
InternetCloseHandle (hFile);
InternetCloseHandle (hInternet);
ReportError (outPath, L"Cannot create output file: " + GetLastErrorString ());
return;
}
BYTE buffer [8192];
DWORD bytesRead = 0;
DWORD bytesWritten = 0;
long long received = 0;
auto t0 = std::chrono::high_resolution_clock::now ();
while (InternetReadFile (hFile, buffer, sizeof (buffer), &bytesRead) && bytesRead > 0)
{
WriteFile (hOut, buffer, bytesRead, &bytesWritten, NULL);
received += bytesRead;
// 计算速度
auto t1 = std::chrono::high_resolution_clock::now ();
double sec = std::chrono::duration<double> (t1 - t0).count ();
long long speed = (long long)(received / (sec > 0 ? sec : 1));
ReportProgress (received, fileSize, speed);
}
CloseHandle (hOut);
InternetCloseHandle (hFile);
InternetCloseHandle (hInternet);
ReportComplete (outPath, received);
}
// ---------------- 回调组装 JSON ----------------
void ReportProgress (long long received, long long total, long long speed)
{
if (!cbProgress) return;
rapidjson::StringBuffer buf;
rapidjson::Writer<rapidjson::StringBuffer> w (buf);
w.StartObject ();
w.Key ("received"); w.Uint64 (received);
w.Key ("total"); w.Uint64 (total);
w.Key ("speed"); w.Uint64 (speed);
w.Key ("progress"); w.Double (received / (double)total * 100);
w.EndObject ();
CallJS (cbProgress, CStringToMPString (StringToWString (buf.GetString (), CP_UTF8)));
}
void ReportComplete (const std::wstring& file, long long size)
{
if (!cbComplete) return;
rapidjson::StringBuffer buf;
rapidjson::Writer<rapidjson::StringBuffer> w (buf);
w.StartObject ();
w.Key ("file"); w.String (WStringToString (file, CP_UTF8).c_str ());
w.Key ("status"); w.String ("ok");
w.Key ("size"); w.Uint64 (size);
w.EndObject ();
CallJS (cbComplete, CStringToMPString (StringToWString (buf.GetString (), CP_UTF8)));
}
void ReportError (const std::wstring& file, const std::wstring &reason)
{
if (!cbError) return;
rapidjson::StringBuffer buf;
rapidjson::Writer<rapidjson::StringBuffer> w (buf);
w.StartObject ();
w.Key ("file"); w.String (WStringToString (file, CP_UTF8).c_str ());
w.Key ("status"); w.String ("failed");
w.Key ("reason"); w.String (WStringToString (reason, CP_UTF8).c_str ());
w.EndObject ();
CallJS (cbError, CStringToMPString (StringToWString (buf.GetString (), CP_UTF8)));
}
// ---------------- 调用 JS 回调 ----------------
void CallJS (Object^ jsFunc, String^ arg)
{
if (!jsFunc) return;
try
{
jsFunc->GetType ()->InvokeMember (
"call",
BindingFlags::InvokeMethod,
nullptr,
jsFunc,
gcnew array<Object^>{ 1, arg }
);
}
catch (...)
{
// 失败可忽略
}
}
private:
String^ m_url;
String^ m_savePath;
Object^ cbProgress;
Object^ cbComplete;
Object^ cbError;
};
using namespace System::Runtime::InteropServices;
[ComVisible (true)]
public ref class _I_Download
{
public:
void WorkAsync (String ^httpurl, String ^saveFilePath, Object ^onComplete, Object ^onError, Object ^onProgress)
{
auto download = gcnew DownloadHelper ();
download->DownloadFile (httpurl, saveFilePath, onProgress, onComplete, onError);
}
};

View File

@@ -12,6 +12,7 @@
#include <rapidjson\document.h> #include <rapidjson\document.h>
#include <rapidjson\writer.h> #include <rapidjson\writer.h>
#include <rapidjson\stringbuffer.h> #include <rapidjson\stringbuffer.h>
#include "download.h"
#include "module.h" #include "module.h"
#include "themeinfo.h" #include "themeinfo.h"
#include "mpstr.h" #include "mpstr.h"
@@ -234,7 +235,7 @@ public ref class _I_Bridge_Base
protected: protected:
_I_String ^str = gcnew _I_String (); _I_String ^str = gcnew _I_String ();
_I_InitConfig ^initconfig = gcnew _I_InitConfig (); _I_InitConfig ^initconfig = gcnew _I_InitConfig ();
_I_Storage ^storage; _I_Storage ^storage = gcnew _I_Storage ();
public: public:
property _I_String ^String { _I_String ^get () { return str; }} property _I_String ^String { _I_String ^get () { return str; }}
property _I_InitConfig ^Config { _I_InitConfig ^get () { return initconfig; }} property _I_InitConfig ^Config { _I_InitConfig ^get () { return initconfig; }}
@@ -682,6 +683,7 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form, public IScrip
_I_IEFrame ^ieframe; _I_IEFrame ^ieframe;
_I_System3 ^sys; _I_System3 ^sys;
_I_VisualElements2 ^ve; _I_VisualElements2 ^ve;
_I_Download ^download;
public: public:
IBridge (MainHtmlWnd ^wnd): wndinst (wnd), _I_Bridge_Base2 (wnd) IBridge (MainHtmlWnd ^wnd): wndinst (wnd), _I_Bridge_Base2 (wnd)
{ {
@@ -689,10 +691,12 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form, public IScrip
sys = gcnew _I_System3 (wnd); sys = gcnew _I_System3 (wnd);
storage = gcnew _I_Storage (); storage = gcnew _I_Storage ();
ve = gcnew _I_VisualElements2 (); ve = gcnew _I_VisualElements2 ();
download = gcnew _I_Download ();
} }
property _I_IEFrame ^IEFrame { _I_IEFrame ^get () { return ieframe; }} property _I_IEFrame ^IEFrame { _I_IEFrame ^get () { return ieframe; }}
property _I_System3 ^System { _I_System3 ^get () { return sys; }} property _I_System3 ^System { _I_System3 ^get () { return sys; }}
property _I_VisualElements2 ^VisualElements { _I_VisualElements2 ^get () { return ve; } } property _I_VisualElements2 ^VisualElements { _I_VisualElements2 ^get () { return ve; } }
property _I_Download ^Download { _I_Download ^get () { return download; }}
}; };
protected: protected:
property WebBrowser ^WebUI { WebBrowser ^get () { return this->webui; } } property WebBrowser ^WebUI { WebBrowser ^get () { return this->webui; } }

View File

@@ -97,7 +97,7 @@
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>shlwapi.lib;version.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>shlwapi.lib;version.lib;dwmapi.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -130,7 +130,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>shlwapi.lib;version.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>shlwapi.lib;version.lib;dwmapi.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -184,6 +184,7 @@
<ClInclude Include="..\appinstaller\typestrans.h" /> <ClInclude Include="..\appinstaller\typestrans.h" />
<ClInclude Include="..\appinstaller\vemani.h" /> <ClInclude Include="..\appinstaller\vemani.h" />
<ClInclude Include="..\appinstaller\version.h" /> <ClInclude Include="..\appinstaller\version.h" />
<ClInclude Include="download.h" />
<ClInclude Include="resmap.h" /> <ClInclude Include="resmap.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
</ItemGroup> </ItemGroup>

View File

@@ -77,6 +77,9 @@
<ClInclude Include="resmap.h"> <ClInclude Include="resmap.h">
<Filter>头文件</Filter> <Filter>头文件</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="download.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="settings.rc"> <ResourceCompile Include="settings.rc">

View File

@@ -218,6 +218,11 @@
containerId = container.id; containerId = container.id;
} }
} else document.getElementById(containerId); } else document.getElementById(containerId);
if (shouldAnimate == true) {
container.setAttribute("data-start-loading", true);
} else {
container.removeAttribute("data-start-loading");
}
var textNode = container.firstChild; var textNode = container.firstChild;
if (!textNode || textNode.nodeType !== 3) { if (!textNode || textNode.nodeType !== 3) {
textNode = document.createTextNode(""); textNode = document.createTextNode("");

View File

@@ -473,63 +473,6 @@
this.HWB = new HWB(this); this.HWB = new HWB(this);
this.stringify = function() { return this.hex; }; this.stringify = function() { return this.hex; };
} }
/**
* 解析颜色字符串
* @param {string} str 颜色字符串
* @returns {Color} 解析得到的颜色对象
*/
Color.parse = function(str) {
var json = JSON.parse(window.external.IEFrame.ParseHtmlColor(str));
return new Color(json.r, json.g, json.b, json.a);
}
Color.getSuitableForegroundTextColor = function(backgroundColor, foregroundColorArray) {
// 将 0255 转为 W3C 的 01并做 gamma 校正
function gammaCorrect(c) {
c /= 255;
if (c <= 0.03928) return c / 12.92;
return Math.pow((c + 0.055) / 1.055, 2.4);
}
// 计算相对亮度 L01
function relativeLuminance(color) {
var R = gammaCorrect(color.red);
var G = gammaCorrect(color.green);
var B = gammaCorrect(color.blue);
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
}
// 计算对比度 (L1+0.05)/(L2+0.05)
function contrastRatio(l1, l2) {
var light = Math.max(l1, l2);
var dark = Math.min(l1, l2);
return (light + 0.05) / (dark + 0.05);
}
// 混合背景透明度:背景 alpha 与白色混合
function blendWithWhite(color) {
const a = (color.alpha !== undefined ? color.alpha : 255) / 255;
return {
red: color.red * a + 255 * (1 - a),
green: color.green * a + 255 * (1 - a),
blue: color.blue * a + 255 * (1 - a),
alpha: 255
};
}
// 透明背景视为与白色叠加
const bg = blendWithWhite(backgroundColor);
const bgL = relativeLuminance(bg);
// 找出和背景对比度最高的前景色
let bestColor = null;
let bestContrast = -1;
for (var i = 0; i < foregroundColorArray.length; i++) {
var fg = foregroundColorArray[i];
var fgBlended = blendWithWhite(fg); // 若前景也有透明度
var fgL = relativeLuminance(fgBlended);
var cr = contrastRatio(bgL, fgL);
if (cr > bestContrast) {
bestContrast = cr;
bestColor = fg;
}
}
return bestColor;
}
Color.Const = { Color.Const = {
white: new Color(255, 255, 255), white: new Color(255, 255, 255),
black: new Color(0, 0, 0), black: new Color(0, 0, 0),
@@ -541,6 +484,83 @@
magenta: new Color(255, 0, 255), magenta: new Color(255, 0, 255),
transparent: new Color(0, 0, 0, 0), transparent: new Color(0, 0, 0, 0),
}; };
/**
* 解析颜色字符串
* @param {string} str 颜色字符串
* @returns {Color} 解析得到的颜色对象
*/
Color.parse = function(str) {
var json = JSON.parse(window.external.IEFrame.ParseHtmlColor(str));
return new Color(json.r, json.g, json.b, json.a);
}
Color.getSuitableForegroundTextColor = function(backgroundColor, foregroundColorArray) {
function gammaCorrect(c) {
c /= 255;
if (c <= 0.03928) return c / 12.92;
return Math.pow((c + 0.055) / 1.055, 2.4);
}
function relativeLuminance(color) {
var R = gammaCorrect(color.red);
var G = gammaCorrect(color.green);
var B = gammaCorrect(color.blue);
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
}
function blendWithWhite(color) {
var a = (color.alpha !== undefined ? color.alpha : 255) / 255;
return {
red: color.red * a + 255 * (1 - a),
green: color.green * a + 255 * (1 - a),
blue: color.blue * a + 255 * (1 - a),
alpha: 255
};
}
// 计算 RGB 欧氏距离,衡量色差
function colorDistance(c1, c2) {
var dr = c1.red - c2.red;
var dg = c1.green - c2.green;
var db = c1.blue - c2.blue;
return Math.sqrt(dr * dr + dg * dg + db * db);
}
var bg = blendWithWhite(backgroundColor);
var bgL = relativeLuminance(bg);
var bestScore = -Infinity;
var bestColor = null;
for (var i = 0; i < foregroundColorArray.length; i++) {
var fg = foregroundColorArray[i];
var fgBlended = blendWithWhite(fg);
var fgL = relativeLuminance(fgBlended);
// 亮度差
var lumDiff = Math.abs(fgL - bgL); // 0~1
// 色彩差RGB欧氏距离0~441
var colorDiff = colorDistance(fgBlended, bg) / Math.sqrt(3 * 255 * 255);
// 综合得分
// 高亮度差 + 色彩差更高 → 得分高
// 同时适当惩罚过暗颜色
var score = lumDiff * 0.6 + colorDiff * 0.4;
// 轻微惩罚过深颜色(背景浅色时)
if (bgL > 0.8 && fgL < 0.3) score -= 0.1;
// 轻微惩罚过浅颜色(背景深色时)
if (bgL < 0.2 && fgL > 0.9) score -= 0.05;
if (score > bestScore) {
bestScore = score;
bestColor = fg;
}
}
return bestColor;
};
module.exports = { Color: Color }; module.exports = { Color: Color };
})(this); })(this);

1725
shared/html/libs/markdown.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
WinJS
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
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.

View File

@@ -31,6 +31,7 @@
</head> </head>
<body> <body>
<div class="pagecontainer full pagesection">
<div class="section padding"> <div class="section padding">
<h2 id="guide-title"></h2> <h2 id="guide-title"></h2>
<p id="guide-desc" style="white-space: pre-wrap;"></p> <p id="guide-desc" style="white-space: pre-wrap;"></p>
@@ -46,6 +47,7 @@
text.textContent = res.byname("IDS_GUIDETEXT_COMMON"); text.textContent = res.byname("IDS_GUIDETEXT_COMMON");
})(); })();
</script> </script>
</div>
</body> </body>
</html> </html>

View File

@@ -5,8 +5,12 @@
var page = document.querySelector("#settingpage"); var page = document.querySelector("#settingpage");
var guide = page.querySelector(".page.guide"); var guide = page.querySelector(".page.guide");
var slide = guide.querySelector("aside"); var slide = guide.querySelector("aside");
setTimeout(function() {
var barcolor = visual["BackgroundColor"];
slide.style.backgroundColor = barcolor;
slide.style.color = Color.getSuitableForegroundTextColor(Color.parse(barcolor), [Color.Const.white, Color.Const.black]).stringify();
}, 50);
var content = guide.querySelector(".main"); var content = guide.querySelector(".main");
var shead = slide.querySelector("header");
var list = slide.querySelector("ul"); var list = slide.querySelector("ul");
list.innerHTML = ""; list.innerHTML = "";
var items = pages; var items = pages;
@@ -19,12 +23,17 @@
li.setAttribute("data-page", item.page); li.setAttribute("data-page", item.page);
li.innerHTML = item.title; li.innerHTML = item.title;
eventutil.addEvent(li, "click", function() { eventutil.addEvent(li, "click", function() {
content.style.display = "none";
for (var j = 0; j < list.children.length; j++) { for (var j = 0; j < list.children.length; j++) {
var child = list.children[j]; var child = list.children[j];
if (child.classList.contains("selected")) if (child.classList.contains("selected"))
child.classList.remove("selected"); child.classList.remove("selected");
} }
content.src = this.getAttribute("data-page"); content.src = this.getAttribute("data-page");
setTimeout(function() {
content.style.display = "";
Windows.UI.Animation.runAsync(content, Windows.UI.Animation.Keyframes.SlideInFromBottom);
}, 0);
this.classList.add("selected"); this.classList.add("selected");
}); });
list.appendChild(li); list.appendChild(li);

View File

@@ -3,6 +3,19 @@
function ready(e) { function ready(e) {
Windows.UI.DPI.mode = 1 Windows.UI.DPI.mode = 1
var pagesection = document.querySelector(".pagesection");
if (pagesection) {
var backcolor = slideback;
setTimeout(function() {
var h2style = document.getElementById("h2-style");
if (!h2style) {
h2style = document.createElement("style");
h2style.id = "h2-style";
}
h2style.innerHTML = ".main h2 { color: " + Color.getSuitableForegroundTextColor(Color.parse("#F3F3F3"), [Color.parse(backcolor), Color.Const.black]).RGBA.stringify() + " }";
document.head.appendChild(h2style);
}, 0);
}
} }
OnLoad.add(ready); OnLoad.add(ready);
})(this); })(this);

View File

@@ -17,8 +17,19 @@
} }
try { try {
slide.style.backgroundColor = Bridge.UI.themeColor; slide.style.backgroundColor = Bridge.UI.themeColor;
slide.style.color = Color.getSuitableForegroundTextColor(Color.parse(slide.style.backgroundColor), [Color.Const.white, Color.Const.black]); slide.style.color = Color.getSuitableForegroundTextColor(Color.parse(Bridge.UI.themeColor), [Color.Const.white, Color.Const.black]).RGBA.stringify();
} catch (e) {} setTimeout(function() {
var h2style = document.getElementById("h2-style");
if (!h2style) {
h2style = document.createElement("style");
h2style.id = "h2-style";
}
h2style.innerHTML = ".main h2 { color: " + Color.getSuitableForegroundTextColor(Color.parse("#F3F3F3"), [Color.parse(Bridge.UI.themeColor), Color.Const.black]).RGBA.stringify() + " }";
document.head.appendChild(h2style);
}, 0);
} catch (e) {
console.error(e);
}
setTimeout(function() { setTimeout(function() {
slide.style.transition = "all 0.5s cubic-bezier(0.1, 0.9, 0.2, 1)"; slide.style.transition = "all 0.5s cubic-bezier(0.1, 0.9, 0.2, 1)";
}, 0); }, 0);

View File

@@ -0,0 +1,385 @@
<!DOCTYPE html>
<html>
<head>
<title>App Installer Settings</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="../js/module.js"></script>
<script type="text/javascript" src="../js/polyfill-ie.js"></script>
<link rel="stylesheet" href="../libs/winjs/2.0/css/ui-light.css" id="winjs-style">
<script type="text/javascript" src="../libs/winjs/1.0/js/base.js"></script>
<script type="text/javascript" src="../libs/winjs/1.0/js/ui.js"></script>
<script src="../libs/markdown.js"></script>
<script type="text/javascript" src="../js/color.js"></script>
<script type="text/javascript" src="../js/promise.js"></script>
<script type="text/javascript" src="../js/bridge.js"></script>
<script type="text/javascript" src="../js/dpimodes.js"></script>
<script type="text/javascript" src="../js/resources.js"></script>
<script type="text/javascript" src="../js/animation.js"></script>
<link rel="stylesheet" href="../fonts/fonts.css">
<script type="text/javascript" src="../js/event.js"></script>
<script type="text/javascript" src="../js/tileback.js"></script>
<script type="text/javascript" src="../js/load.js"></script>
<link rel="stylesheet" type="text/css" href="../libs/msgbox/msgbox.css">
<script type="text/javascript" src="../libs/msgbox/msgbox.js"></script>
<script type="text/javascript" src="../js/init.js"></script>
<link rel="stylesheet" type="text/css" href="page.css">
<link rel="stylesheet" type="text/css" href="subpage.css">
<script type="text/javascript" src="appinstaller/preinit.js"></script>
<script type="text/javascript" src="appinstaller/initsame.js"></script>
<style>
.section .block {
width: 100%;
height: auto;
margin-top: 10px;
margin-bottom: 10px;
box-sizing: border-box;
position: relative;
transition: all 0.5s cubic-bezier(0.1, 0.9, 0.2, 1);
overflow-x: hidden;
overflow-y: hidden;
background-color: blanchedalmond;
}
.pagesection .section {
position: relative;
height: auto;
}
.pagesection .section.padding {
padding: 0 60px;
}
.pagesection .section.padding:first-child {
padding-top: 44px;
}
.pagesection .section.padding:last-child {
padding-bottom: 44px;
}
#check-update-block {
height: 50px;
}
#check-update-block progress {
min-width: 180px;
width: 100%;
max-width: 60%;
transition: all 0.5s cubic-bezier(0.1, 0.9, 0.2, 1);
}
#check-update-block progress[value] {
width: 280px;
}
#newversion-details {
height: auto;
overflow-y: auto;
-ms-overflow-style: -ms-autohiding-scrollbar;
width: 100%;
}
#newversion-desc {
white-space: pre-wrap;
}
#newversion-desc img {
width: 100%;
}
#check-update:disabled {
display: none;
}
#loading-amine {
display: none;
opacity: 0;
font-family: Setup;
}
#loading-amine[data-start-loading] {
display: inline;
opacity: 1;
margin-right: 3px;
}
</style>
<script>
window.parseVersion = function(version) {
var arr = version.split(".");
var major = parseInt(arr[0]);
var minor = parseInt(arr[1]);
var build = parseInt(arr[2]);
var revision = parseInt(arr[3]);
return {
major: major,
minor: minor,
build: build,
revision: revision
};
};
window.compareVersion = function(verl, verr) {
if (typeof verl == "string") verl = parseVersion(verl);
if (typeof verr == "string") verr = parseVersion(verr);
var ret = verl.major - verr.major;
if (ret == 0) {
ret = verl.minor - verr.minor;
}
if (ret == 0) {
ret = verl.build - verr.build;
}
if (ret == 0) {
ret = verl.revision - verr.revision;
}
return ret;
};
window.equalVersion = function(verl, verr) {
if (typeof verl == "string") verl = parseVersion(verl);
if (typeof verr == "string") verr = parseVersion(verr);
return verl.major == verr.major && verl.minor == verr.minor && verl.build == verr.build && verl.revision == verr.revision;
};
window.stringifyVersion = function(version) {
return version.major + "." + version.minor + "." + version.build + "." + version.revision;
};
</script>
<script>
(function(global) {
"use strict";
var jsdownloadAsync = Bridge.External.Download;
function downloadAsync(url, fileName, completeCallback, errorCallback, progressCallback) {
function downloadProgress(p) {
if (progressCallback) progressCallback(JSON.parse(p || "{}"));
}
function downloadComplete(c) {
if (completeCallback) completeCallback(JSON.parse(c || "{}"));
}
function downloadError(e) {
if (errorCallback) errorCallback(JSON.parse(e || "{}"));
}
jsdownloadAsync.workAsync(url, fileName, downloadComplete, downloadError, downloadProgress);
}
global.downloadFile = function(url, fileName) {
return new WinJS.Promise(function(resolve, reject, progress) {
downloadAsync(
url,
fileName,
resolve,
reject,
progress
);
});
};
})(this);
</script>
</head>
<body>
<div class="pagecontainer full pagesection" style="overflow-y: auto;">
<div class="section padding">
<h2 id="section-title" data-res-fromfile="publicRes (103)"></h2>
<p id="section-desc" style="white-space: pre-wrap;">在这里,检查一下应用的更新。</p>
<p><span data-res-fromfile="publicRes (104)"></span>&#9;<span id="current-version"></span></p>
<script>
try {
var storage = Bridge.External.Storage;
var path = storage.path;
var versionFilePath = path.combine(path.root, "version");
var versionFile = storage.getFile(versionFilePath);
window.currver = versionFile.content;
} catch (e) {
window.currver = "0.0.0.1";
}
document.getElementById("current-version").textContent = window.currver;
</script>
</div>
<div class="section padding" style="">
<div class="block" id="check-update-block" style="height: 0px;">
<span id="loading-amine">123</span><span id="check-update-text">正在检查更新...</span><br>
<progress id="progress" min="0" max="100"></progress>
<a target="_blank" id="doc-link">查看文档</a>
</div>
</div>
<div class="section padding" style="margin: 10px 0;"><button id="check-update" data-action="check">检查更新</button></div>
<div class="section padding" style="display: none; overflow-y: auto; height: 0px; transition: all 0.5s cubic-bezier(0.1, 0.9, 0.2, 1); margin-top: 20px;">
<h2>获取到的更新信息</h2>
<div class="block" id="newversion-details">
<h3 id="newversion-title"><span>最新版本</span>: <span id="newversion-version"></span></h3>
<span id="newversion-releasedate"></span><br>
<a id="newversion-url" target="_blank">查看链接</a><br>
<span>发布说明: </span><a id="newversion-desc-showall-hide">展开</a>
<div id="newversion-desc"></div>
</div>
</div>
<script>
(function() {
"use strict";
var eutils = Windows.UI.Event.Util;
var monitor = Windows.UI.Event.Monitor;
var section = document.querySelector(".pagesection .section").parentNode;
var checkUpdateBtn = document.getElementById("check-update");
var checkUpdateBlock = document.getElementById("check-update-block");
var progress = document.querySelector("#check-update-block progress");
var checkUpdateText = document.getElementById("check-update-text");
var docLink = document.getElementById("doc-link");
var currentVersion = document.getElementById("current-version");
var newVersionBlock = document.getElementById("newversion-details");
var newVersionTitle = document.getElementById("newversion-title");
var newVersionVersion = document.getElementById("newversion-version");
var newVersionReleaseDate = document.getElementById("newversion-releasedate");
var newVersionUrl = document.getElementById("newversion-url");
var newVersionDesc = document.getElementById("newversion-desc");
var newVersionDescShowOrHide = document.getElementById("newversion-desc-showall-hide");
var checkUpdateLoading = document.getElementById("loading-amine");
var stopProcess = false;
function newVersionBlockSizeChanged() {
if (stopProcess) return;
var parentSection = newVersionBlock.parentNode;
var sectionHeight = parentSection.parentNode.offsetHeight;
var newHeight = sectionHeight - parentSection.getBoundingClientRect().top;
parentSection.setAttribute("data-height", newHeight);
if (parentSection.hasAttribute("data-showall") == true) {
parentSection.style.height = "auto";
} else {
parentSection.style.height = newHeight + "px";
}
}
stopProcess = true;
var debunced_resize = debounce(newVersionBlockSizeChanged, 500);
eutils.addEvent(newVersionDescShowOrHide, "click", function() {
var parentSection = newVersionBlock.parentNode;
if (parentSection.hasAttribute("data-showall") == true) {
parentSection.removeAttribute("data-showall");
newVersionDescShowOrHide.textContent = "展开";
parentSection.style.height = parentSection.getAttribute("data-height") + "px";
} else {
parentSection.setAttribute("data-showall", true);
newVersionDescShowOrHide.textContent = "收起";
parentSection.style.height = "auto";
}
debunced_resize();
});
monitor.observe(newVersionBlock.parentNode, monitor.EventType.resize, debunced_resize);
eutils.addEvent(checkUpdateBtn, "click", function() {
checkUpdateBlock.style.height = "0px";
var self = this;
this.disabled = true;
progress.removeAttribute("value");
if (checkUpdateBtn.getAttribute("data-action") == "check") {
checkUpdateText.textContent = "正在检查更新...";
checkUpdateBlock.style.height = checkUpdateBlock.scrollHeight + "px";
progress.style.display = "";
docLink.style.display = "none";
stopProcess = true;
newVersionBlock.parentNode.style.height = "0px";
newVersionBlock.parentNode.style.display = "none";
setTimeout(function() {
checkUpdateBlock.style.height = "auto";
}, 500);
try {
WinJS.xhr({
url: "https://api.github.com/repos/modernw/App-Installer-For-Windows-8.x-Reset/releases/latest"
}).done(function(resp) {
console.log("success", resp);
var json = JSON.parse(resp.responseText);
console.log(json);
self.disabled = false;
newVersionVersion.textContent = json.name;
newVersionVersion.setAttribute("data-version", json.tag_name);
window.newver = json.tag_name;
newVersionReleaseDate.textContent = "发布日期: " + json.published_at;
newVersionUrl.href = json.html_url;
newVersionDesc.innerHTML = markdown.toHTML(json.body);
checkUpdateText.textContent = "检查更新完成";
progress.style.display = "none";
newVersionBlock.parentNode.style.display = "";
stopProcess = false;
debunced_resize();
for (var i = 0; i < json.assets.length; i++) {
if (json.assets[i].browser_download_url.indexOf("/InstallerSetup.exe") > -1) {
window.downloadUrl = json.assets[i].browser_download_url;
break;
}
}
if (compareVersion(window.currver, window.newver) > 0) {
checkUpdateText.textContent = "当前已是最新版本";
checkUpdateBtn.textContent = "检查更新";
checkUpdateBtn.setAttribute("data-action", "check");
} else {
checkUpdateText.textContent = "有新版本可用: " + window.newver;
checkUpdateBtn.textContent = "下载更新";
checkUpdateBtn.setAttribute("data-action", "download");
}
}, function(error) {
console.log("error", error);
var json = JSON.parse(error.responseText);
checkUpdateText.textContent = json.message;
progress.style.display = "none";
docLink.style.display = "";
docLink.href = json.documentation_url;
self.disabled = false;
});
} catch (error) {
console.log("error", error);
checkUpdateText.textContent = error.message || e || "Unknown Exception"
progress.style.display = "none";
docLink.style.display = "none";
docLink.href = "";
self.disabled = false;
}
} else if (checkUpdateBtn.getAttribute("data-action") == "download") {
stopProcess = true;
newVersionBlock.parentNode.style.height = "0px";
checkUpdateText.textContent = "正在下载更新...";
progress.style.display = "";
checkUpdateBlock.style.height = checkUpdateBlock.scrollHeight + "px";
var anime = Windows.UI.Animation;
function setError(error) {
console.error("download error", error);
checkUpdateText.textContent = "下载失败,请重试: " + error.reason;
progress.style.display = "none";
self.disabled = false;
self.textContent = "重试";
}
function setException(e) {
console.error("download exception", e);
checkUpdateText.textContent = "下载出现异常,请重试: " + e.message;
}
function setComplete(complete) {
console.log("download complete", complete);
checkUpdateText.textContent = "下载完成,即将进行安装...";
}
progress.value = 0;
anime.loading(checkUpdateLoading, true);
downloadFile(downloadUrl, "E:\\Profiles\\Bruce\\Desktop\\InstallerSetup.exe").done(
function(complete) {
anime.loading(checkUpdateLoading, false);
if (complete.status == "ok") setComplete(complete);
else setError(complete);
},
function(error) {
anime.loading(checkUpdateLoading, false);
setError(error);
},
function(prog) {
console.log("download progress", progress);
progress.value = prog.progress;
checkUpdateText.textContent = "正在下载更新... (" + Math.round(prog.progress) + "%)";
}
)
}
});
})();
</script>
</div>
</body>
</html>

1
shared/version Normal file
View File

@@ -0,0 +1 @@
0.1.0.0