Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88b4aac622 | ||
|
|
9504413ff7 | ||
|
|
0f28de1e94 | ||
|
|
ad11654cb4 | ||
|
|
f43aa16c6a | ||
|
|
c0e757dc12 | ||
|
|
fcecb2c14c | ||
|
|
408911de4a | ||
|
|
23932298fc | ||
|
|
7c554190af | ||
|
|
2f2065e453 | ||
|
|
1480b5d4df | ||
|
|
9ae326ce9f | ||
|
|
3dd83886b8 | ||
|
|
3a1a256198 | ||
|
|
84f9ae5227 | ||
|
|
ce85b39328 | ||
|
|
6c23ac30a3 | ||
|
|
bbe9596d8d | ||
|
|
5c42a2336d | ||
|
|
afa4ad9e91 | ||
|
|
50a3c7624e | ||
|
|
b40dac00b9 | ||
|
|
35be6db96e | ||
|
|
35641d5c79 | ||
|
|
07f1a9f43b | ||
|
|
002e550149 | ||
|
|
cc8dbeb3f0 | ||
|
|
e96fcd5f1b | ||
|
|
d5c87efea9 | ||
|
|
8044cee366 | ||
|
|
2bbbf14ea6 | ||
|
|
2737f9ae01 | ||
|
|
078d4623f9 | ||
|
|
593c170ee5 | ||
|
|
a0279bf8f1 | ||
|
|
dcda15a33c | ||
|
|
39ef48dbec | ||
|
|
c3d9c4525f | ||
|
|
039eb60c4b | ||
|
|
0a6aae5c97 | ||
|
|
08ffcfc50d | ||
|
|
c93db63297 | ||
|
|
36339154dc | ||
|
|
1648d65c47 | ||
|
|
815e426ecc | ||
|
|
f37454fe9b | ||
|
|
b79debc968 | ||
|
|
c2bb1ea80a | ||
|
|
1e9d647de8 | ||
|
|
774e75848a | ||
|
|
ebbb2d90ba | ||
|
|
77b43918f1 | ||
|
|
e505e91931 | ||
|
|
c9118b5abe | ||
|
|
9843c01904 | ||
|
|
4986266268 | ||
|
|
e629bffde8 | ||
|
|
6cf351bac5 | ||
|
|
e32c0bbf97 | ||
|
|
e5abea1474 | ||
|
|
3ae002db91 | ||
|
|
063ca17403 | ||
|
|
b84fd825b3 | ||
|
|
1732c84606 | ||
|
|
4573a9b494 | ||
|
|
8f29d7b8ea | ||
|
|
7156d90967 | ||
|
|
ec726e8c48 | ||
|
|
488403a86b | ||
|
|
59474d68cd | ||
|
|
5ab308bb9b | ||
|
|
bf3d6ad778 | ||
|
|
59356f210e | ||
|
|
42df02f718 | ||
|
|
8728126421 | ||
|
|
e0c36a9545 | ||
|
|
9a2bd1a6cc | ||
|
|
499edb402c | ||
|
|
14216ab98f | ||
|
|
95c10dacd4 |
@@ -37,3 +37,6 @@
|
||||
[submodule "ref/Facepunch.Steamworks"]
|
||||
path = ref/Facepunch.Steamworks
|
||||
url = https://github.com/BeyondDimension/Facepunch.Steamworks.git
|
||||
[submodule "ref/appcenter-sdk-dotnet"]
|
||||
path = ref/appcenter-sdk-dotnet
|
||||
url = https://github.com/BeyondDimension/appcenter-sdk-dotnet.git
|
||||
|
||||
@@ -214,10 +214,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facepunch.Steamworks.Posix"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steam++", "src\BD.WTTS.Client.AppHost.Bridge\Steam++.csproj", "{26D8AA24-2ACE-4167-BC2B-117B9BB76AA4}"
|
||||
EndProject
|
||||
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "BD.WTTS.Client.AppHost.Bridge.Package", "src\BD.WTTS.Client.AppHost.Bridge.Package\BD.WTTS.Client.AppHost.Bridge.Package.wapproj", "{27795C79-2994-4514-8656-BA34FCEE8901}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchiSteamFarm", "ref\ArchiSteamFarm\ArchiSteamFarm\ArchiSteamFarm.csproj", "{8C34FCD5-8C7F-4B10-A970-7DEA8A61F56B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AppCenter", "AppCenter", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BD.AppCenter.Any", "ref\appcenter-sdk-dotnet\SDK\AppCenter\BD.AppCenter.Any\BD.AppCenter.Any.csproj", "{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BD.AppCenter.Analytics.Any", "ref\appcenter-sdk-dotnet\SDK\AppCenterAnalytics\BD.AppCenter.Analytics.Any\BD.AppCenter.Analytics.Any.csproj", "{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -1232,36 +1236,6 @@ Global
|
||||
{26D8AA24-2ACE-4167-BC2B-117B9BB76AA4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{26D8AA24-2ACE-4167-BC2B-117B9BB76AA4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{26D8AA24-2ACE-4167-BC2B-117B9BB76AA4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|x64.Build.0 = Debug|x64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|x86.Build.0 = Debug|x86
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|ARM.Build.0 = Release|ARM
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|x64.ActiveCfg = Release|x64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|x64.Build.0 = Release|x64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|x64.Deploy.0 = Release|x64
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|x86.ActiveCfg = Release|x86
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|x86.Build.0 = Release|x86
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901}.Release|x86.Deploy.0 = Release|x86
|
||||
{8C34FCD5-8C7F-4B10-A970-7DEA8A61F56B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8C34FCD5-8C7F-4B10-A970-7DEA8A61F56B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C34FCD5-8C7F-4B10-A970-7DEA8A61F56B}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
@@ -1282,6 +1256,46 @@ Global
|
||||
{8C34FCD5-8C7F-4B10-A970-7DEA8A61F56B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8C34FCD5-8C7F-4B10-A970-7DEA8A61F56B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8C34FCD5-8C7F-4B10-A970-7DEA8A61F56B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -1347,8 +1361,10 @@ Global
|
||||
{638745C0-B699-4009-9764-05434C511403} = {99D97BD4-3F51-48BC-8BD2-647F6D268BB0}
|
||||
{35676E23-8E54-4785-A75B-98EB0650596B} = {99D97BD4-3F51-48BC-8BD2-647F6D268BB0}
|
||||
{26D8AA24-2ACE-4167-BC2B-117B9BB76AA4} = {5541B406-4A9A-4AC8-AA77-CE14E133DB80}
|
||||
{27795C79-2994-4514-8656-BA34FCEE8901} = {5541B406-4A9A-4AC8-AA77-CE14E133DB80}
|
||||
{8C34FCD5-8C7F-4B10-A970-7DEA8A61F56B} = {99D97BD4-3F51-48BC-8BD2-647F6D268BB0}
|
||||
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {90E88965-DB90-4B49-94F5-6D2965491988}
|
||||
{BD7E0AF0-FABE-3C94-DE36-CF365BF7323D} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{9611DBE7-EDF0-9EB0-EE93-B158981BE48F} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {567F588F-E95C-4286-8B30-DB3B2200221C}
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
default_base_path="$HOME/WattToolkit"
|
||||
base_path="$default_base_path"
|
||||
|
||||
# 检查是否以root身份执行
|
||||
if [ "$EUID" -eq 0 ]; then
|
||||
echo "此脚本不能以root身份执行。"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 循环直到用户输入有效路径或直接回车
|
||||
while true; do
|
||||
# 使用 zenity 提示用户选择安装路径或使用默认路径
|
||||
@@ -41,7 +47,45 @@ base_url="https://api.steampp.net"
|
||||
architecture=1
|
||||
app_name="Watt Toolkit"
|
||||
PROCESS_NAMES=("$exec_name" "$app_name")
|
||||
export LC_ALL=en_US.UTF-8
|
||||
Check_LC_Code() {
|
||||
# 检查当前 LANG 环境变量
|
||||
current_lang="${LC_ALL:-$LANG}"
|
||||
echo "当前语言环境: $current_lang"
|
||||
|
||||
# 检查是否为 C 或 C.UTF-8
|
||||
if [ "$current_lang" = "C" ] || [ "$current_lang" = "C.UTF-8" ]; then
|
||||
echo "当前语言环境是 C 或 C.UTF-8,需要修改。"
|
||||
|
||||
# 列出系统支持的语言环境
|
||||
supported_locales=$(locale -a)
|
||||
if [ -z "$supported_locales" ]; then
|
||||
echo "未能获取到支持的语言环境列表。请检查系统配置。"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 遍历支持的语言环境列表,找到第一个不是 C 或 C.UTF-8 的项
|
||||
first_non_c_locale=""
|
||||
for locale in $supported_locales; do
|
||||
if [ "$locale" != "C" ] && [ "$locale" != "C.UTF-8" ]; then
|
||||
first_non_c_locale="$locale"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# 检查是否找到了非 C/C.UTF-8 的语言环境
|
||||
if [ -n "$first_non_c_locale" ]; then
|
||||
echo "修改语言环境为支持列表中的第一个非 C/C.UTF-8 项:$first_non_c_locale"
|
||||
export LC_ALL="$first_non_c_locale"
|
||||
echo "语言环境已修改为 $first_non_c_locale。"
|
||||
else
|
||||
echo "未能找到非 C/C.UTF-8 的语言环境。请检查系统配置。"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
echo "当前语言环境不是 C 或 C.UTF-8,无需修改。"
|
||||
fi
|
||||
}
|
||||
Check_LC_Code
|
||||
Install_certutil() {
|
||||
# 判断发行版类型
|
||||
if command -v certutil &>/dev/null; then
|
||||
@@ -360,34 +404,44 @@ Kill_Process
|
||||
Decompression
|
||||
# xdg-icon-resource install "$base_path/Icons/Watt-Toolkit.png" --size 128 Watt-Toolkit
|
||||
InitDesktop() {
|
||||
# 检查XDG_DESKTOP_DIR环境变量,如果未设置则使用默认值
|
||||
XDG_DESKTOP_DIR="${XDG_DESKTOP_DIR:-$HOME/Desktop}"
|
||||
|
||||
while true; do
|
||||
# 使用 zenity 提示用户选择安装路径或使用默认路径
|
||||
choice=$(zenity --list --radiolist --title="请选择要添加到的位置" --column="选择" --column="路径" TRUE "$HOME/.local/share/applications/" FALSE "$HOME/Desktop")
|
||||
choice=$(zenity --list --radiolist --title="请选择要添加到的位置" \
|
||||
--column="选择" --column="路径" \
|
||||
TRUE "$XDG_DESKTOP_DIR" \
|
||||
FALSE "$HOME/.local/share/applications/")
|
||||
|
||||
# 检查用户输入
|
||||
if [ "$choice" == "$HOME/.local/share/applications/" ]; then
|
||||
target_dir="$HOME/.local/share/applications/"
|
||||
break
|
||||
elif [ "$choice" == "$HOME/Desktop" ]; then
|
||||
target_dir="$HOME/Desktop/"
|
||||
elif [ "$choice" == "$XDG_DESKTOP_DIR" ]; then
|
||||
target_dir="$XDG_DESKTOP_DIR"
|
||||
break
|
||||
else
|
||||
echo "无效选项,请输入 1 或 2。"
|
||||
# 无效选项时给出提示,并继续循环
|
||||
zenity --info --text="无效选项,请重新选择。"
|
||||
fi
|
||||
done
|
||||
#添加桌面文件
|
||||
|
||||
# 添加桌面文件
|
||||
rm -rf "$target_dir/Watt Toolkit.desktop" 2>/dev/null
|
||||
echo "#!/usr/bin/env xdg-open
|
||||
cat <<EOT > "$target_dir/Watt Toolkit.desktop"
|
||||
[Desktop Entry]
|
||||
Name=Watt Toolkit
|
||||
Exec=$base_path/$exec_name.sh
|
||||
Icon=$base_path/Icons/Watt-Toolkit.png
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=false" >"$target_dir/Watt Toolkit.desktop"
|
||||
StartupNotify=false
|
||||
EOT
|
||||
chmod +x "$target_dir/Watt Toolkit.desktop"
|
||||
|
||||
}
|
||||
|
||||
|
||||
InitDesktop
|
||||
# update-desktop-database ~/.local/share/applications
|
||||
#运行程序
|
||||
|
||||
@@ -997,6 +997,15 @@
|
||||
"Summary": "加速后自动唤起 Watt 加速器界面",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
},
|
||||
{
|
||||
"TypeName": "bool",
|
||||
"PropertyName": "ProxyBeforeDNSCheck",
|
||||
"DefaultValue": "true",
|
||||
"DefaultValueIsConst": true,
|
||||
"Summary": "加速前进行 DNS 可用性检查",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
}
|
||||
],
|
||||
"Usings": ""
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
# Steam++ v3.X Program File Structure for Windows
|
||||
|
||||
- dotnet 共享运行时,删除后将使用已安装的运行时,此目参考 ```C:\Program Files\dotnet```,可自行升级行库小版本号,二进制兼容
|
||||
- host
|
||||
- fxr
|
||||
- x.y.z
|
||||
- hostfxr.dll
|
||||
- shared
|
||||
- Microsoft.AspNetCore.App
|
||||
- x.y.z
|
||||
- Microsoft.NETCore.App
|
||||
- x.y.z
|
||||
- native
|
||||
- win-x64
|
||||
- 7z.dll
|
||||
- av_libglesv2.dll
|
||||
- e_sqlite3.dll
|
||||
- libHarfBuzzSharp.dll
|
||||
- libSkiaSharp.dll
|
||||
- WebView2Loader.dll
|
||||
- WinDivert.dll
|
||||
- WinDivert64.sys
|
||||
- assemblies 主模块程序集
|
||||
- modules 可选模块
|
||||
- ~~Update 自更新模块,删除该文件夹后禁用更新~~
|
||||
- Steam++.Update.exe 更新程序,CDN 分发更包,下载与解压在主程序中,此进程仅退出主程执行覆盖操作
|
||||
- Accelerator 网络加速
|
||||
- Steam++.Accelerator.exe 控制台子服务进,使用匿名管道与主进程通信,无参数或指定某参数(待定)启动时可读取配置文件启动加速,可全独立运行,ASP.NET Core Web API 项目,支持 Docker
|
||||
- Steam++.Plugins.Accelerator.dll 插件程集
|
||||
- AccountSwitch 账号切换
|
||||
- Steam++.Plugins.AccountSwitch.dll
|
||||
- ~~ArchiSteamFarm~~
|
||||
- Steam++.ArchiSteamFarm.exe
|
||||
- Steam++.Plugins.ArchiSteamFarm.dll
|
||||
- GameList 库存游戏
|
||||
- Steam++.Plugins.GameList.dll
|
||||
- LocalAuth 本地令牌
|
||||
- Steam++.Plugins.LocalAuth.dll
|
||||
- GameTools 游戏工具
|
||||
- Steam++.Plugins.GameTools.dll
|
||||
- Steam++.exe (主启动程序).NET Framework 二进制主程序
|
||||
- Steam++.exe.config 使用该配置文件以允许在 .NET Framework 3.5 ~ 4.8.1 中任意版本中兼容运行(从 Windows 7 ~ 11 中所有系统自带运行时)
|
||||
- ~~Steam++.Uninstall.exe 卸载程序(WinForms?AOT?)~~
|
||||
@@ -16,14 +16,14 @@ public static partial class AssemblyInfo
|
||||
/// <summary>
|
||||
/// 预览版本号,范围 1~9,只增不减
|
||||
/// </summary>
|
||||
const string ver_for_preview = "9";
|
||||
const string ver_for_preview = "0";
|
||||
|
||||
/// <summary>
|
||||
/// RC 版本号,范围 0~9,只增不减
|
||||
/// </summary>
|
||||
const string ver_for_rc = "11";
|
||||
const string ver_for_rc = "15";
|
||||
|
||||
public const string FileVersion = $"{Version2}.{ver_for_rc}1{ver_for_preview}.0";
|
||||
public const string FileVersion = $"{Version2}.{ver_for_rc}2{ver_for_preview}.0";
|
||||
|
||||
//public const string InformationalVersion = Version;
|
||||
//public const string InformationalVersion = $"{Version}-preview.{ver_for_preview}";
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Avalonia.Controls;
|
||||
public static class AvaloniaControlsInternalsWindowExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void CloseCore_(this Window window, WindowCloseReason reason, bool isProgrammatic) => window.CloseCore(reason, isProgrammatic);
|
||||
public static void CloseCore_(this Window window, WindowCloseReason reason, bool isProgrammatic, bool ignoreCancel) => window.CloseCore(reason, isProgrammatic, ignoreCancel);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void HandleResized_(this Window window, Size clientSize, WindowResizeReason reason) => window.HandleResized(clientSize, reason);
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace Avalonia.Controls.ApplicationLifetimes
|
||||
{
|
||||
if (w.Owner is null)
|
||||
{
|
||||
w.CloseCore_(WindowCloseReason.ApplicationShutdown, isProgrammatic);
|
||||
w.CloseCore_(WindowCloseReason.ApplicationShutdown, isProgrammatic, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 190 B |
|
Before Width: | Height: | Size: 218 B |
|
Before Width: | Height: | Size: 231 B |
|
Before Width: | Height: | Size: 279 B |
|
Before Width: | Height: | Size: 444 B |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 666 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 666 B |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 484 B |
|
Before Width: | Height: | Size: 787 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
@@ -1,83 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
|
||||
xmlns:desktop2="http://schemas.microsoft.com/appx/manifest/desktop/windows10/2"
|
||||
IgnorableNamespaces="uap rescap desktop desktop2">
|
||||
|
||||
<Identity
|
||||
Name="4651ED44255E.47979655102CE"
|
||||
Publisher="CN=A90E406B-B2D3-4A23-B061-0FA1D65C4F66"
|
||||
Version="3.0.207.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>Watt Toolkit</DisplayName>
|
||||
<PublisherDisplayName>软妹币玩家</PublisherDisplayName>
|
||||
<Logo>Images\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="x-generate"/>
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="App"
|
||||
Executable="$targetnametoken$.exe"
|
||||
EntryPoint="$targetentrypoint$">
|
||||
<uap:VisualElements
|
||||
DisplayName="Watt Toolkit"
|
||||
Description="「Watt Toolkit」是一个开源跨平台的多功能游戏工具箱,此工具的大部分功能都是需要您下载安装 Steam 才能使用。"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Images\Square150x150Logo.png"
|
||||
Square44x44Logo="Images\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png" ShortName="Steam++">
|
||||
<uap:ShowNameOnTiles>
|
||||
<uap:ShowOn Tile="square150x150Logo"/>
|
||||
<uap:ShowOn Tile="wide310x150Logo"/>
|
||||
<uap:ShowOn Tile="square310x310Logo"/>
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile >
|
||||
<uap:SplashScreen Image="Images\SplashScreen.png" />
|
||||
<uap:InitialRotationPreference>
|
||||
<uap:Rotation Preference="landscape"/>
|
||||
</uap:InitialRotationPreference>
|
||||
<uap:LockScreen BadgeLogo="Images\BadgeLogo.png" Notification="badgeAndTileText"/>
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
<desktop:Extension Category="windows.fullTrustProcess" Executable="Steam++\Steam++.exe" />
|
||||
<desktop:Extension Category="windows.startupTask" Executable="Steam++\Steam++.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<desktop:StartupTask TaskId="BootAutoStartTask" Enabled="true" DisplayName="Steam++ System Boot Run" />
|
||||
</desktop:Extension>
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="spp">
|
||||
<uap:Logo>Images\Square44x44Logo.png</uap:Logo>
|
||||
<uap:DisplayName>Steam++ URI Scheme</uap:DisplayName>
|
||||
</uap:Protocol>
|
||||
</uap:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Extensions>
|
||||
<desktop2:Extension Category="windows.firewallRules">
|
||||
<desktop2:FirewallRules Executable="Steam++\modules\Accelerator\Steam++.Accelerator.exe">
|
||||
<desktop2:Rule Direction="in" IPProtocol="TCP" Profile="all"/>
|
||||
<desktop2:Rule Direction="in" IPProtocol="UDP" Profile="all"/>
|
||||
</desktop2:FirewallRules>
|
||||
</desktop2:Extension>
|
||||
</Extensions>
|
||||
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
<rescap:Capability Name="allowElevation" />
|
||||
</Capabilities>
|
||||
</Package>
|
||||
@@ -10,6 +10,6 @@
|
||||
<legacyCorruptedStateExceptionsPolicy enabled="true"/>
|
||||
</runtime>
|
||||
<appSettings>
|
||||
<add key="d" value="8.0.0"/>
|
||||
<add key="d" value="9.0.0"/>
|
||||
</appSettings>
|
||||
</configuration>
|
||||
@@ -16,7 +16,7 @@ static unsafe partial class Program
|
||||
{
|
||||
static Program()
|
||||
{
|
||||
dotnet_version_major = "8";
|
||||
dotnet_version_major = "9";
|
||||
dotnet_version_minor = "0";
|
||||
dotnet_version_build = "0";
|
||||
dotnet_version = $"{dotnet_version_major}.{dotnet_version_minor}.{dotnet_version_build}";
|
||||
@@ -426,8 +426,8 @@ static unsafe partial class Program
|
||||
if (!File.Exists(config_path) || !File.Exists(dotnetlib_path))
|
||||
{
|
||||
#if DEBUG
|
||||
config_path = string.Join(Path.DirectorySeparatorChar.ToString(), new[] { ProjectUtils.ProjPath, "src", "BD.WTTS.Client.Avalonia.App", "bin", "Debug", $"net{dotnet_version_major}.{dotnet_version_minor}-windows10.0.19041.0", $"{dotnet_dll_name}.runtimeconfig.json" });
|
||||
dotnetlib_path = string.Join(Path.DirectorySeparatorChar.ToString(), new[] { ProjectUtils.ProjPath, "src", "BD.WTTS.Client.Avalonia.App", "bin", "Debug", $"net{dotnet_version_major}.{dotnet_version_minor}-windows10.0.19041.0", $"{dotnet_dll_name}.dll" });
|
||||
config_path = string.Join(Path.DirectorySeparatorChar.ToString(), new[] { ProjectUtils.ProjPath, "src", "BD.WTTS.Client.Avalonia.App", "bin", "Debug", $"net{dotnet_version_major}.{dotnet_version_minor}-windows10.0.19041", $"{dotnet_dll_name}.runtimeconfig.json" });
|
||||
dotnetlib_path = string.Join(Path.DirectorySeparatorChar.ToString(), new[] { ProjectUtils.ProjPath, "src", "BD.WTTS.Client.Avalonia.App", "bin", "Debug", $"net{dotnet_version_major}.{dotnet_version_minor}-windows10.0.19041", $"{dotnet_dll_name}.dll" });
|
||||
#else
|
||||
ShowErrMessageBox($"Loading assembly failed \"{dotnetlib_path}\"");
|
||||
return (int)ExitCode.EntryPointFileNotFound;
|
||||
|
||||
@@ -95,31 +95,37 @@
|
||||
<ProjectReference Include="..\BD.WTTS.Client\BD.WTTS.Client.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' AND Exists('$(NugetPackageRoot)\system.drawing.common\$(Version_System_Drawing_Common)\lib\net8.0\System.Drawing.Common.dll')">
|
||||
<!-- Windows Only -->
|
||||
<!-- 修复:存在 Microsoft.WindowsDesktop.App 依赖时不会将 System.Drawing.Common.dll 复制到输出目录-->
|
||||
<None Include="$(NugetPackageRoot)\system.drawing.common\$(Version_System_Drawing_Common)\lib\net8.0\System.Drawing.Common.dll">
|
||||
<!--<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' AND Exists('$(NugetPackageRoot)\system.drawing.common\$(Version_System_Drawing_Common)\lib\net9.0\System.Drawing.Common.dll')">
|
||||
--><!-- Windows Only --><!--
|
||||
--><!-- 修复:存在 Microsoft.WindowsDesktop.App 依赖时不会将 System.Drawing.Common.dll 复制到输出目录--><!--
|
||||
<None Include="$(NugetPackageRoot)\system.drawing.common\$(Version_System_Drawing_Common)\lib\net9.0\System.Drawing.Common.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Reference Include="System.Drawing.Common">
|
||||
<HintPath>$(NugetPackageRoot)\system.drawing.common\$(Version_System_Drawing_Common)\lib\net8.0\System.Drawing.Common.dll</HintPath>
|
||||
<HintPath>$(NugetPackageRoot)\system.drawing.common\$(Version_System_Drawing_Common)\lib\net9.0\System.Drawing.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<None Include="$(NugetPackageRoot)\microsoft.win32.systemevents\9.0.0\runtimes\win\lib\net9.0\Microsoft.Win32.SystemEvents.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Reference Include="Microsoft.Win32.SystemEvents">
|
||||
<HintPath>$(NugetPackageRoot)\microsoft.win32.systemevents\9.0.0\runtimes\win\lib\net9.0\Microsoft.Win32.SystemEvents.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' AND Exists('$(NugetPackageRoot)\splat.drawing\$(Version_Splat_Drawing)\lib\net7.0\Splat.Drawing.dll')">
|
||||
<!-- Windows Only -->
|
||||
<!-- 修复:Splat.Drawing 包存在 WPF 的依赖项 -->
|
||||
--><!-- Windows Only --><!--
|
||||
--><!-- 修复:Splat.Drawing 包存在 WPF 的依赖项 --><!--
|
||||
<PackageReference Include="Splat.Drawing">
|
||||
<ExcludeAssets>all</ExcludeAssets>
|
||||
</PackageReference>
|
||||
<Reference Include="Splat.Drawing">
|
||||
<HintPath>$(NugetPackageRoot)\splat.drawing\$(Version_Splat_Drawing)\lib\net7.0\Splat.Drawing.dll</HintPath>
|
||||
</Reference>
|
||||
<!-- 修复:System.Reactive 包存在 System.Windows.Forms 的依赖项 -->
|
||||
--><!-- 修复:System.Reactive 包存在 System.Windows.Forms 的依赖项 --><!--
|
||||
<Reference Include="System.Reactive">
|
||||
<HintPath>$(NugetPackageRoot)\system.reactive\$(Version_System_Reactive)\lib\net6.0\System.Reactive.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</ItemGroup>-->
|
||||
|
||||
<Import Project="..\TFM_NETX_WITH_DESKTOP.props" />
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>Watt Toolkit</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Watt Toolkit</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>3.0.0.0</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.15</string>
|
||||
<string>3.0.1219.0</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
@@ -175,6 +175,10 @@ partial class Program
|
||||
{
|
||||
RenderingMode = GetRenderingMode().ToArray(),
|
||||
});
|
||||
builder.With(new MacOSPlatformOptions
|
||||
{
|
||||
DisableDefaultApplicationMenuItems = true,
|
||||
});
|
||||
#elif LINUX
|
||||
builder.With(new X11PlatformOptions
|
||||
{
|
||||
|
||||
@@ -54,8 +54,11 @@ sealed class AvaloniaToastServiceImpl : IToastService
|
||||
}
|
||||
}
|
||||
|
||||
var notificationType = GetNotificationType(icon);
|
||||
NotificationManager.Show(text, notificationType: notificationType);
|
||||
if (NotificationManager != null)
|
||||
{
|
||||
var notificationType = GetNotificationType(icon);
|
||||
NotificationManager.Show(text, notificationType: notificationType);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Show(string, int?)"/>
|
||||
|
||||
@@ -13,8 +13,16 @@ public sealed partial class App : Application
|
||||
|
||||
public App()
|
||||
{
|
||||
Name = AssemblyInfo.Trademark;
|
||||
OpenBrowserCommand = ReactiveCommand.Create<object?>(OpenBrowserCommandCore);
|
||||
CopyToClipboardCommand = ReactiveCommand.Create<object?>(CopyToClipboardCommandCore);
|
||||
#if MACOS
|
||||
var menus = new NativeMenu();
|
||||
menus.Add(new NativeMenuItem { Header = Strings.Settings, Command = ReactiveCommand.Create(() => { INavigationService.Instance.Navigate(typeof(SettingsPage)); }) });
|
||||
menus.Add(new NativeMenuItemSeparator());
|
||||
menus.Add(new NativeMenuItem { Header = Strings.Exit, Command = ReactiveCommand.Create(() => { Shutdown(); }) });
|
||||
NativeMenu.SetMenu(this, menus);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -76,7 +84,7 @@ public sealed partial class App : Application
|
||||
Log.Error(nameof(Steamworks), ex, "Steamworks.SteamClient Init");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -111,6 +119,12 @@ public sealed partial class App : Application
|
||||
{
|
||||
Task2.InBackground(() => appWindow.SplashScreen?.RunTasks(CancellationToken.None));
|
||||
}
|
||||
|
||||
IPlatformService.Instance.SetSystemSessionEnding(() =>
|
||||
{
|
||||
Log.Info("System Shutdown", "Application SafeExit...");
|
||||
Shutdown();
|
||||
});
|
||||
}
|
||||
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleView)
|
||||
{
|
||||
@@ -246,8 +260,8 @@ public sealed partial class App : Application
|
||||
try
|
||||
{
|
||||
Uri uri = new(urlString);
|
||||
if (uri.Host.EndsWith("steampp.net", StringComparison.OrdinalIgnoreCase) ||
|
||||
uri.Host.EndsWith("mossimo.net", StringComparison.OrdinalIgnoreCase))
|
||||
if (uri.Host.EndsWith(Constants.Urls.OfficialWebsiteHost, StringComparison.OrdinalIgnoreCase) &&
|
||||
uri.Query.EndsWith(Constants.Urls.Komaasharu_IsAuthQuery, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await UserService.Current.OpenAuthUrl(urlString);
|
||||
return;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ms="https://steampp.net/settings"
|
||||
xmlns:sys="using:System"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
x:CompileBindings="True">
|
||||
<Styles.Resources>
|
||||
<ResourceDictionary>
|
||||
@@ -39,6 +40,14 @@
|
||||
<Setter Property="FontFamily" Value="{Binding Source={x:Static ms:UISettings.FontName}, Path=Value, Mode=OneWay, Converter={StaticResource NameToFontFamilyConverter}}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|FontIcon">
|
||||
<Setter Property="MinWidth" Value="16" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SymbolIcon">
|
||||
<Setter Property="MinWidth" Value="16" />
|
||||
</Style>
|
||||
|
||||
<!--<Style Selector="TextBlock">
|
||||
<Setter Property="FontFamily" Value="{Binding Source={x:Static ms:UISettings.FontName}, Path=Value, Mode=OneWay, Converter={StaticResource NameToFontFamilyConverter}}" />
|
||||
</Style>-->
|
||||
|
||||
@@ -91,6 +91,12 @@
|
||||
CommandParameter="{Binding Data.AssemblyLocation}"
|
||||
Content="{Binding Path=Res.Plugin_OpenFolder, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
IsClickEnabled="True" />
|
||||
<ui:SettingsExpanderItem
|
||||
ActionIconSource="Open"
|
||||
Command="{Binding $parent[spp:Settings_Plugin].((spp:SettingsPageViewModel)DataContext).OpenPluginCacheDirectory_Click}"
|
||||
CommandParameter="{Binding Data.AppDataDirectory}"
|
||||
Content="{Binding Path=Res.Plugin_OpenAppDataFolder, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
IsClickEnabled="True" />
|
||||
<ui:SettingsExpanderItem
|
||||
ActionIconSource="Open"
|
||||
Command="{Binding $parent[spp:Settings_Plugin].((spp:SettingsPageViewModel)DataContext).OpenPluginCacheDirectory_Click}"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<RootNamespace>BD.WTTS</RootNamespace>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<SelfContained>false</SelfContained>
|
||||
<DefineConstants>APP_REVERSE_PROXY;NONE_UI;REMOVE_DNS_INTERCEPT;$(DefineConstants)</DefineConstants>
|
||||
<DefineConstants>APP_REVERSE_PROXY;NONE_UI;$(DefineConstants)</DefineConstants>
|
||||
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ sealed partial class CertificateManagerImpl : ICertificateManager
|
||||
|
||||
bool SharedCreateRootCertificate()
|
||||
{
|
||||
RootCertificate ??= LoadRootCertificate();
|
||||
RootCertificate = LoadRootCertificate();
|
||||
|
||||
if (RootCertificate != null)
|
||||
{
|
||||
|
||||
@@ -83,7 +83,7 @@ sealed class CertService
|
||||
entry.SetAbsoluteExpiration(notAfter);
|
||||
|
||||
var subjectName = new X500DistinguishedName($"CN={domain}");
|
||||
using var serverCert = CertGenerator.CreateEndCertificate(caCert, subjectName, GetDomains(), notBefore, notAfter);
|
||||
using var serverCert = CertGenerator.CreateEndCertificate(caCert, subjectName, GetDomains());
|
||||
var serverCertPfx = serverCert.Export(X509ContentType.Pfx);
|
||||
// 将生成的证书导出后重新创建一个
|
||||
return new X509Certificate2(serverCertPfx);
|
||||
|
||||
@@ -84,7 +84,7 @@ sealed partial class HttpReverseProxyMiddleware
|
||||
!reverseProxyConfig.Service.OnlyEnableProxyScript)
|
||||
{
|
||||
// 部分运营商将奇怪的域名解析到 127.0.0.1 再此排除这些不支持的代理域名
|
||||
var ip = await reverseProxyConfig.DnsAnalysis.AnalysisDomainIpAsync(context.Request.Host.Value, IDnsAnalysisService.DNS_Dnspods).FirstOrDefaultAsync();
|
||||
var ip = await reverseProxyConfig.DnsAnalysis.AnalysisDomainIpAsync(context.Request.Host.Value!, IDnsAnalysisService.DNS_Dnspods).FirstOrDefaultAsync();
|
||||
if (ip == null || IPAddress.IsLoopback(ip))
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||
|
||||
@@ -47,9 +47,55 @@ sealed partial class YarpReverseProxyServiceImpl : ReverseProxyServiceImpl, IRev
|
||||
ICertificateManager.Constants.CheckRootCertificate(
|
||||
platformService,
|
||||
CertificateManager);
|
||||
|
||||
try
|
||||
{
|
||||
X509Certificate2? cer = CertificateManager.RootCertificatePackable;
|
||||
if (cer is not null &&
|
||||
DateTime.Now <= cer.NotAfter && cer.NotAfter <= DateTime.Now.AddMilliseconds(int.MaxValue))
|
||||
{
|
||||
var interval = cer.NotAfter - DateTime.Now;
|
||||
|
||||
_certificateTimer = new System.Timers.Timer(interval)
|
||||
{
|
||||
AutoReset = false,
|
||||
};
|
||||
|
||||
_certificateTimer.Elapsed += async (_, _) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
ICertificateManager.Constants.CheckRootCertificate(
|
||||
platformService,
|
||||
CertificateManager);
|
||||
|
||||
await StopProxyAsync();
|
||||
await StartProxyImpl();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.LogAndShowT(TAG, msg: "CheckRootCertificate in Timer.Elapsed Error");
|
||||
}
|
||||
};
|
||||
_certificateTimer.Start();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.LogAndShowT(TAG, msg: "CheckRootCertificate Error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private System.Timers.Timer? _certificateTimer;
|
||||
|
||||
private void StopCertificateTimer()
|
||||
{
|
||||
_certificateTimer?.Stop();
|
||||
_certificateTimer?.Dispose();
|
||||
_certificateTimer = null;
|
||||
}
|
||||
|
||||
protected override Task<StartProxyResult> StartProxyImpl() => Task.FromResult(StartProxyCore());
|
||||
|
||||
StartProxyResult StartProxyCore()
|
||||
@@ -153,6 +199,7 @@ sealed partial class YarpReverseProxyServiceImpl : ReverseProxyServiceImpl, IRev
|
||||
|
||||
public async Task StopProxyAsync()
|
||||
{
|
||||
StopCertificateTimer();
|
||||
Scripts = null;
|
||||
if (app == null) return;
|
||||
await app.StopAsync();
|
||||
|
||||
@@ -196,6 +196,11 @@ public interface ICertificateManager
|
||||
// 生成证书
|
||||
certificateManager.GenerateCertificate();
|
||||
|
||||
packable = GetRootCertificatePackable();
|
||||
certificate2 = packable;
|
||||
if (certificate2 == null)
|
||||
return StartProxyResultCode.GetX509Certificate2Fail;
|
||||
|
||||
// 安装证书
|
||||
ICertificateManager.Constants.TrustRootCertificate(
|
||||
GetCerFilePath, platformService, certificate2);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<RootNamespace>BD.WTTS</RootNamespace>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>WTTS_PLUGIN;WTTS_PLUGIN_ACCELERATOR;REMOVE_DNS_INTERCEPT;$(DefineConstants)</DefineConstants>
|
||||
<DefineConstants>WTTS_PLUGIN;WTTS_PLUGIN_ACCELERATOR;$(DefineConstants)</DefineConstants>
|
||||
<!--<EnableDynamicLoading>true</EnableDynamicLoading>-->
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -345,7 +345,8 @@ internal partial class NetworkTestService : INetworkTestService
|
||||
)
|
||||
{
|
||||
using UdpClient udpClient = new UdpClient(dnsServerIp, dnsServerPort);
|
||||
|
||||
udpClient.Client.SendTimeout = 3000;
|
||||
udpClient.Client.ReceiveTimeout = 3000;
|
||||
var query = new DnsQueryUdpRequest(testDomain, dnsRecordType);
|
||||
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
@@ -382,7 +383,7 @@ internal partial class NetworkTestService : INetworkTestService
|
||||
Proxy = HttpNoProxy.Instance,
|
||||
};
|
||||
using HttpClient client = new HttpClient(handler);
|
||||
|
||||
client.Timeout = TimeSpan.FromSeconds(3);
|
||||
string queryUrl = $"{dohServer}?name={testDomain}&type={dnsRecordType}";
|
||||
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Threading;
|
||||
using BD.Common.Models;
|
||||
using BD.WTTS.Helpers;
|
||||
using BD.WTTS.UI.Views.Controls;
|
||||
using BD.WTTS.UI.Views.Pages;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
@@ -52,7 +53,7 @@ public sealed partial class GameAcceleratorService
|
||||
[Reactive]
|
||||
public DateTime? VipEndTime { get; set; }
|
||||
|
||||
const string VipEndTimeStringDef = "新用户免费试用 2 天";
|
||||
const string VipEndTimeStringDef = "新用户免费试用";
|
||||
|
||||
[Reactive]
|
||||
public string? VipEndTimeString { get; set; } = VipEndTimeStringDef;
|
||||
@@ -306,6 +307,7 @@ public sealed partial class GameAcceleratorService
|
||||
Games.AddOrUpdate(CurrentAcceleratorGame);
|
||||
|
||||
//加速后
|
||||
TracepointHelper.TrackEvent("AcceleratorGameSuccess");
|
||||
Toast.Show(ToastIcon.Success, "加速成功");
|
||||
if (ProxySettings.AutoShowWattAcceleratorWindow.Value)
|
||||
{
|
||||
@@ -353,9 +355,16 @@ public sealed partial class GameAcceleratorService
|
||||
if (UserService.Current.User?.WattOpenId == null)
|
||||
{
|
||||
Toast.Show(ToastIcon.Warning, "需要登录账号才能使用游戏加速功能!");
|
||||
UserService.Current.ShowWindow();
|
||||
app.IsAccelerating = false;
|
||||
return;
|
||||
}
|
||||
|
||||
TracepointHelper.TrackEvent(nameof(GameAccelerator), new Dictionary<string, string> {
|
||||
{ "GameId", app.Id.ToString() },
|
||||
{ "GameName", app.Name ?? string.Empty },
|
||||
});
|
||||
|
||||
var xunYouIsInstall = await Ioc.Get<IAcceleratorService>().XY_IsInstall();
|
||||
if (xunYouIsInstall.HandleUI(out var isInstall))
|
||||
{
|
||||
@@ -604,6 +613,7 @@ public sealed partial class GameAcceleratorService
|
||||
Toast.Show(ToastIcon.Info, "已安装Watt加速器");
|
||||
return;
|
||||
}
|
||||
TracepointHelper.TrackEvent("DownloadInstallAccelerator");
|
||||
var td = new TaskDialog
|
||||
{
|
||||
Title = "下载插件",
|
||||
@@ -619,44 +629,45 @@ public sealed partial class GameAcceleratorService
|
||||
};
|
||||
var install = Ioc.Get<IAcceleratorService>().XY_Install(GameAcceleratorSettings.WattAcceleratorDirPath.Value!);
|
||||
|
||||
td.Opened += async (s, e) =>
|
||||
td.Opened += (s, e) =>
|
||||
{
|
||||
await foreach (var item in install)
|
||||
{
|
||||
if (item.HandleUI(out var content))
|
||||
{
|
||||
switch (content)
|
||||
{
|
||||
case < 100:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"正在下载 {item.Content}%"; });
|
||||
td.SetProgressBarState(item.Content, TaskDialogProgressState.Normal);
|
||||
break;
|
||||
case 100:
|
||||
td.SetProgressBarState(item.Content, TaskDialogProgressState.Indeterminate);
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"下载完成,正在安装..."; });
|
||||
break;
|
||||
case (int)XunYouDownLoadCode.安装成功:
|
||||
//处理成功
|
||||
//Dispatcher.UIThread.Post(() => { td.Content = $"安装完成"; });
|
||||
Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
td.Hide();
|
||||
break;
|
||||
case int n when n > 101 && n < (int)XunYouDownLoadCode.启动安装程序失败:
|
||||
//处理失败
|
||||
break;
|
||||
// Code 和进度重叠 递进 1000 XunYouInstallOrStartCode.默认 XunYouInstallOrStartCode.已安装
|
||||
case 1000:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"默认"; });
|
||||
// XunYouInstallOrStartCode.默认
|
||||
break;
|
||||
case 1001:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"已安装"; });
|
||||
// XunYouInstallOrStartCode.已安装
|
||||
Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
DownloadCallbackAsync(td, install).Wait();
|
||||
//await foreach (var item in install)
|
||||
//{
|
||||
// if (item.HandleUI(out var content))
|
||||
// {
|
||||
// switch (content)
|
||||
// {
|
||||
// case < 100:
|
||||
// Dispatcher.UIThread.Post(() => { td.Content = $"正在下载 {item.Content}%"; });
|
||||
// td.SetProgressBarState(item.Content, TaskDialogProgressState.Normal);
|
||||
// break;
|
||||
// case 100:
|
||||
// td.SetProgressBarState(item.Content, TaskDialogProgressState.Indeterminate);
|
||||
// Dispatcher.UIThread.Post(() => { td.Content = $"下载完成,正在安装..."; });
|
||||
// break;
|
||||
// case (int)XunYouDownLoadCode.安装成功:
|
||||
// //处理成功
|
||||
// //Dispatcher.UIThread.Post(() => { td.Content = $"安装完成"; });
|
||||
// Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
// td.Hide();
|
||||
// break;
|
||||
// case int n when n > 101 && n < (int)XunYouDownLoadCode.启动安装程序失败:
|
||||
// //处理失败
|
||||
// break;
|
||||
// // Code 和进度重叠 递进 1000 XunYouInstallOrStartCode.默认 XunYouInstallOrStartCode.已安装
|
||||
// case 1000:
|
||||
// Dispatcher.UIThread.Post(() => { td.Content = $"默认"; });
|
||||
// // XunYouInstallOrStartCode.默认
|
||||
// break;
|
||||
// case 1001:
|
||||
// Dispatcher.UIThread.Post(() => { td.Content = $"已安装"; });
|
||||
// // XunYouInstallOrStartCode.已安装
|
||||
// Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
};
|
||||
|
||||
//_ = Task.Run(() => { XunYouSDK.InstallAsync(progress, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WattAccelerator")); });
|
||||
@@ -665,6 +676,47 @@ public sealed partial class GameAcceleratorService
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task DownloadCallbackAsync(TaskDialog td, IAsyncEnumerable<ApiRsp<int>> install)
|
||||
{
|
||||
await foreach (var item in install)
|
||||
{
|
||||
if (item.HandleUI(out var content))
|
||||
{
|
||||
switch (content)
|
||||
{
|
||||
case < 100:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"正在下载 {item.Content}%"; });
|
||||
td.SetProgressBarState(item.Content, TaskDialogProgressState.Normal);
|
||||
break;
|
||||
case 100:
|
||||
td.SetProgressBarState(item.Content, TaskDialogProgressState.Indeterminate);
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"下载完成,正在安装..."; });
|
||||
break;
|
||||
case (int)XunYouDownLoadCode.安装成功:
|
||||
//处理成功
|
||||
//Dispatcher.UIThread.Post(() => { td.Content = $"安装完成"; });
|
||||
TracepointHelper.TrackEvent("DownloadInstallSuccess");
|
||||
Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
td.Hide();
|
||||
break;
|
||||
case int n when n > 101 && n < (int)XunYouDownLoadCode.启动安装程序失败:
|
||||
//处理失败
|
||||
break;
|
||||
// Code 和进度重叠 递进 1000 XunYouInstallOrStartCode.默认 XunYouInstallOrStartCode.已安装
|
||||
case 1000:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"默认"; });
|
||||
// XunYouInstallOrStartCode.默认
|
||||
break;
|
||||
case 1001:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"已安装"; });
|
||||
// XunYouInstallOrStartCode.已安装
|
||||
Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async void UninstallAccelerator()
|
||||
{
|
||||
var xunYouIsInstall = await Ioc.Get<IAcceleratorService>().XY_IsInstall();
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
// ReSharper disable once CheckNamespace
|
||||
using BD.WTTS.Helpers;
|
||||
using BD.WTTS.Services.Implementation;
|
||||
|
||||
namespace BD.WTTS.Services;
|
||||
|
||||
partial class ProxyService
|
||||
@@ -36,10 +39,15 @@ partial class ProxyService
|
||||
Toast.Show(ToastIcon.Warning, Strings.CommunityFix_AccEmpty);
|
||||
}
|
||||
|
||||
TracepointHelper.TrackEvent("StartProxy", new Dictionary<string, string> {
|
||||
{ "ProxyType", ProxySettings.ProxyMode.Value.ToString() },
|
||||
{ "ProxyScriptStatus", ProxySettings.IsEnableScript.Value.ToString() },
|
||||
});
|
||||
|
||||
IReadOnlyCollection<ScriptIPCDTO>? scripts = default;
|
||||
bool isEnableScript = ProxySettings.IsEnableScript.Value;
|
||||
bool isOnlyWorkSteamBrowser = ProxySettings.IsOnlyWorkSteamBrowser.Value;
|
||||
ushort proxyPort = ProxySettings.SystemProxyPortId.Value;
|
||||
ushort proxyPort = ProxySettings.SystemProxyPortId.Value == 0 ? ProxySettings.SystemProxyPortId.Default : ProxySettings.SystemProxyPortId.Value;
|
||||
string? proxyIp = ProxySettings.SystemProxyIp.Value;
|
||||
proxyMode = defaultProxyMode;
|
||||
bool isProxyGOG = ProxySettings.IsProxyGOG.Value;
|
||||
@@ -66,6 +74,18 @@ partial class ProxyService
|
||||
bool useDoh = ProxySettings.UseDoh.Value;
|
||||
string? customDohAddres = ProxySettings.CustomDohAddres2.Value;
|
||||
|
||||
if (ProxySettings.ProxyBeforeDNSCheck.Value)
|
||||
{
|
||||
if (useDoh)
|
||||
{
|
||||
customDohAddres = await GetFastestDNSAsync(ProxySettingsWindowViewModel.DohAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
proxyDNS = await GetFastestDNSAsync(ProxySettingsWindowViewModel.ProxyDNSs.Skip(1));
|
||||
}
|
||||
}
|
||||
|
||||
Lazy<IPAddress> proxyIp_ = new(() => ReverseProxySettings.GetProxyIp(proxyIp));
|
||||
void SetProxyIp(IPAddress proxyIPAddress)
|
||||
{
|
||||
@@ -456,4 +476,69 @@ partial class ProxyService
|
||||
return proxyStatus;
|
||||
}
|
||||
}
|
||||
|
||||
async Task<(long delayMs, string dns)> GetValidDNSAsync(string dns, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var testDomain = "dnscheck-test.steampp.net";
|
||||
try
|
||||
{
|
||||
long delayMs;
|
||||
IPAddress[] address;
|
||||
if (ProxySettings.UseDoh.Value)
|
||||
{
|
||||
(delayMs, address) = await INetworkTestService.Instance.TestDNSOverHttpsAsync(testDomain, dns, cancellationToken: cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
(delayMs, address) = await INetworkTestService.Instance.TestDNSAsync(testDomain, dns, 53, cancellationToken: cancellationToken);
|
||||
}
|
||||
if (address.Length == 0)
|
||||
throw new Exception("Parsing failed. Return empty ip address.");
|
||||
|
||||
return (delayMs, dns);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(StartOrStopProxyService), ex.ToString(), "DNS检测出错");
|
||||
return (0, dns);
|
||||
}
|
||||
}
|
||||
|
||||
async Task<string?> GetFastestDNSAsync(IEnumerable<string> dnsAddresses, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
var tasks = new List<Task<(long delayMs, string dns)>>();
|
||||
|
||||
foreach (var dns in dnsAddresses)
|
||||
{
|
||||
tasks.Add(GetValidDNSAsync(dns, cts.Token));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 等待任意一个任务完成
|
||||
var completedTask = await Task.WhenAny(tasks);
|
||||
|
||||
// 获取任务结果
|
||||
var (delayMs, dns) = await completedTask;
|
||||
_ = cts.CancelAsync(); // 取消其他任务
|
||||
|
||||
// 如果任务成功完成(假设 delayMs > 0 表示成功)
|
||||
if (delayMs > 0)
|
||||
{
|
||||
return dns; // 返回第一个成功的 DNS 地址
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 任务被取消,忽略
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(StartOrStopProxyService), ex.ToString(), "DNS检测出错");
|
||||
}
|
||||
|
||||
// 如果没有有效结果,返回默认值
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
// ReSharper disable once CheckNamespace
|
||||
using Avalonia.Data;
|
||||
using BD.WTTS.Helpers;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Org.BouncyCastle.Bcpg.OpenPgp;
|
||||
using System.Linq;
|
||||
|
||||
@@ -165,6 +165,11 @@ public partial interface IProxySettings
|
||||
/// </summary>
|
||||
bool AutoShowWattAcceleratorWindow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 加速前进行 DNS 可用性检查
|
||||
/// </summary>
|
||||
bool ProxyBeforeDNSCheck { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 启用脚本自动检查更新的默认值
|
||||
/// </summary>
|
||||
@@ -290,4 +295,9 @@ public partial interface IProxySettings
|
||||
/// </summary>
|
||||
const bool DefaultAutoShowWattAcceleratorWindow = true;
|
||||
|
||||
/// <summary>
|
||||
/// 加速前进行 DNS 可用性检查的默认值
|
||||
/// </summary>
|
||||
const bool DefaultProxyBeforeDNSCheck = true;
|
||||
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public static partial class ProxySettings
|
||||
yield return EProxyMode.System;
|
||||
}
|
||||
#else
|
||||
return Array.Empty<EProxyMode>();
|
||||
return Array.Empty<EProxyMode>();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -209,6 +209,12 @@ public sealed partial class ProxySettings_ : IProxySettings, ISettings, ISetting
|
||||
[MPKey(24), MP2Key(24), JsonPropertyOrder(24)]
|
||||
public bool AutoShowWattAcceleratorWindow { get; set; } = IProxySettings.DefaultAutoShowWattAcceleratorWindow;
|
||||
|
||||
/// <summary>
|
||||
/// 加速前进行 DNS 可用性检查
|
||||
/// </summary>
|
||||
[MPKey(25), MP2Key(25), JsonPropertyOrder(25)]
|
||||
public bool ProxyBeforeDNSCheck { get; set; } = IProxySettings.DefaultProxyBeforeDNSCheck;
|
||||
|
||||
}
|
||||
|
||||
public static partial class ProxySettings
|
||||
@@ -383,4 +389,10 @@ public static partial class ProxySettings
|
||||
public static SettingsStructProperty<bool, ProxySettings_> AutoShowWattAcceleratorWindow { get; }
|
||||
= new(DefaultAutoShowWattAcceleratorWindow);
|
||||
|
||||
/// <summary>
|
||||
/// 加速前进行 DNS 可用性检查
|
||||
/// </summary>
|
||||
public static SettingsStructProperty<bool, ProxySettings_> ProxyBeforeDNSCheck { get; }
|
||||
= new(DefaultProxyBeforeDNSCheck);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
using AppResources = BD.WTTS.Client.Resources.Strings;
|
||||
|
||||
using BD.WTTS.UI.Views.Pages;
|
||||
using STUN.StunResult;
|
||||
using STUN.Enums;
|
||||
using AppResources = BD.WTTS.Client.Resources.Strings;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed partial class AcceleratorPageViewModel
|
||||
{
|
||||
public NetworkCheckControlViewModel NetworkCheckControlViewModel { get; } = new();
|
||||
|
||||
DateTime _initializeTime;
|
||||
readonly IHostsFileService? hostsFileService;
|
||||
readonly IPlatformService platformService = IPlatformService.Instance;
|
||||
readonly IReverseProxyService reverseProxyService = IReverseProxyService.Constants.Instance;
|
||||
readonly ICertificateManager certificateManager = ICertificateManager.Constants.Instance;
|
||||
readonly INetworkTestService networkTestService = INetworkTestService.Instance;
|
||||
|
||||
public AcceleratorPageViewModel()
|
||||
{
|
||||
@@ -71,82 +69,6 @@ public sealed partial class AcceleratorPageViewModel
|
||||
GameAcceleratorService.Current.LoadGames();
|
||||
});
|
||||
|
||||
SelectedSTUNAddress = STUNAddress[0];
|
||||
|
||||
NATCheckCommand = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
var natCheckResult = await networkTestService.TestStunClient3489Async(testServerHostName: SelectedSTUNAddress) ?? new ClassicStunResult { NatType = NatType.Unknown };
|
||||
var (netSucc, _) = await networkTestService.TestOpenUrlAsync("https://www.baidu.com");
|
||||
|
||||
var natStatus = natCheckResult.NatType switch
|
||||
{
|
||||
NatType.OpenInternet or NatType.FullCone => NatTypeSimple.Open,
|
||||
NatType.RestrictedCone or NatType.PortRestrictedCone or NatType.SymmetricUdpFirewall => NatTypeSimple.Moderate,
|
||||
NatType.Symmetric or NatType.UdpBlocked => NatTypeSimple.Strict,
|
||||
NatType.Unknown or NatType.UnsupportedServer or _ => NatTypeSimple.Unknown,
|
||||
};
|
||||
|
||||
PublicEndPoint = natCheckResult.PublicEndPoint?.Address.ToString() ?? "Unknown";
|
||||
LocalEndPoint = natCheckResult.LocalEndPoint?.Address.ToString() ?? "Unknown";
|
||||
|
||||
return (natStatus, netSucc);
|
||||
});
|
||||
NATCheckCommand
|
||||
.IsExecuting
|
||||
.ToPropertyEx(this, x => x.IsNATChecking);
|
||||
|
||||
DNSCheckCommand = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
var testDomain = DomainPendingTest == string.Empty ? "store.steampowered.com" : DomainPendingTest;
|
||||
try
|
||||
{
|
||||
long delayMs;
|
||||
IPAddress[] address;
|
||||
if (ProxySettings.UseDoh)
|
||||
{
|
||||
var configDoh = ProxySettings.CustomDohAddres2.Value ?? ProxySettingsWindowViewModel.DohAddress.FirstOrDefault() ?? string.Empty;
|
||||
(delayMs, address) = await networkTestService.TestDNSOverHttpsAsync(testDomain, configDoh);
|
||||
}
|
||||
else
|
||||
{
|
||||
var configDns = ProxySettings.ProxyMasterDns.Value ?? string.Empty;
|
||||
(delayMs, address) = await networkTestService.TestDNSAsync(testDomain, configDns, 53);
|
||||
}
|
||||
if (address.Length == 0)
|
||||
throw new Exception("Parsing failed. Return empty ip address.");
|
||||
|
||||
DNSTestDelay = delayMs + "ms ";
|
||||
DNSTestResult = string.Empty + address.FirstOrDefault();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(AcceleratorPageViewModel), ex.ToString());
|
||||
DNSTestDelay = string.Empty;
|
||||
DNSTestResult = "error";
|
||||
}
|
||||
});
|
||||
DNSCheckCommand
|
||||
.IsExecuting
|
||||
.ToPropertyEx(this, x => x.IsDNSChecking);
|
||||
|
||||
IPv6CheckCommand = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
var result = await IMicroServiceClient.Instance.Accelerate.GetMyIP(ipV6: true);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
IsSupportIPv6 = true;
|
||||
IPv6Address = result.Content ?? string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsSupportIPv6 = false;
|
||||
IPv6Address = string.Empty;
|
||||
}
|
||||
});
|
||||
IPv6CheckCommand
|
||||
.IsExecuting
|
||||
.ToPropertyEx(this, x => x.IsIPv6Checking);
|
||||
|
||||
ProxySettingsCommand = ReactiveCommand.Create(() =>
|
||||
{
|
||||
var vm = new ProxySettingsWindowViewModel();
|
||||
|
||||
@@ -4,66 +4,11 @@ namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed partial class AcceleratorPageViewModel : TabItemViewModel
|
||||
{
|
||||
public enum NatTypeSimple
|
||||
{
|
||||
Unknown,
|
||||
Open,
|
||||
Moderate,
|
||||
Strict,
|
||||
}
|
||||
|
||||
public override string Name => Strings.Welcome;
|
||||
|
||||
[Reactive]
|
||||
public string SelectedSTUNAddress { get; set; }
|
||||
|
||||
public string[] STUNAddress { get; } =
|
||||
[
|
||||
"stun.syncthing.net",
|
||||
"stun.hot-chilli.net",
|
||||
"stun.fitauto.ru",
|
||||
"stun.miwifi.com",
|
||||
];
|
||||
|
||||
[ObservableAsProperty]
|
||||
public bool IsNATChecking { get; }
|
||||
|
||||
[ObservableAsProperty]
|
||||
public bool IsDNSChecking { get; }
|
||||
|
||||
[ObservableAsProperty]
|
||||
public bool IsIPv6Checking { get; }
|
||||
|
||||
[Reactive]
|
||||
public string DomainPendingTest { get; set; } = string.Empty;
|
||||
public override string Name => Strings.CommunityFix;
|
||||
|
||||
[Reactive]
|
||||
public ReadOnlyCollection<ProxyDomainGroupViewModel>? EnableProxyDomainGroupVMs { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string LocalEndPoint { get; set; } = string.Empty;
|
||||
|
||||
[Reactive]
|
||||
public string PublicEndPoint { get; set; } = string.Empty;
|
||||
|
||||
[Reactive]
|
||||
public string DNSTestDelay { get; set; } = string.Empty;
|
||||
|
||||
[Reactive]
|
||||
public string DNSTestResult { get; set; } = string.Empty;
|
||||
|
||||
[Reactive]
|
||||
public string IPv6Address { get; set; } = string.Empty;
|
||||
|
||||
[Reactive]
|
||||
public bool IsSupportIPv6 { get; set; }
|
||||
|
||||
public ReactiveCommand<Unit, (NatTypeSimple Nat, bool PingSuccess)> NATCheckCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> DNSCheckCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> IPv6CheckCommand { get; }
|
||||
|
||||
public ICommand StartProxyCommand { get; }
|
||||
|
||||
public ICommand RefreshCommand { get; }
|
||||
|
||||
@@ -2,7 +2,7 @@ namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed partial class GameAcceleratorPageViewModel : TabItemViewModel
|
||||
{
|
||||
public override string Name => Strings.Welcome;
|
||||
public override string Name => Strings.GameAccelerator;
|
||||
|
||||
private readonly ReadOnlyObservableCollection<XunYouGameViewModel>? _Games;
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using BD.WTTS.Helpers;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed class GameInfoPageViewModel : WindowViewModel
|
||||
@@ -38,6 +40,13 @@ public sealed class GameInfoPageViewModel : WindowViewModel
|
||||
return;
|
||||
}
|
||||
|
||||
TracepointHelper.TrackEvent(nameof(ImmediatelyAccelerate), new Dictionary<string, string> {
|
||||
{ "GameId", XunYouGame.Id.ToString() },
|
||||
{ "GameName", XunYouGame.Name ?? string.Empty },
|
||||
{ "SelectedArea", XunYouGame?.SelectedArea?.Name ?? string.Empty },
|
||||
{ "SelectedServer", XunYouGame?.SelectedServer?.Name ?? string.Empty },
|
||||
});
|
||||
|
||||
Close?.Invoke(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
using STUN.Enums;
|
||||
using STUN.StunResult;
|
||||
using System.Reactive;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public partial class NetworkCheckControlViewModel : ViewModelBase
|
||||
{
|
||||
[GeneratedRegex(DomainValidationAttribute.RegPattern)]
|
||||
private static partial Regex DomainRegExp();
|
||||
|
||||
public class DomainValidationAttribute : RegularExpressionAttribute
|
||||
{
|
||||
public const string RegPattern = @"^[^/]+\.[^/]{2,}$";
|
||||
|
||||
public override string FormatErrorMessage(string name) => "请填入不带分隔符 \"/\" 的域名";
|
||||
|
||||
public DomainValidationAttribute() : base(RegPattern)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private readonly INetworkTestService _networkTestService = INetworkTestService.Instance;
|
||||
|
||||
public record NATFetchResult(string PublicEndPoint, string LocalEndPoint, string NATLevel, string NATTypeTip, bool PingResult);
|
||||
|
||||
public string DefaultTestDomain { get; } = "store.steampowered.com";
|
||||
|
||||
[Reactive]
|
||||
public string SelectedSTUNAddress { get; set; }
|
||||
|
||||
public string[] STUNAddress { get; } =
|
||||
[
|
||||
"stun.syncthing.net",
|
||||
"stun.hot-chilli.net",
|
||||
"stun.fitauto.ru",
|
||||
"stun.miwifi.com",
|
||||
];
|
||||
|
||||
[ObservableAsProperty]
|
||||
public string NATLevel { get; } = string.Empty;
|
||||
|
||||
[ObservableAsProperty]
|
||||
public string NATTypeTip { get; } = string.Empty;
|
||||
|
||||
[ObservableAsProperty]
|
||||
public string LocalEndPoint { get; } = string.Empty;
|
||||
|
||||
[ObservableAsProperty]
|
||||
public string PublicEndPoint { get; } = string.Empty;
|
||||
|
||||
[ObservableAsProperty]
|
||||
public bool PingOkVisible { get; }
|
||||
|
||||
[ObservableAsProperty]
|
||||
public bool PingErrorVisible { get; }
|
||||
|
||||
[ObservableAsProperty]
|
||||
public bool IsNATChecking { get; }
|
||||
|
||||
[ObservableAsProperty]
|
||||
public bool IsDNSChecking { get; }
|
||||
|
||||
[ObservableAsProperty]
|
||||
public bool IsIPv6Checking { get; }
|
||||
|
||||
[DomainValidation]
|
||||
[Reactive]
|
||||
public string DomainPendingTest { get; set; } = string.Empty;
|
||||
|
||||
[Reactive]
|
||||
public string DNSTestDelay { get; set; } = string.Empty;
|
||||
|
||||
[Reactive]
|
||||
public string DNSTestResult { get; set; } = string.Empty;
|
||||
|
||||
[Reactive]
|
||||
public string IPv6Address { get; set; } = string.Empty;
|
||||
|
||||
[Reactive]
|
||||
public bool IsSupportIPv6 { get; set; }
|
||||
|
||||
public ReactiveCommand<Unit, NATFetchResult> NATCheckCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> DNSCheckCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> IPv6CheckCommand { get; }
|
||||
|
||||
public NetworkCheckControlViewModel()
|
||||
{
|
||||
SelectedSTUNAddress = STUNAddress[0];
|
||||
|
||||
NATCheckCommand = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
var natCheckResult = await _networkTestService.TestStunClient3489Async(testServerHostName: SelectedSTUNAddress) ?? new ClassicStunResult { NatType = NatType.Unknown };
|
||||
var (netSucc, _) = await _networkTestService.TestOpenUrlAsync("https://www.baidu.com");
|
||||
|
||||
var publicEndPoint = natCheckResult.PublicEndPoint?.Address.ToString() ?? "Unknown";
|
||||
var localEndPoint = natCheckResult.LocalEndPoint?.Address.ToString() ?? "Unknown";
|
||||
|
||||
var (natLevel, natTypeTip) = natCheckResult.NatType switch
|
||||
{
|
||||
// Open
|
||||
NatType.OpenInternet or NatType.FullCone => ("开放 NAT", "您可与在其网络上具有任意 NAT 类型的用户玩多人游戏和发起多人游戏。"),
|
||||
// Moderate
|
||||
NatType.RestrictedCone or NatType.PortRestrictedCone or NatType.SymmetricUdpFirewall => ("中等 NAT", "您可与一些用户玩多人游戏;但是,并且通常你将不会被选为比赛的主持人。"),
|
||||
// Strict
|
||||
NatType.Symmetric or NatType.UdpBlocked => ("严格 NAT", "您只能与具有开放 NAT 类型的用户玩多人游戏。您不能被选为比赛的主持人。"),
|
||||
// Unknown
|
||||
NatType.Unknown or NatType.UnsupportedServer or _ => ("不可用 NAT", "如果 NAT 不可用,您将无法使用群聊天或连接到某些 Xbox 游戏的多人游戏。"),
|
||||
};
|
||||
|
||||
return new NATFetchResult(publicEndPoint, localEndPoint, natLevel, natTypeTip, netSucc);
|
||||
});
|
||||
NATCheckCommand
|
||||
.IsExecuting
|
||||
.ToPropertyEx(this, x => x.IsNATChecking);
|
||||
NATCheckCommand
|
||||
.Select(x => x.PublicEndPoint)
|
||||
.ToPropertyEx(this, x => x.PublicEndPoint);
|
||||
NATCheckCommand
|
||||
.Select(x => x.LocalEndPoint)
|
||||
.ToPropertyEx(this, x => x.LocalEndPoint);
|
||||
NATCheckCommand
|
||||
.Select(x => x.NATLevel)
|
||||
.Merge(Observable.Return("未知"))
|
||||
.ToPropertyEx(this, x => x.NATLevel);
|
||||
NATCheckCommand
|
||||
.Select(x => x.NATTypeTip)
|
||||
.Merge(Observable.Return("未知类型"))
|
||||
.ToPropertyEx(this, x => x.NATTypeTip);
|
||||
|
||||
var hidePingResultStream = NATCheckCommand
|
||||
.IsExecuting
|
||||
.Where(x => x == true)
|
||||
.Select(x => false);
|
||||
NATCheckCommand
|
||||
.Select(x => x.PingResult == true)
|
||||
.Merge(hidePingResultStream)
|
||||
.ToPropertyEx(this, x => x.PingOkVisible);
|
||||
NATCheckCommand
|
||||
.Select(x => x.PingResult == false)
|
||||
.Merge(hidePingResultStream)
|
||||
.ToPropertyEx(this, x => x.PingErrorVisible);
|
||||
|
||||
var canDNSCheck = this.WhenAnyValue(x => x.DomainPendingTest)
|
||||
.Select(domain => domain == string.Empty || DomainRegExp().IsMatch(domain));
|
||||
DNSCheckCommand = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
var testDomain = DomainPendingTest == string.Empty ? DefaultTestDomain : DomainPendingTest;
|
||||
try
|
||||
{
|
||||
long delayMs;
|
||||
IPAddress[] address;
|
||||
if (ProxySettings.UseDoh)
|
||||
{
|
||||
var configDoh = ProxySettings.CustomDohAddres2.Value ?? ProxySettingsWindowViewModel.DohAddress.FirstOrDefault() ?? string.Empty;
|
||||
(delayMs, address) = await _networkTestService.TestDNSOverHttpsAsync(testDomain, configDoh);
|
||||
}
|
||||
else
|
||||
{
|
||||
var configDns = ProxySettings.ProxyMasterDns.Value ?? string.Empty;
|
||||
(delayMs, address) = await _networkTestService.TestDNSAsync(testDomain, configDns, 53);
|
||||
}
|
||||
if (address.Length == 0)
|
||||
throw new Exception("Parsing failed. Return empty ip address.");
|
||||
|
||||
DNSTestDelay = delayMs + "ms ";
|
||||
DNSTestResult = string.Empty + address.FirstOrDefault();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(AcceleratorPageViewModel), ex.ToString());
|
||||
DNSTestDelay = string.Empty;
|
||||
DNSTestResult = "error";
|
||||
}
|
||||
}, canDNSCheck);
|
||||
DNSCheckCommand
|
||||
.IsExecuting
|
||||
.ToPropertyEx(this, x => x.IsDNSChecking);
|
||||
|
||||
IPv6CheckCommand = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
var result = await IMicroServiceClient.Instance.Accelerate.GetMyIP(ipV6: true);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
IsSupportIPv6 = true;
|
||||
IPv6Address = result.Content ?? string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsSupportIPv6 = false;
|
||||
IPv6Address = string.Empty;
|
||||
}
|
||||
});
|
||||
IPv6CheckCommand
|
||||
.IsExecuting
|
||||
.ToPropertyEx(this, x => x.IsIPv6Checking);
|
||||
|
||||
IPv6CheckCommand.Execute().Subscribe();
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,7 @@ public partial class ScriptPageViewModel : TabItemViewModel
|
||||
if (UserService.Current.IsAuthenticated == false)
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, "脚本商店需要登录账号才可访问");
|
||||
UserService.Current.ShowWindow();
|
||||
return;
|
||||
}
|
||||
var model = new ScriptStorePageViewModel();
|
||||
|
||||