Compare commits

..
Author SHA1 Message Date
dependabot[bot] 12911cf5c4 Bump actions/setup-dotnet from 3 to 4
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 3 to 4.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 23:24:46 +00:00
36 changed files with 458 additions and 1112 deletions
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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
-189
View File
@@ -1,189 +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
#添加桌面文件
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" >"$HOME/Desktop/Watt Toolkit.desktop"
chmod +x "$HOME/Desktop/Watt Toolkit.desktop"
# update-desktop-database ~/.local/share/applications
#运行程序
Show_Run "下载安装完成,是否启动程序?"
exit 0
+2 -32
View File
@@ -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=zn_CN.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
@@ -126,12 +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>
</ItemGroup>
<Import Project="..\TFM_NETX_WITH_DESKTOP.props" />
</Project>
@@ -1,32 +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)
{
if (bucket == null)
bucket = new IEnumerable[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();
}
}
+2 -3
View File
@@ -44,8 +44,7 @@ public sealed partial class App : Application
AvaloniaXamlLoader.Load(this);
#if WINDOWS || LINUX || MACOS
//非主窗口不执行启动时最小化逻辑
if (GeneralSettings.MinimizeOnStartup.Value && MainWindow is MainWindow)
if (GeneralSettings.MinimizeOnStartup.Value)
Startup.Instance.IsMinimize = true;
if (Startup.Instance.IsSteamRun)
{
@@ -102,7 +101,7 @@ public sealed partial class App : Application
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)
@@ -13,9 +13,8 @@
<Thickness x:Key="PageMargin">10</Thickness>
<sys:Double x:Key="SettingsSpacing">3</sys:Double>
<sys:Char x:Key="PasswordChar">&#x25CF;</sys:Char>
<!--<sys:Char x:Key="PasswordChar">•</sys:Char>
<sys:Char x:Key="PasswordChar">·</sys:Char>-->
<!--<sys:Char x:Key="PasswordChar">&#x25CF;</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>
@@ -1,109 +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 />
</Border>
</Design.PreviewWith>
<Style Selector="spp|CarouselItems">
<Setter Property="Template">
<ControlTemplate>
<Border
BorderBrush="{DynamicResource CardStrokeColorDefaultBrush}"
BorderThickness="0"
ClipToBounds="True"
CornerRadius="8">
<Panel>
<Carousel
Name="CarouselControl"
Grid.Column="1"
Classes="AnimeSlide">
<Carousel.ItemTemplate>
<DataTemplate x:DataType="sys:Object">
<ItemsControl ItemTemplate="{TemplateBinding ItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<spp:FixedWrapPanel ItemsPerLine="{TemplateBinding ItemsPerPage}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
</Carousel.ItemTemplate>
</Carousel>
<Button
Name="Left"
HorizontalAlignment="Left"
Classes="action"
IsVisible="False"
Theme="{StaticResource TransparentButton}">
<ui:SymbolIcon FontSize="14" Symbol="ChevronLeft" />
</Button>
<Button
Name="Right"
HorizontalAlignment="Right"
Classes="action"
IsVisible="False"
Theme="{StaticResource TransparentButton}">
<ui:SymbolIcon FontSize="14" Symbol="ChevronRight" />
</Button>
<Panel
Height="10"
Margin="0,0,0,5"
HorizontalAlignment="Center"
VerticalAlignment="Bottom">
<ItemsRepeater Name="Swiper" IsVisible="False">
<ItemsRepeater.Layout>
<StackLayout
DisableVirtualization="True"
Orientation="Horizontal"
Spacing="8" />
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<DataTemplate.DataType>
<x:Type x:TypeArguments="x:Int32, x:String" TypeName="generic:KeyValuePair" />
</DataTemplate.DataType>
<Button
Padding="0"
Classes="Plain"
Command="{Binding CarouselBannerIndexCommand, RelativeSource={RelativeSource TemplatedParent}}"
CommandParameter="{Binding Key}">
<Ellipse
Name="IndexEllipse"
Width="10"
Height="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="{Binding Value}"
Opacity="0.6"
StrokeThickness="0" />
</Button>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</Panel>
</Panel>
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="spp|CarouselItems /template/ Button.action">
<Setter Property="Margin" Value="4" />
<Setter Property="Width" Value="36" />
<Setter Property="Height" Value="36" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Foreground" Value="White" />
</Style>
</Styles>
@@ -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.
@@ -1,92 +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);
}
private Carousel? _carouselControl;
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");
if (_carouselControl != null)
{
}
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
if (change.Property == ItemCountProperty)
{
if (_carouselControl != null)
{
ItemsSource?.Batch(ItemsPerPage);
}
}
base.OnPropertyChanged(change);
}
private void CarouselBannerIndex(int index)
{
if (_carouselControl != null)
_carouselControl.SelectedIndex = index;
}
}
@@ -7,26 +7,17 @@ public class FixedWrapPanel : Panel, INavigableContainer
public static readonly StyledProperty<int> ItemsPerLineProperty =
AvaloniaProperty.Register<FixedWrapPanel, int>(nameof(ItemsPerLine), 3);
public static readonly StyledProperty<double> SpacingProperty =
AvaloniaProperty.Register<FixedWrapPanel, double>(nameof(Spacing), 0);
static FixedWrapPanel()
{
AffectsMeasure<FixedWrapPanel>(ItemsPerLineProperty);
}
public int ItemsPerLine
public double ItemsPerLine
{
get => GetValue(ItemsPerLineProperty);
set => SetValue(ItemsPerLineProperty, value);
}
public double Spacing
{
get => GetValue(SpacingProperty);
set => SetValue(SpacingProperty, value);
}
IInputElement INavigableContainer.GetControl(NavigationDirection direction, IInputElement? from, bool wrap)
{
int index = from is not null ? Children.IndexOf((Control)from) : -1;
@@ -72,7 +63,7 @@ public class FixedWrapPanel : Panel, INavigableContainer
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++)
{
@@ -85,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);
@@ -95,7 +86,7 @@ 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);
}
}
@@ -159,8 +150,8 @@ public class FixedWrapPanel : Panel, INavigableContainer
continue;
}
child.Arrange(new Rect(x, y, width - Spacing, height));
x += width + Spacing;
child.Arrange(new Rect(x, y, width, height));
x += width;
}
}
@@ -21,7 +21,6 @@
</spp:PageBase.PreviewImage>
<spp:PageBase.TabContent>
<TabStrip
Name="TabSelect"
Margin="4"
HorizontalAlignment="Right"
VerticalAlignment="Top"
@@ -111,45 +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>
<TextBlock Text="Test Control" />
</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>
@@ -170,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")
{
@@ -11,7 +11,6 @@ sealed class AcceleratorAutoMapperProfile : Profile
.ForMember(x => x.Icon, d => d.MapFrom(x => x.IconUrl))
.ForMember(x => x.Description, d => d.MapFrom(x => x.Describe))
.ForMember(x => x.Enable, d => d.MapFrom(x => !x.Disable))
.ForMember(x => x.IsBuild, d => d.MapFrom(x => x.IsCompile))
.ForMember(x => x.Id, d => d.MapFrom(x => x.LocalId));
CreateMap<Script, ScriptDTO>()
.ForMember(x => x.LocalId, d => d.MapFrom(x => x.Id))
@@ -19,7 +18,6 @@ sealed class AcceleratorAutoMapperProfile : Profile
.ForMember(x => x.Describe, d => d.MapFrom(x => x.Description))
.ForMember(x => x.IconUrl, d => d.MapFrom(x => x.Icon))
.ForMember(x => x.Disable, d => d.MapFrom(x => !x.Enable))
.ForMember(x => x.IsCompile, d => d.MapFrom(x => x.IsBuild))
.ForMember(x => x.Id, d => d.MapFrom(x => x.Pid));
}
}
@@ -376,6 +376,20 @@ public sealed class ScriptManager : GeneralHttpClientFactory, IScriptManager
var scripts = list.ToList();
foreach (var item in list)
{
//检查缓存文件夹如果不是 IScriptManager.DirName_Build 替换成 IScriptManager.DirName_Build 开头
if (!item.CachePath.StartsWith($"{IScriptManager.DirName_Build}{Path.DirectorySeparatorChar}"))
{
item.CachePath = Path.Combine(IScriptManager.DirName_Build, item.FileName!);
var cachePath = Path.Combine(Plugin.Instance.CacheDirectory, item.CachePath);
if (File.Exists(cachePath))
{
File.Delete(cachePath);
}
await TryReadFileAsync(item, true);
//清理 脚本内容 后续 IPC 传递 插件进程读取。
item.Content = string.Empty;
await scriptRepository.SaveScriptCachePathAsync(item, default);
}
if (!CheckFile(item))
{
var temp = await DeleteScriptAsync(item);
@@ -390,38 +404,6 @@ public sealed class ScriptManager : GeneralHttpClientFactory, IScriptManager
//toast.Show($"脚本:{item.Name}_文件丢失,删除失败去尝试手动删除");
Toast.Show(ToastIcon.Error, Strings.Script_NoFileDeleteError_.Format(item.Name));
}
continue;
}
//检查缓存文件夹如果不是 IScriptManager.DirName_Build 替换成 IScriptManager.DirName_Build 开头
if (!item.CachePath.StartsWith($"{IScriptManager.DirName_Build}{Path.DirectorySeparatorChar}"))
{
var oldCachePath = Path.Combine(Plugin.Instance.CacheDirectory, item.CachePath);
item.CachePath = Path.Combine(IScriptManager.DirName_Build, item.FileName!);
if (File.Exists(oldCachePath))
{
File.Delete(oldCachePath);
}
await TryReadFileAsync(item, true);
//清理 脚本内容 后续 IPC 传递 插件进程读取。
item.Content = string.Empty;
await scriptRepository.SaveScriptCachePathAsync(item, default);
}
else
{
var cachePath = Path.Combine(Plugin.Instance.CacheDirectory, item.CachePath);
var file = new FileInfo(cachePath);
//检查缓存文件是否为空 为空则 刷新
if (file.Exists)
{
if (file.Length == 0)
{
file.Delete();
await TryReadFileAsync(item, true);
//清理 脚本内容 后续 IPC 传递 插件进程读取。
item.Content = string.Empty;
}
}
}
}
return scripts;
@@ -1,30 +0,0 @@
<UserControl
x:Class="BD.WTTS.UI.Views.Controls.GameAccelerator"
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="250"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid RowDefinitions="Auto,*">
<StackPanel
HorizontalAlignment="Right"
Orientation="Horizontal"
Spacing="5">
<AutoCompleteBox MinWidth="200" Watermark="搜索游戏" />
<Button Content="Left" />
<Button Content="Right" />
</StackPanel>
<ItemsControl Grid.Row="1">
<ItemsControl.ItemsPanel />
<ItemsControl.ItemTemplate>
<DataTemplate>
<spp:AppItem Title="aaa" Description="hhh" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
@@ -1,11 +0,0 @@
using Avalonia.Controls;
namespace BD.WTTS.UI.Views.Controls;
public partial class GameAccelerator : UserControl
{
public GameAccelerator()
{
InitializeComponent();
}
}
@@ -13,6 +13,8 @@
<Panel>
<lvc:CartesianChart
x:Name="Chart"
MinWidth="400"
MinHeight="160"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Transparent" />
@@ -1,12 +1,9 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Threading;
using Avalonia.VisualTree;
using LiveChartsCore;
using LiveChartsCore.Motion;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Avalonia;
using LiveChartsCore.SkiaSharpView.Drawing;
using SkiaSharp;
@@ -52,55 +49,39 @@ public partial class ProxyChartView : UserControl
}
};
private readonly ObservableCollection<RateTick> writes = new();
private readonly ObservableCollection<RateTick> reads = new();
//public ISeries[] Series { get; set; }
private readonly List<RateTick> writes = new();
private readonly List<RateTick> reads = new();
public Func<double, string> XFormatter { get; } = timestamp => ((long)timestamp).ToDateTimeS().ToString("HH:mm:ss");
public Func<double, string> YFormatter { get; } = value => $"{IOPath.GetDisplayFileSizeString(value)}/s";
CancellationTokenSource cancellation = new();
public static readonly AvaloniaProperty<IEnumerable<ISeries>> SeriesProperty =
AvaloniaProperty.Register<CartesianChart, IEnumerable<ISeries>>("Series", Enumerable.Empty<ISeries>(), inherits: true);
public ObservableCollection<ISeries> Series
{
get
{
return (ObservableCollection<ISeries>)GetValue(SeriesProperty);
}
set
{
SetValue(SeriesProperty, value);
}
}
public ProxyChartView()
{
InitializeComponent();
this.readSeries.Values = reads;
this.writeSeries.Values = writes;
Series = [readSeries, writeSeries];
if (Chart != null)
{
//Chart.UpdateFinished += Chart_UpdateFinished;
//Chart.Series = new ISeries[] { readSeries, writeSeries };
Chart[!CartesianChart.SeriesProperty] = this[!SeriesProperty];
Chart.Series = new ISeries[] { readSeries, writeSeries };
Chart.XAxes = new Axis[] { new Axis { Labeler = XFormatter } };
Chart.YAxes = new Axis[] { new Axis { Labeler = YFormatter, MinLimit = 0 } };
}
CancellationTokenSource? cancellation = null;
ProxyService.Current.WhenAnyValue(x => x.ProxyStatus)
.Subscribe(x =>
{
if (x)
{
cancellation = new CancellationTokenSource();
Task2.InBackground(FlushFlowChartAsync, true);
FlushFlowChartAsync(cancellation.Token);
}
else
{
@@ -115,7 +96,9 @@ public partial class ProxyChartView : UserControl
});
}
private struct RateTick
private static double GetTimestamp(DateTime dateTime) => dateTime.ToUnixTimeSeconds();
private class RateTick
{
public double Rate { get; }
@@ -128,18 +111,15 @@ public partial class ProxyChartView : UserControl
}
}
private void FlushFlowChartAsync()
private async void FlushFlowChartAsync(CancellationToken token)
{
while (!cancellation.IsCancellationRequested)
while (!token.IsCancellationRequested)
{
try
{
var flowStatistics = IReverseProxyService.Constants.Instance.GetFlowStatistics();
if (flowStatistics == null)
{
Thread.Sleep(1000);
continue;
}
var isAttachedToVisualTree = this.IsAttachedToVisualTree();
@@ -152,7 +132,7 @@ public partial class ProxyChartView : UserControl
});
}
var timestamp = DateTime.Now.ToUnixTimeSeconds();
var timestamp = GetTimestamp(DateTime.Now);
reads.Add(new RateTick(flowStatistics.ReadRate, timestamp));
writes.Add(new RateTick(flowStatistics.WriteRate, timestamp));
@@ -163,26 +143,24 @@ public partial class ProxyChartView : UserControl
this.writes.RemoveAt(0);
}
//if (Chart != null && isAttachedToVisualTree)
//{
// Dispatcher.UIThread.Post(() =>
// {
// Chart.Series = new ISeries[] { readSeries, writeSeries };
// });
//}
if (Chart != null && isAttachedToVisualTree)
Dispatcher.UIThread.Post(() =>
{
Chart.Series = new ISeries[] { readSeries, writeSeries };
});
}
catch
{
}
finally
{
Thread.Sleep(1000);
await Task.Delay(TimeSpan.FromSeconds(1d), CancellationToken.None);
}
}
}
////解决内存泄露问题
////https://github.com/beto-rodriguez/LiveCharts2/issues/1080#issuecomment-1601536016
//解决内存泄露问题
//https://github.com/beto-rodriguez/LiveCharts2/issues/1080#issuecomment-1601536016
//private static void Chart_UpdateFinished(LiveChartsCore.Kernel.Sketches.IChartView<SkiaSharpDrawingContext> chart)
//{
// // Chart library leaks PaintTasks
@@ -191,7 +169,7 @@ public partial class ProxyChartView : UserControl
// // Periodically clean up drawables, this may cause the chart to blip if the user mouses over it during this time
// if (chart.CoreCanvas.DrawablesCount > 50)
// {
// chart.CoreCanvas.SetPaintTasks([]);
// chart.CoreCanvas.SetPaintTasks(new HashSet<LiveChartsCore.Drawing.IPaint<SkiaSharpDrawingContext>>());
// }
// }
//}
@@ -106,6 +106,7 @@
DockPanel.Dock="Right"
IsHitTestVisible="False" />
<Button
Padding="8,4"
Command="{Binding RefreshCommand}"
@@ -288,7 +288,7 @@
<MenuFlyout>
<MenuItem
Command="{Binding CopyCode}"
Header="{Binding Path=Res.LocalAuth_Copy, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Header="{Binding Path=Res.Up, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
ToolTip.Tip="{Binding Path=Res.LocalAuth_Copy, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="Copy" />
@@ -223,17 +223,11 @@ public sealed partial class IdleCardPageViewModel : ViewModelBase
if (!SteamLoginState.Success)
{
LoginViewModel = new IdleSteamLoginPageViewModel(ref SteamLoginState);
LoginViewModel.Close += () =>
{
ViewState = 1;
IsLogin = SteamLoginState.Success;
};
ViewState = 0;
//var vm = new IdleSteamLoginPageViewModel(ref SteamLoginState);
//await IWindowManager.Instance.ShowTaskDialogAsync(vm, Strings.Steam_Login,
// pageContent: new IdleSteamLoginPage(), okButtonText: Strings.Confirm, isOkButton: false);
//IsLogin = SteamLoginState.Success;
var vm = new IdleSteamLoginPageViewModel(ref SteamLoginState);
await IWindowManager.Instance.ShowTaskDialogAsync(vm, Strings.Steam_Login,
pageContent: new IdleSteamLoginPage(), okButtonText: Strings.Confirm, isOkButton: false);
IsLogin = SteamLoginState.Success;
}
var sid = SteamConnectService.Current.CurrentSteamUser?.SteamId64;
@@ -68,12 +68,6 @@ public sealed partial class IdleCardPageViewModel
[Reactive]
public int TotalCardsRemaining { get; set; }
[Reactive]
public int ViewState { get; set; } = 1;
[Reactive]
public IdleSteamLoginPageViewModel? LoginViewModel { get; set; }
public int DropCardsCount => Math.Max(DroppedCardsCount - TotalCardsRemaining, 0);
[Reactive]
@@ -216,18 +216,16 @@
</StackPanel>
</spp:PageBase.PaneContent>
<Carousel Classes="AnimeSlide" SelectedIndex="{Binding ViewState}">
<spp:IdleSteamLoginPage DataContext="{Binding LoginViewModel}" />
<spp:ContentLoader CustomLoadingText="{Binding Path=Res.EnableAccelerationPrompt, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" IsLoading="{Binding IsLoaing}">
<!-- IsVisible="{Binding !IsLoaing}" -->
<Grid
ColumnDefinitions="*,240"
IsVisible="{Binding !IsLoaing}"
RowDefinitions="Auto,Auto,*">
<spp:OptionsDisplayItem Expands="True" IsExpanded="True">
<spp:OptionsDisplayItem.Header>
<!--<TextBlock>
<!--<Carousel Classes="AnimeSlide" SelectedIndex="0">-->
<spp:ContentLoader CustomLoadingText="{Binding Path=Res.EnableAccelerationPrompt, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" IsLoading="{Binding IsLoaing}">
<!-- IsVisible="{Binding !IsLoaing}" -->
<Grid
ColumnDefinitions="*,240"
IsVisible="{Binding !IsLoaing}"
RowDefinitions="Auto,Auto,*">
<spp:OptionsDisplayItem Expands="True" IsExpanded="True">
<spp:OptionsDisplayItem.Header>
<!--<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource VisibleStringConverter}">
<CompiledBinding
@@ -245,337 +243,337 @@
</MultiBinding>
</TextBlock.Text>
</TextBlock>-->
<TextBlock>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource VisibleStringConverter}">
<CompiledBinding Mode="OneWay" Path="IsLogin" />
<CompiledBinding Mode="OneWay" Path="UserIdleInfo.UserName" />
<CompiledBinding
Mode="OneWay"
Path="Res.Idle_NeedLoginSteam"
Source="{x:Static s:ResourceService.Current}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</spp:OptionsDisplayItem.Header>
<spp:OptionsDisplayItem.Description>
<Panel>
<TextBlock IsVisible="{Binding IsLogin}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource VisibleStringConverter}">
<CompiledBinding Mode="OneWay" Path="IsLogin" />
<CompiledBinding Mode="OneWay" Path="UserIdleInfo.UserName" />
<MultiBinding Converter="{StaticResource StringFormatConverter}">
<CompiledBinding
Mode="OneWay"
Path="Res.Idle_NeedLoginSteam"
Path="Res.SteamIdle_UserExpString_"
Source="{x:Static s:ResourceService.Current}" />
<CompiledBinding Mode="OneWay" Path="UserIdleInfo.UserLevel" />
<CompiledBinding Mode="OneWay" Path="UserIdleInfo.CurrentExp" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</spp:OptionsDisplayItem.Header>
<spp:OptionsDisplayItem.Description>
<Panel>
<TextBlock IsVisible="{Binding IsLogin}">
<TextBlock IsVisible="{Binding !IsLogin}" Text="{Binding Path=Res.SteamIdle_SteamClientUserTips, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</Panel>
</spp:OptionsDisplayItem.Description>
<spp:OptionsDisplayItem.Icon>
<spp:Image2
Width="64"
Height="64"
VerticalAlignment="Center"
DecodeWidth="64"
DockPanel.Dock="Top"
FallbackSource="avares://BD.WTTS.Client.Avalonia/UI/Assets/avatar.jpg"
Source="{Binding UserIdleInfo.AvatarUrl, Mode=OneWay}"
Stretch="UniformToFill">
<spp:Image2.Clip>
<EllipseGeometry Rect="0,0,64,64" />
</spp:Image2.Clip>
</spp:Image2>
</spp:OptionsDisplayItem.Icon>
<spp:OptionsDisplayItem.ActionButton>
<Button VerticalAlignment="Center" Command="{Binding LoginSteamCommand}">
<WrapPanel>
<ui:SymbolIcon Margin="0,0,5,0" Symbol="AddFriend" />
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource StringFormatConverter}">
<MultiBinding Converter="{StaticResource VisibleStringConverter}">
<CompiledBinding Mode="OneWay" Path="IsLogin" />
<CompiledBinding
Mode="OneWay"
Path="Res.SteamIdle_UserExpString_"
Path="Res.Logout"
Source="{x:Static s:ResourceService.Current}" />
<CompiledBinding
Mode="OneWay"
Path="Res.User_Login"
Source="{x:Static s:ResourceService.Current}" />
<CompiledBinding Mode="OneWay" Path="UserIdleInfo.UserLevel" />
<CompiledBinding Mode="OneWay" Path="UserIdleInfo.CurrentExp" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<TextBlock IsVisible="{Binding !IsLogin}" Text="{Binding Path=Res.SteamIdle_SteamClientUserTips, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</Panel>
</spp:OptionsDisplayItem.Description>
<spp:OptionsDisplayItem.Icon>
<spp:Image2
Width="64"
Height="64"
VerticalAlignment="Center"
DecodeWidth="64"
DockPanel.Dock="Top"
FallbackSource="avares://BD.WTTS.Client.Avalonia/UI/Assets/avatar.jpg"
Source="{Binding UserIdleInfo.AvatarUrl, Mode=OneWay}"
Stretch="UniformToFill">
<spp:Image2.Clip>
<EllipseGeometry Rect="0,0,64,64" />
</spp:Image2.Clip>
</spp:Image2>
</spp:OptionsDisplayItem.Icon>
<spp:OptionsDisplayItem.ActionButton>
<Button VerticalAlignment="Center" Command="{Binding LoginSteamCommand}">
<WrapPanel>
<ui:SymbolIcon Margin="0,0,5,0" Symbol="AddFriend" />
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource VisibleStringConverter}">
<CompiledBinding Mode="OneWay" Path="IsLogin" />
<CompiledBinding
Mode="OneWay"
Path="Res.Logout"
Source="{x:Static s:ResourceService.Current}" />
<CompiledBinding
Mode="OneWay"
Path="Res.User_Login"
Source="{x:Static s:ResourceService.Current}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</WrapPanel>
</Button>
</spp:OptionsDisplayItem.ActionButton>
<spp:OptionsDisplayItem.Content>
<StackPanel
Margin="24,0"
VerticalAlignment="Center"
Orientation="Vertical"
Spacing="6">
</WrapPanel>
</Button>
</spp:OptionsDisplayItem.ActionButton>
<spp:OptionsDisplayItem.Content>
<StackPanel
Margin="24,0"
VerticalAlignment="Center"
Orientation="Vertical"
Spacing="6">
<TextBlock
Margin="0,6,0,0"
FontWeight="SemiBold"
IsVisible="{Binding IsLogin}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource StringFormatConverter}">
<CompiledBinding
Mode="OneWay"
Path="Res.SteamIdle_UserNextExpString_"
Source="{x:Static s:ResourceService.Current}" />
<CompiledBinding Mode="OneWay" Path="UserIdleInfo.NextLevel" />
<CompiledBinding Mode="OneWay" Path="UserIdleInfo.UpExp" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<TextBlock
Margin="0,6,0,0"
FontWeight="SemiBold"
IsVisible="{Binding !IsLogin}"
Text="{Binding Source={x:Static s:ResourceService.Current}, Path=Res.Idle_NeedLoginSteam, Mode=OneWay}" />
<ProgressBar
Height="10"
Margin="0,0,0,6"
Classes="Material"
Maximum="100"
Value="{Binding UserIdleInfo.NextLevelExpPercentage}" />
<TextBlock
Margin="0,6,0,0"
FontWeight="SemiBold"
IsVisible="{Binding IsLogin}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource StringFormatConverter}">
<CompiledBinding
Mode="OneWay"
Path="Res.SteamIdle_UserNextExpString_"
Source="{x:Static s:ResourceService.Current}" />
<CompiledBinding Mode="OneWay" Path="UserIdleInfo.NextLevel" />
<CompiledBinding Mode="OneWay" Path="UserIdleInfo.UpExp" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<TextBlock
Margin="0,6,0,0"
FontWeight="SemiBold"
IsVisible="{Binding !IsLogin}"
Text="{Binding Source={x:Static s:ResourceService.Current}, Path=Res.Idle_NeedLoginSteam, Mode=OneWay}" />
<ProgressBar
Height="10"
Margin="0,0,0,6"
Classes="Material"
Maximum="100"
Value="{Binding UserIdleInfo.NextLevelExpPercentage}" />
<!--<Border
<!--<Border
Height="1"
Margin="-50,6"
Background="{DynamicResource ApplicationPageBackgroundThemeBrush}" />-->
<Panel>
<WrapPanel HorizontalAlignment="Left">
<TextBlock FontSize="36" Text="{Binding TotalCardsRemaining}" />
<TextBlock VerticalAlignment="Center" Text=" 张剩余卡牌掉落" />
</WrapPanel>
<WrapPanel HorizontalAlignment="Right">
<TextBlock VerticalAlignment="Center" Text="估算价值 ¥ " />
<TextBlock FontSize="36" Text="{Binding TotalCardsAvgPrice, StringFormat={}{0:0.00}}" />
</WrapPanel>
</Panel>
<Border
Height="1"
Margin="-50,6"
Background="{DynamicResource ApplicationPageBackgroundThemeBrush}" />
<StackPanel
Margin="0,6,0,0"
Orientation="Horizontal"
Spacing="5">
<TextBlock VerticalAlignment="Center" Text="当前 Steam 客户端登录账号:" />
<spp:Image2
Width="24"
Height="24"
Margin="0,0,5,0"
VerticalAlignment="Center"
DecodeWidth="36"
FallbackSource="avares://BD.WTTS.Client.Avalonia/UI/Assets/avatar.jpg"
Source="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser.AvatarMedium, Mode=OneWay}"
Stretch="Uniform">
<spp:Image2.Clip>
<EllipseGeometry Rect="0,0,24,24" />
</spp:Image2.Clip>
</spp:Image2>
<TextBlock VerticalAlignment="Center">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource VisibleStringConverter}">
<CompiledBinding
Mode="OneWay"
Path="IsConnectToSteam"
Source="{x:Static s:SteamConnectService.Current}" />
<CompiledBinding
Mode="OneWay"
Path="CurrentSteamUser.SteamNickName"
Source="{x:Static s:SteamConnectService.Current}" />
<CompiledBinding
Mode="OneWay"
Path="Res.SteamAppType_Unknown"
Source="{x:Static s:ResourceService.Current}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</StackPanel>
</spp:OptionsDisplayItem.Content>
</spp:OptionsDisplayItem>
<!-- Description="{Binding CurrentIdle.AppName}" -->
<spp:OptionsDisplayItem
Grid.Column="1"
Expands="True"
IsExpanded="True">
<spp:OptionsDisplayItem.Header>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource VisibleStringConverter}">
<CompiledBinding Mode="OneWay" Path="RunState" />
<CompiledBinding
Mode="OneWay"
Path="Res.SteamIdle_IdleRuning"
Source="{x:Static s:ResourceService.Current}" />
<CompiledBinding
Mode="OneWay"
Path="Res.SteamIdle_IdleNotRuning"
Source="{x:Static s:ResourceService.Current}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</spp:OptionsDisplayItem.Header>
<spp:OptionsDisplayItem.Description>
<Panel>
<TextBlock
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
IsVisible="{Binding !IsRunningSteamProcess, Source={x:Static s:SteamConnectService.Current}, Mode=OneWay}"
Text="{Binding Path=Res.SteamNotRuning, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBlock
Foreground="{DynamicResource SystemFillColorSuccessBrush}"
IsVisible="{Binding IsRunningSteamProcess, Source={x:Static s:SteamConnectService.Current}, Mode=OneWay}"
Text="{Binding Path=Res.SteamRuning, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<WrapPanel HorizontalAlignment="Left">
<TextBlock FontSize="36" Text="{Binding TotalCardsRemaining}" />
<TextBlock VerticalAlignment="Center" Text=" 张剩余卡牌掉落" />
</WrapPanel>
<WrapPanel HorizontalAlignment="Right">
<TextBlock VerticalAlignment="Center" Text="估算价值 ¥ " />
<TextBlock FontSize="36" Text="{Binding TotalCardsAvgPrice, StringFormat={}{0:0.00}}" />
</WrapPanel>
</Panel>
</spp:OptionsDisplayItem.Description>
<spp:OptionsDisplayItem.Icon>
<Panel
Width="6"
Height="6"
Margin="5,0,3,0">
<Ellipse Fill="#47A42B" IsVisible="{Binding RunState}" />
<Ellipse Fill="#FF4F58" IsVisible="{Binding !RunState}" />
</Panel>
</spp:OptionsDisplayItem.Icon>
<spp:OptionsDisplayItem.Content>
<Border
Height="1"
Margin="-50,6"
Background="{DynamicResource ApplicationPageBackgroundThemeBrush}" />
<StackPanel
Margin="24,0"
VerticalAlignment="Center"
Orientation="Vertical"
Spacing="6">
<Panel ToolTip.Tip="{Binding DropCardsCount, Mode=OneWay, Converter={StaticResource StringFormatConverter}, ConverterParameter=SteamIdle_DroppedCardsCountTip_}">
<Arc
Width="80"
Height="80"
StartAngle="0"
Stretch="None"
Stroke="{DynamicResource ControlStrokeColorSecondaryBrush}"
StrokeThickness="5"
SweepAngle="360" />
<ProgressBar
Width="80"
Height="80"
Classes="Circle"
Maximum="{Binding DroppedCardsCount}"
Value="{Binding TotalCardsRemaining}" />
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Path=IdleTime, Mode=OneWay, Converter={StaticResource StringFormatConverter}}" />
</Panel>
Margin="0,6,0,0"
Orientation="Horizontal"
Spacing="5">
<TextBlock VerticalAlignment="Center" Text="当前 Steam 客户端登录账号:" />
<spp:Image2
Width="24"
Height="24"
Margin="0,0,5,0"
VerticalAlignment="Center"
DecodeWidth="36"
FallbackSource="avares://BD.WTTS.Client.Avalonia/UI/Assets/avatar.jpg"
Source="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser.AvatarMedium, Mode=OneWay}"
Stretch="Uniform">
<spp:Image2.Clip>
<EllipseGeometry Rect="0,0,24,24" />
</spp:Image2.Clip>
</spp:Image2>
<TextBlock VerticalAlignment="Center">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource VisibleStringConverter}">
<CompiledBinding
Mode="OneWay"
Path="IsConnectToSteam"
Source="{x:Static s:SteamConnectService.Current}" />
<CompiledBinding
Mode="OneWay"
Path="CurrentSteamUser.SteamNickName"
Source="{x:Static s:SteamConnectService.Current}" />
<CompiledBinding
Mode="OneWay"
Path="Res.SteamAppType_Unknown"
Source="{x:Static s:ResourceService.Current}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</StackPanel>
</spp:OptionsDisplayItem.Content>
</spp:OptionsDisplayItem>
<WrapPanel HorizontalAlignment="Center">
<TextBlock VerticalAlignment="Center" Text="挂卡进度 " />
<TextBlock FontSize="22.6">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} / {1}">
<CompiledBinding Path="DropCardsCount" />
<CompiledBinding Path="DroppedCardsCount" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</WrapPanel>
<!-- Description="{Binding CurrentIdle.AppName}" -->
<spp:OptionsDisplayItem
Grid.Column="1"
Expands="True"
IsExpanded="True">
<spp:OptionsDisplayItem.Header>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource VisibleStringConverter}">
<CompiledBinding Mode="OneWay" Path="RunState" />
<CompiledBinding
Mode="OneWay"
Path="Res.SteamIdle_IdleRuning"
Source="{x:Static s:ResourceService.Current}" />
<CompiledBinding
Mode="OneWay"
Path="Res.SteamIdle_IdleNotRuning"
Source="{x:Static s:ResourceService.Current}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</spp:OptionsDisplayItem.Header>
<spp:OptionsDisplayItem.Description>
<Panel>
<TextBlock
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
IsVisible="{Binding !IsRunningSteamProcess, Source={x:Static s:SteamConnectService.Current}, Mode=OneWay}"
Text="{Binding Path=Res.SteamNotRuning, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBlock
Foreground="{DynamicResource SystemFillColorSuccessBrush}"
IsVisible="{Binding IsRunningSteamProcess, Source={x:Static s:SteamConnectService.Current}, Mode=OneWay}"
Text="{Binding Path=Res.SteamRuning, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</Panel>
</spp:OptionsDisplayItem.Description>
<spp:OptionsDisplayItem.Icon>
<Panel
Width="6"
Height="6"
Margin="5,0,3,0">
<Ellipse Fill="#47A42B" IsVisible="{Binding RunState}" />
<Ellipse Fill="#FF4F58" IsVisible="{Binding !RunState}" />
</Panel>
</spp:OptionsDisplayItem.Icon>
<spp:OptionsDisplayItem.Content>
<StackPanel
Margin="24,0"
VerticalAlignment="Center"
Orientation="Vertical"
Spacing="6">
<Panel ToolTip.Tip="{Binding DropCardsCount, Mode=OneWay, Converter={StaticResource StringFormatConverter}, ConverterParameter=SteamIdle_DroppedCardsCountTip_}">
<Arc
Width="80"
Height="80"
StartAngle="0"
Stretch="None"
Stroke="{DynamicResource ControlStrokeColorSecondaryBrush}"
StrokeThickness="5"
SweepAngle="360" />
<ProgressBar
Width="80"
Height="80"
Classes="Circle"
Maximum="{Binding DroppedCardsCount}"
Value="{Binding TotalCardsRemaining}" />
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Path=IdleTime, Mode=OneWay, Converter={StaticResource StringFormatConverter}}" />
</Panel>
<WrapPanel HorizontalAlignment="Center">
<TextBlock FontSize="24.8" Text="{Binding RuningCount, Mode=OneWay}" />
<TextBlock VerticalAlignment="Center" Text=" 个游戏正在运行" />
</WrapPanel>
<WrapPanel HorizontalAlignment="Center">
<TextBlock VerticalAlignment="Center" Text="挂卡进度 " />
<TextBlock FontSize="22.6">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} / {1}">
<CompiledBinding Path="DropCardsCount" />
<CompiledBinding Path="DroppedCardsCount" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</WrapPanel>
<!--<TextBlock
<WrapPanel HorizontalAlignment="Center">
<TextBlock FontSize="24.8" Text="{Binding RuningCount, Mode=OneWay}" />
<TextBlock VerticalAlignment="Center" Text=" 个游戏正在运行" />
</WrapPanel>
<!--<TextBlock
Grid.Row="2"
Grid.Column="1"
TextAlignment="Center">
<Run FontSize="22.6" Text="{Binding Badges.Count}" />
<Run Text=" 个徽章" />
</TextBlock>-->
</StackPanel>
</spp:OptionsDisplayItem.Content>
</spp:OptionsDisplayItem>
<spp:OptionsDisplayItem
Grid.Row="1"
Grid.ColumnSpan="2"
Description="{Binding IdleGameList.Count, Converter={StaticResource StringFormatConverter}, ConverterParameter=SteamIdle_RemainingGames_}"
Expands="True"
Header="挂卡游戏列表"
IsExpanded="True">
<spp:OptionsDisplayItem.Icon>
<ui:ImageIcon Source="{Binding Icon, Source={x:Static s:Plugin.Instance}, Mode=OneWay, Converter={StaticResource BitmapAssetValueConverter}}" />
</spp:OptionsDisplayItem.Icon>
<spp:OptionsDisplayItem.Content>
<Panel>
<StackPanel
Margin="0,30"
VerticalAlignment="Center"
Spacing="8">
<TextBlock
HorizontalAlignment="Center"
IsVisible="{Binding !IdleGameList.Count}"
Text="未获取到挂卡游戏数据" />
</StackPanel>
</spp:OptionsDisplayItem.Content>
</spp:OptionsDisplayItem>
<spp:OptionsDisplayItem
Grid.Row="1"
Grid.ColumnSpan="2"
Description="{Binding IdleGameList.Count, Converter={StaticResource StringFormatConverter}, ConverterParameter=SteamIdle_RemainingGames_}"
Expands="True"
Header="挂卡游戏列表"
IsExpanded="True">
<spp:OptionsDisplayItem.Icon>
<ui:ImageIcon Source="{Binding Icon, Source={x:Static s:Plugin.Instance}, Mode=OneWay, Converter={StaticResource BitmapAssetValueConverter}}" />
</spp:OptionsDisplayItem.Icon>
<spp:OptionsDisplayItem.Content>
<Panel>
<StackPanel
Margin="0,30"
VerticalAlignment="Center"
Spacing="8">
<TextBlock
HorizontalAlignment="Center"
IsVisible="{Binding !IdleGameList.Count}"
Text="未获取到挂卡游戏数据" />
</StackPanel>
<ItemsRepeater DockPanel.Dock="Bottom" ItemsSource="{Binding IdleGameList}">
<ItemsRepeater.Layout>
<UniformGridLayout
ItemsJustification="Start"
ItemsStretch="Uniform"
MinColumnSpacing="5"
MinItemHeight="160"
MinItemWidth="280"
MinRowSpacing="5" />
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="spp:IdleApp">
<spp:AppItem
Title="{Binding App.DisplayName}"
ContextFlyout="{StaticResource SharedMenuFlyout}"
Description="{Binding Tags}"
MoreFlyout="{StaticResource SharedMenuFlyout}"
Tags="{Binding AppId}">
<spp:AppItem.Status>
<Border Classes="Status">
<Panel>
<WrapPanel IsVisible="{Binding App.Process, Converter={StaticResource IsNullConverter}, ConverterParameter=invert, Mode=OneWay}">
<Ellipse
Width="6"
Height="6"
Margin="0,0,5,0"
Fill="#47A42B" />
<TextBlock
VerticalAlignment="Center"
FontSize="12"
Text="{Binding Path=Res.GameList_RunState, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</WrapPanel>
<WrapPanel IsVisible="{Binding App.Process, Converter={StaticResource IsNullConverter}, Mode=OneWay}">
<Ellipse
Width="6"
Height="6"
Margin="0,0,5,0"
Fill="#FF4F58" />
<TextBlock
VerticalAlignment="Center"
FontSize="12"
Text="{Binding Path=Res.GameList_StopState, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</WrapPanel>
</Panel>
</Border>
</spp:AppItem.Status>
<!--<spp:AppItem.ActionButton>
<ItemsRepeater DockPanel.Dock="Bottom" ItemsSource="{Binding IdleGameList}">
<ItemsRepeater.Layout>
<UniformGridLayout
ItemsJustification="Start"
ItemsStretch="Uniform"
MinColumnSpacing="5"
MinItemHeight="160"
MinItemWidth="280"
MinRowSpacing="5" />
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="spp:IdleApp">
<spp:AppItem
Title="{Binding App.DisplayName}"
ContextFlyout="{StaticResource SharedMenuFlyout}"
Description="{Binding Tags}"
MoreFlyout="{StaticResource SharedMenuFlyout}"
Tags="{Binding AppId}">
<spp:AppItem.Status>
<Border Classes="Status">
<Panel>
<WrapPanel IsVisible="{Binding App.Process, Converter={StaticResource IsNullConverter}, ConverterParameter=invert, Mode=OneWay}">
<Ellipse
Width="6"
Height="6"
Margin="0,0,5,0"
Fill="#47A42B" />
<TextBlock
VerticalAlignment="Center"
FontSize="12"
Text="{Binding Path=Res.GameList_RunState, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</WrapPanel>
<WrapPanel IsVisible="{Binding App.Process, Converter={StaticResource IsNullConverter}, Mode=OneWay}">
<Ellipse
Width="6"
Height="6"
Margin="0,0,5,0"
Fill="#FF4F58" />
<TextBlock
VerticalAlignment="Center"
FontSize="12"
Text="{Binding Path=Res.GameList_StopState, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</WrapPanel>
</Panel>
</Border>
</spp:AppItem.Status>
<!--<spp:AppItem.ActionButton>
<Button
Command="{Binding $parent[spp:PageBase].((spp:IdleAppsPageViewModel)DataContext).DeleteButtonCommand}"
CommandParameter="{Binding}"
@@ -588,9 +586,9 @@
</Viewbox>
</Button>
</spp:AppItem.ActionButton>-->
<spp:AppItem.Image>
<Panel x:Name="ItemImage">
<!--<i:Interaction.Behaviors>
<spp:AppItem.Image>
<Panel x:Name="ItemImage">
<!--<i:Interaction.Behaviors>
<ia:EventTriggerBehavior EventName="PointerEntered" SourceObject="{Binding #ItemImage}">
<ia:ChangePropertyAction
PropertyName="IsVisible"
@@ -604,50 +602,50 @@
Value="False" />
</ia:EventTriggerBehavior>
</i:Interaction.Behaviors>-->
<Panel MinWidth="{Binding $parent[spp:AppItem].MinWidth}" MaxWidth="{Binding $parent[spp:AppItem].MaxWidth}">
<spp:Image2
Name="AppImage"
DecodeWidth="120"
FallbackSource="avares://BD.WTTS.Client.Plugins.GameList/UI/Assets/defaultappimage.png"
RenderOptions.BitmapInterpolationMode="HighQuality"
Source="{Binding App.LibraryGridStream^}"
Stretch="UniformToFill" />
<TextBlock
Margin="8,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
IsVisible="{Binding #AppImage.IsFailed}"
Text="{Binding App.DisplayName}"
TextAlignment="Center"
TextWrapping="WrapWithOverflow"
Theme="{StaticResource BodyStrongTextBlockStyle}" />
<Panel MinWidth="{Binding $parent[spp:AppItem].MinWidth}" MaxWidth="{Binding $parent[spp:AppItem].MaxWidth}">
<spp:Image2
Name="AppImage"
DecodeWidth="120"
FallbackSource="avares://BD.WTTS.Client.Plugins.GameList/UI/Assets/defaultappimage.png"
RenderOptions.BitmapInterpolationMode="HighQuality"
Source="{Binding App.LibraryGridStream^}"
Stretch="UniformToFill" />
<TextBlock
Margin="8,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
IsVisible="{Binding #AppImage.IsFailed}"
Text="{Binding App.DisplayName}"
TextAlignment="Center"
TextWrapping="WrapWithOverflow"
Theme="{StaticResource BodyStrongTextBlockStyle}" />
<Border
Margin="10,0,10,-3"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Background="{DynamicResource SolidBackgroundFillColorBaseBrush}"
CornerRadius="3"
IsVisible="{Binding App.IsInstalled}">
<DockPanel Margin="10,3" HorizontalAlignment="Center">
<TextBlock
Margin="0,0,5,0"
VerticalAlignment="Center"
FontSize="11"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
IsVisible="{Binding App.InstalledDrive, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}"
Text="{Binding App.InstalledDrive}" />
<TextBlock
VerticalAlignment="Center"
FontSize="11"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
Text="{Binding App.SizeOnDisk, Converter={StaticResource StringFormatConverter}, ConverterParameter=size}"
TextWrapping="Wrap" />
</DockPanel>
</Border>
</Panel>
<!--<Panel
<Border
Margin="10,0,10,-3"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Background="{DynamicResource SolidBackgroundFillColorBaseBrush}"
CornerRadius="3"
IsVisible="{Binding App.IsInstalled}">
<DockPanel Margin="10,3" HorizontalAlignment="Center">
<TextBlock
Margin="0,0,5,0"
VerticalAlignment="Center"
FontSize="11"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
IsVisible="{Binding App.InstalledDrive, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}"
Text="{Binding App.InstalledDrive}" />
<TextBlock
VerticalAlignment="Center"
FontSize="11"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
Text="{Binding App.SizeOnDisk, Converter={StaticResource StringFormatConverter}, ConverterParameter=size}"
TextWrapping="Wrap" />
</DockPanel>
</Border>
</Panel>
<!--<Panel
x:Name="ItemBox"
Background="{DynamicResource SolidBackgroundFillColorBaseBrush}"
IsVisible="False"
@@ -694,16 +692,18 @@
</Viewbox>
</Button>
</Panel>-->
</Panel>
</spp:AppItem.Image>
</spp:AppItem>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</Panel>
</spp:OptionsDisplayItem.Content>
</spp:OptionsDisplayItem>
</Grid>
</spp:ContentLoader>
</Carousel>
</Panel>
</spp:AppItem.Image>
</spp:AppItem>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</Panel>
</spp:OptionsDisplayItem.Content>
</spp:OptionsDisplayItem>
</Grid>
</spp:ContentLoader>
<!--<spp:IdleSteamLoginPage />-->
<!--</Carousel>-->
</spp:PageBase>
@@ -154,7 +154,6 @@ public static class ThirdPartyLoginHelper
AppResources.User_Register);
close?.Invoke();
Toast.Show(ToastIcon.Success, msg);
await UserService.Current.RefreshShopTokenAsync();
}
static IDisposable? serverDisposable;
+1 -18
View File
@@ -65,24 +65,10 @@ public static class Migrations
{
MoveAccelerator();
}
//var v_3_0_rc4 = new Version(3, 0, 407);
//if (IApplication.IsDesktop() && PreviousVersion < v_3_0_rc4)
//{
// ClearScriptFile();
//}
}
}
}
static void ClearScriptFile()
{
var scriptDirectory = Path.Combine(IOPath.AppDataDirectory, AssemblyInfo.Plugins, AssemblyInfo.Accelerator, DirName_Scripts);
Directory.Delete(scriptDirectory, true);
var scriptCacheDirectory = Path.Combine(IOPath.CacheDirectory, AssemblyInfo.Plugins, AssemblyInfo.Accelerator, DirName_BuildScripts);
Directory.Delete(scriptCacheDirectory, true);
}
static void MoveDirByScripts(string rootPath, string? newDirName = null)
{
try
@@ -91,14 +77,11 @@ public static class Migrations
AssemblyInfo.Plugins,
AssemblyInfo.Accelerator,
newDirName ?? DirName_Scripts);
var dir = new DirectoryInfo(newPath);
if (!dir.Exists)
if (!Directory.Exists(newPath))
{
var oldPath = Path.Combine(rootPath, DirName_Scripts);
if (Directory.Exists(oldPath))
{
//创建至父级目录
dir.Parent?.Create();
Directory.Move(oldPath, newPath);
}
}
@@ -61,16 +61,6 @@ sealed class MicroServiceClient : MicroServiceClientBase
}
}
public sealed override async Task SaveShopAuthTokenAsync(JWTEntity authToken)
{
var user = await userManager.GetCurrentUserAsync();
if (user != null)
{
user.ShopAuthToken = authToken;
await userManager.SetCurrentUserAsync(user);
}
}
public sealed override async Task OnLoginedAsync(
IReadOnlyPhoneNumber? phoneNumber,
ILoginResponse response)
@@ -199,39 +199,6 @@ public sealed class UserService : ReactiveObject
await RefreshUserAsync(user, refreshCurrentUser);
}
public async Task RefreshShopTokenAsync(bool refreshToken = true)
{
var currentUser = await userManager.GetCurrentUserAsync();
if (refreshToken && currentUser != null)
{
var token = await csc.Shop.GetShopUserTokenAsync();
if (token.IsSuccess)
{
currentUser.ShopAuthToken = token.Content;
await userManager.SetCurrentUserAsync(currentUser);
}
}
}
/// <summary>
/// 带登录状态跳转 Url
/// </summary>
/// <param name="url">跳转地址</param>
/// <returns></returns>
public async Task OpenAuthUrl(string url)
{
var token = await userManager.GetAuthTokenAsync();
if (token == null)
{
Browser2.Open(url.ToString());
}
else
{
Browser2.Open(string.Format(Constants.Urls.OfficialWebsite_Fast_Login_, token.AccessToken, HttpUtility.UrlEncode(token.ExpiresIn.ToString()), HttpUtility.UrlEncode(url)));
}
}
public async Task RefreshUserAvatarAsync()
{
if (User != null)
@@ -86,9 +86,6 @@ public sealed partial class DebugPageViewModel : TabItemViewModel
break;
case "updatetray":
break;
case "gc":
GC.Collect();
break;
case "login":
if (cmds.Length > 1)
@@ -45,7 +45,6 @@ public partial class LoginOrRegisterWindowViewModel : WindowViewModel, SendSmsUI
var msg = Strings.Success_.Format((rsp?.IsLoginOrRegister ?? false) ? Strings.User_Login : Strings.User_Register);
close?.Invoke();
Toast.Show(ToastIcon.Success, msg);
await UserService.Current.RefreshShopTokenAsync();
}
async Task SendSmsAsync() => await this.SendSmsAsync(() => new()