mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-26 12:09:32 +08:00
Compare commits
155
Commits
3.0.0-rc.4
..
push
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96a14d69bd | ||
|
|
c79fba98d3 | ||
|
|
4160bb43c5 | ||
|
|
67209f3861 | ||
|
|
110c92d909 | ||
|
|
cdc773ba74 | ||
|
|
8ea8b73aab | ||
|
|
0614e172b8 | ||
|
|
4c73a5b622 | ||
|
|
34341172b8 | ||
|
|
6813ed9ece | ||
|
|
3eb916e78a | ||
|
|
7424d05f54 | ||
|
|
76829b0ca2 | ||
|
|
bbe98f68f6 | ||
|
|
96025c9ef5 | ||
|
|
2fb12f1b7f | ||
|
|
542b528b93 | ||
|
|
0a4326924d | ||
|
|
e8a9990354 | ||
|
|
4e72f9ccf9 | ||
|
|
6df6ed93cb | ||
|
|
605beeb918 | ||
|
|
2bdfbefda9 | ||
|
|
6747549cbc | ||
|
|
0d4c0b27f7 | ||
|
|
c501066a3d | ||
|
|
57a6b24dad | ||
|
|
143011fbd0 | ||
|
|
11bc9cd440 | ||
|
|
72e9068571 | ||
|
|
5842d5f80f | ||
|
|
bc19a02f4f | ||
|
|
d59d63d57e | ||
|
|
9ad6e8fa8d | ||
|
|
45ef15b220 | ||
|
|
25dfd1f888 | ||
|
|
0495cd3079 | ||
|
|
ea9c45d78b | ||
|
|
4427fd1a5f | ||
|
|
edf3c3a72c | ||
|
|
55490d2351 | ||
|
|
17ae6655b4 | ||
|
|
342d25deac | ||
|
|
f5616dac2e | ||
|
|
28914c53f6 | ||
|
|
f0cbe8ef88 | ||
|
|
e0b45bf8af | ||
|
|
854fe420fd | ||
|
|
c95ce1087a | ||
|
|
14ae662675 | ||
|
|
1594bd250e | ||
|
|
c83ab4fb08 | ||
|
|
e690454e0c | ||
|
|
27b4f4bb10 | ||
|
|
70315c3a99 | ||
|
|
b8e49a5332 | ||
|
|
1374dc52b8 | ||
|
|
150f93e7b7 | ||
|
|
d1aea71f67 | ||
|
|
37a522ec7f | ||
|
|
8b816b9787 | ||
|
|
4f487a5ca8 | ||
|
|
6c7a547a83 | ||
|
|
bde5751d69 | ||
|
|
23544b6c39 | ||
|
|
2c60a9fb69 | ||
|
|
4ce67c8f1a | ||
|
|
e8a1a6153e | ||
|
|
452fa2ac84 | ||
|
|
60e6d71d48 | ||
|
|
ae0e2349e7 | ||
|
|
3a0f2a4950 | ||
|
|
5263863c23 | ||
|
|
c52f3c3e00 | ||
|
|
be61df890e | ||
|
|
6a7c9113a0 | ||
|
|
ac953af7a1 | ||
|
|
147a6b911f | ||
|
|
972054ca7c | ||
|
|
0cea809b40 | ||
|
|
7ec34e59a7 | ||
|
|
00d41dfbc8 | ||
|
|
0272a34e5c | ||
|
|
d450753c92 | ||
|
|
1e6263c241 | ||
|
|
a4602d29a7 | ||
|
|
7623788991 | ||
|
|
8075183be1 | ||
|
|
058f1a9bf2 | ||
|
|
196b7f0f5e | ||
|
|
99d24b2513 | ||
|
|
7e3fb6cf06 | ||
|
|
a0a0dd9bc7 | ||
|
|
81f75e61ca | ||
|
|
11890c68a8 | ||
|
|
be8621d4d5 | ||
|
|
511c84b2ba | ||
|
|
9e75da9e46 | ||
|
|
547b360db8 | ||
|
|
9be21a8e0a | ||
|
|
efbb41bf3f | ||
|
|
c2220359dd | ||
|
|
a788afdeeb | ||
|
|
b543a889a0 | ||
|
|
478950b75f | ||
|
|
27b4114d7d | ||
|
|
6ead1f3666 | ||
|
|
22a015d8b9 | ||
|
|
f5b7cd6db8 | ||
|
|
5a397d1311 | ||
|
|
0c1bedaeb1 | ||
|
|
e959dcc017 | ||
|
|
41610453a0 | ||
|
|
adf3e0ca9d | ||
|
|
21e80a5b7b | ||
|
|
9a78f387cf | ||
|
|
8a091cee0c | ||
|
|
28f9dde2a4 | ||
|
|
aa88832d09 | ||
|
|
3da18b39ac | ||
|
|
01e8478ce0 | ||
|
|
0de026257a | ||
|
|
5ff097d7d6 | ||
|
|
59effc34a3 | ||
|
|
afd21a3285 | ||
|
|
c7ffeb6046 | ||
|
|
e659e3d502 | ||
|
|
077a333d49 | ||
|
|
056a73e3f0 | ||
|
|
db5095c205 | ||
|
|
a1789cec16 | ||
|
|
9a234ae84f | ||
|
|
8692eaef7c | ||
|
|
cb6516ce53 | ||
|
|
d8362ce9ea | ||
|
|
0cfdff80cd | ||
|
|
15c67bcd52 | ||
|
|
3ebe7de3d7 | ||
|
|
deee8d056f | ||
|
|
3016469c7f | ||
|
|
526fb7a78d | ||
|
|
2790ffc5f1 | ||
|
|
e22897e2ae | ||
|
|
00b8c4dfcf | ||
|
|
9a2d2c6c94 | ||
|
|
29fb43fc38 | ||
|
|
4ca3066644 | ||
|
|
890f2fab37 | ||
|
|
f561f841e3 | ||
|
|
a016631d68 | ||
|
|
367c97b480 | ||
|
|
6367bc5ed1 | ||
|
|
2b69b98f3c | ||
|
|
a6010ba5f4 |
@@ -68,19 +68,19 @@ jobs:
|
||||
run: dotnet --info
|
||||
|
||||
- name: Build BD.WTTS.Client.AppHost
|
||||
run: dotnet build -c Release src\BD.WTTS.Client.AppHost\BD.WTTS.Client.AppHost.csproj --nologo -v q /property:WarningLevel=1
|
||||
run: dotnet build -c Release src\BD.WTTS.Client.AppHost\BD.WTTS.Client.AppHost.csproj --nologo -v q --property:WarningLevel=1;DebugType=pdbonly
|
||||
|
||||
- name: Build BD.WTTS.Client.Plugins.Accelerator.ReverseProxy
|
||||
run: dotnet build -c Release src\BD.WTTS.Client.Plugins.Accelerator.ReverseProxy\BD.WTTS.Client.Plugins.Accelerator.ReverseProxy.csproj --nologo -v q /property:WarningLevel=1
|
||||
run: dotnet build -c Release src\BD.WTTS.Client.Plugins.Accelerator.ReverseProxy\BD.WTTS.Client.Plugins.Accelerator.ReverseProxy.csproj --nologo -v q --property:WarningLevel=1;DebugType=pdbonly
|
||||
|
||||
- name: Build BD.WTTS.Client.Avalonia.App
|
||||
run: dotnet build -c Release src\BD.WTTS.Client.Avalonia.App\BD.WTTS.Client.Avalonia.App.csproj --nologo -v q /property:WarningLevel=1
|
||||
run: dotnet build -c Release src\BD.WTTS.Client.Avalonia.App\BD.WTTS.Client.Avalonia.App.csproj --nologo -v q --property:WarningLevel=1;DebugType=pdbonly
|
||||
|
||||
- name: Build BD.WTTS.Client.Avalonia.Designer.HostApp
|
||||
run: dotnet build -c Release src\BD.WTTS.Client.Avalonia.Designer.HostApp\BD.WTTS.Client.Avalonia.Designer.HostApp.csproj --nologo -v q /property:WarningLevel=1
|
||||
run: dotnet build -c Release src\BD.WTTS.Client.Avalonia.Designer.HostApp\BD.WTTS.Client.Avalonia.Designer.HostApp.csproj --nologo -v q --property:WarningLevel=1;DebugType=pdbonly
|
||||
|
||||
- name: Test
|
||||
run: dotnet test src/BD.WTTS.UnitTest/BD.WTTS.UnitTest.csproj -c Release -p:GeneratePackageOnBuild=false --nologo -v q /property:WarningLevel=1
|
||||
run: dotnet test src/BD.WTTS.UnitTest/BD.WTTS.UnitTest.csproj -c Release -p:GeneratePackageOnBuild=false --nologo -v q --property:WarningLevel=1;DebugType=pdbonly
|
||||
|
||||
# release:
|
||||
# name: Release
|
||||
|
||||
@@ -172,17 +172,36 @@ else
|
||||
fi
|
||||
chmod +x "$base_path/$exec_name.sh"
|
||||
# xdg-icon-resource install "$base_path/Icons/Watt-Toolkit.png" --size 128 Watt-Toolkit
|
||||
#添加桌面文件
|
||||
rm -rf "$HOME/Desktop/Watt Toolkit.desktop" 2>/dev/null
|
||||
echo "#!/usr/bin/env xdg-open
|
||||
InitDesktop() {
|
||||
while true; do
|
||||
# 使用 zenity 提示用户选择安装路径或使用默认路径
|
||||
choice=$(zenity --list --radiolist --title="请选择要添加到的位置" --column="选择" --column="路径" TRUE "$HOME/.local/share/applications/" FALSE "$HOME/Desktop")
|
||||
|
||||
# 检查用户输入
|
||||
if [ "$choice" == "$HOME/.local/share/applications/" ]; then
|
||||
target_dir="$HOME/.local/share/applications/"
|
||||
break
|
||||
elif [ "$choice" == "$HOME/Desktop" ]; then
|
||||
target_dir="$HOME/Desktop/"
|
||||
break
|
||||
else
|
||||
echo "无效选项,请输入 1 或 2。"
|
||||
fi
|
||||
done
|
||||
#添加桌面文件
|
||||
rm -rf "$target_dir/Watt Toolkit.desktop" 2>/dev/null
|
||||
echo "#!/usr/bin/env xdg-open
|
||||
[Desktop Entry]
|
||||
Name=Watt Toolkit
|
||||
Exec=$base_path/$exec_name.sh
|
||||
Icon=$base_path/Icons/Watt-Toolkit.png
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=false" >"$HOME/Desktop/Watt Toolkit.desktop"
|
||||
chmod +x "$HOME/Desktop/Watt Toolkit.desktop"
|
||||
StartupNotify=false" >"$target_dir/Watt Toolkit.desktop"
|
||||
chmod +x "$target_dir/Watt Toolkit.desktop"
|
||||
|
||||
}
|
||||
InitDesktop
|
||||
# update-desktop-database ~/.local/share/applications
|
||||
#运行程序
|
||||
Show_Run "下载安装完成,是否启动程序?"
|
||||
|
||||
@@ -1,7 +1,38 @@
|
||||
#!/bin/bash
|
||||
base_path="$HOME/WattToolkit"
|
||||
mkdir -p "$base_path"
|
||||
cd "$base_path" || exit 1
|
||||
# 设置默认的 base_path 参数
|
||||
default_base_path="$HOME/WattToolkit"
|
||||
base_path="$default_base_path"
|
||||
|
||||
# 循环直到用户输入有效路径或直接回车
|
||||
while true; do
|
||||
# 使用 zenity 提示用户选择安装路径或使用默认路径
|
||||
custom_base_path=$(zenity --entry --title="安装路径" --text="请输入安装路径(默认为 $default_base_path,不输入则使用默认路径)")
|
||||
|
||||
# 如果用户提供了自定义路径,则使用该路径
|
||||
if [ -n "$custom_base_path" ]; then
|
||||
base_path="$custom_base_path"
|
||||
break
|
||||
elif [ -z "$custom_base_path" ]; then
|
||||
# 用户直接回车,使用默认路径
|
||||
break
|
||||
else
|
||||
# 用户输入无效路径,重新提示
|
||||
echo "无效路径,请重新输入。"
|
||||
fi
|
||||
done
|
||||
|
||||
# 创建安装路径
|
||||
mkdir -p "$base_path" || {
|
||||
echo "无法创建安装路径 $base_path,请检查权限或路径是否正确。"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 切换到安装路径
|
||||
cd "$base_path" || {
|
||||
echo "无法切换到安装路径 $base_path,请检查权限或路径是否正确。"
|
||||
exit 1
|
||||
}
|
||||
|
||||
appVer_path="$base_path/WattToolkit.AppVer"
|
||||
exec_name="Steam++"
|
||||
tar_name="WattToolkit.tgz"
|
||||
@@ -182,7 +213,9 @@ Get_NewVer() {
|
||||
|
||||
sleep 1
|
||||
#本地版本 Hash
|
||||
o_sha384=$(cat "AppVer")
|
||||
if [ -f "AppVer" ]; then
|
||||
o_sha384=$(cat "AppVer")
|
||||
fi
|
||||
if [ -e "AppVer" ]; then
|
||||
if [ "${o_sha384,,}" = "${n_sha384,,}" ]; then
|
||||
Show_Run "已是最新版本,是否启动程序?"
|
||||
@@ -326,17 +359,36 @@ Kill_Process
|
||||
#解压
|
||||
Decompression
|
||||
# xdg-icon-resource install "$base_path/Icons/Watt-Toolkit.png" --size 128 Watt-Toolkit
|
||||
#添加桌面文件
|
||||
rm -rf "$HOME/Desktop/Watt Toolkit.desktop" 2>/dev/null
|
||||
echo "#!/usr/bin/env xdg-open
|
||||
InitDesktop() {
|
||||
while true; do
|
||||
# 使用 zenity 提示用户选择安装路径或使用默认路径
|
||||
choice=$(zenity --list --radiolist --title="请选择要添加到的位置" --column="选择" --column="路径" TRUE "$HOME/.local/share/applications/" FALSE "$HOME/Desktop")
|
||||
|
||||
# 检查用户输入
|
||||
if [ "$choice" == "$HOME/.local/share/applications/" ]; then
|
||||
target_dir="$HOME/.local/share/applications/"
|
||||
break
|
||||
elif [ "$choice" == "$HOME/Desktop" ]; then
|
||||
target_dir="$HOME/Desktop/"
|
||||
break
|
||||
else
|
||||
echo "无效选项,请输入 1 或 2。"
|
||||
fi
|
||||
done
|
||||
#添加桌面文件
|
||||
rm -rf "$target_dir/Watt Toolkit.desktop" 2>/dev/null
|
||||
echo "#!/usr/bin/env xdg-open
|
||||
[Desktop Entry]
|
||||
Name=Watt Toolkit
|
||||
Exec=$base_path/$exec_name.sh
|
||||
Icon=$base_path/Icons/Watt-Toolkit.png
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=false" >"$HOME/Desktop/Watt Toolkit.desktop"
|
||||
chmod +x "$HOME/Desktop/Watt Toolkit.desktop"
|
||||
StartupNotify=false" >"$target_dir/Watt Toolkit.desktop"
|
||||
chmod +x "$target_dir/Watt Toolkit.desktop"
|
||||
|
||||
}
|
||||
InitDesktop
|
||||
# update-desktop-database ~/.local/share/applications
|
||||
#运行程序
|
||||
Show_Run "下载安装完成,是否启动程序?"
|
||||
|
||||
@@ -212,6 +212,15 @@
|
||||
"Summary": "菜单排序",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
},
|
||||
{
|
||||
"TypeName": "string",
|
||||
"PropertyName": "StartDefaultPageName",
|
||||
"DefaultValue": "null",
|
||||
"DefaultValueIsConst": true,
|
||||
"Summary": "程序启动时默认页",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
}
|
||||
],
|
||||
"Usings": ""
|
||||
@@ -487,6 +496,15 @@
|
||||
"Summary": "账号平台设置集合",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
},
|
||||
{
|
||||
"TypeName": "bool",
|
||||
"PropertyName": "IsShowAccountName",
|
||||
"DefaultValue": "false",
|
||||
"DefaultValueIsConst": false,
|
||||
"Summary": "是否显示账号用户名",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
}
|
||||
],
|
||||
"Usings": ""
|
||||
@@ -961,6 +979,15 @@
|
||||
"Summary": "自定义 DNS over HTTPS 地址",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
},
|
||||
{
|
||||
"TypeName": "int",
|
||||
"PropertyName": "AcceleratorTabsSelectedIndex",
|
||||
"DefaultValue": "0",
|
||||
"DefaultValueIsConst": false,
|
||||
"Summary": "加速页面 Tab 选项卡选中下标",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
}
|
||||
],
|
||||
"Usings": ""
|
||||
|
||||
+1
-1
Submodule ref/Avalonia.Image2 updated: c4162f332f...de291c0d95
+1
-1
Submodule ref/DirectoryPackages updated: 6974b6215e...b6b85044cc
Submodule ref/SteamAchievementManager updated: 4c578c1cc4...39dbdc9678
+1
-1
Submodule ref/SteamClient updated: 079a2c22ef...fddb907049
Submodule ref/WTTS.MicroServices.ClientSDK updated: 29a5a63dcb...5f3111baad
+1
-1
Submodule ref/WinAuth updated: d3f45cffe2...f6ad4f84ca
@@ -3,6 +3,14 @@ namespace BD.WTTS;
|
||||
/// <summary>
|
||||
/// 提供用来获取应用程序信息(如版本号、说明、加载的程序集等)的属性。
|
||||
/// </summary>
|
||||
[Mobius3(
|
||||
"""
|
||||
Mobius.AssemblyInfo
|
||||
AssemblyInfo.cs
|
||||
AssemblyInfo.Version.cs
|
||||
AssemblyInfo.Version.NativeHost.cs
|
||||
AssemblyInfo.Version.Setup.Windows.cs
|
||||
""")]
|
||||
public static partial class AssemblyInfo
|
||||
{
|
||||
const string Version2 = "3.0";
|
||||
@@ -16,12 +24,12 @@ public static partial class AssemblyInfo
|
||||
/// <summary>
|
||||
/// 预览版本号,范围 1~9,只增不减
|
||||
/// </summary>
|
||||
const string ver_for_preview = "7";
|
||||
const string ver_for_preview = "8";
|
||||
|
||||
/// <summary>
|
||||
/// RC 版本号,范围 0~9,只增不减
|
||||
/// </summary>
|
||||
const string ver_for_rc = "4";
|
||||
const string ver_for_rc = "8";
|
||||
|
||||
public const string FileVersion = $"{Version2}.{ver_for_rc}0{ver_for_preview}.0";
|
||||
|
||||
@@ -146,4 +154,20 @@ false
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false)]
|
||||
sealed class Mobius3Attribute : Attribute
|
||||
{
|
||||
public Mobius3Attribute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Mobius3Attribute(string str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool Obsolete { get; set; }
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// Mobius Properties\XmlnsDefinition.cs
|
||||
#if (WINDOWS || MACCATALYST || MACOS || LINUX) && !(IOS || ANDROID)
|
||||
// C# 10 定义全局 using
|
||||
|
||||
|
||||
@@ -38,9 +38,9 @@ public interface IFontManagerImpl2 : IFontManagerImpl
|
||||
return Impl.TryCreateGlyphTypeface(familyName, style, weight, stretch, out glyphTypeface);
|
||||
}
|
||||
|
||||
bool IFontManagerImpl.TryCreateGlyphTypeface(Stream stream, [NotNullWhen(returnValue: true)] out IGlyphTypeface? glyphTypeface)
|
||||
bool IFontManagerImpl.TryCreateGlyphTypeface(Stream stream, FontSimulations fontSimulations, [NotNullWhen(returnValue: true)] out IGlyphTypeface? glyphTypeface)
|
||||
{
|
||||
return Impl.TryCreateGlyphTypeface(stream, out glyphTypeface);
|
||||
return Impl.TryCreateGlyphTypeface(stream, fontSimulations, out glyphTypeface);
|
||||
}
|
||||
|
||||
//IGlyphTypeface IFontManagerImpl.CreateGlyphTypeface(Typeface typeface)
|
||||
|
||||
+166
-2505
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
@@ -8,70 +8,67 @@
|
||||
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" />
|
||||
<Identity
|
||||
Name="4651ED44255E.47979655102CE"
|
||||
Publisher="CN=A90E406B-B2D3-4A23-B061-0FA1D65C4F66"
|
||||
Version="3.0.999.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>Watt Toolkit</DisplayName>
|
||||
<PublisherDisplayName>软妹币玩家</PublisherDisplayName>
|
||||
<Logo>Images\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
<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>
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
<rescap:Capability Name="allowElevation" />
|
||||
</Capabilities>
|
||||
</Package>
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
<string>NSApplication</string>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>AppIcon.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>net.steampp.app</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
||||
@@ -81,8 +81,10 @@
|
||||
<PackageReference Include="Avalonia" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" />
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" />
|
||||
<PackageReference Include="Avalonia.Controls.ItemsRepeater" />
|
||||
<PackageReference Include="Avalonia.Xaml.Behaviors" />
|
||||
<!--<PackageReference Include="Avalonia.AvaloniaEdit" />-->
|
||||
<PackageReference Include="Avalonia.AvaloniaEdit" />
|
||||
<PackageReference Include="AvaloniaEdit.TextMate" />
|
||||
<!--<PackageReference Include="Markdown.Avalonia" />-->
|
||||
<PackageReference Include="FluentAvaloniaUI" />
|
||||
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" />
|
||||
@@ -130,6 +132,9 @@
|
||||
<Compile Update="UI\Views\Controls\Widgets\CarouselItems.cs">
|
||||
<DependentUpon>%(Filename)</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="UI\Views\Pages\PluginStorePage.axaml.cs">
|
||||
<DependentUpon>PluginStorePage.axaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\TFM_NETX_WITH_DESKTOP.props" />
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
namespace BD.WTTS.Converters;
|
||||
|
||||
public sealed class WaveProgressValueConverter : IValueConverter
|
||||
{
|
||||
public static readonly WaveProgressValueConverter Instance = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is not double i) return 0;
|
||||
return 155 - (i * 2.1);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
return BindingOperations.DoNothing;
|
||||
}
|
||||
}
|
||||
|
||||
public class WaveProgressValueColorConverter : IValueConverter
|
||||
{
|
||||
public static readonly WaveProgressValueColorConverter Instance = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is not double d) return Brushes.Black;
|
||||
if (d > 50) return Brushes.GhostWhite;
|
||||
return Application.Current?.ActualThemeVariant == ThemeVariant.Dark ? Brushes.GhostWhite : Brushes.Black;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
return BindingOperations.DoNothing;
|
||||
}
|
||||
}
|
||||
|
||||
public class WaveProgressValueTextConverter : IValueConverter
|
||||
{
|
||||
public static readonly WaveProgressValueTextConverter Instance = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
return value is not double d ? "0%" : $"{d:#0}%";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
return BindingOperations.DoNothing;
|
||||
}
|
||||
}
|
||||
|
||||
public class WaveProgressGradientOffsetConverter : IValueConverter
|
||||
{
|
||||
public static readonly WaveProgressGradientOffsetConverter Instance = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is not double v)
|
||||
return Brushes.Blue;
|
||||
|
||||
var app = Application.Current;
|
||||
if (app == null)
|
||||
return null;
|
||||
|
||||
Color primaryColor = Colors.DodgerBlue;
|
||||
Color accentColor = Colors.Transparent;
|
||||
|
||||
try
|
||||
{
|
||||
if (app.FindResource("SystemAccentColor") is Color primaryColor2)
|
||||
{
|
||||
primaryColor = primaryColor2;
|
||||
}
|
||||
if (app.FindResource("SystemAccentColorLight2") is Color accentColor2)
|
||||
{
|
||||
accentColor = accentColor2;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
var isLight = app.RequestedThemeVariant == ThemeVariant.Light;
|
||||
|
||||
v /= 100;
|
||||
v += isLight ? 0.2 : 0.4;
|
||||
if (v > 1)
|
||||
v = 1;
|
||||
|
||||
return new LinearGradientBrush()
|
||||
{
|
||||
EndPoint = new RelativePoint(0.5, 1, RelativeUnit.Relative),
|
||||
StartPoint = new RelativePoint(0.5, 0, RelativeUnit.Relative),
|
||||
GradientStops = new GradientStops()
|
||||
{
|
||||
new GradientStop() { Color = primaryColor, Offset = 0 },
|
||||
new GradientStop() { Color = isLight ? Colors.Transparent : accentColor, Offset = v },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
return BindingOperations.DoNothing;
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,18 @@ namespace BD.WTTS.UI;
|
||||
|
||||
public static class ControlExtensions
|
||||
{
|
||||
public static void SetViewModel<T>(this Control c) where T : ViewModelBase, new()
|
||||
public static void SetViewModel<T>(this Control c, bool useCache = false) where T : ViewModelBase, new()
|
||||
{
|
||||
if (c.DataContext == null || c.DataContext.GetType() != typeof(T))
|
||||
{
|
||||
c.DataContext = new T();
|
||||
T cx;
|
||||
|
||||
if (useCache)
|
||||
cx = IViewModelManager.Instance.Get<T>();
|
||||
else
|
||||
cx = new T();
|
||||
|
||||
c.DataContext = cx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -113,7 +113,6 @@ public sealed class AvaloniaWindowManagerImpl : IWindowManagerImpl
|
||||
|
||||
if (viewModel != null)
|
||||
{
|
||||
|
||||
if (viewModel is IWindowViewModel window)
|
||||
{
|
||||
window.Close = b => td?.Hide(b ? TaskDialogStandardResult.OK : TaskDialogStandardResult.Close);
|
||||
|
||||
@@ -7,12 +7,28 @@ namespace BD.WTTS.UI;
|
||||
|
||||
partial class App
|
||||
{
|
||||
[Mobius(
|
||||
"""
|
||||
App.DefaultActualTheme
|
||||
""")]
|
||||
const AppTheme _DefaultActualTheme = AppTheme.FollowingSystem;
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.DefaultActualTheme
|
||||
""")]
|
||||
AppTheme IApplication.DefaultActualTheme => _DefaultActualTheme;
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.mTheme
|
||||
""")]
|
||||
AppTheme mTheme = _DefaultActualTheme;
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.Theme
|
||||
""")]
|
||||
public AppTheme Theme
|
||||
{
|
||||
get => mTheme;
|
||||
@@ -50,6 +66,10 @@ partial class App
|
||||
}
|
||||
}
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.SetThemeNotChangeValue
|
||||
""")]
|
||||
public void SetThemeNotChangeValue(AppTheme value)
|
||||
{
|
||||
var mode = value switch
|
||||
@@ -71,6 +91,10 @@ partial class App
|
||||
}
|
||||
}
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.SetThemeAccent
|
||||
""")]
|
||||
public static void SetThemeAccent(string? colorHex)
|
||||
{
|
||||
if (colorHex == null)
|
||||
|
||||
@@ -9,14 +9,34 @@ namespace BD.WTTS.UI;
|
||||
|
||||
partial class App
|
||||
{
|
||||
[Mobius(
|
||||
"""
|
||||
App.TrayMenus
|
||||
""")]
|
||||
public Dictionary<string, TrayMenuItem> TrayMenus { get; } = new Dictionary<string, TrayMenuItem>();
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.TrayIcons
|
||||
""")]
|
||||
public TrayIcons TrayIcons { get; init; } = new TrayIcons();
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.trayIconMenus
|
||||
""")]
|
||||
readonly Dictionary<string, ICommand> trayIconMenus = new();
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.TrayIconMenus
|
||||
""")]
|
||||
public IReadOnlyDictionary<string, ICommand> TrayIconMenus => trayIconMenus;
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.InitTrayIcon
|
||||
""")]
|
||||
void InitTrayIcon()
|
||||
{
|
||||
if (ApplicationLifetime is not
|
||||
@@ -67,6 +87,10 @@ partial class App
|
||||
}
|
||||
}
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.UpdateMenuItems
|
||||
""")]
|
||||
public void UpdateMenuItems()
|
||||
{
|
||||
MainThread2.BeginInvokeOnMainThread(() =>
|
||||
@@ -125,12 +149,20 @@ partial class App
|
||||
{
|
||||
subMenu = new NativeMenu();
|
||||
foreach (var sub in item.Value.Items)
|
||||
subMenu.Add(new NativeMenuItem
|
||||
{
|
||||
var menu = new NativeMenuItem
|
||||
{
|
||||
Header = sub.Name,
|
||||
Command = sub.Command,
|
||||
CommandParameter = sub.CommandParameter,
|
||||
});
|
||||
};
|
||||
|
||||
if (sub.IsVisible is Avalonia.Data.IBinding v)
|
||||
menu[!NativeMenuItem.IsVisibleProperty] = v;
|
||||
if (sub.IsEnabled is Avalonia.Data.IBinding e)
|
||||
menu[!NativeMenuItem.IsEnabledProperty] = e;
|
||||
subMenu.Add(menu);
|
||||
}
|
||||
menus.Add(new NativeMenuItem
|
||||
{
|
||||
Header = item.Value.Name,
|
||||
@@ -158,6 +190,10 @@ partial class App
|
||||
});
|
||||
}
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.UpdateMenuItems
|
||||
""")]
|
||||
public void UpdateMenuItems(string menuKey, TrayMenuItem trayMenuItem)
|
||||
{
|
||||
if (TrayMenus != null)
|
||||
|
||||
@@ -11,6 +11,12 @@ public sealed partial class App : Application
|
||||
{
|
||||
const string TAG = "AvaApp";
|
||||
|
||||
public App()
|
||||
{
|
||||
OpenBrowserCommand = ReactiveCommand.Create<object?>(OpenBrowserCommandCore);
|
||||
CopyToClipboardCommand = ReactiveCommand.Create<object?>(CopyToClipboardCommandCore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前主窗口
|
||||
/// </summary>
|
||||
@@ -44,9 +50,9 @@ public sealed partial class App : Application
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
#if WINDOWS || LINUX || MACOS
|
||||
//非主窗口不执行启动时最小化逻辑
|
||||
if (GeneralSettings.MinimizeOnStartup.Value && MainWindow is MainWindow)
|
||||
if (GeneralSettings.MinimizeOnStartup.Value)
|
||||
Startup.Instance.IsMinimize = true;
|
||||
|
||||
if (Startup.Instance.IsSteamRun)
|
||||
{
|
||||
try
|
||||
@@ -94,9 +100,10 @@ public sealed partial class App : Application
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
MainWindow = InitializeMainWindow?.Invoke(this) ?? new MainWindow();
|
||||
|
||||
desktop.MainWindow =
|
||||
#if !UI_DEMO
|
||||
Startup.Instance.IsMinimize ? null :
|
||||
Startup.Instance.IsMinimize && MainWindow is MainWindow ? null :
|
||||
#endif
|
||||
MainWindow;
|
||||
|
||||
@@ -224,16 +231,32 @@ public sealed partial class App : Application
|
||||
|
||||
public static FontFamily DefaultFontFamily => _DefaultFontFamily.Value;
|
||||
|
||||
public void OpenBrowserCommand(object url)
|
||||
public ICommand OpenBrowserCommand { get; }
|
||||
|
||||
public async void OpenBrowserCommandCore(object? url)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (url == null || string.IsNullOrEmpty(url.ToString()))
|
||||
var urlString = url?.ToString();
|
||||
if (string.IsNullOrEmpty(urlString))
|
||||
{
|
||||
Toast.Show(ToastIcon.Warning, "打开链接失败");
|
||||
return;
|
||||
}
|
||||
Browser2.Open(url.ToString());
|
||||
try
|
||||
{
|
||||
Uri uri = new(urlString);
|
||||
if (uri.Host.EndsWith("steampp.net", StringComparison.OrdinalIgnoreCase) ||
|
||||
uri.Host.EndsWith("mossimo.net", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await UserService.Current.OpenAuthUrl(urlString);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
Browser2.Open(urlString);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -241,7 +264,9 @@ public sealed partial class App : Application
|
||||
}
|
||||
}
|
||||
|
||||
public async void CopyToClipboardCommand(object text)
|
||||
public ICommand CopyToClipboardCommand { get; }
|
||||
|
||||
public async void CopyToClipboardCommandCore(object? text)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
@@ -6,8 +6,8 @@
|
||||
x:CompileBindings="True">
|
||||
<Styles.Resources>
|
||||
<ResourceDictionary>
|
||||
<sys:Double x:Key="TitleBarHeight">60</sys:Double>
|
||||
<Thickness x:Key="TitleBarAfterMargin">0,60,0,0</Thickness>
|
||||
<sys:Double x:Key="TitleBarHeight">50</sys:Double>
|
||||
<Thickness x:Key="TitleBarAfterMargin">0,50,0,0</Thickness>
|
||||
<sys:Double x:Key="SplashScreenImageWidth">100</sys:Double>
|
||||
|
||||
<Thickness x:Key="PageMargin">10</Thickness>
|
||||
@@ -66,6 +66,7 @@
|
||||
<StyleInclude Source="/UI/Styling/Controls/IconElement.axaml" />
|
||||
<StyleInclude Source="/UI/Styling/Controls/CustomFilePicker.axaml" />
|
||||
<StyleInclude Source="/UI/Styling/Controls/NumericUpDown.axaml" />
|
||||
<StyleInclude Source="/UI/Styling/Controls/Skeleton.axaml" />
|
||||
|
||||
<Style Selector="FlyoutPresenter.NoPadding">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<Border Padding="20">
|
||||
<!-- Add Controls for Previewer Here -->
|
||||
<StackPanel Spacing="10">
|
||||
<ui:HyperlinkButton Content="更新日志" />
|
||||
<HyperlinkButton Content="更新日志" />
|
||||
<Button Content="更新日志" Theme="{StaticResource HyperlinkButton}" />
|
||||
<Button
|
||||
Content="更新日志"
|
||||
@@ -87,7 +87,7 @@
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<ui:FABorder
|
||||
<Border
|
||||
Name="Root"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
@@ -101,19 +101,19 @@
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
RecognizesAccessKey="True" />
|
||||
</ui:FABorder>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
|
||||
<Style Selector="^:pointerover">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pressed">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorTertiaryBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
@@ -122,7 +122,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorDisabledBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
@@ -131,7 +131,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:checked">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundChecked}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
@@ -140,7 +140,7 @@
|
||||
|
||||
|
||||
<Style Selector="^:pointerover">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedPointerOver}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
@@ -149,7 +149,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pressed">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedPressed}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
@@ -158,7 +158,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorDisabledBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
@@ -168,19 +168,19 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:indeterminate">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorTransparentBrush}" />
|
||||
</Style>
|
||||
|
||||
|
||||
<Style Selector="^:pointerover">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pressed">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorTertiaryBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
@@ -189,7 +189,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorDisabledBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
@@ -214,10 +214,13 @@
|
||||
<Style Selector="Button.Plain:pointerover">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
<Style Selector="Button.Plain:pointerover /template/ ui|FABorder#Root">
|
||||
<Style Selector="Button.Plain:pointerover /template/ Border#Root">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
<Style Selector="Button.Plain:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
|
||||
|
||||
|
||||
</Styles>
|
||||
|
||||
@@ -63,14 +63,13 @@
|
||||
Height="10"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom">
|
||||
<ItemsRepeater Name="Swiper" IsVisible="False">
|
||||
<ItemsRepeater.Layout>
|
||||
<StackLayout
|
||||
DisableVirtualization="True"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<ItemsControl Name="Swiper" IsVisible="False">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<DataTemplate.DataType>
|
||||
<x:Type x:TypeArguments="x:Int32, x:String" TypeName="generic:KeyValuePair" />
|
||||
@@ -91,8 +90,8 @@
|
||||
StrokeThickness="0" />
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Panel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
@@ -18,27 +18,15 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{TemplateBinding IsLoading}"
|
||||
Spacing="8">
|
||||
<spp:Image2
|
||||
Spacing="10">
|
||||
<!--<spp:Image2
|
||||
Width="100"
|
||||
Height="100"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="avares://BD.WTTS.Client.Avalonia/UI/Assets/mona-loading-default.gif"
|
||||
Stretch="UniformToFill" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Text="{Binding Path=Res.GameList_IsLoading, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
IsVisible="{TemplateBinding CustomLoadingText,
|
||||
Converter={StaticResource IsNullConverter},
|
||||
ConverterParameter=invert}"
|
||||
Text="{TemplateBinding CustomLoadingText}"
|
||||
Theme="{StaticResource BodyStrongTextBlockStyle}" />
|
||||
Stretch="UniformToFill" />-->
|
||||
<Border
|
||||
Width="35"
|
||||
Height="35"
|
||||
@@ -51,6 +39,18 @@
|
||||
Minimum="{TemplateBinding Minimum}"
|
||||
Value="{TemplateBinding ProgressValue}" />
|
||||
</Border>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Text="{Binding Path=Res.GameList_IsLoading, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
IsVisible="{TemplateBinding CustomLoadingText,
|
||||
Converter={StaticResource IsNullConverter},
|
||||
ConverterParameter=invert}"
|
||||
Text="{TemplateBinding CustomLoadingText}"
|
||||
Theme="{StaticResource BodyStrongTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<!--<TextBlock
|
||||
@@ -101,5 +101,8 @@
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:loading /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Effect" Value="blur(5)" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -46,19 +46,19 @@
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<StackPanel>
|
||||
<ui:FABorder
|
||||
<Border
|
||||
Name="LayoutRoot"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<ui:FABorder.Transitions>
|
||||
<Border.Transitions>
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="00:00:00.083" />
|
||||
<BrushTransition Property="BorderBrush" Duration="00:00:00.083" />
|
||||
</Transitions>
|
||||
</ui:FABorder.Transitions>
|
||||
</Border.Transitions>
|
||||
<Grid MinHeight="{TemplateBinding MinHeight}" ColumnDefinitions="Auto,*,Auto,Auto">
|
||||
<Viewbox
|
||||
Name="IconHost"
|
||||
@@ -113,7 +113,7 @@
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18" />
|
||||
</Grid>
|
||||
</ui:FABorder>
|
||||
</Border>
|
||||
|
||||
<ContentPresenter
|
||||
Name="ExpandedContentPresenter"
|
||||
@@ -144,10 +144,10 @@
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="spp|OptionsDisplayItem /template/ ui|FABorder#LayoutRoot:pointerover">
|
||||
<Style Selector="spp|OptionsDisplayItem /template/ Border#LayoutRoot:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
<Style Selector="spp|OptionsDisplayItem:pressed /template/ ui|FABorder#LayoutRoot:pointerover">
|
||||
<Style Selector="spp|OptionsDisplayItem:pressed /template/ Border#LayoutRoot:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorTertiaryBrush}" />
|
||||
</Style>
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
<Setter Property="CornerRadius" Value="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BottomCornerRadiusFilterConverter}}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="spp|OptionsDisplayItem:expanded /template/ ui|FABorder#LayoutRoot">
|
||||
<Style Selector="spp|OptionsDisplayItem:expanded /template/ Border#LayoutRoot">
|
||||
<Setter Property="CornerRadius" Value="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource TopCornerRadiusFilterConverter}}" />
|
||||
</Style>
|
||||
|
||||
@@ -195,19 +195,19 @@
|
||||
<Style Selector="spp|OptionsDisplayItem.Vertical">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<ui:FABorder
|
||||
<Border
|
||||
Name="LayoutRoot"
|
||||
Padding="12"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<ui:FABorder.Transitions>
|
||||
<Border.Transitions>
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="00:00:00.083" />
|
||||
<BrushTransition Property="BorderBrush" Duration="00:00:00.083" />
|
||||
</Transitions>
|
||||
</ui:FABorder.Transitions>
|
||||
</Border.Transitions>
|
||||
<Grid RowDefinitions="*,*">
|
||||
<Border
|
||||
Width="72"
|
||||
@@ -241,7 +241,7 @@
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ui:FABorder>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
@@ -38,18 +38,18 @@
|
||||
<Setter Property="MinHeight" Value="{DynamicResource SettingsExpanderItemMinHeight}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<ui:FABorder
|
||||
<Border
|
||||
Name="Root"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<ui:FABorder.Transitions>
|
||||
<Border.Transitions>
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="00:00:00.083" />
|
||||
<BrushTransition Property="BorderBrush" Duration="00:00:00.083" />
|
||||
</Transitions>
|
||||
</ui:FABorder.Transitions>
|
||||
</Border.Transitions>
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto,Auto" RowDefinitions="*,Auto">
|
||||
<Viewbox
|
||||
@@ -102,7 +102,7 @@
|
||||
<ContentPresenter Name="ExpandChevronActionIconContainer" Content="{Binding TemplateSettings.ActionIcon, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</ui:FABorder>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:nth-last-child(1) /template/ ui|FABorder#Root">
|
||||
<Style Selector="^:nth-last-child(1) /template/ Border#Root">
|
||||
<Setter Property="CornerRadius" Value="{Binding Source={StaticResource ControlCornerRadius}, Converter={StaticResource BottomCornerRadiusFilterConverter}}" />
|
||||
</Style>
|
||||
|
||||
@@ -152,11 +152,11 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:allowClick">
|
||||
<Style Selector="^:pointerover /template/ ui|FABorder#Root">
|
||||
<Style Selector="^:pointerover /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorSecondaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ControlFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed /template/ ui|FABorder#Root">
|
||||
<Style Selector="^:pressed /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorTertiaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeColorDefaultBrush}" />
|
||||
<Setter Property="TextElement.Foreground" Value="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||
@@ -164,7 +164,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorDisabledBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeColorDefaultBrush}" />
|
||||
<Setter Property="TextElement.Foreground" Value="{DynamicResource TextFillColorDisabledBrush}" />
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<Styles
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:spp="https://steampp.net/ui"
|
||||
x:CompileBindings="True">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<!-- Add Controls for Previewer Here -->
|
||||
<StackPanel>
|
||||
<ToggleSwitch Name="loading" Content="Loading" />
|
||||
<ToggleSwitch Name="active" Content="Active" />
|
||||
<Grid
|
||||
MinWidth="400"
|
||||
HorizontalAlignment="Left"
|
||||
ColumnDefinitions="auto,*">
|
||||
<spp:Skeleton
|
||||
Width="100"
|
||||
Height="100"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
IsActive="{Binding #active.IsChecked}"
|
||||
IsLoading="{Binding #loading.IsChecked}">
|
||||
<Image RenderOptions.BitmapInterpolationMode="HighQuality" Source="avares://BD.WTTS.Client.Avalonia/UI/Assets/ApplicationIcon.ico" />
|
||||
</spp:Skeleton>
|
||||
<UniformGrid
|
||||
Grid.Column="1"
|
||||
Margin="5,0"
|
||||
Columns="1"
|
||||
Rows="3">
|
||||
<spp:Skeleton
|
||||
Margin="0,0,200,0"
|
||||
VerticalAlignment="Top"
|
||||
CornerRadius="2"
|
||||
IsActive="{Binding #active.IsChecked}"
|
||||
IsLoading="{Binding #loading.IsChecked}">
|
||||
<SelectableTextBlock Margin="0,2" Text="是先有鸡还是先有蛋" />
|
||||
</spp:Skeleton>
|
||||
<spp:Skeleton
|
||||
Margin="0,0,100,0"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
IsActive="{Binding #active.IsChecked}"
|
||||
IsLoading="{Binding #loading.IsChecked}">
|
||||
<SelectableTextBlock Margin="0,2" Text="什么是工匠精神" />
|
||||
</spp:Skeleton>
|
||||
<spp:Skeleton
|
||||
VerticalAlignment="Bottom"
|
||||
CornerRadius="2"
|
||||
IsActive="{Binding #active.IsChecked}"
|
||||
IsLoading="{Binding #loading.IsChecked}">
|
||||
<SelectableTextBlock Margin="0,2" Text="看山不是山,看水不是水,看山还是山,看水还是水" />
|
||||
</spp:Skeleton>
|
||||
</UniformGrid>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<Styles.Resources>
|
||||
<ControlTheme x:Key="{x:Type spp:Skeleton}" TargetType="spp:Skeleton">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="spp:Skeleton">
|
||||
<Border
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
ClipToBounds="{TemplateBinding ClipToBounds}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Panel>
|
||||
<ContentPresenter
|
||||
x:Name="PART_ContentPresenter"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
<spp:PureRectangle
|
||||
x:Name="PART_LoadingBorder"
|
||||
Background="{DynamicResource SkeletonDefaultBackground}"
|
||||
Classes.Active="{Binding Path=IsActive, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
IsHitTestVisible="{TemplateBinding IsLoading}"
|
||||
IsVisible="{TemplateBinding IsLoading}" />
|
||||
<spp:PureRectangle
|
||||
x:Name="PART_ActiveBorder"
|
||||
IsHitTestVisible="{TemplateBinding IsLoading}"
|
||||
IsVisible="{TemplateBinding IsLoading}" />
|
||||
</Panel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
</Styles.Resources>
|
||||
|
||||
<Style Selector="spp|Skeleton[IsActive=True][IsLoading=True] /template/ spp|PureRectangle#PART_ActiveBorder">
|
||||
<Style.Animations>
|
||||
<Animation
|
||||
Easing="CubicEaseInOut"
|
||||
FillMode="None"
|
||||
IterationCount="Infinite"
|
||||
PlaybackDirection="Alternate"
|
||||
Duration="0:0:1.4">
|
||||
<KeyFrame Cue="0%">
|
||||
<Setter Property="Background" Value="{DynamicResource SkeletonStartAnimationBackground}" />
|
||||
</KeyFrame>
|
||||
<KeyFrame Cue="100%">
|
||||
<Setter Property="Background" Value="{DynamicResource SkeletonEndAnimationBackground}" />
|
||||
</KeyFrame>
|
||||
</Animation>
|
||||
</Style.Animations>
|
||||
</Style>
|
||||
</Styles>
|
||||
@@ -95,7 +95,7 @@
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<LayoutTransformControl Name="PART_LayoutTransformControl" UseRenderTransform="True">
|
||||
<ui:FABorder
|
||||
<Border
|
||||
Name="ContentRoot"
|
||||
VerticalAlignment="Top"
|
||||
BorderBrush="{DynamicResource InfoBarBorderBrush}"
|
||||
@@ -205,13 +205,13 @@
|
||||
</Button>
|
||||
</Grid>
|
||||
</Panel>
|
||||
</ui:FABorder>
|
||||
</Border>
|
||||
</LayoutTransformControl>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^:informational">
|
||||
<Style Selector="^ /template/ ui|FABorder#ContentRoot">
|
||||
<Style Selector="^ /template/ Border#ContentRoot">
|
||||
<!--<Setter Property="Background" Value="{DynamicResource InfoBarInformationalSeverityBackgroundBrush}" />-->
|
||||
<Setter Property="Background" Value="{DynamicResource SolidBackgroundFillColorBaseBrush}" />
|
||||
</Style>
|
||||
@@ -226,7 +226,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:error">
|
||||
<Style Selector="^ /template/ ui|FABorder#ContentRoot">
|
||||
<Style Selector="^ /template/ Border#ContentRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource InfoBarErrorSeverityBackgroundBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Ellipse#IconBackground">
|
||||
@@ -241,7 +241,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:warning">
|
||||
<Style Selector="^ /template/ ui|FABorder#ContentRoot">
|
||||
<Style Selector="^ /template/ Border#ContentRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource InfoBarWarningSeverityBackgroundBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Ellipse#IconBackground">
|
||||
@@ -255,7 +255,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:success">
|
||||
<Style Selector="^ /template/ ui|FABorder#ContentRoot">
|
||||
<Style Selector="^ /template/ Border#ContentRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource InfoBarSuccessSeverityBackgroundBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Ellipse#IconBackground">
|
||||
@@ -294,7 +294,7 @@
|
||||
</Style>
|
||||
|
||||
<!-- Visible -->
|
||||
<Style Selector="^:hidden /template/ ui|FABorder#ContentRoot">
|
||||
<Style Selector="^:hidden /template/ Border#ContentRoot">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<ui:FABorder
|
||||
<Border
|
||||
Name="Root"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
@@ -83,19 +83,19 @@
|
||||
BorderThickness="1"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
TemplatedControl.IsTemplateFocusTarget="True">
|
||||
<ui:FABorder.Transitions>
|
||||
<Border.Transitions>
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="00:00:00.083" />
|
||||
</Transitions>
|
||||
</ui:FABorder.Transitions>
|
||||
</Border.Transitions>
|
||||
|
||||
<Panel>
|
||||
<ui:FABorder
|
||||
<Border
|
||||
Name="Hover"
|
||||
Margin="3"
|
||||
Background="Transparent"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<ui:FABorder.Transitions>
|
||||
<Border.Transitions>
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="00:00:00.083" />
|
||||
<TransformOperationsTransition
|
||||
@@ -103,8 +103,8 @@
|
||||
Property="RenderTransform"
|
||||
Duration="00:00:00.167" />
|
||||
</Transitions>
|
||||
</ui:FABorder.Transitions>
|
||||
</ui:FABorder>
|
||||
</Border.Transitions>
|
||||
</Border>
|
||||
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
@@ -139,19 +139,19 @@
|
||||
</Rectangle>
|
||||
|
||||
</Panel>
|
||||
</ui:FABorder>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
|
||||
<Style Selector="^:pointerover">
|
||||
<Style Selector="^ /template/ ui|FABorder#Hover">
|
||||
<Style Selector="^ /template/ Border#Hover">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pressed">
|
||||
<Style Selector="^ /template/ ui|FABorder#Hover">
|
||||
<Style Selector="^ /template/ Border#Hover">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorTertiaryBrush}" />
|
||||
<Setter Property="RenderTransform" Value="scale(0.96)" />
|
||||
</Style>
|
||||
@@ -161,10 +161,10 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:selected">
|
||||
<Style Selector="^ /template/ ui|FABorder#Hover">
|
||||
<Style Selector="^ /template/ Border#Hover">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorDefaultBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ControlElevationBorderBrush}" />
|
||||
</Style>
|
||||
@@ -181,10 +181,10 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Style Selector="^ /template/ ui|FABorder#Hover">
|
||||
<Style Selector="^ /template/ Border#Hover">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorDisabledBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ControlAltFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Panel Name="LayoutRoot" Background="{x:Null}">
|
||||
<ui:FABorder
|
||||
<Border
|
||||
Name="ContentRoot"
|
||||
MinWidth="{DynamicResource TaskDialogMinWidth}"
|
||||
MinHeight="{DynamicResource TaskDialogMinHeight}"
|
||||
@@ -216,7 +216,7 @@
|
||||
</ItemsControl>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ui:FABorder>
|
||||
</Border>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
@@ -303,7 +303,7 @@
|
||||
<Style Selector="^ /template/ Panel#LayoutRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource TaskDialogSmokeFill}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ui|FABorder#ContentRoot">
|
||||
<Style Selector="^ /template/ Border#ContentRoot">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource TaskDialogBorderBrush}" />
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource OverlayCornerRadius}" />
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource TaskDialogBorderWidth}" />
|
||||
@@ -332,7 +332,7 @@
|
||||
</Animation>
|
||||
</Style.Animations>
|
||||
</Style>
|
||||
<Style Selector="^:hidden /template/ ui|FABorder#ContentRoot">
|
||||
<Style Selector="^:hidden /template/ Border#ContentRoot">
|
||||
<Style.Animations>
|
||||
<Animation FillMode="Forward" Duration="00:00:00.167">
|
||||
<KeyFrame Cue="0%">
|
||||
@@ -368,7 +368,7 @@
|
||||
</Animation>
|
||||
</Style.Animations>
|
||||
</Style>
|
||||
<Style Selector="^:open /template/ ui|FABorder#ContentRoot">
|
||||
<Style Selector="^:open /template/ Border#ContentRoot">
|
||||
<Style.Animations>
|
||||
<Animation FillMode="Forward" Duration="00:00:00.250">
|
||||
<KeyFrame Cue="0%">
|
||||
@@ -389,7 +389,7 @@
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Panel Name="LayoutRoot" Background="{x:Null}">
|
||||
<ui:FABorder
|
||||
<Border
|
||||
Name="ContentRoot"
|
||||
MinWidth="{DynamicResource TaskDialogMinWidth}"
|
||||
MinHeight="{DynamicResource TaskDialogMinHeight}"
|
||||
@@ -521,7 +521,7 @@
|
||||
</ItemsControl>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ui:FABorder>
|
||||
</Border>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
@@ -14,4 +14,5 @@
|
||||
</Styles.Resources>
|
||||
|
||||
<StyleInclude Source="/UI/Styling/Controls.axaml" />
|
||||
<StyleInclude Source="avares://AvaloniaEdit/Themes/Fluent/AvaloniaEdit.xaml" />
|
||||
</Styles>
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
<x:String x:Key="Back"></x:String>
|
||||
<x:String x:Key="Sort"></x:String>
|
||||
<x:String x:Key="Move"></x:String>
|
||||
<x:String x:Key="Device"></x:String>
|
||||
|
||||
|
||||
<ui:ImageIconSource x:Key="AppIcon" Source="avares://BD.WTTS.Client.Avalonia/UI/Assets/ApplicationIcon.ico" />
|
||||
|
||||
@@ -21,4 +21,16 @@
|
||||
</OnPlatform>
|
||||
</RenderOptions.BitmapInterpolationMode>-->
|
||||
</ImageBrush>
|
||||
|
||||
<LinearGradientBrush x:Key="SkeletonStartAnimationBackground" StartPoint="0%,100%" EndPoint="100%,100%">
|
||||
<GradientStop Offset="0" Color="#FF1C1F23" />
|
||||
<GradientStop Offset="0" Color="#FF2E3238" />
|
||||
<GradientStop Offset="1" Color="#FF1C1F23" />
|
||||
</LinearGradientBrush>
|
||||
<LinearGradientBrush x:Key="SkeletonEndAnimationBackground" StartPoint="0%,100%" EndPoint="100%,100%">
|
||||
<GradientStop Offset="0" Color="#FF1C1F23" />
|
||||
<GradientStop Offset="1" Color="#FF2E3238" />
|
||||
<GradientStop Offset="1" Color="#FF1C1F23" />
|
||||
</LinearGradientBrush>
|
||||
<SolidColorBrush x:Key="SkeletonDefaultBackground" Color="#FF1C1F23" />
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -21,4 +21,16 @@
|
||||
</OnPlatform>
|
||||
</RenderOptions.BitmapInterpolationMode>-->
|
||||
</ImageBrush>
|
||||
|
||||
<LinearGradientBrush x:Key="SkeletonStartAnimationBackground" StartPoint="0%,100%" EndPoint="100%,100%">
|
||||
<GradientStop Offset="0" Color="#FFF9F9F9" />
|
||||
<GradientStop Offset="0" Color="#FFE6E8EA" />
|
||||
<GradientStop Offset="1" Color="#FFF9F9F9" />
|
||||
</LinearGradientBrush>
|
||||
<LinearGradientBrush x:Key="SkeletonEndAnimationBackground" StartPoint="0%,100%" EndPoint="100%,100%">
|
||||
<GradientStop Offset="0" Color="#FFF9F9F9" />
|
||||
<GradientStop Offset="1" Color="#FFE6E8EA" />
|
||||
<GradientStop Offset="1" Color="#FFF9F9F9" />
|
||||
</LinearGradientBrush>
|
||||
<SolidColorBrush x:Key="SkeletonDefaultBackground" Color="#FFF9F9F9" />
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -210,7 +210,7 @@
|
||||
<wnd:MinMaxCloseControl
|
||||
Name="SystemCaptionButtons"
|
||||
Height="{Binding TemplateSettings.TitleBarHeight, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Margin="18,0"
|
||||
Margin="14,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top" />
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions;
|
||||
using Avalonia.Rendering.Composition;
|
||||
using FluentAvalonia.UI.Controls.Experimental;
|
||||
using FluentAvalonia.UI.Navigation;
|
||||
|
||||
namespace BD.WTTS.UI.Views.Pages;
|
||||
|
||||
@@ -7,6 +9,8 @@ public class PageBase : UserControl
|
||||
{
|
||||
public PageBase() : base()
|
||||
{
|
||||
_disposables = new();
|
||||
|
||||
SizeChanged += PageBaseSizeChanged;
|
||||
|
||||
if (HeaderBackground == null)
|
||||
@@ -14,6 +18,8 @@ public class PageBase : UserControl
|
||||
this[!HeaderBackgroundProperty] = new DynamicResourceExtension("PageHeaderBackgroundBrush");
|
||||
}
|
||||
|
||||
_disposables.Add(UISettings.WindowBackgroundCustomImage.Subscribe(x => IsShowBackgroundImage = !x));
|
||||
|
||||
//AddHandler(Frame.NavigatingFromEvent, FrameNavigatingFrom, RoutingStrategies.Direct);
|
||||
//AddHandler(Frame.NavigatedToEvent, FrameNavigatedTo, RoutingStrategies.Direct);
|
||||
}
|
||||
@@ -139,6 +145,7 @@ public class PageBase : UserControl
|
||||
|
||||
//_previewImageHost = e.NameScope.Find<IconSourceElement>("PreviewImageElement");
|
||||
//_detailsHost = e.NameScope.Find<StackPanel>("DetailsTextHost");
|
||||
|
||||
_optionsHost = e.NameScope.Find<Panel>("OptionsRegion");
|
||||
_tabsHost = e.NameScope.Find<Border>("TabRegion");
|
||||
_detailsPanel = e.NameScope.Find<Panel>("PageDetails");
|
||||
@@ -157,6 +164,7 @@ public class PageBase : UserControl
|
||||
{
|
||||
base.OnUnloaded(e);
|
||||
_hasLoaded = false;
|
||||
_disposables.Dispose();
|
||||
}
|
||||
|
||||
private void PageBaseSizeChanged(object? sender, SizeChangedEventArgs e)
|
||||
@@ -266,33 +274,28 @@ public class PageBase : UserControl
|
||||
ec.ImplicitAnimations = ani;
|
||||
}
|
||||
|
||||
//private void FrameNavigatingFrom(object sender, NavigatingCancelEventArgs e)
|
||||
//private void FrameNavigatingFrom(object? sender, NavigatingCancelEventArgs e)
|
||||
//{
|
||||
// // If TargetType is not set, we know we're currently on a CoreControls page since those
|
||||
// // are grouped pages - whereas, FA controls only display one control per page and
|
||||
// // set all the extra properties
|
||||
// bool isFAControlPage = TargetType != null;
|
||||
|
||||
// // Only setup the ConnectedAnimation if it makes sense
|
||||
// if ((!isFAControlPage && e.SourcePageType == typeof(CoreControlsPageViewModel)) ||
|
||||
// (isFAControlPage && e.SourcePageType == typeof(FAControlsOverviewPageViewModel)))
|
||||
// if ((e.SourcePageType == typeof(HomePageViewModel)) ||
|
||||
// (e.SourcePageType == typeof(PluginStorePageViewModel)))
|
||||
// {
|
||||
// // Only setup the Back connected animation if we're going back to the
|
||||
// // controls list pages
|
||||
// var svc = ConnectedAnimationService.GetForView(TopLevel.GetTopLevel(this));
|
||||
// svc.PrepareToAnimate("BackAnimation", (Control)_previewImageHost.Parent);
|
||||
// NavigationService.Instance.PreviousPage = this;
|
||||
// //NavigationService.Instance.PreviousPage = this;
|
||||
// }
|
||||
//}
|
||||
|
||||
//private void FrameNavigatedTo(object sender, NavigationEventArgs e)
|
||||
//private void FrameNavigatedTo(object? sender, NavigationEventArgs e)
|
||||
//{
|
||||
// var svc = ConnectedAnimationService.GetForView(TopLevel.GetTopLevel(this));
|
||||
// var animation = svc.GetAnimation("ForwardAnimation");
|
||||
|
||||
// if (animation != null)
|
||||
// {
|
||||
// var coordinated = new List<Visual>
|
||||
// var coordinated = new List<Visual?>
|
||||
// {
|
||||
// _optionsHost,
|
||||
// _detailsHost,
|
||||
@@ -315,6 +318,7 @@ public class PageBase : UserControl
|
||||
//private IconSourceElement? _previewImageHost;
|
||||
//private StackPanel? _detailsHost;
|
||||
private ScrollViewer? _scroller;
|
||||
private CompositeDisposable _disposables;
|
||||
}
|
||||
|
||||
public class PageBase<TViewModel> : PageBase, IViewFor<TViewModel> where TViewModel : class
|
||||
@@ -324,13 +328,14 @@ public class PageBase<TViewModel> : PageBase, IViewFor<TViewModel> where TViewMo
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PageBase{TViewModel}"/> class.
|
||||
/// </summary>
|
||||
public PageBase()
|
||||
public PageBase() : base()
|
||||
{
|
||||
// This WhenActivated block calls ViewModel's WhenActivated
|
||||
// block if the ViewModel implements IActivatableViewModel.
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
disposables.Add(UISettings.WindowBackgroundCustomImage.Subscribe(x => IsShowBackgroundImage = !x));
|
||||
//disposables.Add(UISettings.WindowBackgroundCustomImage.Subscribe(x => IsShowBackgroundImage = !x));
|
||||
});
|
||||
this.GetObservable(ViewModelProperty).Subscribe(OnViewModelChanged);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<spp:Image2
|
||||
Width="{Binding $parent[UserControl].Bounds.Width}"
|
||||
Height="{Binding $parent[UserControl].Bounds.Height}"
|
||||
EnableCancelToken="False"
|
||||
Source="{Binding ImageUrl}"
|
||||
Stretch="UniformToFill" />
|
||||
</Button>
|
||||
|
||||
@@ -126,7 +126,7 @@ public class OptionsDisplayItem : TemplatedControl
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
_layoutRoot = e.NameScope.Find<FABorder>("LayoutRoot");
|
||||
_layoutRoot = e.NameScope.Find<Border>("LayoutRoot");
|
||||
if (_layoutRoot != null)
|
||||
{
|
||||
_layoutRoot.PointerPressed += OnLayoutRootPointerPressed;
|
||||
@@ -172,5 +172,5 @@ public class OptionsDisplayItem : TemplatedControl
|
||||
|
||||
private bool _isPressed;
|
||||
private bool _isExpanded;
|
||||
private FABorder? _layoutRoot;
|
||||
private Border? _layoutRoot;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public class PureCircle : Control
|
||||
{
|
||||
public static readonly StyledProperty<double> DiameterProperty = AvaloniaProperty.Register<PureCircle, double>(
|
||||
nameof(Diameter));
|
||||
|
||||
public double Diameter
|
||||
{
|
||||
get => GetValue(DiameterProperty);
|
||||
set => SetValue(DiameterProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush?>
|
||||
BackgroundProperty = Border.BackgroundProperty.AddOwner<PureCircle>();
|
||||
|
||||
public IBrush? Background
|
||||
{
|
||||
get => GetValue(BackgroundProperty);
|
||||
set => SetValue(BackgroundProperty, value);
|
||||
}
|
||||
|
||||
static PureCircle()
|
||||
{
|
||||
AffectsMeasure<PureCircle>(DiameterProperty);
|
||||
AffectsArrange<PureCircle>(DiameterProperty);
|
||||
AffectsRender<PureCircle>(BackgroundProperty, DiameterProperty);
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
double diameter = Math.Max(0, Diameter);
|
||||
return new Size(diameter, diameter);
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
double diameter = Math.Max(0, Diameter);
|
||||
return new Size(diameter, diameter);
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
double radius = Math.Max(0, Diameter) / 2;
|
||||
context.DrawEllipse(Background, null, new(radius, radius), radius, radius);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Provide the most simplified shape implementation. This is a rectangle with a background, without border and corner radius.
|
||||
/// </summary>
|
||||
public class PureRectangle : Control
|
||||
{
|
||||
public static readonly StyledProperty<IBrush?> BackgroundProperty =
|
||||
Border.BackgroundProperty.AddOwner<PureRectangle>();
|
||||
|
||||
public IBrush? Background
|
||||
{
|
||||
get => GetValue(BackgroundProperty);
|
||||
set => SetValue(BackgroundProperty, value);
|
||||
}
|
||||
|
||||
static PureRectangle()
|
||||
{
|
||||
AffectsRender<PureRectangle>(BackgroundProperty);
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
base.Render(context);
|
||||
context.DrawRectangle(Background, null, new Rect(Bounds.Size));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public class PureRing : PureCircle
|
||||
{
|
||||
public static readonly StyledProperty<double> InnerDiameterProperty = AvaloniaProperty.Register<PureRing, double>(
|
||||
nameof(InnerDiameter));
|
||||
|
||||
public double InnerDiameter
|
||||
{
|
||||
get => GetValue(InnerDiameterProperty);
|
||||
set => SetValue(InnerDiameterProperty, value);
|
||||
}
|
||||
|
||||
static PureRing()
|
||||
{
|
||||
AffectsRender<PureCircle>(InnerDiameterProperty);
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
double outer = Diameter / 2;
|
||||
double inner = InnerDiameter / 2;
|
||||
double thickness = outer - inner;
|
||||
context.DrawEllipse(null,
|
||||
new Pen(Background, outer - inner),
|
||||
new Point(outer, outer),
|
||||
outer - thickness / 2,
|
||||
outer - thickness / 2);
|
||||
}
|
||||
}
|
||||
@@ -62,14 +62,13 @@
|
||||
Margin="0,0,0,5"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom">
|
||||
<ItemsRepeater Name="Swiper" IsVisible="False">
|
||||
<ItemsRepeater.Layout>
|
||||
<StackLayout
|
||||
DisableVirtualization="True"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<ItemsControl Name="Swiper" IsVisible="False">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<DataTemplate.DataType>
|
||||
<x:Type x:TypeArguments="x:Int32, x:String" TypeName="generic:KeyValuePair" />
|
||||
@@ -110,8 +109,8 @@
|
||||
</i:Interaction.Behaviors>-->
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Panel>
|
||||
</Panel>
|
||||
</Border>
|
||||
|
||||
@@ -55,7 +55,7 @@ public class CarouselItems : ItemsControl
|
||||
Carousel? _carouselControl;
|
||||
Button? _leftButton;
|
||||
Button? _rightButton;
|
||||
ItemsRepeater? _swiper;
|
||||
ItemsControl? _swiper;
|
||||
Timer? _timer;
|
||||
|
||||
public ICommand? CarouselBannerIndexCommand { get; }
|
||||
@@ -72,7 +72,7 @@ public class CarouselItems : ItemsControl
|
||||
_carouselControl = e.NameScope.Find<Carousel>("CarouselControl");
|
||||
_leftButton = e.NameScope.Find<Button>("Left");
|
||||
_rightButton = e.NameScope.Find<Button>("Right");
|
||||
_swiper = e.NameScope.Find<ItemsRepeater>("Swiper");
|
||||
_swiper = e.NameScope.Find<Avalonia.Controls.ItemsControl>("Swiper");
|
||||
|
||||
if (_leftButton != null)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public class Skeleton : ContentControl
|
||||
{
|
||||
public static readonly StyledProperty<bool> IsActiveProperty =
|
||||
AvaloniaProperty.Register<Skeleton, bool>(nameof(IsActive));
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get { return GetValue(IsActiveProperty); }
|
||||
set { SetValue(IsActiveProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> IsLoadingProperty =
|
||||
AvaloniaProperty.Register<Skeleton, bool>(nameof(IsLoading));
|
||||
|
||||
public bool IsLoading
|
||||
{
|
||||
get => GetValue(IsLoadingProperty);
|
||||
set => SetValue(IsLoadingProperty, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<UserControl
|
||||
x:Class="BD.WTTS.UI.Views.Controls.WaveProgress"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:spp="https://steampp.net/ui"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Styles>
|
||||
<Style Selector="spp|WaveProgress">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border
|
||||
Canvas.Left="20"
|
||||
Canvas.Top="20"
|
||||
Canvas.Right="20"
|
||||
Canvas.Bottom="20"
|
||||
Width="200"
|
||||
Height="200"
|
||||
Margin="20"
|
||||
Background="Transparent"
|
||||
BorderBrush="{DynamicResource ControlElevationBorderBrush}"
|
||||
BorderThickness="1.2"
|
||||
BoxShadow="{DynamicResource LowShadow}"
|
||||
ClipToBounds="False"
|
||||
CornerRadius="100">
|
||||
<Border.Resources>
|
||||
<spp:WaveProgressValueConverter x:Key="WValueConvert" />
|
||||
<spp:WaveProgressValueTextConverter x:Key="WValueTextConvert" />
|
||||
<spp:WaveProgressValueColorConverter x:Key="WValueColorConvert" />
|
||||
<spp:WaveProgressGradientOffsetConverter x:Key="WGradientConverter" />
|
||||
</Border.Resources>
|
||||
|
||||
|
||||
<Border
|
||||
Width="200"
|
||||
Height="200"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="100">
|
||||
<Panel>
|
||||
<Canvas Width="200" Height="200">
|
||||
<Path
|
||||
Canvas.Top="{TemplateBinding Value,
|
||||
Converter={StaticResource WValueConvert}}"
|
||||
Classes="WaveAnimatedFast"
|
||||
Data="M 0,50 H 700 V 350 H 0 M 0,50 C 25,55 75,45 100,50 S 175,55 200,50 S 275,45 300,50 S 375,55 400,50 S 475,45 500,50 S 575,55 600,50 S 675,45 700,50"
|
||||
Fill="{TemplateBinding Value,
|
||||
Converter={StaticResource WGradientConverter}}"
|
||||
Opacity="0.45"
|
||||
StrokeThickness="0">
|
||||
|
||||
<Path.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Canvas.Top" Duration="0:0:1.5">
|
||||
<DoubleTransition.Easing>
|
||||
<CircularEaseOut />
|
||||
</DoubleTransition.Easing>
|
||||
</DoubleTransition>
|
||||
</Transitions>
|
||||
</Path.Transitions>
|
||||
</Path>
|
||||
<Path
|
||||
Canvas.Top="{TemplateBinding Value,
|
||||
Converter={StaticResource WValueConvert}}"
|
||||
Classes="WaveAnimated"
|
||||
Data="M 0,50 H 700 V 350 H 0 M 0,50 C 25,55 75,45 100,50 S 175,55 200,50 S 275,45 300,50 S 375,55 400,50 S 475,45 500,50 S 575,55 600,50 S 675,45 700,50"
|
||||
Fill="{TemplateBinding Value,
|
||||
Converter={StaticResource WGradientConverter}}"
|
||||
Opacity="0.8"
|
||||
StrokeThickness="0">
|
||||
<Path.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Canvas.Top" Duration="0:0:2.5">
|
||||
<DoubleTransition.Easing>
|
||||
<CircularEaseOut />
|
||||
</DoubleTransition.Easing>
|
||||
</DoubleTransition>
|
||||
</Transitions>
|
||||
</Path.Transitions>
|
||||
</Path>
|
||||
</Canvas>
|
||||
<TextBlock
|
||||
Name="PART_Text"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{TemplateBinding Value,
|
||||
Converter={StaticResource WValueColorConvert}}"
|
||||
Text="{TemplateBinding Value,
|
||||
Converter={StaticResource WValueTextConvert}}"
|
||||
Theme="{StaticResource TitleTextBlockStyle}">
|
||||
<TextBlock.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Opacity" Duration="0:0:0.3" />
|
||||
</Transitions>
|
||||
</TextBlock.Transitions>
|
||||
</TextBlock>
|
||||
</Panel>
|
||||
</Border>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="spp|WaveProgress[IsTextVisible=True] /template/ TextBlock#PART_Text">
|
||||
<Setter Property="Opacity" Value="1" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="spp|WaveProgress[IsTextVisible=False] /template/ TextBlock#PART_Text">
|
||||
<Setter Property="Opacity" Value="0" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Path.WaveAnimated">
|
||||
<Style.Animations>
|
||||
<Animation IterationCount="INFINITE" Duration="0:0:6">
|
||||
<KeyFrame Cue="0%">
|
||||
<Setter Property="Canvas.Left" Value="-100" />
|
||||
</KeyFrame>
|
||||
<KeyFrame Cue="100%">
|
||||
<Setter Property="Canvas.Left" Value="-500" />
|
||||
</KeyFrame>
|
||||
</Animation>
|
||||
</Style.Animations>
|
||||
</Style>
|
||||
<Style Selector="Path.WaveAnimatedFast">
|
||||
<Style.Animations>
|
||||
<Animation IterationCount="INFINITE" Duration="0:0:3">
|
||||
<KeyFrame Cue="0%">
|
||||
<Setter Property="Canvas.Left" Value="-100" />
|
||||
</KeyFrame>
|
||||
<KeyFrame Cue="100%">
|
||||
<Setter Property="Canvas.Left" Value="-500" />
|
||||
</KeyFrame>
|
||||
</Animation>
|
||||
</Style.Animations>
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,63 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public sealed partial class WaveProgress : UserControl
|
||||
{
|
||||
public static readonly DirectProperty<WaveProgress, double> ValueProperty =
|
||||
AvaloniaProperty.RegisterDirect<WaveProgress, double>(
|
||||
nameof(Value),
|
||||
o => o.Value,
|
||||
(o, v) => o.Value = v,
|
||||
defaultBindingMode: BindingMode.TwoWay,
|
||||
enableDataValidation: true);
|
||||
|
||||
public static readonly StyledProperty<bool> IsTextVisibleProperty =
|
||||
AvaloniaProperty.Register<WaveProgress, bool>(nameof(IsTextVisible), defaultValue: true);
|
||||
|
||||
public WaveProgress()
|
||||
{
|
||||
InitializeComponent();
|
||||
//var theme = App.Current.thm;
|
||||
//theme.OnBaseThemeChanged += _ =>
|
||||
//{
|
||||
// Value++;
|
||||
// Value--;
|
||||
//};
|
||||
//theme.OnColorThemeChanged += _ =>
|
||||
//{
|
||||
// Value++;
|
||||
// Value--;
|
||||
//};
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private double _value = 65;
|
||||
|
||||
public double Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (value is < 0 or > 100)
|
||||
return;
|
||||
|
||||
SetAndRaise(ValueProperty, ref _value, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsTextVisible
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetValue(IsTextVisibleProperty);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetValue(IsTextVisibleProperty, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,20 +139,24 @@
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||
Text="{Binding Path=Res.Link, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ItemsRepeater Margin="0,0,6,6" ItemsSource="{Binding Hyperlinks, Mode=OneTime}">
|
||||
<ItemsRepeater.Layout>
|
||||
<UniformGridLayout MinItemWidth="166" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<ItemsControl Margin="0,0,6,6" ItemsSource="{Binding Hyperlinks, Mode=OneTime}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="spp:HyperlinkModel">
|
||||
<Button
|
||||
Command="{Binding Command, Mode=OneWay}"
|
||||
Content="{Binding Text, Mode=OneWay}"
|
||||
Cursor="Hand"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
<Border MinWidth="166">
|
||||
<Button
|
||||
Command="{Binding Command, Mode=OneWay}"
|
||||
Content="{Binding Text, Mode=OneWay}"
|
||||
Cursor="Hand"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<Border
|
||||
Height="1"
|
||||
Margin="-50,0"
|
||||
@@ -162,20 +166,24 @@
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||
Text="{Binding Path=Res.OpenSourceLibrary, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ItemsRepeater Margin="0,0,6,6" ItemsSource="{Binding OSL, Mode=OneTime}">
|
||||
<ItemsRepeater.Layout>
|
||||
<UniformGridLayout MinItemWidth="290" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<ItemsControl Margin="0,0,6,6" ItemsSource="{Binding OSL, Mode=OneTime}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="spp:HyperlinkModel">
|
||||
<Button
|
||||
Command="{Binding Command, Mode=OneWay}"
|
||||
Content="{Binding Text, Mode=OneWay}"
|
||||
Cursor="Hand"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
<Border MinWidth="290">
|
||||
<Button
|
||||
Command="{Binding Command, Mode=OneWay}"
|
||||
Content="{Binding Text, Mode=OneWay}"
|
||||
Cursor="Hand"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</spp:OptionsDisplayItem.Content>
|
||||
</spp:OptionsDisplayItem>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
d:DesignWidth="800"
|
||||
x:CompileBindings="True"
|
||||
x:DataType="spp:DebugPageViewModel"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
mc:Ignorable="d">
|
||||
<Design.DataContext>
|
||||
<spp:DebugPageViewModel />
|
||||
@@ -149,7 +150,53 @@
|
||||
</Panel>
|
||||
|
||||
<Panel>
|
||||
<TextBlock Text="Test Control" />
|
||||
<StackPanel>
|
||||
<ToggleSwitch Name="loading" Content="Loading" />
|
||||
<ToggleSwitch Name="active" Content="Active" />
|
||||
<Grid
|
||||
MinWidth="400"
|
||||
HorizontalAlignment="Left"
|
||||
ColumnDefinitions="auto,*">
|
||||
<spp:Skeleton
|
||||
Width="100"
|
||||
Height="100"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
IsActive="{Binding #active.IsChecked}"
|
||||
IsLoading="{Binding #loading.IsChecked}">
|
||||
<Image RenderOptions.BitmapInterpolationMode="HighQuality" Source="avares://BD.WTTS.Client.Avalonia/UI/Assets/ApplicationIcon.ico" />
|
||||
</spp:Skeleton>
|
||||
<UniformGrid
|
||||
Grid.Column="1"
|
||||
Margin="5,0"
|
||||
Columns="1"
|
||||
Rows="3">
|
||||
<spp:Skeleton
|
||||
Margin="0,0,200,0"
|
||||
VerticalAlignment="Top"
|
||||
CornerRadius="2"
|
||||
IsActive="{Binding #active.IsChecked}"
|
||||
IsLoading="{Binding #loading.IsChecked}">
|
||||
<SelectableTextBlock Margin="0,2" Text="不忘初心,方得始终" />
|
||||
</spp:Skeleton>
|
||||
<spp:Skeleton
|
||||
Margin="0,0,100,0"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
IsActive="{Binding #active.IsChecked}"
|
||||
IsLoading="{Binding #loading.IsChecked}">
|
||||
<SelectableTextBlock Margin="0,2" Text="---" />
|
||||
</spp:Skeleton>
|
||||
<spp:Skeleton
|
||||
VerticalAlignment="Bottom"
|
||||
CornerRadius="2"
|
||||
IsActive="{Binding #active.IsChecked}"
|
||||
IsLoading="{Binding #loading.IsChecked}">
|
||||
<SelectableTextBlock Margin="0,2" Text="路漫漫其修远兮,吾将上下而求索。" />
|
||||
</spp:Skeleton>
|
||||
</UniformGrid>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Panel>
|
||||
</Carousel>
|
||||
</spp:PageBase>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
<Panel>
|
||||
<Image Source="/UI/Assets/back.png" Stretch="UniformToFill" />
|
||||
<!--<Image Source="/UI/Assets/back.png" Stretch="UniformToFill" />-->
|
||||
<!--<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
</Border>
|
||||
</spp:AppItem.Status>
|
||||
<spp:AppItem.Image>
|
||||
<spp:Image2 Source="{Binding ImageUrl}" />
|
||||
<spp:Image2 EnableCancelToken="False" Source="{Binding ImageUrl}" />
|
||||
</spp:AppItem.Image>
|
||||
</spp:AppItem>
|
||||
</DataTemplate>
|
||||
@@ -279,57 +279,60 @@
|
||||
ItemsSource="{Binding Shops}">
|
||||
<spp:CarouselItems.ItemTemplate>
|
||||
<DataTemplate x:DataType="spp:ShopRecommendGoodItem">
|
||||
<Border spp:Animations.EnableAnimations="True">
|
||||
<spp:AppItem
|
||||
Title="{Binding Name}"
|
||||
MaxWidth="260"
|
||||
Classes="Vertical Scale"
|
||||
ClickCommand="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
Cursor="Hand"
|
||||
Tags="{Binding GoodsAllCategorysText}"
|
||||
ToolTip.Tip="{Binding Brief}">
|
||||
<spp:AppItem.ClickCommandParameter>
|
||||
<MultiBinding Converter="{StaticResource StringFormatConverter}">
|
||||
<CompiledBinding Path="." Source="{x:Static spp:HomePageViewModel.WattGame_Goods_Detail_}" />
|
||||
<CompiledBinding Path="Id" />
|
||||
</MultiBinding>
|
||||
</spp:AppItem.ClickCommandParameter>
|
||||
<spp:AppItem.Image>
|
||||
<spp:Image2 RenderOptions.BitmapInterpolationMode="HighQuality" Source="{Binding Image}" />
|
||||
</spp:AppItem.Image>
|
||||
<spp:AppItem.Status>
|
||||
<Border Classes="Status">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
IsVisible="{Binding !!DiscountValue}"
|
||||
Text="{Binding Mktprice, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Static spp:CurrencyCode.CNY}}"
|
||||
TextDecorations="Strikethrough" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="{Binding Price, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Static spp:CurrencyCode.CNY}}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</spp:AppItem.Status>
|
||||
<spp:AppItem.ActionButton>
|
||||
<Border
|
||||
Height="24"
|
||||
Padding="8,0"
|
||||
Background="#4c6b22"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="4"
|
||||
IsVisible="{Binding !!DiscountValue}">
|
||||
<!--<Border spp:Animations.EnableAnimations="True">-->
|
||||
<spp:AppItem
|
||||
Title="{Binding Name}"
|
||||
MaxWidth="260"
|
||||
Classes="Vertical Scale"
|
||||
ClickCommand="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
Cursor="Hand"
|
||||
Tags="{Binding GoodsAllCategorysText}"
|
||||
ToolTip.Tip="{Binding Brief}">
|
||||
<spp:AppItem.ClickCommandParameter>
|
||||
<MultiBinding Converter="{StaticResource StringFormatConverter}">
|
||||
<CompiledBinding Path="." Source="{x:Static spp:HomePageViewModel.WattGame_Goods_Detail_}" />
|
||||
<CompiledBinding Path="Id" />
|
||||
</MultiBinding>
|
||||
</spp:AppItem.ClickCommandParameter>
|
||||
<spp:AppItem.Image>
|
||||
<spp:Image2
|
||||
EnableCancelToken="False"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="{Binding Image}" />
|
||||
</spp:AppItem.Image>
|
||||
<spp:AppItem.Status>
|
||||
<Border Classes="Status">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="#beee11"
|
||||
Text="{Binding DiscountValue, StringFormat={}-{0}%}" />
|
||||
</Border>
|
||||
</spp:AppItem.ActionButton>
|
||||
</spp:AppItem>
|
||||
</Border>
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
IsVisible="{Binding !!DiscountValue}"
|
||||
Text="{Binding Mktprice, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Static spp:CurrencyCode.CNY}}"
|
||||
TextDecorations="Strikethrough" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="{Binding Price, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Static spp:CurrencyCode.CNY}}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</spp:AppItem.Status>
|
||||
<spp:AppItem.ActionButton>
|
||||
<Border
|
||||
Height="24"
|
||||
Padding="8,0"
|
||||
Background="#4c6b22"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="4"
|
||||
IsVisible="{Binding !!DiscountValue}">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="#beee11"
|
||||
Text="{Binding DiscountValue, StringFormat={}-{0}%}" />
|
||||
</Border>
|
||||
</spp:AppItem.ActionButton>
|
||||
</spp:AppItem>
|
||||
<!--</Border>-->
|
||||
</DataTemplate>
|
||||
</spp:CarouselItems.ItemTemplate>
|
||||
</spp:CarouselItems>
|
||||
|
||||
@@ -7,7 +7,7 @@ public partial class HomePage : ReactiveUserControl<HomePageViewModel>
|
||||
public HomePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.SetViewModel<HomePageViewModel>();
|
||||
this.SetViewModel<HomePageViewModel>(useCache: true);
|
||||
|
||||
//ShopsScrollViewer.PointerWheelChanged += ShopsScrollViewer_PointerWheelChanged;
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|NavigationView.AppNav[IsBackButtonVisible=False] SplitView /template/ ContentPresenter#PART_PanePresenter">
|
||||
<Setter Property="Margin" Value="0 50 0 0" />
|
||||
<Setter Property="Margin" Value="0 42 0 0" />
|
||||
</Style>
|
||||
<Style Selector="ui|NavigationView.AppNav[IsBackButtonVisible=True] SplitView /template/ ContentPresenter#PART_PanePresenter">
|
||||
<Setter Property="Margin" Value="0 10 0 0" />
|
||||
<Setter Property="Margin" Value="0 2 0 0" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|NavigationViewItem.AppNav">
|
||||
@@ -216,9 +216,22 @@
|
||||
|
||||
<StackPanel VerticalAlignment="Center" IsVisible="{Binding Path=User, Mode=OneWay, Source={x:Static s:UserService.Current}, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}">
|
||||
<TextBlock Text="{Binding Path=User.NickName, Mode=OneWay, Source={x:Static s:UserService.Current}}" />
|
||||
|
||||
<Border VerticalAlignment="Center" IsVisible="{Binding Path=User.UserType, Mode=OneWay, Source={x:Static s:UserService.Current}, Converter={StaticResource EnumEqualValueConverter}, ConverterParameter={x:Static enum:UserType.Sponsor}}">
|
||||
<TextBlock FontSize="10" Text="{Binding Path=Res.User_Sponsor, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}❤️{0}}" />
|
||||
<Border
|
||||
Padding="5,1"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
IsVisible="{Binding Path=User.UserType, Mode=OneWay, Source={x:Static s:UserService.Current}, Converter={StaticResource EnumEqualValueConverter}, ConverterParameter={x:Static enum:UserType.Sponsor}}">
|
||||
<Border.Background>
|
||||
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
|
||||
<GradientStop Offset="0.0" Color="#453a94" />
|
||||
<GradientStop Offset="1.0" Color="#f43b47" />
|
||||
</LinearGradientBrush>
|
||||
</Border.Background>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="10"
|
||||
Foreground="White"
|
||||
Text="{Binding Path=Res.User_Sponsor, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}❤️{0}}" />
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
@@ -263,18 +276,18 @@
|
||||
</MenuItem.Header>
|
||||
</MenuItem>
|
||||
<MenuItem Header="-" IsVisible="{Binding Path=User, Mode=OneWay, Source={x:Static s:UserService.Current}, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}" />
|
||||
<MenuItem
|
||||
<MenuItem
|
||||
Command="{Binding Path=OpenAuthOfficialCommand, Source={x:Static s:UserService.Current}}"
|
||||
CommandParameter="https://steampp.net/account/center/info"
|
||||
Header="{Binding Path=Res.PersonalCenter, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
IsVisible="{Binding Path=User, Mode=OneWay, Source={x:Static s:UserService.Current}, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}" />
|
||||
<!--<MenuItem Header="{Binding Path=Res.MyOrder, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" IsVisible="{Binding Path=User, Mode=OneWay, Source={x:Static s:UserService.Current}, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}" />-->
|
||||
<MenuItem
|
||||
<!--<MenuItem Header="{Binding Path=Res.MyOrder, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" IsVisible="{Binding Path=User, Mode=OneWay, Source={x:Static s:UserService.Current}, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}" />-->
|
||||
<MenuItem
|
||||
Command="{Binding Path=OpenAuthOfficialCommand, Source={x:Static s:UserService.Current}}"
|
||||
CommandParameter="https://steampp.net/account/center/bind"
|
||||
Header="{Binding Path=Res.BindThirdPartyAccount, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
IsVisible="{Binding Path=User, Mode=OneWay, Source={x:Static s:UserService.Current}, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}" />
|
||||
<MenuItem
|
||||
<MenuItem
|
||||
Command="{Binding Path=OpenAuthOfficialCommand, Source={x:Static s:UserService.Current}}"
|
||||
CommandParameter="https://steampp.net/account/center/safe"
|
||||
Header="{Binding Path=Res.PersonalSafe, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
@@ -318,7 +331,7 @@
|
||||
PaneDisplayMode="Left">
|
||||
<ui:NavigationView.Resources>
|
||||
<!-- Override this -->
|
||||
<Thickness x:Key="NavigationViewContentMargin">0,60,0,0</Thickness>
|
||||
<Thickness x:Key="NavigationViewContentMargin">0,50,0,0</Thickness>
|
||||
</ui:NavigationView.Resources>
|
||||
<ui:NavigationView.Styles>
|
||||
<Style Selector="Button#NavigationViewBackButton">
|
||||
@@ -329,7 +342,7 @@
|
||||
<Setter Property="Content" Value="" />
|
||||
</Style>
|
||||
<Style Selector="Grid#PaneToggleButtonGrid">
|
||||
<Setter Property="Margin" Value="5 5 0 0" />
|
||||
<Setter Property="Margin" Value="5 0 0 0" />
|
||||
<Setter Property="ToolTip.Tip" Value="{Binding Path=Res.Back, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Setter Property="ToolTip.Placement" Value="Bottom" />
|
||||
</Style>
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
<UserControl
|
||||
x:Class="BD.WTTS.UI.Views.Pages.PluginStorePage"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:s="https://steampp.net/services"
|
||||
xmlns:spp="https://steampp.net/ui"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
x:CompileBindings="True"
|
||||
x:DataType="spp:PluginStorePageViewModel"
|
||||
mc:Ignorable="d">
|
||||
<ScrollViewer Padding="20">
|
||||
<!--<spp:ContentLoader IsLoading="False">-->
|
||||
<StackPanel
|
||||
x:Name="HomeRoot"
|
||||
MaxWidth="1080"
|
||||
Spacing="20">
|
||||
<TextBlock
|
||||
Margin="-3,0,0,0"
|
||||
Text="插件商店是什么?"
|
||||
Theme="{StaticResource TitleTextBlockStyle}" />
|
||||
|
||||
<TextBlock Text="3.0 版本的计划是将所有功能插件化,拆分后按需下载安装,每个人都可以只下载自己需要的插件功能使用,并且支持所有人都可以开发插件,等等还有许多暂时不方便说的内容,因为计划的过于异想天开,且遇到的问题有点多,所以开发难度有点点大,这个功能上线还需要一点时间,上线后 3.0 也将正式发布正式版,对一直等待的大家说声抱歉麻烦在多等等了 😭,如果您不习惯启动后是插件商店页面也可以在界面设置中修改启动默认页。" TextWrapping="WrapWithOverflow" />
|
||||
<TextBlock
|
||||
Margin="-3,0,0,0"
|
||||
Text="已安装功能"
|
||||
Theme="{StaticResource TitleTextBlockStyle}" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding MainWindow2.TabItems, Mode=OneWay, Source={x:Static s:IViewModelManager.Instance}}">
|
||||
<ItemsControl.Resources>
|
||||
<ControlTheme
|
||||
x:Key="NavButtonStyle"
|
||||
BasedOn="{StaticResource {x:Type Button}}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Width" Value="120" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Margin" Value="6" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
||||
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="ClipToBounds" Value="True" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ItemsControl.Resources>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="spp:TabItemViewModel">
|
||||
<Border spp:Animations.EnableAnimations="True">
|
||||
<Button
|
||||
Command="{Binding $parent[spp:PluginStorePage].((spp:PluginStorePageViewModel)DataContext).NavgationToMenuPageCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Theme="{StaticResource NavButtonStyle}">
|
||||
<Grid RowDefinitions="3*,*">
|
||||
<Border
|
||||
Name="IconHost"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
CornerRadius="4 4 0 0"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality">
|
||||
<spp:Image2
|
||||
Width="96"
|
||||
Height="96"
|
||||
Margin="0,10,0,0"
|
||||
Source="{Binding IconKey}"
|
||||
Stretch="Uniform" />
|
||||
</Border>
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="12"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding Name}" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,92 @@
|
||||
using FluentAvalonia.UI.Controls.Experimental;
|
||||
using FluentAvalonia.UI.Navigation;
|
||||
|
||||
namespace BD.WTTS.UI.Views.Pages;
|
||||
|
||||
public partial class PluginStorePage : UserControl
|
||||
{
|
||||
public PluginStorePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.SetViewModel<PluginStorePageViewModel>(useCache: true);
|
||||
|
||||
// Use the frame events here to ensure ConnectedAnimations still work with
|
||||
// Back/Forward navigation and not just explicit page invokes
|
||||
//AddHandler(Frame.NavigatingFromEvent, OnNavigatingFrom, RoutingStrategies.Direct);
|
||||
//AddHandler(Frame.NavigatedToEvent, OnNavigatedTo, RoutingStrategies.Direct);
|
||||
|
||||
}
|
||||
|
||||
//private void PluginStorePage_Click(object? sender, RoutedEventArgs e)
|
||||
//{
|
||||
// if (sender != null && sender is Button b && b.DataContext is TabItemViewModel fci)
|
||||
// {
|
||||
// _animationPage = fci;
|
||||
// //NavigationService.Instance.NavigateFromContext(fci);
|
||||
// }
|
||||
//}
|
||||
|
||||
//private void OnNavigatedTo(object? sender, NavigationEventArgs e)
|
||||
//{
|
||||
// if (_animationPage == null)
|
||||
// return;
|
||||
|
||||
// var svc = ConnectedAnimationService.GetForView(TopLevel.GetTopLevel(this));
|
||||
// var anim = svc.GetAnimation("BackAnimation");
|
||||
|
||||
// if (anim == null)
|
||||
// return;
|
||||
|
||||
// var item = this.GetVisualDescendants()
|
||||
// ?.Where(x => x is Button && x.DataContext == _animationPage)
|
||||
// ?.FirstOrDefault()
|
||||
// ?.GetVisualDescendants()
|
||||
// .Where(x => x is Border && x.Name == "IconHost")
|
||||
// .FirstOrDefault();
|
||||
|
||||
// var presenter = item;// GetAnimationSource();
|
||||
|
||||
// // In WinUI, ConnectedAnimation is somehow exempt from all clipping behaviors
|
||||
// // Here, we are not, so disable ClipToBounds on all elements in the SettingsExpander
|
||||
// // The rest are taken care of in the xaml.
|
||||
// // NOTE: The ScrollViewer is not changed here as that's important for scrolling - thus
|
||||
// // the animation will be cut off, but the back animation is pretty fast and mostly is
|
||||
// // only visible closer to the element so we're ok, I think
|
||||
// var x = presenter?.GetVisualParent();
|
||||
|
||||
// while (!(x is ScrollContentPresenter) && x != null)
|
||||
// {
|
||||
// x.ClipToBounds = false;
|
||||
// x = x.GetVisualParent();
|
||||
// }
|
||||
|
||||
// anim.Configuration = new DirectConnectedAnimationConfiguration();
|
||||
// anim.TryStart(presenter);
|
||||
//}
|
||||
|
||||
//private void OnNavigatingFrom(object? sender, NavigatingCancelEventArgs e)
|
||||
//{
|
||||
// if (_animationPage == null)
|
||||
// return;
|
||||
|
||||
// // We're not navigating to a control page, don't set up the animation & clear
|
||||
// // the previous animation source
|
||||
// if (!e.SourcePageType.Name.Equals(nameof(TabItemViewModel)))
|
||||
// {
|
||||
// _animationPage = null;
|
||||
// _animationPage = null;
|
||||
// return;
|
||||
// }
|
||||
|
||||
// var item = this.GetVisualDescendants()
|
||||
// ?.Where(x => x is ListBoxItem && x.DataContext == _animationPage)
|
||||
// ?.FirstOrDefault()
|
||||
// ?.GetVisualDescendants()
|
||||
// .Where(x => x is Viewbox && x.Name == "IconHost")
|
||||
// .FirstOrDefault();
|
||||
// var svc = ConnectedAnimationService.GetForView(TopLevel.GetTopLevel(this));
|
||||
// svc.PrepareToAnimate("ForwardAnimation", item);
|
||||
//}
|
||||
|
||||
//private TabItemViewModel? _animationPage;
|
||||
}
|
||||
@@ -102,6 +102,7 @@
|
||||
Command="{Binding $parent[spp:Settings_Plugin].((spp:SettingsPageViewModel)DataContext).DeletePlugin_Click}"
|
||||
CommandParameter="{Binding Data}"
|
||||
Content="{Binding Path=Res.Plugin_Delete, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
|
||||
IsClickEnabled="True" />
|
||||
</ui:SettingsExpander>
|
||||
</DataTemplate>
|
||||
|
||||
@@ -22,6 +22,23 @@
|
||||
Text="{Binding Path=Res.Settings_UI, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
|
||||
<Border>
|
||||
<ui:SettingsExpander Header="{Binding Path=Res.Settings_UI_StartDefaultPage, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<ui:FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="{StaticResource Device}" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ComboBox ItemsSource="{Binding Path=MainWindow2.TabItems, Mode=OneWay, Source={x:Static s:IViewModelManager.Instance}}" SelectedItem="{Binding SelectDefaultPage, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate DataType="spp:TabItemViewModel">
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</Border>
|
||||
|
||||
<Border IsEnabled="{Binding Path=User, Mode=OneWay, Source={x:Static s:UserService.Current}, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}">
|
||||
<ui:SettingsExpander
|
||||
Description="{Binding Path=Res.Advertisement_NoShow_Tip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
|
||||
@@ -172,13 +172,13 @@
|
||||
|
||||
<WrapPanel Margin="0,20" HorizontalAlignment="Center">
|
||||
<TextBlock Text="{Binding Path=Res.User_LoginUnexpectedPrompt, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<ui:HyperlinkButton
|
||||
<HyperlinkButton
|
||||
Margin="5,0"
|
||||
Padding="0"
|
||||
HorizontalContentAlignment="Center"
|
||||
Command="{Binding ManualLogin}">
|
||||
<TextBlock Text="{Binding Path=Res.Login_ManualLogin, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</ui:HyperlinkButton>
|
||||
</HyperlinkButton>
|
||||
</WrapPanel>
|
||||
|
||||
<ProgressBar
|
||||
@@ -222,23 +222,23 @@
|
||||
FontSize="12"
|
||||
Text="{Binding Path=Res.User_RegisterAgreed, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<ui:HyperlinkButton
|
||||
<HyperlinkButton
|
||||
Margin="5,0"
|
||||
Padding="0"
|
||||
Command="{Binding OpenHyperlink}"
|
||||
CommandParameter="Agreement"
|
||||
Cursor="Hand">
|
||||
<TextBlock Text="{Binding Path=Res.User_Agreement, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</ui:HyperlinkButton>
|
||||
</HyperlinkButton>
|
||||
<TextBlock Text="{Binding Path=Res.And, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<ui:HyperlinkButton
|
||||
<HyperlinkButton
|
||||
Margin="5,0"
|
||||
Padding="0"
|
||||
Command="{Binding OpenHyperlink}"
|
||||
CommandParameter="Privacy"
|
||||
Cursor="Hand">
|
||||
<TextBlock Text="{Binding Path=Res.User_Privacy, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</ui:HyperlinkButton>
|
||||
</HyperlinkButton>
|
||||
</WrapPanel>
|
||||
|
||||
<StackPanel
|
||||
|
||||
@@ -45,6 +45,17 @@ public partial class LoginOrRegisterPage : ReactiveUserControl<LoginOrRegisterWi
|
||||
this.ViewModel.Close(false);
|
||||
}
|
||||
}
|
||||
// 11.1 使用新 API https://docs.avaloniaui.net/docs/concepts/services/activatable-lifetime#handling-uri-activation
|
||||
//if (Application.Current.TryGetFeature<IActivatableLifetime>() is { } activatableLifetime)
|
||||
//{
|
||||
// activatableLifetime.Activated += (s, a) =>
|
||||
// {
|
||||
// if (a is ProtocolActivatedEventArgs protocolArgs && protocolArgs.Kind == ActivationKind.OpenUri)
|
||||
// {
|
||||
// Console.WriteLine($"App activated via Uri: {protocolArgs.Uri}");
|
||||
// }
|
||||
// };
|
||||
//}
|
||||
Application.Current!.UrlsOpened += Current_UrlsOpened;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,36 @@ public sealed partial class MainWindow : ReactiveAppWindow<MainWindowViewModel>
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
DateTime lastOpenedTime;
|
||||
|
||||
internal bool SetStartDefaultPageName()
|
||||
{
|
||||
if (NavigationService.Instance.CurrnetPage != null)
|
||||
return false;
|
||||
|
||||
var mw2 = IViewModelManager.Instance.MainWindow2;
|
||||
if (mw2 == null)
|
||||
return false;
|
||||
|
||||
Type? pageType = null;
|
||||
if (!string.IsNullOrEmpty(UISettings.StartDefaultPageName.Value))
|
||||
{
|
||||
var tabItems = mw2?.TabItems;
|
||||
if (tabItems == null)
|
||||
return false;
|
||||
|
||||
var page = tabItems.OfType<MenuTabItemViewModel>()
|
||||
.FirstOrDefault(s => s.Id == UISettings.StartDefaultPageName.Value);
|
||||
if (page != null)
|
||||
{
|
||||
pageType = page.PageType;
|
||||
}
|
||||
}
|
||||
INavigationService.Instance.Navigate(pageType ?? typeof(PluginStorePage));
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override async void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
if (Steamworks.SteamClient.IsValid)
|
||||
@@ -46,24 +75,23 @@ public sealed partial class MainWindow : ReactiveAppWindow<MainWindowViewModel>
|
||||
}
|
||||
if (AppSplashScreen.IsInitialized)
|
||||
{
|
||||
if (NavigationService.Instance.CurrnetPage == null)
|
||||
{
|
||||
INavigationService.Instance.Navigate(typeof(HomePage));
|
||||
}
|
||||
Task2.InBackground(async () =>
|
||||
{
|
||||
IViewModelManager.Instance.Get<HomePageViewModel>().GetServerContent();
|
||||
await AdvertiseService.Current.RefrshAdvertiseAsync();
|
||||
NoticeService.Current.GetNewsAsync();
|
||||
});
|
||||
try // 在主窗口显示时调用此函数检查是否需要显示新版本通知窗口
|
||||
{
|
||||
Ioc.Get_Nullable<IAppUpdateService>()?.OnMainOpenTryShowNewVersionWindow();
|
||||
}
|
||||
catch
|
||||
{
|
||||
SetStartDefaultPageName();
|
||||
}
|
||||
if (lastOpenedTime == default ||
|
||||
(DateTime.Now - lastOpenedTime) > TimeSpan.FromMinutes(30))
|
||||
{
|
||||
lastOpenedTime = DateTime.Now;
|
||||
await IViewModelManager.Instance.Get<HomePageViewModel>().GetServerContent();
|
||||
await AdvertiseService.Current.RefrshAdvertiseAsync();
|
||||
await NoticeService.Current.GetNewsAsync();
|
||||
}
|
||||
try // 在主窗口显示时调用此函数检查是否需要显示新版本通知窗口
|
||||
{
|
||||
Ioc.Get_Nullable<IAppUpdateService>()?.OnMainOpenTryShowNewVersionWindow();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,7 +100,7 @@ public sealed class AppSplashScreen : IApplicationSplashScreen
|
||||
{
|
||||
public static bool IsInitialized = false;
|
||||
|
||||
public WindowViewModel? ViewModel { get; }
|
||||
//public WindowViewModel? ViewModel { get; }
|
||||
|
||||
public string? AppName { get; }
|
||||
|
||||
@@ -162,7 +190,7 @@ public sealed class AppSplashScreen : IApplicationSplashScreen
|
||||
});
|
||||
|
||||
AdvertiseService.Current.InitAdvertise();
|
||||
NoticeService.Current.GetNewsAsync();
|
||||
await NoticeService.Current.GetNewsAsync();
|
||||
|
||||
var mainWindow = App.Instance.MainWindow;
|
||||
mainWindow.ThrowIsNull();
|
||||
@@ -188,7 +216,7 @@ public sealed class AppSplashScreen : IApplicationSplashScreen
|
||||
#endif
|
||||
new MenuTabItemViewModel("Plugin_Store")
|
||||
{
|
||||
PageType = null,
|
||||
PageType = typeof(PluginStorePage),
|
||||
IsResourceGet = true,
|
||||
IconKey = "avares://BD.WTTS.Client.Avalonia/UI/Assets/Icons/store.ico",
|
||||
},
|
||||
@@ -205,8 +233,10 @@ public sealed class AppSplashScreen : IApplicationSplashScreen
|
||||
{
|
||||
mainWindow.DataContext = IViewModelManager.Instance.MainWindow;
|
||||
s.InitSettingSubscribe();
|
||||
|
||||
INavigationService.Instance.Navigate(typeof(HomePage));
|
||||
if (mainWindow is MainWindow mainWindow1)
|
||||
{
|
||||
mainWindow1.SetStartDefaultPageName();
|
||||
}
|
||||
});
|
||||
#if STARTUP_WATCH_TRACE || DEBUG
|
||||
WatchTrace.Record("InitMainWindowViewModel");
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace BD;
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false)]
|
||||
public sealed class MobiusAttribute : Attribute
|
||||
{
|
||||
public MobiusAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MobiusAttribute(string str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool Obsolete { get; set; }
|
||||
}
|
||||
@@ -6,6 +6,7 @@ namespace BD.WTTS.Services;
|
||||
/// <summary>
|
||||
/// 子进程的 IPC 服务实现
|
||||
/// </summary>
|
||||
[Mobius(Obsolete = true)]
|
||||
public interface IPCSubProcessService : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
@@ -93,6 +94,9 @@ public interface IPCSubProcessService : IDisposable
|
||||
var nativeLibraryPath = Environment.GetEnvironmentVariable(EnvKey_NativeLibraryPath);
|
||||
if (!string.IsNullOrWhiteSpace(nativeLibraryPath))
|
||||
{
|
||||
var nativeLibraryPaths = nativeLibraryPath.Split(';',
|
||||
StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// 监听当前应用程序域的程序集加载
|
||||
AppDomain.CurrentDomain.AssemblyLoad += (_, args)
|
||||
=> CurrentDomain_AssemblyLoad(args.LoadedAssembly);
|
||||
@@ -119,23 +123,34 @@ public interface IPCSubProcessService : IDisposable
|
||||
return libraryName;
|
||||
}
|
||||
var libraryFileName = GetLibraryFileName(libraryName);
|
||||
var libraryPath = Path.Combine(nativeLibraryPath, libraryFileName);
|
||||
if (File.Exists(libraryPath) &&
|
||||
NativeLibrary.TryLoad(libraryPath, out var handle))
|
||||
string libraryPath = libraryName;
|
||||
try
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
else if (!OperatingSystem.IsWindows() && !libraryFileName.StartsWith("lib", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
libraryFileName = $"lib{libraryFileName}";
|
||||
libraryPath = Path.Combine(nativeLibraryPath, libraryFileName);
|
||||
if (File.Exists(libraryPath) &&
|
||||
NativeLibrary.TryLoad(libraryPath, out handle))
|
||||
foreach (var nativeLibraryPath in nativeLibraryPaths)
|
||||
{
|
||||
return handle;
|
||||
libraryPath = Path.Combine(nativeLibraryPath, libraryFileName);
|
||||
if (File.Exists(libraryPath) &&
|
||||
NativeLibrary.TryLoad(libraryPath, out var handle))
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
else if (!OperatingSystem.IsWindows() && !libraryFileName.StartsWith("lib", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
libraryFileName = $"lib{libraryFileName}";
|
||||
libraryPath = Path.Combine(nativeLibraryPath, libraryFileName);
|
||||
if (File.Exists(libraryPath) &&
|
||||
NativeLibrary.TryLoad(libraryPath, out handle))
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NativeLibrary.Load(libraryName, assembly, searchPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new FileNotFoundException(null, libraryPath, ex);
|
||||
}
|
||||
return NativeLibrary.Load(libraryName, assembly, searchPath);
|
||||
}
|
||||
NativeLibrary.SetDllImportResolver(loadedAssembly, Delegate);
|
||||
}
|
||||
|
||||
+1
@@ -123,6 +123,7 @@ public static class KestrelServerOptionsExtensions
|
||||
var httpsPort = IReverseProxyConfig.HttpsPort;
|
||||
options.Listen(IReverseProxyService.Constants.Instance.ProxyIp, httpsPort, listen =>
|
||||
{
|
||||
listen.Protocols = HttpProtocols.Http1AndHttp2;
|
||||
listen.UseFlowAnalyze();
|
||||
listen.UseTls();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace BD;
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false)]
|
||||
public sealed class MobiusAttribute : Attribute
|
||||
{
|
||||
public MobiusAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MobiusAttribute(string str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool Obsolete { get; set; }
|
||||
}
|
||||
+15
-1
@@ -155,7 +155,21 @@ public static class CertGenerator
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddDnsName(name);
|
||||
try
|
||||
{
|
||||
builder.AddDnsName(name);
|
||||
}
|
||||
catch
|
||||
{
|
||||
/* name = Environment.MachineName
|
||||
* System.ArgumentException: Decoded string is not a valid IDN name. (Parameter 'unicode')
|
||||
* at System.Globalization.IdnMapping.IcuGetAsciiCore(String unicodeString, Char* unicode, Int32 count)
|
||||
* at System.Globalization.IdnMapping.GetAscii(String unicode, Int32 index, Int32 count)
|
||||
* at System.Security.Cryptography.X509Certificates.SubjectAlternativeNameBuilder.AddDnsName(String dnsName)
|
||||
* at BD.WTTS.Services.Implementation.CertGenerator.Add(SubjectAlternativeNameBuilder builder, String name)
|
||||
* at BD.WTTS.Services.Implementation.CertGenerator.CreateEndCertificate(X509Certificate2 issuerCertificate, X500DistinguishedName subjectName, IEnumerable`1 extraDnsNames, Nullable`1 notBefore, Nullable`1 notAfter, Int32 rsaKeySizeInBits)
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
@@ -450,4 +450,36 @@ sealed partial class CertificateManagerImpl : ICertificateManager
|
||||
var result = ICertificateManager.Constants.IsCertificateInstalled(platformService, packable);
|
||||
return result;
|
||||
}
|
||||
|
||||
public string GetCertificateInfo()
|
||||
{
|
||||
var rootCert = RootCertificate;
|
||||
if (rootCert == null)
|
||||
{
|
||||
GenerateCertificate();
|
||||
}
|
||||
rootCert = RootCertificate;
|
||||
|
||||
if (rootCert == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder b = new();
|
||||
b.AppendLine("Subject:");
|
||||
b.AppendLine(rootCert.Subject);
|
||||
b.AppendLine("SerialNumber:");
|
||||
b.AppendLine(rootCert.SerialNumber);
|
||||
b.AppendLine("PeriodValidity:");
|
||||
b.Append(rootCert.GetEffectiveDateString());
|
||||
b.Append(" ~ ");
|
||||
b.Append(rootCert.GetExpirationDateString());
|
||||
b.AppendLine();
|
||||
b.AppendLine("SHA256:");
|
||||
b.AppendLine(rootCert.GetCertHashStringCompat(HashAlgorithmName.SHA256));
|
||||
b.AppendLine("SHA1:");
|
||||
b.AppendLine(rootCert.GetCertHashStringCompat(HashAlgorithmName.SHA1));
|
||||
|
||||
return b.ToString();
|
||||
}
|
||||
}
|
||||
+5
@@ -46,4 +46,9 @@ sealed class LazyCertificateManager : ICertificateManager
|
||||
{
|
||||
return impl().DeleteRootCertificate();
|
||||
}
|
||||
|
||||
public string GetCertificateInfo()
|
||||
{
|
||||
return impl().GetCertificateInfo();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ sealed class ReverseProxyHttpClientHandler : DelegatingHandler
|
||||
var tlsSniValue = domainConfig.GetTlsSniPattern().WithDomain(uri.Host).WithRandom();
|
||||
request.SetRequestContext(new RequestContext(isHttps, tlsSniValue));
|
||||
|
||||
// 设置请求头 host,修改协议为 http
|
||||
// 设置请求头 host,因为连接中已带端口号故 修改协议为 http
|
||||
request.Headers.Host = uri.Host;
|
||||
request.RequestUri = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttp }.Uri;
|
||||
|
||||
|
||||
+29
-2
@@ -80,7 +80,15 @@ sealed partial class HttpReverseProxyMiddleware
|
||||
return;
|
||||
}
|
||||
|
||||
var destinationPrefix = GetDestinationPrefix(context.Request.Scheme, context.Request.Host, domainConfig.Destination);
|
||||
var destination = domainConfig.Destination;
|
||||
if (domainConfig.Destination?.AbsoluteUri.Contains("@") == true)
|
||||
{
|
||||
var newUrl = domainConfig.Destination.AbsoluteUri.Replace("@domain", context.Request.Host.Host);
|
||||
newUrl = newUrl.Replace("@uri", context.Request.RawUrl());
|
||||
destination = new Uri(newUrl);
|
||||
}
|
||||
|
||||
var destinationPrefix = GetDestinationPrefix(context.Request.Scheme, context.Request.Host, destination);
|
||||
var httpClient = httpClientFactory.CreateHttpClient(context.Request.Host.Host, domainConfig);
|
||||
if (!string.IsNullOrEmpty(domainConfig.UserAgent))
|
||||
{
|
||||
@@ -89,9 +97,19 @@ sealed partial class HttpReverseProxyMiddleware
|
||||
|
||||
var forwarderRequestConfig = new ForwarderRequestConfig()
|
||||
{
|
||||
Version = context.Request.Protocol.StartsWith("HTTP/2") ? System.Net.HttpVersion.Version20 : System.Net.HttpVersion.Version11,
|
||||
Version = context.Request.Protocol switch
|
||||
{
|
||||
var protocol when protocol.StartsWith("HTTP/2") => System.Net.HttpVersion.Version20,
|
||||
var protocol when protocol.StartsWith("HTTP/3") => System.Net.HttpVersion.Version30,
|
||||
_ => System.Net.HttpVersion.Version11,
|
||||
},
|
||||
};
|
||||
|
||||
if (domainConfig.IsServerSideProxy)
|
||||
{
|
||||
SetWattHeaders(context, reverseProxyConfig.Service.ServerSideProxyToken);
|
||||
}
|
||||
|
||||
var error = await httpForwarder.SendAsync(context, destinationPrefix, httpClient, forwarderRequestConfig, HttpTransformer.Empty);
|
||||
|
||||
if (error != ForwarderError.None)
|
||||
@@ -393,6 +411,15 @@ sealed partial class HttpReverseProxyMiddleware
|
||||
return false;
|
||||
}
|
||||
|
||||
static void SetWattHeaders(HttpContext context, string? token)
|
||||
{
|
||||
context.Request.Headers.TryAdd("X-Watt-Origin-Dest-Scheme", context.Request.Scheme);
|
||||
context.Request.Headers.TryAdd("X-Watt-Origin-Dest-Host", context.Request.Host.ToString());
|
||||
context.Request.Headers.TryAdd("X-Watt-Origin-Dest-PathAndQuery", context.Request.GetEncodedPathAndQuery());
|
||||
|
||||
context.Request.Headers.TryAdd("X-Watt-Token", token ?? string.Empty);
|
||||
}
|
||||
|
||||
const int UTF8PreambleLength = 3;
|
||||
const byte UTF8PreambleByte2 = 0xBF;
|
||||
const int UTF8PreambleFirst2Bytes = 0xEFBB;
|
||||
|
||||
+3
-2
@@ -89,6 +89,8 @@ abstract class ReverseProxyServiceImpl : IReverseProxySettings
|
||||
|
||||
public string? CustomDohAddres { get; set; }
|
||||
|
||||
public string? ServerSideProxyToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个随机的未使用的端口
|
||||
/// </summary>
|
||||
@@ -157,7 +159,7 @@ abstract class ReverseProxyServiceImpl : IReverseProxySettings
|
||||
return StartProxyResultCode.DeserializeReverseProxySettingsFail;
|
||||
}
|
||||
|
||||
// Linux 如果是443 需要验证 是否允许使用
|
||||
// Linux 如果是443 需要验证 是否允许使用
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(reverseProxySettings.ProxyIp))
|
||||
@@ -178,7 +180,6 @@ abstract class ReverseProxyServiceImpl : IReverseProxySettings
|
||||
|
||||
protected virtual void CheckRootCertificate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected abstract Task<StartProxyResult> StartProxyImpl();
|
||||
|
||||
+9
@@ -193,6 +193,9 @@ public interface ICertificateManager
|
||||
var isRootCertificateInstalled = IsCertificateInstalled();
|
||||
if (!isRootCertificateInstalled)
|
||||
{
|
||||
// 生成证书
|
||||
certificateManager.GenerateCertificate();
|
||||
|
||||
// 安装证书
|
||||
ICertificateManager.Constants.TrustRootCertificate(
|
||||
GetCerFilePath, platformService, certificate2);
|
||||
@@ -271,4 +274,10 @@ public interface ICertificateManager
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
bool? GenerateCertificate();
|
||||
|
||||
/// <summary>
|
||||
/// 获取证书信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
string GetCertificateInfo();
|
||||
}
|
||||
+16
-3
@@ -1,6 +1,9 @@
|
||||
using dotnetCampus.Ipc.CompilerServices.Attributes;
|
||||
|
||||
#if APP_REVERSE_PROXY
|
||||
|
||||
using InstanceReverseProxyService = BD.WTTS.Services.Implementation.YarpReverseProxyServiceImpl;
|
||||
|
||||
#else
|
||||
using InstanceReverseProxyService = BD.WTTS.Services.IReverseProxyService;
|
||||
#endif
|
||||
@@ -59,6 +62,7 @@ public partial interface IReverseProxyService : IDisposable
|
||||
Task StopProxyAsync();
|
||||
|
||||
#if DEBUG
|
||||
|
||||
string GetDebugString()
|
||||
{
|
||||
return $"Pid: {Environment.ProcessId}, Exe: {Environment.ProcessPath}, Asm: {Assembly.GetAssembly(GetType())?.FullName}";
|
||||
@@ -69,6 +73,7 @@ public partial interface IReverseProxyService : IDisposable
|
||||
StartProxyResult r = new(StartProxyResultCode.Exception, new Exception("aaaa"));
|
||||
return Task.FromResult(r);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -139,7 +144,7 @@ public partial interface IReverseProxySettings
|
||||
/// </summary>
|
||||
ushort Socks5ProxyPortId { get; set; }
|
||||
|
||||
#endregion
|
||||
#endregion Socks5
|
||||
|
||||
#region TwoLevelAgent(二级代理)
|
||||
|
||||
@@ -155,7 +160,7 @@ public partial interface IReverseProxySettings
|
||||
|
||||
string? TwoLevelAgentPassword { get; set; }
|
||||
|
||||
#endregion
|
||||
#endregion TwoLevelAgent(二级代理)
|
||||
|
||||
IPAddress? ProxyDNS { get; set; }
|
||||
|
||||
@@ -167,6 +172,11 @@ public partial interface IReverseProxySettings
|
||||
bool UseDoh { get; set; }
|
||||
|
||||
string? CustomDohAddres { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 服务端代理令牌
|
||||
/// </summary>
|
||||
string? ServerSideProxyToken { get; set; }
|
||||
}
|
||||
|
||||
[MP2Obj(SerializeLayout.Explicit)]
|
||||
@@ -214,7 +224,9 @@ public readonly partial record struct ReverseProxySettings(
|
||||
[property:MP2Key(20)]
|
||||
bool UseDoh,
|
||||
[property:MP2Key(21)]
|
||||
string? CustomDohAddres)
|
||||
string? CustomDohAddres,
|
||||
[property:MP2Key(22)]
|
||||
string? ServerSideProxyToken)
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal IPAddress GetProxyIp() => GetProxyIp(ProxyIp);
|
||||
@@ -267,6 +279,7 @@ public readonly partial record struct ReverseProxySettings(
|
||||
settings.IsSupportIpv6 = IsSupportIpv6;
|
||||
settings.UseDoh = UseDoh;
|
||||
settings.CustomDohAddres = CustomDohAddres;
|
||||
settings.ServerSideProxyToken = ServerSideProxyToken;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -123,8 +123,8 @@ static class WinDivertInitHelper
|
||||
//case Architecture.X86:
|
||||
case Architecture.X64:
|
||||
IsSupported = true;
|
||||
libraryDirPath = Path.Combine(AppContext.BaseDirectory, "native", "win-x64");
|
||||
libraryPath = Path.Combine(libraryDirPath, "WinDivert.dll");
|
||||
libraryPath = GlobalDllImportResolver.GetLibraryPath("WinDivert.dll");
|
||||
libraryDirPath = Path.GetDirectoryName(libraryPath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,13 @@ public partial class XunYouGameViewModel : ReactiveSerializationObject, IReactiv
|
||||
[MP2Key(0), JsonPropertyOrder(0)]
|
||||
public XunYouGame Model { get; set; } = model;
|
||||
|
||||
/// <summary>
|
||||
/// PicInfo
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
[XmlIgnore, IgnoreDataMember, SystemTextJsonIgnore, NewtonsoftJsonIgnore, MPIgnore, MP2Ignore]
|
||||
public XunYouPicInfo? PicInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 加速延迟
|
||||
/// </summary>
|
||||
@@ -41,12 +48,26 @@ public partial class XunYouGameViewModel : ReactiveSerializationObject, IReactiv
|
||||
[XmlIgnore, IgnoreDataMember, SystemTextJsonIgnore, NewtonsoftJsonIgnore, MPIgnore, MP2Ignore]
|
||||
public float PingSpeedLoss { get; set; }
|
||||
|
||||
XunYouGameInfo? _GameInfo;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏信息
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
[XmlIgnore, IgnoreDataMember, SystemTextJsonIgnore, NewtonsoftJsonIgnore, MPIgnore, MP2Ignore]
|
||||
public XunYouGameInfo? GameInfo { get; set; }
|
||||
public XunYouGameInfo? GameInfo
|
||||
{
|
||||
get => _GameInfo;
|
||||
set
|
||||
{
|
||||
_GameInfo = value;
|
||||
this.RaisePropertyChanged();
|
||||
this.RaisePropertyChanged(nameof(ShowStart));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="XunYouGameInfo.ShowStart"/>
|
||||
[XmlIgnore, IgnoreDataMember, SystemTextJsonIgnore, NewtonsoftJsonIgnore, MPIgnore, MP2Ignore]
|
||||
public bool ShowStart => IsAccelerated && (GameInfo != null && GameInfo.ShowStart);
|
||||
|
||||
/// <summary>
|
||||
/// 是否正在加速等待
|
||||
@@ -62,12 +83,25 @@ public partial class XunYouGameViewModel : ReactiveSerializationObject, IReactiv
|
||||
[MP2Ignore, SystemTextJsonIgnore]
|
||||
public int AcceleratingProgress { get; set; }
|
||||
|
||||
bool _IsAccelerated;
|
||||
|
||||
/// <summary>
|
||||
/// 是否已加速
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
[MP2Ignore, SystemTextJsonIgnore]
|
||||
public bool IsAccelerated { get; set; }
|
||||
public bool IsAccelerated
|
||||
{
|
||||
get => _IsAccelerated;
|
||||
set
|
||||
{
|
||||
if (_IsAccelerated != value)
|
||||
{
|
||||
_IsAccelerated = value;
|
||||
this.RaisePropertyChanged();
|
||||
this.RaisePropertyChanged(nameof(ShowStart));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否正在停止加速等待
|
||||
|
||||
@@ -151,7 +151,7 @@ public sealed class Plugin : PluginBase<Plugin>, IPlugin
|
||||
|
||||
//if (ResourceService.IsChineseSimplified)
|
||||
//{
|
||||
await ProxyService.Current.InitializeAsync();
|
||||
await MainThread2.InvokeOnMainThreadAsync(ProxyService.Current.InitializeAsync);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -189,4 +189,12 @@ partial class BackendAcceleratorServiceImpl
|
||||
await Task.CompletedTask;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<ApiRsp<XunYouStartGameCode>> XY_StartGame(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = XunYouSDK.StartGame();
|
||||
await Task.CompletedTask;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,10 @@ public sealed class ScriptManager : GeneralHttpClientFactory, IScriptManager
|
||||
if (jsSaveInfo.Exists)
|
||||
{
|
||||
if (isNoRepeat)
|
||||
{
|
||||
jsSaveInfo.Delete();
|
||||
fileInfo.CopyTo(jsSavePath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -404,7 +407,7 @@ public sealed class ScriptManager : GeneralHttpClientFactory, IScriptManager
|
||||
}
|
||||
await TryReadFileAsync(item, true);
|
||||
//清理 脚本内容 后续 IPC 传递 插件进程读取。
|
||||
item.Content = string.Empty;
|
||||
//item.Content = string.Empty;
|
||||
await scriptRepository.SaveScriptCachePathAsync(item, default);
|
||||
}
|
||||
else
|
||||
@@ -419,9 +422,15 @@ public sealed class ScriptManager : GeneralHttpClientFactory, IScriptManager
|
||||
file.Delete();
|
||||
await TryReadFileAsync(item, true);
|
||||
//清理 脚本内容 后续 IPC 传递 插件进程读取。
|
||||
item.Content = string.Empty;
|
||||
//item.Content = string.Empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await TryReadFileAsync(item, true);
|
||||
//item.Content = string.Empty;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return scripts;
|
||||
@@ -443,7 +452,7 @@ public sealed class ScriptManager : GeneralHttpClientFactory, IScriptManager
|
||||
var cachePath = Path.Combine(Plugin.Instance.CacheDirectory, item.CachePath);
|
||||
if (File.Exists(cachePath))
|
||||
{
|
||||
//item.Content = File.ReadAllText(cachePath);
|
||||
item.Content = File.ReadAllText(cachePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -81,6 +81,12 @@ partial interface IAcceleratorService // XunYou
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<ApiRsp<XunYouIsRunningCode>> XY_IsRunning(CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 迅游加速器启动游戏
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<ApiRsp<XunYouStartGameCode>> XY_StartGame(CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
partial interface IXunYouAccelStateToFrontendCallback
|
||||
|
||||
@@ -13,9 +13,9 @@ public sealed partial class GameAcceleratorService
|
||||
: ReactiveObject
|
||||
#endif
|
||||
{
|
||||
static GameAcceleratorService? mCurrent;
|
||||
static readonly Lazy<GameAcceleratorService> mCurrent = new(() => new(), LazyThreadSafetyMode.ExecutionAndPublication);
|
||||
|
||||
public static GameAcceleratorService Current => mCurrent ??= new();
|
||||
public static GameAcceleratorService Current => mCurrent.Value;
|
||||
|
||||
public SourceCache<XunYouGameViewModel, int> Games { get; }
|
||||
|
||||
@@ -38,12 +38,25 @@ public sealed partial class GameAcceleratorService
|
||||
|
||||
public ICommand GameAcceleratorCommand { get; }
|
||||
|
||||
public ICommand GameLaunchCommand { get; }
|
||||
|
||||
public ICommand InstallAcceleratorCommand { get; }
|
||||
|
||||
public ICommand UninstallAcceleratorCommand { get; }
|
||||
|
||||
public ICommand AcceleratorChangeAreaCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// VIP 到期时间
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
public DateTime? VipEndTime { get; set; }
|
||||
|
||||
const string VipEndTimeStringDef = "新用户免费试用 2 天";
|
||||
|
||||
[Reactive]
|
||||
public string? VipEndTimeString { get; set; } = VipEndTimeStringDef;
|
||||
|
||||
GameAcceleratorService()
|
||||
{
|
||||
Ioc.Get<IAcceleratorService>().InitStateSubscribe(); // 仅旧项目(WattToolkit)上监听
|
||||
@@ -52,6 +65,7 @@ public sealed partial class GameAcceleratorService
|
||||
|
||||
DeleteMyGameCommand = ReactiveCommand.Create<XunYouGameViewModel>(DeleteMyGame);
|
||||
GameAcceleratorCommand = ReactiveCommand.CreateFromTask<XunYouGameViewModel>(GameAccelerator);
|
||||
GameLaunchCommand = ReactiveCommand.CreateFromTask<XunYouGameViewModel>(GameLaunch);
|
||||
InstallAcceleratorCommand = ReactiveCommand.CreateFromTask(InstallAccelerator);
|
||||
UninstallAcceleratorCommand = ReactiveCommand.Create(UninstallAccelerator);
|
||||
AcceleratorChangeAreaCommand = ReactiveCommand.Create<XunYouGameViewModel>(AcceleratorChangeArea);
|
||||
@@ -139,6 +153,12 @@ public sealed partial class GameAcceleratorService
|
||||
case XunYouState.启动中:
|
||||
case XunYouState.启动成功:
|
||||
break;
|
||||
case XunYouState.启动游戏成功:
|
||||
Toast.Show(ToastIcon.Success, "启动游戏成功");
|
||||
break;
|
||||
case XunYouState.启动游戏失败:
|
||||
Toast.Show(ToastIcon.Error, "启动游戏失败");
|
||||
break;
|
||||
default:
|
||||
Games.Items.Where(s => s.IsAccelerating || s.IsAccelerated).ForEach(s =>
|
||||
{
|
||||
@@ -155,6 +175,58 @@ public sealed partial class GameAcceleratorService
|
||||
}
|
||||
});
|
||||
|
||||
UserService.Current.WhenAnyValue(static x => x.User)
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.Subscribe(async x =>
|
||||
{
|
||||
string vipEndTimeString = VipEndTimeStringDef;
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(x?.WattOpenId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var vipEndTimeResult = await IMicroServiceClient.Instance.Manage.GetXunYouVipEndTime();
|
||||
if (vipEndTimeResult == null)
|
||||
{
|
||||
Log.Error(nameof(GameAcceleratorService),
|
||||
"XunYouSDK.GetVipEndTime is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vipEndTimeResult.IsSuccess || vipEndTimeResult.Content == null)
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, "获取会员时间失败");
|
||||
return;
|
||||
}
|
||||
|
||||
if (vipEndTimeResult.Content.Code == XunYouBaseResponseCode.成功)
|
||||
{
|
||||
var etime = vipEndTimeResult.Content.Data?.ExpireTime;
|
||||
if (etime.HasValue)
|
||||
{
|
||||
VipEndTime = etime.Value.ToDateTime(UnixTimestampType.Seconds);
|
||||
if (VipEndTime.Value > DateTime.Now)
|
||||
{
|
||||
vipEndTimeString = $"游戏加速会员有效期 {VipEndTime.Value:yyyy-MM-dd}";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error(nameof(GameAcceleratorService),
|
||||
"XunYouSDK.GetVipEndTime is fail, message: {message}, code: {code}.",
|
||||
vipEndTimeResult.Content.Message,
|
||||
vipEndTimeResult.Content.Code);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
VipEndTimeString = vipEndTimeString;
|
||||
}
|
||||
});
|
||||
|
||||
RefreshAllGames();
|
||||
LoadGames();
|
||||
}
|
||||
@@ -183,6 +255,10 @@ public sealed partial class GameAcceleratorService
|
||||
CurrentAcceleratorGame.IsAccelerated = true;
|
||||
CurrentAcceleratorGame.LastAccelerateTime = DateTimeOffset.Now;
|
||||
|
||||
if (CurrentAcceleratorGame.PicInfo == null)
|
||||
{
|
||||
CurrentAcceleratorGame.PicInfo = XunYouSDK.GetPicInfo(CurrentAcceleratorGame.Id);
|
||||
}
|
||||
if (CurrentAcceleratorGame.SelectedArea?.Id != areaId)
|
||||
{
|
||||
var gameInfo = XunYouSDK.GetGameInfo(game.Id);
|
||||
@@ -205,6 +281,7 @@ public sealed partial class GameAcceleratorService
|
||||
var gameInfo = XunYouSDK.GetGameInfo(game.Id);
|
||||
cApp.SelectedArea = gameInfo?.Areas?.FirstOrDefault(s => s.Id == areaId);
|
||||
cApp.SelectedServer = cApp.SelectedArea?.Servers?.FirstOrDefault(s => s.Id == serverId);
|
||||
cApp.PicInfo = XunYouSDK.GetPicInfo(game.Id);
|
||||
|
||||
CurrentAcceleratorGame = cApp;
|
||||
}
|
||||
@@ -403,6 +480,8 @@ public sealed partial class GameAcceleratorService
|
||||
GameAcceleratorSettings.MyGames.Remove(app.Id);
|
||||
if (GameAcceleratorSettings.MyGames.TryAdd(app.Id, app))
|
||||
{
|
||||
if (app.PicInfo == null)
|
||||
app.PicInfo = XunYouSDK.GetPicInfo(app.Id);
|
||||
Current.Games.AddOrUpdate(app);
|
||||
Toast.Show(ToastIcon.Success, "已添加到游戏列表");
|
||||
}
|
||||
@@ -424,6 +503,12 @@ public sealed partial class GameAcceleratorService
|
||||
if (GameAcceleratorSettings.MyGames.Any_Nullable())
|
||||
{
|
||||
Games.Clear();
|
||||
var temp = GameAcceleratorSettings.MyGames.Value!.Values.ToArray();
|
||||
foreach (var item in temp)
|
||||
{
|
||||
if (item.PicInfo == null)
|
||||
item.PicInfo = XunYouSDK.GetPicInfo(item.Id);
|
||||
}
|
||||
Games.AddOrUpdate(GameAcceleratorSettings.MyGames.Value!.Values);
|
||||
}
|
||||
else
|
||||
@@ -433,6 +518,12 @@ public sealed partial class GameAcceleratorService
|
||||
{
|
||||
Games.Clear();
|
||||
GameAcceleratorSettings.MyGames.AddRange(games.Select(s => new KeyValuePair<int, XunYouGameViewModel>(s.Id, new XunYouGameViewModel(s))));
|
||||
var temp = GameAcceleratorSettings.MyGames.Value!.Values.ToArray();
|
||||
foreach (var item in temp)
|
||||
{
|
||||
if (item.PicInfo == null)
|
||||
item.PicInfo = XunYouSDK.GetPicInfo(item.Id);
|
||||
}
|
||||
Games.AddOrUpdate(GameAcceleratorSettings.MyGames.Value!.Values);
|
||||
}
|
||||
}
|
||||
@@ -643,4 +734,16 @@ public sealed partial class GameAcceleratorService
|
||||
XYAccelState = content;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task GameLaunch(XunYouGameViewModel app)
|
||||
{
|
||||
var result = await Ioc.Get<IAcceleratorService>().XY_StartGame();
|
||||
if (result.HandleUI(out var r))
|
||||
{
|
||||
if (r == XunYouStartGameCode.失败)
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, $"启动 {app.Name} 失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ partial class ProxyService
|
||||
const ushort httpsPort = 443;
|
||||
ProxyMode proxyMode = defaultProxyMode;
|
||||
|
||||
static string? proxyTokenCache = null;
|
||||
|
||||
/// <summary>
|
||||
/// 启动代理服务
|
||||
/// </summary>
|
||||
@@ -126,7 +128,6 @@ partial class ProxyService
|
||||
//{
|
||||
// //if (string.IsNullOrWhiteSpace(Plugin.Instance.SubProcessPath))
|
||||
// //{
|
||||
|
||||
// //}
|
||||
// // var processPath = Environment.ProcessPath;
|
||||
// // processPath.ThrowIsNull();
|
||||
@@ -156,6 +157,7 @@ partial class ProxyService
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ProxyMode.System:
|
||||
if (OperatingSystem.IsWindows() &&
|
||||
proxyIp_.Value.Equals(IPAddress.Any))
|
||||
@@ -170,6 +172,7 @@ partial class ProxyService
|
||||
return Strings.CommunityFix_SetAsSystemProxyFail;
|
||||
}
|
||||
break;
|
||||
|
||||
case ProxyMode.PAC:
|
||||
if (OperatingSystem.IsWindows() &&
|
||||
proxyIp_.Value.Equals(IPAddress.Any))
|
||||
@@ -203,12 +206,15 @@ partial class ProxyService
|
||||
}
|
||||
}
|
||||
|
||||
string? proxyToken = proxyDomains.Any_Nullable(s => s.ProxyType == ProxyType.ServerAccelerate) ?
|
||||
await TryRequestServerSideProxyToken() : null;
|
||||
|
||||
ReverseProxySettings reverseProxySettings = new(proxyDomains, scripts,
|
||||
isEnableScript, isOnlyWorkSteamBrowser, proxyPort,
|
||||
proxyIp, proxyMode, isProxyGOG, onlyEnableProxyScript,
|
||||
enableHttpProxyToHttps, socks5ProxyEnable, socks5ProxyPortId,
|
||||
twoLevelAgentEnable, twoLevelAgentProxyType, twoLevelAgentIp,
|
||||
twoLevelAgentPortId, twoLevelAgentUserName, twoLevelAgentPassword, proxyDNS, isSupportIpv6, useDoh, customDohAddres);
|
||||
twoLevelAgentPortId, twoLevelAgentUserName, twoLevelAgentPassword, proxyDNS, isSupportIpv6, useDoh, customDohAddres, proxyToken);
|
||||
byte[] reverseProxySettings_ = Serializable.SMP2(reverseProxySettings);
|
||||
var startProxyResult = await reverseProxyService.StartProxyAsync(reverseProxySettings_);
|
||||
if (startProxyResult)
|
||||
@@ -331,12 +337,14 @@ partial class ProxyService
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ProxyMode.System:
|
||||
if (callSet)
|
||||
{
|
||||
await platformService.SetAsSystemProxyAsync(false);
|
||||
}
|
||||
break;
|
||||
|
||||
case ProxyMode.PAC:
|
||||
if (callSet)
|
||||
{
|
||||
@@ -361,6 +369,34 @@ partial class ProxyService
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试获取服务端代理token
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
static async Task<string?> TryRequestServerSideProxyToken()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(proxyTokenCache))
|
||||
return proxyTokenCache;
|
||||
|
||||
var resp = await IMicroServiceClient.Instance.Account
|
||||
.GenerateServerSideProxyToken();
|
||||
|
||||
if (resp != null && !string.IsNullOrEmpty(resp.Content?.AccessToken))
|
||||
{
|
||||
proxyTokenCache = resp.Content.AccessToken;
|
||||
}
|
||||
|
||||
return proxyTokenCache;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.LogAndShowT();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 操作代理服务返回结果
|
||||
/// </summary>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using BD.Common;
|
||||
using System.Linq;
|
||||
using KeyValuePair = System.Collections.Generic.KeyValuePair;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
using Avalonia.Data;
|
||||
|
||||
namespace BD.WTTS.Services;
|
||||
|
||||
public sealed partial class ProxyService
|
||||
@@ -10,9 +8,9 @@ public sealed partial class ProxyService
|
||||
: ReactiveObject, IProxyService
|
||||
#endif
|
||||
{
|
||||
static ProxyService? mCurrent;
|
||||
static readonly Lazy<ProxyService> mCurrent = new(() => new(), LazyThreadSafetyMode.ExecutionAndPublication);
|
||||
|
||||
public static ProxyService Current => mCurrent ??= new();
|
||||
public static ProxyService Current => mCurrent.Value;
|
||||
|
||||
readonly IReverseProxyService reverseProxyService = IReverseProxyService.Constants.Instance;
|
||||
readonly IScriptManager scriptManager = IScriptManager.Instance;
|
||||
@@ -31,37 +29,38 @@ public sealed partial class ProxyService
|
||||
.Bind(out _ProxyDomainsList)
|
||||
.Subscribe(_ => SelectGroup = ProxyDomains.Items.FirstOrDefault());
|
||||
|
||||
this.WhenValueChanged(x => x.ProxyStatus, false)
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.Subscribe(async proxyStatusLeft =>
|
||||
{
|
||||
bool proxyStatusRight;
|
||||
if (proxyStatusLeft)
|
||||
{
|
||||
var reuslt = await StartProxyServiceAsync();
|
||||
proxyStatusRight = reuslt.OnStartedShowToastReturnProxyStatus();
|
||||
}
|
||||
else
|
||||
{
|
||||
var reuslt = await StopProxyServiceAsync();
|
||||
proxyStatusRight = reuslt.OnStopedShowToastReturnProxyStatus();
|
||||
}
|
||||
if (proxyStatusLeft != proxyStatusRight)
|
||||
{
|
||||
ProxyStatus = proxyStatusRight;
|
||||
//this.WhenValueChanged(x => x.ProxyStatus, false)
|
||||
// .ObserveOn(RxApp.MainThreadScheduler)
|
||||
// .Subscribe(async proxyStatusLeft =>
|
||||
// {
|
||||
// bool proxyStatusRight;
|
||||
// if (proxyStatusLeft)
|
||||
// {
|
||||
// var reuslt = await StartProxyServiceAsync();
|
||||
// proxyStatusRight = reuslt.OnStartedShowToastReturnProxyStatus();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var reuslt = await StopProxyServiceAsync();
|
||||
// proxyStatusRight = reuslt.OnStopedShowToastReturnProxyStatus();
|
||||
// }
|
||||
// if (proxyStatusLeft != proxyStatusRight)
|
||||
// {
|
||||
// ProxyStatus = proxyStatusRight;
|
||||
|
||||
//UpdateProxyTrayMenuItems();
|
||||
//if (Steamworks.SteamClient.IsValid)
|
||||
//{
|
||||
// if (ProxyStatus)
|
||||
// Steamworks.SteamFriends.SetRichPresence("steam_display", "#Status_Accelerator");
|
||||
// else
|
||||
// Steamworks.SteamFriends.ClearRichPresence();
|
||||
//}
|
||||
}
|
||||
});
|
||||
// //UpdateProxyTrayMenuItems();
|
||||
// //if (Steamworks.SteamClient.IsValid)
|
||||
// //{
|
||||
// // if (ProxyStatus)
|
||||
// // Steamworks.SteamFriends.SetRichPresence("steam_display", "#Status_Accelerator");
|
||||
// // else
|
||||
// // Steamworks.SteamFriends.ClearRichPresence();
|
||||
// //}
|
||||
// }
|
||||
// });
|
||||
|
||||
this.WhenAnyValue(v => v.ProxyDomainsList)
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.Subscribe(domain => domain?
|
||||
.ToObservableChangeSet()
|
||||
.AutoRefresh(x => x.ObservableItems)
|
||||
@@ -75,6 +74,7 @@ public sealed partial class ProxyService
|
||||
}));
|
||||
|
||||
this.WhenAnyValue(v => v.ProxyScripts)
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.Subscribe(script => script?
|
||||
.Connect()
|
||||
.AutoRefresh(x => x.Disable)
|
||||
@@ -111,13 +111,54 @@ public sealed partial class ProxyService
|
||||
|
||||
public SourceList<ScriptDTO> ProxyScripts { get; }
|
||||
|
||||
public async Task StartOrStopProxyService(bool startOrStop)
|
||||
{
|
||||
if (startOrStop == ProxyStatus)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!ProxyStarting)
|
||||
{
|
||||
ProxyStarting = true;
|
||||
|
||||
bool proxyStatusRight;
|
||||
if (startOrStop)
|
||||
{
|
||||
var reuslt = await StartProxyServiceAsync();
|
||||
proxyStatusRight = reuslt.OnStartedShowToastReturnProxyStatus();
|
||||
}
|
||||
else
|
||||
{
|
||||
var reuslt = await StopProxyServiceAsync();
|
||||
proxyStatusRight = reuslt.OnStopedShowToastReturnProxyStatus();
|
||||
}
|
||||
|
||||
if (startOrStop != proxyStatusRight)
|
||||
{
|
||||
startOrStop = proxyStatusRight;
|
||||
}
|
||||
|
||||
//UpdateProxyTrayMenuItems();
|
||||
//if (Steamworks.SteamClient.IsValid)
|
||||
//{
|
||||
// if (startOrStop)
|
||||
// Steamworks.SteamFriends.SetRichPresence("steam_display", "#Status_Accelerator");
|
||||
// else
|
||||
// Steamworks.SteamFriends.ClearRichPresence();
|
||||
//}
|
||||
|
||||
ProxyStarting = false;
|
||||
ProxyStatus = startOrStop;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<AccelerateProjectDTO>? GetEnableProxyDomains()
|
||||
{
|
||||
if (!ProxyDomains.Items.Any_Nullable())
|
||||
return null;
|
||||
var data = ProxyDomains.Items
|
||||
.Where(x => x.Items != null)
|
||||
.SelectMany(s => s.Items!.Where(w => w.Checked));
|
||||
.SelectMany(s => s.Items!.Where(w => w.ThreeStateEnable != false));
|
||||
//return data.Concat(data.SelectMany(s => GetProxyDomainsItems(s)));
|
||||
return data;
|
||||
}
|
||||
@@ -204,17 +245,20 @@ public sealed partial class ProxyService
|
||||
// return r;
|
||||
//}
|
||||
|
||||
#endregion
|
||||
#endregion HOSTS_PROXY_RUNNING_STATUS
|
||||
|
||||
#region 代理状态启动退出
|
||||
private bool _ProxyStatus;
|
||||
|
||||
public bool ProxyStatus
|
||||
{
|
||||
get { return _ProxyStatus; }
|
||||
set => this.RaiseAndSetIfChanged(ref _ProxyStatus, value);
|
||||
}
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// 代理启动中
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
public bool ProxyStarting { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool ProxyStatus { get; set; }
|
||||
|
||||
#endregion 代理状态启动退出
|
||||
|
||||
static bool IsProgramStartupRunProxy()
|
||||
{
|
||||
@@ -273,7 +317,8 @@ public sealed partial class ProxyService
|
||||
}
|
||||
else
|
||||
{
|
||||
ProxyStatus = true;
|
||||
//ProxyStatus = true;
|
||||
await StartOrStopProxyService(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,10 +343,30 @@ public sealed partial class ProxyService
|
||||
{
|
||||
new TrayMenuItem
|
||||
{
|
||||
Name = "启动/停止",
|
||||
Command = ReactiveCommand.Create(() =>
|
||||
Name = "启动",
|
||||
//IsEnabled = new Binding()
|
||||
//{
|
||||
// Source = ProxyService.Current,
|
||||
// Mode = BindingMode.OneWay,
|
||||
// Path = "!" + nameof(ProxyStatus),
|
||||
//},
|
||||
Command = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
ProxyStatus = !ProxyStatus;
|
||||
await StartOrStopProxyService(true);
|
||||
}),
|
||||
},
|
||||
new TrayMenuItem
|
||||
{
|
||||
Name = "停止",
|
||||
//IsEnabled = new Binding()
|
||||
//{
|
||||
// Source = ProxyService.Current,
|
||||
// Mode = BindingMode.OneWay,
|
||||
// Path = nameof(ProxyStatus),
|
||||
//},
|
||||
Command = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await StartOrStopProxyService(false);
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -630,7 +695,8 @@ public sealed partial class ProxyService
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion 脚本相关
|
||||
|
||||
public async void FixNetwork()
|
||||
{
|
||||
@@ -652,7 +718,6 @@ public sealed partial class ProxyService
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -155,6 +155,11 @@ public partial interface IProxySettings
|
||||
/// </summary>
|
||||
string? CustomDohAddres { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 加速页面 Tab 选项卡选中下标
|
||||
/// </summary>
|
||||
int AcceleratorTabsSelectedIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 启用脚本自动检查更新的默认值
|
||||
/// </summary>
|
||||
@@ -270,4 +275,9 @@ public partial interface IProxySettings
|
||||
/// </summary>
|
||||
const string? DefaultCustomDohAddres = null;
|
||||
|
||||
/// <summary>
|
||||
/// 加速页面 Tab 选项卡选中下标的默认值
|
||||
/// </summary>
|
||||
static readonly int DefaultAcceleratorTabsSelectedIndex = 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -197,6 +197,12 @@ public sealed partial class ProxySettings_ : IProxySettings, ISettings, ISetting
|
||||
[MPKey(22), MP2Key(22), JsonPropertyOrder(22)]
|
||||
public string? CustomDohAddres { get; set; } = IProxySettings.DefaultCustomDohAddres;
|
||||
|
||||
/// <summary>
|
||||
/// 加速页面 Tab 选项卡选中下标
|
||||
/// </summary>
|
||||
[MPKey(23), MP2Key(23), JsonPropertyOrder(23)]
|
||||
public int AcceleratorTabsSelectedIndex { get; set; } = IProxySettings.DefaultAcceleratorTabsSelectedIndex;
|
||||
|
||||
}
|
||||
|
||||
public static partial class ProxySettings
|
||||
@@ -359,4 +365,10 @@ public static partial class ProxySettings
|
||||
public static SettingsProperty<string, ProxySettings_> CustomDohAddres { get; }
|
||||
= new(DefaultCustomDohAddres);
|
||||
|
||||
/// <summary>
|
||||
/// 加速页面 Tab 选项卡选中下标
|
||||
/// </summary>
|
||||
public static SettingsStructProperty<int, ProxySettings_> AcceleratorTabsSelectedIndex { get; }
|
||||
= new(DefaultAcceleratorTabsSelectedIndex);
|
||||
|
||||
}
|
||||
|
||||
@@ -15,12 +15,13 @@ public sealed partial class AcceleratorPageViewModel
|
||||
|
||||
public AcceleratorPageViewModel()
|
||||
{
|
||||
StartProxyCommand = ReactiveCommand.Create(() =>
|
||||
StartProxyCommand = ReactiveCommand.CreateFromTask(async _ =>
|
||||
{
|
||||
#if LINUX
|
||||
if (!EnvironmentCheck()) return;
|
||||
#endif
|
||||
ProxyService.Current.ProxyStatus = !ProxyService.Current.ProxyStatus;
|
||||
//ProxyService.Current.ProxyStatus = !ProxyService.Current.ProxyStatus;
|
||||
await ProxyService.Current.StartOrStopProxyService(!ProxyService.Current.ProxyStatus);
|
||||
});
|
||||
|
||||
RefreshCommand = ReactiveCommand.Create(async () =>
|
||||
@@ -58,6 +59,7 @@ public sealed partial class AcceleratorPageViewModel
|
||||
ResetHostsFileCommand = ReactiveCommand.CreateFromTask(hostsFileService.ResetFile);
|
||||
NetworkFixCommand = ReactiveCommand.Create(ProxyService.Current.FixNetwork);
|
||||
TrustCerCommand = ReactiveCommand.Create(TrustCer_OnClick);
|
||||
ShowCertificateCommand = ReactiveCommand.Create(ShowCertificate_OnClick);
|
||||
OpenCertificateDirCommand = ReactiveCommand.Create(() =>
|
||||
{
|
||||
certificateManager.GetCerFilePathGeneratedWhenNoFileExists();
|
||||
@@ -125,4 +127,10 @@ public sealed partial class AcceleratorPageViewModel
|
||||
Toast.Show(ToastIcon.Error, Strings.CommunityFix_DeleteCertificate_Fail);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowCertificate_OnClick()
|
||||
{
|
||||
var certInfo = certificateManager.GetCertificateInfo();
|
||||
MessageBox.Show(certInfo, "证书信息");
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ public sealed partial class AcceleratorPageViewModel : TabItemViewModel
|
||||
|
||||
public ICommand? DeleteCertificateCommand { get; }
|
||||
|
||||
public ICommand? ShowCertificateCommand { get; }
|
||||
|
||||
public ICommand? OpenCertificateDirCommand { get; }
|
||||
|
||||
public ICommand? EditHostsFileCommand { get; }
|
||||
|
||||
@@ -93,13 +93,13 @@
|
||||
Grid.ColumnSpan="2"
|
||||
Stretch="UniformToFill">
|
||||
<spp:Image2
|
||||
DecodeWidth="600"
|
||||
DecodeWidth="300"
|
||||
FallbackSource="avares://BD.WTTS.Client.Plugins.Accelerator/UI/Assets/defaultBackground.png"
|
||||
Source="{Binding PicUrl}"
|
||||
Source="{Binding PicInfo.Small.Url}"
|
||||
Stretch="UniformToFill" />
|
||||
</Viewbox>
|
||||
|
||||
<spp:Image2
|
||||
<!--<spp:Image2
|
||||
Grid.RowSpan="2"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="10,0,50,0"
|
||||
@@ -107,7 +107,7 @@
|
||||
VerticalAlignment="Bottom"
|
||||
DecodeWidth="250"
|
||||
Source="{Binding LogoUrl}"
|
||||
Stretch="Uniform" />
|
||||
Stretch="Uniform" />-->
|
||||
|
||||
<Border
|
||||
Name="ShadowBox"
|
||||
@@ -180,7 +180,7 @@
|
||||
VerticalAlignment="Center"
|
||||
DecodeWidth="20"
|
||||
IsVisible="{Binding !$self.IsFailed}"
|
||||
Source="{Binding IconUrl}">
|
||||
Source="{Binding PicInfo.Icon.Url}">
|
||||
<spp:Image2.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
Classes="Scale"
|
||||
DecodeWidth="800"
|
||||
FallbackSource="avares://BD.WTTS.Client.Plugins.Accelerator/UI/Assets/defaultBackground.png"
|
||||
Source="{Binding PicUrl}" />
|
||||
Source="{Binding PicInfo.Large.Url}" />
|
||||
</Viewbox>
|
||||
|
||||
<spp:Image2
|
||||
@@ -46,7 +46,7 @@
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
DecodeWidth="400"
|
||||
Source="{Binding LogoUrl}"
|
||||
Source="{Binding PicInfo.Logo.Url}"
|
||||
Stretch="Uniform" />
|
||||
|
||||
<Panel
|
||||
@@ -68,7 +68,7 @@
|
||||
VerticalAlignment="Center"
|
||||
DecodeWidth="36"
|
||||
IsVisible="{Binding !$self.IsFailed}"
|
||||
Source="{Binding IconUrl}">
|
||||
Source="{Binding PicInfo.Icon.Url}">
|
||||
<spp:Image2.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition
|
||||
@@ -163,15 +163,28 @@
|
||||
Foreground="White"
|
||||
Text="KB" />-->
|
||||
</Grid>
|
||||
<Button
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Width="150"
|
||||
Height="42"
|
||||
Classes="accent"
|
||||
Command="{Binding GameAcceleratorCommand, Source={x:Static s:GameAcceleratorService.Current}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="停止加速"
|
||||
FontSize="18" />
|
||||
Orientation="Horizontal"
|
||||
Spacing="10">
|
||||
<Button
|
||||
Width="150"
|
||||
Height="42"
|
||||
Classes="accent"
|
||||
Command="{Binding GameLaunchCommand, Source={x:Static s:GameAcceleratorService.Current}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="启动游戏"
|
||||
FontSize="18"
|
||||
IsVisible="{Binding ShowStart}" />
|
||||
|
||||
<Button
|
||||
Width="150"
|
||||
Height="42"
|
||||
Command="{Binding GameAcceleratorCommand, Source={x:Static s:GameAcceleratorService.Current}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="停止加速"
|
||||
FontSize="18" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
</Panel>
|
||||
|
||||
@@ -297,6 +297,10 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding DeleteCertificateCommand}"
|
||||
Content="{Binding Path=Res.CommunityFix_DeleteCertificate, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Button
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding ShowCertificateCommand}"
|
||||
Content="查看证书信息" />
|
||||
<Button
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding OpenCertificateDirCommand}"
|
||||
|
||||
@@ -7,6 +7,6 @@ public partial class AcceleratorPage : PageBase<AcceleratorPageViewModel>
|
||||
public AcceleratorPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.SetViewModel<AcceleratorPageViewModel>();
|
||||
this.SetViewModel<AcceleratorPageViewModel>(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:enum="using:BD.WTTS.Enums"
|
||||
xmlns:i="using:Avalonia.Xaml.Interactivity"
|
||||
xmlns:ia="using:Avalonia.Xaml.Interactions.Core"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
@@ -25,26 +26,25 @@
|
||||
</spp:PageBase.PreviewImage>
|
||||
<spp:PageBase.ActionContent>
|
||||
<StackPanel Orientation="Horizontal" Spacing="2">
|
||||
<Button
|
||||
<SplitButton
|
||||
Padding="8,4"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Command="{Binding StartProxyCommand}"
|
||||
DockPanel.Dock="Right"
|
||||
IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=!ProxyStatus, Mode=OneWay}"
|
||||
Theme="{StaticResource TransparentButton}">
|
||||
<!--<SplitButton.Flyout>
|
||||
<ui:FAMenuFlyout>
|
||||
<ui:MenuFlyoutSubItem ItemsSource="{Binding Source={x:Static ms:ProxySettings.ProxyModes}, Path=., Mode=OneWay}" Text="加速模式">
|
||||
IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=!ProxyStatus, Mode=OneWay}">
|
||||
<SplitButton.Flyout>
|
||||
<ui:FAMenuFlyout Placement="BottomEdgeAlignedRight">
|
||||
<!--<ui:MenuFlyoutSubItem ItemsSource="{Binding Source={x:Static ms:ProxySettings.ProxyModes}, Path=., Mode=OneWay}" Text="加速模式">
|
||||
<ui:MenuFlyoutSubItem.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ui:RadioMenuFlyoutItem GroupName="ProxyMode" Text="{Binding}" />
|
||||
</DataTemplate>
|
||||
</ui:MenuFlyoutSubItem.ItemTemplate>
|
||||
</ui:MenuFlyoutSubItem>
|
||||
<ui:ToggleMenuFlyoutItem Text="启用脚本" />
|
||||
</ui:MenuFlyoutSubItem>-->
|
||||
<ui:ToggleMenuFlyoutItem IsChecked="{Binding Source={x:Static s:ProxyService.Current}, Path=IsEnableScript, Mode=TwoWay}" Text="启用脚本" />
|
||||
</ui:FAMenuFlyout>
|
||||
</SplitButton.Flyout>-->
|
||||
</SplitButton.Flyout>
|
||||
<Panel>
|
||||
<Viewbox
|
||||
Width="16"
|
||||
@@ -52,13 +52,34 @@
|
||||
HorizontalAlignment="Left">
|
||||
<ui:FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="{StaticResource SpeedHigh}" />
|
||||
</Viewbox>
|
||||
<TextBlock
|
||||
<ContentControl
|
||||
Margin="28,4,0,4"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center">
|
||||
<ContentControl.Content>
|
||||
<MultiBinding Converter="{StaticResource VisibleStringConverter}">
|
||||
<CompiledBinding
|
||||
Mode="OneWay"
|
||||
Path="ProxyStarting"
|
||||
Source="{x:Static s:ProxyService.Current}" />
|
||||
<CompiledBinding
|
||||
Mode="OneWay"
|
||||
Path="Res.CommunityFix_Starting"
|
||||
Source="{x:Static s:ResourceService.Current}" />
|
||||
<CompiledBinding
|
||||
Mode="OneWay"
|
||||
Path="Res.CommunityFix_StartProxy"
|
||||
Source="{x:Static s:ResourceService.Current}" />
|
||||
</MultiBinding>
|
||||
</ContentControl.Content>
|
||||
</ContentControl>
|
||||
<!--<TextBlock
|
||||
Margin="28,4,0,4"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static spp:Strings.CommunityFix_StartProxy}" />
|
||||
Text="{x:Static spp:Strings.CommunityFix_StartProxy}" />-->
|
||||
</Panel>
|
||||
</Button>
|
||||
</SplitButton>
|
||||
|
||||
<Button
|
||||
Padding="8,4"
|
||||
@@ -291,6 +312,10 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding DeleteCertificateCommand}"
|
||||
Content="{x:Static spp:Strings.CommunityFix_DeleteCertificate}" />
|
||||
<Button
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding ShowCertificateCommand}"
|
||||
Content="查看证书信息" />
|
||||
<Button
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding OpenCertificateDirCommand}"
|
||||
@@ -353,10 +378,52 @@
|
||||
VerticalAlignment="Top"
|
||||
ItemContainerTheme="{StaticResource TabItemStyle}"
|
||||
Theme="{StaticResource TabStripStyle}">
|
||||
<TabStripItem Name="GameAccTab" Content="游戏加速" />
|
||||
<TabStripItem Content="平台加速 (免费)" IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=!ProxyStatus, Mode=OneWay}" />
|
||||
<TabStripItem Content="平台加速" IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=!ProxyStatus, Mode=OneWay}">
|
||||
<WrapPanel>
|
||||
<TextBlock Text="平台加速" />
|
||||
<Border
|
||||
Margin="5,0,0,0"
|
||||
Padding="5,1"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2">
|
||||
<Border.Background>
|
||||
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
|
||||
<GradientStop Offset="0.0" Color="#48C6EF" />
|
||||
<GradientStop Offset="1.0" Color="#6F86D6" />
|
||||
</LinearGradientBrush>
|
||||
</Border.Background>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="10"
|
||||
Foreground="White"
|
||||
Text="免费" />
|
||||
</Border>
|
||||
</WrapPanel>
|
||||
</TabStripItem>
|
||||
<TabStripItem Content="{x:Static spp:Strings.CommunityFix_FlowStatistics}" IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=ProxyStatus, Mode=OneWay}" />
|
||||
<TabStripItem Content="{x:Static spp:Strings.CommunityFix_Services}" IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=ProxyStatus, Mode=OneWay}" />
|
||||
<TabStripItem Name="GameAccTab">
|
||||
<WrapPanel>
|
||||
<TextBlock Text="游戏加速" />
|
||||
<Border
|
||||
Margin="5,0,0,0"
|
||||
Padding="5,1"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2">
|
||||
<Border.Background>
|
||||
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
|
||||
<GradientStop Offset="0.0" Color="#EEAD92" />
|
||||
<GradientStop Offset="1.0" Color="#6018DC" />
|
||||
</LinearGradientBrush>
|
||||
</Border.Background>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="10"
|
||||
Foreground="White"
|
||||
Text="收费" />
|
||||
</Border>
|
||||
</WrapPanel>
|
||||
</TabStripItem>
|
||||
</TabStrip>
|
||||
<Carousel
|
||||
Grid.Row="1"
|
||||
@@ -364,66 +431,6 @@
|
||||
Classes="AnimeSlide"
|
||||
SelectedIndex="{Binding #AcceleratorTabs.SelectedIndex}">
|
||||
|
||||
<!-- 游戏加速 -->
|
||||
<Panel x:DataType="spp:GameAcceleratorPageViewModel">
|
||||
<Panel.DataContext>
|
||||
<spp:GameAcceleratorPageViewModel />
|
||||
</Panel.DataContext>
|
||||
<spp:ContentLoader
|
||||
IsLoading="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=IsLoadingGames, Mode=OneWay}"
|
||||
IsShowNoResultText="{Binding !!!Games.Count}"
|
||||
IsVisible="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=!CurrentAcceleratorGame.IsAccelerated}"
|
||||
NoResultMessage="{x:Static spp:Strings.GameAccelerator_GamesEmptyTip}}">
|
||||
<ScrollViewer
|
||||
Name="GameScrollViewer"
|
||||
Padding="0,0,10,0"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
IsVisible="{Binding !!Games.Count}"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel>
|
||||
<ItemsRepeater ItemsSource="{Binding Games}" VerticalCacheLength="50">
|
||||
<ItemsRepeater.Layout>
|
||||
<UniformGridLayout
|
||||
ItemsJustification="Start"
|
||||
ItemsStretch="Uniform"
|
||||
MinColumnSpacing="10"
|
||||
MinItemHeight="180"
|
||||
MinItemWidth="200"
|
||||
MinRowSpacing="10" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate DataType="spp:XunYouGameViewModel">
|
||||
<spp:GameAppItem ButtonCommand="{Binding GameAcceleratorCommand, Source={x:Static s:GameAcceleratorService.Current}}" />
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
|
||||
<StackPanel
|
||||
Margin="0,30"
|
||||
HorizontalAlignment="Center"
|
||||
Spacing="10">
|
||||
<spp:Image2
|
||||
Width="100"
|
||||
Height="100"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="avares://BD.WTTS.Client.Avalonia/UI/Assets/Icons/empty.png"
|
||||
Stretch="UniformToFill" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="已经到底啦! 没有找到想加速的游戏的话可以搜索添加哦~" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</spp:ContentLoader>
|
||||
<spp:GameDetail
|
||||
Margin="0,0,10,0"
|
||||
Content="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=CurrentAcceleratorGame}"
|
||||
IsVisible="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=CurrentAcceleratorGame.IsAccelerated}" />
|
||||
</Panel>
|
||||
|
||||
<!-- 平台加速 -->
|
||||
<ScrollViewer
|
||||
Padding="0,0,10,0"
|
||||
@@ -464,7 +471,25 @@
|
||||
HorizontalAlignment="Left"
|
||||
DockPanel.Dock="Left"
|
||||
IsChecked="{Binding ThreeStateEnable, Mode=TwoWay}">
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
|
||||
<Border
|
||||
Padding="5,0"
|
||||
CornerRadius="5"
|
||||
IsVisible="{Binding ProxyType, Converter={StaticResource EnumEqualValueConverter}, ConverterParameter={x:Static enum:ProxyType.ServerAccelerate}}"
|
||||
ToolTip.Tip="Beta 测试加速项,不稳定且随时可能调整">
|
||||
<Border.Background>
|
||||
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
|
||||
<GradientStop Offset="0.0" Color="#43cbff" />
|
||||
<GradientStop Offset="1.0" Color="#9708cc" />
|
||||
</LinearGradientBrush>
|
||||
</Border.Background>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="10"
|
||||
Text="Beta" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</CheckBox>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Right"
|
||||
@@ -544,6 +569,67 @@
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
|
||||
<!-- 游戏加速 -->
|
||||
<Panel x:DataType="spp:GameAcceleratorPageViewModel">
|
||||
<Panel.DataContext>
|
||||
<spp:GameAcceleratorPageViewModel />
|
||||
</Panel.DataContext>
|
||||
<spp:ContentLoader
|
||||
IsLoading="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=IsLoadingGames, Mode=OneWay}"
|
||||
IsShowNoResultText="{Binding !!!Games.Count}"
|
||||
IsVisible="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=!CurrentAcceleratorGame.IsAccelerated}"
|
||||
NoResultMessage="{x:Static spp:Strings.GameAccelerator_GamesEmptyTip}}">
|
||||
<ScrollViewer
|
||||
Name="GameScrollViewer"
|
||||
Padding="0,0,10,0"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
IsVisible="{Binding !!Games.Count}"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel>
|
||||
<ItemsRepeater ItemsSource="{Binding Games}" VerticalCacheLength="30">
|
||||
<ItemsRepeater.Layout>
|
||||
<UniformGridLayout
|
||||
ItemsJustification="Start"
|
||||
ItemsStretch="Uniform"
|
||||
MinColumnSpacing="10"
|
||||
MinItemHeight="240"
|
||||
MinItemWidth="200"
|
||||
MinRowSpacing="10" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate DataType="spp:XunYouGameViewModel">
|
||||
<spp:GameAppItem ButtonCommand="{Binding GameAcceleratorCommand, Source={x:Static s:GameAcceleratorService.Current}}" />
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
|
||||
<StackPanel
|
||||
Margin="0,30"
|
||||
HorizontalAlignment="Center"
|
||||
Spacing="10">
|
||||
<spp:Image2
|
||||
Width="100"
|
||||
Height="100"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="avares://BD.WTTS.Client.Avalonia/UI/Assets/Icons/empty.png"
|
||||
Stretch="UniformToFill" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="已经到底啦! 没有找到想加速的游戏的话可以搜索添加哦~" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</spp:ContentLoader>
|
||||
<spp:GameDetail
|
||||
Margin="0,0,10,0"
|
||||
Content="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=CurrentAcceleratorGame}"
|
||||
IsVisible="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=CurrentAcceleratorGame.IsAccelerated}" />
|
||||
</Panel>
|
||||
|
||||
<!--<TabItem Header="加速日志">
|
||||
|
||||
</TabItem>-->
|
||||
@@ -552,75 +638,126 @@
|
||||
</TabItem>-->
|
||||
</Carousel>
|
||||
|
||||
<AutoCompleteBox
|
||||
Name="SearchGameBox"
|
||||
<StackPanel
|
||||
Grid.ColumnSpan="2"
|
||||
Width="240"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Search"
|
||||
FilterMode="ContainsOrdinal"
|
||||
IsVisible="{Binding #GameAccTab.IsSelected}"
|
||||
ItemsSource="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=AllGames}"
|
||||
MaxDropDownHeight="300"
|
||||
ValueMemberBinding="{Binding Name, x:DataType=spp:XunYouGame}"
|
||||
Watermark="{x:Static spp:Strings.GameAccelerator_SearchGame}">
|
||||
<AutoCompleteBox.ItemTemplate>
|
||||
<DataTemplate DataType="spp:XunYouGame">
|
||||
<WrapPanel>
|
||||
<spp:Image2
|
||||
Width="20"
|
||||
Height="20"
|
||||
Margin="0,0,5,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
DecodeWidth="20"
|
||||
Source="{Binding IconUrl}">
|
||||
<spp:Image2.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition
|
||||
Easing="0,0 0,1"
|
||||
Property="Width"
|
||||
Duration="00:00:00.25" />
|
||||
<DoubleTransition
|
||||
Easing="0,0 0,1"
|
||||
Property="Height"
|
||||
Duration="00:00:00.25" />
|
||||
</Transitions>
|
||||
</spp:Image2.Transitions>
|
||||
</spp:Image2>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
MaxLines="2"
|
||||
Text="{Binding Name}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="WrapWithOverflow" />
|
||||
</WrapPanel>
|
||||
</DataTemplate>
|
||||
</AutoCompleteBox.ItemTemplate>
|
||||
</AutoCompleteBox>
|
||||
Orientation="Horizontal"
|
||||
Spacing="5">
|
||||
<Border
|
||||
Padding="5,1"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
IsVisible="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=VipEndTimeString, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}">
|
||||
<Border.Background>
|
||||
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
|
||||
<GradientStop Offset="0.0" Color="#453a94" />
|
||||
<GradientStop Offset="1.0" Color="#f43b47" />
|
||||
</LinearGradientBrush>
|
||||
</Border.Background>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="White"
|
||||
Text="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=VipEndTimeString}" />
|
||||
</Border>
|
||||
<Button
|
||||
Command="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
CommandParameter="https://steampp.net/customer/service"
|
||||
Cursor="Hand"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="联系客服">
|
||||
<ui:FontIcon FontSize="22" Glyph="" />
|
||||
</Button>
|
||||
<AutoCompleteBox
|
||||
Name="SearchGameBox"
|
||||
Width="240"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Search"
|
||||
FilterMode="ContainsOrdinal"
|
||||
ItemsSource="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=AllGames}"
|
||||
MaxDropDownHeight="300"
|
||||
ValueMemberBinding="{Binding Name, x:DataType=spp:XunYouGame}"
|
||||
Watermark="{x:Static spp:Strings.GameAccelerator_SearchGame}">
|
||||
<AutoCompleteBox.ItemTemplate>
|
||||
<DataTemplate DataType="spp:XunYouGame">
|
||||
<WrapPanel>
|
||||
<spp:Image2
|
||||
Width="20"
|
||||
Height="20"
|
||||
Margin="0,0,5,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
DecodeWidth="20"
|
||||
Source="{Binding IconUrl}">
|
||||
<spp:Image2.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition
|
||||
Easing="0,0 0,1"
|
||||
Property="Width"
|
||||
Duration="00:00:00.25" />
|
||||
<DoubleTransition
|
||||
Easing="0,0 0,1"
|
||||
Property="Height"
|
||||
Duration="00:00:00.25" />
|
||||
</Transitions>
|
||||
</spp:Image2.Transitions>
|
||||
</spp:Image2>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
MaxLines="2"
|
||||
Text="{Binding Name}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="WrapWithOverflow" />
|
||||
</WrapPanel>
|
||||
</DataTemplate>
|
||||
</AutoCompleteBox.ItemTemplate>
|
||||
</AutoCompleteBox>
|
||||
</StackPanel>
|
||||
|
||||
<!--<StackPanel
|
||||
|
||||
<StackPanel
|
||||
Grid.ColumnSpan="2"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=ProxyStatus, Mode=OneWay}"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<StackPanel.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<CompiledBinding
|
||||
Mode="OneWay"
|
||||
Path="ProxyStatus"
|
||||
Source="{x:Static s:ProxyService.Current}" />
|
||||
<Binding Path="!#GameAccTab.IsSelected" />
|
||||
</MultiBinding>
|
||||
</StackPanel.IsVisible>
|
||||
<StackPanel.Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</StackPanel.Styles>
|
||||
<TextBlock>
|
||||
<Run Text="{x:Static spp:Strings.CommunityFix_ProxyMode}" />
|
||||
<Run Text="{Binding Source={x:Static ms:ProxySettings.ProxyMode}, Path=Value, Mode=OneWay, Converter={StaticResource EnumLocalizationNameConverter}}" />
|
||||
<Button Theme="{StaticResource TransparentButton}">
|
||||
<ToolTip.Tip>
|
||||
<TextBlock>
|
||||
<Run FontSize="16" Text="Q:为什么加速后流量一直显示 0KB ?" />
|
||||
<LineBreak />
|
||||
<Run Text="A:流量统计图表是用于查看实时流量数据信息,您需要先访问对应的网站,这边才会有相应的流量波动数据,请检查是否已经选择了对应的网站加速项目,如果确定有正常勾选加速项目并且访问网站依然无流量,则可能是加速的监听服务没有启用成功,尝试更换加速模式。" />
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Run FontSize="16" Text="Q:加速后对应网站打不开显示SSL错误或者Steam浏览器显示-100错误?" />
|
||||
<LineBreak />
|
||||
<Run Text="A:可以尝试执行以下操作进行修复,关闭加速,点击加速设置-移除证书再安装证书,重开加速。或者加速设置-代理设置-尝试更换doh地址或者关闭doh使用dns等方案。" />
|
||||
</TextBlock>
|
||||
</ToolTip.Tip>
|
||||
<ui:FontIcon FontSize="22" Glyph="" />
|
||||
</Button>
|
||||
<TextBlock Text="{x:Static spp:Strings.CommunityFix_ProxyMode}" />
|
||||
<TextBlock Text="{Binding Source={x:Static ms:ProxySettings.ProxyMode}, Path=Value, Mode=OneWay, Converter={StaticResource EnumLocalizationNameConverter}}" />
|
||||
|
||||
<Run Text=" " />
|
||||
|
||||
<Run Text="{x:Static spp:Strings.CommunityFix_EnableScriptService}" />
|
||||
<Run Text="{Binding Source={x:Static s:ProxyService.Current}, Path=IsEnableScript, Converter={StaticResource StringFormatConverter}}" />
|
||||
</TextBlock>
|
||||
</StackPanel>-->
|
||||
<TextBlock Text="{x:Static spp:Strings.CommunityFix_EnableScriptService}" />
|
||||
<TextBlock Text="{Binding Source={x:Static s:ProxyService.Current}, Path=IsEnableScript, Converter={StaticResource StringFormatConverter}}" />
|
||||
</StackPanel>
|
||||
|
||||
<spp:AdControl
|
||||
Grid.Row="1"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
|
||||
namespace BD.WTTS.UI.Views.Pages;
|
||||
@@ -12,6 +13,8 @@ public partial class AcceleratorPage2 : PageBase<AcceleratorPageViewModel>
|
||||
{
|
||||
readonly Dictionary<string, string[]> dictPinYinArray = new();
|
||||
|
||||
List<int> acceleratorTabsSelectedIndexs = new();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AcceleratorPage2"/> class.
|
||||
/// </summary>
|
||||
@@ -21,7 +24,27 @@ public partial class AcceleratorPage2 : PageBase<AcceleratorPageViewModel>
|
||||
var mode = ProxySettings.ProxyMode.Value;
|
||||
|
||||
InitializeComponent();
|
||||
this.SetViewModel<AcceleratorPageViewModel>();
|
||||
this.SetViewModel<AcceleratorPageViewModel>(true);
|
||||
|
||||
for (int i = 0; i < AcceleratorTabs.Items.Count; i++)
|
||||
{
|
||||
var item = AcceleratorTabs.Items[i];
|
||||
if (item is Visual visual && visual.IsVisible)
|
||||
{
|
||||
acceleratorTabsSelectedIndexs.Add(i);
|
||||
}
|
||||
}
|
||||
var itemCount = AcceleratorTabs.ItemCount;
|
||||
var acceleratorTabsSelectedIndex = ProxySettings.AcceleratorTabsSelectedIndex.Value;
|
||||
if (acceleratorTabsSelectedIndex >= 0 && acceleratorTabsSelectedIndex < itemCount)
|
||||
{
|
||||
if (acceleratorTabsSelectedIndexs.Contains(acceleratorTabsSelectedIndex))
|
||||
{
|
||||
AcceleratorTabs.SelectedIndex = acceleratorTabsSelectedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
AcceleratorTabs.SelectionChanged += AcceleratorTabs_SelectionChanged;
|
||||
|
||||
//重置回保存的值
|
||||
ProxySettings.ProxyMode.Value = mode;
|
||||
@@ -31,7 +54,7 @@ public partial class AcceleratorPage2 : PageBase<AcceleratorPageViewModel>
|
||||
ProxyService.Current.WhenValueChanged(x => x.ProxyStatus, false)
|
||||
.Subscribe(x =>
|
||||
{
|
||||
AcceleratorTabs.SelectedIndex = x ? 2 : 1;
|
||||
AcceleratorTabs.SelectedIndex = x ? 1 : 0;
|
||||
}));
|
||||
|
||||
if (XunYouSDK.IsSupported)
|
||||
@@ -48,15 +71,31 @@ public partial class AcceleratorPage2 : PageBase<AcceleratorPageViewModel>
|
||||
else
|
||||
{
|
||||
GameAccTab.IsVisible = false;
|
||||
AcceleratorTabs.SelectedIndex = 1;
|
||||
AcceleratorTabs.SelectedIndex = 0;
|
||||
}
|
||||
});
|
||||
|
||||
SearchGameBox.DropDownClosed += SearchGameBox_DropDownClosed;
|
||||
SearchGameBox.TextSelector = (_, _) => null;
|
||||
SearchGameBox.TextSelector = (_, _) => null!;
|
||||
SearchGameBox.TextFilter = GameContains;
|
||||
}
|
||||
|
||||
void AcceleratorTabs_SelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
var value = AcceleratorTabs.SelectedIndex;
|
||||
if (acceleratorTabsSelectedIndexs.Contains(value))
|
||||
{
|
||||
ProxySettings.AcceleratorTabsSelectedIndex.Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
if (AcceleratorTabs.SelectedIndex == default && ProxyService.Current.ProxyStatus)
|
||||
AcceleratorTabs.SelectedIndex = 1;
|
||||
}
|
||||
|
||||
private void SearchGameBox_DropDownClosed(object? sender, EventArgs e)
|
||||
{
|
||||
if (SearchGameBox.SelectedItem is XunYouGame xunYouGame && xunYouGame is not null)
|
||||
@@ -98,17 +137,17 @@ public partial class AcceleratorPage2 : PageBase<AcceleratorPageViewModel>
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
//protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
//{
|
||||
// base.OnDetachedFromVisualTree(e);
|
||||
|
||||
//try
|
||||
//{
|
||||
// ISettingsLoadService.Current.ForceSave<GameAcceleratorSettingsModel>();
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// Log.Error(nameof(AcceleratorPage), ex, "ForceSave fail.");
|
||||
//}
|
||||
}
|
||||
// //try
|
||||
// //{
|
||||
// // ISettingsLoadService.Current.ForceSave<GameAcceleratorSettingsModel>();
|
||||
// //}
|
||||
// //catch (Exception ex)
|
||||
// //{
|
||||
// // Log.Error(nameof(AcceleratorPage), ex, "ForceSave fail.");
|
||||
// //}
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,19 @@
|
||||
</On>
|
||||
</OnFormFactor>
|
||||
</TabStrip.ItemsPanel>
|
||||
<TabStripItem Content="{Binding Path=Res.CommunityFix, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<TabStripItem>
|
||||
<WrapPanel>
|
||||
<Border
|
||||
Margin="-5,0,3,0"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2">
|
||||
<ui:ImageIcon
|
||||
Width="24"
|
||||
Height="24"
|
||||
Source="avares://BD.WTTS.Client.Plugins.Accelerator/UI/Assets/accelerator.ico" />
|
||||
</Border>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.CommunityFix, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</WrapPanel>
|
||||
<TabStripItem.Tag>
|
||||
<x:Type TypeName="spp:AcceleratorPage2" />
|
||||
</TabStripItem.Tag>
|
||||
@@ -40,7 +52,19 @@
|
||||
<x:Type TypeName="spp:AcceleratorPage" />
|
||||
</TabStripItem.Tag>
|
||||
</TabStripItem>-->
|
||||
<TabStripItem Content="{Binding Path=Res.ScriptConfig, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<TabStripItem>
|
||||
<WrapPanel>
|
||||
<Border
|
||||
Margin="-5,0,3,0"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2">
|
||||
<ui:ImageIcon
|
||||
Width="24"
|
||||
Height="24"
|
||||
Source="avares://BD.WTTS.Client.Plugins.Accelerator/UI/Assets/script.ico" />
|
||||
</Border>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.ScriptConfig, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</WrapPanel>
|
||||
<TabStripItem.Tag>
|
||||
<x:Type TypeName="spp:ScriptPage" />
|
||||
</TabStripItem.Tag>
|
||||
|
||||
@@ -54,13 +54,6 @@
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem>
|
||||
<TextBlock Text="{Binding Path=Res.CommunityFix_ProxyOnlyOnScript, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch Classes="LeftContent" IsChecked="{Binding Source={x:Static ms:ProxySettings.OnlyEnableProxyScript}, Path=Value, Mode=TwoWay}" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem>
|
||||
<TextBlock Text="{Binding Path=Res.CommunityFix_EnableHttpProxyToHttps, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
@@ -95,6 +88,13 @@
|
||||
<Label Content="自定义根证书" ></Label>
|
||||
<Button Content="选择证书"/>
|
||||
</DockPanel>-->
|
||||
|
||||
<ui:SettingsExpanderItem Description="*该选项勾选后会导致程序的加速完全不生效,请确认是仅需要脚本功能后再启用">
|
||||
<TextBlock Text="{Binding Path=Res.CommunityFix_ProxyOnlyOnScript, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch Classes="LeftContent" IsChecked="{Binding Source={x:Static ms:ProxySettings.OnlyEnableProxyScript}, Path=Value, Mode=TwoWay}" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -141,7 +141,6 @@
|
||||
<DataTemplate DataType="spp:ScriptDTO">
|
||||
<spp:AppItem
|
||||
Title="{Binding Name}"
|
||||
MaxHeight="200"
|
||||
Description="{Binding Describe}"
|
||||
ImageMargin="30"
|
||||
ImageStretch="None">
|
||||
@@ -159,31 +158,31 @@
|
||||
Margin="0,0,3,0"
|
||||
Orientation="Horizontal"
|
||||
Spacing="5">
|
||||
<Button
|
||||
<Button
|
||||
Command="{Binding $parent[spp:PageBase].((spp:ScriptPageViewModel)DataContext).DownloadScriptItemCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
IsVisible="{Binding IsUpdate}"
|
||||
Theme="{DynamicResource TransparentButton}">
|
||||
<ToolTip.Tip>
|
||||
<MultiBinding StringFormat="{}{0} v{1}">
|
||||
<CompiledBinding
|
||||
<ToolTip.Tip>
|
||||
<MultiBinding StringFormat="{}{0} v{1}">
|
||||
<CompiledBinding
|
||||
Mode="OneWay"
|
||||
Path="Res.Script_Update"
|
||||
Source="{x:Static s:ResourceService.Current}" />
|
||||
<CompiledBinding Mode="OneWay" Path="NewVersion" />
|
||||
</MultiBinding>
|
||||
</ToolTip.Tip>
|
||||
<StackPanel Orientation="Horizontal" Spacing="3">
|
||||
<Viewbox Width="16" Height="16">
|
||||
<ui:SymbolIcon Symbol="Download" />
|
||||
</Viewbox>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding NewVersion}" />
|
||||
<Ellipse
|
||||
<CompiledBinding Mode="OneWay" Path="NewVersion" />
|
||||
</MultiBinding>
|
||||
</ToolTip.Tip>
|
||||
<StackPanel Orientation="Horizontal" Spacing="3">
|
||||
<Viewbox Width="16" Height="16">
|
||||
<ui:SymbolIcon Symbol="Download" />
|
||||
</Viewbox>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding NewVersion}" />
|
||||
<Ellipse
|
||||
Width="6"
|
||||
Height="6"
|
||||
Fill="#dd5a5a" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button
|
||||
Command="{Binding $parent[spp:PageBase].((spp:ScriptPageViewModel)DataContext).EditScriptItemCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Mobius.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 调用加速器默认启动当前加速的游戏返回值
|
||||
/// <para>23.接口 xunyou_start_game</para>
|
||||
/// </summary>
|
||||
public enum XunYouStartGameCode
|
||||
{
|
||||
/// <summary>
|
||||
/// 发送失败
|
||||
/// </summary>
|
||||
失败 = -1,
|
||||
|
||||
/// <summary>
|
||||
/// 发送命令到客户端成功
|
||||
/// </summary>
|
||||
成功 = 0,
|
||||
}
|
||||
@@ -23,4 +23,6 @@ public enum XunYouState
|
||||
停止加速中 = 403,
|
||||
加速已断开 = 404,
|
||||
加速失败 = 405,
|
||||
启动游戏失败 = 406,
|
||||
启动游戏成功 = 407,
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Mobius;
|
||||
|
||||
partial class XunYouSDK // 1.接口 xunyou_install
|
||||
partial class XunYouSDK // 21.接口 xunyou_install_ex
|
||||
{
|
||||
/// <summary>
|
||||
/// 迅游下载进度回调函数委托
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user