mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-19 15:21:26 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 12911cf5c4 |
@@ -33,7 +33,7 @@ jobs:
|
||||
|
||||
- name: Setup .NET
|
||||
if: ${{ matrix.os != 'aigio-win10ltsc-vm' }}
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 7.0.x
|
||||
|
||||
@@ -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;DebugType=pdbonly
|
||||
run: dotnet build -c Release src\BD.WTTS.Client.AppHost\BD.WTTS.Client.AppHost.csproj --nologo -v q /property:WarningLevel=1
|
||||
|
||||
- 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;DebugType=pdbonly
|
||||
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
|
||||
|
||||
- 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;DebugType=pdbonly
|
||||
run: dotnet build -c Release src\BD.WTTS.Client.Avalonia.App\BD.WTTS.Client.Avalonia.App.csproj --nologo -v q /property:WarningLevel=1
|
||||
|
||||
- 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;DebugType=pdbonly
|
||||
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
|
||||
|
||||
- name: Test
|
||||
run: dotnet test src/BD.WTTS.UnitTest/BD.WTTS.UnitTest.csproj -c Release -p:GeneratePackageOnBuild=false --nologo -v q --property:WarningLevel=1;DebugType=pdbonly
|
||||
run: dotnet test src/BD.WTTS.UnitTest/BD.WTTS.UnitTest.csproj -c Release -p:GeneratePackageOnBuild=false --nologo -v q /property:WarningLevel=1
|
||||
|
||||
# release:
|
||||
# name: Release
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET 6
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET 6
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
@@ -321,7 +321,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET 6
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET 6
|
||||
uses: actions/setup-dotnet@v3
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
#!/bin/bash
|
||||
run_path=$(dirname "$0")
|
||||
base_path="$(dirname "$run_path")"
|
||||
mkdir -p "$base_path"
|
||||
cd "$base_path" || exit 1
|
||||
appVer_path="$base_path/WattToolkit.AppVer"
|
||||
exec_name="Steam++"
|
||||
tar_name="WattToolkit.tgz"
|
||||
tar_path="$base_path/$tar_name"
|
||||
app_name="Watt Toolkit"
|
||||
PROCESS_NAMES=("$exec_name" "$app_name")
|
||||
export LC_ALL=en_US.UTF-8
|
||||
Install_certutil() {
|
||||
# 判断发行版类型
|
||||
if command -v certutil &>/dev/null; then
|
||||
echo "certutil 工具已安装。"
|
||||
else
|
||||
echo "证书导入以及验证需要使用 certutil 工具。"
|
||||
# 判断包管理器
|
||||
if command -v apt &>/dev/null; then
|
||||
# 使用 apt (Debian/Ubuntu)
|
||||
sudo apt update
|
||||
sudo apt install -y libnss3-tools
|
||||
elif command -v dnf &>/dev/null; then
|
||||
# 使用 dnf (Fedora)
|
||||
sudo dnf install -y nss-tools
|
||||
elif command -v yum &>/dev/null; then
|
||||
# 使用 yum (CentOS/Red Hat)
|
||||
sudo yum install -y nss-tools
|
||||
elif command -v pacman &>/dev/null; then
|
||||
# 使用 pacman (Arch Linux)
|
||||
# sudo pacman -S nss
|
||||
echo "请手动安装 certutil 工具。"
|
||||
exit 1
|
||||
else
|
||||
echo "请手动安装 certutil 工具。"
|
||||
exit 1
|
||||
fi
|
||||
echo "certutil 工具已安装。"
|
||||
fi
|
||||
}
|
||||
certutil_Init() {
|
||||
certutil -d $HOME/.pki/nssdb -L
|
||||
ret=$?
|
||||
if [ $ret -ne 0 ]; then
|
||||
echo "即将初始化 certutil \$HOME/.pki/nssdb"
|
||||
mkdir -p $HOME/.pki
|
||||
mkdir -p $HOME/.pki/nssdb
|
||||
chmod 700 $HOME/.pki/nssdb
|
||||
certutil -d $HOME/.pki/nssdb -N --empty-password
|
||||
else
|
||||
echo "certutil nssdb 正常"
|
||||
fi
|
||||
}
|
||||
Install_jq() {
|
||||
# Check if jq is already installed
|
||||
if command -v jq &>/dev/null; then
|
||||
echo "jq 工具已安装。"
|
||||
else
|
||||
echo "jq 用来解析版本更新。"
|
||||
# Check the package manager
|
||||
if command -v apt &>/dev/null; then
|
||||
# Using apt (Debian/Ubuntu)
|
||||
sudo apt update
|
||||
sudo apt install -y jq
|
||||
elif command -v dnf &>/dev/null; then
|
||||
# Using dnf (Fedora)
|
||||
sudo dnf install -y jq
|
||||
elif command -v yum &>/dev/null; then
|
||||
# Using yum (CentOS/Red Hat)
|
||||
sudo yum install -y jq
|
||||
elif command -v pacman &>/dev/null; then
|
||||
# Using pacman (Arch Linux)
|
||||
sudo pacman -S jq
|
||||
else
|
||||
echo "请手动安装 jq 工具。"
|
||||
exit 1
|
||||
fi
|
||||
echo "请手动安装 jq 工具。"
|
||||
fi
|
||||
}
|
||||
Install_zenity() {
|
||||
# 判断发行版类型
|
||||
if command -v zenity &>/dev/null; then
|
||||
echo "zenity 工具已安装。"
|
||||
else
|
||||
echo "安装过程需要 zenity 工具。"
|
||||
# 判断包管理器
|
||||
if command -v apt &>/dev/null; then
|
||||
# 使用 apt (Debian/Ubuntu)
|
||||
sudo apt update
|
||||
sudo apt install -y zenity
|
||||
elif command -v dnf &>/dev/null; then
|
||||
# 使用 dnf (Fedora)
|
||||
sudo dnf install -y zenity
|
||||
elif command -v yum &>/dev/null; then
|
||||
# 使用 yum (CentOS/Red Hat)
|
||||
sudo yum install -y zenity
|
||||
elif command -v pacman &>/dev/null; then
|
||||
# 使用 pacman (Arch Linux)
|
||||
# sudo pacman -S zenity
|
||||
echo "请手动安装 zenity 工具。"
|
||||
exit 1
|
||||
else
|
||||
echo "请手动安装 zenity 工具。"
|
||||
exit 1
|
||||
fi
|
||||
echo "zenity 工具已安装。"
|
||||
fi
|
||||
}
|
||||
|
||||
Show_Run() {
|
||||
local param1=$1
|
||||
# 显示提示框,询问是否运行程序
|
||||
zenity --question --text="$1" --width=400
|
||||
|
||||
# 获取上一个命令的退出码
|
||||
response=$?
|
||||
|
||||
if [ $response -eq 0 ]; then
|
||||
echo "程序已启动。"
|
||||
exit 0 &
|
||||
# 用户点击了 "运行" 按钮,启动程序
|
||||
/bin/sh -c "$base_path/$exec_name.sh"
|
||||
else
|
||||
# 用户点击了 "关闭" 按钮,退出脚本
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
Kill_Process() {
|
||||
# 尝试的次数
|
||||
Kill_MAX_RETRIES=3
|
||||
|
||||
# 循环尝试终止进程
|
||||
for process_name in "${PROCESS_NAMES[@]}"; do
|
||||
kill_retry=1
|
||||
while [ $kill_retry -le $Kill_MAX_RETRIES ]; do
|
||||
pid=$(pgrep "$process_name")
|
||||
if [ -n "$pid" ]; then
|
||||
echo "尝试 $kill_retry: 进程 $process_name 正在运行中。正在终止..."
|
||||
kill $pid
|
||||
sleep 2
|
||||
else
|
||||
break
|
||||
fi
|
||||
kill_retry=$((kill_retry + 1))
|
||||
done
|
||||
done
|
||||
|
||||
for process_name in "${PROCESS_NAMES[@]}"; do
|
||||
# 检查是否成功终止进程
|
||||
if pgrep -x "$process_name" >/dev/null; then
|
||||
echo "无法终止程序 $process_name。尝试次数已达上限。"
|
||||
exit 1
|
||||
else
|
||||
echo "程序 $process_name 已成功终止。"
|
||||
fi
|
||||
done
|
||||
|
||||
}
|
||||
Install_certutil
|
||||
Install_zenity
|
||||
Install_jq
|
||||
certutil_Init
|
||||
Kill_Process
|
||||
|
||||
dotnet_exec="$dotnet_path/dotnet/dotnet"
|
||||
if [ -x "$dotnet_exec" ]; then
|
||||
echo "文件具有执行权限。"
|
||||
else
|
||||
chmod +x "$dotnet_exec"
|
||||
fi
|
||||
chmod +x "$base_path/$exec_name.sh"
|
||||
# xdg-icon-resource install "$base_path/Icons/Watt-Toolkit.png" --size 128 Watt-Toolkit
|
||||
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" >"$target_dir/Watt Toolkit.desktop"
|
||||
chmod +x "$target_dir/Watt Toolkit.desktop"
|
||||
|
||||
}
|
||||
InitDesktop
|
||||
# update-desktop-database ~/.local/share/applications
|
||||
#运行程序
|
||||
Show_Run "下载安装完成,是否启动程序?"
|
||||
exit 0
|
||||
@@ -1,38 +1,7 @@
|
||||
#!/bin/bash
|
||||
# 设置默认的 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
|
||||
}
|
||||
|
||||
base_path="$HOME/WattToolkit"
|
||||
mkdir -p "$base_path"
|
||||
cd "$base_path" || exit 1
|
||||
appVer_path="$base_path/WattToolkit.AppVer"
|
||||
exec_name="Steam++"
|
||||
tar_name="WattToolkit.tgz"
|
||||
@@ -213,9 +182,7 @@ Get_NewVer() {
|
||||
|
||||
sleep 1
|
||||
#本地版本 Hash
|
||||
if [ -f "AppVer" ]; then
|
||||
o_sha384=$(cat "AppVer")
|
||||
fi
|
||||
o_sha384=$(cat "AppVer")
|
||||
if [ -e "AppVer" ]; then
|
||||
if [ "${o_sha384,,}" = "${n_sha384,,}" ]; then
|
||||
Show_Run "已是最新版本,是否启动程序?"
|
||||
@@ -359,36 +326,17 @@ Kill_Process
|
||||
#解压
|
||||
Decompression
|
||||
# xdg-icon-resource install "$base_path/Icons/Watt-Toolkit.png" --size 128 Watt-Toolkit
|
||||
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
|
||||
#添加桌面文件
|
||||
rm -rf "$HOME/Desktop/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" >"$target_dir/Watt Toolkit.desktop"
|
||||
chmod +x "$target_dir/Watt Toolkit.desktop"
|
||||
|
||||
}
|
||||
InitDesktop
|
||||
StartupNotify=false" >"$HOME/Desktop/Watt Toolkit.desktop"
|
||||
chmod +x "$HOME/Desktop/Watt Toolkit.desktop"
|
||||
# update-desktop-database ~/.local/share/applications
|
||||
#运行程序
|
||||
Show_Run "下载安装完成,是否启动程序?"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
run_path=$(dirname "$0")
|
||||
base_path="$(dirname "$run_path")"
|
||||
base_path="$HOME/WattToolkit"
|
||||
export LC_ALL=en_US.UTF-8
|
||||
exec_name="Steam++"
|
||||
app_name="Watt Toolkit"
|
||||
AppData="$XDG_DATA_HOME/Steam++"
|
||||
@@ -8,37 +8,7 @@ AppData_t="$HOME/.local/share/Steam++"
|
||||
Cache="$XDG_CACHE_HOME/Steam++"
|
||||
Cache_t="$HOME/.cache/Steam+"
|
||||
PROCESS_NAMES=("$exec_name" "$app_name")
|
||||
export LC_ALL=en_US.UTF-8
|
||||
#检查是否存在 Steam++.sh 避免卸载错误
|
||||
file_to_check="$base_path/Steam++.sh"
|
||||
folders_to_check=("dotnet" "modules" "native" "script" "assemblies")
|
||||
if [ -e "$file_to_check" ]; then
|
||||
echo "文件 $file_to_check 存在"
|
||||
else
|
||||
echo "文件 $file_to_check 不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for folder in "${folders_to_check[@]}"; do
|
||||
folder_path="$base_path/$folder"
|
||||
if [ -d "$folder_path" ]; then
|
||||
echo "文件夹 $folder_path 存在"
|
||||
else
|
||||
echo "文件夹 $folder_path 不存在"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "验证该文件夹是 $app_name 安装目录,请确认是否卸载。"
|
||||
|
||||
read -p "所有文件和文件夹都存在,确认卸载吗? (输入 'y' 确认): " confirmation
|
||||
|
||||
if [ "${confirmation,,}" == "y" ]; then
|
||||
echo "开始执行卸载操作"
|
||||
# 在这里添加您的卸载操作
|
||||
else
|
||||
echo "用户取消卸载操作"
|
||||
exit 0
|
||||
fi
|
||||
Kill_Process() {
|
||||
# 尝试的次数
|
||||
Kill_MAX_RETRIES=3
|
||||
|
||||
@@ -212,15 +212,6 @@
|
||||
"Summary": "菜单排序",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
},
|
||||
{
|
||||
"TypeName": "string",
|
||||
"PropertyName": "StartDefaultPageName",
|
||||
"DefaultValue": "null",
|
||||
"DefaultValueIsConst": true,
|
||||
"Summary": "程序启动时默认页",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
}
|
||||
],
|
||||
"Usings": ""
|
||||
@@ -496,15 +487,6 @@
|
||||
"Summary": "账号平台设置集合",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
},
|
||||
{
|
||||
"TypeName": "bool",
|
||||
"PropertyName": "IsShowAccountName",
|
||||
"DefaultValue": "false",
|
||||
"DefaultValueIsConst": false,
|
||||
"Summary": "是否显示账号用户名",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
}
|
||||
],
|
||||
"Usings": ""
|
||||
@@ -979,15 +961,6 @@
|
||||
"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: de291c0d95...92eeb1ce78
+1
-1
Submodule ref/Common updated: 4fd40563b7...e258b48fbf
+1
-1
Submodule ref/DirectoryPackages updated: b6b85044cc...07bf9c2d47
Submodule ref/SteamAchievementManager updated: 39dbdc9678...4c578c1cc4
+1
-1
Submodule ref/SteamClient updated: fddb907049...2d79c7da61
Submodule ref/WTTS.MicroServices.ClientSDK updated: 5f3111baad...24bf5ab24b
+1
-1
Submodule ref/WinAuth updated: f6ad4f84ca...a20460165f
Binary file not shown.
Binary file not shown.
@@ -3,14 +3,6 @@ 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";
|
||||
@@ -24,12 +16,12 @@ public static partial class AssemblyInfo
|
||||
/// <summary>
|
||||
/// 预览版本号,范围 1~9,只增不减
|
||||
/// </summary>
|
||||
const string ver_for_preview = "8";
|
||||
const string ver_for_preview = "7";
|
||||
|
||||
/// <summary>
|
||||
/// RC 版本号,范围 0~9,只增不减
|
||||
/// </summary>
|
||||
const string ver_for_rc = "8";
|
||||
const string ver_for_rc = "3";
|
||||
|
||||
public const string FileVersion = $"{Version2}.{ver_for_rc}0{ver_for_preview}.0";
|
||||
|
||||
@@ -154,20 +146,4 @@ false
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false)]
|
||||
sealed class Mobius3Attribute : Attribute
|
||||
{
|
||||
public Mobius3Attribute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Mobius3Attribute(string str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool Obsolete { get; set; }
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// Mobius Properties\XmlnsDefinition.cs
|
||||
#if (WINDOWS || MACCATALYST || MACOS || LINUX) && !(IOS || ANDROID)
|
||||
// C# 10 定义全局 using
|
||||
|
||||
@@ -23,9 +22,6 @@ global using Avalonia.Metadata;
|
||||
[assembly: XmlnsDefinition("https://steampp.net/ui", "BD.WTTS.Converters")]
|
||||
[assembly: XmlnsDefinition("https://steampp.net/ui", "BD.WTTS.Markup")]
|
||||
[assembly: XmlnsDefinition("https://steampp.net/ui", "BD.WTTS.Client.Resources")]
|
||||
[assembly: XmlnsDefinition("https://steampp.net/ui", "Mobius.Models")]
|
||||
[assembly: XmlnsDefinition("https://steampp.net/ui", "Mobius")]
|
||||
|
||||
[assembly: XmlnsDefinition("https://steampp.net/services", "BD.WTTS.Services")]
|
||||
[assembly: XmlnsDefinition("https://steampp.net/services", "BD.WTTS.Plugins")]
|
||||
[assembly: XmlnsDefinition("https://steampp.net/services", "BD.WTTS.Plugins.Abstractions")]
|
||||
|
||||
@@ -38,9 +38,9 @@ public interface IFontManagerImpl2 : IFontManagerImpl
|
||||
return Impl.TryCreateGlyphTypeface(familyName, style, weight, stretch, out glyphTypeface);
|
||||
}
|
||||
|
||||
bool IFontManagerImpl.TryCreateGlyphTypeface(Stream stream, FontSimulations fontSimulations, [NotNullWhen(returnValue: true)] out IGlyphTypeface? glyphTypeface)
|
||||
bool IFontManagerImpl.TryCreateGlyphTypeface(Stream stream, [NotNullWhen(returnValue: true)] out IGlyphTypeface? glyphTypeface)
|
||||
{
|
||||
return Impl.TryCreateGlyphTypeface(stream, fontSimulations, out glyphTypeface);
|
||||
return Impl.TryCreateGlyphTypeface(stream, out glyphTypeface);
|
||||
}
|
||||
|
||||
//IGlyphTypeface IFontManagerImpl.CreateGlyphTypeface(Typeface typeface)
|
||||
|
||||
+2505
-166
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,67 +8,70 @@
|
||||
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.999.0" />
|
||||
<Identity
|
||||
Name="4651ED44255E.47979655102CE"
|
||||
Publisher="CN=A90E406B-B2D3-4A23-B061-0FA1D65C4F66"
|
||||
Version="3.0.207.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>Watt Toolkit</DisplayName>
|
||||
<PublisherDisplayName>软妹币玩家</PublisherDisplayName>
|
||||
<Logo>Images\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
<rescap:Capability Name="allowElevation" />
|
||||
</Capabilities>
|
||||
<Extensions>
|
||||
<desktop2:Extension Category="windows.firewallRules">
|
||||
<desktop2:FirewallRules Executable="Steam++\modules\Accelerator\Steam++.Accelerator.exe">
|
||||
<desktop2:Rule Direction="in" IPProtocol="TCP" Profile="all"/>
|
||||
<desktop2:Rule Direction="in" IPProtocol="UDP" Profile="all"/>
|
||||
</desktop2:FirewallRules>
|
||||
</desktop2:Extension>
|
||||
</Extensions>
|
||||
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
<rescap:Capability Name="allowElevation" />
|
||||
</Capabilities>
|
||||
</Package>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"><assemblyIdentity version="1.0.0.0" name="BeyondDimension.WattToolkit.AppHost"/><trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"><requestedExecutionLevel level="requireAdministrator" uiAccess="false" /></requestedPrivileges></security></trustInfo><compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application><supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" /><supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" /><supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" /><supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" /><supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /></application></compatibility></assembly>
|
||||
<?xml version="1.0" encoding="utf-8"?><assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"><assemblyIdentity version="1.0.0.0" name="BeyondDimension.WattToolkit.AppHost"/><trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"><requestedExecutionLevel level="asInvoker" uiAccess="false" /></requestedPrivileges></security></trustInfo><compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application><supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" /><supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" /><supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" /><supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" /><supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /></application></compatibility></assembly>
|
||||
@@ -22,8 +22,6 @@
|
||||
<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>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"><assemblyIdentity version="1.0.0.0" name="BeyondDimension.WattToolkit.App"/><trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"><requestedExecutionLevel level="requireAdministrator" uiAccess="false" /></requestedPrivileges></security></trustInfo><compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application><supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" /><supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" /><supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" /><supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" /><supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /></application></compatibility></assembly>
|
||||
<?xml version="1.0" encoding="utf-8"?><assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"><assemblyIdentity version="1.0.0.0" name="BeyondDimension.WattToolkit.App"/><trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"><requestedExecutionLevel level="asInvoker" uiAccess="false" /></requestedPrivileges></security></trustInfo><compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application><supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" /><supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" /><supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" /><supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" /><supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /></application></compatibility></assembly>
|
||||
@@ -81,10 +81,8 @@
|
||||
<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="AvaloniaEdit.TextMate" />
|
||||
<!--<PackageReference Include="Avalonia.AvaloniaEdit" />-->
|
||||
<!--<PackageReference Include="Markdown.Avalonia" />-->
|
||||
<PackageReference Include="FluentAvaloniaUI" />
|
||||
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" />
|
||||
@@ -128,15 +126,6 @@
|
||||
<ProjectReference Include="..\BD.WTTS.Client\BD.WTTS.Client.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<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" />
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
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,7 +2,7 @@ namespace BD.WTTS.UI;
|
||||
|
||||
public static class ControlExtensions
|
||||
{
|
||||
public static void SetViewModel<T>(this Control c, bool useCache = false) where T : ViewModelBase, new()
|
||||
public static void SetViewModel<T>(this Control c, bool useCache = true) where T : ViewModelBase
|
||||
{
|
||||
if (c.DataContext == null || c.DataContext.GetType() != typeof(T))
|
||||
{
|
||||
@@ -11,7 +11,7 @@ public static class ControlExtensions
|
||||
if (useCache)
|
||||
cx = IViewModelManager.Instance.Get<T>();
|
||||
else
|
||||
cx = new T();
|
||||
cx = Activator.CreateInstance<T>();
|
||||
|
||||
c.DataContext = cx;
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
namespace BD.WTTS;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IEnumerable"/> extensions methods
|
||||
/// </summary>
|
||||
public static class IEnumerableExtensions
|
||||
{
|
||||
public static IEnumerable<IEnumerable> Batch(this IEnumerable source, int size)
|
||||
{
|
||||
object[]? bucket = null;
|
||||
var count = 0;
|
||||
|
||||
foreach (var item in source)
|
||||
{
|
||||
bucket ??= new object[size];
|
||||
|
||||
bucket[count++] = item;
|
||||
|
||||
if (count == size)
|
||||
{
|
||||
yield return bucket;
|
||||
bucket = null;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (bucket != null && count > 0)
|
||||
yield return bucket.Take(count).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -4,7 +4,7 @@ using System.Collections.Immutable;
|
||||
namespace BD.WTTS.Services.Implementation;
|
||||
|
||||
/// <inheritdoc cref="IWindowManager"/>
|
||||
public sealed class AvaloniaWindowManagerImpl : IWindowManagerImpl
|
||||
sealed class AvaloniaWindowManagerImpl : IWindowManagerImpl
|
||||
{
|
||||
Type? IWindowManagerImpl.WindowType => typeof(Window);
|
||||
|
||||
@@ -113,9 +113,10 @@ public sealed class AvaloniaWindowManagerImpl : IWindowManagerImpl
|
||||
|
||||
if (viewModel != null)
|
||||
{
|
||||
|
||||
if (viewModel is IWindowViewModel window)
|
||||
{
|
||||
window.Close = b => td?.Hide(b ? TaskDialogStandardResult.OK : TaskDialogStandardResult.Close);
|
||||
window.Close = () => td?.Hide(TaskDialogStandardResult.Close);
|
||||
}
|
||||
|
||||
td.DataContext = viewModel;
|
||||
|
||||
@@ -7,28 +7,12 @@ 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;
|
||||
@@ -66,10 +50,6 @@ App.Theme
|
||||
}
|
||||
}
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.SetThemeNotChangeValue
|
||||
""")]
|
||||
public void SetThemeNotChangeValue(AppTheme value)
|
||||
{
|
||||
var mode = value switch
|
||||
@@ -91,10 +71,6 @@ App.SetThemeNotChangeValue
|
||||
}
|
||||
}
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.SetThemeAccent
|
||||
""")]
|
||||
public static void SetThemeAccent(string? colorHex)
|
||||
{
|
||||
if (colorHex == null)
|
||||
|
||||
@@ -9,34 +9,14 @@ 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
|
||||
@@ -87,10 +67,6 @@ App.InitTrayIcon
|
||||
}
|
||||
}
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.UpdateMenuItems
|
||||
""")]
|
||||
public void UpdateMenuItems()
|
||||
{
|
||||
MainThread2.BeginInvokeOnMainThread(() =>
|
||||
@@ -149,20 +125,12 @@ App.UpdateMenuItems
|
||||
{
|
||||
subMenu = new NativeMenu();
|
||||
foreach (var sub in item.Value.Items)
|
||||
{
|
||||
var menu = new NativeMenuItem
|
||||
subMenu.Add(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,
|
||||
@@ -190,10 +158,6 @@ App.UpdateMenuItems
|
||||
});
|
||||
}
|
||||
|
||||
[Mobius(
|
||||
"""
|
||||
App.UpdateMenuItems
|
||||
""")]
|
||||
public void UpdateMenuItems(string menuKey, TrayMenuItem trayMenuItem)
|
||||
{
|
||||
if (TrayMenus != null)
|
||||
|
||||
@@ -11,12 +11,6 @@ public sealed partial class App : Application
|
||||
{
|
||||
const string TAG = "AvaApp";
|
||||
|
||||
public App()
|
||||
{
|
||||
OpenBrowserCommand = ReactiveCommand.Create<object?>(OpenBrowserCommandCore);
|
||||
CopyToClipboardCommand = ReactiveCommand.Create<object?>(CopyToClipboardCommandCore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前主窗口
|
||||
/// </summary>
|
||||
@@ -52,7 +46,6 @@ public sealed partial class App : Application
|
||||
#if WINDOWS || LINUX || MACOS
|
||||
if (GeneralSettings.MinimizeOnStartup.Value)
|
||||
Startup.Instance.IsMinimize = true;
|
||||
|
||||
if (Startup.Instance.IsSteamRun)
|
||||
{
|
||||
try
|
||||
@@ -100,16 +93,15 @@ 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 && MainWindow is MainWindow ? null :
|
||||
Startup.Instance.IsMinimize ? null :
|
||||
#endif
|
||||
MainWindow;
|
||||
|
||||
if (Startup.Instance.IsMinimize && MainWindow is AppWindow appWindow)
|
||||
{
|
||||
Task2.InBackground(() => appWindow.SplashScreen?.RunTasks(CancellationToken.None));
|
||||
Task2.InBackground(() => appWindow.SplashScreen.RunTasks(CancellationToken.None));
|
||||
}
|
||||
}
|
||||
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleView)
|
||||
@@ -231,32 +223,16 @@ public sealed partial class App : Application
|
||||
|
||||
public static FontFamily DefaultFontFamily => _DefaultFontFamily.Value;
|
||||
|
||||
public ICommand OpenBrowserCommand { get; }
|
||||
|
||||
public async void OpenBrowserCommandCore(object? url)
|
||||
public void OpenBrowserCommand(object url)
|
||||
{
|
||||
try
|
||||
{
|
||||
var urlString = url?.ToString();
|
||||
if (string.IsNullOrEmpty(urlString))
|
||||
if (url == null || string.IsNullOrEmpty(url.ToString()))
|
||||
{
|
||||
Toast.Show(ToastIcon.Warning, "打开链接失败");
|
||||
return;
|
||||
}
|
||||
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);
|
||||
Browser2.Open(url.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -264,9 +240,7 @@ public sealed partial class App : Application
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand CopyToClipboardCommand { get; }
|
||||
|
||||
public async void CopyToClipboardCommandCore(object? text)
|
||||
public async void CopyToClipboardCommand(object text)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -6,16 +6,15 @@
|
||||
x:CompileBindings="True">
|
||||
<Styles.Resources>
|
||||
<ResourceDictionary>
|
||||
<sys:Double x:Key="TitleBarHeight">50</sys:Double>
|
||||
<Thickness x:Key="TitleBarAfterMargin">0,50,0,0</Thickness>
|
||||
<sys:Double x:Key="TitleBarHeight">60</sys:Double>
|
||||
<Thickness x:Key="TitleBarAfterMargin">0,60,0,0</Thickness>
|
||||
<sys:Double x:Key="SplashScreenImageWidth">100</sys:Double>
|
||||
|
||||
<Thickness x:Key="PageMargin">10</Thickness>
|
||||
<sys:Double x:Key="SettingsSpacing">3</sys:Double>
|
||||
|
||||
<sys:Char x:Key="PasswordChar">●</sys:Char>
|
||||
<!--<sys:Char x:Key="PasswordChar">•</sys:Char>
|
||||
<sys:Char x:Key="PasswordChar">·</sys:Char>-->
|
||||
<!--<sys:Char x:Key="PasswordChar">●</sys:Char>-->
|
||||
<sys:Char x:Key="PasswordChar">•</sys:Char>
|
||||
<FontFamily x:Key="ContentControlThemeFontFamily">Null</FontFamily>
|
||||
<BoxShadows x:Key="InfoBoxShadow">4 4 32 0 #66000000</BoxShadows>
|
||||
|
||||
@@ -45,7 +44,6 @@
|
||||
|
||||
<StyleInclude Source="/UI/Styling/InfoBox.axaml" />
|
||||
<StyleInclude Source="/UI/Styling/Controls/PageBase.axaml" />
|
||||
<StyleInclude Source="/UI/Styling/Controls/CarouselItems.axaml" />
|
||||
<StyleInclude Source="/UI/Styling/Controls/OptionsDisplayItem.axaml" />
|
||||
<StyleInclude Source="/UI/Styling/Controls/RippleEffect.axaml" />
|
||||
<StyleInclude Source="/UI/Styling/Controls/Draggable.axaml" />
|
||||
@@ -66,7 +64,6 @@
|
||||
<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">
|
||||
<HyperlinkButton Content="更新日志" />
|
||||
<ui:HyperlinkButton Content="更新日志" />
|
||||
<Button Content="更新日志" Theme="{StaticResource HyperlinkButton}" />
|
||||
<Button
|
||||
Content="更新日志"
|
||||
@@ -87,7 +87,7 @@
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border
|
||||
<ui:FABorder
|
||||
Name="Root"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
@@ -101,19 +101,19 @@
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
RecognizesAccessKey="True" />
|
||||
</Border>
|
||||
</ui:FABorder>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
|
||||
<Style Selector="^:pointerover">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pressed">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#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/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#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/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundChecked}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
@@ -140,7 +140,7 @@
|
||||
|
||||
|
||||
<Style Selector="^:pointerover">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#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/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#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/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#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/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorTransparentBrush}" />
|
||||
</Style>
|
||||
|
||||
|
||||
<Style Selector="^:pointerover">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pressed">
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#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/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorDisabledBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
@@ -214,13 +214,10 @@
|
||||
<Style Selector="Button.Plain:pointerover">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
<Style Selector="Button.Plain:pointerover /template/ Border#Root">
|
||||
<Style Selector="Button.Plain:pointerover /template/ ui|FABorder#Root">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
<Style Selector="Button.Plain:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
|
||||
|
||||
|
||||
</Styles>
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
<Styles
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:generic="using:System.Collections.Generic"
|
||||
xmlns:spp="https://steampp.net/ui"
|
||||
xmlns:sys="using:System"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
x:CompileBindings="True">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<spp:CarouselItems>
|
||||
<spp:CarouselItems.Items>
|
||||
<Border Background="Red" />
|
||||
<Border Background="Blue" />
|
||||
<Border Background="Black" />
|
||||
<Border Background="Yellow" />
|
||||
</spp:CarouselItems.Items>
|
||||
</spp:CarouselItems>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<Style Selector="spp|CarouselItems">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border
|
||||
BorderBrush="{DynamicResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="0"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="8">
|
||||
<Grid RowDefinitions="*,5,Auto">
|
||||
<Carousel Name="CarouselControl" Classes="AnimeSlide">
|
||||
<Carousel.ItemTemplate>
|
||||
<DataTemplate DataType="sys:Object">
|
||||
<ItemsControl ItemTemplate="{Binding $parent[spp:CarouselItems].ItemTemplate}" ItemsSource="{Binding}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<spp:FixedWrapPanel ItemsPerLine="{Binding $parent[spp:CarouselItems].ItemsPerPage}" Spacing="5" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</DataTemplate>
|
||||
</Carousel.ItemTemplate>
|
||||
</Carousel>
|
||||
<Button
|
||||
Name="Left"
|
||||
HorizontalAlignment="Left"
|
||||
Background="#80000000"
|
||||
Classes="action"
|
||||
IsVisible="False">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="ChevronLeft" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="Right"
|
||||
HorizontalAlignment="Right"
|
||||
Background="#80000000"
|
||||
Classes="action"
|
||||
IsVisible="False">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="ChevronRight" />
|
||||
</Button>
|
||||
|
||||
<Panel
|
||||
Grid.Row="2"
|
||||
Height="10"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom">
|
||||
<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" />
|
||||
</DataTemplate.DataType>
|
||||
<Button
|
||||
Padding="0"
|
||||
Classes="Plain"
|
||||
Command="{Binding $parent[spp:CarouselItems].CarouselBannerIndexCommand}"
|
||||
CommandParameter="{Binding Key}">
|
||||
<Ellipse
|
||||
Name="IndexEllipse"
|
||||
Width="10"
|
||||
Height="10"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Fill="{Binding Value}"
|
||||
Opacity="0.6"
|
||||
StrokeThickness="0" />
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Panel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
|
||||
<Style Selector="spp|CarouselItems /template/ Button.action">
|
||||
<Setter Property="Width" Value="36" />
|
||||
<Setter Property="Height" Value="64" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Style>
|
||||
</Styles>
|
||||
@@ -18,27 +18,15 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{TemplateBinding IsLoading}"
|
||||
Spacing="10">
|
||||
<!--<spp:Image2
|
||||
Spacing="8">
|
||||
<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" />-->
|
||||
<Border
|
||||
Width="35"
|
||||
Height="35"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top">
|
||||
<ProgressBar
|
||||
Classes="Circle ParentSize"
|
||||
IsIndeterminate="{TemplateBinding IsIndeterminate}"
|
||||
Maximum="{TemplateBinding Maximum}"
|
||||
Minimum="{TemplateBinding Minimum}"
|
||||
Value="{TemplateBinding ProgressValue}" />
|
||||
</Border>
|
||||
Stretch="UniformToFill" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Text="{Binding Path=Res.GameList_IsLoading, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
@@ -51,6 +39,18 @@
|
||||
ConverterParameter=invert}"
|
||||
Text="{TemplateBinding CustomLoadingText}"
|
||||
Theme="{StaticResource BodyStrongTextBlockStyle}" />
|
||||
<Border
|
||||
Width="35"
|
||||
Height="35"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top">
|
||||
<ProgressBar
|
||||
Classes="Circle ParentSize"
|
||||
IsIndeterminate="{TemplateBinding IsIndeterminate}"
|
||||
Maximum="{TemplateBinding Maximum}"
|
||||
Minimum="{TemplateBinding Minimum}"
|
||||
Value="{TemplateBinding ProgressValue}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<!--<TextBlock
|
||||
@@ -75,34 +75,21 @@
|
||||
</ContentPresenter.IsVisible>-->
|
||||
</ContentPresenter>
|
||||
|
||||
<Panel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<spp:Image2
|
||||
Width="100"
|
||||
Height="100"
|
||||
Margin="0,0,0,120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="avares://BD.WTTS.Client.Avalonia/UI/Assets/Icons/empty.png"
|
||||
Stretch="UniformToFill" />
|
||||
<Panel.IsVisible>
|
||||
<ContentPresenter
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding NoResultMessage}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}">
|
||||
<ContentPresenter.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="IsShowNoResultText" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
<Binding Path="!IsLoading" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
</MultiBinding>
|
||||
</Panel.IsVisible>
|
||||
<ContentPresenter
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding NoResultMessage}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
</Panel>
|
||||
</ContentPresenter.IsVisible>
|
||||
</ContentPresenter>
|
||||
</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>
|
||||
<Border
|
||||
<ui:FABorder
|
||||
Name="LayoutRoot"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Border.Transitions>
|
||||
<ui:FABorder.Transitions>
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="00:00:00.083" />
|
||||
<BrushTransition Property="BorderBrush" Duration="00:00:00.083" />
|
||||
</Transitions>
|
||||
</Border.Transitions>
|
||||
</ui:FABorder.Transitions>
|
||||
<Grid MinHeight="{TemplateBinding MinHeight}" ColumnDefinitions="Auto,*,Auto,Auto">
|
||||
<Viewbox
|
||||
Name="IconHost"
|
||||
@@ -113,7 +113,7 @@
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</ui:FABorder>
|
||||
|
||||
<ContentPresenter
|
||||
Name="ExpandedContentPresenter"
|
||||
@@ -144,10 +144,10 @@
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="spp|OptionsDisplayItem /template/ Border#LayoutRoot:pointerover">
|
||||
<Style Selector="spp|OptionsDisplayItem /template/ ui|FABorder#LayoutRoot:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
<Style Selector="spp|OptionsDisplayItem:pressed /template/ Border#LayoutRoot:pointerover">
|
||||
<Style Selector="spp|OptionsDisplayItem:pressed /template/ ui|FABorder#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/ Border#LayoutRoot">
|
||||
<Style Selector="spp|OptionsDisplayItem:expanded /template/ ui|FABorder#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>
|
||||
<Border
|
||||
<ui:FABorder
|
||||
Name="LayoutRoot"
|
||||
Padding="12"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Border.Transitions>
|
||||
<ui:FABorder.Transitions>
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="00:00:00.083" />
|
||||
<BrushTransition Property="BorderBrush" Duration="00:00:00.083" />
|
||||
</Transitions>
|
||||
</Border.Transitions>
|
||||
</ui:FABorder.Transitions>
|
||||
<Grid RowDefinitions="*,*">
|
||||
<Border
|
||||
Width="72"
|
||||
@@ -241,7 +241,7 @@
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</ui:FABorder>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
@@ -38,18 +38,18 @@
|
||||
<Setter Property="MinHeight" Value="{DynamicResource SettingsExpanderItemMinHeight}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border
|
||||
<ui:FABorder
|
||||
Name="Root"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<Border.Transitions>
|
||||
<ui:FABorder.Transitions>
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="00:00:00.083" />
|
||||
<BrushTransition Property="BorderBrush" Duration="00:00:00.083" />
|
||||
</Transitions>
|
||||
</Border.Transitions>
|
||||
</ui:FABorder.Transitions>
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto,Auto" RowDefinitions="*,Auto">
|
||||
<Viewbox
|
||||
@@ -102,7 +102,7 @@
|
||||
<ContentPresenter Name="ExpandChevronActionIconContainer" Content="{Binding TemplateSettings.ActionIcon, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</Border>
|
||||
</ui:FABorder>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:nth-last-child(1) /template/ Border#Root">
|
||||
<Style Selector="^:nth-last-child(1) /template/ ui|FABorder#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/ Border#Root">
|
||||
<Style Selector="^:pointerover /template/ ui|FABorder#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorSecondaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ControlFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed /template/ Border#Root">
|
||||
<Style Selector="^:pressed /template/ ui|FABorder#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/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#Root">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorDisabledBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeColorDefaultBrush}" />
|
||||
<Setter Property="TextElement.Foreground" Value="{DynamicResource TextFillColorDisabledBrush}" />
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
<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">
|
||||
<Border
|
||||
<ui:FABorder
|
||||
Name="ContentRoot"
|
||||
VerticalAlignment="Top"
|
||||
BorderBrush="{DynamicResource InfoBarBorderBrush}"
|
||||
@@ -205,13 +205,13 @@
|
||||
</Button>
|
||||
</Grid>
|
||||
</Panel>
|
||||
</Border>
|
||||
</ui:FABorder>
|
||||
</LayoutTransformControl>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^:informational">
|
||||
<Style Selector="^ /template/ Border#ContentRoot">
|
||||
<Style Selector="^ /template/ ui|FABorder#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/ Border#ContentRoot">
|
||||
<Style Selector="^ /template/ ui|FABorder#ContentRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource InfoBarErrorSeverityBackgroundBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Ellipse#IconBackground">
|
||||
@@ -241,7 +241,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:warning">
|
||||
<Style Selector="^ /template/ Border#ContentRoot">
|
||||
<Style Selector="^ /template/ ui|FABorder#ContentRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource InfoBarWarningSeverityBackgroundBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Ellipse#IconBackground">
|
||||
@@ -255,7 +255,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:success">
|
||||
<Style Selector="^ /template/ Border#ContentRoot">
|
||||
<Style Selector="^ /template/ ui|FABorder#ContentRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource InfoBarSuccessSeverityBackgroundBrush}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Ellipse#IconBackground">
|
||||
@@ -294,7 +294,7 @@
|
||||
</Style>
|
||||
|
||||
<!-- Visible -->
|
||||
<Style Selector="^:hidden /template/ Border#ContentRoot">
|
||||
<Style Selector="^:hidden /template/ ui|FABorder#ContentRoot">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border
|
||||
<ui:FABorder
|
||||
Name="Root"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
@@ -83,19 +83,19 @@
|
||||
BorderThickness="1"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
TemplatedControl.IsTemplateFocusTarget="True">
|
||||
<Border.Transitions>
|
||||
<ui:FABorder.Transitions>
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="00:00:00.083" />
|
||||
</Transitions>
|
||||
</Border.Transitions>
|
||||
</ui:FABorder.Transitions>
|
||||
|
||||
<Panel>
|
||||
<Border
|
||||
<ui:FABorder
|
||||
Name="Hover"
|
||||
Margin="3"
|
||||
Background="Transparent"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Border.Transitions>
|
||||
<ui:FABorder.Transitions>
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="00:00:00.083" />
|
||||
<TransformOperationsTransition
|
||||
@@ -103,8 +103,8 @@
|
||||
Property="RenderTransform"
|
||||
Duration="00:00:00.167" />
|
||||
</Transitions>
|
||||
</Border.Transitions>
|
||||
</Border>
|
||||
</ui:FABorder.Transitions>
|
||||
</ui:FABorder>
|
||||
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
@@ -139,19 +139,19 @@
|
||||
</Rectangle>
|
||||
|
||||
</Panel>
|
||||
</Border>
|
||||
</ui:FABorder>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
|
||||
<Style Selector="^:pointerover">
|
||||
<Style Selector="^ /template/ Border#Hover">
|
||||
<Style Selector="^ /template/ ui|FABorder#Hover">
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pressed">
|
||||
<Style Selector="^ /template/ Border#Hover">
|
||||
<Style Selector="^ /template/ ui|FABorder#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/ Border#Hover">
|
||||
<Style Selector="^ /template/ ui|FABorder#Hover">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#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/ Border#Hover">
|
||||
<Style Selector="^ /template/ ui|FABorder#Hover">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#Root">
|
||||
<Style Selector="^ /template/ ui|FABorder#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}">
|
||||
<Border
|
||||
<ui:FABorder
|
||||
Name="ContentRoot"
|
||||
MinWidth="{DynamicResource TaskDialogMinWidth}"
|
||||
MinHeight="{DynamicResource TaskDialogMinHeight}"
|
||||
@@ -216,7 +216,7 @@
|
||||
</ItemsControl>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</ui:FABorder>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
@@ -303,7 +303,7 @@
|
||||
<Style Selector="^ /template/ Panel#LayoutRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource TaskDialogSmokeFill}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#ContentRoot">
|
||||
<Style Selector="^ /template/ ui|FABorder#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/ Border#ContentRoot">
|
||||
<Style Selector="^:hidden /template/ ui|FABorder#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/ Border#ContentRoot">
|
||||
<Style Selector="^:open /template/ ui|FABorder#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}">
|
||||
<Border
|
||||
<ui:FABorder
|
||||
Name="ContentRoot"
|
||||
MinWidth="{DynamicResource TaskDialogMinWidth}"
|
||||
MinHeight="{DynamicResource TaskDialogMinHeight}"
|
||||
@@ -521,7 +521,7 @@
|
||||
</ItemsControl>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</ui:FABorder>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
@@ -14,5 +14,4 @@
|
||||
</Styles.Resources>
|
||||
|
||||
<StyleInclude Source="/UI/Styling/Controls.axaml" />
|
||||
<StyleInclude Source="avares://AvaloniaEdit/Themes/Fluent/AvaloniaEdit.xaml" />
|
||||
</Styles>
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
<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,16 +21,4 @@
|
||||
</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,16 +21,4 @@
|
||||
</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="14,0"
|
||||
Margin="18,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top" />
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions;
|
||||
using Avalonia.Rendering.Composition;
|
||||
using FluentAvalonia.UI.Controls.Experimental;
|
||||
using FluentAvalonia.UI.Navigation;
|
||||
|
||||
namespace BD.WTTS.UI.Views.Pages;
|
||||
|
||||
@@ -9,8 +7,6 @@ public class PageBase : UserControl
|
||||
{
|
||||
public PageBase() : base()
|
||||
{
|
||||
_disposables = new();
|
||||
|
||||
SizeChanged += PageBaseSizeChanged;
|
||||
|
||||
if (HeaderBackground == null)
|
||||
@@ -18,8 +14,6 @@ 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);
|
||||
}
|
||||
@@ -145,7 +139,6 @@ 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");
|
||||
@@ -164,7 +157,6 @@ public class PageBase : UserControl
|
||||
{
|
||||
base.OnUnloaded(e);
|
||||
_hasLoaded = false;
|
||||
_disposables.Dispose();
|
||||
}
|
||||
|
||||
private void PageBaseSizeChanged(object? sender, SizeChangedEventArgs e)
|
||||
@@ -274,28 +266,33 @@ 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 ((e.SourcePageType == typeof(HomePageViewModel)) ||
|
||||
// (e.SourcePageType == typeof(PluginStorePageViewModel)))
|
||||
// if ((!isFAControlPage && e.SourcePageType == typeof(CoreControlsPageViewModel)) ||
|
||||
// (isFAControlPage && e.SourcePageType == typeof(FAControlsOverviewPageViewModel)))
|
||||
// {
|
||||
// // 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,
|
||||
@@ -318,7 +315,6 @@ 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
|
||||
@@ -328,14 +324,13 @@ public class PageBase<TViewModel> : PageBase, IViewFor<TViewModel> where TViewMo
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PageBase{TViewModel}"/> class.
|
||||
/// </summary>
|
||||
public PageBase() : base()
|
||||
public PageBase()
|
||||
{
|
||||
// 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,7 +25,6 @@
|
||||
<spp:Image2
|
||||
Width="{Binding $parent[UserControl].Bounds.Width}"
|
||||
Height="{Binding $parent[UserControl].Bounds.Height}"
|
||||
EnableCancelToken="False"
|
||||
Source="{Binding ImageUrl}"
|
||||
Stretch="UniformToFill" />
|
||||
</Button>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public enum AlignContent
|
||||
{
|
||||
FlexStart,
|
||||
FlexEnd,
|
||||
Center,
|
||||
Stretch,
|
||||
SpaceBetween,
|
||||
SpaceAround,
|
||||
SpaceEvenly
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
[SuppressMessage("Naming", "CA1717:Only FlagsAttribute enums should have plural names")]
|
||||
public enum AlignItems
|
||||
{
|
||||
FlexStart,
|
||||
FlexEnd,
|
||||
Center,
|
||||
Stretch
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public static class Flex
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines an attached property to control the alignment of a specific child in a flex layout.
|
||||
/// </summary>
|
||||
public static readonly AttachedProperty<AlignItems?> AlignSelfProperty =
|
||||
AvaloniaProperty.RegisterAttached<Layoutable, AlignItems?>("AlignSelf", typeof(Flex));
|
||||
|
||||
/// <summary>
|
||||
/// Defines an attached property to control the order of a specific child in a flex layout.
|
||||
/// </summary>
|
||||
public static readonly AttachedProperty<int> OrderProperty =
|
||||
AvaloniaProperty.RegisterAttached<Layoutable, int>("Order", typeof(Flex));
|
||||
|
||||
public static readonly AttachedProperty<FlexBasis> BasisProperty =
|
||||
AvaloniaProperty.RegisterAttached<Layoutable, FlexBasis>("Basis", typeof(Flex), FlexBasis.Auto);
|
||||
|
||||
public static readonly AttachedProperty<double> ShrinkProperty =
|
||||
AvaloniaProperty.RegisterAttached<Layoutable, double>("Shrink", typeof(Flex), 1.0, validate: v => v >= 0.0);
|
||||
|
||||
public static readonly AttachedProperty<double> GrowProperty =
|
||||
AvaloniaProperty.RegisterAttached<Layoutable, double>("Grow", typeof(Flex), 0.0, validate: v => v >= 0.0);
|
||||
|
||||
internal static readonly AttachedProperty<double> BaseLengthProperty =
|
||||
AvaloniaProperty.RegisterAttached<Layoutable, double>("BaseLength", typeof(Flex), 0.0);
|
||||
|
||||
internal static readonly AttachedProperty<double> CurrentLengthProperty =
|
||||
AvaloniaProperty.RegisterAttached<Layoutable, double>("CurrentLength", typeof(Flex), 0.0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the child alignment in a flex layout
|
||||
/// </summary>
|
||||
public static AlignItems? GetAlignSelf(Layoutable layoutable)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
return layoutable.GetValue(AlignSelfProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the child alignment in a flex layout
|
||||
/// </summary>
|
||||
public static void SetAlignSelf(Layoutable layoutable, AlignItems? value)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
layoutable.SetValue(AlignSelfProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the child order in a flex layout
|
||||
/// </summary>
|
||||
public static int GetOrder(Layoutable layoutable)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
return layoutable.GetValue(OrderProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the child order in a flex layout
|
||||
/// </summary>
|
||||
public static void SetOrder(Layoutable layoutable, int value)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
layoutable.SetValue(OrderProperty, value);
|
||||
}
|
||||
|
||||
public static FlexBasis GetBasis(Layoutable layoutable)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
return layoutable.GetValue(BasisProperty);
|
||||
}
|
||||
|
||||
public static void SetBasis(Layoutable layoutable, FlexBasis value)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
layoutable.SetValue(BasisProperty, value);
|
||||
}
|
||||
|
||||
public static double GetShrink(Layoutable layoutable)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
return layoutable.GetValue(ShrinkProperty);
|
||||
}
|
||||
|
||||
public static void SetShrink(Layoutable layoutable, double value)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
layoutable.SetValue(ShrinkProperty, value);
|
||||
}
|
||||
|
||||
public static double GetGrow(Layoutable layoutable)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
return layoutable.GetValue(GrowProperty);
|
||||
}
|
||||
|
||||
public static void SetGrow(Layoutable layoutable, double value)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
layoutable.SetValue(GrowProperty, value);
|
||||
}
|
||||
|
||||
internal static double GetBaseLength(Layoutable layoutable)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
return layoutable.GetValue(BaseLengthProperty);
|
||||
}
|
||||
|
||||
internal static void SetBaseLength(Layoutable layoutable, double value)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
layoutable.SetValue(BaseLengthProperty, value);
|
||||
}
|
||||
|
||||
internal static double GetCurrentLength(Layoutable layoutable)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
return layoutable.GetValue(CurrentLengthProperty);
|
||||
}
|
||||
|
||||
internal static void SetCurrentLength(Layoutable layoutable, double value)
|
||||
{
|
||||
if (layoutable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutable));
|
||||
}
|
||||
|
||||
layoutable.SetValue(CurrentLengthProperty, value);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public readonly struct FlexBasis : IEquatable<FlexBasis>
|
||||
{
|
||||
public double Value { get; }
|
||||
|
||||
public FlexBasisKind Kind { get; }
|
||||
|
||||
public FlexBasis(double value, FlexBasisKind kind)
|
||||
{
|
||||
if (value < 0 || double.IsNaN(value) || double.IsInfinity(value))
|
||||
throw new ArgumentException($"Invalid basis value: {value}", nameof(value));
|
||||
if (kind < FlexBasisKind.Auto || kind > FlexBasisKind.Relative)
|
||||
throw new ArgumentException($"Invalid basis kind: {kind}", nameof(kind));
|
||||
Value = value;
|
||||
Kind = kind;
|
||||
}
|
||||
|
||||
public FlexBasis(double value) : this(value, FlexBasisKind.Absolute) { }
|
||||
|
||||
public static FlexBasis Auto => new(0.0, FlexBasisKind.Auto);
|
||||
|
||||
public bool IsAuto => Kind == FlexBasisKind.Auto;
|
||||
|
||||
public bool IsAbsolute => Kind == FlexBasisKind.Absolute;
|
||||
|
||||
public bool IsRelative => Kind == FlexBasisKind.Relative;
|
||||
|
||||
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
|
||||
public bool Equals(FlexBasis other) =>
|
||||
(IsAuto && other.IsAuto) || (Value == other.Value && Kind == other.Kind);
|
||||
|
||||
public override bool Equals(object? obj) =>
|
||||
obj is FlexBasis other && Equals(other);
|
||||
|
||||
public override int GetHashCode() =>
|
||||
HashCode.Combine(Value, (int)Kind);
|
||||
|
||||
public static bool operator ==(FlexBasis left, FlexBasis right) =>
|
||||
left.Equals(right);
|
||||
|
||||
public static bool operator !=(FlexBasis left, FlexBasis right) =>
|
||||
!left.Equals(right);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Kind switch
|
||||
{
|
||||
FlexBasisKind.Auto => "Auto",
|
||||
FlexBasisKind.Absolute => FormattableString.Invariant($"{Value:G17}"),
|
||||
FlexBasisKind.Relative => FormattableString.Invariant($"{Value * 100:G17}%"),
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
|
||||
public static FlexBasis Parse(string str)
|
||||
{
|
||||
return str.ToUpperInvariant() switch
|
||||
{
|
||||
"AUTO" => Auto,
|
||||
var s when s.EndsWith("%") => new FlexBasis(ParseDouble(s[..^1].Trim()) / 100, FlexBasisKind.Relative),
|
||||
_ => new FlexBasis(ParseDouble(str), FlexBasisKind.Absolute),
|
||||
};
|
||||
double ParseDouble(string s) => double.Parse(s, CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public enum FlexBasisKind
|
||||
{
|
||||
Auto,
|
||||
Absolute,
|
||||
Relative,
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public enum FlexDirection
|
||||
{
|
||||
Row,
|
||||
RowReverse,
|
||||
Column,
|
||||
ColumnReverse
|
||||
}
|
||||
@@ -1,468 +0,0 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public sealed class FlexPanel : Panel
|
||||
{
|
||||
private static readonly Func<Layoutable, int> s_getOrder = x => x is { } y ? Flex.GetOrder(y) : 0;
|
||||
private static readonly Func<Layoutable, bool> s_isVisible = x => x.IsVisible;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="Direction"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<FlexDirection> DirectionProperty =
|
||||
AvaloniaProperty.Register<FlexPanel, FlexDirection>(nameof(Direction));
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="JustifyContent"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<JustifyContent> JustifyContentProperty =
|
||||
AvaloniaProperty.Register<FlexPanel, JustifyContent>(nameof(JustifyContent));
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="AlignItems"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<AlignItems> AlignItemsProperty =
|
||||
AvaloniaProperty.Register<FlexPanel, AlignItems>(nameof(AlignItems));
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="AlignContent"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<AlignContent> AlignContentProperty =
|
||||
AvaloniaProperty.Register<FlexPanel, AlignContent>(nameof(AlignContent));
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="Wrap"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<FlexWrap> WrapProperty =
|
||||
AvaloniaProperty.Register<FlexPanel, FlexWrap>(nameof(Wrap), FlexWrap.Wrap);
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="ColumnSpacing"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<double> ColumnSpacingProperty =
|
||||
AvaloniaProperty.Register<FlexPanel, double>(nameof(ColumnSpacing));
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="RowSpacing"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<double> RowSpacingProperty =
|
||||
AvaloniaProperty.Register<FlexPanel, double>(nameof(RowSpacing));
|
||||
|
||||
private FlexLayoutState? _state;
|
||||
|
||||
static FlexPanel()
|
||||
{
|
||||
AffectsMeasure<FlexPanel>(
|
||||
DirectionProperty,
|
||||
JustifyContentProperty,
|
||||
WrapProperty,
|
||||
ColumnSpacingProperty,
|
||||
RowSpacingProperty);
|
||||
|
||||
AffectsArrange<FlexPanel>(
|
||||
AlignItemsProperty,
|
||||
AlignContentProperty);
|
||||
|
||||
AffectsParentMeasure<FlexPanel>(
|
||||
HorizontalAlignmentProperty,
|
||||
VerticalAlignmentProperty,
|
||||
Flex.OrderProperty,
|
||||
Flex.BasisProperty,
|
||||
Flex.ShrinkProperty,
|
||||
Flex.GrowProperty);
|
||||
|
||||
AffectsParentArrange<FlexPanel>(
|
||||
Flex.AlignSelfProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the flex direction
|
||||
/// </summary>
|
||||
public FlexDirection Direction
|
||||
{
|
||||
get => GetValue(DirectionProperty);
|
||||
set => SetValue(DirectionProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the flex justify content mode
|
||||
/// </summary>
|
||||
public JustifyContent JustifyContent
|
||||
{
|
||||
get => GetValue(JustifyContentProperty);
|
||||
set => SetValue(JustifyContentProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the flex align items mode
|
||||
/// </summary>
|
||||
public AlignItems AlignItems
|
||||
{
|
||||
get => GetValue(AlignItemsProperty);
|
||||
set => SetValue(AlignItemsProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the flex align content mode
|
||||
/// </summary>
|
||||
public AlignContent AlignContent
|
||||
{
|
||||
get => GetValue(AlignContentProperty);
|
||||
set => SetValue(AlignContentProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the flex wrap mode
|
||||
/// </summary>
|
||||
public FlexWrap Wrap
|
||||
{
|
||||
get => GetValue(WrapProperty);
|
||||
set => SetValue(WrapProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column spacing
|
||||
/// </summary>
|
||||
public double ColumnSpacing
|
||||
{
|
||||
get => GetValue(ColumnSpacingProperty);
|
||||
set => SetValue(ColumnSpacingProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the row spacing
|
||||
/// </summary>
|
||||
public double RowSpacing
|
||||
{
|
||||
get => GetValue(RowSpacingProperty);
|
||||
set => SetValue(RowSpacingProperty, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
var children = (IReadOnlyList<Layoutable>)Children;
|
||||
|
||||
var isColumn = Direction is FlexDirection.Column or FlexDirection.ColumnReverse;
|
||||
|
||||
var max = Uv.FromSize(availableSize, isColumn);
|
||||
var spacing = Uv.FromSize(ColumnSpacing, RowSpacing, isColumn);
|
||||
|
||||
var (lineU, lineV, lineShrink, lineGrow, lineAutoMargins) = (0.0, 0.0, 0.0, 0.0, 0);
|
||||
var (childIndex, firstChildIndex, itemIndex, lineIndex) = (0, 0, 0, 0);
|
||||
|
||||
var lines = new List<FlexLine>();
|
||||
children = children.Where(s_isVisible).OrderBy(s_getOrder).ToArray();
|
||||
|
||||
foreach (var element in children)
|
||||
{
|
||||
var basis = Flex.GetBasis(element);
|
||||
var flexConstraint = basis.Kind switch
|
||||
{
|
||||
FlexBasisKind.Auto => max.U,
|
||||
FlexBasisKind.Absolute => basis.Value,
|
||||
FlexBasisKind.Relative => max.U * basis.Value / 100,
|
||||
_ => throw new InvalidOperationException()
|
||||
};
|
||||
element.Measure(Uv.ToSize(max.WithU(flexConstraint), isColumn));
|
||||
|
||||
var size = Uv.FromSize(element.DesiredSize, isColumn);
|
||||
var flexLength = basis.Kind switch
|
||||
{
|
||||
FlexBasisKind.Auto => size.U,
|
||||
FlexBasisKind.Absolute or FlexBasisKind.Relative => Math.Max(size.U, flexConstraint),
|
||||
_ => throw new InvalidOperationException()
|
||||
};
|
||||
size = size.WithU(flexLength);
|
||||
Flex.SetBaseLength(element, flexLength);
|
||||
Flex.SetCurrentLength(element, flexLength);
|
||||
|
||||
if (Wrap != FlexWrap.NoWrap && lineU + size.U + itemIndex * spacing.U > max.U)
|
||||
{
|
||||
lines.Add(new FlexLine(firstChildIndex, childIndex - 1,
|
||||
lineU, lineV, lineShrink, lineGrow, lineAutoMargins));
|
||||
(lineU, lineV, lineShrink, lineGrow, lineAutoMargins) = (0.0, 0.0, 0.0, 0.0, 0);
|
||||
firstChildIndex = childIndex;
|
||||
itemIndex = 0;
|
||||
lineIndex++;
|
||||
}
|
||||
|
||||
lineU += size.U;
|
||||
lineV = Math.Max(lineV, size.V);
|
||||
lineShrink += Flex.GetShrink(element);
|
||||
lineGrow += Flex.GetGrow(element);
|
||||
lineAutoMargins += GetItemAutoMargins(element, isColumn);
|
||||
itemIndex++;
|
||||
childIndex++;
|
||||
}
|
||||
|
||||
if (itemIndex != 0)
|
||||
{
|
||||
lines.Add(new FlexLine(firstChildIndex, firstChildIndex + itemIndex - 1,
|
||||
lineU, lineV, lineShrink, lineGrow, lineAutoMargins));
|
||||
}
|
||||
|
||||
var state = new FlexLayoutState(children, lines, Wrap);
|
||||
|
||||
var totalSpacingV = (lines.Count - 1) * spacing.V;
|
||||
var panelSizeU = lines.Count > 0 ? lines.Max(line => line.U + (line.Count - 1) * spacing.U) : 0.0;
|
||||
|
||||
// Reizing along main axis using grow and shrink factors can affect cross axis, so remeasure affected items and lines.
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var (itemsCount, totalSpacingU, totalU, freeU) = GetLineMeasureU(line, max.U, spacing.U);
|
||||
var (lineMult, autoMargins, remainingFreeU) = GetLineMultInfo(line, freeU);
|
||||
if (lineMult != 0.0 && remainingFreeU != 0.0)
|
||||
{
|
||||
foreach (var element in state.GetLineItems(line))
|
||||
{
|
||||
var baseLength = Flex.GetBaseLength(element);
|
||||
var mult = GetItemMult(element, freeU);
|
||||
if (mult != 0.0)
|
||||
{
|
||||
var length = Math.Max(0.0, baseLength + remainingFreeU * mult / lineMult);
|
||||
element.Measure(Uv.ToSize(max.WithU(length), isColumn));
|
||||
}
|
||||
}
|
||||
|
||||
line.V = state.GetLineItems(line).Max(i => Uv.FromSize(i.DesiredSize, isColumn).V);
|
||||
}
|
||||
}
|
||||
|
||||
_state = state;
|
||||
var totalLineV = lines.Sum(l => l.V);
|
||||
var panelSize = lines.Count == 0 ? default : new Uv(panelSizeU, totalLineV + totalSpacingV);
|
||||
return Uv.ToSize(panelSize, isColumn);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
var state = _state ?? throw new InvalidOperationException();
|
||||
|
||||
var isColumn = Direction is FlexDirection.Column or FlexDirection.ColumnReverse;
|
||||
var isReverse = Direction is FlexDirection.RowReverse or FlexDirection.ColumnReverse;
|
||||
|
||||
var panelSize = Uv.FromSize(finalSize, isColumn);
|
||||
var spacing = Uv.FromSize(ColumnSpacing, RowSpacing, isColumn);
|
||||
|
||||
var linesCount = state.Lines.Count;
|
||||
var totalLineV = state.Lines.Sum(s => s.V);
|
||||
var totalSpacingV = (linesCount - 1) * spacing.V;
|
||||
var totalV = totalLineV + totalSpacingV;
|
||||
var freeV = panelSize.V - totalV;
|
||||
|
||||
var alignContent = freeV >= 0.0 ? AlignContent : AlignContent switch
|
||||
{
|
||||
AlignContent.FlexStart or AlignContent.Stretch or AlignContent.SpaceBetween => AlignContent.FlexStart,
|
||||
AlignContent.Center or AlignContent.SpaceAround or AlignContent.SpaceEvenly => AlignContent.Center,
|
||||
AlignContent.FlexEnd => AlignContent.FlexEnd,
|
||||
_ => throw new InvalidOperationException()
|
||||
};
|
||||
|
||||
var (spacingV, v) = alignContent switch
|
||||
{
|
||||
AlignContent.FlexStart => (spacing.V, 0.0),
|
||||
AlignContent.FlexEnd => (spacing.V, freeV),
|
||||
AlignContent.Center => (spacing.V, freeV / 2),
|
||||
AlignContent.Stretch => (spacing.V, 0.0),
|
||||
AlignContent.SpaceBetween => (spacing.V + freeV / (linesCount - 1), 0.0),
|
||||
AlignContent.SpaceAround => (spacing.V + freeV / linesCount, freeV / linesCount / 2),
|
||||
AlignContent.SpaceEvenly => (spacing.V + freeV / (linesCount + 1), freeV / (linesCount + 1)),
|
||||
_ => throw new InvalidOperationException()
|
||||
};
|
||||
|
||||
var scaleV = alignContent == AlignContent.Stretch ? (panelSize.V - totalSpacingV) / totalLineV : 1.0;
|
||||
|
||||
foreach (var line in state.Lines)
|
||||
{
|
||||
var lineV = scaleV * line.V;
|
||||
var (itemsCount, totalSpacingU, totalU, freeU) = GetLineMeasureU(line, panelSize.U, spacing.U);
|
||||
var (lineMult, lineAutoMargins, remainingFreeU) = GetLineMultInfo(line, freeU);
|
||||
|
||||
var currentFreeU = remainingFreeU;
|
||||
if (lineMult != 0.0 && remainingFreeU != 0.0)
|
||||
{
|
||||
foreach (var element in state.GetLineItems(line))
|
||||
{
|
||||
var baseLength = Flex.GetBaseLength(element);
|
||||
var mult = GetItemMult(element, freeU);
|
||||
if (mult != 0.0)
|
||||
{
|
||||
var length = Math.Max(0.0, baseLength + remainingFreeU * mult / lineMult);
|
||||
Flex.SetCurrentLength(element, length);
|
||||
currentFreeU -= length - baseLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
remainingFreeU = currentFreeU;
|
||||
|
||||
if (lineAutoMargins != 0 && remainingFreeU != 0.0)
|
||||
{
|
||||
foreach (var element in state.GetLineItems(line))
|
||||
{
|
||||
var baseLength = Flex.GetCurrentLength(element);
|
||||
var autoMargins = GetItemAutoMargins(element, isColumn);
|
||||
if (autoMargins != 0)
|
||||
{
|
||||
var length = Math.Max(0.0, baseLength + remainingFreeU * autoMargins / lineAutoMargins);
|
||||
Flex.SetCurrentLength(element, length);
|
||||
currentFreeU -= length - baseLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
remainingFreeU = currentFreeU;
|
||||
|
||||
var (spacingU, u) = line.Grow > 0 ? (spacing.U, 0.0) : JustifyContent switch
|
||||
{
|
||||
JustifyContent.FlexStart => (spacing.U, 0.0),
|
||||
JustifyContent.FlexEnd => (spacing.U, remainingFreeU),
|
||||
JustifyContent.Center => (spacing.U, remainingFreeU / 2),
|
||||
JustifyContent.SpaceBetween => (spacing.U + remainingFreeU / (itemsCount - 1), 0.0),
|
||||
JustifyContent.SpaceAround => (spacing.U + remainingFreeU / itemsCount, remainingFreeU / itemsCount / 2),
|
||||
JustifyContent.SpaceEvenly => (spacing.U + remainingFreeU / (itemsCount + 1), remainingFreeU / (itemsCount + 1)),
|
||||
_ => throw new InvalidOperationException()
|
||||
};
|
||||
|
||||
foreach (var element in state.GetLineItems(line))
|
||||
{
|
||||
var size = Uv.FromSize(element.DesiredSize, isColumn).WithU(Flex.GetCurrentLength(element));
|
||||
var align = Flex.GetAlignSelf(element) ?? AlignItems;
|
||||
|
||||
var positionV = align switch
|
||||
{
|
||||
AlignItems.FlexStart => v,
|
||||
AlignItems.FlexEnd => v + lineV - size.V,
|
||||
AlignItems.Center => v + (lineV - size.V) / 2,
|
||||
AlignItems.Stretch => v,
|
||||
_ => throw new InvalidOperationException()
|
||||
};
|
||||
|
||||
size = size.WithV(align == AlignItems.Stretch ? lineV : size.V);
|
||||
var position = new Uv(isReverse ? panelSize.U - size.U - u : u, positionV);
|
||||
element.Arrange(new Rect(Uv.ToPoint(position, isColumn), Uv.ToSize(size, isColumn)));
|
||||
|
||||
u += size.U + spacingU;
|
||||
}
|
||||
|
||||
v += lineV + spacingV;
|
||||
}
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
private static (int ItemsCount, double TotalSpacingU, double TotalU, double FreeU) GetLineMeasureU(
|
||||
FlexLine line, double panelSizeU, double spacingU)
|
||||
{
|
||||
var itemsCount = line.Count;
|
||||
var totalSpacingU = (itemsCount - 1) * spacingU;
|
||||
var totalU = line.U + totalSpacingU;
|
||||
var freeU = panelSizeU - totalU;
|
||||
return (itemsCount, totalSpacingU, totalU, freeU);
|
||||
}
|
||||
|
||||
private static (double LineMult, double LineAutoMargins, double RemainingFreeU) GetLineMultInfo(FlexLine line, double freeU)
|
||||
{
|
||||
var lineMult = freeU switch
|
||||
{
|
||||
< 0 => line.Shrink,
|
||||
> 0 => line.Grow,
|
||||
_ => 0.0,
|
||||
};
|
||||
// https://www.w3.org/TR/css-flexbox-1/#remaining-free-space
|
||||
// Sum of flex factors less than 1 reduces remaining free space to be distributed.
|
||||
return lineMult is > 0 and < 1
|
||||
? (lineMult, line.AutoMargins, freeU * lineMult)
|
||||
: (lineMult, line.AutoMargins, freeU);
|
||||
}
|
||||
|
||||
private static double GetItemMult(Layoutable element, double freeU)
|
||||
{
|
||||
var mult = freeU switch
|
||||
{
|
||||
< 0 => Flex.GetShrink(element),
|
||||
> 0 => Flex.GetGrow(element),
|
||||
_ => 0.0,
|
||||
};
|
||||
return mult;
|
||||
}
|
||||
|
||||
private static int GetItemAutoMargins(Layoutable element, bool isColumn)
|
||||
{
|
||||
return isColumn
|
||||
? element.VerticalAlignment switch
|
||||
{
|
||||
VerticalAlignment.Stretch => 0,
|
||||
VerticalAlignment.Top or VerticalAlignment.Bottom => 1,
|
||||
VerticalAlignment.Center => 2,
|
||||
_ => throw new InvalidOperationException()
|
||||
}
|
||||
: element.HorizontalAlignment switch
|
||||
{
|
||||
HorizontalAlignment.Stretch => 0,
|
||||
HorizontalAlignment.Left or HorizontalAlignment.Right => 1,
|
||||
HorizontalAlignment.Center => 2,
|
||||
_ => throw new InvalidOperationException()
|
||||
};
|
||||
}
|
||||
|
||||
private readonly struct FlexLayoutState
|
||||
{
|
||||
private readonly IReadOnlyList<Layoutable> _children;
|
||||
|
||||
public IReadOnlyList<FlexLine> Lines { get; }
|
||||
|
||||
public FlexLayoutState(IReadOnlyList<Layoutable> children, List<FlexLine> lines, FlexWrap wrap)
|
||||
{
|
||||
if (wrap == FlexWrap.WrapReverse)
|
||||
{
|
||||
lines.Reverse();
|
||||
}
|
||||
_children = children;
|
||||
Lines = lines;
|
||||
}
|
||||
|
||||
public IEnumerable<Layoutable> GetLineItems(FlexLine line)
|
||||
{
|
||||
for (var i = line.First; i <= line.Last; i++)
|
||||
yield return _children[i];
|
||||
}
|
||||
}
|
||||
|
||||
private class FlexLine
|
||||
{
|
||||
public FlexLine(int first, int last, double u, double v, double shrink, double grow, int autoMargins)
|
||||
{
|
||||
First = first;
|
||||
Last = last;
|
||||
U = u;
|
||||
V = v;
|
||||
Shrink = shrink;
|
||||
Grow = grow;
|
||||
AutoMargins = autoMargins;
|
||||
}
|
||||
|
||||
/// <summary>First item index.</summary>
|
||||
public int First { get; }
|
||||
|
||||
/// <summary>Last item index.</summary>
|
||||
public int Last { get; }
|
||||
|
||||
/// <summary>Sum of main sizes of items.</summary>
|
||||
public double U { get; }
|
||||
|
||||
/// <summary>Max of cross sizes of items.</summary>
|
||||
public double V { get; set; }
|
||||
|
||||
/// <summary>Sum of shrink factors of flexible items.</summary>
|
||||
public double Shrink { get; }
|
||||
|
||||
/// <summary>Sum of grow factors of flexible items.</summary>
|
||||
public double Grow { get; }
|
||||
|
||||
/// <summary>Number of "auto margins" along main axis.</summary>
|
||||
public int AutoMargins { get; }
|
||||
|
||||
/// <summary>Number of items.</summary>
|
||||
public int Count => Last - First + 1;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public enum FlexWrap
|
||||
{
|
||||
NoWrap,
|
||||
Wrap,
|
||||
WrapReverse
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public enum JustifyContent
|
||||
{
|
||||
FlexStart,
|
||||
FlexEnd,
|
||||
Center,
|
||||
SpaceBetween,
|
||||
SpaceAround,
|
||||
SpaceEvenly
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
internal readonly struct Uv(double u, double v)
|
||||
{
|
||||
public double U { get; } = u;
|
||||
|
||||
public double V { get; } = v;
|
||||
|
||||
public static Uv FromSize(double width, double height, bool swap) =>
|
||||
new Uv(swap ? height : width, swap ? width : height);
|
||||
|
||||
public static Uv FromSize(Size size, bool swap) =>
|
||||
FromSize(size.Width, size.Height, swap);
|
||||
|
||||
public static Point ToPoint(Uv uv, bool swap) =>
|
||||
new Point(swap ? uv.V : uv.U, swap ? uv.U : uv.V);
|
||||
|
||||
public static Size ToSize(Uv uv, bool swap) =>
|
||||
new Size(swap ? uv.V : uv.U, swap ? uv.U : uv.V);
|
||||
|
||||
public Uv WithU(double u) =>
|
||||
new Uv(u, V);
|
||||
|
||||
public Uv WithV(double v) =>
|
||||
new Uv(U, v);
|
||||
|
||||
public override string ToString() =>
|
||||
$"U: {U}, V: {V}";
|
||||
}
|
||||
@@ -126,7 +126,7 @@ public class OptionsDisplayItem : TemplatedControl
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
_layoutRoot = e.NameScope.Find<Border>("LayoutRoot");
|
||||
_layoutRoot = e.NameScope.Find<FABorder>("LayoutRoot");
|
||||
if (_layoutRoot != null)
|
||||
{
|
||||
_layoutRoot.PointerPressed += OnLayoutRootPointerPressed;
|
||||
@@ -172,5 +172,5 @@ public class OptionsDisplayItem : TemplatedControl
|
||||
|
||||
private bool _isPressed;
|
||||
private bool _isExpanded;
|
||||
private Border? _layoutRoot;
|
||||
private FABorder? _layoutRoot;
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
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,13 +62,14 @@
|
||||
Margin="0,0,0,5"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom">
|
||||
<ItemsControl Name="Swiper" IsVisible="False">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<ItemsRepeater Name="Swiper" IsVisible="False">
|
||||
<ItemsRepeater.Layout>
|
||||
<StackLayout
|
||||
DisableVirtualization="True"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<DataTemplate.DataType>
|
||||
<x:Type x:TypeArguments="x:Int32, x:String" TypeName="generic:KeyValuePair" />
|
||||
@@ -109,8 +110,8 @@
|
||||
</i:Interaction.Behaviors>-->
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</Panel>
|
||||
</Panel>
|
||||
</Border>
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace BD.WTTS.UI.Views.Controls
|
||||
/// Defines the <see cref="AutoScrollInterval"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<int> AutoScrollIntervalProperty =
|
||||
AvaloniaProperty.Register<CarouselBanner, int>(nameof(AutoScrollInterval), 6000);
|
||||
AvaloniaProperty.Register<CarouselBanner, int>(nameof(AutoScrollInterval), 8000);
|
||||
|
||||
/// <summary>
|
||||
/// Defines the Avalonia.Controls.ItemsControl.Items property.
|
||||
@@ -85,8 +85,8 @@ namespace BD.WTTS.UI.Views.Controls
|
||||
public CarouselBanner()
|
||||
{
|
||||
InitializeComponent();
|
||||
Left.Command = ReactiveCommand.Create(SwiperPrevious);
|
||||
Right.Command = ReactiveCommand.Create(SwiperNext);
|
||||
Left.Click += (s, e) => SwiperPrevious();
|
||||
Right.Click += (s, e) => SwiperNext();
|
||||
|
||||
//CarouselControl[!Carousel.Items] = this[!Items];
|
||||
CarouselControl[!Carousel.ItemsSourceProperty] = this[!ItemsSourceProperty];
|
||||
@@ -96,7 +96,7 @@ namespace BD.WTTS.UI.Views.Controls
|
||||
.Subscribe(_ => SwipersLoad());
|
||||
|
||||
CarouselControl.GetObservable(Carousel.SelectedIndexProperty)
|
||||
.Subscribe(_ => SwipersLoad());
|
||||
.Subscribe(x => SwipersLoad());
|
||||
|
||||
this.GetObservable(AutoScrollProperty)
|
||||
.Subscribe(x =>
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Layout;
|
||||
using FluentAvalonia.Core;
|
||||
using System.Reactive;
|
||||
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
public class CarouselItems : ItemsControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the <see cref="AutoScroll"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<bool> AutoScrollProperty =
|
||||
AvaloniaProperty.Register<CarouselItems, bool>(nameof(AutoScroll), true);
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="AutoScrollInterval"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<int> AutoScrollIntervalProperty =
|
||||
AvaloniaProperty.Register<CarouselItems, int>(nameof(AutoScrollInterval), 6000);
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="ItemsPerPage"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<int> ItemsPerPageProperty =
|
||||
AvaloniaProperty.Register<CarouselItems, int>(nameof(ItemsPerPage), 4);
|
||||
|
||||
/// <summary>
|
||||
/// AutoScroll
|
||||
/// </summary>
|
||||
public bool AutoScroll
|
||||
{
|
||||
get => GetValue(AutoScrollProperty);
|
||||
set => SetValue(AutoScrollProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自动播放间隔时间(单位毫秒)
|
||||
/// </summary>
|
||||
public int AutoScrollInterval
|
||||
{
|
||||
get => GetValue(AutoScrollIntervalProperty);
|
||||
set => SetValue(AutoScrollIntervalProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ItemsPerPage
|
||||
/// </summary>
|
||||
public int ItemsPerPage
|
||||
{
|
||||
get => GetValue(ItemsPerPageProperty);
|
||||
set => SetValue(ItemsPerPageProperty, value);
|
||||
}
|
||||
|
||||
Carousel? _carouselControl;
|
||||
Button? _leftButton;
|
||||
Button? _rightButton;
|
||||
ItemsControl? _swiper;
|
||||
Timer? _timer;
|
||||
|
||||
public ICommand? CarouselBannerIndexCommand { get; }
|
||||
|
||||
public CarouselItems()
|
||||
{
|
||||
CarouselBannerIndexCommand = ReactiveCommand.Create<int>(CarouselBannerIndex);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
_carouselControl = e.NameScope.Find<Carousel>("CarouselControl");
|
||||
_leftButton = e.NameScope.Find<Button>("Left");
|
||||
_rightButton = e.NameScope.Find<Button>("Right");
|
||||
_swiper = e.NameScope.Find<Avalonia.Controls.ItemsControl>("Swiper");
|
||||
|
||||
if (_leftButton != null)
|
||||
{
|
||||
_leftButton.Command = ReactiveCommand.Create(SwiperPrevious);
|
||||
}
|
||||
if (_rightButton != null)
|
||||
{
|
||||
_rightButton.Command = ReactiveCommand.Create(SwiperNext);
|
||||
}
|
||||
|
||||
if (_carouselControl != null)
|
||||
{
|
||||
_carouselControl.GetObservable(Carousel.ItemCountProperty)
|
||||
.Subscribe(_ => SwipersLoad());
|
||||
|
||||
_carouselControl.GetObservable(Carousel.SelectedIndexProperty)
|
||||
.Subscribe(_ => SwipersLoad());
|
||||
|
||||
RefreshItemsSource();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == ItemCountProperty)
|
||||
{
|
||||
RefreshItemsSource();
|
||||
}
|
||||
else if (change.Property == ItemsPerPageProperty)
|
||||
{
|
||||
RefreshItemsSource();
|
||||
}
|
||||
else if (change.Property == AutoScrollProperty)
|
||||
{
|
||||
var x = change.GetNewValue<bool>();
|
||||
if (x && _timer == null)
|
||||
{
|
||||
_timer = new Timer(_ =>
|
||||
{
|
||||
if (!this.IsPointerOver)
|
||||
{
|
||||
Dispatcher.UIThread.Post(SwiperNext, DispatcherPriority.Background);
|
||||
}
|
||||
}, nameof(AutoScroll), AutoScrollInterval, AutoScrollInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_timer != null)
|
||||
{
|
||||
_timer.Dispose();
|
||||
_timer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerEntered(PointerEventArgs e)
|
||||
{
|
||||
base.OnPointerEntered(e);
|
||||
|
||||
if (_swiper == null || _leftButton == null || _rightButton == null)
|
||||
return;
|
||||
|
||||
_leftButton.IsVisible = _rightButton.IsVisible = _swiper.IsVisible;
|
||||
}
|
||||
|
||||
protected override void OnPointerExited(PointerEventArgs e)
|
||||
{
|
||||
base.OnPointerExited(e);
|
||||
|
||||
if (_swiper == null || _leftButton == null || _rightButton == null)
|
||||
return;
|
||||
|
||||
_leftButton.IsVisible = _rightButton.IsVisible = false;
|
||||
}
|
||||
|
||||
void RefreshItemsSource()
|
||||
{
|
||||
if (_carouselControl != null)
|
||||
{
|
||||
var items = ItemsSource?.Batch(ItemsPerPage);
|
||||
_carouselControl.ItemsSource = items;
|
||||
}
|
||||
}
|
||||
|
||||
void CarouselBannerIndex(int index)
|
||||
{
|
||||
if (_carouselControl != null)
|
||||
_carouselControl.SelectedIndex = index;
|
||||
}
|
||||
|
||||
void SwipersLoad()
|
||||
{
|
||||
if (_carouselControl == null || _swiper == null || _leftButton == null || _rightButton == null)
|
||||
return;
|
||||
|
||||
if (_carouselControl.ItemCount <= 0)
|
||||
{
|
||||
_swiper.ItemsSource = null;
|
||||
return;
|
||||
}
|
||||
if (_carouselControl.ItemCount == 1)
|
||||
{
|
||||
_swiper.IsVisible = false;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
_swiper.IsVisible = true;
|
||||
var arr = new Dictionary<int, string>();
|
||||
for (var i = 0; i < _carouselControl.ItemCount; i++)
|
||||
{
|
||||
arr.Add(i, "#ADADAD");
|
||||
}
|
||||
var index = _carouselControl.SelectedIndex < 0 ? 0 : _carouselControl.SelectedIndex;
|
||||
arr[index] = "#FFFFFF";
|
||||
|
||||
_swiper.ItemsSource = arr;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 滑动到下一个
|
||||
/// </summary>
|
||||
public void SwiperNext()
|
||||
{
|
||||
if (_carouselControl == null || _carouselControl.ItemCount < 1)
|
||||
return;
|
||||
|
||||
if (_carouselControl.SelectedIndex < _carouselControl.ItemCount - 1)
|
||||
{
|
||||
_carouselControl.Next();
|
||||
}
|
||||
else
|
||||
{
|
||||
_carouselControl.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 滑动到上一个
|
||||
/// </summary>
|
||||
public void SwiperPrevious()
|
||||
{
|
||||
if (_carouselControl == null || _carouselControl.ItemCount < 1)
|
||||
return;
|
||||
|
||||
if (_carouselControl.SelectedIndex > 0)
|
||||
{
|
||||
_carouselControl.Previous();
|
||||
}
|
||||
else
|
||||
{
|
||||
_carouselControl.SelectedIndex = _carouselControl.ItemCount - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,50 +2,25 @@ using static System.Math;
|
||||
|
||||
namespace BD.WTTS.UI.Views.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// 固定的 WrapPanel
|
||||
/// </summary>
|
||||
public class FixedWrapPanel : Panel, INavigableContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the <see cref="ItemsPerLine"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<int> ItemsPerLineProperty =
|
||||
AvaloniaProperty.Register<FixedWrapPanel, int>(nameof(ItemsPerLine), 3);
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="Spacing"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<double> SpacingProperty =
|
||||
AvaloniaProperty.Register<FixedWrapPanel, double>(nameof(Spacing), 0);
|
||||
|
||||
static FixedWrapPanel()
|
||||
{
|
||||
AffectsMeasure<FixedWrapPanel>(ItemsPerLineProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ItemsPerLine
|
||||
/// </summary>
|
||||
public int ItemsPerLine
|
||||
public double ItemsPerLine
|
||||
{
|
||||
get => GetValue(ItemsPerLineProperty);
|
||||
set => SetValue(ItemsPerLineProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spacing
|
||||
/// </summary>
|
||||
public double Spacing
|
||||
{
|
||||
get => GetValue(SpacingProperty);
|
||||
set => SetValue(SpacingProperty, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IInputElement INavigableContainer.GetControl(NavigationDirection direction, IInputElement? from, bool wrap)
|
||||
{
|
||||
int index = from is Control control ? Children.IndexOf(control) : -1;
|
||||
int index = from is not null ? Children.IndexOf((Control)from) : -1;
|
||||
switch (direction)
|
||||
{
|
||||
case NavigationDirection.First:
|
||||
@@ -82,14 +57,13 @@ public class FixedWrapPanel : Panel, INavigableContainer
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Size MeasureOverride(Size constraint)
|
||||
{
|
||||
double itemWidth = (constraint.Width - (Spacing * (ItemsPerLine - 1))) / ItemsPerLine;
|
||||
double itemWidth = constraint.Width / ItemsPerLine;
|
||||
MutableSize currentLineSize = default;
|
||||
MutableSize panelSize = default;
|
||||
Size lineConstraint = new(constraint.Width, constraint.Height);
|
||||
Size childConstraint = new(itemWidth - Spacing, constraint.Height);
|
||||
Size childConstraint = new(itemWidth, constraint.Height);
|
||||
|
||||
for (int i = 0, count = Children.Count; i < count; i++)
|
||||
{
|
||||
@@ -102,7 +76,7 @@ public class FixedWrapPanel : Panel, INavigableContainer
|
||||
child.Measure(childConstraint);
|
||||
Size childSize = new(itemWidth, child.DesiredSize.Height);
|
||||
|
||||
if (MathUtilities.GreaterThan(currentLineSize.Width + childSize.Width + Spacing, lineConstraint.Width))
|
||||
if (MathUtilities.GreaterThan(currentLineSize.Width + childSize.Width, lineConstraint.Width))
|
||||
{
|
||||
// Need to switch to another line
|
||||
panelSize.Width = Max(currentLineSize.Width, panelSize.Width);
|
||||
@@ -112,25 +86,21 @@ public class FixedWrapPanel : Panel, INavigableContainer
|
||||
else
|
||||
{
|
||||
// Continue to accumulate a line
|
||||
currentLineSize.Width += childSize.Width + Spacing;
|
||||
currentLineSize.Width += childSize.Width;
|
||||
currentLineSize.Height = Max(childSize.Height, currentLineSize.Height);
|
||||
}
|
||||
}
|
||||
|
||||
// The last line size, if any should be added
|
||||
panelSize.Width = Max(currentLineSize.Width, panelSize.Width);
|
||||
panelSize.Height = currentLineSize.Height;
|
||||
|
||||
if (double.IsInfinity(panelSize.Width))
|
||||
panelSize.Width = 0;
|
||||
panelSize.Height += currentLineSize.Height;
|
||||
|
||||
return panelSize.ToSize();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
double itemWidth = (finalSize.Width - (Spacing * (ItemsPerLine - 1))) / ItemsPerLine;
|
||||
double itemWidth = finalSize.Width / ItemsPerLine;
|
||||
int firstInLine = 0;
|
||||
double accumulatedHeight = 0;
|
||||
var currentLineSize = default(MutableSize);
|
||||
@@ -169,7 +139,7 @@ public class FixedWrapPanel : Panel, INavigableContainer
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
void ArrangeLine(double y, double height, int start, int end, double width)
|
||||
private void ArrangeLine(double y, double height, int start, int end, double width)
|
||||
{
|
||||
double x = 0;
|
||||
for (int i = start; i < end; i++)
|
||||
@@ -180,20 +150,12 @@ public class FixedWrapPanel : Panel, INavigableContainer
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i < end - 1)
|
||||
{
|
||||
child.Arrange(new Rect(x, y, width - Spacing, height));
|
||||
x += width + Spacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
child.Arrange(new Rect(x, y, width, height));
|
||||
x += width;
|
||||
}
|
||||
child.Arrange(new Rect(x, y, width, height));
|
||||
x += width;
|
||||
}
|
||||
}
|
||||
|
||||
record struct MutableSize
|
||||
private struct MutableSize
|
||||
{
|
||||
internal MutableSize(double width, double height)
|
||||
{
|
||||
@@ -210,7 +172,7 @@ public class FixedWrapPanel : Panel, INavigableContainer
|
||||
internal double Width;
|
||||
internal double Height;
|
||||
|
||||
internal readonly Size ToSize()
|
||||
internal Size ToSize()
|
||||
{
|
||||
return new Size(Width, Height);
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
<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>
|
||||
@@ -1,63 +0,0 @@
|
||||
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,24 +139,20 @@
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||
Text="{Binding Path=Res.Link, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ItemsControl Margin="0,0,6,6" ItemsSource="{Binding Hyperlinks, Mode=OneTime}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<ItemsRepeater Margin="0,0,6,6" ItemsSource="{Binding Hyperlinks, Mode=OneTime}">
|
||||
<ItemsRepeater.Layout>
|
||||
<UniformGridLayout MinItemWidth="166" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate x:DataType="spp:HyperlinkModel">
|
||||
<Border MinWidth="166">
|
||||
<Button
|
||||
Command="{Binding Command, Mode=OneWay}"
|
||||
Content="{Binding Text, Mode=OneWay}"
|
||||
Cursor="Hand"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
</Border>
|
||||
<Button
|
||||
Command="{Binding Command, Mode=OneWay}"
|
||||
Content="{Binding Text, Mode=OneWay}"
|
||||
Cursor="Hand"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
<Border
|
||||
Height="1"
|
||||
Margin="-50,0"
|
||||
@@ -166,24 +162,20 @@
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||
Text="{Binding Path=Res.OpenSourceLibrary, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ItemsControl Margin="0,0,6,6" ItemsSource="{Binding OSL, Mode=OneTime}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<ItemsRepeater Margin="0,0,6,6" ItemsSource="{Binding OSL, Mode=OneTime}">
|
||||
<ItemsRepeater.Layout>
|
||||
<UniformGridLayout MinItemWidth="290" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate x:DataType="spp:HyperlinkModel">
|
||||
<Border MinWidth="290">
|
||||
<Button
|
||||
Command="{Binding Command, Mode=OneWay}"
|
||||
Content="{Binding Text, Mode=OneWay}"
|
||||
Cursor="Hand"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
</Border>
|
||||
<Button
|
||||
Command="{Binding Command, Mode=OneWay}"
|
||||
Content="{Binding Text, Mode=OneWay}"
|
||||
Cursor="Hand"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</StackPanel>
|
||||
</spp:OptionsDisplayItem.Content>
|
||||
</spp:OptionsDisplayItem>
|
||||
|
||||
@@ -8,8 +8,7 @@ public partial class AboutPage : ReactiveUserControl<AboutPageViewModel>
|
||||
public AboutPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new AboutPageViewModel();
|
||||
this.SetViewModel<AboutPageViewModel>();
|
||||
this.SetViewModel<AboutPageViewModel>(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
d:DesignWidth="800"
|
||||
x:CompileBindings="True"
|
||||
x:DataType="spp:DebugPageViewModel"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
mc:Ignorable="d">
|
||||
<Design.DataContext>
|
||||
<spp:DebugPageViewModel />
|
||||
@@ -22,7 +21,6 @@
|
||||
</spp:PageBase.PreviewImage>
|
||||
<spp:PageBase.TabContent>
|
||||
<TabStrip
|
||||
Name="TabSelect"
|
||||
Margin="4"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
@@ -112,91 +110,19 @@
|
||||
</DropDownButton>
|
||||
</StackPanel>
|
||||
</spp:PageBase.ActionContent>
|
||||
|
||||
<Carousel SelectedIndex="{Binding #TabSelect.SelectedIndex}">
|
||||
<Border Background="{DynamicResource CardBackgroundFillColorDefaultBrush}" CornerRadius="{DynamicResource ControlCornerRadius}">
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
<TextBox
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Classes="readonlybox"
|
||||
Text="{Binding DebugString}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBox
|
||||
Name="CommandTextBox"
|
||||
Grid.Row="1"
|
||||
Watermark="{Binding Path=Res.Debug_InstructionPlaceholder, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Panel>
|
||||
<TextBlock Text="Test Control" />
|
||||
<ItemsControl>
|
||||
<ItemsControl.Items>
|
||||
<Border Height="30" Background="Red" />
|
||||
<Border Background="Blue" />
|
||||
<Border Background="Yellow" />
|
||||
<Border Height="30" Background="Yellow" />
|
||||
<Border Background="Red" />
|
||||
<Border Background="Blue" />
|
||||
</ItemsControl.Items>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<spp:FixedWrapPanel ItemsPerLine="3" Spacing="5" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</Panel>
|
||||
|
||||
<Panel>
|
||||
<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>
|
||||
<Border Background="{DynamicResource CardBackgroundFillColorDefaultBrush}" CornerRadius="{DynamicResource ControlCornerRadius}">
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
<TextBox
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Classes="readonlybox"
|
||||
Text="{Binding DebugString}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBox
|
||||
Name="CommandTextBox"
|
||||
Grid.Row="1"
|
||||
Watermark="{Binding Path=Res.Debug_InstructionPlaceholder, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</spp:PageBase>
|
||||
|
||||
@@ -7,7 +7,7 @@ public partial class DebugPage : PageBase<DebugPageViewModel>
|
||||
public DebugPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.SetViewModel<DebugPageViewModel>();
|
||||
this.SetViewModel<DebugPageViewModel>(false);
|
||||
|
||||
CommandTextBox.KeyUp += (s, e) =>
|
||||
{
|
||||
|
||||
@@ -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 EnableCancelToken="False" Source="{Binding ImageUrl}" />
|
||||
<spp:Image2 Source="{Binding ImageUrl}" />
|
||||
</spp:AppItem.Image>
|
||||
</spp:AppItem>
|
||||
</DataTemplate>
|
||||
@@ -229,34 +229,31 @@
|
||||
DataContext="{Binding Articles[2]}" />
|
||||
</Grid>
|
||||
|
||||
<!--<spp:CarouselItems ItemsPerPage="3" ItemsSource="{Binding Articles}">
|
||||
<spp:CarouselItems.ItemTemplate>
|
||||
<DataTemplate x:DataType="spp:ArticleItemDTO">
|
||||
<spp:AppItem
|
||||
Title="{Binding Title}"
|
||||
Classes="Vertical Scale"
|
||||
ClickCommand="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
Cursor="Hand"
|
||||
Description="{Binding Introduction}"
|
||||
Tags="{Binding AuthorName}">
|
||||
<spp:AppItem.ClickCommandParameter>
|
||||
<MultiBinding Converter="{StaticResource StringFormatConverter}">
|
||||
<CompiledBinding Path="." Source="{x:Static spp:HomePageViewModel.OfficialWebsite_Article_Detail_}" />
|
||||
<CompiledBinding Path="Id" />
|
||||
</MultiBinding>
|
||||
</spp:AppItem.ClickCommandParameter>
|
||||
<spp:AppItem.Image>
|
||||
<spp:Image2 RenderOptions.BitmapInterpolationMode="HighQuality" Source="{Binding CoverUrl}" />
|
||||
</spp:AppItem.Image>
|
||||
<spp:AppItem.Status>
|
||||
<Border Classes="Status">
|
||||
<TextBlock Text="{Binding CreationTime, StringFormat={}{0:yyyy-MM-dd}}" />
|
||||
</Border>
|
||||
</spp:AppItem.Status>
|
||||
</spp:AppItem>
|
||||
</DataTemplate>
|
||||
</spp:CarouselItems.ItemTemplate>
|
||||
</spp:CarouselItems>-->
|
||||
<!--<ItemsControl ItemsSource="{Binding Articles}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Grid ColumnDefinitions="*,*,*" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="spp:ArticleItemDTO">
|
||||
<spp:AppItem
|
||||
Title="{Binding Title}"
|
||||
Classes="Vertical Scale"
|
||||
Description="{Binding Introduction}"
|
||||
Tags="{Binding AuthorName}">
|
||||
<spp:AppItem.Image>
|
||||
<spp:Image2 RenderOptions.BitmapInterpolationMode="HighQuality" Source="{Binding CoverUrl}" />
|
||||
</spp:AppItem.Image>
|
||||
<spp:AppItem.Status>
|
||||
<Border Classes="Status">
|
||||
<TextBlock Text="{Binding CreationTime, StringFormat={}{yyyy-MM-dd}}" />
|
||||
</Border>
|
||||
</spp:AppItem.Status>
|
||||
</spp:AppItem>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>-->
|
||||
|
||||
<DockPanel>
|
||||
<TextBlock
|
||||
@@ -273,71 +270,7 @@
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
</DockPanel>
|
||||
|
||||
<spp:CarouselItems
|
||||
MinHeight="250"
|
||||
ItemsPerPage="4"
|
||||
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
|
||||
EnableCancelToken="False"
|
||||
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}">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="#beee11"
|
||||
Text="{Binding DiscountValue, StringFormat={}-{0}%}" />
|
||||
</Border>
|
||||
</spp:AppItem.ActionButton>
|
||||
</spp:AppItem>
|
||||
<!--</Border>-->
|
||||
</DataTemplate>
|
||||
</spp:CarouselItems.ItemTemplate>
|
||||
</spp:CarouselItems>
|
||||
|
||||
<!--<spp:CarouselBanner
|
||||
<spp:CarouselBanner
|
||||
MinHeight="250"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
@@ -421,8 +354,7 @@
|
||||
ContentTemplate="{StaticResource ShopItem}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
-->
|
||||
<!--<DataTemplate>
|
||||
<!--<DataTemplate>
|
||||
<DataTemplate.DataType>
|
||||
<x:Type x:TypeArguments="spp:ShopRecommendGoodItem" TypeName="col:IEnumerable" />
|
||||
</DataTemplate.DataType>
|
||||
@@ -434,9 +366,8 @@
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</DataTemplate>-->
|
||||
<!--
|
||||
</spp:CarouselBanner.ItemTemplate>
|
||||
</spp:CarouselBanner>-->
|
||||
</spp:CarouselBanner>
|
||||
|
||||
<!--<ScrollViewer
|
||||
Name="ShopsScrollViewer"
|
||||
|
||||
@@ -7,7 +7,7 @@ public partial class HomePage : ReactiveUserControl<HomePageViewModel>
|
||||
public HomePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.SetViewModel<HomePageViewModel>(useCache: true);
|
||||
this.SetViewModel<HomePageViewModel>(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 42 0 0" />
|
||||
<Setter Property="Margin" Value="0 50 0 0" />
|
||||
</Style>
|
||||
<Style Selector="ui|NavigationView.AppNav[IsBackButtonVisible=True] SplitView /template/ ContentPresenter#PART_PanePresenter">
|
||||
<Setter Property="Margin" Value="0 2 0 0" />
|
||||
<Setter Property="Margin" Value="0 10 0 0" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|NavigationViewItem.AppNav">
|
||||
@@ -216,22 +216,9 @@
|
||||
|
||||
<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
|
||||
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 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>
|
||||
|
||||
</StackPanel>
|
||||
@@ -276,18 +263,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}}"
|
||||
@@ -331,7 +318,7 @@
|
||||
PaneDisplayMode="Left">
|
||||
<ui:NavigationView.Resources>
|
||||
<!-- Override this -->
|
||||
<Thickness x:Key="NavigationViewContentMargin">0,50,0,0</Thickness>
|
||||
<Thickness x:Key="NavigationViewContentMargin">0,60,0,0</Thickness>
|
||||
</ui:NavigationView.Resources>
|
||||
<ui:NavigationView.Styles>
|
||||
<Style Selector="Button#NavigationViewBackButton">
|
||||
@@ -342,7 +329,7 @@
|
||||
<Setter Property="Content" Value="" />
|
||||
</Style>
|
||||
<Style Selector="Grid#PaneToggleButtonGrid">
|
||||
<Setter Property="Margin" Value="5 0 0 0" />
|
||||
<Setter Property="Margin" Value="5 5 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>
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<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>
|
||||
@@ -1,92 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@@ -7,7 +7,7 @@ public partial class SettingsPage : PageBase<SettingsPageViewModel>
|
||||
public SettingsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.SetViewModel<SettingsPageViewModel>();
|
||||
this.SetViewModel<SettingsPageViewModel>(false);
|
||||
|
||||
//SettingsScrollTab.SelectionChanged += SettingsScrollTab_SelectionChanged;
|
||||
|
||||
|
||||
@@ -102,7 +102,6 @@
|
||||
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,23 +22,6 @@
|
||||
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}" />
|
||||
<HyperlinkButton
|
||||
<ui: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}" />
|
||||
</HyperlinkButton>
|
||||
</ui: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}" />
|
||||
<HyperlinkButton
|
||||
<ui: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}" />
|
||||
</HyperlinkButton>
|
||||
</ui:HyperlinkButton>
|
||||
<TextBlock Text="{Binding Path=Res.And, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<HyperlinkButton
|
||||
<ui: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}" />
|
||||
</HyperlinkButton>
|
||||
</ui:HyperlinkButton>
|
||||
</WrapPanel>
|
||||
|
||||
<StackPanel
|
||||
|
||||
@@ -34,7 +34,7 @@ public partial class LoginOrRegisterPage : ReactiveUserControl<LoginOrRegisterWi
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
this.SetViewModel<LoginOrRegisterWindowViewModel>();
|
||||
this.SetViewModel<LoginOrRegisterWindowViewModel>(false);
|
||||
|
||||
if (this.ViewModel != null)
|
||||
{
|
||||
@@ -42,20 +42,9 @@ public partial class LoginOrRegisterPage : ReactiveUserControl<LoginOrRegisterWi
|
||||
if (UserService.Current.IsAuthenticated)
|
||||
{
|
||||
Toast.Show(ToastIcon.Info, "当前已是登录状态");
|
||||
this.ViewModel.Close(false);
|
||||
this.ViewModel.Close();
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -65,8 +54,8 @@ public partial class LoginOrRegisterPage : ReactiveUserControl<LoginOrRegisterWi
|
||||
if (loginUrl != null)
|
||||
{
|
||||
//var token = loginUrl.TrimStart(Constants.UrlSchemes.Login);
|
||||
var token = loginUrl[Constants.UrlSchemes.Login.Length..];
|
||||
await ThirdPartyLoginHelper.LoginForStr(token);
|
||||
var token = loginUrl.Substring(Constants.UrlSchemes.Login.Length, loginUrl.Length - Constants.UrlSchemes.Login.Length);
|
||||
await ThirdPartyLoginHelper.OnMessageAsync(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,36 +37,7 @@ public sealed partial class MainWindow : ReactiveAppWindow<MainWindowViewModel>
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
if (Steamworks.SteamClient.IsValid)
|
||||
@@ -75,23 +46,24 @@ public sealed partial class MainWindow : ReactiveAppWindow<MainWindowViewModel>
|
||||
}
|
||||
if (AppSplashScreen.IsInitialized)
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +72,7 @@ public sealed class AppSplashScreen : IApplicationSplashScreen
|
||||
{
|
||||
public static bool IsInitialized = false;
|
||||
|
||||
//public WindowViewModel? ViewModel { get; }
|
||||
public WindowViewModel? ViewModel { get; }
|
||||
|
||||
public string? AppName { get; }
|
||||
|
||||
@@ -190,7 +162,7 @@ public sealed class AppSplashScreen : IApplicationSplashScreen
|
||||
});
|
||||
|
||||
AdvertiseService.Current.InitAdvertise();
|
||||
await NoticeService.Current.GetNewsAsync();
|
||||
NoticeService.Current.GetNewsAsync();
|
||||
|
||||
var mainWindow = App.Instance.MainWindow;
|
||||
mainWindow.ThrowIsNull();
|
||||
@@ -198,14 +170,13 @@ public sealed class AppSplashScreen : IApplicationSplashScreen
|
||||
#pragma warning disable SA1114 // Parameter list should follow declaration
|
||||
IViewModelManager.Instance.InitViewModels(new TabItemViewModel[]
|
||||
{
|
||||
new MenuTabItemViewModel("Welcome")
|
||||
{
|
||||
PageType = typeof(HomePage),
|
||||
IsResourceGet = true,
|
||||
IconKey = "avares://BD.WTTS.Client.Avalonia/UI/Assets/Icons/home.ico",
|
||||
},
|
||||
},
|
||||
ImmutableArray.Create<TabItemViewModel>(
|
||||
new MenuTabItemViewModel("Welcome")
|
||||
{
|
||||
PageType = typeof(HomePage),
|
||||
IsResourceGet = true,
|
||||
IconKey = "avares://BD.WTTS.Client.Avalonia/UI/Assets/Icons/home.ico",
|
||||
},
|
||||
}, ImmutableArray.Create<TabItemViewModel>(
|
||||
#if DEBUG
|
||||
new MenuTabItemViewModel("Debug")
|
||||
{
|
||||
@@ -216,7 +187,7 @@ public sealed class AppSplashScreen : IApplicationSplashScreen
|
||||
#endif
|
||||
new MenuTabItemViewModel("Plugin_Store")
|
||||
{
|
||||
PageType = typeof(PluginStorePage),
|
||||
PageType = null,
|
||||
IsResourceGet = true,
|
||||
IconKey = "avares://BD.WTTS.Client.Avalonia/UI/Assets/Icons/store.ico",
|
||||
},
|
||||
@@ -233,10 +204,8 @@ public sealed class AppSplashScreen : IApplicationSplashScreen
|
||||
{
|
||||
mainWindow.DataContext = IViewModelManager.Instance.MainWindow;
|
||||
s.InitSettingSubscribe();
|
||||
if (mainWindow is MainWindow mainWindow1)
|
||||
{
|
||||
mainWindow1.SetStartDefaultPageName();
|
||||
}
|
||||
|
||||
INavigationService.Instance.Navigate(typeof(HomePage));
|
||||
});
|
||||
#if STARTUP_WATCH_TRACE || DEBUG
|
||||
WatchTrace.Record("InitMainWindowViewModel");
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace BD;
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false)]
|
||||
public sealed class MobiusAttribute : Attribute
|
||||
{
|
||||
public MobiusAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MobiusAttribute(string str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool Obsolete { get; set; }
|
||||
}
|
||||
@@ -6,7 +6,6 @@ namespace BD.WTTS.Services;
|
||||
/// <summary>
|
||||
/// 子进程的 IPC 服务实现
|
||||
/// </summary>
|
||||
[Mobius(Obsolete = true)]
|
||||
public interface IPCSubProcessService : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
@@ -94,9 +93,6 @@ 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);
|
||||
@@ -123,34 +119,23 @@ public interface IPCSubProcessService : IDisposable
|
||||
return libraryName;
|
||||
}
|
||||
var libraryFileName = GetLibraryFileName(libraryName);
|
||||
string libraryPath = libraryName;
|
||||
try
|
||||
var libraryPath = Path.Combine(nativeLibraryPath, libraryFileName);
|
||||
if (File.Exists(libraryPath) &&
|
||||
NativeLibrary.TryLoad(libraryPath, out var handle))
|
||||
{
|
||||
foreach (var nativeLibraryPath in nativeLibraryPaths)
|
||||
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))
|
||||
{
|
||||
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 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,7 +123,6 @@ public static class KestrelServerOptionsExtensions
|
||||
var httpsPort = IReverseProxyConfig.HttpsPort;
|
||||
options.Listen(IReverseProxyService.Constants.Instance.ProxyIp, httpsPort, listen =>
|
||||
{
|
||||
listen.Protocols = HttpProtocols.Http1AndHttp2;
|
||||
listen.UseFlowAnalyze();
|
||||
listen.UseTls();
|
||||
});
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace BD;
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false)]
|
||||
public sealed class MobiusAttribute : Attribute
|
||||
{
|
||||
public MobiusAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MobiusAttribute(string str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool Obsolete { get; set; }
|
||||
}
|
||||
+1
-15
@@ -155,21 +155,7 @@ public static class CertGenerator
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
*/
|
||||
}
|
||||
builder.AddDnsName(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-32
@@ -450,36 +450,4 @@ 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,9 +46,4 @@ 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;
|
||||
|
||||
|
||||
+2
-29
@@ -80,15 +80,7 @@ sealed partial class HttpReverseProxyMiddleware
|
||||
return;
|
||||
}
|
||||
|
||||
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 destinationPrefix = GetDestinationPrefix(context.Request.Scheme, context.Request.Host, domainConfig.Destination);
|
||||
var httpClient = httpClientFactory.CreateHttpClient(context.Request.Host.Host, domainConfig);
|
||||
if (!string.IsNullOrEmpty(domainConfig.UserAgent))
|
||||
{
|
||||
@@ -97,19 +89,9 @@ sealed partial class HttpReverseProxyMiddleware
|
||||
|
||||
var forwarderRequestConfig = new ForwarderRequestConfig()
|
||||
{
|
||||
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,
|
||||
},
|
||||
Version = context.Request.Protocol.StartsWith("HTTP/2") ? System.Net.HttpVersion.Version20 : 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)
|
||||
@@ -411,15 +393,6 @@ 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;
|
||||
|
||||
+2
-3
@@ -89,8 +89,6 @@ abstract class ReverseProxyServiceImpl : IReverseProxySettings
|
||||
|
||||
public string? CustomDohAddres { get; set; }
|
||||
|
||||
public string? ServerSideProxyToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个随机的未使用的端口
|
||||
/// </summary>
|
||||
@@ -159,7 +157,7 @@ abstract class ReverseProxyServiceImpl : IReverseProxySettings
|
||||
return StartProxyResultCode.DeserializeReverseProxySettingsFail;
|
||||
}
|
||||
|
||||
// Linux 如果是443 需要验证 是否允许使用
|
||||
// Linux 如果是443 需要验证 是否允许使用
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(reverseProxySettings.ProxyIp))
|
||||
@@ -180,6 +178,7 @@ abstract class ReverseProxyServiceImpl : IReverseProxySettings
|
||||
|
||||
protected virtual void CheckRootCertificate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected abstract Task<StartProxyResult> StartProxyImpl();
|
||||
|
||||
-9
@@ -193,9 +193,6 @@ public interface ICertificateManager
|
||||
var isRootCertificateInstalled = IsCertificateInstalled();
|
||||
if (!isRootCertificateInstalled)
|
||||
{
|
||||
// 生成证书
|
||||
certificateManager.GenerateCertificate();
|
||||
|
||||
// 安装证书
|
||||
ICertificateManager.Constants.TrustRootCertificate(
|
||||
GetCerFilePath, platformService, certificate2);
|
||||
@@ -274,10 +271,4 @@ public interface ICertificateManager
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
bool? GenerateCertificate();
|
||||
|
||||
/// <summary>
|
||||
/// 获取证书信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
string GetCertificateInfo();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user