From fc66b6de72dad861220a6d57fe7b825fd5c8aee6 Mon Sep 17 00:00:00 2001 From: Bruce Date: Wed, 10 Dec 2025 22:12:32 +0800 Subject: [PATCH] Update theme and fix bugs. --- priformatcli/priformatcli.cpp | 41 +--- priformatcli/priformatcli.vcxproj | 1 + priformatcli/priformatcli.vcxproj.filters | 3 + priformatcli/strcmp.h | 154 +++++++++++++++ shared/config.ini | Bin 1628 -> 1654 bytes shared/html/applist.html | 7 +- shared/html/install.html | 4 +- shared/html/js/theme.js | 197 ++++++++++++++++++- shared/html/settings/appinstaller/about.html | 5 + shared/html/settings/appinstaller/theme.html | 11 +- shared/html/theme/dark/default.css | 35 ---- shared/html/theme/dark/default/default.css | 91 +++++++++ shared/html/theme/light/default.css | 19 -- shared/html/theme/light/default/default.css | 77 ++++++++ 14 files changed, 543 insertions(+), 102 deletions(-) create mode 100644 priformatcli/strcmp.h delete mode 100644 shared/html/theme/dark/default.css create mode 100644 shared/html/theme/dark/default/default.css delete mode 100644 shared/html/theme/light/default.css create mode 100644 shared/html/theme/light/default/default.css diff --git a/priformatcli/priformatcli.cpp b/priformatcli/priformatcli.cpp index 002d5a6..ac2ef0b 100644 --- a/priformatcli/priformatcli.cpp +++ b/priformatcli/priformatcli.cpp @@ -10,6 +10,7 @@ #include "themeinfo.h" #include "localeex.h" #include "syncutil.h" +#include "strcmp.h" #include #include @@ -116,44 +117,6 @@ ref class PriFileInst } } }; -std::wstring GetStringLeft (const std::wstring &str, size_t length = 1) -{ - std::wstring ret = L""; - ret.reserve (length + 1); - size_t slen = lstrlenW (str.c_str ()); - for (size_t i = 0; i < length && i < slen; i ++) - { - ret += str.at (i); - } - return ret; -} -std::wstring GetStringRight (const std::wstring &str, size_t length = 1) -{ - std::wstring ret = L""; - ret.reserve (length + 1); - size_t slen = lstrlenW (str.c_str ()); - for (size_t i = ((int64_t)slen - length) < 0 ? 0 : slen - length; i < slen; i ++) ret += str.at (i); - return ret; -} -std::string GetStringLeft (const std::string &str, size_t length = 1) -{ - std::string ret = ""; - ret.reserve (length + 1); - size_t slen = strlen (str.c_str ()); - for (size_t i = 0; i < length && i < slen; i ++) - { - ret += str.at (i); - } - return ret; -} -std::string GetStringRight (const std::string &str, size_t length = 1) -{ - std::string ret = ""; - ret.reserve (length + 1); - size_t slen = strlen (str.c_str ()); - for (size_t i = ((int64_t)slen - length) < 0 ? 0 : slen - length; i < slen; i ++) ret += str.at (i); - return ret; -} size_t KeyToPath (const std::wstring &key, std::vector &output); typedef struct _TASKITEM_SEARCH { @@ -531,7 +494,7 @@ std::wstring GetSuitablePathValueByDPI (std::vector &pathcand) }); if (pathcand.empty ()) return L""; uint32_t nowdpi = GetDPI (); - for (auto &cv : pathcand) if (cv.get_scale () >= nowdpi) return cv.value; + for (auto &cv : pathcand) if (cv.get_scale () >= nowdpi && !StrInclude (cv.value, L"layoutdir-RTL", true)) return cv.value; return pathcand.back ().value; } std::wstring GetSuitablePathValue (std::vector &pathcand) diff --git a/priformatcli/priformatcli.vcxproj b/priformatcli/priformatcli.vcxproj index 4a289b0..245a27f 100644 --- a/priformatcli/priformatcli.vcxproj +++ b/priformatcli/priformatcli.vcxproj @@ -159,6 +159,7 @@ + diff --git a/priformatcli/priformatcli.vcxproj.filters b/priformatcli/priformatcli.vcxproj.filters index c7d525b..6987141 100644 --- a/priformatcli/priformatcli.vcxproj.filters +++ b/priformatcli/priformatcli.vcxproj.filters @@ -51,6 +51,9 @@ 头文件 + + 头文件 + diff --git a/priformatcli/strcmp.h b/priformatcli/strcmp.h new file mode 100644 index 0000000..1748724 --- /dev/null +++ b/priformatcli/strcmp.h @@ -0,0 +1,154 @@ +#pragma once +#include +#include "nstring.h" +#ifdef __cplusplus +#define ptrnull(ptr) (!(ptr)) +#else +#define ptrnull(ptr) ((ptr) == NULL) +#endif +#define ptrvalid(ptr) (!ptrnull (ptr)) +// char * WCHAR * ַβΪ NULLжǷΪǿַָЧҳȴ 0ǧҰָ룬һ +#define strvalid(strptr) (ptrvalid (strptr) && *(strptr)) +// char * WCHAR * ַβΪ NULLжǷΪַָΪ NULL 򳤶Ϊ 0ǧҰָ룬һ +#define strnull(strptr) (ptrnull (strptr) || !*(strptr)) +typedef std::wnstring strlabel, StringLabel; +std::wstring StringTrim (const std::wstring &str) { return std::wnstring::trim (str); } +std::string StringTrim (const std::string &str) { return std::nstring::trim (str); } +#define StringToUpper l0km::toupper +#define StringToLower l0km::tolower +int LabelCompare (const std::wstring &l1, const std::wstring &l2) +{ + return std::wnstring::compare (l1, l2); +} +int LabelCompare (const std::string &l1, const std::string &l2) +{ + return std::nstring::compare (l1, l2); +} +bool LabelEqual (const std::wstring &l1, const std::wstring &l2) +{ + return std::wnstring::equals (l1, l2); +} +bool LabelEqual (const std::string &l1, const std::string &l2) +{ + return std::wnstring::equals (l1, l2); +} +bool LabelEmpty (const std::wstring &str) { return std::wnstring::empty (str); } +bool LabelEmpty (const std::string &str) { return std::nstring::empty (str); } +#define LabelNoEmpty(_str_) (!LabelEmpty (_str_)) +int InStr (const std::string &text, const std::string &keyword, bool ignoreCase = false) +{ + std::string s1, s2; + if (ignoreCase) + { + s1 = StringToUpper (text); + s2 = StringToUpper (keyword); + } + else + { + s1 = text; + s2 = keyword; + } + const char *found = StrStrIA (s1.c_str (), s2.c_str ()); + if (!found) + { + return -1; + } + return found - text.c_str (); +} +int InStr (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false) +{ + std::wstring s1, s2; + if (ignoreCase) + { + s1 = StringToUpper (text); + s2 = StringToUpper (keyword); + } + else + { + s1 = text; + s2 = keyword; + } + const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ()); + if (!found) + { + return -1; + } + return found - text.c_str (); +} +bool StrInclude (const std::string &text, const std::string &keyword, bool ignoreCase = false) +{ + std::string s1, s2; + if (ignoreCase) + { + s1 = StringToUpper (text); + s2 = StringToUpper (keyword); + } + else + { + s1 = text; + s2 = keyword; + } + const char *found = StrStrIA (s1.c_str (), s2.c_str ()); + if (!found) return false; + return true; +} +bool StrInclude (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false) +{ + std::wstring s1, s2; + if (ignoreCase) + { + s1 = StringToUpper (text); + s2 = StringToUpper (keyword); + } + else + { + s1 = text; + s2 = keyword; + } + const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ()); + if (!found) return false; + return true; +} +// ú "\0\0" ַͨöԻеļ +LPCWSTR strcpynull (LPWSTR dest, LPCWSTR endwith, size_t bufsize) +{ + if (!dest || !endwith || bufsize == 0) + return dest; + if (dest [0] == L'\0' && bufsize > 1) + { + dest [1] = L'\0'; + } + size_t pos = 0; + while (pos < bufsize - 1) + { + if (dest [pos] == L'\0' && dest [pos + 1] == L'\0') + { + if (dest [0]) pos ++; + break; + } + pos ++; + } + size_t i = 0; + while (pos < bufsize - 1 && endwith [i] != L'\0') + { + dest [pos ++] = endwith [i ++]; + } + if (pos < bufsize) + { + dest [pos] = L'\0'; + } + return dest; +} +// ȡıߣע⣺ָıַ硰chijΪ2 +std::wstring GetStringLeft (const std::wstring &str, size_t length) +{ + std::vector buf (length + 1); + lstrcpynW (buf.data (), str.c_str (), length + 1); + return buf.data (); +} +// ȡıұ +std::wstring GetStringRight (const std::wstring &str, size_t length) +{ + if (length >= str.length ()) return str; + return str.substr (str.length () - length, length).c_str (); +} diff --git a/shared/config.ini b/shared/config.ini index 0a037591f95eda3337d8bf6bc8c27b4f7ecac486..046b277f0d77d775e2df0c96c0f12d7ba8f4e805 100644 GIT binary patch delta 208 zcmcb^^NnYN3JYrpLlHyiWNntk?1>De3?&TtlP9vuPtIcPnk>i4!|BYB&yWMeMU$;r z^(Sv&WwEbh2w})%$Yn@nP++hHVj~6v216j!1=8j~(vZOvsKS83g24(%8bC=sFx!A3 d3S@eSAJBw!h76!>#Fz!L0jpUIybN4$3;^?YA)f#M delta 140 zcmeyybBAYx3Jbd%Ln1>CL-Axymc^52u<}igVo{lVg+*?14J(ge2tx)#Dnl+1`!eJ+ zq%fpTp2(^{`4dZ*vJ+5OGD9{)Iztgqrj#KMDC-Plv(2CX0$ diff --git a/shared/html/applist.html b/shared/html/applist.html index f5a6f36..c723c8d 100644 --- a/shared/html/applist.html +++ b/shared/html/applist.html @@ -6,7 +6,7 @@ - + @@ -245,11 +245,13 @@ font-weight: normal; } + +
-
+
@@ -345,6 +347,7 @@ function createItem(title, logo, appid, color) { var item = AppListElements.template.cloneNode(true); + item.removeAttribute("role"); var inode = new AppListNodeElement(item); inode.title = title; inode.logo = logo; diff --git a/shared/html/install.html b/shared/html/install.html index 01ef41d..b360060 100644 --- a/shared/html/install.html +++ b/shared/html/install.html @@ -22,12 +22,12 @@ - - + + diff --git a/shared/html/js/theme.js b/shared/html/js/theme.js index 6ac9eac..39201ea 100644 --- a/shared/html/js/theme.js +++ b/shared/html/js/theme.js @@ -1,5 +1,200 @@ (function(global) { "use strict"; + var winjsCss = document.querySelector("link#winjs-style"); + var themeCss = document.querySelector("link#theme-style"); + var winjsPath = "libs/winjs/2.0/css/ui-{themecolor}.css"; + var themePath = "theme/{themecolor}/{id}/{id}.css"; + var ini = Bridge.External.Config.getConfig(); + var themeSection = ini.getSection("Personalization"); + var ThemeType = { + light: 1, // 浅色模式 + dark: 2, // 深色模式 + auto: 3, // 跟随系统 + time: 4, // 跟随时间 + custom: 5 // 自定义 + }; + var nstrutil = Bridge.NString; + var ColorType = { + light: 0xFFFFFF, + dark: 0x000000, + }; - function changeDarkMode(mode) {} + function getThemeSwitchType() { + var themeType = themeSection.getKey("AppInstaller:ThemeMode").value; + if (nstrutil.equals(themeType, "light")) return ThemeType.light; + else if (nstrutil.equals(themeType, "dark")) return ThemeType.dark; + else if (nstrutil.equals(themeType, "auto")) return ThemeType.auto; + else if (nstrutil.equals(themeType, "time")) return ThemeType.time; + else if (nstrutil.equals(themeType, "custom")) return ThemeType.custom; + else return ThemeType.light; + } + + function getCurrentThemeColor() { + try { + var themeType = getThemeSwitchType(); + if (themeType === ThemeType.light) return ColorType.light; + else if (themeType === ThemeType.dark) return ColorType.dark; + else if (themeType === ThemeType.auto) { + if (Bridge.UI.darkmode) return ColorType.dark; + else return ColorType.light; + } else if (themeType === ThemeType.time) { + var daytime = new Date(); + var nighttime = new Date(); + try { + var daytimestr = themeSection.getKey("AppInstaller:DayTime").value; + daytime = new Date(daytimestr); + } catch (e) { + console.error(e); + daytime = new Date('2011-07-15T08:00:00.000Z'); + } + try { + var nighttimestr = themeSection.getKey("AppInstaller:NightTime").value; + nighttime = new Date(nighttimestr); + } catch (e) { + console.error(e); + nighttime = new Date('2011-07-15T20:00:00.000Z'); + } + var now = new Date(); + daytime.setFullYear(now.getFullYear()); + nighttime.setFullYear(now.getFullYear()); + daytime.setMonth(now.getMonth()); + nighttime.setMonth(now.getMonth()); + daytime.setDate(now.getDate()); + nighttime.setDate(now.getDate()); + if (now >= daytime && now < nighttime) return ColorType.light; + else return ColorType.dark; + } else if (themeType === ThemeType.custom) { + var customColor = themeSection.getKey("AppInstaller:CustomColor").value; + if (nstrutil.equals(customColor, "light")) return ColorType.light; + else if (nstrutil.equals(customColor, "dark")) return ColorType.dark; + else return ColorType.light; + } else { + return ColorType.light; + } + } catch (e) { + return ColorType.light; + } + } + + function getSuitableTheme() { + var color = getCurrentThemeColor(); + var ret = ""; + if (color === ColorType.light) ret = themeSection.getKey("AppInstaller:LightTheme").value; + else ret = themeSection.getKey("AppInstaller:DarkTheme").value; + if (nstrutil.empty(ret)) ret = "default"; + return ret; + } + + function getTimeModeTimeLimit() { + var ret = { + day: new Date(), + night: new Date() + }; + try { + var daytimestr = themeSection.getKey("AppInstaller:DayTime").value; + ret.day = new Date(daytimestr); + } catch (e) { + console.error(e); + ret.day = new Date('2011-07-15T08:00:00.000Z'); + } + try { + var nighttimestr = themeSection.getKey("AppInstaller:NightTime").value; + ret.night = new Date(nighttimestr); + } catch (e) { + console.error(e); + ret.night = new Date('2011-07-15T20:00:00.000Z'); + } + var now = new Date(); + ret.day.setFullYear(now.getFullYear()); + ret.night.setFullYear(now.getFullYear()); + ret.day.setMonth(now.getMonth()); + ret.night.setMonth(now.getMonth()); + ret.day.setDate(now.getDate()); + ret.night.setDate(now.getDate()); + return ret; + } + + function copyTime(to, from) { + to.setHours( + from.getHours(), + from.getMinutes(), + from.getSeconds(), + from.getMilliseconds() + ); + } + var dayTimer = null; + var nightTimer = null; + + function setupThemeTimers(limit, execFunc) { + if (limit === null || limit === void 0) limit = getTimeModeTimeLimit(); + var now = new Date(); + var dayTime = new Date(now); + var nightTime = new Date(now); + copyTime(dayTime, limit.day); + copyTime(nightTime, limit.night); + // 处理跨天:如果 night <= day,说明夜晚跨到第二天 + var nightIsNextDay = nightTime <= dayTime; + if (nightIsNextDay) { + nightTime.setDate(nightTime.getDate() + 1); + } + var isDayTime; + if (nightIsNextDay) { + isDayTime = now >= dayTime && now < nightTime; + } else { + isDayTime = now >= dayTime && now < nightTime; + } + var nextDay = new Date(dayTime); + var nextNight = new Date(nightTime); + if (now >= dayTime) nextDay.setDate(nextDay.getDate() + 1); + if (now >= nightTime) nextNight.setDate(nextNight.getDate() + 1); + if (dayTimer) { + clearTimeout(dayTimer); + dayTimer = null; + } + if (nightTimer) { + clearTimeout(nightTimer); + nightTimer = null; + } + dayTimer = setTimeout(function() { + execFunc("day"); + setupThemeTimers(); // 递归重建,防漂移 + }, nextDay - now); + nightTimer = setTimeout(function() { + execFunc("night"); + setupThemeTimers(); + }, nextNight - now); + return isDayTime ? "day" : "night"; + } + + function refreshTheme() { + var type = getThemeSwitchType(); + var color = getCurrentThemeColor(); + var theme = getSuitableTheme(); + if (type === ThemeType.time) { + setupThemeTimers(getTimeModeTimeLimit(), refreshTheme); + } + var colorstr = "light"; + if (color === ColorType.light) colorstr = "light"; + else if (color === ColorType.dark) colorstr = "dark"; + winjsCss.setAttribute("href", winjsPath.replace("{themecolor}", colorstr)); + themeCss.setAttribute("href", themePath.replace("{themecolor}", colorstr).replace("{id}", theme).replace("{id}", theme)); + setTimeout(function() { + try { Windows.UI.DPI.mode = 1; } catch (e) {} + }, 0); + } + + module.exports = { + Theme: { + ThemeType: ThemeType, + ColorType: ColorType, + getType: getThemeSwitchType, + getColor: getCurrentThemeColor, + getTheme: getSuitableTheme, + getTimeModeTimeLimit: getTimeModeTimeLimit, + refresh: refreshTheme + } + }; + if (typeof OnLoad !== "undefined") { + OnLoad.add(refreshTheme); + } })(this); \ No newline at end of file diff --git a/shared/html/settings/appinstaller/about.html b/shared/html/settings/appinstaller/about.html index ee0cc52..f32c1a5 100644 --- a/shared/html/settings/appinstaller/about.html +++ b/shared/html/settings/appinstaller/about.html @@ -219,6 +219,8 @@ var json = JSON.parse(resp.responseText); var decoderesult = decodeBase64(json.content); content.innerHTML = decoderesult; + content.style.height = "300px"; + content.style.maxHeight = "100%"; }, function(err) { progress.style.display = "none"; @@ -257,6 +259,9 @@ script.src = jsfile; content.contentWindow.document.head.appendChild(script); } + var style2 = document.createElement("style"); + style2.innerHTML = '*,button,input,select,textarea,a,label,p,span,h1,h2,h3,h4,h5,h6,ul,ol,li,dl,dt,dd,table,th,td,tr,img,iframe,object,embed,audio,video,canvas,form,fieldset,legend,.win-type-x-large,.win-type-xx-large,.font-fixed{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";}'; + content.contentWindow.document.head.appendChild(style2); content.contentWindow.document.body.style.overflowY = "auto"; content.contentWindow.Windows.UI.DPI.mode = 1; } catch (e) {} diff --git a/shared/html/settings/appinstaller/theme.html b/shared/html/settings/appinstaller/theme.html index 370ae50..9800fd0 100644 --- a/shared/html/settings/appinstaller/theme.html +++ b/shared/html/settings/appinstaller/theme.html @@ -64,14 +64,14 @@
白天
-
+
夜晚
-
+
@@ -79,7 +79,7 @@

-
+

-
+

浅色主题

+
+

深色主题

+
diff --git a/shared/html/theme/dark/default.css b/shared/html/theme/dark/default.css deleted file mode 100644 index 6e93c18..0000000 --- a/shared/html/theme/dark/default.css +++ /dev/null @@ -1,35 +0,0 @@ -* { - transition: all 0.5s cubic-bezier(0.1, 0.9, 0.2, 1); -} - -.page { - background-color: #1d1d1d; -} - -.page.splash { - background-color: #001629; -} - -.page.splash .content, -.page.splash .content * { - transition: none; -} - -.page .content.loading, -.page .content.main, -.page .progress, -.page .reason p, -.page .controls .checkbox { - color: white; -} - -.page .content.main .pkgapplabel { - color: #299fff; -} - -.page .reason textarea { - background-color: rgba (255, 255, 255, 0); - color: white; - border: 2px solid white; - box-sizing: border-box; -} \ No newline at end of file diff --git a/shared/html/theme/dark/default/default.css b/shared/html/theme/dark/default/default.css new file mode 100644 index 0000000..d121c35 --- /dev/null +++ b/shared/html/theme/dark/default/default.css @@ -0,0 +1,91 @@ +/* +[ThemeInfo] +Id = default +DisplayName = Default Theme +Author = Bruce Winter +Version = 1.0 +Description = Default theme. +Url = https://github.com/modernw +Color = Dark +*/ + +.page, +.page * { + transition: background-color 0.3s cubic-bezier(0.1, 0.9, 0.2, 1), color 0.5s cubic-bezier(0.1, 0.9, 0.2, 1), border-color 0.5s cubic-bezier(0.1, 0.9, 0.2, 1); +} + +.page { + background-color: #1d1d1d; +} + +.page.splash { + background-color: #001629; +} + +.page.splash .content, +.page.splash .content * { + transition: none; +} + +.page .content.loading, +.page .content.main, +.page .progress, +.page .reason p, +.page .controls .checkbox { + color: white; +} + +.page .content.main .pkgapplabel { + color: #299fff; +} + +.page .reason textarea { + background-color: rgba (255, 255, 255, 0); + color: white; + border: 2px solid white; + box-sizing: border-box; +} + + +/* App Launch List */ + +.applist-font-title { + color: white; +} + +.applist-font-text { + color: white; +} + +.applist-window { + border: 2px solid rgb(42, 42, 42); + background-color: #1d1d1d; +} + +.applist-title { + background: #1d1d1d; +} + +.applist-control { + background: #1d1d1d; +} + +.applist-list-item { + background-color: rgba(0, 255, 255, 0); +} + +.applist-list-item:hover { + background-color: rgba(255, 255, 255, 0.13); +} + +.applist-item-picbox { + background-color: #001020; +} + +.applist-item-img-border { + border: 1px solid rgba(254, 254, 254, 0.1); +} + +.win10.applist-window { + border: 1px solid #ccc; +} \ No newline at end of file diff --git a/shared/html/theme/light/default.css b/shared/html/theme/light/default.css deleted file mode 100644 index a1d5a35..0000000 --- a/shared/html/theme/light/default.css +++ /dev/null @@ -1,19 +0,0 @@ -.page { - background-color: #F3F3F3; -} - -.page.splash { - background-color: #0078d7; -} - -.page .content.loading, -.page .content.main, -.page .progress, -.page .reason p, -.page .controls .checkbox { - color: black; -} - -.page .content.main .pkgapplabel { - color: #0078d7; -} \ No newline at end of file diff --git a/shared/html/theme/light/default/default.css b/shared/html/theme/light/default/default.css new file mode 100644 index 0000000..21c48f6 --- /dev/null +++ b/shared/html/theme/light/default/default.css @@ -0,0 +1,77 @@ +/* +[ThemeInfo] +Id = default +DisplayName = Default Theme +Author = Bruce Winter +Version = 1.0 +Description = Default theme. +Url = https://github.com/modernw +Color = Light +*/ + + +/* Installer */ + +.page { + background-color: #F3F3F3; +} + +.page.splash { + background-color: #0078d7; +} + +.page .content.loading, +.page .content.main, +.page .progress, +.page .reason p, +.page .controls .checkbox { + color: black; +} + +.page .content.main .pkgapplabel { + color: #0078d7; +} + + +/* App Launch List */ + +.applist-font-title { + color: black; +} + +.applist-font-text { + color: black; +} + +.applist-window { + border: 2px solid rgb(42, 42, 42); + background-color: white; +} + +.applist-title { + background: white; +} + +.applist-control { + background: white; +} + +.applist-list-item { + background-color: rgba(0, 255, 255, 0); +} + +.applist-list-item:hover { + background-color: rgb(222, 222, 222); +} + +.applist-item-picbox { + background-color: #001020; +} + +.applist-item-img-border { + border: 1px solid rgba(254, 254, 254, 0.1); +} + +.win10.applist-window { + border: 1px solid #ccc; +} \ No newline at end of file