Compare commits

..

2 Commits

Author SHA1 Message Date
yingpanwang 2bd7276f6a 🚧 测试请求指定网页连接 2024-08-16 11:20:06 +08:00
wangyingpan 62fb8038be 🚧 网络环境检测服务 2024-07-26 14:45:01 +08:00
114 changed files with 1612 additions and 4713 deletions
+1 -1
View File
@@ -16,7 +16,7 @@
[![NET 7.0](https://img.shields.io/badge/dotnet-7.0-purple.svg?style=flat-square&color=512bd4)](https://learn.microsoft.com/zh-cn/dotnet/core/whats-new/dotnet-7)
[![C# 11](https://img.shields.io/badge/c%23-11-brightgreen.svg?style=flat-square&color=6da86a)](https://learn.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-11)
[![爱发电](https://img.shields.io/badge/爱发电-软妹币玩家-blue.svg?style=flat-square&color=ea4aaa&logo=github-sponsors)](https://afdian.com/@rmbgame)
[![爱发电](https://img.shields.io/badge/爱发电-软妹币玩家-blue.svg?style=flat-square&color=ea4aaa&logo=github-sponsors)](https://afdian.net/@rmbgame)
[![Kofi](https://img.shields.io/badge/Kofi-RMBGAME-orange.svg?style=flat-square&logo=kofi)](https://ko-fi.com/rmbgame)
[![Patreon](https://img.shields.io/badge/Patreon-RMBGAME-red.svg?style=flat-square&logo=patreon)](https://www.patreon.com/rmbgame)
-9
View File
@@ -988,15 +988,6 @@
"Summary": "加速页面 Tab 选项卡选中下标",
"IsRegionOrEndregion": null,
"IsValueType": null
},
{
"TypeName": "bool",
"PropertyName": "AutoShowWattAcceleratorWindow",
"DefaultValue": "true",
"DefaultValueIsConst": true,
"Summary": "加速后自动唤起 Watt 加速器界面",
"IsRegionOrEndregion": null,
"IsValueType": null
}
],
"Usings": ""
-5
View File
@@ -1,5 +0,0 @@
<Project>
<PropertyGroup>
<CheckEolWorkloads>false</CheckEolWorkloads>
</PropertyGroup>
</Project>
BIN
View File
Binary file not shown.
-11
View File
@@ -1,11 +0,0 @@
static void WinDivert()
{
var dllWinDivert = Path.Combine(ProjectUtils.ProjPath, "ref", "WinDivert.dll");
var sysWinDivert64 = Path.Combine(ProjectUtils.ProjPath, "ref", "WinDivert64.sys");
byte[][] data = [File.ReadAllBytes(dllWinDivert), File.ReadAllBytes(sysWinDivert64)];
var bytes = MemoryPackSerializer.Serialize(data);
bytes.AsSpan().Reverse();
File.WriteAllBytes(Path.Combine(ProjectUtils.ProjPath, "ref", "WinDivert.mpo"), bytes);
}
+2 -2
View File
@@ -16,14 +16,14 @@ public static partial class AssemblyInfo
/// <summary>
/// 预览版本号,范围 1~9,只增不减
/// </summary>
const string ver_for_preview = "9";
const string ver_for_preview = "8";
/// <summary>
/// RC 版本号,范围 0~9,只增不减
/// </summary>
const string ver_for_rc = "9";
public const string FileVersion = $"{Version2}.{ver_for_rc}1{ver_for_preview}.0";
public const string FileVersion = $"{Version2}.{ver_for_rc}0{ver_for_preview}.0";
//public const string InformationalVersion = Version;
//public const string InformationalVersion = $"{Version}-preview.{ver_for_preview}";
@@ -7,7 +7,6 @@
<DelaySign>false</DelaySign>
<AssemblyOriginatorKeyFile>$(MSBuildProjectDirectory)\..\..\avalonia.snk</AssemblyOriginatorKeyFile>
<!--https://github.com/AvaloniaUI/Avalonia/blob/0.10.10/build/SharedVersion.props#L18-->
<AvaloniaAccessUnstablePrivateApis>true</AvaloniaAccessUnstablePrivateApis>
</PropertyGroup>
<ItemGroup>
@@ -91,6 +91,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BD.Common.XmlnsDefinition.Avalonia">
<Aliases>BD_Common_XmlnsDefinition_Avalonia</Aliases>
</PackageReference>
<ProjectReference Include="..\BD.WTTS.Client.Avalonia\BD.WTTS.Client.Avalonia.csproj" />
<ProjectReference Include="..\BD.WTTS.Client\BD.WTTS.Client.csproj" />
</ItemGroup>
@@ -68,6 +68,9 @@
<ItemGroup>
<PackageReference Include="Moq" />
<PackageReference Include="BD.Common.XmlnsDefinition.Avalonia">
<Aliases>BD_Common_XmlnsDefinition_Avalonia</Aliases>
</PackageReference>
<ProjectReference Include="..\BD.WTTS.Client.Avalonia\BD.WTTS.Client.Avalonia.csproj" />
<ProjectReference Include="..\BD.WTTS.Client.Plugins.Accelerator\BD.WTTS.Client.Plugins.Accelerator.csproj" />
<ProjectReference Include="..\BD.WTTS.Client.Plugins.ArchiSteamFarmPlus\BD.WTTS.Client.Plugins.ArchiSteamFarmPlus.csproj" />
@@ -4,7 +4,6 @@
<RootNamespace>BD.WTTS</RootNamespace>
<DefineConstants>AVALONIA;$(DefineConstants)</DefineConstants>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<AvaloniaAccessUnstablePrivateApis>true</AvaloniaAccessUnstablePrivateApis>
</PropertyGroup>
<ItemGroup>
@@ -73,6 +72,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BD.Common.XmlnsDefinition.Avalonia">
<Aliases>BD_Common_XmlnsDefinition_Avalonia</Aliases>
</PackageReference>
<PackageReference Include="BD.Common" />
<PackageReference Include="BD.Common.Primitives" />
<PackageReference Include="BD.Common.Essentials" />
@@ -1,203 +0,0 @@
using Avalonia.Reactive;
using Avalonia.Xaml.Interactions.Responsive;
using Avalonia.Xaml.Interactivity;
namespace BD.WTTS.Behaviors;
/// <summary>
/// Observes <see cref="Behavior{T}.AssociatedObject"/> control or <see cref="SourceControl"/> control <see cref="Visual.Bounds"/> property changes and if triggered sets or removes style classes when conditions from <see cref="AdaptiveClassSetter"/> are met.
/// </summary>
public class AdaptiveBehavior : Behavior<Control>
{
private IDisposable? _disposable;
private AvaloniaList<AdaptiveClassSetter>? _setters;
/// <summary>
/// Identifies the <seealso cref="SourceControl"/> avalonia property.
/// </summary>
public static readonly StyledProperty<Control?> SourceControlProperty =
AvaloniaProperty.Register<AdaptiveBehavior, Control?>(nameof(SourceControl));
/// <summary>
/// Identifies the <seealso cref="TargetControl"/> avalonia property.
/// </summary>
public static readonly StyledProperty<Control?> TargetControlProperty =
AvaloniaProperty.Register<AdaptiveBehavior, Control?>(nameof(TargetControl));
/// <summary>
/// Identifies the <seealso cref="Setters"/> avalonia property.
/// </summary>
public static readonly DirectProperty<AdaptiveBehavior, AvaloniaList<AdaptiveClassSetter>> SettersProperty =
AvaloniaProperty.RegisterDirect<AdaptiveBehavior, AvaloniaList<AdaptiveClassSetter>>(nameof(Setters), t => t.Setters);
/// <summary>
/// Gets or sets the the source control that <see cref="Visual.BoundsProperty"/> property are observed from, if not set <see cref="Behavior{T}.AssociatedObject"/> is used. This is a avalonia property.
/// </summary>
[ResolveByName]
public Control? SourceControl
{
get => GetValue(SourceControlProperty);
set => SetValue(SourceControlProperty, value);
}
/// <summary>
/// Gets or sets the target control that class name that should be added or removed when triggered, if not set <see cref="Behavior{T}.AssociatedObject"/> is used or <see cref="AdaptiveClassSetter.TargetControl"/> from <see cref="AdaptiveClassSetter"/>. This is a avalonia property.
/// </summary>
[ResolveByName]
public Control? TargetControl
{
get => GetValue(TargetControlProperty);
set => SetValue(TargetControlProperty, value);
}
/// <summary>
/// Gets adaptive class setters collection. This is a avalonia property.
/// </summary>
[Content]
public AvaloniaList<AdaptiveClassSetter> Setters => _setters ??= new AvaloniaList<AdaptiveClassSetter>();
/// <inheritdoc/>
protected override void OnAttachedToVisualTree()
{
base.OnAttachedToVisualTree();
StopObserving();
StartObserving();
}
/// <inheritdoc/>
protected override void OnDetachedFromVisualTree()
{
base.OnDetachedFromVisualTree();
StopObserving();
}
private void StartObserving()
{
var sourceControl = GetValue(SourceControlProperty) is not null
? SourceControl
: AssociatedObject;
if (sourceControl is not null)
{
_disposable = ObserveBounds(sourceControl);
}
}
private void StopObserving()
{
_disposable?.Dispose();
}
private IDisposable ObserveBounds(Control sourceControl)
{
if (sourceControl is null)
{
throw new ArgumentNullException(nameof(sourceControl));
}
return sourceControl.GetObservable(Visual.BoundsProperty)
.Subscribe(new AnonymousObserver<Rect>(bounds => ValueChanged(sourceControl, Setters, bounds)));
}
private void ValueChanged(Control? sourceControl, AvaloniaList<AdaptiveClassSetter>? setters, Rect bounds)
{
if (sourceControl is null || setters is null)
{
return;
}
foreach (var setter in setters)
{
var isMinOrMaxWidthSet = setter.IsSet(AdaptiveClassSetter.MinWidthProperty)
|| setter.IsSet(AdaptiveClassSetter.MaxWidthProperty);
var widthConditionTriggered = GetResult(setter.MinWidthOperator, bounds.Width, setter.MinWidth)
&& GetResult(setter.MaxWidthOperator, bounds.Width, setter.MaxWidth);
var isMinOrMaxHeightSet = setter.IsSet(AdaptiveClassSetter.MinHeightProperty)
|| setter.IsSet(AdaptiveClassSetter.MaxHeightProperty);
var heightConditionTriggered = GetResult(setter.MinHeightOperator, bounds.Height, setter.MinHeight)
&& GetResult(setter.MaxHeightOperator, bounds.Height, setter.MaxHeight);
var isAddClassTriggered = isMinOrMaxWidthSet switch
{
true when !isMinOrMaxHeightSet => widthConditionTriggered,
false when isMinOrMaxHeightSet => heightConditionTriggered,
true when isMinOrMaxHeightSet => widthConditionTriggered && heightConditionTriggered,
_ => false
};
var targetControl = setter.GetValue(AdaptiveClassSetter.TargetControlProperty) is not null
? setter.TargetControl
: GetValue(TargetControlProperty) is not null
? TargetControl
: AssociatedObject;
if (targetControl is not null)
{
var className = setter.ClassName;
var isPseudoClass = setter.IsPseudoClass;
if (isAddClassTriggered)
{
Add(targetControl, className, isPseudoClass);
}
else
{
Remove(targetControl, className, isPseudoClass);
}
}
}
}
private bool GetResult(ComparisonConditionType comparisonConditionType, double property, double value)
{
return comparisonConditionType switch
{
// ReSharper disable once CompareOfFloatsByEqualityOperator
ComparisonConditionType.Equal => property == value,
// ReSharper disable once CompareOfFloatsByEqualityOperator
ComparisonConditionType.NotEqual => property != value,
ComparisonConditionType.LessThan => property < value,
ComparisonConditionType.LessThanOrEqual => property <= value,
ComparisonConditionType.GreaterThan => property > value,
ComparisonConditionType.GreaterThanOrEqual => property >= value,
_ => throw new ArgumentOutOfRangeException()
};
}
private static void Add(Control targetControl, string? className, bool isPseudoClass)
{
if (className is null || string.IsNullOrEmpty(className) || targetControl.Classes.Contains(className))
{
return;
}
if (isPseudoClass)
{
((IPseudoClasses)targetControl.Classes).Add(className);
}
else
{
targetControl.Classes.Add(className);
}
}
private static void Remove(Control targetControl, string? className, bool isPseudoClass)
{
if (className is null || string.IsNullOrEmpty(className) || !targetControl.Classes.Contains(className))
{
return;
}
if (isPseudoClass)
{
((IPseudoClasses)targetControl.Classes).Remove(className);
}
else
{
targetControl.Classes.Remove(className);
}
}
}
@@ -11,7 +11,6 @@
[assembly: XmlnsDefinition("https://steampp.net/ui", "BD.WTTS.UI.Views.Windows")]
[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.Behaviors")]
[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")]
@@ -95,7 +95,7 @@ public sealed class AvaloniaWindowManagerImpl : IWindowManagerImpl
Func<bool>? cancelCloseAction = null,
bool disableScroll = false)
where TPageViewModel : ViewModelBase
{
{
var td = new TaskDialogEx
{
Title = title,
@@ -111,12 +111,6 @@ public sealed class AvaloniaWindowManagerImpl : IWindowManagerImpl
XamlRoot = GetWindowTopLevel(),
};
if (td.XamlRoot == null)
{
Toast.LogAndShowT(new Exception("在 AppWindow 为 Null 时,无法弹出 Taskdialog."));
return false;
}
if (viewModel != null)
{
if (viewModel is IWindowViewModel window)
@@ -9,11 +9,6 @@
<StackPanel Spacing="10">
<HyperlinkButton Content="更新日志" />
<Button Content="更新日志" Theme="{StaticResource HyperlinkButton}" />
<Button Classes="TransparentAccent" Content="更新日志" />
<Button
Classes="TransparentAccent"
Content="更新日志"
IsEnabled="False" />
<Button
Content="更新日志"
IsEnabled="False"
@@ -226,15 +221,6 @@
<Setter Property="Background" Value="Transparent" />
</Style>
<Style Selector="Button.TransparentAccent /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource HyperlinkButtonForeground}" />
</Style>
<Style Selector="Button.TransparentAccent:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource HyperlinkButtonForegroundPointerOver}" />
</Style>
<Style Selector="Button.TransparentAccent:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource HyperlinkButtonForegroundPressed}" />
</Style>
</Styles>
@@ -97,7 +97,7 @@
</Design.PreviewWith>
<Styles.Resources>
<Thickness x:Key="AppPageMargin">20,10,20,20</Thickness>
<Thickness x:Key="AppPageMargin">20</Thickness>
</Styles.Resources>
<Style Selector="spp|PageBase">
@@ -313,7 +313,7 @@
<Setter Property="Grid.Row" Value="2" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Margin" Value="0 12 0 0" />
<Setter Property="Margin" Value="0 12" />
</Style>
<Style Selector="^ /template/ Panel#PageDetails">
@@ -86,10 +86,4 @@
<StreamGeometry x:Key="Phone">
M15.75 2C16.9926 2 18 3.00736 18 4.25V19.75C18 20.9926 16.9926 22 15.75 22H8.25C7.00736 22 6 20.9926 6 19.75V4.25C6 3.00736 7.00736 2 8.25 2H15.75ZM13.25 18H10.75C10.3358 18 10 18.3358 10 18.75C10 19.1642 10.3358 19.5 10.75 19.5H13.25C13.6642 19.5 14 19.1642 14 18.75C14 18.3358 13.6642 18 13.25 18Z
</StreamGeometry>
<StreamGeometry x:Key="GOGGalaxy">
M304.99296 650.144H185.98496a17.12 17.12 0 0 0-16.992 17.184v85.344c0 8.992 7.68 16.992 16.992 16.992h119.52v56.32H156.16096a43.84 43.84 0 0 1-43.488-44v-144.512c0-23.968 19.68-43.488 44-43.488h148.32z m43.168-157.824c0 24.832-20 44.832-44.832 44.832H112.19296v-57.696h161.312a16.896 16.896 0 0 0 17.024-16.992V272.64a17.024 17.024 0 0 0-17.024-17.184H187.36096a17.152 17.152 0 0 0-17.536 17.184v86.144c0 9.856 7.68 17.024 17.024 17.024H256.00096v57.632H157.02496a44.544 44.544 0 0 1-44.832-44.32V242.304c0-24.352 20.192-44.32 44.832-44.32H303.04096c24.672 0 44.64 19.968 44.64 44.32v249.984z m563.168 333.664h-56.32v-175.84h-39.68a17.12 17.12 0 0 0-16.992 17.184v158.624h-56.832v-175.84h-39.68a17.12 17.12 0 0 0-16.992 17.184v158.624h-56.832v-188.512c0-23.968 19.68-43.488 44-43.488h239.328z m0.512-333.664c0 24.832-20.192 44.832-44.832 44.832h-191.136v-57.696h161.312a16.96 16.96 0 0 0 17.024-16.992V272.64a17.12 17.12 0 0 0-17.024-17.184h-86.656a17.024 17.024 0 0 0-17.024 17.184v86.144c0 9.856 7.68 17.024 17.024 17.024h69.152v57.632h-98.688a44.352 44.352 0 0 1-44.64-44.32V242.304c0-24.352 19.968-44.32 44.64-44.32h146.336c24.832 0 44.832 19.968 44.832 44.32v249.984zM585.34496 198.016h-146.688c-24.832 0-44.512 19.968-44.512 44.32v146.816a44.16 44.16 0 0 0 44.512 44.32h146.688a44.48 44.48 0 0 0 44.512-44.32V242.336c0-24.352-20.192-44.32-44.512-44.32z m-12.672 74.656v86.144c0 9.504-7.68 17.024-17.152 17.024h-86.688a16.96 16.96 0 0 1-16.992-17.024V272.96c0-9.312 7.328-16.992 16.992-16.992h85.856c9.824 0 16.992 7.68 16.992 16.992z m-33.824 321.344h-144.672c-24.16 0-43.808 19.488-43.808 43.488v144.512c0 24.32 19.68 44 43.808 44h144.672c24.32 0 44-19.68 44-44v-144.512c0-23.968-19.68-43.488-44-43.488z m-12.864 73.344v85.344a16.96 16.96 0 0 1-16.992 16.992v-0.352h-84.864a17.12 17.12 0 0 1-17.152-17.152v-84.832a17.28 17.28 0 0 1 17.152-17.184h85.344c9.344 0 17.024 7.84 17.024 17.184z m476.16-620.352A74.24 74.24 0 0 0 949.31296 24.64H74.65696A74.304 74.304 0 0 0 0.00096 99.296v825.344a74.304 74.304 0 0 0 74.656 74.656h874.656a74.304 74.304 0 0 0 74.656-74.656V99.296c0-20.32-8.48-39.168-21.856-52.832z m0 877.664a52.416 52.416 0 0 1-52.832 52.832H74.65696a52.576 52.576 0 0 1-53.344-52.832V99.328a52.672 52.672 0 0 1 52.832-52.832H948.80096c29.344 0 52.992 23.68 52.992 52.832v825.344z
</StreamGeometry>
<StreamGeometry x:Key="Discord">
M1049.062 139.672a3 3 0 0 0-1.528-1.4A970.13 970.13 0 0 0 808.162 64.06a3.632 3.632 0 0 0-3.846 1.82 674.922 674.922 0 0 0-29.8 61.2 895.696 895.696 0 0 0-268.852 0 619.082 619.082 0 0 0-30.27-61.2 3.78 3.78 0 0 0-3.848-1.82 967.378 967.378 0 0 0-239.376 74.214 3.424 3.424 0 0 0-1.576 1.352C78.136 367.302 36.372 589.38 56.86 808.708a4.032 4.032 0 0 0 1.53 2.75 975.332 975.332 0 0 0 293.65 148.378 3.8 3.8 0 0 0 4.126-1.352A696.4 696.4 0 0 0 416.24 860.8a3.72 3.72 0 0 0-2.038-5.176 642.346 642.346 0 0 1-91.736-43.706 3.77 3.77 0 0 1-0.37-6.252 502.094 502.094 0 0 0 18.218-14.274 3.638 3.638 0 0 1 3.8-0.512c192.458 87.834 400.82 87.834 591 0a3.624 3.624 0 0 1 3.848 0.466 469.066 469.066 0 0 0 18.264 14.32 3.768 3.768 0 0 1-0.324 6.252 602.814 602.814 0 0 1-91.78 43.66 3.75 3.75 0 0 0-2 5.222 782.11 782.11 0 0 0 60.028 97.63 3.728 3.728 0 0 0 4.126 1.4A972.096 972.096 0 0 0 1221.4 811.458a3.764 3.764 0 0 0 1.53-2.704c24.528-253.566-41.064-473.824-173.868-669.082zM444.982 675.16c-57.944 0-105.688-53.174-105.688-118.478s46.818-118.482 105.688-118.482c59.33 0 106.612 53.64 105.686 118.478 0 65.308-46.82 118.482-105.686 118.482z m390.76 0c-57.942 0-105.686-53.174-105.686-118.478s46.818-118.482 105.686-118.482c59.334 0 106.614 53.64 105.688 118.478 0 65.308-46.354 118.482-105.688 118.482z
</StreamGeometry>
</ResourceDictionary>
@@ -193,39 +193,4 @@ public class SnackbarManager : TemplatedControl, IManagedNotificationManager
PseudoClasses.Set(":bottomleft", position == NotificationPosition.BottomLeft);
PseudoClasses.Set(":bottomright", position == NotificationPosition.BottomRight);
}
/// <inheritdoc/>
public void Close(INotification notification)
{
Dispatcher.UIThread.VerifyAccess();
//if (_items.Remove(notification, out var notificationCard))
//{
// notificationCard.Close();
//}
}
/// <inheritdoc/>
public void Close(object content)
{
Dispatcher.UIThread.VerifyAccess();
//if (_items.Remove(content, out var notificationCard))
//{
// notificationCard.Close();
//}
}
/// <inheritdoc/>
public void CloseAll()
{
Dispatcher.UIThread.VerifyAccess();
//foreach (var kvp in _items)
//{
// kvp.Close();
//}
_items?.Clear();
}
}
@@ -85,36 +85,44 @@ public class FixedWrapPanel : Panel, INavigableContainer
/// <inheritdoc/>
protected override Size MeasureOverride(Size constraint)
{
var panelSize = default(MutableSize);
var lineSize = default(MutableSize);
int itemsInCurrentLine = 0;
double itemWidth = (constraint.Width - (Spacing * (ItemsPerLine - 1))) / ItemsPerLine;
MutableSize currentLineSize = default;
MutableSize panelSize = default;
Size lineConstraint = new(constraint.Width, constraint.Height);
Size childConstraint = new(itemWidth - Spacing, constraint.Height);
foreach (var child in Children.OfType<Control>())
for (int i = 0, count = Children.Count; i < count; i++)
{
child.Measure(new Size(itemWidth, constraint.Height));
var childSize = child.DesiredSize;
if (itemsInCurrentLine == ItemsPerLine)
Control child = Children[i];
if (child is null)
{
// Start a new line
panelSize.Width = Math.Max(panelSize.Width, lineSize.Width);
panelSize.Height += lineSize.Height + Spacing;
lineSize = new MutableSize(childSize.Width, childSize.Height);
itemsInCurrentLine = 1;
continue;
}
child.Measure(childConstraint);
Size childSize = new(itemWidth, child.DesiredSize.Height);
if (MathUtilities.GreaterThan(currentLineSize.Width + childSize.Width + Spacing, lineConstraint.Width))
{
// Need to switch to another line
panelSize.Width = Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height;
currentLineSize = new(childSize);
}
else
{
// Add to the current line
lineSize.Width += childSize.Width + (itemsInCurrentLine > 0 ? Spacing : 0);
lineSize.Height = Math.Max(lineSize.Height, childSize.Height);
itemsInCurrentLine++;
// Continue to accumulate a line
currentLineSize.Width += childSize.Width + Spacing;
currentLineSize.Height = Max(childSize.Height, currentLineSize.Height);
}
}
// Add the last line size
panelSize.Width = Math.Max(panelSize.Width, lineSize.Width);
panelSize.Height += lineSize.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;
return panelSize.ToSize();
}
@@ -122,33 +130,41 @@ public class FixedWrapPanel : Panel, INavigableContainer
/// <inheritdoc/>
protected override Size ArrangeOverride(Size finalSize)
{
var itemWidth = (finalSize.Width - (Spacing * (ItemsPerLine - 1))) / ItemsPerLine;
var position = default(MutablePoint);
var lineHeight = 0.0;
int itemsInCurrentLine = 0;
try
double itemWidth = (finalSize.Width - (Spacing * (ItemsPerLine - 1))) / ItemsPerLine;
int firstInLine = 0;
double accumulatedHeight = 0;
var currentLineSize = default(MutableSize);
for (int i = 0; i < Children.Count; i++)
{
foreach (var child in Children.OfType<Control>())
Control child = Children[i];
if (child == null)
{
if (itemsInCurrentLine == ItemsPerLine)
{
// Move to the next line
position.X = 0;
position.Y += lineHeight + Spacing;
lineHeight = 0;
itemsInCurrentLine = 0;
}
continue;
}
var childSize = new Size(itemWidth, child.DesiredSize.Height);
child.Arrange(new Rect(position.ToPoint(), childSize));
position.X += itemWidth + Spacing;
lineHeight = Math.Max(lineHeight, childSize.Height);
itemsInCurrentLine++;
MutableSize itemSize = new(itemWidth, child.DesiredSize.Height);
if (MathUtilities.GreaterThan(currentLineSize.Width + itemSize.Width, finalSize.Width))
{
// Need to switch to another line
ArrangeLine(accumulatedHeight, currentLineSize.Height, firstInLine, i, itemWidth);
accumulatedHeight += currentLineSize.Height;
currentLineSize = itemSize;
firstInLine = i;
}
else
{
// Continue to accumulate a line
currentLineSize.Width += itemSize.Width;
currentLineSize.Height = Max(itemSize.Height, currentLineSize.Height);
}
}
catch
{ }
if (firstInLine < Children.Count)
{
// Arrange the last line, if any
ArrangeLine(accumulatedHeight, currentLineSize.Height, firstInLine, Children.Count, itemWidth);
}
return finalSize;
}
@@ -164,32 +180,19 @@ public class FixedWrapPanel : Panel, INavigableContainer
continue;
}
try
if (i < end - 1)
{
if (i < end - 1 || i % ItemsPerLine == 0)
{
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 - Spacing, height));
x += width + Spacing;
}
else
{
child.Arrange(new Rect(x, y, width, height));
x += width;
}
catch { }
}
}
record struct MutablePoint
{
internal double X;
internal double Y;
internal readonly Point ToPoint() => new Point(X, Y);
}
record struct MutableSize
{
internal MutableSize(double width, double height)
@@ -135,15 +135,11 @@
<ItemsControl>
<ItemsControl.Items>
<Border Height="30" Background="Red" />
<Border Height="30" Background="Blue" />
<Border Background="Blue" />
<Border Background="Yellow" />
<Border Height="30" Background="Yellow" />
<Border Height="30" Background="Yellow" />
<Border Height="30" Background="Red" />
<Border Height="30" Background="Blue" />
<Border Height="30" Background="Blue" />
<Border Height="30" Background="Blue" />
<Border Height="30" Background="Blue" />
<Border Height="30" Background="Red" />
<Border Background="Red" />
<Border Background="Blue" />
</ItemsControl.Items>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
@@ -287,7 +287,6 @@
<!--<Border spp:Animations.EnableAnimations="True">-->
<spp:AppItem
Title="{Binding Name}"
MinHeight="250"
MaxWidth="260"
Classes="Vertical Scale"
ClickCommand="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
@@ -311,29 +311,10 @@ sealed class IPCSubProcessFileSystem : IOPath.FileSystemBase
config.LoggingRules.Add(new LoggingRule("*", minLevel, target));
}
public static string GetLogDirPath(string? moduleName = null, string? cacheDirectory = null)
{
cacheDirectory ??= IOPath.CacheDirectory;
string logDirPath;
if (moduleName == null)
{
logDirPath = Path.Combine(cacheDirectory, LogDirName);
}
else
{
var dirName = GetDirectoryName(moduleName);
logDirPath = Path.Combine(cacheDirectory, LogDirName, dirName);
}
IOPath.DirCreateByNotExists(logDirPath);
return logDirPath;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InitLog(
ref string? logDirPath,
string? moduleName = null,
string? mainProcessModuleName = null,
string? alias = null,
string? cacheDirectory = null
#if STARTUP_WATCH_TRACE || DEBUG
@@ -354,8 +335,16 @@ sealed class IPCSubProcessFileSystem : IOPath.FileSystemBase
cacheDirectory ??= IOPath.CacheDirectory;
logDirPath = GetLogDirPath(moduleName, cacheDirectory);
if (mainProcessModuleName == null)
{
logDirPath = Path.Combine(cacheDirectory, LogDirName);
}
else
{
var dirName = GetDirectoryName(mainProcessModuleName);
logDirPath = Path.Combine(cacheDirectory, LogDirName, dirName);
}
IOPath.DirCreateByNotExists(logDirPath);
#if (STARTUP_WATCH_TRACE || DEBUG) && !LIB_CLIENT_IPC
if (watchTrace) Startup.WatchTrace.Record("InitLog.IOPath");
#endif
@@ -76,9 +76,6 @@
<Compile Include="..\BD.WTTS.Client\Services\Platform\IPlatformService.OS.Linux.Etc.Os_Release.cs">
<LinkBase>Services\Platform</LinkBase>
</Compile>
<Compile Include="..\BD.WTTS.Client\Services\Mvvm\LogConsoleService.Logger.cs">
<LinkBase>Services\Mvvm</LinkBase>
</Compile>
</ItemGroup>
<ItemGroup>
@@ -107,7 +104,6 @@
<PackageReference Include="System.Drawing.Common" />
<PackageReference Include="System.Runtime.Caching" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
<PackageReference Include="Utf8StringInterpolation" />
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::IsOSPlatform('windows')) AND ($(RuntimeIdentifier.StartsWith('win-')) OR $(RuntimeIdentifier) == '')">
@@ -20,7 +20,7 @@ public partial interface IReverseProxyConfig
/// </summary>
/// <param name="domain"></param>
/// <returns></returns>
bool IsMatch(string url) => TryGetDomainConfig(url, out _);
bool IsMatch(string domain) => TryGetDomainConfig(domain, out _);
/// <summary>
/// 尝试获取域名配置
@@ -28,7 +28,7 @@ public partial interface IReverseProxyConfig
/// <param name="domain"></param>
/// <param name="value"></param>
/// <returns></returns>
bool TryGetDomainConfig(string url, [MaybeNullWhen(false)] out IDomainConfig value);
bool TryGetDomainConfig(string domain, [MaybeNullWhen(false)] out IDomainConfig value);
/// <summary>
/// 尝试获取脚本配置
@@ -36,7 +36,7 @@ public partial interface IReverseProxyConfig
/// <param name="domain"></param>
/// <param name="value"></param>
/// <returns></returns>
bool TryGetScriptConfig(string url, [MaybeNullWhen(false)] out IEnumerable<IScriptConfig> value);
bool TryGetScriptConfig(string domain, [MaybeNullWhen(false)] out IEnumerable<IScriptConfig> value);
/// <summary>
/// 尝试获取脚本内容
@@ -148,26 +148,26 @@ sealed class ReverseProxyConfig : IReverseProxyConfig
// return result;
//}
public bool TryGetDomainConfig(string url, [MaybeNullWhen(false)] out IDomainConfig value)
public bool TryGetDomainConfig(string domain, [MaybeNullWhen(false)] out IDomainConfig value)
{
//value = domainConfigCache.GetOrAdd(domain.Host, GetDomainConfig);
var uri = new UriBuilder(url).Uri;
var uri = new UriBuilder(domain).Uri;
domainConfigCache.TryGetValue(uri.Host, out value);
if (value != null)
return true;
value = GetDomainConfig(url);
value = GetDomainConfig(domain);
if (value == null)
return false;
domainConfigCache.TryAdd(uri.Host, value);
return true;
IDomainConfig? GetDomainConfig(string url)
IDomainConfig? GetDomainConfig(string domain)
{
var key = domainConfigs.Keys.FirstOrDefault(item => item.IsMatch(url));
var key = domainConfigs.Keys.FirstOrDefault(item => item.IsMatch(domain));
return key == null ? null : domainConfigs[key];
}
}
@@ -81,7 +81,6 @@ static void ConfigureServices(IServiceCollection services)
#if DEBUG
l.AddConsole();
#endif
l.AddProvider(new LogConsoleService.Utf8StringLoggerProvider(moduleName));
});
// 设置仓储层数据库文件存放路径
@@ -39,7 +39,6 @@ sealed partial class HttpReverseProxyMiddleware
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var url = context.Request.GetDisplayUrl();
//var url = context.Request.GetDisplayUrl().Remove(0, context.Request.Scheme.Length + 3);
var isScriptInject = reverseProxyConfig.TryGetScriptConfig(url, out var scriptConfigs);
@@ -52,7 +51,7 @@ sealed partial class HttpReverseProxyMiddleware
context.Response.Body = memoryStream;
}
if (TryGetDomainConfig(url.Remove(0, context.Request.Scheme.Length + 3), out var domainConfig) == false)
if (TryGetDomainConfig(url, out var domainConfig) == false)
{
if (reverseProxyConfig.Service.TwoLevelAgentEnable)
{
@@ -182,7 +181,7 @@ sealed partial class HttpReverseProxyMiddleware
return true;
}
var host = new UriBuilder(uri).Host;
var host = new Uri(uri).Host;
// 未配置的域名,但仍然被解析到本机 IP 的域名
if (IsDomain(host))
{
@@ -23,8 +23,6 @@ sealed class LazyReverseProxyServiceImpl : IReverseProxyService
public byte[]? GetFlowStatistics_Bytes() => impl().GetFlowStatistics_Bytes();
public string? GetLogAllMessage() => impl().GetLogAllMessage();
public async Task<StartProxyResult> StartProxyAsync(byte[] reverseProxySettings)
{
var result = await impl().StartProxyAsync(reverseProxySettings);
@@ -53,14 +53,14 @@ sealed class DnsDohAnalysisService : GeneralHttpClientFactory
{
if (dnsClients.TryGetValue(dohAddresUri, out var value))
return value;
//var client = CreateClient($"{TAG}_{dohAddresUri}", HttpHandlerCategory.Default);
var handler = new HttpClientHandler
{
UseCookies = false,
UseProxy = false,
Proxy = HttpNoProxy.Instance,
};
var client = new HttpClient(handler);
var client = CreateClient($"{TAG}_{dohAddresUri}", HttpHandlerCategory.Default);
//var handler = new HttpClientHandler
//{
// UseCookies = false,
// UseProxy = false,
// Proxy = HttpNoProxy.Instance,
//};
//var client = new HttpClient(handler);
client.BaseAddress = dohAddresUri;
var dnsClient = new DnsHttpClient(client);
dnsClients.TryAdd(dohAddresUri, dnsClient);
@@ -65,8 +65,6 @@ sealed partial class YarpReverseProxyServiceImpl : ReverseProxyServiceImpl, IRev
WebRootPath = RootPath,
});
builder.Logging.AddProvider(new LogConsoleService.Utf8StringLoggerProvider(AssemblyInfo.Accelerator));
builder.Services.Configure<HostFilteringOptions>(static o =>
{
o.AllowEmptyHosts = true;
@@ -169,12 +167,6 @@ sealed partial class YarpReverseProxyServiceImpl : ReverseProxyServiceImpl, IRev
return bytes;
}
public string? GetLogAllMessage()
{
var result = LogConsoleService.Builder;
return result.ToString();
}
// IDisposable
protected override void DisposeCore()
@@ -15,12 +15,6 @@ partial interface IReverseProxyService
/// </summary>
/// <returns></returns>
byte[]? GetFlowStatistics_Bytes();
/// <summary>
/// 获取所有日志信息
/// </summary>
/// <returns></returns>
string? GetLogAllMessage();
}
public static partial class ReverseProxyServiceExtensions
@@ -8,18 +8,18 @@ public partial interface IDnsAnalysisService // 公共常量定义
{
#region DNS 常量
const string DNS_Ali_DohAddres = "https://dns.alidns.com/resolve";
const string DNS_Ali_DohAddres2 = "https://223.6.6.6/resolve";
const string DNS_Ali_DohAddres3 = "https://223.5.5.5/resolve";
const string DNS_Ali_DohAddres = "https://dns.alidns.com";
const string DNS_Ali_DohAddres2 = "https://223.6.6.6/dns-query";
const string DNS_Ali_DohAddres3 = "https://223.5.5.5/dns-query";
const string Dnspod_DohAddres = "https://1.12.12.12/resolve";
const string Dnspod_DohAddres2 = "https://doh.pub/resolve";
const string Dnspod_DohAddres3 = "https://120.53.53.53/resolve";
const string Dnspod_DohAddres = "https://1.12.12.12/dns-query";
const string Dnspod_DohAddres2 = "https://doh.pub/dns-query";
const string Dnspod_DohAddres3 = "https://120.53.53.53/dns-query";
const string Google_DohAddres = "https://dns.google/resolve";
const string Cloudflare_DohAddres = "https://cloudflare-dns.com/resolve";
const string DohAddres_360 = "https://doh.360.cn/resolve";
const string TUNA_DohAddres = "https://101.6.6.6:8443/resolve";
const string Google_DohAddres = "https://dns.google";
const string Cloudflare_DohAddres = "https://cloudflare-dns.com";
const string DohAddres_360 = "https://doh.360.cn/dns-query";
const string TUNA_DohAddres = "https://101.6.6.6:8443/dns-query";
const string PrimaryDNS_IPV6_Ali = "2400:3200::1";
@@ -60,5 +60,5 @@ public partial interface IDnsAnalysisService // 公共常量定义
public static readonly IPEndPoint Cloudflare2 = new(IPAddress.Parse("1.0.0.1"), 53);
}
#endregion DNS 常量
#endregion
}
@@ -42,14 +42,6 @@ static class WinDivertInitHelper
/// </summary>
public static async Task InitializeAsync()
{
(byte[] WinDivert_dll, byte[] WinDivert64_sys) data = default;
void GetData()
{
if (data != default)
data = GetWinDivertBinRes();
}
if (libraryPath != null && libraryDirPath != null)
{
bool isWrite;
@@ -63,10 +55,9 @@ static class WinDivertInitHelper
}
else
{
GetData();
var libraryBytes = await File.ReadAllBytesAsync(libraryPath);
var libraryHash = SHA256.HashData(libraryBytes);
var libraryHashRes = SHA256.HashData(data.WinDivert_dll!);
var libraryHashRes = SHA256.HashData(WinDivertBinRes.WinDivert_dll);
if (libraryHash.SequenceEqual(libraryHashRes)) // 哈希值相同,不写入
{
isWrite = false;
@@ -85,15 +76,14 @@ static class WinDivertInitHelper
if (isWrite) // 检查文件不存在时写入
{
GetData();
switch (RuntimeInformation.ProcessArchitecture)
{
//case Architecture.X86:
// break;
case Architecture.X64:
IOPath.DirCreateByNotExists(libraryDirPath);
var task1 = File.WriteAllBytesAsync(Path.Combine(libraryDirPath, "WinDivert64.sys"), data.WinDivert64_sys!);
var task2 = File.WriteAllBytesAsync(libraryPath, data.WinDivert_dll!);
var task1 = File.WriteAllBytesAsync(Path.Combine(libraryDirPath, "WinDivert64.sys"), WinDivertBinRes.WinDivert64_sys);
var task2 = File.WriteAllBytesAsync(libraryPath, WinDivertBinRes.WinDivert_dll);
await Task.WhenAll(task1, task2);
break;
}
@@ -138,15 +128,5 @@ static class WinDivertInitHelper
break;
}
}
static (byte[] WinDivert_dll, byte[] WinDivert64_sys) GetWinDivertBinRes()
{
byte[] bytes = WinDivertBinRes.WinDivert_mpo;
bytes.AsSpan().Reverse();
var data = MemoryPackSerializer.Deserialize<byte[][]>(bytes)!;
return (data[0], data[1]);
}
}
#endif
@@ -66,9 +66,6 @@ public sealed class Plugin : PluginBase<Plugin>, IPlugin
services.AddSingleton(_ => certificateManager.Task.GetAwaiter().GetResult());
#endif
}
services.AddSingleton<INetworkTestService, NetworkTestService>();
//if (startup.HasIPCRoot)
//{
// services.AddSingleton<IAcceleratorService, BackendAcceleratorServiceImpl>();
@@ -1,4 +1,4 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
@@ -63,9 +63,19 @@ namespace BD.WTTS.Properties {
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] WinDivert_mpo {
internal static byte[] WinDivert_dll {
get {
object obj = ResourceManager.GetObject("WinDivert_mpo", resourceCulture);
object obj = ResourceManager.GetObject("WinDivert_dll", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] WinDivert64_sys {
get {
object obj = ResourceManager.GetObject("WinDivert64_sys", resourceCulture);
return ((byte[])(obj));
}
}
@@ -99,7 +99,10 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="WinDivert_mpo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\..\ref\WinDivert.mpo;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<data name="WinDivert64_sys" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\..\ref\WinDivert64.sys;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="WinDivert_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\..\ref\WinDivert.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>
@@ -80,11 +80,6 @@ partial class BackendAcceleratorServiceImpl
/// <inheritdoc/>
public async Task<ApiRsp<bool>> XY_IsInstall(CancellationToken cancellationToken = default)
{
if (!XunYouSDK.IsSupported)
{
return ApiRspHelper.Ok(false);
}
var result = XunYouSDK.IsInstall();
await Task.CompletedTask;
return result;
@@ -93,11 +88,6 @@ partial class BackendAcceleratorServiceImpl
/// <inheritdoc/>
public async Task<ApiRsp<XunYouUninstallCode>> XY_Uninstall(CancellationToken cancellationToken = default)
{
if (!XunYouSDK.IsSupported)
{
return ApiRspHelper.Ok(XunYouUninstallCode.卸载成功);
}
var result = XunYouSDK.Uninstall();
await Task.CompletedTask;
return result;
@@ -114,16 +104,9 @@ partial class BackendAcceleratorServiceImpl
string? svrPath = default,
CancellationToken cancellationToken = default)
{
if (!XunYouSDK.IsSupported)
{
return ApiRspHelper.Ok(0);
}
var show = XunYouShowCommands.SW_HIDE;
var result = XunYouSDK.StartEx2(
openid,
nickname,
show,
gameid,
area,
server,
@@ -145,11 +128,6 @@ partial class BackendAcceleratorServiceImpl
string? svrName = default,
CancellationToken cancellationToken = default)
{
if (!XunYouSDK.IsSupported)
{
return ApiRspHelper.Ok(0);
}
var result = XunYouSDK.StartAccel(
gameid,
area,
@@ -163,11 +141,6 @@ partial class BackendAcceleratorServiceImpl
/// <inheritdoc/>
public async Task<ApiRsp<XunYouAccelStateModel?>> XY_GetAccelStateEx(CancellationToken cancellationToken = default)
{
if (!XunYouSDK.IsSupported)
{
return ApiRspHelper.Ok((XunYouAccelStateModel?)null);
}
var result = GetXunYouAccelStateModel(lastXunYouState);
await Task.CompletedTask;
return result;
@@ -176,11 +149,6 @@ partial class BackendAcceleratorServiceImpl
/// <inheritdoc/>
public async IAsyncEnumerable<ApiRsp<int>> XY_Install(string installPath, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
if (!XunYouSDK.IsSupported)
{
yield break;
}
var channel = Channel.CreateUnbounded<int>();
int XunYouDownLoadCallback(int par, nint thisptr)
{
@@ -209,11 +177,6 @@ partial class BackendAcceleratorServiceImpl
/// <inheritdoc/>
public async Task<ApiRsp<XunYouSendResultCode>> XY_StopAccel(CancellationToken cancellationToken = default)
{
if (!XunYouSDK.IsSupported)
{
return ApiRspHelper.Ok(XunYouSendResultCode.发送成功);
}
var result = XunYouSDK.Stop();
await Task.CompletedTask;
return result;
@@ -222,11 +185,6 @@ partial class BackendAcceleratorServiceImpl
/// <inheritdoc/>
public async Task<ApiRsp<XunYouIsRunningCode>> XY_IsRunning(CancellationToken cancellationToken = default)
{
if (!XunYouSDK.IsSupported)
{
return ApiRspHelper.Ok(XunYouIsRunningCode.加速器未启动);
}
var result = XunYouSDK.IsRunning();
await Task.CompletedTask;
return result;
@@ -235,26 +193,8 @@ partial class BackendAcceleratorServiceImpl
/// <inheritdoc/>
public async Task<ApiRsp<XunYouStartGameCode>> XY_StartGame(CancellationToken cancellationToken = default)
{
if (!XunYouSDK.IsSupported)
{
return ApiRspHelper.Ok(XunYouStartGameCode.失败);
}
var result = XunYouSDK.StartGame();
await Task.CompletedTask;
return result;
}
/// <inheritdoc/>
public async Task<ApiRsp<int>> XY_ShowWinodw(bool showHide, CancellationToken cancellationToken = default)
{
if (!XunYouSDK.IsSupported)
{
return ApiRspHelper.Ok(0);
}
XunYouSDK.xunyou_show(Convert.ToInt32(showHide));
await Task.CompletedTask;
return ApiRspHelper.Ok(0);
}
}
@@ -52,7 +52,7 @@ internal partial class NetworkTestService : INetworkTestService
#region Open/Upload/Download Speed Test
public async Task<(bool Success, long? DelayMs)> TestOpenUrlAsync(string url, Func<HttpClient>? httpClientFunc = null, CancellationToken cancellationToken = default)
public async Task<(bool success, long? delayMs)> TestOpenUrlAsync(string url, Func<HttpClient>? httpClientFunc = null, CancellationToken cancellationToken = default)
{
using var testClient = httpClientFunc?.Invoke() ?? new HttpClient();
@@ -64,16 +64,20 @@ internal partial class NetworkTestService : INetworkTestService
watch.Stop();
resp.EnsureSuccessStatusCode();
return (true, watch.ElapsedMilliseconds);
}
catch (Exception ex)
{
Log.Error(nameof(NetworkTestService), ex, "测试打开 URL 异常");
return (false, default);
}
}
public async Task<(bool Success, double? Rate)> TestUploadSpeedAsync(
public async Task<(bool success, double? rate)> TestUploadSpeedAsync(
string uploadServerUrl,
byte[] uploadBytes,
CancellationToken cancellationToken = default
@@ -99,7 +103,7 @@ internal partial class NetworkTestService : INetworkTestService
}
}
public async Task<(bool Success, double? Rate)> TestDownloadSpeedAsync(string downloadUrl, CancellationToken cancellationToken = default)
public async Task<(bool success, double? rate)> TestDownloadSpeedAsync(string downloadUrl, CancellationToken cancellationToken = default)
{
using HttpClient testClient = new HttpClient();
@@ -115,7 +119,7 @@ internal partial class NetworkTestService : INetworkTestService
/// <param name="uploadBytes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
static async Task<(bool Success, double? Rate)> TestUploadSpeedCoreAsync(
static async Task<(bool success, double? rate)> TestUploadSpeedCoreAsync(
Func<HttpClient> httpClientFunc,
Func<byte[], HttpContent> uploadContentFunc,
string uploadServerUrl,
@@ -155,7 +159,7 @@ internal partial class NetworkTestService : INetworkTestService
/// <param name="url"></param>
/// <param name="httpClientFunc"></param>
/// <returns></returns>
static async Task<(bool Success, double? Rate)> TestDownloadSpeedCoreAsync(string url, Func<HttpClient>? httpClientFunc = null, CancellationToken cancellationToken = default)
static async Task<(bool success, double? rate)> TestDownloadSpeedCoreAsync(string url, Func<HttpClient>? httpClientFunc = null, CancellationToken cancellationToken = default)
{
var httpClient = httpClientFunc?.Invoke() ?? new HttpClient();
@@ -196,7 +200,7 @@ internal partial class NetworkTestService : INetworkTestService
return megabits / seconds; // 返回速率,单位是 Mbps
}
#endregion Open/Upload/Download Speed Test
#endregion Upload/Download Speed Test
#region STUN 测试
@@ -765,7 +769,7 @@ internal partial class NetworkTestService : INetworkTestService
}
}
private class DnsQueryAnswerRecordConverter : System.Text.Json.Serialization.JsonConverter<DnsQueryAnswerRecord>
class DnsQueryAnswerRecordConverter : System.Text.Json.Serialization.JsonConverter<DnsQueryAnswerRecord>
{
public override DnsQueryAnswerRecord? Read(ref Utf8JsonReader reader, Type typeToConvert, SystemTextJsonSerializerOptions options)
{
@@ -87,12 +87,6 @@ partial interface IAcceleratorService // XunYou
/// </summary>
/// <returns></returns>
Task<ApiRsp<XunYouStartGameCode>> XY_StartGame(CancellationToken cancellationToken = default);
/// <summary>
/// 迅游加速器显示隐藏
/// </summary>
/// <returns></returns>
Task<ApiRsp<int>> XY_ShowWinodw(bool showHide, CancellationToken cancellationToken = default);
}
partial interface IXunYouAccelStateToFrontendCallback
@@ -6,8 +6,6 @@ namespace BD.WTTS.Services;
internal interface INetworkTestService : IHttpRequestTestService, IStunTestService
{
static INetworkTestService Instance => Ioc.Get<INetworkTestService>();
/// <summary>
/// Ping
/// </summary>
@@ -59,7 +57,7 @@ internal interface IHttpRequestTestService
/// <param name="httpClientFunc"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<(bool Success, long? DelayMs)> TestOpenUrlAsync(string url, Func<HttpClient>? httpClientFunc = null, CancellationToken cancellationToken = default);
Task<(bool success, long? delayMs)> TestOpenUrlAsync(string url, Func<HttpClient>? httpClientFunc = null, CancellationToken cancellationToken = default);
/// <summary>
/// 测试上传速度
@@ -68,7 +66,7 @@ internal interface IHttpRequestTestService
/// <param name="uploadBytes"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<(bool Success, double? Rate)> TestUploadSpeedAsync(
Task<(bool success, double? rate)> TestUploadSpeedAsync(
string uploadServerUrl,
byte[] uploadBytes,
CancellationToken cancellationToken = default
@@ -80,7 +78,7 @@ internal interface IHttpRequestTestService
/// <param name="downloadUrl"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<(bool Success, double? Rate)> TestDownloadSpeedAsync(string downloadUrl, CancellationToken cancellationToken = default);
Task<(bool success, double? rate)> TestDownloadSpeedAsync(string downloadUrl, CancellationToken cancellationToken = default);
}
internal interface IStunTestService
@@ -66,14 +66,7 @@ public sealed partial class GameAcceleratorService
DeleteMyGameCommand = ReactiveCommand.Create<XunYouGameViewModel>(DeleteMyGame);
GameAcceleratorCommand = ReactiveCommand.CreateFromTask<XunYouGameViewModel>(GameAccelerator);
GameLaunchCommand = ReactiveCommand.CreateFromTask<XunYouGameViewModel>(GameLaunch);
InstallAcceleratorCommand = ReactiveCommand.CreateFromTask(async () =>
{
if (await IWindowManager.Instance.ShowTaskDialogAsync(new MessageBoxWindowViewModel(),
pageContent: new AcceleratorPathAskBox(), title: "游戏加速", isCancelButton: false, isOkButton: false))
{
await InstallAccelerator();
}
});
InstallAcceleratorCommand = ReactiveCommand.CreateFromTask(InstallAccelerator);
UninstallAcceleratorCommand = ReactiveCommand.Create(UninstallAccelerator);
AcceleratorChangeAreaCommand = ReactiveCommand.Create<XunYouGameViewModel>(AcceleratorChangeArea);
@@ -254,13 +247,8 @@ public sealed partial class GameAcceleratorService
/// <summary>
/// 设置加速游戏状态
/// </summary>
async void SetGameStatus(XunYouGameViewModel game, int areaId = 0, int serverId = 0)
void SetGameStatus(XunYouGameViewModel game, int areaId = 0, int serverId = 0)
{
if (!XunYouSDK.IsSupported)
{
return;
}
if (CurrentAcceleratorGame != null && CurrentAcceleratorGame.Id == game.Id)
{
CurrentAcceleratorGame.IsAccelerating = false;
@@ -307,10 +295,6 @@ public sealed partial class GameAcceleratorService
//加速后
Toast.Show(ToastIcon.Success, "加速成功");
if (ProxySettings.AutoShowWattAcceleratorWindow.Value)
{
_ = ShowXunYouWindow(true);
}
int testSpeedCallback(SpeedCallbackWrapper w)
{
if (CurrentAcceleratorGame != null)
@@ -337,11 +321,6 @@ public sealed partial class GameAcceleratorService
public async Task GameAccelerator(XunYouGameViewModel app)
{
if (!XunYouSDK.IsSupported)
{
return;
}
if (app.IsAccelerating)
return;
@@ -369,7 +348,7 @@ public sealed partial class GameAcceleratorService
//}
if (!await IWindowManager.Instance.ShowTaskDialogAsync(new MessageBoxWindowViewModel(),
pageContent: new AcceleratorPathAskBox(), title: "游戏加速", isCancelButton: false, isOkButton: false))
pageContent: new AcceleratorPathAskBox(), title: "未安装加速插件", isCancelButton: true))
{
app.IsAccelerating = false;
return;
@@ -767,9 +746,4 @@ public sealed partial class GameAcceleratorService
}
}
}
public async Task ShowXunYouWindow(bool showHide)
{
var result = await Ioc.Get<IAcceleratorService>().XY_ShowWinodw(showHide);
}
}
@@ -1,7 +1,6 @@
// ReSharper disable once CheckNamespace
using Avalonia.Data;
using Google.Protobuf.WellKnownTypes;
using Org.BouncyCastle.Bcpg.OpenPgp;
using System.Linq;
namespace BD.WTTS.Services;
@@ -152,7 +151,6 @@ public sealed partial class ProxyService
ProxyStarting = false;
ProxyStatus = startOrStop;
IsAnyProxyScripts = ProxyStatus && IsEnableScript;
}
}
@@ -262,16 +260,6 @@ public sealed partial class ProxyService
[Reactive]
public bool ProxyStatus { get; set; }
[Reactive]
public bool IsAnyProxyScripts { get; set; }
private bool CheckProxyScriptsEnable()
{
if (!ProxyScripts.Items.Any_Nullable())
return false;
return ProxyScripts.Items!.Any(w => !w.Disable);
}
#endregion 代理状态启动退出
static bool IsProgramStartupRunProxy()
@@ -160,11 +160,6 @@ public partial interface IProxySettings
/// </summary>
int AcceleratorTabsSelectedIndex { get; set; }
/// <summary>
/// 加速后自动唤起 Watt 加速器界面
/// </summary>
bool AutoShowWattAcceleratorWindow { get; set; }
/// <summary>
/// 启用脚本自动检查更新的默认值
/// </summary>
@@ -285,9 +280,4 @@ public partial interface IProxySettings
/// </summary>
static readonly int DefaultAcceleratorTabsSelectedIndex = 0;
/// <summary>
/// 加速后自动唤起 Watt 加速器界面的默认值
/// </summary>
const bool DefaultAutoShowWattAcceleratorWindow = true;
}
@@ -203,12 +203,6 @@ public sealed partial class ProxySettings_ : IProxySettings, ISettings, ISetting
[MPKey(23), MP2Key(23), JsonPropertyOrder(23)]
public int AcceleratorTabsSelectedIndex { get; set; } = IProxySettings.DefaultAcceleratorTabsSelectedIndex;
/// <summary>
/// 加速后自动唤起 Watt 加速器界面
/// </summary>
[MPKey(24), MP2Key(24), JsonPropertyOrder(24)]
public bool AutoShowWattAcceleratorWindow { get; set; } = IProxySettings.DefaultAutoShowWattAcceleratorWindow;
}
public static partial class ProxySettings
@@ -377,10 +371,4 @@ public static partial class ProxySettings
public static SettingsStructProperty<int, ProxySettings_> AcceleratorTabsSelectedIndex { get; }
= new(DefaultAcceleratorTabsSelectedIndex);
/// <summary>
/// 加速后自动唤起 Watt 加速器界面
/// </summary>
public static SettingsStructProperty<bool, ProxySettings_> AutoShowWattAcceleratorWindow { get; }
= new(DefaultAutoShowWattAcceleratorWindow);
}
@@ -1,8 +1,7 @@
using AppResources = BD.WTTS.Client.Resources.Strings;
using BD.WTTS.Client.Resources;
using BD.WTTS.UI.Views.Pages;
using STUN.StunResult;
using STUN.Enums;
namespace BD.WTTS.UI.ViewModels;
@@ -13,7 +12,6 @@ public sealed partial class AcceleratorPageViewModel
readonly IPlatformService platformService = IPlatformService.Instance;
readonly IReverseProxyService reverseProxyService = IReverseProxyService.Constants.Instance;
readonly ICertificateManager certificateManager = ICertificateManager.Constants.Instance;
readonly INetworkTestService networkTestService = INetworkTestService.Instance;
public AcceleratorPageViewModel()
{
@@ -24,29 +22,6 @@ public sealed partial class AcceleratorPageViewModel
#endif
//ProxyService.Current.ProxyStatus = !ProxyService.Current.ProxyStatus;
await ProxyService.Current.StartOrStopProxyService(!ProxyService.Current.ProxyStatus);
if (ProxyService.Current.ProxyStatus == false)
return;
// Create new ProxyEnableDomain for 加速服务 page
var enableGroupDomain = ProxyService.Current.ProxyDomainsList
.Where(list => list.ThreeStateEnable == true || list.ThreeStateEnable == null)
.Select(list => new ProxyDomainGroupViewModel
{
Name = list.Name,
IconUrl = list.IconUrl ?? string.Empty,
EnableProxyDomainVMs = new(
list.Items!
.Where(i => i.ThreeStateEnable == true)
.Select(i => new ProxyDomainViewModel(i.Name, i.ProxyType, "https://" + i.ListenDomainNames.Split(";")[0],
i.Items?
.Select(c => new ProxyDomainViewModel(c.Name, c.ProxyType, "https://" + c.ListenDomainNames.Split(';')[0]))
.ToList()))
.ToList()),
})
.ToList();
EnableProxyDomainGroupVMs = enableGroupDomain.AsReadOnly();
});
RefreshCommand = ReactiveCommand.Create(async () =>
@@ -54,7 +29,6 @@ public sealed partial class AcceleratorPageViewModel
if (_initializeTime > DateTime.Now.AddSeconds(-2))
{
Toast.Show(ToastIcon.Warning, Strings.Warning_DoNotOperateFrequently);
return;
}
@@ -69,65 +43,10 @@ public sealed partial class AcceleratorPageViewModel
GameAcceleratorService.Current.LoadGames();
});
SelectedSTUNAddress = STUNAddress[0];
NATCheckCommand = ReactiveCommand.CreateFromTask(async () =>
{
var natCheckResult = await networkTestService.TestStunClient3489Async(testServerHostName: SelectedSTUNAddress) ?? new ClassicStunResult { NatType = NatType.Unknown };
var (netSucc, _) = await networkTestService.TestOpenUrlAsync("https://www.baidu.com");
var natStatus = natCheckResult.NatType switch
{
NatType.OpenInternet or NatType.FullCone => NatTypeSimple.Open,
NatType.RestrictedCone or NatType.PortRestrictedCone or NatType.SymmetricUdpFirewall => NatTypeSimple.Moderate,
NatType.Symmetric or NatType.UdpBlocked => NatTypeSimple.Strict,
NatType.Unknown or NatType.UnsupportedServer or _ => NatTypeSimple.Unknown,
};
PublicEndPoint = natCheckResult.PublicEndPoint?.Address.ToString() ?? "Unknown";
LocalEndPoint = natCheckResult.LocalEndPoint?.Address.ToString() ?? "Unknown";
return (natStatus, netSucc);
});
NATCheckCommand
.IsExecuting
.ToPropertyEx(this, x => x.IsNATChecking);
DNSCheckCommand = ReactiveCommand.CreateFromTask(async () =>
{
var testDomain = DomainPendingTest == string.Empty ? "steamcommunity.com" : DomainPendingTest;
try
{
long delayMs;
IPAddress[] address;
if (ProxySettings.UseDoh)
{
var configDoh = ProxySettings.CustomDohAddres.Value ?? string.Empty;
(delayMs, address) = await networkTestService.TestDNSOverHttpsAsync(testDomain, configDoh);
}
else
{
var configDns = ProxySettings.ProxyMasterDns.Value ?? string.Empty;
(delayMs, address) = await networkTestService.TestDNSAsync(testDomain, configDns, 53);
}
DNSTestDelay = delayMs + "ms ";
DNSTestResult = "" + address.FirstOrDefault() ?? "0.0.0.0";
}
catch (Exception ex)
{
Log.Error(nameof(AcceleratorPageViewModel), ex.ToString());
DNSTestDelay = string.Empty;
DNSTestResult = "error";
}
});
DNSCheckCommand
.IsExecuting
.ToPropertyEx(this, x => x.IsDNSChecking);
ProxySettingsCommand = ReactiveCommand.Create(() =>
{
var vm = new ProxySettingsWindowViewModel();
_ = IWindowManager.Instance.ShowTaskDialogAsync(vm, vm.Title, pageContent: new ProxySettingsPage(), isOkButton: false);
IWindowManager.Instance.ShowTaskDialogAsync(vm, vm.Title, pageContent: new ProxySettingsPage(), isOkButton: false);
});
if (IApplication.IsDesktop())
@@ -146,15 +65,10 @@ public sealed partial class AcceleratorPageViewModel
certificateManager.GetCerFilePathGeneratedWhenNoFileExists();
platformService.OpenFolder(certificateManager.PfxFilePath);
});
OpenLogFileCommand = ReactiveCommand.Create(() =>
{
platformService.OpenFolder(IPCSubProcessFileSystem.GetLogDirPath(Plugin.Instance.UniqueEnglishName));
});
}
}
#if LINUX
public bool EnvironmentCheck()
{
try
@@ -175,7 +89,6 @@ public sealed partial class AcceleratorPageViewModel
return false;
}
}
#endif
public void TrustCer_OnClick()
@@ -1,145 +1,12 @@
using Avalonia.Controls;
using Avalonia.Media;
using BD.WTTS.Client.Resources;
using System.Reactive;
namespace BD.WTTS.UI.ViewModels;
public class ProxyDomainGroupViewModel : ReactiveObject
{
private readonly INetworkTestService networkTestService = INetworkTestService.Instance;
public string Name { get; set; } = string.Empty;
public string IconUrl { get; set; } = string.Empty;
public ReadOnlyCollection<ProxyDomainViewModel>? EnableProxyDomainVMs { get; set; }
public ReactiveCommand<Unit, Unit> ConnectTestCommand { get; set; }
public ProxyDomainGroupViewModel()
{
ConnectTestCommand = ReactiveCommand.CreateFromTask(async () =>
{
var tasks = EnableProxyDomainVMs!.Select(async enableDomain =>
{
enableDomain.DelayMillseconds = "- ms";
var (success, delayMs) = await networkTestService.TestOpenUrlAsync(enableDomain.Url);
enableDomain.DelayMillseconds = success switch
{
true when delayMs > 20000 => "Timeout",
true => delayMs.ToString() + " ms",
false => "error",
};
});
await Task.WhenAll(tasks);
});
}
}
public class ProxyDomainViewModel : ReactiveObject
{
private readonly INetworkTestService networkTestService = INetworkTestService.Instance;
public string Name { get; }
public ProxyType ProxyType { get; }
public string Url { get; }
[Reactive]
public string DelayMillseconds { get; set; } = string.Empty;
[ObservableAsProperty]
public bool RetestButtonVisible { get; }
[ObservableAsProperty]
public IBrush DelayColor { get; } = null!;
public ReadOnlyCollection<ProxyDomainViewModel>? Children { get; }
public ProxyDomainViewModel(string name, ProxyType proxyType, string url, List<ProxyDomainViewModel>? children = null)
{
Name = name;
ProxyType = proxyType;
Url = url;
Children = children?.AsReadOnly();
this.WhenAnyValue(x => x.DelayMillseconds)
.Subscribe(delay => Children?.ForEach(child => child.DelayMillseconds = delay));
this.WhenAnyValue(x => x.DelayMillseconds)
.Select(d => d != string.Empty && d != "-")
.ToPropertyEx(this, x => x.RetestButtonVisible);
const int DelayMiddle = 1000;
this.WhenAnyValue(x => x.DelayMillseconds)
.Select(d => d switch
{
"Timeout" or "error" => Brushes.Red,
var s when s.Split(' ') is [var num, "ms"] && int.TryParse(num, out int ms)
=> ms switch
{
<= DelayMiddle => Brushes.Green,
> DelayMiddle => Brushes.Orange,
},
_ => (IBrush?)App.Instance.FindResource("TextFillColorPrimaryBrush"),
})
.ToPropertyEx(this, x => x.DelayColor);
}
}
public sealed partial class AcceleratorPageViewModel : TabItemViewModel
{
public enum NatTypeSimple
{
Unknown,
Open,
Moderate,
Strict,
}
public override string Name => Strings.Welcome;
[Reactive]
public string SelectedSTUNAddress { get; set; }
public List<string> STUNAddress { get; } =
[
"stun.syncthing.net",
"stun.hot-chilli.net",
"stun.fitauto.ru",
"stun.miwifi.com",
];
[ObservableAsProperty]
public bool IsNATChecking { get; }
[ObservableAsProperty]
public bool IsDNSChecking { get; }
[Reactive]
public string DomainPendingTest { get; set; } = string.Empty;
[Reactive]
public ReadOnlyCollection<ProxyDomainGroupViewModel>? EnableProxyDomainGroupVMs { get; set; }
[Reactive]
public string LocalEndPoint { get; set; } = string.Empty;
[Reactive]
public string PublicEndPoint { get; set; } = string.Empty;
[Reactive]
public string DNSTestDelay { get; set; } = string.Empty;
[Reactive]
public string DNSTestResult { get; set; } = string.Empty;
public ReactiveCommand<Unit, (NatTypeSimple Nat, bool PingSuccess)> NATCheckCommand { get; }
public ReactiveCommand<Unit, Unit> DNSCheckCommand { get; }
public ICommand StartProxyCommand { get; }
public ICommand RefreshCommand { get; }
@@ -163,6 +30,4 @@ public sealed partial class AcceleratorPageViewModel : TabItemViewModel
public ICommand? ProxySettingsCommand { get; }
public ICommand? TrustCerCommand { get; }
public ICommand? OpenLogFileCommand { get; }
}
}
@@ -9,20 +9,17 @@ public sealed class AllGamesListPageViewModel : WindowViewModel
{
XunYouGames = new ObservableCollection<XunYouGameViewModel>();
if (XunYouSDK.IsSupported)
Task2.InBackground(() =>
{
Task2.InBackground(() =>
var games = XunYouSDK.GetAllGames();
if (games != null)
{
var games = XunYouSDK.GetAllGames();
if (games != null)
XunYouGames.Clear();
foreach (var game in games)
{
XunYouGames.Clear();
foreach (var game in games)
{
XunYouGames.Add(new XunYouGameViewModel(game));
}
XunYouGames.Add(new XunYouGameViewModel(game));
}
});
}
}
});
}
}
@@ -14,7 +14,7 @@ public sealed class ProxySettingsWindowViewModel : WindowViewModel
//public IEnumerable<ExternalProxyType> ProxyTypes { get; }
// = Enum2.GetAll<ExternalProxyType>();
public static IEnumerable<string> ProxyDNSs { get; } = new[]
public IEnumerable<string> ProxyDNSs { get; } = new[]
{
"System Default",
PrimaryDNS_114,
@@ -31,7 +31,7 @@ public sealed class ProxySettingsWindowViewModel : WindowViewModel
"127.0.0.1",
};
public static IEnumerable<string> DohAddress { get; }
public IEnumerable<string> DohAddress { get; }
= new[] {
Dnspod_DohAddres,
Dnspod_DohAddres2,
@@ -44,4 +44,4 @@ public sealed class ProxySettingsWindowViewModel : WindowViewModel
DohAddres_360,
TUNA_DohAddres,
};
}
}
@@ -10,14 +10,7 @@
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<StackPanel Spacing="15">
<TextBlock FontSize="21" TextAlignment="Center">
<Run Text="下载 Watt加速器" />
<LineBreak />
<Run Text="拒绝游戏延迟,提高稳定性" />
</TextBlock>
<StackPanel Spacing="6">
<ui:SettingsExpander
Description="{Binding Source={x:Static ms:GameAcceleratorSettings.WattAcceleratorDirPath}, Path=Value}"
Header="安装路径"
@@ -29,16 +22,6 @@
<Button Click="SelectWattAcceleratorInstallPath" Content="选择路径" />
</ui:SettingsExpander.Footer>
</ui:SettingsExpander>
<!--<TextBlock Text="需要下载 Watt 加速器插件才可使用,确定要下载吗?" />-->
<Button
Margin="0,15"
Padding="20,10"
HorizontalAlignment="Center"
Classes="TransparentAccent"
Click="OKButton_Click"
Content="立即下载"
FontSize="14" />
<TextBlock Text="需要下载 Watt 加速器插件才可使用,确定要下载吗?" />
</StackPanel>
</UserControl>
@@ -1,10 +1,9 @@
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using Avalonia.ReactiveUI;
namespace BD.WTTS.UI.Views.Controls;
public partial class AcceleratorPathAskBox : ReactiveUserControl<MessageBoxWindowViewModel>
public partial class AcceleratorPathAskBox : UserControl
{
public AcceleratorPathAskBox()
{
@@ -31,9 +30,4 @@ public partial class AcceleratorPathAskBox : ReactiveUserControl<MessageBoxWindo
GameAcceleratorSettings.WattAcceleratorDirPath.Value = Path.Combine(path, "WattAccelerator");
}
}
private void OKButton_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
this.ViewModel?.Close?.Invoke(true);
}
}
@@ -1,98 +0,0 @@
<UserControl
x:Class="BD.WTTS.UI.Views.Pages.AcceleratorServiceStatus"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:enum="using:BD.WTTS.Enums"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:spp="https://steampp.net/ui"
xmlns:ui="using:FluentAvalonia.UI.Controls"
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True"
x:DataType="spp:AcceleratorPageViewModel"
mc:Ignorable="d">
<ScrollViewer
Padding="0,0,10,0"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding EnableProxyDomainGroupVMs}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" Spacing="{StaticResource SettingsSpacing}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border>
<ui:SettingsExpander IsClickEnabled="False" IsExpanded="True">
<ui:SettingsExpander.Header>
<StackPanel Orientation="Horizontal" Spacing="10">
<spp:Image2
Width="30"
Height="30"
VerticalAlignment="Center"
RenderOptions.BitmapInterpolationMode="HighQuality"
Source="{Binding IconUrl}"
Stretch="UniformToFill" />
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
</StackPanel>
</ui:SettingsExpander.Header>
<ui:SettingsExpander.Footer>
<Button
HorizontalAlignment="Right"
Click="ConnectTestButtonOnClick"
Command="{Binding ConnectTestCommand}"
Content="连通性测试"
DockPanel.Dock="Right" />
</ui:SettingsExpander.Footer>
<ui:SettingsExpanderItem Theme="{StaticResource SettingsExpanderItem2}">
<TreeView ItemsSource="{Binding EnableProxyDomainVMs}" SelectionMode="Single">
<TreeView.ItemContainerTheme>
<ControlTheme BasedOn="{StaticResource {x:Type TreeViewItem}}" TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
</ControlTheme>
</TreeView.ItemContainerTheme>
<TreeView.ItemTemplate>
<TreeDataTemplate ItemsSource="{Binding Children}">
<DockPanel Margin="8,0">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
<Border
Padding="5,0"
CornerRadius="5"
IsVisible="{Binding ProxyType, Converter={StaticResource EnumEqualValueConverter}, ConverterParameter={x:Static enum:ProxyType.ServerAccelerate}}"
ToolTip.Tip="Beta 测试加速项,不稳定且随时可能调整">
<Border.Background>
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
<GradientStop Offset="0.0" Color="#43cbff" />
<GradientStop Offset="1.0" Color="#9708cc" />
</LinearGradientBrush>
</Border.Background>
<TextBlock
VerticalAlignment="Center"
FontSize="10"
Text="Beta" />
</Border>
</StackPanel>
<TextBlock
Margin="0,0,4,0"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
Foreground="{Binding DelayColor}"
Text="{Binding DelayMillseconds}"
ToolTip.Tip="此数值代表测试网页打开访问所需时间,仅供参考" />
</DockPanel>
</TreeDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</ui:SettingsExpanderItem>
</ui:SettingsExpander>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</UserControl>
@@ -1,25 +0,0 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.VisualTree;
using FluentAvalonia.UI.Controls;
namespace BD.WTTS.UI.Views.Pages;
public partial class AcceleratorServiceStatus : UserControl
{
public AcceleratorServiceStatus()
{
InitializeComponent();
}
private void ConnectTestButtonOnClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var expander = button.FindAncestorOfType<SettingsExpander>();
if (expander != null) expander.IsExpanded = true;
}
}
}
@@ -177,15 +177,6 @@
FontSize="18"
IsVisible="{Binding ShowStart}" />
<Button
Width="175"
Height="42"
Classes="accent"
Command="{Binding ShowXunYouWindow, Source={x:Static s:GameAcceleratorService.Current}}"
CommandParameter="True"
Content="{x:Static spp:Strings.GameAccelerator_ShowWattAccelerator}"
FontSize="18" />
<Button
Width="150"
Height="42"
@@ -1,307 +0,0 @@
<UserControl
x:Class="BD.WTTS.UI.Views.Pages.NetworkCheck"
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:ms="https://steampp.net/settings"
xmlns:s="https://steampp.net/services"
xmlns:spp="https://steampp.net/ui"
xmlns:sys="using:System"
xmlns:ui="using:FluentAvalonia.UI.Controls"
d:DesignHeight="450"
d:DesignWidth="800"
x:DataType="spp:AcceleratorPageViewModel"
mc:Ignorable="d">
<ScrollViewer
Padding="0,0,10,0"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<StackPanel Spacing="8">
<ui:SettingsExpander IsClickEnabled="False" IsExpanded="True">
<ui:SettingsExpander.Header>
<StackPanel Orientation="Horizontal">
<ui:FontIcon
FontFamily="Segoe Fluent Icons"
FontSize="26"
Glyph="&#xE969;" />
<TextBlock
Margin="12,0,0,0"
VerticalAlignment="Center"
Text="NAT 类型检测" />
</StackPanel>
</ui:SettingsExpander.Header>
<ui:SettingsExpander.Footer>
<WrapPanel>
<ui:FAComboBox
x:Name="STUNServer"
Margin="4"
x:FieldModifier="public"
IsEditable="False"
IsEnabled="{Binding !IsNATChecking}"
ItemsSource="{Binding STUNAddress}"
SelectedItem="{Binding SelectedSTUNAddress}"
ToolTip.Tip="STUN 服务器地址">
<ui:FAComboBox.ItemTemplate>
<DataTemplate DataType="sys:String">
<TextBlock Text="{Binding}" />
</DataTemplate>
</ui:FAComboBox.ItemTemplate>
</ui:FAComboBox>
<Button
x:Name="NATCheckButton"
Width="100"
Margin="4"
x:FieldModifier="public"
Content="检测"
IsEnabled="True" />
</WrapPanel>
</ui:SettingsExpander.Footer>
<StackPanel
Margin="24,0,0,0"
Background="Transparent"
Spacing="8">
<ui:SettingsExpanderItem Background="Transparent">
<TextBlock VerticalAlignment="Center" Text="NAT 类型:" />
<ui:SettingsExpanderItem.Footer>
<Grid>
<ui:ProgressRing
Width="22"
Margin="0,-4,0,-10"
HorizontalAlignment="Right"
IsVisible="{Binding IsNATChecking}" />
<DockPanel IsVisible="{Binding !IsNATChecking}">
<SelectableTextBlock
x:Name="NATTextBlock"
VerticalAlignment="Center"
Foreground="Gray"
Text="未知" />
<ui:FontIcon
Margin="3,0"
FontSize="20"
Glyph="&#xE946;">
<ToolTip.Tip>
<TextBlock x:Name="NATTypeTip" Text="未知类型" />
</ToolTip.Tip>
</ui:FontIcon>
</DockPanel>
</Grid>
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<Separator Margin="-64,0" Classes="Separator" />
<ui:SettingsExpanderItem Background="Transparent">
<TextBlock VerticalAlignment="Center" Text="本地IP地址:" />
<ui:SettingsExpanderItem.Footer>
<Grid>
<ui:ProgressRing
Width="22"
Margin="0,-4,0,-10"
HorizontalAlignment="Right"
IsVisible="{Binding IsNATChecking}" />
<SelectableTextBlock
x:Name="LocalIPAddress"
Foreground="Gray"
IsVisible="{Binding !IsNATChecking}" />
</Grid>
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<Separator Margin="-64,0" Classes="Separator" />
<ui:SettingsExpanderItem Background="Transparent">
<TextBlock
VerticalAlignment="Center"
Text="对外IP地址:"
ToolTip.Tip="若与您路由器 WAN IP 地址相同,则为公共网络" />
<ui:SettingsExpanderItem.Footer>
<Grid>
<ui:ProgressRing
Width="22"
Margin="0,-4,0,-10"
HorizontalAlignment="Right"
IsVisible="{Binding IsNATChecking}" />
<SelectableTextBlock
Foreground="Gray"
IsVisible="{Binding !IsNATChecking}"
Text="{Binding PublicEndPoint}" />
</Grid>
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<Separator Margin="-64,0" Classes="Separator" />
<!--<Border Classes="paper" Margin="-64 0" />-->
<ui:SettingsExpanderItem Background="Transparent">
<TextBlock VerticalAlignment="Center" Text="互联网连通情况:" />
<ui:SettingsExpanderItem.Footer>
<Grid>
<ui:ProgressRing
Width="22"
Margin="0,-4,0,-10"
HorizontalAlignment="Right"
IsVisible="{Binding IsNATChecking}" />
<ui:FontIcon
x:Name="PingOK"
HorizontalAlignment="Right"
x:FieldModifier="public"
FontFamily="{StaticResource SymbolThemeFontFamily}"
FontSize="26"
Foreground="Green"
Glyph="&#xe73d;" />
<Grid x:Name="PingError" x:FieldModifier="public">
<ui:FontIcon
Margin="3"
HorizontalAlignment="Right"
FontFamily="Segoe Fluent Icons"
FontSize="20"
Foreground="Red"
Glyph="&#xf127;" />
<ui:FontIcon
HorizontalAlignment="Right"
FontSize="26"
Foreground="White"
Glyph="&#xea39;" />
</Grid>
</Grid>
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<!--<Separator Classes="Separator" Margin="-64 0" />-->
<Separator Margin="-64,0" Classes="Horizontal" />
<ui:SettingsExpanderItem Margin="-28,0,0,-4" Background="Transparent">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock
VerticalAlignment="Center"
FontWeight="Bold"
Text="相关链接" />
<HyperlinkButton
VerticalAlignment="Center"
Content="解决NAT错误"
NavigateUri="https://support.xbox.com/zh-CN/help/hardware-network/connect-network/xbox-one-nat-error" />
</StackPanel>
</ui:SettingsExpanderItem>
</StackPanel>
</ui:SettingsExpander>
<!-- DNS -->
<ui:SettingsExpander IsClickEnabled="False" IsExpanded="True">
<ui:SettingsExpander.Header>
<StackPanel Orientation="Horizontal">
<ui:FontIcon
FontFamily="Segoe Fluent Icons"
FontSize="26"
Glyph="&#xEDA3;" />
<TextBlock
Margin="12,0,0,0"
VerticalAlignment="Center"
Text="DNS 检测" />
</StackPanel>
</ui:SettingsExpander.Header>
<ui:SettingsExpander.Footer>
<Button
x:Name="DNSCheckButton"
Width="100"
Content="检测"
IsEnabled="True" />
</ui:SettingsExpander.Footer>
<StackPanel Margin="24,0,0,0">
<ui:SettingsExpanderItem Margin="-28,0,0,-4" Background="Transparent">
<TextBlock
VerticalAlignment="Center"
FontWeight="Bold"
Text="检测项目" />
</ui:SettingsExpanderItem>
<Separator Margin="-64,0" Classes="Separator" />
<ui:SettingsExpanderItem Background="Transparent">
<TextBlock Text="待检测的域名" />
<ui:SettingsExpanderItem.Footer>
<TextBox
x:Name="DomainTextBox"
Width="200"
Watermark="steamcommunity.com" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Background="Transparent">
<TextBlock Text="{Binding Path=Res.Settings_Proxy_CustomDNS, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<ui:SettingsExpanderItem.Footer>
<ui:FAComboBox
x:Name="dummy"
Width="200"
IsEditable="False"
IsEnabled="{Binding Source={x:Static ms:ProxySettings.UseDoh}, Path=!Value}"
ItemsSource="{Binding Source={x:Static spp:ProxySettingsWindowViewModel.ProxyDNSs}}"
Text="{Binding Source={x:Static ms:ProxySettings.ProxyMasterDns}, Path=Value, Mode=TwoWay}" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Background="Transparent">
<TextBlock Text="{Binding Path=Res.CommunityFix_EnableUseDoh, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<ui:SettingsExpanderItem.Footer>
<ToggleSwitch Classes="LeftContent" IsChecked="{Binding Source={x:Static ms:ProxySettings.UseDoh}, Path=Value, Mode=TwoWay}" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Background="Transparent">
<TextBlock Text="{Binding Path=Res.CommunityFix_CustomDohAddres, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<ui:SettingsExpanderItem.Footer>
<ui:FAComboBox
Width="200"
IsEditable="False"
IsEnabled="{Binding Source={x:Static ms:ProxySettings.UseDoh}, Path=Value}"
ItemsSource="{Binding Source={x:Static spp:ProxySettingsWindowViewModel.DohAddress}}"
PlaceholderText="{Binding Source={x:Static s:IDnsAnalysisService.Dnspod_DohAddres}, Mode=OneWay}"
Text="{Binding Source={x:Static ms:ProxySettings.CustomDohAddres}, Path=Value, Mode=TwoWay}" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Margin="-28,0,0,-4" Background="Transparent">
<TextBlock
VerticalAlignment="Center"
FontWeight="Bold"
Text="测试结果" />
</ui:SettingsExpanderItem>
<Separator Margin="-64,0" Classes="Separator" />
<ui:SettingsExpanderItem Background="Transparent">
<TextBlock Text="延迟" />
<ui:SettingsExpanderItem.Footer>
<Grid>
<ui:ProgressRing
Width="22"
Margin="0,-4,0,-10"
IsVisible="{Binding IsDNSChecking}" />
<SelectableTextBlock Text="{Binding DNSTestDelay}" />
</Grid>
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Background="Transparent">
<TextBlock Text="解析地址" />
<ui:SettingsExpanderItem.Footer>
<Grid>
<ui:ProgressRing
Width="22"
Margin="0,-4,0,-10"
IsVisible="{Binding IsDNSChecking}" />
<SelectableTextBlock Text="{Binding DNSTestResult}" />
</Grid>
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
</StackPanel>
</ui:SettingsExpander>
</StackPanel>
</ScrollViewer>
</UserControl>
@@ -1,17 +0,0 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Org.BouncyCastle.Asn1.Utilities;
namespace BD.WTTS.UI.Views.Pages;
public partial class NetworkCheck : UserControl
{
public NetworkCheck()
{
InitializeComponent();
this.dummy.SelectedItem = ProxySettings.ProxyMasterDns.Value;
this.dummy.Text = ProxySettings.ProxyMasterDns.Value;
}
}
@@ -1,10 +1,14 @@
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;
namespace BD.WTTS.UI.Views.Controls;
@@ -1,20 +0,0 @@
<UserControl
x:Class="BD.WTTS.UI.Views.Controls.ProxyLog"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:AvaloniaEdit="using:AvaloniaEdit"
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"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Border Background="{DynamicResource CardBackgroundFillColorDefaultBrush}" CornerRadius="{DynamicResource ControlCornerRadius}">
<AvaloniaEdit:TextEditor
x:Name="LogTextbox"
HorizontalScrollBarVisibility="Disabled"
IsReadOnly="True"
ShowLineNumbers="True" />
</Border>
</UserControl>
@@ -1,92 +0,0 @@
using Avalonia.Controls;
using Avalonia.Threading;
using Avalonia.VisualTree;
using AvaloniaEdit;
using AvaloniaEdit.TextMate;
using Org.BouncyCastle.Math;
using TextMateSharp.Grammars;
namespace BD.WTTS.UI.Views.Controls;
public partial class ProxyLog : UserControl
{
CancellationTokenSource cancellation = new();
public ProxyLog()
{
InitializeComponent();
var logTextbox = this.FindControl<TextEditor>("LogTextbox")!;
//Here we initialize RegistryOptions with the theme we want to use.
var registryOptions = new TextMateSharp.Grammars.RegistryOptions(ThemeName.Dark);
//Initial setup of TextMate.
var textMateInstallation = logTextbox.InstallTextMate(registryOptions);
//Here we are getting the language by the extension and right after that we are initializing grammar with this language.
//And that's all 😀, you are ready to use AvaloniaEdit with syntax highlighting!
textMateInstallation.SetGrammar(registryOptions.GetScopeByLanguageId(registryOptions.GetLanguageByExtension(".log").Id));
//logTextbox.Text = LogText;
//logTextbox.ScrollToLine(logTextbox.Document.LineCount);
logTextbox.TextChanged += LogTextbox_TextChanged;
ProxyService.Current.WhenAnyValue(x => x.ProxyStatus)
.Subscribe(x =>
{
if (x)
{
cancellation = new CancellationTokenSource();
Task2.InBackground(FlushLogsAsync, true);
}
else
{
if (cancellation != null)
{
cancellation.Cancel();
cancellation.Dispose();
}
}
});
}
private void LogTextbox_TextChanged(object? sender, EventArgs e)
{
LogTextbox.ScrollToLine(LogTextbox.Document.LineCount);
}
void FlushLogsAsync()
{
while (!cancellation.IsCancellationRequested)
{
try
{
var isAttachedToVisualTree = this.IsAttachedToVisualTree();
if (isAttachedToVisualTree)
{
var logtext = IReverseProxyService.Constants.Instance.GetLogAllMessage();
if (string.IsNullOrEmpty(logtext))
{
Thread.Sleep(1000);
continue;
}
Dispatcher.UIThread.Post(() =>
{
if (LogTextbox.Text.Length != logtext.Length)
LogTextbox.Text = logtext;
});
}
}
catch
{
}
finally
{
Thread.Sleep(1000);
}
}
}
}
@@ -1,47 +0,0 @@
<UserControl
x:Class="BD.WTTS.UI.Views.Pages.ProxyServiceStatus"
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"
d:DesignHeight="450"
d:DesignWidth="800"
x:DataType="spp:AcceleratorPageViewModel"
mc:Ignorable="d">
<ScrollViewer
Padding="0,0,10,0"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<ItemsControl Grid.Column="1" ItemsSource="{Binding EnableProxyScripts^, Source={x:Static s:ProxyService.Current}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type spp:ScriptDTO}">
<spp:AppItem
Title="{Binding Name}"
MaxWidth="135"
Margin="4"
Classes="Vertical"
Description="{Binding AuthorName}"
ImageMargin="20"
ImageStretch="None"
ToolTip.Tip="{Binding Describe}">
<spp:AppItem.Image>
<spp:Image2
FallbackSource="avares://BD.WTTS.Client.Plugins.Accelerator/UI/Assets/script.ico"
RenderOptions.BitmapInterpolationMode="HighQuality"
Source="{Binding IconUrl}"
Stretch="Uniform" />
</spp:AppItem.Image>
</spp:AppItem>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</UserControl>
@@ -1,13 +0,0 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace BD.WTTS.UI.Views.Pages;
public partial class ProxyServiceStatus : UserControl
{
public ProxyServiceStatus()
{
InitializeComponent();
}
}
@@ -6,15 +6,13 @@
xmlns:enum="using:BD.WTTS.Enums"
xmlns:i="using:Avalonia.Xaml.Interactivity"
xmlns:ia="using:Avalonia.Xaml.Interactions.Core"
xmlns:ir="using:Avalonia.Xaml.Interactions.Responsive"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ms="https://steampp.net/settings"
xmlns:s="https://steampp.net/services"
xmlns:spp="https://steampp.net/ui"
xmlns:sys="using:System"
xmlns:ui="using:FluentAvalonia.UI.Controls"
Title="{Binding Name, Source={x:Static s:Plugin.Instance}, Mode=OneWay}"
d:DesignHeight="650"
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True"
x:DataType="spp:AcceleratorPageViewModel"
@@ -306,59 +304,37 @@
<Separator Margin="0,8" Classes="Horizontal" />
<ItemsControl>
<ItemsControl.Items>
<Button
HorizontalAlignment="Stretch"
Command="{Binding SetupCertificateCommand}"
Content="{x:Static spp:Strings.CommunityFix_SetupCertificate}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding DeleteCertificateCommand}"
Content="{x:Static spp:Strings.CommunityFix_DeleteCertificate}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding ShowCertificateCommand}"
Content="查看证书信息" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding OpenCertificateDirCommand}"
Content="{x:Static spp:Strings.CommunityFix_OpenCertificateDir}" />
</ItemsControl.Items>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<spp:FixedWrapPanel ItemsPerLine="2" Spacing="5" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button
HorizontalAlignment="Stretch"
Command="{Binding SetupCertificateCommand}"
Content="{x:Static spp:Strings.CommunityFix_SetupCertificate}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding DeleteCertificateCommand}"
Content="{x:Static spp:Strings.CommunityFix_DeleteCertificate}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding ShowCertificateCommand}"
Content="查看证书信息" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding OpenCertificateDirCommand}"
Content="{x:Static spp:Strings.CommunityFix_OpenCertificateDir}" />
<Separator Margin="0,8" Classes="Horizontal" />
<ItemsControl>
<ItemsControl.Items>
<Button
HorizontalAlignment="Stretch"
Command="{Binding EditHostsFileCommand}"
Content="{x:Static spp:Strings.CommunityFix_EditHostsFile}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding ResetHostsFileCommand}"
Content="{x:Static spp:Strings.CommunityFix_ResetHostsFile}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding OpenHostsDirCommand}"
Content="{x:Static spp:Strings.CommunityFix_OpenHostsDir}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding OpenLogFileCommand}"
Content="打开加速日志文件夹" />
</ItemsControl.Items>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<spp:FixedWrapPanel ItemsPerLine="2" Spacing="5" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button
HorizontalAlignment="Stretch"
Command="{Binding EditHostsFileCommand}"
Content="{x:Static spp:Strings.CommunityFix_EditHostsFile}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding ResetHostsFileCommand}"
Content="{x:Static spp:Strings.CommunityFix_ResetHostsFile}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding OpenHostsDirCommand}"
Content="{x:Static spp:Strings.CommunityFix_OpenHostsDir}" />
<!--<ui:FAComboBox ItemsSource="{Binding Source={x:Static ms:ProxySettings.ProxyModes}, Path=., Mode=OneWay}" SelectedItem="{Binding Source={x:Static ms:ProxySettings.ProxyMode}, Path=Value, Mode=TwoWay}">
<ui:FAComboBox.ItemTemplate>
@@ -368,19 +344,9 @@
</ui:FAComboBox.ItemTemplate>
</ui:FAComboBox>-->
<StackPanel IsVisible="{x:Static spp:XunYouSDK.IsSupported}}" Spacing="10">
<Separator Margin="0,8" Classes="Horizontal" />
<Separator Margin="0,8" Classes="Horizontal" />
<TextBlock Text="Watt 加速器相关" Theme="{StaticResource BodyStrongTextBlockStyle}" />
<ToggleSwitch
VerticalAlignment="Center"
Classes="NoContent"
IsChecked="{Binding Source={x:Static ms:ProxySettings.AutoShowWattAcceleratorWindow}, Path=Value, Mode=TwoWay}"
OffContent="{x:Static spp:Strings.GameAccelerator_SetShowWattWindow}"
OnContent="{x:Static spp:Strings.GameAccelerator_SetShowWattWindow}" />
<!--<TextBlock Text="{x:Static spp:Strings.GameAccelerator_WattAcceleratorInstallPath}" Theme="{StaticResource BodyStrongTextBlockStyle}" />
<!--<TextBlock Text="{x:Static spp:Strings.GameAccelerator_WattAcceleratorInstallPath}" Theme="{StaticResource BodyStrongTextBlockStyle}" />
<ui:SettingsExpander Description="{Binding Source={x:Static ms:GameAcceleratorSettings.WattAcceleratorDirPath}, Path=Value, Mode=OneWay}}" IsExpanded="True">
<ui:SettingsExpander.IconSource>
@@ -393,127 +359,74 @@
<Button Content="打开文件夹" />
<Button Content="选择路径" />
</StackPanel>
</ui:SettingsExpander>-->
<!--<ItemsControl>
<ItemsControl.Items>
</ItemsControl.Items>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<spp:FixedWrapPanel ItemsPerLine="2" Spacing="5" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>-->
<Button
HorizontalAlignment="Stretch"
Command="{Binding ShowXunYouWindow, Source={x:Static s:GameAcceleratorService.Current}}"
CommandParameter="True"
Content="{x:Static spp:Strings.GameAccelerator_ShowWattAccelerator}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding InstallAcceleratorCommand, Source={x:Static s:GameAcceleratorService.Current}}"
Content="{x:Static spp:Strings.GameAccelerator_InstallWattAccelerator}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding UninstallAcceleratorCommand, Source={x:Static s:GameAcceleratorService.Current}}"
Content="{x:Static spp:Strings.GameAccelerator_UninstallWattAccelerator}" />
</StackPanel>
<Button
HorizontalAlignment="Stretch"
Command="{Binding InstallAcceleratorCommand, Source={x:Static s:GameAcceleratorService.Current}}"
Content="{x:Static spp:Strings.GameAccelerator_InstallWattAccelerator}" />
<Button
HorizontalAlignment="Stretch"
Command="{Binding UninstallAcceleratorCommand, Source={x:Static s:GameAcceleratorService.Current}}"
Content="{x:Static spp:Strings.GameAccelerator_UninstallWattAccelerator}" />
</StackPanel>
</spp:PageBase.PaneContent>
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,Auto,*">
<Grid.Resources>
<sys:Double x:Key="AdaptiveWidth">800</sys:Double>
</Grid.Resources>
<Grid.Styles>
<Style Selector="StackPanel.small">
<Setter Property="Grid.Row" Value="1" />
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
<Style Selector="StackPanel.wide">
<Setter Property="Grid.Row" Value="0" />
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
<Style Selector="TabStrip.small">
<Setter Property="Grid.ColumnSpan" Value="2" />
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
<Style Selector="TabStrip.wide">
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
</Grid.Styles>
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,*">
<TabStrip
x:Name="AcceleratorTabs"
VerticalAlignment="Top"
ItemContainerTheme="{StaticResource TabItemStyle}"
Theme="{StaticResource TabStripStyle}">
<i:Interaction.Behaviors>
<spp:AdaptiveBehavior SourceControl="{Binding $parent[TopLevel]}">
<ir:AdaptiveClassSetter
MinWidth="0"
MaxWidth="{StaticResource AdaptiveWidth}"
ClassName="small" />
<ir:AdaptiveClassSetter
MinWidth="{StaticResource AdaptiveWidth}"
MaxWidth="Infinity"
ClassName="wide" />
</spp:AdaptiveBehavior>
</i:Interaction.Behaviors>
<TabStripItem Content="平台加速" IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=!ProxyStatus, Mode=OneWay}">
<!--<WrapPanel>-->
<TextBlock Text="平台加速" />
<!--<Border
<WrapPanel>
<TextBlock Text="平台加速" />
<Border
Margin="5,0,0,0"
Padding="5,1"
VerticalAlignment="Center"
CornerRadius="2">
<Border.Background>
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
<GradientStop Offset="0.0" Color="#48C6EF" />
<GradientStop Offset="1.0" Color="#6F86D6" />
</LinearGradientBrush>
</Border.Background>
<TextBlock
<Border.Background>
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
<GradientStop Offset="0.0" Color="#48C6EF" />
<GradientStop Offset="1.0" Color="#6F86D6" />
</LinearGradientBrush>
</Border.Background>
<TextBlock
VerticalAlignment="Center"
FontSize="10"
Foreground="White"
Text="免费" />
</Border>
</WrapPanel>-->
</WrapPanel>
</TabStripItem>
<TabStripItem Content="{x:Static spp:Strings.CommunityFix_Services}" IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=ProxyStatus, Mode=OneWay}" />
<TabStripItem Content="加速脚本" IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=IsAnyProxyScripts, Mode=OneWay}" />
<TabStripItem Content="{x:Static spp:Strings.CommunityFix_ProxyLog}" IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=ProxyStatus, Mode=OneWay}" />
<TabStripItem Content="{x:Static spp:Strings.CommunityFix_FlowStatistics}" IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=ProxyStatus, Mode=OneWay}" />
<TabStripItem Content="{x:Static spp:Strings.CommunityFix_Services}" IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=ProxyStatus, Mode=OneWay}" />
<TabStripItem Name="GameAccTab">
<!--<WrapPanel>-->
<TextBlock Text="游戏加速" />
<!--<Border
<WrapPanel>
<TextBlock Text="游戏加速" />
<Border
Margin="5,0,0,0"
Padding="5,1"
VerticalAlignment="Center"
CornerRadius="2">
<Border.Background>
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
<GradientStop Offset="0.0" Color="#EEAD92" />
<GradientStop Offset="1.0" Color="#6018DC" />
</LinearGradientBrush>
</Border.Background>
<TextBlock
<Border.Background>
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
<GradientStop Offset="0.0" Color="#EEAD92" />
<GradientStop Offset="1.0" Color="#6018DC" />
</LinearGradientBrush>
</Border.Background>
<TextBlock
VerticalAlignment="Center"
FontSize="10"
Foreground="White"
Text="收费" />
</Border>-->
<!--</WrapPanel>-->
</Border>
</WrapPanel>
</TabStripItem>
<TabStripItem Content="网络检测" IsVisible="True" />
<TabStripItem Content="dummy_tab_for_transisit_animation" IsVisible="False" />
</TabStrip>
<Carousel
Grid.Row="2"
Grid.Row="1"
Margin="0,10,0,0"
Classes="AnimeSlide"
SelectedIndex="{Binding #AcceleratorTabs.SelectedIndex}">
@@ -596,18 +509,84 @@
</spp:ContentLoader>
</ScrollViewer>
<!-- 加速服务 -->
<spp:AcceleratorServiceStatus />
<!-- 加速脚本 -->
<spp:ProxyServiceStatus />
<!-- 加速日志 -->
<spp:ProxyLog Margin="5,0" />
<!-- 流量统计 -->
<spp:ProxyChartView Margin="5,0" />
<!-- 加速服务 -->
<Grid Margin="0,0,10,0" ColumnDefinitions="*,20,*">
<Border
Grid.Column="0"
Padding="10"
Classes="paper">
<DockPanel>
<TextBlock
Margin="0,0,0,10"
DockPanel.Dock="Top"
FontSize="16"
Text="{x:Static spp:Strings.CommunityFix_AccelerationsEnable}" />
<ScrollViewer>
<ItemsControl ItemsSource="{Binding EnableProxyDomains, Source={x:Static s:ProxyService.Current}}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type spp:AccelerateProjectDTO}">
<StackPanel Margin="10">
<DockPanel>
<TextBlock Text="{Binding Name}" />
<Border
Padding="5,0"
HorizontalAlignment="Left"
CornerRadius="5"
IsVisible="{Binding ProxyType, Converter={StaticResource EnumEqualValueConverter}, ConverterParameter={x:Static enum:ProxyType.ServerAccelerate}}"
ToolTip.Tip="Beta 测试加速项,不稳定且随时可能调整">
<Border.Background>
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
<GradientStop Offset="0.0" Color="#43cbff" />
<GradientStop Offset="1.0" Color="#9708cc" />
</LinearGradientBrush>
</Border.Background>
<TextBlock
VerticalAlignment="Center"
FontSize="10"
Text="Beta" />
</Border>
</DockPanel>
<Separator Classes="Separator" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</Border>
<Border
Grid.Column="2"
Padding="10"
Classes="paper">
<DockPanel>
<TextBlock
Margin="0,0,0,10"
DockPanel.Dock="Top"
FontSize="16"
Text="{x:Static spp:Strings.CommunityFix_ScriptsEnable}" />
<ScrollViewer>
<ItemsControl ItemsSource="{Binding EnableProxyScripts^, Source={x:Static s:ProxyService.Current}}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type spp:ScriptDTO}">
<StackPanel Margin="10">
<DockPanel>
<TextBlock Text="{Binding Name}" />
</DockPanel>
<Separator Classes="Separator" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</Border>
</Grid>
<!-- 游戏加速 -->
<Panel x:DataType="spp:GameAcceleratorPageViewModel">
<Panel.DataContext>
@@ -668,30 +647,20 @@
IsVisible="{Binding Source={x:Static s:GameAcceleratorService.Current}, Path=CurrentAcceleratorGame.IsAccelerated}" />
</Panel>
<!-- 网络检测 -->
<spp:NetworkCheck x:Name="NetworkCheckControl" />
<!--<TabItem Header="加速日志">
</TabItem>-->
<!--<TabItem Header="AD">
</TabItem>-->
</Carousel>
<!-- Side tab of paid game spped up -->
<StackPanel
Grid.ColumnSpan="2"
HorizontalAlignment="Right"
IsVisible="{Binding #GameAccTab.IsSelected}"
Orientation="Horizontal"
Spacing="5">
<i:Interaction.Behaviors>
<spp:AdaptiveBehavior SourceControl="{Binding $parent[TopLevel]}">
<ir:AdaptiveClassSetter
MinWidth="0"
MaxWidth="{StaticResource AdaptiveWidth}"
ClassName="small" />
<ir:AdaptiveClassSetter
MinWidth="{StaticResource AdaptiveWidth}"
MaxWidth="Infinity"
ClassName="wide" />
</spp:AdaptiveBehavior>
</i:Interaction.Behaviors>
<Border
Padding="5,1"
VerticalAlignment="Center"
@@ -763,26 +732,14 @@
</AutoCompleteBox>
</StackPanel>
<!-- Side tab after speed up -->
<StackPanel
Grid.ColumnSpan="2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
IsVisible="{Binding Source={x:Static s:ProxyService.Current}, Path=ProxyStatus, Mode=OneWay}"
Orientation="Horizontal"
Spacing="8">
<i:Interaction.Behaviors>
<spp:AdaptiveBehavior SourceControl="{Binding $parent[TopLevel]}">
<ir:AdaptiveClassSetter
MinWidth="0"
MaxWidth="{StaticResource AdaptiveWidth}"
ClassName="small" />
<ir:AdaptiveClassSetter
MinWidth="{StaticResource AdaptiveWidth}"
MaxWidth="Infinity"
ClassName="wide" />
</spp:AdaptiveBehavior>
</i:Interaction.Behaviors>
<StackPanel.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<CompiledBinding
@@ -820,7 +777,7 @@
</StackPanel>
<spp:AdControl
Grid.Row="2"
Grid.Row="1"
Grid.Column="1"
Width="165"
Height="390"
@@ -828,4 +785,4 @@
VerticalAlignment="Top"
Standard="Vertical" />
</Grid>
</spp:PageBase>
</spp:PageBase>
@@ -1,8 +1,8 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Interactivity;
using Avalonia.VisualTree;
using FluentAvalonia.UI.Controls;
using static System.Net.Mime.MediaTypeNames;
namespace BD.WTTS.UI.Views.Pages;
@@ -73,36 +73,6 @@ public partial class AcceleratorPage2 : PageBase<AcceleratorPageViewModel>
GameAccTab.IsVisible = false;
AcceleratorTabs.SelectedIndex = 0;
}
this.Bind(ViewModel, vm => vm.SelectedSTUNAddress, v => v.NetworkCheckControl.STUNServer.SelectedItem).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.NATCheckCommand, v => v.NetworkCheckControl.NATCheckButton).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.LocalEndPoint, v => v.NetworkCheckControl.LocalIPAddress.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.DNSCheckCommand, v => v.NetworkCheckControl.DNSCheckButton).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DomainPendingTest, v => v.NetworkCheckControl.DomainTextBox.Text).DisposeWith(disposables);
NetworkCheckControl.PingOK.IsVisible = false;
NetworkCheckControl.PingError.IsVisible = false;
NetworkCheckControl.NATCheckButton.Click += (_, _) => NetworkCheckControl.PingError.IsVisible = NetworkCheckControl.PingOK.IsVisible = false;
ViewModel!.NATCheckCommand
.Subscribe(result =>
{
(NetworkCheckControl.NATTextBlock.Text, NetworkCheckControl.NATTypeTip.Text) = result.Nat switch
{
AcceleratorPageViewModel.NatTypeSimple.Open => ("开放 NAT", "您可与在其网络上具有任意 NAT 类型的用户玩多人游戏和发起多人游戏。"),
AcceleratorPageViewModel.NatTypeSimple.Moderate => ("中等 NAT", "您可与一些用户玩多人游戏;但是,并且通常你将不会被选为比赛的主持人。"),
AcceleratorPageViewModel.NatTypeSimple.Strict => ("严格 NAT", "您只能与具有开放 NAT 类型的用户玩多人游戏。您不能被选为比赛的主持人。"),
_ => ("不可用 NAT", "如果 NAT 不可用,您将无法使用群聊天或连接到某些 Xbox 游戏的多人游戏。"),
};
if (result.PingSuccess)
{
NetworkCheckControl.PingOK.IsVisible = true;
}
else
{
NetworkCheckControl.PingError.IsVisible = true;
}
}).DisposeWith(disposables);
});
SearchGameBox.DropDownClosed += SearchGameBox_DropDownClosed;
@@ -180,4 +150,4 @@ public partial class AcceleratorPage2 : PageBase<AcceleratorPageViewModel>
// // Log.Error(nameof(AcceleratorPage), ex, "ForceSave fail.");
// //}
//}
}
}
@@ -16,7 +16,6 @@ partial class XunYouSDK // 12.接口 xunyou_start_ex2
/// </summary>
/// <param name="openid">登录 token,由调用方提供</param>
/// <param name="nickname">账号昵称</param>
/// <param name="show"><see cref="PInvoke.User32.WindowStyles"/></param>
/// <param name="gameid">游戏 id,由迅游给出明确值,或传 0,如果传 0,表示只启动迅游,不自动加速。</param>
/// <param name="area">游戏分区 id ,由游戏给出区服名和 id 对照表,或传 0,如果传 0,表示只启动迅游,不自动加速。</param>
/// <param name="server">游戏服 id</param>
@@ -29,7 +28,6 @@ partial class XunYouSDK // 12.接口 xunyou_start_ex2
public static int StartEx2(
string openid,
string nickname,
XunYouShowCommands show = XunYouShowCommands.SW_HIDE,
int gameid = 0,
int area = 0,
int server = 0,
@@ -53,7 +51,7 @@ partial class XunYouSDK // 12.接口 xunyou_start_ex2
result = xunyou_start_ex2(appId, openid, openid_len,
userType, channel_no, channel_no.Length,
nickname, nickname_len, show,
nickname, nickname_len, XunYouShowCommands.SW_HIDE,
gameid,
area, server, xunyou_callback, ptr,
installPath, install_path_len, areaName,
@@ -14,7 +14,6 @@ partial class XunYouSDK // 22.接口 xunyou_start_ex3
/// </summary>
/// <param name="jwt">登录 token,由调用方提供</param>
/// <param name="nickname">账号昵称</param>
/// <param name="show"><see cref="PInvoke.User32.WindowStyles"/></param>
/// <param name="gameid">游戏 id,由迅游给出明确值,或传 0,如果传 0,表示只启动迅游,不自动加速。</param>
/// <param name="area">游戏分区 id ,由游戏给出区服名和 id 对照表,或传 0,如果传 0,表示只启动迅游,不自动加速。</param>
/// <param name="server">游戏服 id</param>
@@ -27,7 +26,6 @@ partial class XunYouSDK // 22.接口 xunyou_start_ex3
public static int StartEx3(
string jwt,
string nickname,
XunYouShowCommands show = XunYouShowCommands.SW_HIDE,
int gameid = 0,
int area = 0,
int server = 0,
@@ -51,7 +49,7 @@ partial class XunYouSDK // 22.接口 xunyou_start_ex3
result = xunyou_start_ex2(appId, jwt, jwt_len,
userType, channel_no, channel_no.Length,
nickname, nickname_len, show,
nickname, nickname_len, XunYouShowCommands.SW_HIDE,
gameid,
area, server, xunyou_callback, ptr,
installPath, install_path_len, areaName,
@@ -1,12 +0,0 @@
namespace Mobius;
partial class XunYouSDK // 25.接口 xunyou_show
{
/// <summary>
/// 设置当前启动客户端的显隐状态
/// </summary>
/// <param name="show">客户端显示状态(SW_HIDE)</param>
[LibraryImport(libraryName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvStdcall)])]
public static partial void xunyou_show(int show = 0);
}
@@ -115,6 +115,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BD.Common.XmlnsDefinition.Avalonia">
<Aliases>BD_Common_XmlnsDefinition_Avalonia</Aliases>
</PackageReference>
<ProjectReference Include="..\BD.WTTS.Client\BD.WTTS.Client.csproj" />
<ProjectReference Include="..\BD.WTTS.Client.Avalonia\BD.WTTS.Client.Avalonia.csproj" />
</ItemGroup>
@@ -69,7 +69,7 @@ public partial class ArchiSteamFarmServiceImpl : ReactiveObject, IArchiSteamFarm
isFirstStart = false;
}
(var isSuccess, var ipcUrl) = await StartProcessAsync();
(var isSuccess, var ipcUrl) = await StartProcess();
if (!isSuccess && !isFirstStart)
throw new ArgumentException();
else
@@ -85,7 +85,7 @@ public partial class ArchiSteamFarmServiceImpl : ReactiveObject, IArchiSteamFarm
#region StartProcess
private async Task<(bool IsSuccess, string Message)> StartProcessAsync()
private async Task<(bool IsSuccess, string Message)> StartProcess()
{
var isStartSuccess = false;
var ipcUrl = string.Empty;
@@ -306,7 +306,7 @@ public partial class ArchiSteamFarmServiceImpl : ReactiveObject, IArchiSteamFarm
}
}
public async Task RestartAsync()
public async Task Restart()
{
Toast.Show(ToastIcon.Info, AppResources.ASF_Restarting, ToastLength.Short);
@@ -47,7 +47,7 @@ public sealed class ASFService : ReactiveObject
{
SteamBotsSourceList = new SourceCache<BotViewModel, string>(t => t.Bot.BotName);
archiSteamFarmService.OnConsoleWirteLine += OnConsoleWriteLine;
archiSteamFarmService.OnConsoleWirteLine += OnConsoleWirteLine;
ASFSettings.ConsoleMaxLine.Subscribe(x =>
{
@@ -58,9 +58,9 @@ public sealed class ASFService : ReactiveObject
});
}
void OnConsoleWriteLine(string message)
void OnConsoleWirteLine(string message)
{
MainThread2.BeginInvokeOnMainThread(() =>
MainThread2.InvokeOnMainThreadAsync(() =>
{
//ConsoleLogBuilder.Append(message); // message 包含换行
//var text = ConsoleLogBuilder.ToString();
@@ -74,7 +74,7 @@ public sealed class ASFService : ReactiveObject
{
return;
}
_ = archiSteamFarmService.ShellMessageInput(input);
archiSteamFarmService.ShellMessageInput(input);
}
/// <summary>
@@ -287,7 +287,7 @@ public sealed class ASFService : ReactiveObject
Toast.Show(ToastIcon.Success, string.Format(AppResources.LocalAuth_ImportSuccessTip_, num));
}
public async Task SelectASFProgramLocationAsync()
public async Task SelectASFProgramLocation()
{
AvaloniaFilePickerFileTypeFilter fileTypes = new AvaloniaFilePickerFileTypeFilter.Item[] {
new("ArchiSteamFarm") {
@@ -302,77 +302,5 @@ public sealed class ASFService : ReactiveObject
ASFSettings.ArchiSteamFarmExePath.Value = path;
}, fileTypes);
}
public async void DownloadASFAsync(string variant = "win-x64", IProgress<float>? progress = null, CancellationToken cancellationToken = default)
{
try
{
var assetName = $"{nameof(ASF)}-{variant}.zip";
using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", IHttpPlatformHelperService.Instance.UserAgent);
using var latestReleaseStream = await httpClient.GetStreamAsync("https://api.github.com/repos/JustArchiNET/ArchiSteamFarm/releases/latest", cancellationToken);
using var element = await JsonDocument.ParseAsync(latestReleaseStream, cancellationToken: cancellationToken);
if (element.RootElement.TryGetProperty("assets", out var assets) &&
assets.EnumerateArray().FirstOrDefault(s => s.GetProperty("name").ValueEquals(assetName))
.TryGetProperty("browser_download_url", out var downloadUrl))
{
var tag_name = element.RootElement.GetProperty("tag_name").GetString();
var downloadSavingPath = Path.Combine(Plugin.Instance.AppDataDirectory, $"ASF-{tag_name}", assetName);
var downloadSavingDir = Path.GetDirectoryName(downloadSavingPath)!;
Directory.CreateDirectory(downloadSavingDir);
var message = new HttpRequestMessage(HttpMethod.Get, downloadUrl.GetString());
var result = await httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
using var contentStream = await result.Content.ReadAsStreamAsync(cancellationToken);
byte batch = 0;
long readThisBatch = 0;
long batchIncreaseSize = result.Content.Headers.ContentLength.GetValueOrDefault() / 100;
await using (FileStream fileStream = new(downloadSavingPath, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true))
{
ArrayPool<byte> bytePool = ArrayPool<byte>.Shared;
byte[] buffer = bytePool.Rent(4096);
try
{
while (contentStream.CanRead)
{
int read = await contentStream.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken);
if (read == 0)
break;
await fileStream.WriteAsync(buffer.AsMemory(0, read), cancellationToken);
if ((progress == null) || (batchIncreaseSize == 0) || (batch >= 99))
{
continue;
}
readThisBatch += read;
while ((readThisBatch >= batchIncreaseSize) && (batch < 99))
{
readThisBatch -= batchIncreaseSize;
progress.Report(++batch);
}
}
}
finally
{
bytePool.Return(buffer);
}
}
ZipFile.ExtractToDirectory(downloadSavingPath, downloadSavingDir);
ASFSettings.ArchiSteamFarmExePath.Value = Path.Combine(downloadSavingDir, "ArchiSteamFarm.exe");
progress?.Report(100);
Toast.Show(ToastIcon.Success, "ASF 下载成功");
}
}
catch (Exception ex)
{
Toast.LogAndShowT(ex, "ASF 文件下载异常");
}
}
}
#endif
@@ -4,16 +4,8 @@ public partial class ArchiSteamFarmExePathSettingsPageViewModel : ViewModelBase
{
public ICommand SelectProgramPath { get; }
public ICommand DownloadASF { get; }
public ArchiSteamFarmExePathSettingsPageViewModel()
{
SelectProgramPath = ReactiveCommand.Create(ASFService.Current.SelectASFProgramLocationAsync);
DownloadASF = ReactiveCommand.Create(() =>
{
var progress = INotificationService.Instance.NotifyDownload(() => "开始下载 ASF ", NotificationType.NewVersion);
ASFService.Current.DownloadASFAsync(progress: progress);
Toast.Show(ToastIcon.Info, "等待后台下载文件", ToastLength.Short);
});
SelectProgramPath = ReactiveCommand.Create(ASFService.Current.SelectASFProgramLocation);
}
}
@@ -9,7 +9,7 @@ public sealed partial class ArchiSteamFarmPlusPageViewModel : ViewModelBase
public ArchiSteamFarmPlusPageViewModel()
{
SelectASFExePath = ReactiveCommand.CreateFromTask(ASFService.Current.SelectASFProgramLocationAsync);
SelectASFExePath = ReactiveCommand.CreateFromTask(ASFService.Current.SelectASFProgramLocation);
OpenWebUIConsole = ReactiveCommand.Create(() => ASFService.Current.OpenBrowser(null));
@@ -18,12 +18,12 @@ public sealed partial class ArchiSteamFarmPlusPageViewModel : ViewModelBase
RunOrStop = ReactiveCommand.Create(RunOrStopASF);
}
public override async void Activation()
public override void Activation()
{
base.Activation();
if (string.IsNullOrEmpty(ASFSettings.ArchiSteamFarmExePath.Value))
{
await MainThread2.InvokeOnMainThreadAsync(async () =>
MainThread2.InvokeOnMainThreadAsync(async () =>
{
var model = new ArchiSteamFarmExePathSettingsPageViewModel();
await IWindowManager.Instance.ShowTaskDialogAsync(model,
@@ -44,16 +44,7 @@ public sealed partial class ArchiSteamFarmPlusPageViewModel : ViewModelBase
StartOrStopASF_Click();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
ASFService.Current.StopASFAsync().Wait();
}
base.Dispose(disposing);
}
public void StartOrStopASF_Click(bool? startOrStop = null) => _ = Task.Run(async () =>
public static void StartOrStopASF_Click(bool? startOrStop = null) => Task.Run(async () =>
{
var s = ASFService.Current;
if (!s.IsASFRuning)
@@ -26,16 +26,5 @@
<Button Command="{Binding SelectProgramPath}" Content="选择路径" />
</ui:SettingsExpander.Footer>
</ui:SettingsExpander>
<ui:SettingsExpander
Description="下载并设置 ASF 路径"
Header="还没有下载过ASF?请点击下载"
IsClickEnabled="True">
<ui:SettingsExpander.IconSource>
<ui:FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE896;" />
</ui:SettingsExpander.IconSource>
<ui:SettingsExpander.Footer>
<Button Command="{Binding DownloadASF}" Content="一键下载" />
</ui:SettingsExpander.Footer>
</ui:SettingsExpander>
</StackPanel>
</UserControl>
@@ -63,6 +63,10 @@
</ItemGroup>
<ItemGroup>
<!--<PackageReference Include="Avalonia" />
<PackageReference Include="BD.Common.XmlnsDefinition.Avalonia">
<Aliases>BD_Common_XmlnsDefinition_Avalonia</Aliases>
</PackageReference>-->
<PackageReference Include="ReactiveUI.Fody" />
</ItemGroup>
@@ -26,8 +26,6 @@ public sealed partial class PlatformAccount : ReactiveObject
public bool IsRegDeleteOnClear { get; set; }
public bool AllFilesRequired { get; set; }
public string? ExeExtraArgs { get; set; }
public string? DefaultExePath { get; set; }
@@ -575,16 +575,14 @@ Windows Registry Editor Version 5.00
// FILE OR FOLDER
if (PathHelper.HandleFileOrFolder(accFile, savedFile, localCachePath, false, platform.FolderPath)) continue;
if (platform.AllFilesRequired)
{
// Could not find file/folder
Toast.Show(ToastIcon.Error, AppResources.Error_CannotFindAccountFile_.Format(accFile));
return false;
}
else
{
Log.Warn(nameof(CurrnetUserAdd), $"{accFile} Could not find file/folder");
}
// Could not find file/folder
Toast.Show(ToastIcon.Error, AppResources.Error_CannotFindAccountFile_.Format(accFile));
return false;
// TODO: Run some action that can be specified in the Platforms.json file
// Add for the start, and end of this function -- To allow 'plugins'?
// Use reflection?
}
JTokenHelper.SaveRegJson(regJson, platform.RegJsonPath(name));
@@ -46,7 +46,7 @@ public sealed class SteamPlatformSwitcher : IPlatformSwitcher
}
else
{
await ClearCurrentLoginUser(platform);
await steamService.SetSteamCurrentUserAsync(string.Empty);
foreach (var user in users)
{
user.MostRecent = false;
@@ -62,7 +62,7 @@ public sealed class SteamPlatformSwitcher : IPlatformSwitcher
return true;
}
public async ValueTask<bool> ClearCurrentLoginUser(PlatformAccount platform)
async ValueTask<bool> IPlatformSwitcher.ClearCurrentLoginUser(PlatformAccount platform)
{
await steamService.SetSteamCurrentUserAsync(string.Empty);
return true;
@@ -82,7 +82,6 @@ public sealed class SteamPlatformSwitcher : IPlatformSwitcher
public async ValueTask NewUserLogin(PlatformAccount platform)
{
await ClearCurrentLoginUser(platform);
await SwapToAccount(null, platform);
}
@@ -24,8 +24,7 @@
"BackupFileTypesIgnore": null,
"BackupFileTypesInclude": null,
"UniqueIdPath": "REG:HKCU\\Software\\Epic Games\\Unreal Engine\\Identifiers:AccountId",
"UniqueIdType": 2,
"AllFilesRequired": true
"UniqueIdType": 2
},
{
"FullName": "Ubisoft",
@@ -42,7 +41,6 @@
"%LocalAppData%\\Ubisoft Game Launcher\\user.dat": "user.dat"
},
"ClearPaths": [ "SAME_AS_LOGIN_FILES" ],
"ProfilePicPath": "%Platform_Folder%\\cache\\avatars\\%UniqueId%_256.png",
"CachePaths": [
"%Platform_Folder%\\cache\\achievements",
"%Platform_Folder%\\cache\\assets",
@@ -104,9 +102,8 @@
],
"ClearPaths": [ "SAME_AS_LOGIN_FILES" ],
"LoginFiles": {
"%LocalAppData%\\Riot Games\\Riot Client\\Data\\Cookies": "Cookies",
"%LocalAppData%\\Riot Games\\Riot Client\\Data\\Sessions": "Sessions",
"%LocalAppData%\\Riot Games\\Riot Client\\Data\\RiotClientPrivateSettings.yaml": "RiotClientPrivateSettings.yaml",
"%LocalAppData%\\Riot Games\\Riot Client\\Data\\Cookies\\": "Cookies",
"%LocalAppData%\\Riot Games\\Riot Client\\Data\\RiotGamesPrivateSettings.yaml": "RiotGamesPrivateSettings.yaml",
"%LocalAppData%\\Riot Games\\Riot Client\\Config\\RiotClientSettings.yaml": "RiotClientSettings.yaml",
"%LocalAppData%\\Riot Games\\Riot Client\\WattToolkit.id": "WattToolkit.id"
},
@@ -153,75 +150,6 @@
},
"IsExitBeforeInteract": true,
"UniqueIdPath": "%AppData%\\Battle.net\\Battle.net.config::$.Client.SavedAccountNames",
"UniqueIdType": 5,
"AllFilesRequired": true
},
{
"FullName": "GOG Galaxy",
"Icon": "GOGGalaxy",
"Platform": 64,
"PlatformIds": [ "g", "gog", "gog2" ],
"DefaultExePath": "%ProgramFiles(x86)%\\GOG Galaxy\\GalaxyClient.exe",
"ExesToEnd": [ "GalaxyClient.exe", "GOG Galaxy Notifications Renderer.exe", "GalaxyClientService.exe", "GalaxyCommunication.exe" ],
"ClearPaths": [ "SAME_AS_LOGIN_FILES" ],
"LoginFiles": {
"%LocalAppData%\\GOG.com\\Galaxy\\Configuration\\config.json": "LocalAppData\\config.json",
"REG:HKCU\\Software\\GOG.com\\Galaxy\\settings:username": "userId",
"REG:HKCU\\Software\\GOG.com\\Galaxy:refreshToken": "refreshToken",
"REG:HKCU\\Software\\GOG.com\\Galaxy\\settings:userId": "UNIQUE_ID",
"%ProgramData%\\GOG.com\\Galaxy\\webcache\\common\\Cache\\index": "ProgramData\\Cache\\index",
"%ProgramData%\\GOG.com\\Galaxy\\webcache\\common\\Cache\\data_*": "ProgramData\\Cache\\",
"%ProgramData%\\GOG.com\\Galaxy\\webcache\\common\\Code Cache\\js\\index-dir\\the-real-index": "ProgramData\\Code Cache\\js\\index-dir\\the-real-index",
"%ProgramData%\\GOG.com\\Galaxy\\webcache\\common\\GPUCache\\index": "ProgramData\\GPUCache\\index",
"%ProgramData%\\GOG.com\\Galaxy\\webcache\\common\\Local Storage\\leveldb": "ProgramData\\Local Storage\\leveldb\\",
"%ProgramData%\\GOG.com\\Galaxy\\webcache\\common\\Session Storage\\*.log": "ProgramData\\Session Storage\\",
"%ProgramData%\\GOG.com\\Galaxy\\webcache\\common\\Session Storage\\*.ldb": "ProgramData\\Session Storage\\",
"%ProgramData%\\GOG.com\\Galaxy\\webcache\\common\\Cookies": "ProgramData\\Cookies",
"%ProgramData%\\GOG.com\\Galaxy\\storage\\etags.db": "ProgramData\\storage\\etags.db",
"%ProgramData%\\GOG.com\\Galaxy\\storage\\galaxy-2.0.db*": "ProgramData\\storage\\",
"%ProgramData%\\GOG.com\\Galaxy\\config.json": "ProgramData\\config.json"
},
"ProfilePicPath": "%ProgramData%\\GOG.com\\Galaxy\\webcache\\%UniqueId%\\user\\%LARGEST%.jpg",
"CachePaths": [
"C:\\Program Files (x86)\\GOG Galaxy\\GPUCache",
"%ProgramData%\\GOG.com\\Galaxy\\webcache\\common\\Cache",
"%ProgramData%\\GOG.com\\Galaxy\\webcache\\common\\GPUCache"
],
"BackupPaths": [
"%LocalAppData%\\GOG.com\\Galaxy\\Configuration\\"
],
"UniqueIdFile": "HKCU\\Software\\GOG.com\\Galaxy\\settings:userId",
"UniqueIdType": 2
},
{
"FullName": "Discord",
"Icon": "Discord",
"Platform": 32768,
"PlatformIds": [ "d", "discord" ],
"DefaultExePath": "%LocalAppData%\\Discord\\Update.exe",
"ExeExtraArgs": "--processStart Discord.exe",
"ExesToEnd": [ "Discord.exe" ],
"PathListToClear": [ "SAME_AS_LOGIN_FILES" ],
"LoginFiles": {
"%AppData%\\discord\\settings.json": "settings.json",
"%AppData%\\discord\\Network Persistent State": "Network Persistent State",
"%AppData%\\discord\\Preferences": "Preferences",
"%AppData%\\discord\\TransportSecurity": "TransportSecurity",
"%AppData%\\discord\\Cache\\index": "Cache\\index",
"%AppData%\\discord\\Cache\\data_*": "Cache\\",
"%AppData%\\discord\\Code Cache\\js\\index-dir\\the-real-index": "Code Cache\\js\\index-dir\\the-real-index",
"%AppData%\\discord\\GPUCache\\index": "GPUCache\\index",
"%AppData%\\discord\\Local Storage\\leveldb": "Local Storage\\leveldb\\",
"%AppData%\\discord\\Session Storage\\*.log": "Session Storage\\",
"%AppData%\\discord\\Session Storage\\*.ldb": "Session Storage\\",
"%AppData%\\discord\\blob_storage": "blob_storage\\",
"%AppData%\\discord\\WattToolkit.id": "WattToolkit.id"
},
"IsExitBeforeInteract": true,
"CachePaths": [
"%AppData%\\discord\\Cache\\f_*"
],
"UniqueIdFile": "%AppData%\\discord\\WattToolkit.id",
"UniqueIdType": 1
"UniqueIdType": 5
}
]
]
@@ -94,11 +94,11 @@ public sealed partial class GameAccountPageViewModel
GamePlatforms?[0].LoadUsers();
var temp = GetSupportPlatforms();
if (temp != null && OperatingSystem2.IsWindows())
if (temp != null)
{
if (GameAccountSettings.EnablePlatforms.Any_Nullable())
{
AddGamePlatforms = [];
AddGamePlatforms = new ObservableCollection<PlatformAccount>();
foreach (var p in temp)
{
@@ -233,7 +233,6 @@ public sealed partial class GameListPageViewModel : TabItemViewModel
if (result.IsOK())
{
Toast.Show(ToastIcon.Info, Strings.GameList_RuningWait);
NavAppToSteamView(app);
app.StartSteamAppProcess(SteamAppRunType.UnlockAchievement);
SteamConnectService.Current.RuningSteamApps.TryAdd(app.AppId, app);
}
@@ -12,7 +12,6 @@
<None Remove="UI\Assets\CounterStrike.png" />
<None Remove="UI\Assets\CPU.png" />
<None Remove="UI\Assets\movecross.png" />
<None Remove="UI\Assets\movecross_hide.png" />
</ItemGroup>
<ItemGroup>
@@ -20,7 +19,6 @@
<AvaloniaResource Include="UI\Assets\CounterStrike.png" />
<AvaloniaResource Include="UI\Assets\CPU.png" />
<AvaloniaResource Include="UI\Assets\movecross.png" />
<AvaloniaResource Include="UI\Assets\movecross_hide.png" />
<AvaloniaResource Include="UI\Assets\toolbox.ico" />
</ItemGroup>
@@ -74,9 +72,6 @@
<Compile Include="..\ImplicitUsings.NLog.cs">
<LinkBase>Properties</LinkBase>
</Compile>
<Compile Include="..\ImplicitUsings.Steam.cs">
<LinkBase>Properties</LinkBase>
</Compile>
<Compile Include="..\ImplicitUsings.Plugins.cs">
<LinkBase>Properties</LinkBase>
</Compile>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

@@ -1,6 +1,5 @@
using Avalonia.Platform;
using BD.WTTS.UI.Views.Pages;
using static System.Net.Mime.MediaTypeNames;
namespace BD.WTTS.UI.ViewModels;
@@ -45,16 +44,7 @@ public sealed partial class BorderlessGamePageViewModel : ViewModelBase
public BorderlessGamePageViewModel()
{
}
public async void CopyGameInfo_Click()
{
var text = $"{Strings.GameRelated_Borderless_Title}: {SelectWindow!.Title}\n" +
$"{Strings.GameRelated_Borderless_Title}: {SelectWindow!.Title}\n" +
$"{Strings.GameRelated_Borderless_ClassName}: {SelectWindow!.Name}\n" +
$"{Strings.GameRelated_Borderless_Path}: {SelectWindow!.Path}";
await Clipboard2.SetTextAsync(text);
Toast.Show(ToastIcon.Success, Strings.CopyToClipboard);
}
public void Cross_MouseDown()
@@ -62,8 +52,7 @@ public sealed partial class BorderlessGamePageViewModel : ViewModelBase
windowApi.GetMoveMouseDownWindow((window) =>
{
SelectWindow = window;
if (window is not null)
WindowList.Insert(0, window);
WindowList.Insert(0, window);
});
}
@@ -1,5 +1,3 @@
using static System.Net.Mime.MediaTypeNames;
namespace BD.WTTS.UI.ViewModels;
public sealed partial class CsgoVacRepairPageViewModel : ViewModelBase
@@ -17,17 +15,55 @@ public sealed partial class CsgoVacRepairPageViewModel : ViewModelBase
#if WINDOWS
readonly ISteamService steamService = ISteamService.Instance;
string BatPath = Path.Combine(Plugin.Instance.AppDataDirectory, "BAT", $"CSGOVAC_REPAIR{FileEx.BAT}");
public async Task Repairs_Click()
public void Repairs_Click()
{
OutputString = string.Empty;
Task2.InBackground(async () =>
{
await ExcuteBat();
});
}
public async Task ExcuteBat()
{
try
{
if (!File.Exists(BatPath))
{
GenerateFixScript(BatPath);
}
Repairing = true;
var installPath = $"\"{Path.GetDirectoryName(steamService.SteamProgramPath)}\\bin\"";
await ExcuteBatCommand(installPath);
using var process = new Process
{
StartInfo =
{
FileName = BatPath,
RedirectStandardOutput = true,
RedirectStandardError = true,
StandardOutputEncoding = Encoding.UTF8,
StandardErrorEncoding = Encoding.UTF8,
UseShellExecute = false,
CreateNoWindow = true,
Arguments = $"\"{Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Valve\Steam", "SteamPath", null)}/bin\""
}
};
process.OutputDataReceived += (_, e) =>
{
OutHandle(e.Data);
};
process.ErrorDataReceived += (_, e) =>
{
OutHandle(e.Data);
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
await process.WaitForExitAsync();
}
finally
{
@@ -35,45 +71,7 @@ public sealed partial class CsgoVacRepairPageViewModel : ViewModelBase
}
}
public async Task ExcuteBatCommand(string arg)
{
OutputString = string.Empty;
if (!File.Exists(BatPath))
{
GenerateFixScript(BatPath);
}
using var p = new Process
{
StartInfo =
{
FileName = BatPath,
RedirectStandardOutput = true,
RedirectStandardError = true,
StandardOutputEncoding = Encoding.UTF8,
StandardErrorEncoding = Encoding.UTF8,
UseShellExecute = false,
CreateNoWindow = true,
Arguments = arg,
Verb = "runas",
}
};
p.Start();
_ = ConsumeReader(p.StandardOutput);
_ = ConsumeReader(p.StandardError);
await p.WaitForExitAsync();
}
async Task ConsumeReader(TextReader reader)
{
string? text;
while ((text = await reader.ReadLineAsync()) != null)
{
OutHandle(text);
}
}
void GenerateFixScript(string path)
static void GenerateFixScript(string path)
{
var dirPath = Path.GetDirectoryName(path);
if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath!);
@@ -82,22 +80,17 @@ public sealed partial class CsgoVacRepairPageViewModel : ViewModelBase
stream.Write("""
@echo off
chcp 65001
goto enableservice
:steam
echo Info - Checking if Steam is launched.
echo info - Checking if Steam is launched.
tasklist | find /I "Steam.exe"
if errorlevel 1 goto closedstatus
if not errorlevel 1 goto killsteam
:killsteam
taskkill /F /IM Steam.exe
goto steamrepair
goto steaminstall
:closedstatus
echo Info - Not Started
goto steamrepair
:enableservice
echo info - Not Started
goto steaminstall
sc config Netman start= AUTO
sc start Netman
sc config RasMan start= AUTO
@@ -108,28 +101,19 @@ public sealed partial class CsgoVacRepairPageViewModel : ViewModelBase
sc start MpsSvc
netsh advfirewall set allprofiles state on
goto steam
:steamrepair
echo Info - ※^>^>^> 执行修复启动器服务项
:steaminstall
echo info - ※^>^>^> 执行 Steam Services 修复中......
cd /d %1
steamservice /install
ping -n 2 127.0.0.1>nul
echo.
echo
steamservice /repair
ping -n 2 127.0.0.1>nul
echo Info - ※ 恢复DEP默认启动设置
bcdedit /deletevalue nointegritychecks
bcdedit /deletevalue loadoptions
echo info - ※ 开启数据执行保护
bcdedit /debug off
bcdedit /deletevalue nx
echo Info - ※^>^>^> 重启 Steam
cd /d ..
start /high steam
ping -n 2 127.0.0.1>nul
bcdedit.exe/set {current} nx alwayson
echo info - ※ 执行完毕
sc config "Steam Client Service" start= AUTO
sc start "Steam Client Service"
echo Info - ※ 执行完毕
exit
"""u8);
stream.Flush();
stream.SetLength(stream.Position);
@@ -139,7 +123,7 @@ public sealed partial class CsgoVacRepairPageViewModel : ViewModelBase
{
if (!string.IsNullOrEmpty(msg))
{
OutputString += msg + Environment.NewLine;
OutputString += $"{msg}\n";
if (msg.Contains("Add firewall exception failed for steamservice.exe", StringComparison.OrdinalIgnoreCase))
{
@@ -10,7 +10,7 @@
xmlns:spp="https://steampp.net/ui"
xmlns:ui="using:FluentAvalonia.UI.Controls"
Title="游戏无边框窗口化"
d:DesignHeight="850"
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True"
x:DataType="spp:BorderlessGamePageViewModel"
@@ -103,214 +103,102 @@
</StackPanel>
</spp:PageBase.PaneContent>
<ScrollViewer>
<StackPanel x:Name="Grid_Menu" MaxWidth="1000" Spacing="8">
<Border Padding="20" Classes="paper"
Height="180">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid HorizontalAlignment="Center" Grid.Column="0">
<Image
Width="64"
HorizontalAlignment="Left"
Source="avares://BD.WTTS.Client.Plugins.GameTools/UI/Assets/movecross_hide.png">
</Image>
<Image
x:Name="move"
Width="64"
HorizontalAlignment="Left"
Source="avares://BD.WTTS.Client.Plugins.GameTools/UI/Assets/movecross.png">
<i:Interaction.Behaviors>
<ia:EventTriggerBehavior EventName="PointerPressed" SourceObject="{Binding #move}">
<ia:InvokeCommandAction Command="{ReflectionBinding $parent[spp:PageBase].((spp:BorderlessGamePageViewModel)DataContext).Cross_MouseDown}" />
</ia:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Image>
</Grid>
<TextBlock Grid.Column="1"
Margin="10"
VerticalAlignment="Center"
Text="{Binding Path=Res.GameRelated_Borderless_MoveMouseTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
TextWrapping="WrapWithOverflow"/>
</Grid>
</Border>
<ScrollViewer Padding="10">
<StackPanel Spacing="20">
<WrapPanel HorizontalAlignment="Center">
<Image
x:Name="move"
Width="64"
HorizontalAlignment="Left"
Source="avares://BD.WTTS.Client.Plugins.GameTools/UI/Assets/movecross.png">
<i:Interaction.Behaviors>
<ia:EventTriggerBehavior EventName="PointerPressed" SourceObject="{Binding #move}">
<ia:InvokeCommandAction Command="{ReflectionBinding $parent[spp:PageBase].((spp:BorderlessGamePageViewModel)DataContext).Cross_MouseDown}" />
</ia:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Image>
<TextBlock
Margin="10,0"
VerticalAlignment="Center"
Text="{Binding Path=Res.GameRelated_Borderless_MoveMouseTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</WrapPanel>
<Expander IsExpanded="True">
<Expander.Styles>
<Style Selector="Expander /template/ ToggleButton#ExpanderHeader">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</Expander.Styles>
<Expander.Header>
<DockPanel>
<StackPanel Orientation="Horizontal" >
<ui:FontIcon FontSize="26" Margin="0 0 12 0" FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE946;" />
<TextBlock VerticalAlignment="Center" Text="窗口信息" />
<!--<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.SteamAppType_Game, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
<!--<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.Info, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
</StackPanel>
<Button DockPanel.Dock="Right" HorizontalAlignment="Right"
Width="100" Content="{Binding Path=Res.Copy, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Command="{ReflectionBinding CopyGameInfo_Click}"
IsEnabled="{ReflectionBinding !!SelectWindow}" />
</DockPanel>
</Expander.Header>
<StackPanel>
<Grid
HorizontalAlignment="Stretch"
ColumnDefinitions="Auto,*"
RowDefinitions="Auto,Auto,Auto,Auto">
<TextBlock VerticalAlignment="Top" Text="{Binding Path=Res.GameRelated_Borderless_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
<SelectableTextBlock
Grid.Column="1"
Margin="4,0,0,10"
Text="{ReflectionBinding SelectWindow.Title,
Mode=OneWay}"
TextWrapping="WrapWithOverflow"
Foreground="Gray" VerticalAlignment="Top" />
<Grid
HorizontalAlignment="Center"
ColumnDefinitions="Auto,*"
IsVisible="{ReflectionBinding !!SelectWindow}"
RowDefinitions="Auto,Auto,Auto,Auto">
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.GameRelated_Borderless_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
<TextBox
Grid.Column="1"
Margin="0,0,0,10"
IsReadOnly="True"
Text="{ReflectionBinding SelectWindow.Title,
Mode=OneWay}"
TextWrapping="WrapWithOverflow" />
<TextBlock
Grid.Row="1"
VerticalAlignment="Top"
Text="{Binding Path=Res.GameRelated_Borderless_Process, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
<SelectableTextBlock
Grid.Row="1"
Grid.Column="1"
Margin="4,0,0,10"
Text="{ReflectionBinding SelectWindow.Title,
Mode=OneWay}"
TextWrapping="WrapWithOverflow"
Foreground="Gray" VerticalAlignment="Top" />
<TextBlock
Grid.Row="1"
VerticalAlignment="Center"
Text="{Binding Path=Res.GameRelated_Borderless_Process, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
<TextBox
Grid.Row="1"
Grid.Column="1"
Margin="0,0,0,10"
IsReadOnly="True"
Text="{ReflectionBinding SelectWindow.Title,
Mode=OneWay}"
TextWrapping="WrapWithOverflow" />
<TextBlock
Grid.Row="2"
VerticalAlignment="Top"
Text="{Binding Path=Res.GameRelated_Borderless_ClassName, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
<SelectableTextBlock
Grid.Row="2"
Grid.Column="1"
Margin="4,0,0,10"
Text="{ReflectionBinding SelectWindow.Name,
Mode=OneWay}"
TextWrapping="WrapWithOverflow"
Foreground="Gray" VerticalAlignment="Top" />
<TextBlock
Grid.Row="2"
VerticalAlignment="Center"
Text="{Binding Path=Res.GameRelated_Borderless_ClassName, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
<TextBox
Grid.Row="2"
Grid.Column="1"
Margin="0,0,0,10"
IsReadOnly="True"
Text="{ReflectionBinding SelectWindow.Name,
Mode=OneWay}"
TextWrapping="WrapWithOverflow" />
<TextBlock
Grid.Row="3"
VerticalAlignment="Top"
Text="{Binding Path=Res.GameRelated_Borderless_Path, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
<SelectableTextBlock
Grid.Row="3"
Grid.Column="1"
Margin="4,0,0,10"
Text="{ReflectionBinding SelectWindow.Path,
Mode=OneWay}"
TextWrapping="WrapWithOverflow"
Foreground="Gray" VerticalAlignment="Top" />
</Grid>
<TextBlock
Grid.Row="3"
VerticalAlignment="Center"
Text="{Binding Path=Res.GameRelated_Borderless_Path, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
<TextBox
Grid.Row="3"
Grid.Column="1"
Margin="0,0,0,10"
IsReadOnly="True"
Text="{ReflectionBinding SelectWindow.Path,
Mode=OneWay}"
TextWrapping="WrapWithOverflow" />
</Grid>
<Border x:Name="ButtonGroup" Padding="4" Classes="paper" Margin="-16 16 -16 -16"
Height="200">
<WrapPanel HorizontalAlignment="Center" Orientation="Horizontal">
<WrapPanel.Styles>
<Style Selector="Button">
<Setter Property="Height" Value="30" />
<Setter Property="Margin" Value="8" />
<Setter Property="Width" Value="120" />
</Style>
</WrapPanel.Styles>
<WrapPanel HorizontalAlignment="Center" Orientation="Horizontal">
<WrapPanel.Styles>
<Style Selector="Button">
<Setter Property="Height" Value="30" />
<Setter Property="Margin" Value="3" />
</Style>
</WrapPanel.Styles>
<Button Command="{ReflectionBinding WindowKill_Click}" Content="{Binding Path=Res.GameRelated_Borderless_KillProcess, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<Button Command="{ReflectionBinding BorderlessWindow_Click}" Content="{Binding Path=Res.GameRelated_Borderless_BorderlessWindow, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<Button Command="{ReflectionBinding MaximizeWindow_Click}" Content="{Binding Path=Res.GameRelated_Borderless_Maximize, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<Button Command="{ReflectionBinding NormalWindow_Click}" Content="{Binding Path=Res.GameRelated_Borderless_Normal, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<Button Command="{ReflectionBinding HideWindow_Click}" Content="{Binding Path=Res.GameRelated_Borderless_Hide, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<Button Command="{ReflectionBinding ShowWindow_Click}" Content="{Binding Path=Res.GameRelated_Borderless_Show, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<Button
Command="{ReflectionBinding ToWallerpaperWindow_Click}"
Content="{Binding Path=Res.GameRelated_Borderless_ToWallerpaper, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
ToolTip.Tip="{Binding Path=Res.GameRelated_Borderless_ToWallerpaperTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<Button Command="{ReflectionBinding ResetWallerpaper_Click}" Content="{Binding Path=Res.GameRelated_Borderless_ResetWallerpaper, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</WrapPanel>
<!--Button Group 1-->
<Button Command="{ReflectionBinding BorderlessWindow_Click}" IsEnabled="{ReflectionBinding !!SelectWindow}">
<!--<Button.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="#0071c7" />
<Setter Property="Foreground" Value="White" />
</Style>
<Style Selector="Button:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="TextElement.Foreground" Value="White" />
<Setter Property="TextElement.Background" Value="#006abb" />
</Style>
<Style Selector="Button:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="#0062ae" />
</Style>
</Button.Styles>-->
<!--<TextBlock Text="{ReflectionBinding Path=Res.GameRelated_Borderless_ToWallerpaperTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat=*{0}}" TextWrapping="WrapWithOverflow" />-->
<StackPanel Orientation="Horizontal">
<ui:FontIcon Glyph="&#xf58a;" FontFamily="Segoe Fluent Icons" />
<TextBlock Text="{Binding Path=Res.GameRelated_Borderless_BorderlessWindow, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"/>
</StackPanel>
</Button>
<Button Command="{ReflectionBinding MaximizeWindow_Click}" IsEnabled="{ReflectionBinding !!SelectWindow}">
<StackPanel Orientation="Horizontal">
<ui:FontIcon Margin="0 0 4 0" FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE922;" />
<TextBlock Text="{Binding Path=Res.GameRelated_Borderless_Maximize, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"/>
</StackPanel>
</Button>
<Button Command="{ReflectionBinding NormalWindow_Click}" IsEnabled="{ReflectionBinding !!SelectWindow}">
<StackPanel Orientation="Horizontal">
<ui:FontIcon Margin="0 0 4 0" FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE923;" />
<TextBlock Text="{Binding Path=Res.GameRelated_Borderless_Normal, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"/>
</StackPanel>
</Button>
<!--Button Group 2-->
<Button Command="{ReflectionBinding HideWindow_Click}" IsEnabled="{ReflectionBinding !!SelectWindow}">
<StackPanel Orientation="Horizontal">
<ui:FontIcon Margin="0 0 4 0" FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xed1a;" />
<TextBlock Text="{Binding Path=Res.GameRelated_Borderless_Hide, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"/>
</StackPanel>
</Button>
<Button Command="{ReflectionBinding ShowWindow_Click}" IsEnabled="{ReflectionBinding !!SelectWindow}">
<StackPanel Orientation="Horizontal">
<ui:FontIcon Margin="0 0 4 0" FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xe7b3;" />
<TextBlock Text="{Binding Path=Res.GameRelated_Borderless_Show, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"/>
</StackPanel>
</Button>
<!--Button Group 3-->
<Button
Command="{ReflectionBinding ToWallerpaperWindow_Click}"
IsEnabled="{ReflectionBinding !!SelectWindow}"
ToolTip.Tip="{Binding Path=Res.GameRelated_Borderless_ToWallerpaperTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
<StackPanel Orientation="Horizontal">
<ui:FontIcon Margin="0 0 4 0" FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE718;" />
<TextBlock Text="{Binding Path=Res.GameRelated_Borderless_ToWallerpaper, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"/>
</StackPanel>
</Button>
<Button Command="{ReflectionBinding ResetWallerpaper_Click}" IsEnabled="{ReflectionBinding !!SelectWindow}">
<StackPanel Orientation="Horizontal">
<ui:FontIcon Margin="0 0 4 0" FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72C;" />
<TextBlock Text="{Binding Path=Res.GameRelated_Borderless_ResetWallerpaper, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"/>
</StackPanel>
</Button>
<Button Command="{ReflectionBinding WindowKill_Click}" IsEnabled="{ReflectionBinding !!SelectWindow}">
<Button.Styles>
<Style Selector="Button:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="TextElement.Foreground" Value="White" />
<Setter Property="TextElement.Background" Value="Red" />
</Style>
<Style Selector="Button:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="#f1707a" />
</Style>
</Button.Styles>
<StackPanel Orientation="Horizontal">
<ui:FontIcon Margin="0 0 4 0" FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE8BB;" />
<TextBlock Text="{Binding Path=Res.GameRelated_Borderless_KillProcess, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"/>
</StackPanel>
</Button>
</WrapPanel>
</Border>
</StackPanel>
</Expander>
</StackPanel>
<!--<TextBlock Text="{ReflectionBinding Path=Res.GameRelated_Borderless_ToWallerpaperTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat=*{0}}" TextWrapping="WrapWithOverflow" />-->
</StackPanel>
</ScrollViewer>
</spp:PageBase>
@@ -6,16 +6,5 @@ public partial class BorderlessGamePage : PageBase<BorderlessGamePageViewModel>
{
InitializeComponent();
DataContext ??= new BorderlessGamePageViewModel();
move.PointerPressed += (_, _) => move.IsVisible = false;
move.PointerReleased += (_, _) => move.IsVisible = true;
const int threeLineButtonWidth = 554;
const int fourLineButtonWidth = 418;
Observable.FromEventPattern<Avalonia.Controls.SizeChangedEventArgs>(ButtonGroup, nameof(ButtonGroup.SizeChanged))
.Select(eventPattern => eventPattern.EventArgs.NewSize.Width)
.Select(width => width < fourLineButtonWidth ? 200 : width < threeLineButtonWidth ? 150 : 100)
.DistinctUntilChanged()
.Subscribe(newHeight => ButtonGroup.Height = newHeight);
}
}
@@ -14,13 +14,13 @@
d:DesignWidth="800"
x:CompileBindings="True"
x:DataType="spp:CsgoVacRepairPageViewModel"
Description="该功能可为玩家修复 CS:GO VAC 屏蔽问题"
Description="该功能可以为玩家修复 CS:GO VAC 问题"
Subtitle="{Binding Author, Source={x:Static s:Plugin.Instance}, Mode=OneWay, Converter={StaticResource StringFormatConverter}, ConverterParameter=Plugin_Author}"
mc:Ignorable="d">
<spp:PageBase.PreviewImage>
<ui:ImageIconSource Source="avares://BD.WTTS.Client.Plugins.GameTools/UI/Assets/CounterStrike.png" />
</spp:PageBase.PreviewImage>
<spp:PageBase.ActionContent>
<spp:PageBase.PreviewImage>
<ui:ImageIconSource Source="avares://BD.WTTS.Client.Plugins.GameTools/UI/Assets/CounterStrike.png" />
</spp:PageBase.PreviewImage>
<spp:PageBase.ActionContent>
<StackPanel Orientation="Horizontal" Spacing="2">
<Button
Padding="8,4"
@@ -61,25 +61,6 @@
Text="修复中" />
</Panel>
</Button>
<!--<ToggleButton
Padding="8,4"
DockPanel.Dock="Right"
IsChecked="{Binding $parent[spp:PageBase].IsPaneOpen, Mode=TwoWay}"
Theme="{StaticResource TransparentButton}">
<Panel>
<Viewbox
Width="18"
Height="18"
HorizontalAlignment="Left">
<ui:FontIcon Glyph="&#xEA80;" />
</Viewbox>
<TextBlock
Margin="28,4,0,4"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="帮助" />
</Panel>
</ToggleButton>-->
<DropDownButton
Padding="8"
HorizontalContentAlignment="Center"
@@ -88,32 +69,32 @@
FontFamily="{StaticResource SymbolThemeFontFamily}"
FontSize="20"
Theme="{StaticResource TransparentButton}">
<DropDownButton.Flyout>
<ui:FAMenuFlyout Placement="BottomEdgeAlignedRight">
<!--<ui:MenuFlyoutItem x:Name="PluginSettingButton" Text="{Binding Path=Res.Settings_Plugin, Mode=OneWay,Source={x:Static s:ResourceService.Current}}" />
<DropDownButton.Flyout>
<ui:FAMenuFlyout Placement="BottomEdgeAlignedRight">
<!--<ui:MenuFlyoutItem x:Name="PluginSettingButton" Text="{Binding Path=Res.Settings_Plugin, Mode=OneWay,Source={x:Static s:ResourceService.Current}}" />
<ui:MenuFlyoutSeparator />-->
<ui:MenuFlyoutItem IsEnabled="False">
<ui:MenuFlyoutItem.Text>
<MultiBinding StringFormat="{}{0}{1}">
<CompiledBinding
<ui:MenuFlyoutItem IsEnabled="False">
<ui:MenuFlyoutItem.Text>
<MultiBinding StringFormat="{}{0}{1}">
<CompiledBinding
Mode="OneWay"
Path="Res.Plugin_Version"
Source="{x:Static s:ResourceService.Current}" />
<CompiledBinding
<CompiledBinding
Mode="OneWay"
Path="Version"
Source="{x:Static s:Plugin.Instance}" />
</MultiBinding>
</ui:MenuFlyoutItem.Text>
</ui:MenuFlyoutItem>
<!--<ui:MenuFlyoutItem Text="{Binding Path=Res.ViewInStore, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
<!--<ui:MenuFlyoutItem Text="{Binding Path=Res.UseHelp, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
<!--<ui:MenuFlyoutItem Text="{Binding Path=Res.AboutThisPlugin, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
</ui:FAMenuFlyout>
</DropDownButton.Flyout>
</DropDownButton>
</StackPanel>
</spp:PageBase.ActionContent>
</MultiBinding>
</ui:MenuFlyoutItem.Text>
</ui:MenuFlyoutItem>
<!--<ui:MenuFlyoutItem Text="{Binding Path=Res.ViewInStore, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<ui:MenuFlyoutItem Text="{Binding Path=Res.UseHelp, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<ui:MenuFlyoutItem Text="{Binding Path=Res.AboutThisPlugin, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
</ui:FAMenuFlyout>
</DropDownButton.Flyout>
</DropDownButton>
</StackPanel>
</spp:PageBase.ActionContent>
<Panel>
<Border Background="{DynamicResource CardBackgroundFillColorDefaultBrush}" CornerRadius="{DynamicResource ControlCornerRadius}">
<Grid RowDefinitions="*,Auto">
@@ -124,59 +105,11 @@
Text="{Binding OutputString}"
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>
<!--<spp:PageBase.PaneContent>
<StackPanel Margin="10,10" Spacing="10">
<TextBlock FontWeight="Bold" FontSize="13" Text ="其他 VAC 修复方式"/>
<spp:OptionsDisplayItem Description="" Header="验证游戏完整性">
<spp:OptionsDisplayItem.Icon>
<ui:FontIcon FontFamily="Segoe Fluent Icons" Glyph="&#xF156;" />
</spp:OptionsDisplayItem.Icon>
</spp:OptionsDisplayItem>
<spp:OptionsDisplayItem Header="关闭冲突软件">
<spp:OptionsDisplayItem.Icon>
<ui:FontIcon FontFamily="Segoe Fluent Icons" Glyph="&#xF167;" />
</spp:OptionsDisplayItem.Icon>
<spp:OptionsDisplayItem.ActionButton>
<Button Command="{ReflectionBinding CloseConflictApp_Click}" Content="关闭" />
</spp:OptionsDisplayItem.ActionButton>
</spp:OptionsDisplayItem>
<spp:OptionsDisplayItem Header="管理员启动Steam">
<spp:OptionsDisplayItem.Icon>
<ui:FontIcon FontFamily="Segoe Fluent Icons" Glyph="&#xEF58;" />
</spp:OptionsDisplayItem.Icon>
<spp:OptionsDisplayItem.ActionButton>
<Button Command="{ReflectionBinding AdminStartup_Click}" Content="启动" />
</spp:OptionsDisplayItem.ActionButton>
</spp:OptionsDisplayItem>
<spp:OptionsDisplayItem Header="重启电脑">
<spp:OptionsDisplayItem.Icon>
<ui:FontIcon FontFamily="Segoe Fluent Icons" Glyph="&#xE7ad;" />
</spp:OptionsDisplayItem.Icon>
<spp:OptionsDisplayItem.ActionButton>
<Button Command="{ReflectionBinding ResetComputer_Click}" Content="重启" />
</spp:OptionsDisplayItem.ActionButton>
</spp:OptionsDisplayItem>
<spp:OptionsDisplayItem Header="修复系统文件">
<spp:OptionsDisplayItem.Icon>
<ui:FontIcon FontFamily="Segoe Fluent Icons" Glyph="&#xE705;" />
</spp:OptionsDisplayItem.Icon>
<spp:OptionsDisplayItem.ActionButton>
<Button Command="{ReflectionBinding RepairSystemFiles_Click}" Content="执行" />
</spp:OptionsDisplayItem.ActionButton>
</spp:OptionsDisplayItem>
<TextBlock FontWeight="Bold" FontSize="13" Text ="其他异常处理"/>
<spp:OptionsDisplayItem Header="闪退">
<spp:OptionsDisplayItem.Icon>
<ui:FontIcon FontFamily="Segoe Fluent Icons" Glyph="&#xea91;" />
</spp:OptionsDisplayItem.Icon>
<spp:OptionsDisplayItem.ActionButton>
<Button Content="修复" />
</spp:OptionsDisplayItem.ActionButton>
</spp:OptionsDisplayItem>
</StackPanel>
</spp:PageBase.PaneContent>-->
</spp:PageBase>
</spp:PageBase>
@@ -1,3 +1,6 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace BD.WTTS.UI.Views.Pages;
public partial class CsgoVacRepairPage : PageBase<CsgoVacRepairPageViewModel>
@@ -1,8 +0,0 @@
{
"profiles": {
"WSL": {
"commandName": "WSL2",
"distributionName": ""
}
}
}
@@ -122,16 +122,11 @@
<PackageReference Include="Squid-Box.SevenZipSharp.Lite" />
<PackageReference Include="SharpZipLib" />
<PackageReference Include="ZstdNet" />
<!--<PackageReference Include="BsDiff" />-->
<PackageReference Include="7-Zip.NativeAssets.Win32" />
<PackageReference Include="Portable.BouncyCastle" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ref\WTTS.MicroServices.ClientSDK\src\BD.WTTS.MicroServices.ClientSDK\BD.WTTS.MicroServices.ClientSDK.csproj" />
</ItemGroup>
<Import Project="..\TFM_NETX.props" />
</Project>
@@ -1,492 +0,0 @@
//using BsDiff;
//using JsonSerializer = System.Text.Json.JsonSerializer;
//using BD.WTTS.Models;
//namespace BD.WTTS.Client.Tools.Publish.Commands;
//interface IGenerateBsPatch : ICommand
//{
// const string commandName = "bs";
// const string BaseUrl =
//#if DEBUG
// "https://localhost:9881";
//#else
// "http://192.168.2.16:19001";
//#endif
// static Command ICommand.GetCommand()
// {
// var type = new Option<int>("--type", "type 0:Create 1:Apply 2:UploadFile 3:传入版本号生成补丁");
// //旧文件
// var oldFile = new Option<string>("--old", "old file");
// //新文件
// var newFile = new Option<string>("--new", "new file");
// //保存路径
// var patchFile = new Option<string>("--path", "new file");
// //程序版本号
// var clientPlatform = new Option<ClientPlatform>("--platform", "ClientPlatform");
// var command = new Command(commandName, "Bridge csproj xml generate")
// {
// type, oldFile, newFile, patchFile, clientPlatform
// };
// command.SetHandler(Handler, type, oldFile, newFile, patchFile, clientPlatform);
// return command;
// }
// internal static void Handler(int type, string oldFile, string newFile, string patchFile, ClientPlatform platform = ClientPlatform.Win32X64)
// {
// if (type < 2)
// {
// if (!File.Exists(oldFile))
// {
// Console.WriteLine("old file not exists");
// return;
// }
// if (!File.Exists(newFile))
// {
// Console.WriteLine("new file not exists");
// return;
// }
// if (string.IsNullOrWhiteSpace(patchFile))
// {
// Console.WriteLine("The patch file path cannot be empty");
// return;
// }
// }
// switch (type)
// {
// case 0:
// using (var output = new FileStream(patchFile, FileMode.Create))
// GenerateBsPatch(File.ReadAllBytes(oldFile), File.ReadAllBytes(newFile), output);
// break;
// case 1:
// using (var input = new FileStream(oldFile, FileMode.Open, FileAccess.Read, FileShare.Read))
// using (var output = new FileStream(newFile, FileMode.Create))
// BinaryPatch.Apply(input, () => new FileStream(patchFile, FileMode.Open, FileAccess.Read, FileShare.Read), output);
// break;
// case 2:
// UploadFiles(oldFile).Wait();
// break;
// case 3:
// GenerateAppPublishPatchBundleInfo(oldFile, newFile, platform, patchFile).Wait();
// break;
// case 4:
// UploadAppVer(oldFile, newFile, platform).Wait();
// break;
// case 5:
// ApplyPatch(oldFile, newFile, patchFile).Wait();
// break;
// }
// Console.WriteLine("end");
// }
// /// <summary>
// /// 应用补丁
// /// </summary>
// /// <param name="applyPath"></param>
// /// <param name="saveFilePath"></param>
// /// <param name="patchPath"></param>
// /// <returns></returns>
// internal static async ThreadTask ApplyPatch(string applyPath, string saveFilePath, string patchPath)
// {
// if (!File.Exists(patchPath))
// {
// Console.WriteLine("PatchPath not exists");
// return;
// }
// if (!Directory.Exists(applyPath))
// {
// Console.WriteLine("ApplyPath not exists");
// return;
// }
// var fileStream = File.OpenRead(patchPath);
// var jsonData = new BrotliStream(fileStream, CompressionMode.Decompress);
// var dic = await MemoryPackSerializer.DeserializeAsync<Dictionary<string, PatchBundleInfo?>>(jsonData);
// if (dic is null)
// {
// Console.WriteLine("Patch Error");
// return;
// }
// if (!Directory.Exists(saveFilePath))
// {
// Directory.CreateDirectory(saveFilePath);
// }
// else
// {
// Directory.Delete(saveFilePath);
// }
// CopyDirectory(applyPath, saveFilePath);
// FileInfo? fileInfo = null;
// foreach (var item in dic.Where(x => x.Value is not null))
// {
// PatchBundleInfo info = item.Value!;
// if (info.PatchData is not null)
// {
// fileInfo = new FileInfo(Path.Combine(saveFilePath, item.Key));
// if (!(fileInfo.Directory?.Exists ?? false))
// fileInfo.Directory?.Create();
// if (info.IsFullOrPatch)
// {
// File.WriteAllBytes(Path.Combine(saveFilePath, item.Key), info.PatchData);
// }
// else
// {
// using var oldFile = File.OpenRead(Path.Combine(applyPath, item.Key));
// var newFile = Path.Combine(saveFilePath, item.Key);
// using var saveFile = File.Exists(newFile) ? File.Create(newFile) : File.OpenWrite(newFile);
// BinaryPatch.Apply(oldFile, () => new MemoryStream(info.PatchData), saveFile);
// }
// }
// }
// Console.WriteLine("ApplyPatch OK");
// }
// /// <summary>
// /// 复制目录下的文件
// /// </summary>
// /// <param name="sourceDir"></param>
// /// <param name="targetDir"></param>
// /// <exception cref="DirectoryNotFoundException"></exception>
// public static void CopyDirectory(string sourceDir, string targetDir)
// {
// DirectoryInfo dir = new DirectoryInfo(sourceDir);
// DirectoryInfo[] dirs = dir.GetDirectories();
// // If the source directory does not exist, throw an exception.
// if (!dir.Exists)
// {
// throw new DirectoryNotFoundException($"Source directory does not exist or could not be found: {sourceDir}");
// }
// // If the destination directory does not exist, create it.
// if (!Directory.Exists(targetDir))
// {
// Directory.CreateDirectory(targetDir);
// }
// // Get the files in the directory and copy them to the new location.
// FileInfo[] files = dir.GetFiles();
// foreach (FileInfo file in files)
// {
// string tempPath = Path.Combine(targetDir, file.Name);
// file.CopyTo(tempPath, false);
// }
// // If copying subdirectories, copy them and their contents to the new location.
// foreach (DirectoryInfo subdir in dirs)
// {
// string tempPath = Path.Combine(targetDir, subdir.Name);
// CopyDirectory(subdir.FullName, tempPath);
// }
// }
// /// <summary>
// /// 根据 2个 文件生成补丁
// /// </summary>
// /// <param name="oldByte"></param>
// /// <param name="newByte"></param>
// /// <param name="output"></param>
// internal static void GenerateBsPatch(byte[] oldByte, byte[] newByte, Stream output)
// {
// BinaryPatch.Create(oldByte, newByte, output);
// }
// /// <summary>
// /// 上传版本信息 加 FileList
// /// </summary>
// /// <param name="appVer"></param>
// /// <param name="jsonPath">发布工具生成的 Json</param>
// /// <param name="platform"></param>
// /// <returns></returns>
// internal static async ThreadTask UploadAppVer(string appVer, string jsonPath, ClientPlatform platform)
// {
// if (string.IsNullOrWhiteSpace(appVer))
// {
// Console.WriteLine("AppVer not exists");
// return;
// }
// if (string.IsNullOrWhiteSpace(jsonPath))
// {
// Console.WriteLine("jsonPath not exists");
// return;
// }
// if (!File.Exists(jsonPath))
// {
// Console.WriteLine("jsonPath not Find");
// return;
// }
// var fileListRaw = File.ReadAllBytes(jsonPath);
// var appver = await GetAppVer(appVer);
// if (appver is not null)
// {
// var thisFileList = appver.FileList?.FirstOrDefault(x => x.Platform == platform);
// if (thisFileList is not null)
// {
// if (Hashs.String.SHA384(thisFileList.FileListRaw) != Hashs.String.SHA384(fileListRaw))
// {
// thisFileList.FileListRaw = fileListRaw;
// }
// }
// else
// {
// if (appver.FileList is null)
// {
// appver.FileList = new List<AppVerFileList>
// {
// new AppVerFileList
// {
// Platform = platform,
// FileListRaw = fileListRaw
// }
// };
// }
// else
// {
// appver.FileList.Add(new AppVerFileList
// {
// Platform = platform,
// FileListRaw = fileListRaw
// });
// }
// }
// await UploadAppVer(appver);
// }
// else
// {
// appver = new AppVer
// {
// Platform = platform,
// Ver = appVer,
// Published = DateTimeOffset.Now,
// FileList = new List<AppVerFileList>
// {
// new AppVerFileList
// {
// Platform = platform,
// FileListRaw = fileListRaw
// }
// }
// };
// await UploadAppVer(appver);
// }
// }
// /// <summary>
// /// 上传版本信息
// /// </summary>
// /// <param name="appVer"></param>
// /// <returns></returns>
// internal static async ThreadTask UploadAppVer(AppVer appVer)
// {
// using var httpClient = new HttpClient();
// var content = JsonContent.Create(appVer);
// var response = await httpClient.PostAsync($"{BaseUrl}/appver/", content);
// }
// /// <summary>
// /// 传入 2 个版本号生成补丁
// /// </summary>
// /// <param name="oldVer"></param>
// /// <param name="newVer"></param>
// /// <param name="platform"></param>
// /// <param name="patchFilePath"></param>
// /// <returns></returns>
// internal static async ThreadTask GenerateAppPublishPatchBundleInfo(string oldVer, string newVer, ClientPlatform platform, string patchFilePath)
// {
// var oldAppVer = await GetAppVer(oldVer);
// var newAppVer = await GetAppVer(newVer);
// if (oldAppVer is null || newAppVer is null)
// {
// Console.WriteLine("AppVer not exists");
// return;
// }
// var oldFileList = await GetAppPublishInfo(oldAppVer.Id, platform);
// var newFileList = await GetAppPublishInfo(newAppVer.Id, platform);
// if (oldFileList is null || newFileList is null)
// {
// Console.WriteLine("AppPublishInfo not exists");
// return;
// }
// var oldAppVerFileList = JsonSerializer.Deserialize<AppPublishInfo>(oldFileList.FileListRaw);
// var newAppVerFileList = JsonSerializer.Deserialize<AppPublishInfo>(newFileList.FileListRaw);
// if (oldAppVerFileList is null || newAppVerFileList is null)
// {
// Console.WriteLine("AppPublishInfo not exists");
// return;
// }
// var pathSavePath = Path.Combine(patchFilePath, oldVer, $"{newVer}.dat");
// var pathFileInfo = new FileInfo(pathSavePath);
// if (!(pathFileInfo.Directory?.Exists ?? false))
// {
// pathFileInfo.Directory?.Create();
// }
// Console.WriteLine($"开始生成: {oldVer} -> {newVer} platform:{platform}");
// await ContrastVersion(oldAppVerFileList, newAppVerFileList, pathSavePath);
// }
// /// <summary>
// /// 获取版本号信息
// /// </summary>
// /// <param name="ver"></param>
// /// <returns></returns>
// public static async Task<AppVer?> GetAppVer(string ver)
// {
// using var httpClient = new HttpClient();
// var response = await httpClient.GetAsync($"{BaseUrl}/appver/{ver}");
// var data = JsonSerializer.Deserialize<ApiRsp<AppVer?>>(await response.Content.ReadAsStringAsync(), new JsonSerializerOptions
// {
// PropertyNameCaseInsensitive = true
// });
// return data?.Content;
// }
// /// <summary>
// /// 更具 APP 版本 ID 获取发布信息
// /// </summary>
// /// <param name="appVerId">版本号</param>
// /// <param name="platform">平台</param>
// /// <returns></returns>
// public static async Task<AppVerFileList?> GetAppPublishInfo(Guid appVerId, ClientPlatform platform)
// {
// using var httpClient = new HttpClient();
// var response = await httpClient.GetAsync($"{BaseUrl}/appver/file/{appVerId}/{platform}/list");
// var data = JsonSerializer.Deserialize<ApiRsp<AppVerFileList?>>(await response.Content.ReadAsStringAsync(), new JsonSerializerOptions
// {
// PropertyNameCaseInsensitive = true
// });
// return data?.Content;
// }
// /// <summary>
// /// 根据 2 个版本的文件列表生成补丁
// /// </summary>
// /// <param name="oldFileList"></param>
// /// <param name="newFileList"></param>
// /// <param name="patchFilePath"></param>
// /// <returns></returns>
// public static async ThreadTask ContrastVersion(AppPublishInfo oldFileList, AppPublishInfo newFileList, string patchFilePath)
// {
// var oldFiles = oldFileList.Files.Where(x => !x.RelativePath.StartsWith("dotnet\\"));
// var newFiles = newFileList.Files.Where(x => !x.RelativePath.StartsWith("dotnet\\"));
// Console.WriteLine($"旧版本文件数:{oldFiles.Count()}");
// Console.WriteLine($"新版本文件数:{newFiles.Count()}");
// var changeList = new Dictionary<string, PatchBundleInfo?>();
// var removeFiles = oldFiles.Select(x => x.RelativePath).Except(newFiles.Select(x => x.RelativePath));
// //文件删除
// foreach (var item in removeFiles)
// {
// changeList.Add(item, null);
// }
// Console.WriteLine($"需要删除的文件数:{changeList.Count}");
// foreach (var item in newFiles)
// {
// var oldFile = oldFiles.FirstOrDefault(x => x.RelativePath.Equals(item.RelativePath));
// //文件新增
// if (oldFile == null)
// {
// var newFileRaw = string.IsNullOrWhiteSpace(item.SignatureSHA384) ? await GetFileRaw(item.SHA384) : await GetFileRaw(item.SignatureSHA384);
// if (newFileRaw is null)
// {
// Console.WriteLine("new file not exists");
// return;
// }
// changeList.Add(item.RelativePath, new PatchBundleInfo
// {
// SHA384 = item.SHA384,
// IsFullOrPatch = true,
// PatchData = newFileRaw.DataRaw
// });
// }
// else
// {
// //文件修改
// if (oldFile.SHA384 != item.SHA384)
// {
// var oldFileRaw = string.IsNullOrWhiteSpace(oldFile.SignatureSHA384) ? await GetFileRaw(oldFile.SHA384) : await GetFileRaw(oldFile.SignatureSHA384);
// if (oldFileRaw is null)
// {
// Console.WriteLine("old file not exists");
// return;
// }
// var newFileRaw = string.IsNullOrWhiteSpace(item.SignatureSHA384) ? await GetFileRaw(item.SHA384) : await GetFileRaw(item.SignatureSHA384); // await GetFileRaw(item.SignatureSHA384);
// if (newFileRaw is null)
// {
// Console.WriteLine("new file not exists");
// return;
// }
// using (var output = new MemoryStream())
// {
// //BinaryPatch.Create(oldFileRaw.DataRaw, File.ReadAllBytes(item.RelativePath), output);
// BinaryPatch.Create(oldFileRaw.DataRaw, newFileRaw.DataRaw, output);
// changeList.Add(item.RelativePath, new PatchBundleInfo
// {
// SHA384 = item.SHA384,
// IsFullOrPatch = false,
// PatchData = output.ToArray()
// });
// }
// }
// }
// }
// if (File.Exists(patchFilePath))
// File.Delete(patchFilePath);
// Console.WriteLine($"变动文件数量:{changeList.Count}");
// using var fileStream = File.OpenWrite(patchFilePath);
// using var brSave = new BrotliStream(fileStream, CompressionLevel.SmallestSize);
// Console.WriteLine($"开始压缩");
// await MemoryPackSerializer.SerializeAsync(typeof(Dictionary<string, PatchBundleInfo?>), brSave, changeList);
// //fileStream.Flush();
// Console.WriteLine($"结束");
// }
// /// <summary>
// /// Hash 384 获取源文件数据
// /// </summary>
// /// <param name="sha384"></param>
// /// <returns></returns>
// public static async Task<AppVerFile?> GetFileRaw(string sha384)
// {
// using var httpClient = new HttpClient();
// var response = await httpClient.GetAsync($"{BaseUrl}/appver/file/{sha384}");
// var data = JsonSerializer.Deserialize<ApiRsp<AppVerFile?>>(await response.Content.ReadAsStringAsync(), new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
// return data?.Content;
// }
// /// <summary>
// /// 上传指定文件到服务器
// /// </summary>
// /// <param name="directoryPath">需要上传的目录</param>
// internal static async ThreadTask UploadFiles(string directoryPath)
// {
// DirectoryInfo directoryInfo = new(directoryPath);
// if (directoryInfo.Exists)
// {
// using var httpClient = new HttpClient();
// var fileList = new List<AppPublishFileInfo>();
// IScanPublicDirectoryCommand.ScanPathCore(directoryPath, fileList, null, null);
// using var form = new MultipartFormDataContent();
// fileList.ForEach(file =>
// {
// var fileStream = file.FileInfo!.OpenRead();
// form.Add(new StreamContent(fileStream), file.FileInfo!.Name, file.FileInfo!.Name);
// });
// if (form.Count() > 0)
// {
// var response = await httpClient.PostAsync($"{BaseUrl}/appver/file/upload", form);
// Console.WriteLine(response);
// }
// }
// else
// {
// Console.WriteLine("文件夹不存在");
// }
// }
//}
@@ -1,47 +0,0 @@
namespace BD.WTTS.Client.Tools.Publish.Models;
/// <summary>
/// 程序发布【修补包】信息
/// </summary>
[MP2Obj(SerializeLayout.Explicit)]
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public sealed partial class AppPublishPatchBundleInfo
{
string DebuggerDisplay() => $"{OldAppVer}-{NewAppVer} {SHA384} {IOPath.GetDisplayFileSizeString(Length)}";
/// <summary>
/// 当前包适用程序版本
/// </summary>
[MP2Key(0)]
public string OldAppVer { get; set; } = string.Empty;
/// <summary>
/// 当前包适用程序版本
/// </summary>
[MP2Key(1)]
public string NewAppVer { get; set; } = string.Empty;
/// <summary>
/// 修补包 SHA384 值
/// </summary>
[MP2Key(2)]
public string SHA384 { get; set; } = string.Empty;
/// <summary>
/// 修补包文件大小
/// </summary>
[MP2Key(3)]
public long Length { get; set; }
/// <summary>
/// 修补包文件路径
/// </summary>
[MP2Key(4)]
public string FilePath { get; set; } = string.Empty;
/// <summary>
/// 修补包数据 (文件相对路径,包信息 为 null 删除文件) 不存在其中的文件全量复制
/// </summary>
[MP2Key(5)]
public Dictionary<string, PatchBundleInfo?> PatchData { get; set; } = new();
}
@@ -1,23 +0,0 @@
namespace BD.WTTS.Client.Tools.Publish.Models;
public sealed class AppVer
{
public Guid Id { get; set; }
/// <summary>
/// 版本号
/// </summary>
public string Ver { get; set; } = "";
/// <summary>
/// 发布时间
/// </summary>
public DateTimeOffset Published { get; set; }
/// <summary>
/// 支持的平台
/// </summary>
public ClientPlatform Platform { get; set; }
public IList<AppVerFileList>? FileList { get; set; }
}
@@ -1,26 +0,0 @@
namespace BD.WTTS.Client.Tools.Publish.Models;
public sealed class AppVerFile
{
public Guid Id { get; set; }
/// <summary>
/// 文件 Hash
/// </summary>
public string SHA384 { get; set; } = "";
/// <summary>
/// 发布时间
/// </summary>
public DateTimeOffset Published { get; set; }
/// <summary>
/// 文件原始 Byte 数据
/// </summary>
public byte[] DataRaw { get; set; } = Array.Empty<byte>();
/// <summary>
/// 文件大小
/// </summary>
public long Length { get; set; }
}
@@ -1,23 +0,0 @@
namespace BD.WTTS.Client.Tools.Publish.Models;
public sealed class AppVerFileList
{
public Guid Id { get; set; }
/// <summary>
/// 版本号ID
/// </summary>
public Guid AppVerId { get; set; }
/// <summary>
/// 平台
/// </summary>
public ClientPlatform Platform { get; set; }
/// <summary>
/// 文件清单列表
/// </summary>
public byte[] FileListRaw { get; set; } = Array.Empty<byte>();
public AppVer? AppVerInfo { get; set; }
}
@@ -1,27 +0,0 @@
namespace BD.WTTS.Client.Tools.Publish.Models;
/// <summary>
/// 修补包信息
/// </summary>
[MP2Obj(SerializeLayout.Explicit)]
public sealed partial class PatchBundleInfo
{
/// <summary>
/// 文件修补完后SHA384
/// </summary>
[MP2Key(0)]
public string? SHA384 { get; set; }
/// <summary>
/// 补丁包数据
/// </summary>
[MP2Key(1)]
public byte[]? PatchData { get; set; }
/// <summary>
/// 是否全量或补丁
/// </summary>
[MP2Key(2)]
public bool IsFullOrPatch { get; set; }
}
@@ -6,91 +6,7 @@
"commandLineArgs_release": "run --rids win-x64 --hsm-sign --stm-upload",
"commandLineArgs_nsis": "nsis --rids win-x64 --hsm-sign --t 240314_1523131679333",
"commandLineArgs_debug": "run --rids win-x64 --hsm-sign --stm-upload --debug",
"commandLineArgs_GenerateBridgeContentXml": "csproj --rids win-x64",
"commandLineArgs_TestUploadFile": "bs --type 2 --old \"C:\\Users\\Mossimo\\Desktop\\Steam++\\ms-test.steampp.net\""
},
"BD.WTTS.Client.Tools.Publish(TestUploadRc1)": {
"commandName": "Project",
"commandLineArgs": "bs --type 2 --old \"D:\\BuildTest\\rc1\""
},
"BD.WTTS.Client.Tools.Publish(TestUploadRc2)": {
"commandName": "Project",
"commandLineArgs": "bs --type 2 --old \"D:\\BuildTest\\rc2\""
},
"BD.WTTS.Client.Tools.Publish(TestUploadRc4)": {
"commandName": "Project",
"commandLineArgs": "bs --type 2 --old \"D:\\BuildTest\\rc4\""
},
"BD.WTTS.Client.Tools.Publish(TestUploadRc5)": {
"commandName": "Project",
"commandLineArgs": "bs --type 2 --old \"D:\\BuildTest\\rc5\""
},
"BD.WTTS.Client.Tools.Publish(AppVer.Rc1)": {
"commandName": "Project",
"commandLineArgs": "bs --type 4 --old 3.0.107.0 --new \"D:\\BuildTest\\rc1.json\" --platform 2"
},
"BD.WTTS.Client.Tools.Publish(AppVer.Rc2)": {
"commandName": "Project",
"commandLineArgs": "bs --type 4 --old 3.0.207.0 --new \"D:\\BuildTest\\rc2.json\" --platform 2"
},
"BD.WTTS.Client.Tools.Publish(AppVer.Rc4)": {
"commandName": "Project",
"commandLineArgs": "bs --type 4 --old 3.0.407.0 --new \"D:\\BuildTest\\rc4.json\" --platform 2"
},
"BD.WTTS.Client.Tools.Publish(AppVer.Rc5)": {
"commandName": "Project",
"commandLineArgs": "bs --type 4 --old 3.0.507.0 --new \"D:\\BuildTest\\rc5.json\" --platform 2"
},
"GenerateAppPublishPatchBundleInfo(rc1-rc2)": {
"commandName": "Project",
"commandLineArgs": "bs --type 3 --old 3.0.107.0 --new 3.0.207.0 --platform 2 --path \"D:\\BuildTest\""
},
"GenerateAppPublishPatchBundleInfo(rc1-rc4)": {
"commandName": "Project",
"commandLineArgs": "bs --type 3 --old 3.0.107.0 --new 3.0.407.0 --platform 2 --path \"D:\\BuildTest\""
},
"GenerateAppPublishPatchBundleInfo(rc1-rc5)": {
"commandName": "Project",
"commandLineArgs": "bs --type 3 --old 3.0.107.0 --new 3.0.507.0 --platform 2 --path \"D:\\BuildTest\""
},
"GenerateAppPublishPatchBundleInfo(rc2-rc4)": {
"commandName": "Project",
"commandLineArgs": "bs --type 3 --old 3.0.207.0 --new 3.0.407.0 --platform 2 --path \"D:\\BuildTest\""
},
"GenerateAppPublishPatchBundleInfo(rc2-rc5)": {
"commandName": "Project",
"commandLineArgs": "bs --type 3 --old 3.0.207.0 --new 3.0.507.0 --platform 2 --path \"D:\\BuildTest\""
},
"GenerateAppPublishPatchBundleInfo(rc4-rc5)": {
"commandName": "Project",
"commandLineArgs": "bs --type 3 --old 3.0.407.0 --new 3.0.507.0 --platform 2 --path \"D:\\BuildTest\""
},
"ApplyPatch(rc1-rc2)": {
"commandName": "Project",
"commandLineArgs": "bs --type 5 --old \"D:\\BuildTest\\rc1\" --new \"D:\\BuildTest\\pacth\\rc1-rc2\" --path \"D:\\BuildTest\\3.0.107.0\\3.0.207.0.dat\""
},
"ApplyPatch(rc1-rc2-rc4)": {
"commandName": "Project",
"commandLineArgs": "bs --type 5 --old \"D:\\BuildTest\\pacth\\rc1-rc2\" --new \"D:\\BuildTest\\pacth\\rc1-rc2-rc4\" --path \"D:\\BuildTest\\3.0.207.0\\3.0.407.0.dat\""
},
"ApplyPatch(rc1-rc2-rc4-rc5)": {
"commandName": "Project",
"commandLineArgs": "bs --type 5 --old \"D:\\BuildTest\\pacth\\rc1-rc2-rc4\" --new \"D:\\BuildTest\\pacth\\rc1-rc2-rc4-rc5\" --path \"D:\\BuildTest\\3.0.407.0\\3.0.507.0.dat\""
},
"ApplyPatch(rc1-rc5)": {
"commandName": "Project",
"commandLineArgs": "bs --type 5 --old \"D:\\BuildTest\\rc1\" --new \"D:\\BuildTest\\pacth\\rc1-rc5\" --path \"D:\\BuildTest\\3.0.107.0\\3.0.507.0.dat\""
},
"ApplyPatch(rc2-rc5)": {
"commandName": "Project",
"commandLineArgs": "bs --type 5 --old \"D:\\BuildTest\\rc2\" --new \"D:\\BuildTest\\pacth\\rc2-rc5\" --path \"D:\\BuildTest\\3.0.207.0\\3.0.507.0.dat\""
},
"ApplyPatch(rc4-rc5)": {
"commandName": "Project",
"commandLineArgs": "bs --type 5 --old \"D:\\BuildTest\\rc4\" --new \"D:\\BuildTest\\pacth\\rc4-rc5\" --path \"D:\\BuildTest\\3.0.407.0\\3.0.507.0.dat\""
"commandLineArgs_GenerateBridgeContentXml": "csproj --rids win-x64"
}
}
}

Some files were not shown because too many files have changed in this diff Show More