Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f171c740c | ||
|
|
83de4dacb9 | ||
|
|
719bd1e08f | ||
|
|
08655eb0c1 | ||
|
|
a886b21b79 | ||
|
|
27f113dce3 | ||
|
|
a4adbac8d5 | ||
|
|
6356d98a0c | ||
|
|
a1ba6f22fb | ||
|
|
2a9e3bc455 | ||
|
|
d768bcfe7b | ||
|
|
b5d8cd1a55 | ||
|
|
fdd8c5f0bc | ||
|
|
b5439743d1 | ||
|
|
a1de4f50a7 | ||
|
|
3b266ba614 | ||
|
|
3405117e86 | ||
|
|
5bd21d4474 | ||
|
|
4bd049d94a | ||
|
|
15a2b7f42a | ||
|
|
d6c88ac361 | ||
|
|
f1c58637aa | ||
|
|
fa5b21a2f9 | ||
|
|
2894227048 |
@@ -171,7 +171,7 @@
|
||||
{
|
||||
"TypeName": "string",
|
||||
"PropertyName": "WindowBackgroundCustomImagePath",
|
||||
"DefaultValue": "\"/UI/Assets/back.png\"",
|
||||
"DefaultValue": "\"avares://BD.WTTS.Client.Avalonia/UI/Assets/back.png\"",
|
||||
"DefaultValueIsConst": true,
|
||||
"Summary": "自定义背景图像路径",
|
||||
"IsRegionOrEndregion": null,
|
||||
@@ -265,6 +265,15 @@
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
},
|
||||
{
|
||||
"TypeName": "bool",
|
||||
"PropertyName": "MessagePopupNotification",
|
||||
"DefaultValue": "true",
|
||||
"DefaultValueIsConst": true,
|
||||
"Summary": "启用消息推送通知",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
},
|
||||
{
|
||||
"TypeName": "bool",
|
||||
"PropertyName": "GameListUseLocalCache",
|
||||
|
||||
@@ -14,7 +14,7 @@ public static partial class AssemblyInfo
|
||||
/// <summary>
|
||||
/// 预览版本号,范围 1~9
|
||||
/// </summary>
|
||||
const string ver_for_preview = "1";
|
||||
const string ver_for_preview = "2";
|
||||
|
||||
/// <summary>
|
||||
/// RC 版本号,范围 0~9
|
||||
@@ -29,14 +29,19 @@ public static partial class AssemblyInfo
|
||||
|
||||
#if !APP_HOST
|
||||
/// <summary>
|
||||
/// 当前应用程序是否为预览版本
|
||||
/// 当前应用程序是否为预览版本(Preview)
|
||||
/// </summary>
|
||||
public static bool IsPreview => InformationalVersion.Contains("preview", StringComparison.OrdinalIgnoreCase);
|
||||
public static bool IsPreview { get; } = InformationalVersion.Contains("preview", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// 当前应用程序是否为候选版本
|
||||
/// 当前应用程序是否为候选版本(RC)
|
||||
/// </summary>
|
||||
public static bool IsReleaseCandidate => !IsPreview && InformationalVersion.Contains("rc", StringComparison.OrdinalIgnoreCase);
|
||||
public static bool IsReleaseCandidate { get; } = !IsPreview && InformationalVersion.Contains("rc", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// 当前应用程序是否为正式版本(GA)
|
||||
/// </summary>
|
||||
public static bool IsGeneralAvailability { get; } = !IsPreview && !IsReleaseCandidate;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -104,6 +104,9 @@ sealed partial class Program : Startup
|
||||
services.AddSingleton<IApplication>(s => s.GetRequiredService<App>());
|
||||
|
||||
services.TryAddAvaloniaFilePickerPlatformService();
|
||||
#if LINUX
|
||||
services.AddSingleton<IClipboardPlatformService, AvaloniaClipboardPlatformService>();
|
||||
#endif
|
||||
|
||||
#region WindowManager
|
||||
|
||||
|
||||
@@ -36,7 +36,10 @@ public sealed class OnPlatformExtension : MarkupExtension<bool>
|
||||
"DesktopBridge" => DesktopBridge.IsRunningAsUwp,
|
||||
"SteamApp" => Startup.Instance.IsSteamRun,
|
||||
"OfficialRelease" => !(Startup.Instance.IsSteamRun || DesktopBridge.IsRunningAsUwp),
|
||||
"Preview" => AssemblyInfo.InformationalVersion.Contains("preview", StringComparison.OrdinalIgnoreCase),
|
||||
"Preview" => AssemblyInfo.IsPreview,
|
||||
"RC" => AssemblyInfo.IsReleaseCandidate,
|
||||
"GA" => AssemblyInfo.IsGeneralAvailability,
|
||||
"!GA" => !AssemblyInfo.IsGeneralAvailability,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
@@ -92,7 +92,8 @@ sealed class AvaloniaWindowManagerImpl : IWindowManagerImpl
|
||||
string? okButtonText = null,
|
||||
string? retryButtonText = null,
|
||||
string? moreInfoText = null,
|
||||
Func<bool>? cancelCloseAction = null)
|
||||
Func<bool>? cancelCloseAction = null,
|
||||
bool disableScroll = false)
|
||||
where TPageViewModel : ViewModelBase
|
||||
{
|
||||
var td = new TaskDialogEx
|
||||
@@ -143,6 +144,10 @@ sealed class AvaloniaWindowManagerImpl : IWindowManagerImpl
|
||||
{
|
||||
td.Buttons.Add(new TaskDialogButton(Strings.Cancel, TaskDialogStandardResult.Cancel));
|
||||
}
|
||||
if (disableScroll)
|
||||
{
|
||||
td.Classes.Add("disableScroll");
|
||||
}
|
||||
//td.DataTemplates.Add(new FuncDataTemplate<DebugPageViewModel>((x, _) => new DebugPage(), true));
|
||||
|
||||
object? result = null;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#if LINUX
|
||||
namespace BD.WTTS.Services.Implementation;
|
||||
|
||||
public sealed class AvaloniaClipboardPlatformService : IClipboardPlatformService
|
||||
{
|
||||
public bool PlatformHasText => !string.IsNullOrEmpty(PlatformGetTextAsync().GetAwaiter().GetResult());
|
||||
|
||||
public async Task<string> PlatformGetTextAsync()
|
||||
{
|
||||
TopLevel? topLevel = App.Instance.MainWindow;
|
||||
if (topLevel != null)
|
||||
{
|
||||
var clipboard = topLevel.Clipboard;
|
||||
if (clipboard != null)
|
||||
{
|
||||
var result = await clipboard.GetTextAsync();
|
||||
return result ?? string.Empty;
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public async Task PlatformSetTextAsync(string text)
|
||||
{
|
||||
TopLevel? topLevel = App.Instance.MainWindow;
|
||||
if (topLevel != null)
|
||||
{
|
||||
var clipboard = topLevel.Clipboard;
|
||||
if (clipboard != null)
|
||||
{
|
||||
await clipboard.SetTextAsync(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -50,13 +50,24 @@ public sealed class NavigationService : INavigationService
|
||||
_overlayHost = p;
|
||||
}
|
||||
|
||||
public void Navigate(Type t, NavigationTransitionEffect effect = NavigationTransitionEffect.None)
|
||||
public void Navigate(Type? t, NavigationTransitionEffect effect = NavigationTransitionEffect.None)
|
||||
{
|
||||
if (t == null)
|
||||
{
|
||||
_frame?.Navigate(typeof(ErrorPage), null, GetNavigationTransitionInfo(effect));
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.IsSubclassOf(typeof(ViewModelBase)))
|
||||
{
|
||||
var pageType = GetViewModelToPageContent(t, false);
|
||||
if (pageType == null) return;
|
||||
t = (Type)pageType;
|
||||
t = pageType as Type;
|
||||
}
|
||||
|
||||
if (t == null)
|
||||
{
|
||||
_frame?.Navigate(typeof(ErrorPage), null, GetNavigationTransitionInfo(effect));
|
||||
return;
|
||||
}
|
||||
|
||||
if (_frame?.Content?.GetType() != t)
|
||||
|
||||
@@ -127,7 +127,6 @@ public sealed partial class App : Application
|
||||
{
|
||||
MainThread2.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
IPCMainProcessService.Instance.DisposeAsync();
|
||||
desktop.Shutdown(exitCode);
|
||||
});
|
||||
return true;
|
||||
|
||||
@@ -385,6 +385,147 @@
|
||||
|
||||
</Style>
|
||||
|
||||
<Style Selector="^.disableScroll">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Panel Name="LayoutRoot" Background="{x:Null}">
|
||||
<ui:FABorder
|
||||
Name="ContentRoot"
|
||||
MinWidth="{DynamicResource TaskDialogMinWidth}"
|
||||
MinHeight="{DynamicResource TaskDialogMinHeight}"
|
||||
MaxWidth="{DynamicResource TaskDialogMaxWidth}"
|
||||
MaxHeight="{DynamicResource TaskDialogMaxHeight}"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="{TemplateBinding Background}">
|
||||
<Grid RowDefinitions="Auto,Auto,*,Auto">
|
||||
<Panel
|
||||
Name="HeaderHost"
|
||||
Grid.Row="0"
|
||||
Background="{TemplateBinding HeaderBackground}"
|
||||
IsVisible="False">
|
||||
<Viewbox
|
||||
Name="IconHost"
|
||||
Width="{StaticResource TaskDialogIconSize}"
|
||||
Height="{StaticResource TaskDialogIconSize}"
|
||||
Margin="{DynamicResource TaskDialogIconMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="False">
|
||||
<ui:IconSourceElement Name="IconElement" IconSource="{TemplateBinding IconSource}" />
|
||||
</Viewbox>
|
||||
<TextBlock
|
||||
Name="HeaderText"
|
||||
Margin="{DynamicResource TaskDialogHeaderPadding}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="{DynamicResource TaskDialogHeaderFontSize}"
|
||||
FontWeight="{StaticResource TaskDialogHeaderFontWeight}"
|
||||
IsVisible="False"
|
||||
Text="{TemplateBinding Header}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<Button
|
||||
Name="CloseButton"
|
||||
Margin="0,0,12,0"
|
||||
HorizontalAlignment="Right"
|
||||
Classes="Close"
|
||||
Content="{StaticResource Close}"
|
||||
Focusable="True"
|
||||
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||
IsTabStop="True"
|
||||
Theme="{StaticResource FA_SystemCaptionButton}" />
|
||||
</Panel>
|
||||
|
||||
<TextBlock
|
||||
Name="SubHeaderText"
|
||||
Grid.Row="1"
|
||||
Margin="{DynamicResource TaskDialogSubHeaderPadding}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="{StaticResource TaskDialogSubHeaderFontSize}"
|
||||
FontWeight="{StaticResource TaskDialogSubHeaderFontWeight}"
|
||||
IsVisible="False"
|
||||
Text="{TemplateBinding SubHeader}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<DockPanel Grid.Row="2" Margin="{StaticResource TaskDialogContentMargin}">
|
||||
<ContentPresenter
|
||||
Name="ContentPresenter"
|
||||
Grid.Row="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}">
|
||||
<ContentPresenter.Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
</Style>
|
||||
</ContentPresenter.Styles>
|
||||
</ContentPresenter>
|
||||
|
||||
<StackPanel DockPanel.Dock="Bottom" Spacing="18">
|
||||
<ProgressBar
|
||||
Name="ProgressBar"
|
||||
Grid.Row="3"
|
||||
IsVisible="False" />
|
||||
|
||||
<ItemsControl
|
||||
Name="CommandsHost"
|
||||
Grid.Row="4"
|
||||
IsVisible="{Binding !!$self.ItemCount}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Spacing="2" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
|
||||
<StackPanel
|
||||
Name="MoreDetailsPanel"
|
||||
Grid.Row="5"
|
||||
IsVisible="False">
|
||||
<Button
|
||||
Name="MoreDetailsButton"
|
||||
Classes="TaskDialog_MoreDetails"
|
||||
Content="{x:Static spp:Strings.MoreInfo}"
|
||||
IsVisible="False"
|
||||
Theme="{StaticResource TaskDialogMoreDetailsButton}" />
|
||||
<ContentPresenter
|
||||
Name="FooterHost"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Top"
|
||||
Content="{TemplateBinding Footer}"
|
||||
ContentTemplate="{TemplateBinding FooterTemplate}"
|
||||
IsVisible="False" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
|
||||
<Border
|
||||
Name="ButtonBorder"
|
||||
Grid.Row="3"
|
||||
Padding="{StaticResource TaskDialogButtonHostMargin}"
|
||||
Background="{DynamicResource TaskDialogButtonAreaBackground}"
|
||||
IsVisible="{Binding !!#ButtonsHost.ItemCount}">
|
||||
<ItemsControl Name="ButtonsHost" KeyboardNavigation.TabNavigation="Continue">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<uip:TaskDialogButtonsPanel Spacing="8" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ui:FABorder>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
<Border Background="{TemplateBinding Background}" IsHitTestVisible="False" />
|
||||
<Panel Name="WindowBackground" IsHitTestVisible="False">
|
||||
<Border Background="{DynamicResource SolidBackgroundFillColorBaseBrush}" Opacity="{Binding Value, Source={x:Static ms:UISettings.WindowBackgroundOpacity}, Mode=OneWay}" />
|
||||
<Image
|
||||
<spp:Image2
|
||||
IsVisible="{Binding Source={x:Static ms:UISettings.WindowBackgroundCustomImage}, Path=Value, Mode=OneWay}"
|
||||
Opacity="{Binding Value, Source={x:Static ms:UISettings.WindowBackgroundCustomImageOpacity}, Mode=OneWay}"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
|
||||
@@ -19,6 +19,24 @@ public class ReactiveAppWindow<TViewModel> : AppWindow, IViewFor<TViewModel>, IV
|
||||
/// </summary>
|
||||
public ReactiveAppWindow() : base()
|
||||
{
|
||||
#if WINDOWS
|
||||
if (OperatingSystem2.IsWindows() && !Design.IsDesignMode)
|
||||
{
|
||||
if (!GeneralSettings.GPU.Value)
|
||||
{
|
||||
var hWND = this.TryGetPlatformHandle()?.Handle;
|
||||
if (hWND != null)
|
||||
IPlatformService.Instance.BeautifyTheWindow(hWND.Value);
|
||||
}
|
||||
else if (UISettings.WindowBackgroundMaterial.Value is WindowBackgroundMaterial.None or WindowBackgroundMaterial.Blur)
|
||||
{
|
||||
var hWND = this.TryGetPlatformHandle()?.Handle;
|
||||
if (hWND != null)
|
||||
IPlatformService.Instance.BeautifyTheWindow(hWND.Value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// This WhenActivated block calls ViewModel's WhenActivated
|
||||
// block if the ViewModel implements IActivatableViewModel.
|
||||
this.WhenActivated(disposables => { });
|
||||
@@ -46,14 +64,6 @@ public class ReactiveAppWindow<TViewModel> : AppWindow, IViewFor<TViewModel>, IV
|
||||
}
|
||||
}
|
||||
|
||||
//this.GetObservable(TransparencyLevelHintProperty)
|
||||
// .Subscribe(x =>
|
||||
// {
|
||||
// PseudoClasses.Set(":transparent", TransparencyLevelHint == WindowTransparencyLevel.Mica ||
|
||||
// TransparencyLevelHint == WindowTransparencyLevel.Blur ||
|
||||
// TransparencyLevelHint == WindowTransparencyLevel.AcrylicBlur);
|
||||
// });
|
||||
|
||||
//UISettings.EnableCustomBackgroundImage.ValueChanged += (sender, e) =>
|
||||
//{
|
||||
// PseudoClasses.Set(":image", e.NewValue);
|
||||
|
||||
@@ -48,12 +48,6 @@ public class ContentLoader : ContentControl
|
||||
public static readonly StyledProperty<bool> IsShowNoResultTextProperty =
|
||||
AvaloniaProperty.Register<ContentLoader, bool>(nameof(IsShowNoResultText), false);
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="ItemsSource"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<IEnumerable?> ItemsSourceProperty =
|
||||
ItemsControl.ItemsSourceProperty.AddOwner<ContentLoader>();
|
||||
|
||||
/// <summary>
|
||||
/// 是否正在加载中
|
||||
/// </summary>
|
||||
@@ -105,12 +99,6 @@ public class ContentLoader : ContentControl
|
||||
set => SetValue(MaximumProperty, value);
|
||||
}
|
||||
|
||||
public IEnumerable? ItemsSource
|
||||
{
|
||||
get => GetValue(ItemsSourceProperty);
|
||||
set => SetValue(ItemsSourceProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
@@ -130,36 +118,12 @@ public class ContentLoader : ContentControl
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e.Property == IsLoadingProperty)
|
||||
else if (e.Property == IsLoadingProperty || e.Property == IsShowNoResultTextProperty)
|
||||
{
|
||||
if (IsLoading && IsShowNoResultText)
|
||||
{
|
||||
IsShowNoResultText = false;
|
||||
}
|
||||
}
|
||||
else if (e.Property == ItemsSourceProperty)
|
||||
{
|
||||
var items = e.GetNewValue<IEnumerable?>();
|
||||
if (items == null)
|
||||
{
|
||||
IsLoading = true;
|
||||
IsShowNoResultText = false;
|
||||
}
|
||||
else if (items.Count() == 0)
|
||||
{
|
||||
IsLoading = false;
|
||||
IsShowNoResultText = true;
|
||||
}
|
||||
else if (items.Count() != 0)
|
||||
{
|
||||
IsLoading = false;
|
||||
IsShowNoResultText = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsLoading = true;
|
||||
IsShowNoResultText = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,8 +77,8 @@
|
||||
VerticalAlignment="Top"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
IsVisible="{spp:OnPlatform Preview}"
|
||||
Message="当前使用的程序版本为预览版本,可能会有各种各样不可言明的 Bug,遇到问题请理性反馈,谢谢。"
|
||||
IsVisible="{spp:OnPlatform !GA}"
|
||||
Message="当前使用的程序版本为测试版本,可能会有各种各样不可言明的 Bug,遇到问题请理性反馈,谢谢。"
|
||||
Severity="Warning" />
|
||||
<spp:Snackbar
|
||||
Title="{Binding Path=Res.Notice_Tray_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
@@ -268,6 +268,7 @@
|
||||
</DockPanel>
|
||||
|
||||
<ScrollViewer
|
||||
Name="ShopsScrollViewer"
|
||||
Margin="0,3,0,20"
|
||||
Padding="0,0,0,15"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
@@ -334,7 +335,66 @@
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
|
||||
<TextBlock Text="联系我们" Theme="{StaticResource TitleTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Margin="-2,0,0,0"
|
||||
Text="已安装功能"
|
||||
Theme="{StaticResource TitleTextBlockStyle}" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding MainWindow2.TabItems, Mode=OneWay, Source={x:Static s:IViewModelManager.Instance}}">
|
||||
<ItemsControl.Resources>
|
||||
<ControlTheme
|
||||
x:Key="NavButtonStyle"
|
||||
BasedOn="{StaticResource {x:Type Button}}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Width" Value="120" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Margin" Value="6" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
||||
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="ClipToBounds" Value="True" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ItemsControl.Resources>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="spp:TabItemViewModel">
|
||||
<Border spp:Animations.EnableAnimations="True">
|
||||
<Button
|
||||
Command="{Binding $parent[spp:HomePage].((spp:HomePageViewModel)DataContext).NavgationToMenuPageCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Theme="{StaticResource NavButtonStyle}">
|
||||
<Grid RowDefinitions="3*,*">
|
||||
<Border
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
CornerRadius="4 4 0 0"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality">
|
||||
<spp:Image2
|
||||
Width="96"
|
||||
Height="96"
|
||||
Margin="0,10,0,0"
|
||||
Source="{Binding IconKey}"
|
||||
Stretch="Uniform" />
|
||||
</Border>
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="12"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding Name}" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<!--<TextBlock Text="联系我们" Theme="{StaticResource TitleTextBlockStyle}" />
|
||||
|
||||
<Grid Margin="0,0,0,20" ColumnDefinitions="*,10,*,10,*,10,*,10,*">
|
||||
<spp:AppItem
|
||||
@@ -387,7 +447,7 @@
|
||||
</Border>
|
||||
</spp:AppItem.Image>
|
||||
</spp:AppItem>
|
||||
</Grid>
|
||||
</Grid>-->
|
||||
|
||||
</StackPanel>
|
||||
|
||||
|
||||
@@ -9,8 +9,34 @@ public partial class HomePage : ReactiveUserControl<HomePageViewModel>
|
||||
InitializeComponent();
|
||||
this.SetViewModel<HomePageViewModel>();
|
||||
|
||||
//Subtitle = "11111111111111111111111111111";
|
||||
//Description = "2222222222222222222222222222222";
|
||||
//ContentDescription = "This is a description";
|
||||
ShopsScrollViewer.PointerWheelChanged += ShopsScrollViewer_PointerWheelChanged;
|
||||
}
|
||||
|
||||
private void ShopsScrollViewer_PointerWheelChanged(object? sender, PointerWheelEventArgs e)
|
||||
{
|
||||
if (sender is ScrollViewer scroll)
|
||||
if (scroll.IsPointerOver)
|
||||
if (scroll.Extent.Height > scroll.Viewport.Height || scroll.Extent.Width > scroll.Viewport.Width)
|
||||
{
|
||||
var delta = e.Delta;
|
||||
|
||||
var isScrollStart = scroll.Offset.X == 0;
|
||||
var isScrollEnd = scroll.Offset.X + scroll.Bounds.Size.Width >= scroll.Extent.Width;
|
||||
if (isScrollStart && MathUtilities.IsOne(e.Delta.Y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (isScrollEnd && e.Delta.Y == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (MathUtilities.IsZero(delta.X))
|
||||
{
|
||||
var horizontalOffset = scroll.Offset.X;
|
||||
horizontalOffset -= delta.Y * 50; // 根据事件参数来调整滚动的距离
|
||||
scroll.Offset = new Vector(horizontalOffset, scroll.Offset.Y);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
Height="40"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Command="{Binding Path=MarkNotificationsHasRead, Mode=OneWay, Source={x:Static s:NotificationService.Current}}"
|
||||
Command="{Binding Path=MarkNotificationsHasRead, Mode=OneWay, Source={x:Static s:NoticeService.Current}}"
|
||||
Theme="{DynamicResource TransparentButton}">
|
||||
<Panel>
|
||||
<ui:InfoBadge
|
||||
@@ -143,7 +143,7 @@
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Classes="Attention Dot"
|
||||
IsVisible="{Binding Path=!!UnreadNotificationsCount, Mode=OneWay, Source={x:Static s:NotificationService.Current}}" />
|
||||
IsVisible="{Binding Path=!!UnreadNotificationsCount, Mode=OneWay, Source={x:Static s:NoticeService.Current}}" />
|
||||
<Viewbox
|
||||
Width="22"
|
||||
Height="22"
|
||||
@@ -155,7 +155,7 @@
|
||||
<DropDownButton.Flyout>
|
||||
<!--<ui:FAMenuFlyout
|
||||
FlyoutPresenterClasses="NoPadding"
|
||||
ItemsSource="{Binding Path=Notices, Mode=OneWay, Source={x:Static s:NotificationService.Current}}"
|
||||
ItemsSource="{Binding Path=Notices, Mode=OneWay, Source={x:Static s:NoticeService.Current}}"
|
||||
Placement="BottomEdgeAlignedRight">
|
||||
<ui:FAMenuFlyout.ItemTemplate>
|
||||
<DataTemplate DataType="spp:OfficialMessageItemDTO">
|
||||
|
||||
@@ -72,6 +72,15 @@
|
||||
</spp:OptionsDisplayItem.ActionButton>
|
||||
</spp:OptionsDisplayItem>
|
||||
|
||||
<spp:OptionsDisplayItem Header="启用消息推送通知">
|
||||
<spp:OptionsDisplayItem.Icon>
|
||||
<ui:FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="" />
|
||||
</spp:OptionsDisplayItem.Icon>
|
||||
<spp:OptionsDisplayItem.ActionButton>
|
||||
<ToggleSwitch Classes="LeftContent" IsChecked="{Binding Source={x:Static ms:GeneralSettings.MessagePopupNotification}, Path=Value, Mode=TwoWay}" />
|
||||
</spp:OptionsDisplayItem.ActionButton>
|
||||
</spp:OptionsDisplayItem>
|
||||
|
||||
<ui:SettingsExpander
|
||||
Header="{Binding Path=Res.Settings_General_StorageSpace, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
IconSource="Globe"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding Path=!!!Notices.Count, Mode=OneWay, Source={x:Static s:NotificationService.Current}}"
|
||||
IsVisible="{Binding Path=!!!Notices.Count, Mode=OneWay, Source={x:Static s:NoticeService.Current}}"
|
||||
Text="当前没有通知消息"
|
||||
Theme="{StaticResource BodyStrongTextBlockStyle}" />
|
||||
<DockPanel>
|
||||
@@ -25,7 +25,7 @@
|
||||
Cursor="Hand"
|
||||
DockPanel.Dock="Top"
|
||||
Theme="{StaticResource HyperlinkButton}" />-->
|
||||
<ItemsControl ItemsSource="{Binding Path=Notices, Mode=OneWay, Source={x:Static s:NotificationService.Current}}">
|
||||
<ItemsControl ItemsSource="{Binding Path=Notices, Mode=OneWay, Source={x:Static s:NoticeService.Current}}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Spacing="3" />
|
||||
|
||||
@@ -41,7 +41,7 @@ public sealed partial class MainWindow : ReactiveAppWindow<MainWindowViewModel>
|
||||
Task2.InBackground(async () =>
|
||||
{
|
||||
await AdvertiseService.Current.RefrshAdvertiseAsync();
|
||||
NotificationService.Current.GetNewsAsync();
|
||||
NoticeService.Current.GetNewsAsync();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@ public sealed class AppSplashScreen : IApplicationSplashScreen
|
||||
});
|
||||
|
||||
AdvertiseService.Current.InitAdvertise();
|
||||
NotificationService.Current.GetNewsAsync();
|
||||
NoticeService.Current.GetNewsAsync();
|
||||
|
||||
var mainWindow = App.Instance.MainWindow;
|
||||
mainWindow.ThrowIsNull();
|
||||
@@ -195,6 +195,7 @@ public sealed class AppSplashScreen : IApplicationSplashScreen
|
||||
await IViewModelManager.Instance.MainWindow.Initialize();
|
||||
|
||||
App.Instance.CompositeDisposable.Add(IViewModelManager.Instance.MainWindow);
|
||||
App.Instance.CompositeDisposable.Add(SteamConnectService.Current.Dispose);
|
||||
|
||||
IsInitialized = true;
|
||||
}, cancellationToken: token);
|
||||
|
||||
@@ -23,7 +23,7 @@ static void SetConsoleTitle(string title)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static bool IsProcessElevated_DEBUG_Only()
|
||||
{
|
||||
if (!OperatingSystem2.IsWindows())
|
||||
if (!OperatingSystem.IsWindows())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -122,24 +122,7 @@ public sealed class Plugin : PluginBase<Plugin>, IPlugin
|
||||
|
||||
public override async ValueTask OnExit()
|
||||
{
|
||||
var task1 = Task.Factory.StartNew(async () =>
|
||||
{
|
||||
IReverseProxyService? reverseProxyService = null;
|
||||
try
|
||||
{
|
||||
reverseProxyService = Ioc.Get_Nullable<IReverseProxyService>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
if (reverseProxyService != null)
|
||||
{
|
||||
await reverseProxyService.StopProxyAsync();
|
||||
}
|
||||
});
|
||||
var task2 = Task.Factory.StartNew(ProxyService.OnExitRestoreHosts);
|
||||
await Task.WhenAll(task1, task2);
|
||||
await ProxyService.Current.ExitAsync();
|
||||
}
|
||||
|
||||
string? subProcessPath;
|
||||
|
||||
@@ -14,6 +14,12 @@ partial class ProxyService
|
||||
async Task<OperateProxyServiceResult> StartProxyServiceAsync()
|
||||
{
|
||||
IReadOnlyCollection<AccelerateProjectDTO>? proxyDomains = EnableProxyDomains;
|
||||
|
||||
if (!proxyDomains.Any_Nullable())
|
||||
{
|
||||
Toast.Show(ToastIcon.Warning, "你没有启用任何加速项!!");
|
||||
}
|
||||
|
||||
IReadOnlyCollection<ScriptIPCDTO>? scripts = default;
|
||||
bool isEnableScript = ProxySettings.IsEnableScript.Value;
|
||||
bool isOnlyWorkSteamBrowser = ProxySettings.IsOnlyWorkSteamBrowser.Value;
|
||||
@@ -140,9 +146,10 @@ partial class ProxyService
|
||||
{
|
||||
SetProxyIp(IPAddress.Loopback);
|
||||
}
|
||||
if (!platformService.SetAsSystemProxy(true,
|
||||
var resultSetSystemProxy = await platformService.SetAsSystemProxyAsync(true,
|
||||
proxyIp_.Value,
|
||||
proxyPort))
|
||||
proxyPort);
|
||||
if (!resultSetSystemProxy)
|
||||
{
|
||||
return Strings.CommunityFix_SetAsSystemProxyFail;
|
||||
}
|
||||
@@ -154,7 +161,8 @@ partial class ProxyService
|
||||
SetProxyIp(IPAddress.Loopback);
|
||||
}
|
||||
var pacUrl = $"http://{proxyIp_.Value}:{proxyPort}/pac";
|
||||
if (!platformService.SetAsSystemPACProxy(true, pacUrl))
|
||||
var resultSetSystemPACProxy = await platformService.SetAsSystemPACProxyAsync(true, pacUrl);
|
||||
if (!resultSetSystemPACProxy)
|
||||
{
|
||||
return Strings.CommunityFix_SetAsSystemPACProxyFail;
|
||||
}
|
||||
@@ -268,10 +276,10 @@ partial class ProxyService
|
||||
}
|
||||
break;
|
||||
case ProxyMode.System:
|
||||
platformService.SetAsSystemProxy(false);
|
||||
await platformService.SetAsSystemProxyAsync(false);
|
||||
break;
|
||||
case ProxyMode.PAC:
|
||||
platformService.SetAsSystemPACProxy(false);
|
||||
await platformService.SetAsSystemPACProxyAsync(false);
|
||||
break;
|
||||
}
|
||||
StopTimer(); // 停止 UI 计时器
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace BD.WTTS.Services;
|
||||
|
||||
public sealed partial class ProxyService
|
||||
#if (WINDOWS || MACCATALYST || MACOS || LINUX) && !(IOS || ANDROID)
|
||||
: ReactiveObject, IDisposable, IAsyncDisposable, IProxyService
|
||||
: ReactiveObject, IProxyService
|
||||
#endif
|
||||
{
|
||||
static ProxyService? mCurrent;
|
||||
@@ -22,7 +22,7 @@ public sealed partial class ProxyService
|
||||
{
|
||||
mCurrent = this;
|
||||
|
||||
ProxyDomains = new SourceList<AccelerateProjectGroupDTO>();
|
||||
ProxyDomains = new SourceCache<AccelerateProjectGroupDTO, string>(s => s.Name);
|
||||
ProxyScripts = new SourceList<ScriptDTO>();
|
||||
|
||||
ProxyDomains
|
||||
@@ -85,7 +85,7 @@ public sealed partial class ProxyService
|
||||
}));
|
||||
}
|
||||
|
||||
public SourceList<AccelerateProjectGroupDTO> ProxyDomains { get; }
|
||||
public SourceCache<AccelerateProjectGroupDTO, string> ProxyDomains { get; }
|
||||
|
||||
private readonly ReadOnlyObservableCollection<AccelerateProjectGroupDTO> _ProxyDomainsList;
|
||||
|
||||
@@ -278,7 +278,7 @@ public sealed partial class ProxyService
|
||||
}
|
||||
}
|
||||
|
||||
ProxyDomains.AddRange(result.Content!);
|
||||
ProxyDomains.AddOrUpdate(result.Content!);
|
||||
}
|
||||
|
||||
LoadOrSaveLocalAccelerate();
|
||||
@@ -321,7 +321,7 @@ public sealed partial class ProxyService
|
||||
Log.Error(nameof(ProxyService), ex, nameof(LoadOrSaveLocalAccelerate));
|
||||
}
|
||||
if (accelerates.Any_Nullable())
|
||||
ProxyDomains.AddRange(accelerates!);
|
||||
ProxyDomains.AddOrUpdate(accelerates!);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -571,8 +571,8 @@ public sealed partial class ProxyService
|
||||
|
||||
#if WINDOWS
|
||||
{
|
||||
platformService.SetAsSystemProxy(false);
|
||||
platformService.SetAsSystemPACProxy(false);
|
||||
await platformService.SetAsSystemProxyAsync(false);
|
||||
await platformService.SetAsSystemPACProxyAsync(false);
|
||||
await reverseProxyService.StopProxyAsync();
|
||||
try
|
||||
{
|
||||
|
||||
@@ -76,6 +76,11 @@ public partial class ScriptPageViewModel : TabItemViewModel
|
||||
|
||||
public async void OpenScriptStoreWindow()
|
||||
{
|
||||
if (UserService.Current.IsAuthenticated == false)
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, "脚本商店需要登录账号才可访问");
|
||||
return;
|
||||
}
|
||||
var model = new ScriptStorePageViewModel();
|
||||
await IWindowManager.Instance.ShowTaskDialogAsync(model,
|
||||
Strings.ScriptStore,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
x:DataType="spp:AcceleratorPageViewModel"
|
||||
Description="{Binding Description, Source={x:Static s:Plugin.Instance}, Mode=OneWay}"
|
||||
OpenPaneLength="335"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
Subtitle="{Binding Author, Source={x:Static s:Plugin.Instance}, Mode=OneWay, Converter={StaticResource StringFormatConverter}, ConverterParameter=Plugin_Author}"
|
||||
mc:Ignorable="d">
|
||||
<spp:PageBase.PreviewImage>
|
||||
@@ -163,8 +164,8 @@
|
||||
</DataTemplate>
|
||||
</ui:MenuFlyoutSubItem.ItemTemplate>
|
||||
</ui:MenuFlyoutSubItem>-->
|
||||
<ui:MenuFlyoutItem Text="{Binding Path=Res.Settings_Plugin, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:MenuFlyoutSeparator />
|
||||
<!--<ui:MenuFlyoutItem Text="{Binding Path=Res.Settings_Plugin, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
|
||||
<!--<ui:MenuFlyoutSeparator />-->
|
||||
<!--<ui:MenuFlyoutItem Text="安装证书" />
|
||||
<ui:MenuFlyoutItem Text="移除证书" />
|
||||
<ui:MenuFlyoutItem Text="打开证书文件夹" />
|
||||
@@ -187,9 +188,9 @@
|
||||
</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.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:MenuFlyoutItem Text="{Binding Path=Res.AboutThisPlugin, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
|
||||
</ui:FAMenuFlyout>
|
||||
</DropDownButton.Flyout>
|
||||
</DropDownButton>
|
||||
@@ -202,6 +203,7 @@
|
||||
<TabStrip
|
||||
Background="{DynamicResource ControlOnImageFillColorDefaultBrush}"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}"
|
||||
IsEnabled="{Binding Source={x:Static s:ProxyService.Current}, Path=!ProxyStatus, Mode=OneWay}"
|
||||
ItemContainerTheme="{StaticResource TabItemStyle}"
|
||||
ItemsSource="{Binding Source={x:Static ms:ProxySettings.ProxyModes}, Path=., Mode=OneWay}"
|
||||
SelectedItem="{Binding Source={x:Static ms:ProxySettings.ProxyMode}, Path=Value, Mode=TwoWay}"
|
||||
@@ -232,11 +234,11 @@
|
||||
ToolTip.Tip="{Binding Source={x:Static s:ProxyService.Current}, Path=IPv6AddresString, Mode=OneWay}">
|
||||
<TextBlock.Styles>
|
||||
<Style Selector="TextBlock.Support">
|
||||
<Setter Property="Text" Value="已支持 Ipv6 访问" />
|
||||
<Setter Property="Text" Value="已支持 IPv6 访问" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SystemFillColorSuccessBrush}" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.NotSupport">
|
||||
<Setter Property="Text" Value="不支持 Ipv6 访问" />
|
||||
<Setter Property="Text" Value="不支持 IPv6 访问" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SystemFillColorCriticalBrush}" />
|
||||
</Style>
|
||||
</TextBlock.Styles>
|
||||
@@ -321,80 +323,84 @@
|
||||
</StackPanel>
|
||||
</spp:PageBase.PaneContent>
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<Carousel
|
||||
Name="AcceleratorCarousel"
|
||||
Classes="AnimeSlide"
|
||||
SelectedIndex="0">
|
||||
<i:Interaction.Behaviors>
|
||||
<ia:DataTriggerBehavior
|
||||
Binding="{Binding Source={x:Static s:ProxyService.Current}, Path=!ProxyStatus, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="True">
|
||||
<ia:ChangePropertyAction
|
||||
PropertyName="SelectedIndex"
|
||||
TargetObject="{Binding #AcceleratorCarousel}"
|
||||
Value="0" />
|
||||
</ia:DataTriggerBehavior>
|
||||
<ia:DataTriggerBehavior
|
||||
Binding="{Binding Source={x:Static s:ProxyService.Current}, Path=!ProxyStatus, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="False">
|
||||
<ia:ChangePropertyAction
|
||||
PropertyName="SelectedIndex"
|
||||
TargetObject="{Binding #AcceleratorCarousel}"
|
||||
Value="1" />
|
||||
</ia:DataTriggerBehavior>
|
||||
</i:Interaction.Behaviors>
|
||||
<ScrollViewer
|
||||
Padding="0,0,10,0"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<Carousel
|
||||
Name="AcceleratorCarousel"
|
||||
Classes="AnimeSlide"
|
||||
SelectedIndex="{Binding Source={x:Static s:ProxyService.Current}, Path=ProxyStatus, Mode=OneWay}">
|
||||
<!--<i:Interaction.Behaviors>
|
||||
<ia:DataTriggerBehavior
|
||||
Binding="{Binding Source={x:Static s:ProxyService.Current}, Path=!ProxyStatus, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="True">
|
||||
<ia:ChangePropertyAction
|
||||
PropertyName="SelectedIndex"
|
||||
TargetObject="{Binding #AcceleratorCarousel}"
|
||||
Value="0" />
|
||||
</ia:DataTriggerBehavior>
|
||||
<ia:DataTriggerBehavior
|
||||
Binding="{Binding Source={x:Static s:ProxyService.Current}, Path=!ProxyStatus, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="False">
|
||||
<ia:ChangePropertyAction
|
||||
PropertyName="SelectedIndex"
|
||||
TargetObject="{Binding #AcceleratorCarousel}"
|
||||
Value="1" />
|
||||
</ia:DataTriggerBehavior>
|
||||
</i:Interaction.Behaviors>-->
|
||||
|
||||
<spp:ContentLoader IsLoading="{Binding Source={x:Static s:ProxyService.Current}, Path=!!!ProxyDomainsList.Count, Mode=OneWay}" NoResultMessage="{Binding Path=Res.CommunityFix_ItemsEmpty, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<ItemsControl ItemsSource="{Binding Source={x:Static s:ProxyService.Current}, Path=ProxyDomainsList, Mode=OneWay}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical" Spacing="{StaticResource SettingsSpacing}" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<spp:ContentLoader IsLoading="{Binding Source={x:Static s:ProxyService.Current}, Path=!!!ProxyDomainsList.Count, Mode=OneWay}" NoResultMessage="{Binding Path=Res.CommunityFix_ItemsEmpty, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<ItemsControl ItemsSource="{Binding Source={x:Static s:ProxyService.Current}, Path=ProxyDomainsList, Mode=OneWay}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical" Spacing="{StaticResource SettingsSpacing}" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="spp:AccelerateProjectGroupDTO">
|
||||
<Border>
|
||||
<!--<ui:SettingsExpander ItemsSource="{Binding Items}">-->
|
||||
<ui:SettingsExpander IsClickEnabled="False">
|
||||
<ui:SettingsExpander.Header>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<CheckBox IsChecked="{Binding ThreeStateEnable, Mode=TwoWay}" />
|
||||
<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:SettingsExpanderItem Theme="{StaticResource SettingsExpanderItem2}">
|
||||
<TreeView ItemsSource="{Binding ObservableItems}" SelectionMode="Single">
|
||||
<TreeView.ItemTemplate>
|
||||
<TreeDataTemplate DataType="spp:AccelerateProjectDTO" ItemsSource="{Binding ObservableItems}">
|
||||
<DockPanel Margin="8,0">
|
||||
<CheckBox
|
||||
HorizontalAlignment="Left"
|
||||
DockPanel.Dock="Left"
|
||||
IsChecked="{Binding ThreeStateEnable, Mode=TwoWay}">
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
|
||||
</CheckBox>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
DockPanel.Dock="Right"
|
||||
Text="{Binding DomainNamesArray[0]}" />
|
||||
</DockPanel>
|
||||
</TreeDataTemplate>
|
||||
</TreeView.ItemTemplate>
|
||||
</TreeView>
|
||||
</ui:SettingsExpanderItem>
|
||||
<!--<ui:SettingsExpander.ItemTemplate>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="spp:AccelerateProjectGroupDTO">
|
||||
<Border>
|
||||
<!--<ui:SettingsExpander ItemsSource="{Binding Items}">-->
|
||||
<ui:SettingsExpander IsClickEnabled="False">
|
||||
<ui:SettingsExpander.Header>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<CheckBox IsChecked="{Binding ThreeStateEnable, Mode=TwoWay}" />
|
||||
<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:SettingsExpanderItem Theme="{StaticResource SettingsExpanderItem2}">
|
||||
<TreeView ItemsSource="{Binding ObservableItems}" SelectionMode="Single">
|
||||
<TreeView.ItemTemplate>
|
||||
<TreeDataTemplate DataType="spp:AccelerateProjectDTO" ItemsSource="{Binding ObservableItems}">
|
||||
<DockPanel Margin="8,0">
|
||||
<CheckBox
|
||||
HorizontalAlignment="Left"
|
||||
DockPanel.Dock="Left"
|
||||
IsChecked="{Binding ThreeStateEnable, Mode=TwoWay}">
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
|
||||
</CheckBox>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
DockPanel.Dock="Right"
|
||||
Text="{Binding DomainNamesArray[0]}" />
|
||||
</DockPanel>
|
||||
</TreeDataTemplate>
|
||||
</TreeView.ItemTemplate>
|
||||
</TreeView>
|
||||
</ui:SettingsExpanderItem>
|
||||
<!--<ui:SettingsExpander.ItemTemplate>
|
||||
<DataTemplate DataType="spp:AccelerateProjectDTO">
|
||||
<ui:SettingsExpanderItem IsClickEnabled="True">
|
||||
<ui:SettingsExpanderItem.Content>
|
||||
@@ -409,35 +415,35 @@
|
||||
</ui:SettingsExpanderItem>
|
||||
</DataTemplate>
|
||||
</ui:SettingsExpander.ItemTemplate>-->
|
||||
</ui:SettingsExpander>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ui:SettingsExpander>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</spp:ContentLoader>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</spp:ContentLoader>
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,*,Auto">
|
||||
<TabStrip
|
||||
x:Name="Tabs"
|
||||
ItemContainerTheme="{StaticResource TabItemStyle}"
|
||||
Theme="{StaticResource TabStripStyle}">
|
||||
<TabStripItem Content="{Binding Path=Res.CommunityFix_FlowStatistics, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TabStripItem Content="{Binding Path=Res.CommunityFix_Services, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</TabStrip>
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="8">
|
||||
<StackPanel.Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</StackPanel.Styles>
|
||||
<!--<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
|
||||
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,*,Auto">
|
||||
<TabStrip
|
||||
x:Name="Tabs"
|
||||
ItemContainerTheme="{StaticResource TabItemStyle}"
|
||||
Theme="{StaticResource TabStripStyle}">
|
||||
<TabStripItem Content="{Binding Path=Res.CommunityFix_FlowStatistics, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TabStripItem Content="{Binding Path=Res.CommunityFix_Services, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</TabStrip>
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="8">
|
||||
<StackPanel.Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</StackPanel.Styles>
|
||||
<!--<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
|
||||
<TextBlock FontSize="26" Text="{Binding Path=Res.CommunityFix_AlreadyProxy, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBlock
|
||||
Margin="5,0,0,0"
|
||||
@@ -446,97 +452,97 @@
|
||||
Source={x:Static s:ProxyService.Current},
|
||||
StringFormat={}{0:hh\\:mm\\:ss}}" />
|
||||
</StackPanel>-->
|
||||
<TextBlock>
|
||||
<Run Text="{Binding Path=Res.CommunityFix_ProxyMode, StringFormat={}{0}:, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Run Text="{Binding Source={x:Static ms:ProxySettings.ProxyMode}, Path=Value, Mode=OneWay, Converter={StaticResource EnumLocalizationNameConverter}}" />
|
||||
<TextBlock>
|
||||
<Run Text="{Binding Path=Res.CommunityFix_ProxyMode, StringFormat={}{0}:, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Run Text="{Binding Source={x:Static ms:ProxySettings.ProxyMode}, Path=Value, Mode=OneWay, Converter={StaticResource EnumLocalizationNameConverter}}" />
|
||||
|
||||
<Run Text=" " />
|
||||
<Run Text=" " />
|
||||
|
||||
<Run Text="{Binding Path=Res.CommunityFix_EnableScriptService, StringFormat={}{0}:, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Run Text="{Binding Source={x:Static s:ProxyService.Current}, Path=IsEnableScript, Converter={StaticResource StringFormatConverter}}" />
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<Run Text="{Binding Path=Res.CommunityFix_EnableScriptService, StringFormat={}{0}:, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Run Text="{Binding Source={x:Static s:ProxyService.Current}, Path=IsEnableScript, Converter={StaticResource StringFormatConverter}}" />
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<Carousel
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Classes="AnimeSlide"
|
||||
SelectedIndex="{Binding #Tabs.SelectedIndex}">
|
||||
<Carousel
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Classes="AnimeSlide"
|
||||
SelectedIndex="{Binding #Tabs.SelectedIndex}">
|
||||
|
||||
<spp:ProxyChartView Margin="5,0" />
|
||||
<spp:ProxyChartView Margin="5,0" />
|
||||
|
||||
<Grid ColumnDefinitions="*,20,*">
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
Padding="10"
|
||||
Classes="paper">
|
||||
<DockPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
DockPanel.Dock="Top"
|
||||
FontSize="16"
|
||||
Text="{Binding Path=Res.CommunityFix_AccelerationsEnable, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<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}" />
|
||||
</DockPanel>
|
||||
<Separator Classes="Separator" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Grid ColumnDefinitions="*,20,*">
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
Padding="10"
|
||||
Classes="paper">
|
||||
<DockPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
DockPanel.Dock="Top"
|
||||
FontSize="16"
|
||||
Text="{Binding Path=Res.CommunityFix_AccelerationsEnable, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<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}" />
|
||||
</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="{Binding Path=Res.CommunityFix_ScriptsEnable, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<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>
|
||||
<Border
|
||||
Grid.Column="2"
|
||||
Padding="10"
|
||||
Classes="paper">
|
||||
<DockPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
DockPanel.Dock="Top"
|
||||
FontSize="16"
|
||||
Text="{Binding Path=Res.CommunityFix_ScriptsEnable, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<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>
|
||||
|
||||
|
||||
<!--<TabItem Header="加速日志">
|
||||
<!--<TabItem Header="加速日志">
|
||||
|
||||
</TabItem>-->
|
||||
<!--<TabItem Header="AD">
|
||||
<!--<TabItem Header="AD">
|
||||
|
||||
</TabItem>-->
|
||||
</Carousel>
|
||||
</Grid>
|
||||
</Carousel>
|
||||
</Carousel>
|
||||
</Grid>
|
||||
</Carousel>
|
||||
</ScrollViewer>
|
||||
|
||||
<spp:AdControl
|
||||
Grid.Column="1"
|
||||
Width="165"
|
||||
MaxHeight="390"
|
||||
Margin="10,0,0,0"
|
||||
VerticalAlignment="Top"
|
||||
DockPanel.Dock="Right"
|
||||
Standard="Vertical" />
|
||||
|
||||
@@ -96,10 +96,10 @@
|
||||
Theme="{StaticResource TransparentButton}">
|
||||
<DropDownButton.Flyout>
|
||||
<ui:FAMenuFlyout Placement="BottomEdgeAlignedRight">
|
||||
<ui:MenuFlyoutItem Text="{Binding Path=Res.Script_Settings, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:MenuFlyoutSeparator />
|
||||
<ui:MenuFlyoutItem Text="{Binding Path=Res.Script_AutoUpdate, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:MenuFlyoutItem Text="{Binding Path=Res.CommunityFix_OnlySteamBrowser, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<!--<ui:MenuFlyoutItem Text="{Binding Path=Res.Script_Settings, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
|
||||
<!--<ui:MenuFlyoutSeparator />-->
|
||||
<ui:ToggleMenuFlyoutItem IsChecked="{Binding Source={x:Static ms:ProxySettings.IsAutoCheckScriptUpdate}, Path=Value, Mode=TwoWay}" Text="{Binding Path=Res.Script_AutoUpdate, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:ToggleMenuFlyoutItem IsChecked="{Binding Source={x:Static ms:ProxySettings.IsOnlyWorkSteamBrowser}, Path=Value, Mode=TwoWay}" Text="{Binding Path=Res.CommunityFix_OnlySteamBrowser, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:MenuFlyoutSeparator />
|
||||
<ui:MenuFlyoutItem IsEnabled="False">
|
||||
<ui:MenuFlyoutItem.Text>
|
||||
@@ -115,9 +115,9 @@
|
||||
</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.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:MenuFlyoutItem Text="{Binding Path=Res.AboutThisPlugin, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
|
||||
</ui:FAMenuFlyout>
|
||||
</DropDownButton.Flyout>
|
||||
</DropDownButton>
|
||||
@@ -205,11 +205,11 @@
|
||||
</ui:MenuFlyoutItem.Text>
|
||||
</ui:MenuFlyoutItem>
|
||||
<ui:MenuFlyoutSeparator />
|
||||
<ui:MenuFlyoutItem
|
||||
<ui:MenuFlyoutItem
|
||||
Command="{Binding $parent[spp:PageBase].((spp:ScriptPageViewModel)DataContext).DeleteScriptItemCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
|
||||
Text="{Binding Path=Res.Delete, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
|
||||
Text="{Binding Path=Res.Delete, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</ui:FAMenuFlyout>
|
||||
</spp:AppItem.MoreFlyout>
|
||||
<spp:AppItem.Image>
|
||||
|
||||
@@ -216,7 +216,6 @@ internal sealed class AccountPlatformAuthenticatorRepository : Repository<Accoun
|
||||
public async Task<(bool isSuccess, bool isUpdate)> InsertOrUpdateAsync(IAuthenticatorDTO item, bool isLocal,
|
||||
string? secondaryPassword = null)
|
||||
{
|
||||
var isUpdate = item.Id == default;
|
||||
|
||||
var entity = await ConvertAsync(item, isLocal, secondaryPassword);
|
||||
|
||||
@@ -224,7 +223,7 @@ internal sealed class AccountPlatformAuthenticatorRepository : Repository<Accoun
|
||||
|
||||
item.Id = entity.Id;
|
||||
|
||||
return (r.rowCount > 0, isUpdate);
|
||||
return (r.rowCount > 0, r.result == DbRowExecResult.Update);
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(ushort id) => await base.DeleteAsync(id);
|
||||
|
||||
@@ -55,8 +55,6 @@ public sealed partial class AuthenticatorHomePageViewModel : ViewModelBase
|
||||
var sourceList = await AuthenticatorHelper.GetAllSourceAuthenticatorAsync();
|
||||
if (sourceList.Any_Nullable())
|
||||
{
|
||||
AuthenticatorIsEmpty = false;
|
||||
|
||||
(HasLocalPcEncrypt, HasPasswordEncrypt) = AuthenticatorHelper.HasEncrypt(sourceList);
|
||||
|
||||
if (HasPasswordEncrypt && IsVerificationPass == false)
|
||||
@@ -439,6 +437,12 @@ public sealed partial class AuthenticatorHomePageViewModel : ViewModelBase
|
||||
|
||||
public async Task OpenExportWindow()
|
||||
{
|
||||
if (!Auths.Any_Nullable())
|
||||
{
|
||||
Toast.Show(ToastIcon.Warning, AppResources.Warning_RefuseOperate);
|
||||
return;
|
||||
}
|
||||
|
||||
await IWindowManager.Instance.ShowTaskDialogAsync(new AuthenticatorExportViewModel(), AppResources.ExportAuth,
|
||||
pageContent: new AuthenticatorExportPage(), isOkButton: false);
|
||||
}
|
||||
@@ -538,6 +542,8 @@ public sealed partial class AuthenticatorHomePageViewModel : ViewModelBase
|
||||
{
|
||||
if (sender is not AuthenticatorItemModel authenticatorItemModel) return;
|
||||
var index = Auths.IndexOf(authenticatorItemModel);
|
||||
if (index == 0)
|
||||
return;
|
||||
if (authenticatorItemModel.AuthData.ServerId != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_currentAnswer))
|
||||
@@ -557,6 +563,8 @@ public sealed partial class AuthenticatorHomePageViewModel : ViewModelBase
|
||||
{
|
||||
if (sender is not AuthenticatorItemModel authenticatorItemModel) return;
|
||||
var index = Auths.IndexOf(authenticatorItemModel);
|
||||
if (index == Auths.Count)
|
||||
return;
|
||||
if (authenticatorItemModel.AuthData.ServerId != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_currentAnswer))
|
||||
|
||||
@@ -21,7 +21,4 @@ public partial class AuthenticatorHomePageViewModel
|
||||
|
||||
[Reactive]
|
||||
public bool IsVerificationPass { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool AuthenticatorIsEmpty { get; set; } = true;
|
||||
}
|
||||
@@ -175,20 +175,20 @@ public class AuthenticatorImportPageViewModel : ViewModelBase
|
||||
if (!string.IsNullOrEmpty(authString))
|
||||
{
|
||||
var reader = XmlReader.Create(new StringReader(authString));
|
||||
await reader.ReadAsync();
|
||||
reader.Read();
|
||||
while (reader is { EOF: false, IsEmptyElement: true })
|
||||
{
|
||||
await reader.ReadAsync();
|
||||
}
|
||||
|
||||
await reader.MoveToContentAsync();
|
||||
reader.MoveToContent();
|
||||
while (reader.EOF == false)
|
||||
{
|
||||
if (reader.IsStartElement())
|
||||
{
|
||||
if (reader.Name == "Auth")
|
||||
{
|
||||
await reader.ReadAsync();
|
||||
reader.Read();
|
||||
}
|
||||
|
||||
if (reader.Name != "WinAuthAuthenticator") continue;
|
||||
@@ -198,7 +198,7 @@ public class AuthenticatorImportPageViewModel : ViewModelBase
|
||||
}
|
||||
else
|
||||
{
|
||||
await reader.ReadAsync();
|
||||
reader.Read();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ public sealed partial class SteamTradePageViewModel : WindowViewModel
|
||||
else
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, AppResources.Error_UnknownLogin_.Format(loginstate.Message));
|
||||
await Logout();
|
||||
_steamClient.Logout();
|
||||
}
|
||||
|
||||
IsLoading = false;
|
||||
@@ -167,6 +167,12 @@ public sealed partial class SteamTradePageViewModel : WindowViewModel
|
||||
Confirmations.Add(result.Select(item => new SteamTradeConfirmationModel(_steamAuthenticator!, item)));
|
||||
}
|
||||
}
|
||||
catch (WinAuthUnauthorisedSteamRequestException)
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_AuthTrade_GetError3);
|
||||
_steamClient?.Logout();
|
||||
IsLogged = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.LogAndShowT();
|
||||
@@ -181,10 +187,11 @@ public sealed partial class SteamTradePageViewModel : WindowViewModel
|
||||
{
|
||||
if (_steamClient == null) return;
|
||||
if (await IWindowManager.Instance.ShowTaskDialogAsync(
|
||||
new MessageBoxWindowViewModel() { Content = Strings.LocalAuth_LogoutTip, }, isCancelButton: true,
|
||||
new MessageBoxWindowViewModel() { Content = Strings.LocalAuth_LogoutTip, }, AppResources.Logout, isCancelButton: true,
|
||||
isDialog: false))
|
||||
{
|
||||
_steamClient.Logout();
|
||||
IsLogged = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@
|
||||
<StackPanel.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<CompiledBinding Path="!IsVerificationPass" />
|
||||
<CompiledBinding Path="!AuthenticatorIsEmpty" />
|
||||
<CompiledBinding Path="!!Auths.Count" />
|
||||
</MultiBinding>
|
||||
</StackPanel.IsVisible>
|
||||
<TextBlock
|
||||
@@ -224,11 +224,11 @@
|
||||
IsEnabled="True" />
|
||||
</StackPanel>
|
||||
|
||||
<spp:ContentLoader IsLoading="{Binding IsLoading}" IsShowNoResultText="{Binding AuthenticatorIsEmpty}">
|
||||
<spp:ContentLoader IsLoading="{Binding IsLoading}" IsShowNoResultText="{Binding !!!Auths.Count}">
|
||||
<spp:ContentLoader.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<CompiledBinding Path="IsVerificationPass" />
|
||||
<CompiledBinding Path="!AuthenticatorIsEmpty" />
|
||||
<CompiledBinding Path="!!Auths.Count" />
|
||||
</MultiBinding>
|
||||
</spp:ContentLoader.IsVisible>
|
||||
<spp:ContentLoader.NoResultMessage>
|
||||
@@ -250,7 +250,7 @@
|
||||
ItemsJustification="Start"
|
||||
ItemsStretch="Uniform"
|
||||
MinColumnSpacing="10"
|
||||
MinItemHeight="150"
|
||||
MinItemWidth="362"
|
||||
MinRowSpacing="10" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
|
||||
@@ -66,6 +66,11 @@
|
||||
DockPanel.Dock="Right"
|
||||
IsSticky="False">
|
||||
<ui:CommandBar.PrimaryCommands>
|
||||
<ui:CommandBarButton Command="{Binding Logout}" Label="{Binding Path=Res.Logout, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:CommandBarButton.IconSource>
|
||||
<ui:FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="" />
|
||||
</ui:CommandBarButton.IconSource>
|
||||
</ui:CommandBarButton>
|
||||
<ui:CommandBarButton
|
||||
Command="{Binding Refresh}"
|
||||
IconSource="Refresh"
|
||||
|
||||
@@ -91,111 +91,113 @@ public sealed class SteamPlatformSwitcher : IPlatformSwitcher
|
||||
|
||||
public async Task<IEnumerable<IAccount>?> GetUsers(PlatformAccount platform, Action? refreshUsers = null)
|
||||
{
|
||||
var users = steamService.GetRememberUserList();
|
||||
//var users = steamService.GetRememberUserList();
|
||||
await SteamConnectService.Current.RefreshSteamUsers();
|
||||
var users = SteamConnectService.Current.SteamUsers.Items;
|
||||
if (!users.Any_Nullable())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#region 加载备注信息和 JumpList
|
||||
// #region 加载备注信息和 JumpList
|
||||
|
||||
var accountRemarks = Ioc.Get<IPartialGameAccountSettings>()?.AccountRemarks;
|
||||
// var accountRemarks = Ioc.Get<IPartialGameAccountSettings>()?.AccountRemarks;
|
||||
|
||||
#if WINDOWS
|
||||
List<(string title, string applicationPath, string iconResourcePath, string arguments, string description, string customCategory)>? jumplistData = new();
|
||||
#endif
|
||||
foreach (var user in users)
|
||||
{
|
||||
if (accountRemarks?.TryGetValue("Steam-" + user.SteamId64, out var remark) == true &&
|
||||
!string.IsNullOrEmpty(remark))
|
||||
user.Remark = remark;
|
||||
//#if WINDOWS
|
||||
// List<(string title, string applicationPath, string iconResourcePath, string arguments, string description, string customCategory)>? jumplistData = new();
|
||||
//#endif
|
||||
// foreach (var user in users)
|
||||
// {
|
||||
// if (accountRemarks?.TryGetValue("Steam-" + user.SteamId64, out var remark) == true &&
|
||||
// !string.IsNullOrEmpty(remark))
|
||||
// user.Remark = remark;
|
||||
|
||||
#if WINDOWS
|
||||
{
|
||||
var title = user.SteamNickName ?? user.SteamId64.ToString(CultureInfo.InvariantCulture);
|
||||
if (!string.IsNullOrEmpty(user.Remark))
|
||||
{
|
||||
title = user.SteamNickName + "(" + user.Remark + ")";
|
||||
}
|
||||
//#if WINDOWS
|
||||
// {
|
||||
// var title = user.SteamNickName ?? user.SteamId64.ToString(CultureInfo.InvariantCulture);
|
||||
// if (!string.IsNullOrEmpty(user.Remark))
|
||||
// {
|
||||
// title = user.SteamNickName + "(" + user.Remark + ")";
|
||||
// }
|
||||
|
||||
var processPath = Environment.ProcessPath;
|
||||
processPath.ThrowIsNull();
|
||||
if (!string.IsNullOrEmpty(user.AccountName)) jumplistData!.Add((title,
|
||||
applicationPath: processPath,
|
||||
iconResourcePath: processPath,
|
||||
arguments: $"-clt steam -account {user.AccountName}",
|
||||
description: Strings.UserChange_BtnTootlip,
|
||||
customCategory: Strings.UserFastChange));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// var processPath = Environment.ProcessPath;
|
||||
// processPath.ThrowIsNull();
|
||||
// if (!string.IsNullOrEmpty(user.AccountName)) jumplistData!.Add((title,
|
||||
// applicationPath: processPath,
|
||||
// iconResourcePath: processPath,
|
||||
// arguments: $"-clt steam -account {user.AccountName}",
|
||||
// description: Strings.UserChange_BtnTootlip,
|
||||
// customCategory: Strings.UserFastChange));
|
||||
// }
|
||||
//#endif
|
||||
// }
|
||||
|
||||
#if WINDOWS
|
||||
if (jumplistData.Any())
|
||||
{
|
||||
MainThread2.BeginInvokeOnMainThread(async () =>
|
||||
{
|
||||
var s = IJumpListService.Instance;
|
||||
await s.AddJumpItemsAsync(jumplistData);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
//#if WINDOWS
|
||||
// if (jumplistData.Any())
|
||||
// {
|
||||
// MainThread2.BeginInvokeOnMainThread(async () =>
|
||||
// {
|
||||
// var s = IJumpListService.Instance;
|
||||
// await s.AddJumpItemsAsync(jumplistData);
|
||||
// });
|
||||
// }
|
||||
//#endif
|
||||
// #endregion
|
||||
|
||||
#region 通过webapi加载头像图片用户信息
|
||||
Task2.InBackground(async () =>
|
||||
{
|
||||
foreach (var user in users)
|
||||
{
|
||||
var temp = await swWebService.GetUserInfo(user.SteamId64);
|
||||
if (!string.IsNullOrEmpty(temp.SteamID))
|
||||
{
|
||||
user.SteamID = temp.SteamID;
|
||||
user.OnlineState = temp.OnlineState;
|
||||
user.MemberSince = temp.MemberSince;
|
||||
user.VacBanned = temp.VacBanned;
|
||||
user.Summary = temp.Summary;
|
||||
user.PrivacyState = temp.PrivacyState;
|
||||
user.AvatarIcon = temp.AvatarIcon;
|
||||
user.AvatarMedium = temp.AvatarMedium;
|
||||
user.AvatarFull = temp.AvatarFull;
|
||||
user.MiniProfile = temp.MiniProfile;
|
||||
user.Level = user.MiniProfile?.Level;
|
||||
// #region 通过webapi加载头像图片用户信息
|
||||
// Task2.InBackground(async () =>
|
||||
// {
|
||||
// foreach (var user in users)
|
||||
// {
|
||||
// var temp = await swWebService.GetUserInfo(user.SteamId64);
|
||||
// if (!string.IsNullOrEmpty(temp.SteamID))
|
||||
// {
|
||||
// user.SteamID = temp.SteamID;
|
||||
// user.OnlineState = temp.OnlineState;
|
||||
// user.MemberSince = temp.MemberSince;
|
||||
// user.VacBanned = temp.VacBanned;
|
||||
// user.Summary = temp.Summary;
|
||||
// user.PrivacyState = temp.PrivacyState;
|
||||
// user.AvatarIcon = temp.AvatarIcon;
|
||||
// user.AvatarMedium = temp.AvatarMedium;
|
||||
// user.AvatarFull = temp.AvatarFull;
|
||||
// user.MiniProfile = temp.MiniProfile;
|
||||
// user.Level = user.MiniProfile?.Level;
|
||||
|
||||
//if (user.MiniProfile != null && !string.IsNullOrEmpty(user.MiniProfile.AnimatedAvatar))
|
||||
//{
|
||||
// user.AvatarStream = imageHttpClientService.GetImageMemoryStreamAsync(user.MiniProfile.AnimatedAvatar, cache: true);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// user.AvatarStream = imageHttpClientService.GetImageMemoryStreamAsync(temp.AvatarFull, cache: true);
|
||||
//}
|
||||
}
|
||||
}
|
||||
// //if (user.MiniProfile != null && !string.IsNullOrEmpty(user.MiniProfile.AnimatedAvatar))
|
||||
// //{
|
||||
// // user.AvatarStream = imageHttpClientService.GetImageMemoryStreamAsync(user.MiniProfile.AnimatedAvatar, cache: true);
|
||||
// //}
|
||||
// //else
|
||||
// //{
|
||||
// // user.AvatarStream = imageHttpClientService.GetImageMemoryStreamAsync(temp.AvatarFull, cache: true);
|
||||
// //}
|
||||
// }
|
||||
// }
|
||||
|
||||
refreshUsers?.Invoke();
|
||||
});
|
||||
#endregion
|
||||
// refreshUsers?.Invoke();
|
||||
// });
|
||||
// #endregion
|
||||
|
||||
#region 加载动态头像头像框数据
|
||||
//foreach (var user in users)
|
||||
//{
|
||||
// if (user.MiniProfile == null)
|
||||
// {
|
||||
// user.MiniProfile = await swWebService.GetUserMiniProfile(user.SteamId32);
|
||||
// }
|
||||
// if (user.MiniProfile != null)
|
||||
// {
|
||||
// if (!string.IsNullOrEmpty(user.MiniProfile.AnimatedAvatar))
|
||||
// user.AvatarStream = imageHttpClientService.GetImageMemoryStreamAsync(user.MiniProfile.AnimatedAvatar, cache: true);
|
||||
// #region 加载动态头像头像框数据
|
||||
// //foreach (var user in users)
|
||||
// //{
|
||||
// // if (user.MiniProfile == null)
|
||||
// // {
|
||||
// // user.MiniProfile = await swWebService.GetUserMiniProfile(user.SteamId32);
|
||||
// // }
|
||||
// // if (user.MiniProfile != null)
|
||||
// // {
|
||||
// // if (!string.IsNullOrEmpty(user.MiniProfile.AnimatedAvatar))
|
||||
// // user.AvatarStream = imageHttpClientService.GetImageMemoryStreamAsync(user.MiniProfile.AnimatedAvatar, cache: true);
|
||||
|
||||
// if (!string.IsNullOrEmpty(user.MiniProfile.AvatarFrame))
|
||||
// user.MiniProfile.AvatarFrameStream = imageHttpClientService.GetImageMemoryStreamAsync(user.MiniProfile.AvatarFrame, cache: true);
|
||||
// // if (!string.IsNullOrEmpty(user.MiniProfile.AvatarFrame))
|
||||
// // user.MiniProfile.AvatarFrameStream = imageHttpClientService.GetImageMemoryStreamAsync(user.MiniProfile.AvatarFrame, cache: true);
|
||||
|
||||
// user.Level = user.MiniProfile.Level;
|
||||
// }
|
||||
//}
|
||||
#endregion
|
||||
// // user.Level = user.MiniProfile.Level;
|
||||
// // }
|
||||
// //}
|
||||
// #endregion
|
||||
|
||||
return users.Select(s => new SteamAccount(s));
|
||||
}
|
||||
|
||||
@@ -140,9 +140,9 @@
|
||||
</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.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:MenuFlyoutItem Text="{Binding Path=Res.AboutThisPlugin, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
|
||||
</ui:FAMenuFlyout>
|
||||
</DropDownButton.Flyout>
|
||||
</DropDownButton>
|
||||
|
||||
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
@@ -13,8 +13,7 @@ public sealed class EditAppInfoPageViewModel : WindowViewModel
|
||||
|
||||
public ReadOnlyObservableCollection<SteamGridItem>? SteamGridItems => _SteamGridItems;
|
||||
|
||||
[Reactive]
|
||||
public SteamApp App { get; set; }
|
||||
public SteamApp App { get; }
|
||||
|
||||
[Reactive]
|
||||
public SteamGridItem? SelectGrid { get; set; }
|
||||
@@ -36,7 +35,7 @@ public sealed class EditAppInfoPageViewModel : WindowViewModel
|
||||
|
||||
public ICommand OpenSteamGridDBAuthorUrlCommand { get; }
|
||||
|
||||
public EditAppInfoPageViewModel(SteamApp app)
|
||||
public EditAppInfoPageViewModel(ref SteamApp app)
|
||||
{
|
||||
App = app;
|
||||
|
||||
@@ -121,8 +120,9 @@ public sealed class EditAppInfoPageViewModel : WindowViewModel
|
||||
public async void SaveEditAppInfo()
|
||||
{
|
||||
#region 自定义图片保存
|
||||
var mostRecentUser = ISteamService.Instance.GetRememberUserList().Where(s => s.MostRecent).FirstOrDefault();
|
||||
if (!(App.EditHeaderLogoStream is FileStream fs3))
|
||||
//var mostRecentUser = ISteamService.Instance.GetRememberUserList().Where(s => s.MostRecent).FirstOrDefault();
|
||||
var mostRecentUser = SteamConnectService.Current.SteamUsers.Items.Where(s => s.MostRecent).FirstOrDefault();
|
||||
if (!(App.EditHeaderLogoStream is FileStream fs3 && fs3.Name == (await App.HeaderLogoStream)?.Name))
|
||||
{
|
||||
if (!CheckCurrentSteamUserStats(mostRecentUser))
|
||||
return;
|
||||
@@ -130,10 +130,12 @@ public sealed class EditAppInfoPageViewModel : WindowViewModel
|
||||
if (await ISteamService.Instance.SaveAppImageToSteamFile(App.EditHeaderLogoStream,
|
||||
mostRecentUser!, App.AppId, SteamGridItemType.Header) == false)
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, string.Format(Strings.SaveImageFileFailed, nameof(SteamGridItemType.Logo)));
|
||||
Toast.Show(ToastIcon.Error, string.Format(Strings.SaveImageFileFailed, nameof(SteamGridItemType.Header)));
|
||||
}
|
||||
else
|
||||
this.RaisePropertyChanged(nameof(App.HeaderLogoStream));
|
||||
}
|
||||
if (!(App.EditLibraryLogoStream is FileStream fs))
|
||||
if (!(App.EditLibraryLogoStream is FileStream fs && fs.Name == (await App.LibraryLogoStream)?.Name))
|
||||
{
|
||||
if (!CheckCurrentSteamUserStats(mostRecentUser))
|
||||
return;
|
||||
@@ -143,8 +145,10 @@ public sealed class EditAppInfoPageViewModel : WindowViewModel
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, string.Format(Strings.SaveImageFileFailed, nameof(SteamGridItemType.Logo)));
|
||||
}
|
||||
else
|
||||
this.RaisePropertyChanged(nameof(App.LibraryLogoStream));
|
||||
}
|
||||
if (!(App.EditLibraryHeroStream is FileStream fs1))
|
||||
if (!(App.EditLibraryHeroStream is FileStream fs1 && fs1.Name == (await App.LibraryHeroStream)?.Name))
|
||||
{
|
||||
if (!CheckCurrentSteamUserStats(mostRecentUser))
|
||||
return;
|
||||
@@ -154,8 +158,10 @@ public sealed class EditAppInfoPageViewModel : WindowViewModel
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, string.Format(Strings.SaveImageFileFailed, nameof(SteamGridItemType.Hero)));
|
||||
}
|
||||
else
|
||||
this.RaisePropertyChanged(nameof(App.LibraryHeroStream));
|
||||
}
|
||||
if (!(App.EditLibraryGridStream is FileStream fs2))
|
||||
if (!(App.EditLibraryGridStream is FileStream fs2 && fs2.Name == (await App.LibraryGridStream)?.Name))
|
||||
{
|
||||
if (!CheckCurrentSteamUserStats(mostRecentUser))
|
||||
return;
|
||||
@@ -165,6 +171,8 @@ public sealed class EditAppInfoPageViewModel : WindowViewModel
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, string.Format(Strings.SaveImageFileFailed, nameof(SteamGridItemType.Grid)));
|
||||
}
|
||||
else
|
||||
this.RaisePropertyChanged(nameof(App.LibraryGridStream));
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -228,6 +236,11 @@ public sealed class EditAppInfoPageViewModel : WindowViewModel
|
||||
if (SelectGrid == null)
|
||||
{
|
||||
//Toast.Show(ToastIcon.Warning, Strings.SaveEditedAppInfo_SelectImageFailed);
|
||||
var mostRecentUser = SteamConnectService.Current.SteamUsers.Items.Where(s => s.MostRecent).FirstOrDefault();
|
||||
if (!CheckCurrentSteamUserStats(mostRecentUser))
|
||||
return;
|
||||
await ISteamService.Instance.SaveAppImageToSteamFile(null, mostRecentUser!, App.AppId, type);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case SteamGridItemType.Header:
|
||||
@@ -266,14 +279,6 @@ public sealed class EditAppInfoPageViewModel : WindowViewModel
|
||||
|
||||
public override void OnClosing(object? sender, CancelEventArgs e)
|
||||
{
|
||||
if (App != null && !App.IsEdited)
|
||||
{
|
||||
App.EditLibraryGridStream = null;
|
||||
App.EditLibraryHeroStream = null;
|
||||
App.EditLibraryLogoStream = null;
|
||||
App.EditHeaderLogoStream = null;
|
||||
}
|
||||
|
||||
_SteamGridItemSourceList.Dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ public sealed class EditAppsPageViewModel : ViewModelBase
|
||||
|
||||
public bool IsSteamEditedAppsEmpty => !SteamEditedApps.Any_Nullable();
|
||||
|
||||
public ICommand EditAppInfoClickCommand { get; }
|
||||
|
||||
public EditAppsPageViewModel()
|
||||
{
|
||||
SteamConnectService.Current.SteamApps
|
||||
@@ -26,6 +28,8 @@ public sealed class EditAppsPageViewModel : ViewModelBase
|
||||
.Bind(out _SteamEditedApps)
|
||||
.Subscribe(_ => this.RaisePropertyChanged(nameof(IsSteamEditedAppsEmpty)));
|
||||
|
||||
EditAppInfoClickCommand = ReactiveCommand.Create<SteamApp>(GameListPageViewModel.EditAppInfoClick);
|
||||
|
||||
LoadSteamEditedApps();
|
||||
}
|
||||
|
||||
|
||||
@@ -194,9 +194,9 @@ public sealed partial class GameListPageViewModel : TabItemViewModel
|
||||
public static async void EditAppInfoClick(SteamApp app)
|
||||
{
|
||||
if (app == null) return;
|
||||
var vm = new EditAppInfoPageViewModel(app);
|
||||
var vm = new EditAppInfoPageViewModel(ref app);
|
||||
var result = await IWindowManager.Instance.ShowTaskDialogAsync(vm, Strings.GameList_EditAppInfo,
|
||||
pageContent: new EditAppInfoPage(), okButtonText: Strings.Save, isCancelButton: true);
|
||||
pageContent: new EditAppInfoPage(), okButtonText: Strings.Save, isCancelButton: true, disableScroll: true);
|
||||
|
||||
if (result)
|
||||
{
|
||||
|
||||
@@ -6,9 +6,6 @@ public sealed partial class GameListPageViewModel : TabItemViewModel
|
||||
{
|
||||
public override string Name => Strings.GameList;
|
||||
|
||||
[Reactive]
|
||||
public bool IsOpenFilter { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool IsInstalledFilter { get; set; }
|
||||
|
||||
|
||||
@@ -210,6 +210,8 @@ public sealed class IdleAppsPageViewModel : ViewModelBase
|
||||
{
|
||||
var list = new ObservableCollection<SteamApp>();
|
||||
if (GameLibrarySettings.AFKAppList.Any_Nullable())
|
||||
{
|
||||
int runOtherAppCount = 0;
|
||||
foreach (var item in GameLibrarySettings.AFKAppList.Value!)
|
||||
{
|
||||
var appInfo = SteamConnectService.Current.SteamApps.Items.FirstOrDefault(x => x.AppId == item.Key);
|
||||
@@ -239,6 +241,7 @@ public sealed class IdleAppsPageViewModel : ViewModelBase
|
||||
}
|
||||
else
|
||||
{
|
||||
runOtherAppCount++;
|
||||
SteamConnectService.Current.RuningSteamApps.TryGetValue(item.Key, out var runState);
|
||||
runState?.Process?.KillEntireProcessTree();
|
||||
list.Add(new SteamApp
|
||||
@@ -249,6 +252,11 @@ public sealed class IdleAppsPageViewModel : ViewModelBase
|
||||
}
|
||||
}
|
||||
|
||||
if (runOtherAppCount > 0)
|
||||
{
|
||||
Toast.Show(ToastIcon.Warning, Strings.GameList_RunOtherAppCount_.Format(runOtherAppCount));
|
||||
}
|
||||
}
|
||||
IdleGameList = list;
|
||||
ChangeRunTxt(true);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
Mode=OneWay,
|
||||
Source={x:Static s:ResourceService.Current}}" />-->
|
||||
|
||||
<ToggleSplitButton IsChecked="{Binding Source={x:Static s:SteamConnectService.Current}, Path=IsWatchSteamDownloading, Mode=TwoWay}">
|
||||
<ToggleSplitButton IsChecked="{Binding Source={x:Static s:SteamConnectService.Current}, Path=IsWatchSteamDownloading, Mode=TwoWay}" ToolTip.Tip="启用此按钮才会启动监听 Steam 下载数据并在下载完时执行对应操作!">
|
||||
<ToggleSplitButton.Content>
|
||||
<TextBlock>
|
||||
<TextBlock.Text>
|
||||
@@ -169,7 +169,7 @@
|
||||
Width="250"
|
||||
Height="116"
|
||||
DecodeWidth="250"
|
||||
Source="{Binding HeaderLogoUrl}"
|
||||
Source="{Binding HeaderLogoStream^}"
|
||||
Stretch="UniformToFill" />
|
||||
|
||||
<Border
|
||||
|
||||
@@ -15,505 +15,534 @@
|
||||
mc:Ignorable="d">
|
||||
<TabControl DockPanel.Dock="Top">
|
||||
<TabItem Header="{Binding Path=Res.Info, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<StackPanel Classes="InfoBox">
|
||||
<ScrollViewer>
|
||||
<StackPanel Classes="InfoBox">
|
||||
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="AppId" />
|
||||
<TextBlock Classes="right" Text="{Binding App.AppId}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="AppId" />
|
||||
<TextBlock Classes="right" Text="{Binding App.AppId}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.Name, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding App.Name}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.Name, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding App.Name}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.SortAs, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding App.SortAs}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.SortAs, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding App.SortAs}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.Developer, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding App.Developer}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.Developer, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding App.Developer}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.Publisher, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding App.Publisher}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.Publisher, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding App.Publisher}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<!--<Border Classes="Item">
|
||||
<!--<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="发布日期"/>
|
||||
<TextBox Text="{Binding App.SteamReleaseDate}"/>
|
||||
</DockPanel>
|
||||
</Border>-->
|
||||
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.SupportSystem, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBlock Classes="right" Text="{Binding App.OSList}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.SupportSystem, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBlock Classes="right" Text="{Binding App.OSList}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="Item" IsVisible="{Binding App.IsInstalled}">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.DiskUsage, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBlock Classes="right" Text="{Binding App.SizeOnDisk, Converter={StaticResource StringFormatConverter}, ConverterParameter=size}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item" IsVisible="{Binding App.IsInstalled}">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.DiskUsage, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBlock Classes="right" Text="{Binding App.SizeOnDisk, Converter={StaticResource StringFormatConverter}, ConverterParameter=size}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="Item" IsVisible="{Binding App.IsInstalled}">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.InstalledPath, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:HyperlinkButton
|
||||
HorizontalAlignment="Right"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Command="{Binding OpenFolder}"
|
||||
CommandParameter="{Binding App.InstalledDir}"
|
||||
ToolTip.Tip="{Binding Path=Res.Settings_General_BrowseCustomFolder, Mode=OneWay, Source={x:Static s:ResourceService.Current}, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Null}}">
|
||||
<TextBlock Text="{Binding App.InstalledDir}" TextWrapping="Wrap" />
|
||||
</ui:HyperlinkButton>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item" IsVisible="{Binding App.IsInstalled}">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.InstalledPath, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:HyperlinkButton
|
||||
HorizontalAlignment="Right"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Command="{Binding OpenFolder}"
|
||||
CommandParameter="{Binding App.InstalledDir}"
|
||||
ToolTip.Tip="{Binding Path=Res.Settings_General_BrowseCustomFolder, Mode=OneWay, Source={x:Static s:ResourceService.Current}, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Null}}">
|
||||
<TextBlock Text="{Binding App.InstalledDir}" TextWrapping="Wrap" />
|
||||
</ui:HyperlinkButton>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="Item" IsVisible="{Binding App.IsInstalled}">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.LastUpdatedDateTime, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBlock Classes="right" Text="{Binding App.LastUpdated, StringFormat={}{0:yyyy-MM-dd HH:mm:ss}}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item" IsVisible="{Binding App.IsInstalled}">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Path=Res.LastUpdatedDateTime, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBlock Classes="right" Text="{Binding App.LastUpdated, StringFormat={}{0:yyyy-MM-dd HH:mm:ss}}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="{Binding Path=Res.Media, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<Panel>
|
||||
<spp:ContentLoader
|
||||
x:Name="SteamGridDBContent"
|
||||
MinWidth="300"
|
||||
IsLoading="{Binding IsLoadingSteamGrid}"
|
||||
IsShowNoResultText="{Binding IsSteamGridEmpty}"
|
||||
IsVisible="False"
|
||||
NoResultMessage="{Binding Path=Res.FailedGetImageFromSteamGridDB, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ItemsControl
|
||||
ItemsSource="{Binding SteamGridItems}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type spp:SteamGridItem}">
|
||||
<spp:AppItem
|
||||
Title="{Binding Author.Name}"
|
||||
MaxWidth="150"
|
||||
Margin="5"
|
||||
Classes="Vertical"
|
||||
Cursor="Hand"
|
||||
Tapped="SteamGridDBItem_Tapped"
|
||||
ToolTip.Tip="{Binding Author.Name}">
|
||||
<!-- Description="{Binding Style}" -->
|
||||
<spp:AppItem.MoreFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).OpenSteamGridDBImageUrlCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Header="{Binding Path=Res.OpenImageInBrowser, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<MenuItem
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).OpenSteamGridDBAppUrlCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Header="{Binding Path=Res.OpenSteamGridDBInBrowser, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<MenuItem
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).OpenSteamGridDBAuthorUrlCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Header="{Binding Path=Res.OpenTheAuthorPageInBrowser, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</MenuFlyout>
|
||||
</spp:AppItem.MoreFlyout>
|
||||
<spp:AppItem.Image>
|
||||
<spp:Image2
|
||||
Width="150"
|
||||
DecodeWidth="150"
|
||||
Source="{Binding Thumb}"
|
||||
Stretch="Uniform" />
|
||||
</spp:AppItem.Image>
|
||||
</spp:AppItem>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<DockPanel>
|
||||
<Button
|
||||
Height="30"
|
||||
Margin="5,5,5,10"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Click="HideGridDialog_Click"
|
||||
Content="{Binding Path=Res.Back, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
DockPanel.Dock="Top" />
|
||||
<ScrollViewer DockPanel.Dock="Bottom">
|
||||
<ItemsControl
|
||||
ItemsSource="{Binding SteamGridItems}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type spp:SteamGridItem}">
|
||||
<spp:AppItem
|
||||
Title="{Binding Author.Name}"
|
||||
MaxWidth="150"
|
||||
Margin="5"
|
||||
Classes="Vertical"
|
||||
Cursor="Hand"
|
||||
Tapped="SteamGridDBItem_Tapped"
|
||||
ToolTip.Tip="{Binding Author.Name}">
|
||||
<!-- Description="{Binding Style}" -->
|
||||
<spp:AppItem.MoreFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuItem
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).OpenSteamGridDBImageUrlCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Header="{Binding Path=Res.OpenImageInBrowser, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<MenuItem
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).OpenSteamGridDBAppUrlCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Header="{Binding Path=Res.OpenSteamGridDBInBrowser, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<MenuItem
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).OpenSteamGridDBAuthorUrlCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Header="{Binding Path=Res.OpenTheAuthorPageInBrowser, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</MenuFlyout>
|
||||
</spp:AppItem.MoreFlyout>
|
||||
<spp:AppItem.Image>
|
||||
<spp:Image2
|
||||
Width="150"
|
||||
DecodeWidth="150"
|
||||
Source="{Binding Thumb}"
|
||||
Stretch="Uniform" />
|
||||
</spp:AppItem.Image>
|
||||
</spp:AppItem>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
</spp:ContentLoader>
|
||||
<StackPanel x:Name="MediaContent" Classes="InfoBox">
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<StackPanel Margin="0">
|
||||
<WrapPanel>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.HorizontalTitlePage, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Button
|
||||
Margin="5,0"
|
||||
Click="ShowGridDialog_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Header}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.GetImageFromSteamGridDB, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="CloudDownload" />
|
||||
</Button>
|
||||
<Button
|
||||
Click="ResetGridImage_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Header}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.Reset, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="Redo" />
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
|
||||
<!--<TextBlock Text="{Binding Path=Res.HorizontalTitlePage,Mode=OneWay,Source={x:Static s:ResourceService.Current}}"/>
|
||||
<ScrollViewer x:Name="MediaContent">
|
||||
<StackPanel Classes="InfoBox">
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<StackPanel Margin="0">
|
||||
<WrapPanel>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.HorizontalTitlePage, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Button
|
||||
Margin="5,0"
|
||||
Padding="5"
|
||||
Click="ShowGridDialog_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Header}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.GetImageFromSteamGridDB, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="CloudDownload" />
|
||||
</Button>
|
||||
<Button
|
||||
Padding="5"
|
||||
Click="ResetGridImage_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Header}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.Reset, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="Redo" />
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
|
||||
<!--<TextBlock Text="{Binding Path=Res.HorizontalTitlePage,Mode=OneWay,Source={x:Static s:ResourceService.Current}}"/>
|
||||
<Button Classes="Hyperlink"
|
||||
FontSize="12"
|
||||
Content="{Binding Path=Res.GetImageFromSteamGridDB,Mode=OneWay,Source={x:Static s:ResourceService.Current}}"
|
||||
Tag="{x:Static spp:SteamGridItemType.Header}"
|
||||
Click="ShowGridDialog_Click"/>-->
|
||||
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="{Binding Path=Res.RecommendedResolution, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="460 x 215 px"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="{Binding Path=Res.RecommendedResolution, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="460 x 215 px"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<spp:CustomFilePicker
|
||||
MaxHeight="260"
|
||||
Margin="50,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
FileStream="{Binding App.EditHeaderLogoStream, Mode=TwoWay}">
|
||||
<spp:Image2
|
||||
DecodeHeight="260"
|
||||
Source="{Binding App.EditHeaderLogoStream}"
|
||||
Stretch="Uniform" />
|
||||
</spp:CustomFilePicker>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<StackPanel Margin="0">
|
||||
<WrapPanel>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.VerticalTitlePage, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Button
|
||||
Margin="5,0"
|
||||
Click="ShowGridDialog_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Grid}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.GetImageFromSteamGridDB, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="CloudDownload" />
|
||||
</Button>
|
||||
<Button
|
||||
Click="ResetGridImage_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Header}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.Reset, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="Redo" />
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
<!--<TextBlock Text="{Binding Path=Res.VerticalTitlePage,Mode=OneWay,Source={x:Static s:ResourceService.Current}}"/>
|
||||
<spp:CustomFilePicker
|
||||
MaxHeight="260"
|
||||
Margin="50,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
FileStream="{Binding App.EditHeaderLogoStream, Mode=TwoWay}">
|
||||
<spp:Image2
|
||||
DecodeHeight="260"
|
||||
Source="{Binding App.EditHeaderLogoStream}"
|
||||
Stretch="Uniform" />
|
||||
</spp:CustomFilePicker>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<StackPanel Margin="0">
|
||||
<WrapPanel>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.VerticalTitlePage, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Button
|
||||
Margin="5,0"
|
||||
Padding="5"
|
||||
Click="ShowGridDialog_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Grid}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.GetImageFromSteamGridDB, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="CloudDownload" />
|
||||
</Button>
|
||||
<Button
|
||||
Padding="5"
|
||||
Click="ResetGridImage_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Grid}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.Reset, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="Redo" />
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
<!--<TextBlock Text="{Binding Path=Res.VerticalTitlePage,Mode=OneWay,Source={x:Static s:ResourceService.Current}}"/>
|
||||
<Button Classes="Hyperlink"
|
||||
FontSize="12"
|
||||
Content="{Binding Path=Res.GetImageFromSteamGridDB,Mode=OneWay,Source={x:Static s:ResourceService.Current}}"
|
||||
Tag="{x:Static spp:SteamGridItemType.Grid}"
|
||||
Click="ShowGridDialog_Click"/>-->
|
||||
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="{Binding Path=Res.RecommendedResolution, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="600 x 900 px"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="{Binding Path=Res.RecommendedResolution, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="600 x 900 px"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<spp:CustomFilePicker
|
||||
MaxHeight="260"
|
||||
Margin="50,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
FileStream="{Binding App.EditLibraryGridStream, Mode=TwoWay}">
|
||||
<spp:Image2
|
||||
DecodeHeight="260"
|
||||
Source="{Binding App.EditLibraryGridStream}"
|
||||
Stretch="Uniform" />
|
||||
</spp:CustomFilePicker>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<StackPanel Margin="0">
|
||||
<WrapPanel>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.Background, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Button
|
||||
Margin="5,0"
|
||||
Click="ShowGridDialog_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Hero}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.GetImageFromSteamGridDB, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="CloudDownload" />
|
||||
</Button>
|
||||
<Button
|
||||
Click="ResetGridImage_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Header}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.Reset, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="Redo" />
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
<!--<TextBlock Text="{Binding Path=Res.Background,Mode=OneWay,Source={x:Static s:ResourceService.Current}}"/>
|
||||
<spp:CustomFilePicker
|
||||
MaxHeight="260"
|
||||
Margin="50,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
FileStream="{Binding App.EditLibraryGridStream, Mode=TwoWay}">
|
||||
<spp:Image2
|
||||
DecodeHeight="260"
|
||||
Source="{Binding App.EditLibraryGridStream}"
|
||||
Stretch="Uniform" />
|
||||
</spp:CustomFilePicker>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<StackPanel Margin="0">
|
||||
<WrapPanel>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.Background, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Button
|
||||
Margin="5,0"
|
||||
Padding="5"
|
||||
Click="ShowGridDialog_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Hero}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.GetImageFromSteamGridDB, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="CloudDownload" />
|
||||
</Button>
|
||||
<Button
|
||||
Padding="5"
|
||||
Click="ResetGridImage_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Hero}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.Reset, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="Redo" />
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
<!--<TextBlock Text="{Binding Path=Res.Background,Mode=OneWay,Source={x:Static s:ResourceService.Current}}"/>
|
||||
<Button Classes="Hyperlink"
|
||||
FontSize="12"
|
||||
Content="{Binding Path=Res.GetImageFromSteamGridDB,Mode=OneWay,Source={x:Static s:ResourceService.Current}}"
|
||||
Tag="{x:Static spp:SteamGridItemType.Hero}"
|
||||
Click="ShowGridDialog_Click"/>-->
|
||||
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="{Binding Path=Res.RecommendedResolution, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="1920 x 620 px"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="{Binding Path=Res.RecommendedResolution, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="1920 x 620 px"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<spp:CustomFilePicker
|
||||
MaxHeight="260"
|
||||
Margin="50,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
FileStream="{Binding App.EditLibraryHeroStream, Mode=TwoWay}">
|
||||
<spp:Image2
|
||||
DecodeHeight="260"
|
||||
Source="{Binding App.EditLibraryHeroStream}"
|
||||
Stretch="Uniform" />
|
||||
</spp:CustomFilePicker>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<StackPanel Margin="0">
|
||||
<WrapPanel>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.Icon, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Button
|
||||
Margin="5,0"
|
||||
Click="ShowGridDialog_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Logo}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.GetImageFromSteamGridDB, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="CloudDownload" />
|
||||
</Button>
|
||||
<Button
|
||||
Click="ResetGridImage_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Header}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.Reset, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="Redo" />
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
<!--<Button Classes="Hyperlink"
|
||||
<spp:CustomFilePicker
|
||||
MaxHeight="260"
|
||||
Margin="50,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
FileStream="{Binding App.EditLibraryHeroStream, Mode=TwoWay}">
|
||||
<spp:Image2
|
||||
DecodeHeight="260"
|
||||
Source="{Binding App.EditLibraryHeroStream}"
|
||||
Stretch="Uniform" />
|
||||
</spp:CustomFilePicker>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<StackPanel Margin="0">
|
||||
<WrapPanel>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Res.Icon, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Button
|
||||
Margin="5,0"
|
||||
Padding="5"
|
||||
Click="ShowGridDialog_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Logo}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.GetImageFromSteamGridDB, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="CloudDownload" />
|
||||
</Button>
|
||||
<Button
|
||||
Padding="5"
|
||||
Click="ResetGridImage_Click"
|
||||
Cursor="Hand"
|
||||
Tag="{x:Static spp:SteamGridItemType.Logo}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.Reset, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="Redo" />
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
<!--<Button Classes="Hyperlink"
|
||||
FontSize="12"
|
||||
Content="{Binding Path=Res.GetImageFromSteamGridDB,Mode=OneWay,Source={x:Static s:ResourceService.Current}}"
|
||||
Tag="{x:Static spp:SteamGridItemType.Logo}"
|
||||
Click="ShowGridDialog_Click"/>-->
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="{Binding Path=Res.RecommendedResolution, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="120 x 120 px"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="{Binding Path=Res.RecommendedResolution, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Classes="prompt"
|
||||
Text="120 x 120 px"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<spp:CustomFilePicker
|
||||
MaxWidth="220"
|
||||
Margin="50,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
FileStream="{Binding App.EditLibraryLogoStream, Mode=TwoWay}">
|
||||
<spp:Image2
|
||||
DecodeWidth="220"
|
||||
Source="{Binding App.EditLibraryLogoStream}"
|
||||
Stretch="Uniform" />
|
||||
</spp:CustomFilePicker>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
<spp:CustomFilePicker
|
||||
MaxWidth="220"
|
||||
Margin="50,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
FileStream="{Binding App.EditLibraryLogoStream, Mode=TwoWay}">
|
||||
<spp:Image2
|
||||
DecodeWidth="220"
|
||||
Source="{Binding App.EditLibraryLogoStream}"
|
||||
Stretch="Uniform" />
|
||||
</spp:CustomFilePicker>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Panel>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="{Binding Path=Res.LaunchItem, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" IsVisible="{Binding App.IsInstalled}">
|
||||
<StackPanel Classes="InfoBox">
|
||||
<ItemsRepeater ItemsSource="{Binding App.LaunchItems}">
|
||||
<ItemsRepeater.Layout>
|
||||
<StackLayout Orientation="Vertical" Spacing="{StaticResource SettingsSpacing}" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type spp:SteamAppLaunchItem}">
|
||||
<Border Classes="Item">
|
||||
<StackPanel Spacing="5">
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.Name, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding Label}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.ExecutableFile, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding Executable}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.Arguments, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding Arguments}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.WorkingDir, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding WorkingDir}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.SupportSystem, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:FAComboBox IsEditable="True" Text="{Binding Platform, Mode=TwoWay}">
|
||||
<ui:FAComboBox.Items>
|
||||
<x:String>windows</x:String>
|
||||
<x:String>linux</x:String>
|
||||
<x:String>macos</x:String>
|
||||
</ui:FAComboBox.Items>
|
||||
</ui:FAComboBox>
|
||||
</DockPanel>
|
||||
<ScrollViewer>
|
||||
<StackPanel Classes="InfoBox">
|
||||
<ItemsRepeater ItemsSource="{Binding App.LaunchItems}">
|
||||
<ItemsRepeater.Layout>
|
||||
<StackLayout Orientation="Vertical" Spacing="{StaticResource SettingsSpacing}" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type spp:SteamAppLaunchItem}">
|
||||
<Border Classes="Item">
|
||||
<StackPanel Spacing="5">
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.Name, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding Label}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.ExecutableFile, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding Executable}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.Arguments, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding Arguments}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.WorkingDir, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox Text="{Binding WorkingDir}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.SupportSystem, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:FAComboBox IsEditable="True" Text="{Binding Platform, Mode=TwoWay}">
|
||||
<ui:FAComboBox.Items>
|
||||
<x:String>windows</x:String>
|
||||
<x:String>linux</x:String>
|
||||
<x:String>macos</x:String>
|
||||
</ui:FAComboBox.Items>
|
||||
</ui:FAComboBox>
|
||||
</DockPanel>
|
||||
|
||||
<Grid ColumnDefinitions="*,*,*">
|
||||
<Button
|
||||
Margin="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).UpLaunchItemCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding Path=Res.MoveUp, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Cursor="Hand" />
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Margin="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).DownLaunchItemCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding Path=Res.MoveDown, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Cursor="Hand" />
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Margin="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).DeleteLaunchItemCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding Path=Res.Delete, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Cursor="Hand" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
<Border Classes="Item">
|
||||
<Button
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Command="{Binding AddLaunchItem}"
|
||||
Cursor="Hand">
|
||||
<ui:SymbolIcon
|
||||
Margin="0,20"
|
||||
FontSize="32"
|
||||
Symbol="Add" />
|
||||
</Button>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
<Grid ColumnDefinitions="*,*,*">
|
||||
<Button
|
||||
Margin="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).UpLaunchItemCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding Path=Res.MoveUp, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Cursor="Hand" />
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Margin="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).DownLaunchItemCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding Path=Res.MoveDown, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Cursor="Hand" />
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Margin="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).DeleteLaunchItemCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding Path=Res.Delete, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Cursor="Hand" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
<Border Classes="Item">
|
||||
<Button
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Command="{Binding AddLaunchItem}"
|
||||
Cursor="Hand">
|
||||
<ui:SymbolIcon
|
||||
Margin="0,20"
|
||||
FontSize="32"
|
||||
Symbol="Add" />
|
||||
</Button>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="{Binding Path=Res.SaveFile, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" IsVisible="{Binding App.IsCloudArchive}">
|
||||
<StackPanel Classes="InfoBox">
|
||||
<Border Classes="Item">
|
||||
<StackPanel Spacing="5">
|
||||
<DockPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<Label Content="{Binding Path=Res.CloudSaveFileSize, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Button
|
||||
Command="{Binding ManageCloudArchive_Click}"
|
||||
Cursor="Hand"
|
||||
ToolTip.Tip="{Binding Path=Res.GameList_CloudArchiveManager, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="CloudBackup" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<TextBlock Classes="right" Text="{Binding App.CloudQuota, Converter={StaticResource StringFormatConverter}, ConverterParameter=size}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.CloudMaxnumFiles, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBlock Classes="right" Text="{Binding App.CloudMaxnumFiles}" />
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<ItemsRepeater ItemsSource="{Binding App.SaveFiles}">
|
||||
<ItemsRepeater.Layout>
|
||||
<StackLayout Orientation="Vertical" Spacing="10" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type spp:SteamAppSaveFile}">
|
||||
<Border Classes="Item">
|
||||
<StackPanel Spacing="5">
|
||||
<DockPanel>
|
||||
<Label Content="Root" />
|
||||
<TextBlock Classes="right" Text="{Binding Root}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="Path" />
|
||||
<TextBlock Classes="right" Text="{Binding Path}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="Pattern" />
|
||||
<TextBlock Classes="right" Text="{Binding Pattern}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.DirPath, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:HyperlinkButton
|
||||
HorizontalAlignment="Right"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).OpenFolder}"
|
||||
CommandParameter="{Binding FormatDirPath}"
|
||||
ToolTip.Tip="{Binding Path=Res.Settings_General_BrowseCustomFolder, Mode=OneWay, Source={x:Static s:ResourceService.Current}, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Null}}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding FormatDirPath}"
|
||||
TextWrapping="Wrap" />
|
||||
</ui:HyperlinkButton>
|
||||
</DockPanel>
|
||||
<ScrollViewer>
|
||||
<StackPanel Classes="InfoBox">
|
||||
<Border Classes="Item">
|
||||
<StackPanel Spacing="5">
|
||||
<DockPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<Label Content="{Binding Path=Res.CloudSaveFileSize, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<Button
|
||||
Command="{Binding ManageCloudArchive_Click}"
|
||||
Cursor="Hand"
|
||||
ToolTip.Tip="{Binding Path=Res.GameList_CloudArchiveManager, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="CloudBackup" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</StackPanel>
|
||||
<TextBlock Classes="right" Text="{Binding App.CloudQuota, Converter={StaticResource StringFormatConverter}, ConverterParameter=size}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.CloudMaxnumFiles, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBlock Classes="right" Text="{Binding App.CloudMaxnumFiles}" />
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<ItemsRepeater ItemsSource="{Binding App.SaveFiles}">
|
||||
<ItemsRepeater.Layout>
|
||||
<StackLayout Orientation="Vertical" Spacing="10" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type spp:SteamAppSaveFile}">
|
||||
<Border Classes="Item">
|
||||
<StackPanel Spacing="5">
|
||||
<DockPanel>
|
||||
<Label Content="Root" />
|
||||
<TextBlock Classes="right" Text="{Binding Root}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="Path" />
|
||||
<TextBlock Classes="right" Text="{Binding Path}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="Pattern" />
|
||||
<TextBlock Classes="right" Text="{Binding Pattern}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="{Binding Path=Res.DirPath, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<ui:HyperlinkButton
|
||||
HorizontalAlignment="Right"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Command="{Binding $parent[UserControl].((spp:EditAppInfoPageViewModel)DataContext).OpenFolder}"
|
||||
CommandParameter="{Binding FormatDirPath}"
|
||||
ToolTip.Tip="{Binding Path=Res.Settings_General_BrowseCustomFolder, Mode=OneWay, Source={x:Static s:ResourceService.Current}, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Null}}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding FormatDirPath}"
|
||||
TextWrapping="Wrap" />
|
||||
</ui:HyperlinkButton>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<!--<TabItem Header="DLC">
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.VisualTree;
|
||||
using BD.SteamClient.Enums.SteamGridDB;
|
||||
using BD.SteamClient.Models.SteamGridDB;
|
||||
using BD.WTTS.UI.Views.Controls;
|
||||
|
||||
namespace BD.WTTS.UI.Views.Pages;
|
||||
|
||||
@@ -24,6 +27,12 @@ public partial class EditAppInfoPage : ReactiveUserControl<EditAppInfoPageViewMo
|
||||
}
|
||||
}
|
||||
|
||||
public void HideGridDialog_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
SteamGridDBContent.IsVisible = false;
|
||||
MediaContent.IsVisible = true;
|
||||
}
|
||||
|
||||
public void ShowGridDialog_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
if (ViewModel != null)
|
||||
|
||||
@@ -88,9 +88,9 @@
|
||||
</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.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:MenuFlyoutItem Text="{Binding Path=Res.AboutThisPlugin, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
|
||||
</ui:FAMenuFlyout>
|
||||
</DropDownButton.Flyout>
|
||||
</DropDownButton>
|
||||
@@ -113,33 +113,13 @@
|
||||
Title="{Binding DisplayName}"
|
||||
Height="270"
|
||||
MaxWidth="120"
|
||||
Classes="Vertical">
|
||||
Classes="Vertical"
|
||||
ClickCommand="{Binding $parent[spp:PageBase].((spp:EditAppsPageViewModel)DataContext).EditAppInfoClickCommand}"
|
||||
ClickCommandParameter="{Binding}"
|
||||
Cursor="Hand">
|
||||
<spp:AppItem.Status>
|
||||
<Border Classes="Status">
|
||||
<Panel>
|
||||
<WrapPanel IsVisible="{Binding !Process, Converter={StaticResource IsNullConverter}}">
|
||||
<Ellipse
|
||||
Width="6"
|
||||
Height="6"
|
||||
Margin="0,0,5,0"
|
||||
Fill="#47A42B" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Text="{Binding Path=Res.GameList_RunState, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</WrapPanel>
|
||||
<WrapPanel IsVisible="{Binding Process, Converter={StaticResource IsNullConverter}}">
|
||||
<Ellipse
|
||||
Width="6"
|
||||
Height="6"
|
||||
Margin="0,0,5,0"
|
||||
Fill="#FF4F58" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Text="{Binding Path=Res.GameList_StopState, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</WrapPanel>
|
||||
</Panel>
|
||||
<TextBlock Text="{Binding Path=Res.Edit, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</Border>
|
||||
</spp:AppItem.Status>
|
||||
<!--<spp:AppItem.ActionButton>
|
||||
@@ -147,9 +127,7 @@
|
||||
Command="{Binding $parent[spp:PageBase].((spp:EditAppsPageViewModel)DataContext).DeleteButtonCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Cursor="Hand"
|
||||
ToolTip.Tip="{Binding Path=Res.GameList_RemoveItemBtn,
|
||||
Mode=OneWay,
|
||||
Source={x:Static s:ResourceService.Current}}">
|
||||
ToolTip.Tip="{Binding Path=Res.GameList_RemoveItemBtn, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<Viewbox>
|
||||
<ui:SymbolIcon Symbol="Delete" />
|
||||
</Viewbox>
|
||||
@@ -162,7 +140,7 @@
|
||||
DecodeWidth="120"
|
||||
FallbackSource="avares://BD.WTTS.Client.Plugins.GameList/UI/Assets/defaultappimage.png"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="{Binding LibraryGridUrl}"
|
||||
Source="{Binding LibraryGridStream^}"
|
||||
Stretch="UniformToFill" />
|
||||
<TextBlock
|
||||
Margin="8,0"
|
||||
|
||||
@@ -343,112 +343,6 @@
|
||||
</StackPanel>
|
||||
</spp:PageBase.PaneContent>
|
||||
<DockPanel>
|
||||
<!--<Grid
|
||||
Margin="0,0,0,10"
|
||||
ColumnDefinitions="Auto,*,Auto"
|
||||
DockPanel.Dock="Top"
|
||||
RowDefinitions="Auto,10,Auto">
|
||||
<AutoCompleteBox
|
||||
MinWidth="300"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Search" />
|
||||
<TabStrip
|
||||
Grid.Column="2"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{DynamicResource ControlOnImageFillColorDefaultBrush}"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}"
|
||||
ItemContainerTheme="{StaticResource TabItemStyle}"
|
||||
Theme="{StaticResource TabStripStyle}">
|
||||
<TabStripItem Content="" FontFamily="{StaticResource SymbolThemeFontFamily}" />
|
||||
<TabStripItem Content="" FontFamily="{StaticResource SymbolThemeFontFamily}" />
|
||||
<TabStripItem Content="" FontFamily="{StaticResource SymbolThemeFontFamily}" />
|
||||
</TabStrip>
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding SteamApps.Count, Converter={StaticResource StringFormatConverter}, ConverterParameter='找到 {0} 个应用'}" />
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
Spacing="4">
|
||||
<ToggleButton
|
||||
Padding="8"
|
||||
Theme="{StaticResource TransparentToggleButton}"
|
||||
ToolTip.Tip="仅显示已安装的游戏">
|
||||
<Viewbox Width="20" Height="20">
|
||||
<ui:SymbolIcon Symbol="Play" />
|
||||
</Viewbox>
|
||||
</ToggleButton>
|
||||
|
||||
<ToggleButton
|
||||
Padding="8"
|
||||
Theme="{StaticResource TransparentToggleButton}"
|
||||
ToolTip.Tip="仅显示支持 Steam 云存档游戏">
|
||||
<Viewbox Width="20" Height="20">
|
||||
<ui:SymbolIcon Symbol="CloudSyncComplete" />
|
||||
</Viewbox>
|
||||
</ToggleButton>
|
||||
|
||||
<DropDownButton
|
||||
Width="200"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Center">
|
||||
<DropDownButton.Content>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Classes="h8"
|
||||
DockPanel.Dock="Left"
|
||||
Text="{Binding TypeFilterString}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
</DropDownButton.Content>
|
||||
<DropDownButton.Styles>
|
||||
<Style Selector="FlyoutPresenter">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
</Style>
|
||||
</DropDownButton.Styles>
|
||||
<DropDownButton.Flyout>
|
||||
<Flyout FlyoutPresenterClasses="NoPadding" Placement="Bottom">
|
||||
<Border Width="{Binding $parent.Width}" Height="200">
|
||||
<ScrollViewer Padding="10,5">
|
||||
<ItemsControl ItemsSource="{Binding AppTypeFiltres}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<DataTemplate.DataType>
|
||||
<x:Type x:TypeArguments="spp:SteamAppType" TypeName="spp:EnumModel" />
|
||||
</DataTemplate.DataType>
|
||||
<DockPanel>
|
||||
<CheckBox VerticalAlignment="Center" IsChecked="{Binding Enable, Mode=TwoWay}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<StackPanel.Styles>
|
||||
<Style Selector="TextBlock.count">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
</StackPanel.Styles>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding LocalizationName}" />
|
||||
<TextBlock
|
||||
Margin="5,0,0,0"
|
||||
Classes="count"
|
||||
Text="(" />
|
||||
<TextBlock Classes="count" Text="{Binding Count}" />
|
||||
<TextBlock Classes="count" Text=")" />
|
||||
</StackPanel>
|
||||
</CheckBox>
|
||||
</DockPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Flyout>
|
||||
</DropDownButton.Flyout>
|
||||
</DropDownButton>
|
||||
</StackPanel>
|
||||
</Grid>-->
|
||||
<spp:ContentLoader
|
||||
IsLoading="{Binding Source={x:Static s:SteamConnectService.Current}, Path=IsLoadingGameList, Mode=OneWay}"
|
||||
IsShowNoResultText="{Binding IsSteamAppsEmpty}"
|
||||
@@ -529,7 +423,7 @@
|
||||
DecodeWidth="169"
|
||||
FallbackSource="avares://BD.WTTS.Client.Plugins.GameList/UI/Assets/defaultappimage.png"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="{Binding LibraryGridUrl}"
|
||||
Source="{Binding LibraryGridStream^}"
|
||||
Stretch="UniformToFill" />
|
||||
<TextBlock
|
||||
Margin="8,0"
|
||||
|
||||
@@ -121,9 +121,9 @@
|
||||
</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.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:MenuFlyoutItem Text="{Binding Path=Res.AboutThisPlugin, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
|
||||
</ui:FAMenuFlyout>
|
||||
</DropDownButton.Flyout>
|
||||
</DropDownButton>
|
||||
@@ -150,7 +150,7 @@
|
||||
<spp:AppItem.Status>
|
||||
<Border Classes="Status">
|
||||
<Panel>
|
||||
<WrapPanel IsVisible="{Binding !Process, Converter={StaticResource IsNullConverter}}">
|
||||
<WrapPanel IsVisible="{Binding Process, Converter={StaticResource IsNullConverter}, ConverterParameter=invert, Mode=OneWay}">
|
||||
<Ellipse
|
||||
Width="6"
|
||||
Height="6"
|
||||
@@ -161,7 +161,7 @@
|
||||
FontSize="12"
|
||||
Text="{Binding Path=Res.GameList_RunState, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</WrapPanel>
|
||||
<WrapPanel IsVisible="{Binding Process, Converter={StaticResource IsNullConverter}}">
|
||||
<WrapPanel IsVisible="{Binding Process, Converter={StaticResource IsNullConverter}, Mode=OneWay}">
|
||||
<Ellipse
|
||||
Width="6"
|
||||
Height="6"
|
||||
@@ -210,7 +210,7 @@
|
||||
DecodeWidth="120"
|
||||
FallbackSource="avares://BD.WTTS.Client.Plugins.GameList/UI/Assets/defaultappimage.png"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="{Binding LibraryGridUrl}"
|
||||
Source="{Binding LibraryGridStream^}"
|
||||
Stretch="UniformToFill" />
|
||||
<TextBlock
|
||||
Margin="8,0"
|
||||
|
||||
@@ -8,6 +8,17 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="UI\Assets\BorderlessWindow.png" />
|
||||
<None Remove="UI\Assets\CounterStrike.png" />
|
||||
<None Remove="UI\Assets\CPU.png" />
|
||||
<None Remove="UI\Assets\movecross.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AvaloniaResource Include="UI\Assets\BorderlessWindow.png" />
|
||||
<AvaloniaResource Include="UI\Assets\CounterStrike.png" />
|
||||
<AvaloniaResource Include="UI\Assets\CPU.png" />
|
||||
<AvaloniaResource Include="UI\Assets\movecross.png" />
|
||||
<AvaloniaResource Include="UI\Assets\toolbox.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -75,17 +86,15 @@
|
||||
<ProjectReference Include="..\BD.WTTS.Client.Avalonia\BD.WTTS.Client.Avalonia.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="UI\ViewModels\" />
|
||||
<Folder Include="UI\Views\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="UI\Views\GameToolsPage.axaml.cs">
|
||||
<DependentUpon>GameToolsPage.axaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -95,6 +104,6 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\TFM_NETX_WITH_ALL.props" />
|
||||
<Import Project="..\TFM_NETX_WITH_DESKTOP.props" />
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace BD.WTTS;
|
||||
|
||||
#if WINDOWS
|
||||
public static partial class HandleWindowExtensions
|
||||
{
|
||||
public static bool IsHasProcessExits(this NativeWindowModel window)
|
||||
{
|
||||
if (window?.Process?.HasExited == false && window.Name != Process.GetCurrentProcess().ProcessName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Kill(this NativeWindowModel window)
|
||||
{
|
||||
if (!window.IsHasProcessExits())
|
||||
{
|
||||
window.Process?.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,4 +1,5 @@
|
||||
using BD.WTTS.Properties;
|
||||
using BD.WTTS.UI.Views.Pages;
|
||||
|
||||
namespace BD.WTTS.Plugins;
|
||||
|
||||
@@ -15,7 +16,7 @@ public sealed class Plugin : PluginBase<Plugin>, IPlugin
|
||||
|
||||
public sealed override string UniqueEnglishName => moduleName;
|
||||
|
||||
public sealed override string Description => "游戏工具";
|
||||
public sealed override string Description => "通用游戏工具";
|
||||
|
||||
protected sealed override string? AuthorOriginalString => null;
|
||||
|
||||
@@ -25,7 +26,7 @@ public sealed class Plugin : PluginBase<Plugin>, IPlugin
|
||||
{
|
||||
yield return new MenuTabItemViewModel(this, nameof(Strings.GameRelated))
|
||||
{
|
||||
PageType = null,
|
||||
PageType = typeof(GameToolsPage),
|
||||
IsResourceGet = true,
|
||||
IconKey = Icon,
|
||||
};
|
||||
|
||||
@@ -1,77 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
Version 1.3
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">1.3</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1">this is my long string</data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
[base64 mime encoded serialized .NET Framework object]
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
@@ -0,0 +1,127 @@
|
||||
using Avalonia.Platform;
|
||||
using BD.WTTS.UI.Views.Pages;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed partial class BorderlessGamePageViewModel : ViewModelBase
|
||||
{
|
||||
#if WINDOWS
|
||||
readonly IPlatformService windowApi = IPlatformService.Instance!;
|
||||
|
||||
#region SelectWindow 变更通知
|
||||
|
||||
private NativeWindowModel? _SelectWindow;
|
||||
|
||||
public NativeWindowModel? SelectWindow
|
||||
{
|
||||
get => _SelectWindow;
|
||||
set
|
||||
{
|
||||
if (_SelectWindow != value)
|
||||
{
|
||||
_SelectWindow = value;
|
||||
this.RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
ObservableCollection<NativeWindowModel> _WindowList = new();
|
||||
|
||||
public ObservableCollection<NativeWindowModel> WindowList
|
||||
{
|
||||
get => _WindowList;
|
||||
set
|
||||
{
|
||||
if (_WindowList != value)
|
||||
{
|
||||
_WindowList = value;
|
||||
this.RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BorderlessGamePageViewModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Cross_MouseDown()
|
||||
{
|
||||
windowApi.GetMoveMouseDownWindow((window) =>
|
||||
{
|
||||
SelectWindow = window;
|
||||
WindowList.Insert(0, window);
|
||||
});
|
||||
}
|
||||
|
||||
public void BorderlessWindow_Click()
|
||||
{
|
||||
if (SelectWindow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
windowApi.BorderlessWindow(SelectWindow);
|
||||
}
|
||||
|
||||
public void MaximizeWindow_Click()
|
||||
{
|
||||
if (SelectWindow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
windowApi.MaximizeWindow(SelectWindow);
|
||||
}
|
||||
|
||||
public void NormalWindow_Click()
|
||||
{
|
||||
if (SelectWindow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
windowApi.NormalWindow(SelectWindow);
|
||||
}
|
||||
|
||||
public void WindowKill_Click()
|
||||
{
|
||||
if (SelectWindow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SelectWindow.Kill();
|
||||
}
|
||||
|
||||
public void ShowWindow_Click()
|
||||
{
|
||||
if (SelectWindow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
windowApi.ShowWindow(SelectWindow);
|
||||
}
|
||||
|
||||
public void HideWindow_Click()
|
||||
{
|
||||
if (SelectWindow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
windowApi.HideWindow(SelectWindow);
|
||||
}
|
||||
|
||||
public void ToWallerpaperWindow_Click()
|
||||
{
|
||||
if (SelectWindow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
windowApi.ToWallerpaperWindow(SelectWindow);
|
||||
}
|
||||
|
||||
public void ResetWallerpaper_Click()
|
||||
{
|
||||
windowApi.ResetWallerpaper();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<spp:PageBase
|
||||
x:Class="BD.WTTS.UI.Views.Pages.BorderlessGamePage"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:i="using:Avalonia.Xaml.Interactivity"
|
||||
xmlns:ia="using:Avalonia.Xaml.Interactions.Core"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:s="https://steampp.net/services"
|
||||
xmlns:spp="https://steampp.net/ui"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
Title="游戏无边框窗口化"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
x:CompileBindings="True"
|
||||
x:DataType="spp:BorderlessGamePageViewModel"
|
||||
Description="该功能可以获取游戏窗口句柄执行一些对应操作"
|
||||
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/BorderlessWindow.png" />
|
||||
</spp:PageBase.PreviewImage>
|
||||
<spp:PageBase.ActionContent>
|
||||
<StackPanel Orientation="Horizontal" Spacing="2">
|
||||
<ToggleButton
|
||||
Padding="8,4"
|
||||
DockPanel.Dock="Right"
|
||||
IsChecked="{Binding $parent[spp:PageBase].IsPaneOpen, Mode=TwoWay}"
|
||||
Theme="{StaticResource TransparentButton}">
|
||||
<Panel>
|
||||
<Viewbox
|
||||
Width="16"
|
||||
Height="16"
|
||||
HorizontalAlignment="Left">
|
||||
<ui:FontIcon Glyph="" />
|
||||
</Viewbox>
|
||||
<TextBlock
|
||||
Margin="28,4,0,4"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="查看捕获窗口记录" />
|
||||
</Panel>
|
||||
</ToggleButton>
|
||||
<DropDownButton
|
||||
Padding="8"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="{StaticResource More}"
|
||||
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}}" />-->
|
||||
<!--<ui:MenuFlyoutSeparator />-->
|
||||
<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
|
||||
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>
|
||||
<spp:PageBase.PaneContent>
|
||||
<StackPanel Margin="15,20" Spacing="10">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="历史记录"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
<ListBox ItemsSource="{ReflectionBinding WindowList, Mode=OneWay}" SelectedItem="{ReflectionBinding SelectWindow}">
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical" Spacing="5" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<WrapPanel VerticalAlignment="Center">
|
||||
<TextBlock>
|
||||
<Run Text="{ReflectionBinding Name, Mode=OneWay}" />
|
||||
<Run Text="(" />
|
||||
<Run Text="{ReflectionBinding Title, Mode=OneWay}" />
|
||||
<Run Text=")" />
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</StackPanel>
|
||||
</spp:PageBase.PaneContent>
|
||||
|
||||
<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>
|
||||
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
IsVisible="{ReflectionBinding !!SelectWindow}"
|
||||
Orientation="Vertical"
|
||||
Spacing="10">
|
||||
<TextBlock TextWrapping="WrapWithOverflow">
|
||||
<Run Text="{Binding Path=Res.GameRelated_Borderless_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
|
||||
<Run Text="{ReflectionBinding SelectWindow.Title, Mode=OneWay}" />
|
||||
</TextBlock>
|
||||
<TextBlock TextWrapping="WrapWithOverflow">
|
||||
<Run Text="{Binding Path=Res.GameRelated_Borderless_ClassName, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
|
||||
<Run Text="{ReflectionBinding SelectWindow.ClassName, Mode=OneWay}" />
|
||||
</TextBlock>
|
||||
<TextBlock TextWrapping="WrapWithOverflow">
|
||||
<Run Text="{Binding Path=Res.GameRelated_Borderless_Process, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
|
||||
<Run Text="{ReflectionBinding SelectWindow.Name, Mode=OneWay}" />
|
||||
</TextBlock>
|
||||
<TextBlock TextWrapping="WrapWithOverflow">
|
||||
<Run Text="{Binding Path=Res.GameRelated_Borderless_Path, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat={}{0}:}" />
|
||||
<Run Text="{ReflectionBinding SelectWindow.Path, Mode=OneWay}" />
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<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>
|
||||
|
||||
<!--<TextBlock Text="{ReflectionBinding Path=Res.GameRelated_Borderless_ToWallerpaperTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}, StringFormat=*{0}}" TextWrapping="WrapWithOverflow" />-->
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</spp:PageBase>
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace BD.WTTS.UI.Views.Pages;
|
||||
|
||||
public partial class BorderlessGamePage : PageBase<BorderlessGamePageViewModel>
|
||||
{
|
||||
public BorderlessGamePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext ??= new BorderlessGamePageViewModel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
<spp:PageBase
|
||||
x:Class="BD.WTTS.UI.Views.Pages.GameToolsPage"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:s="https://steampp.net/services"
|
||||
xmlns:spp="https://steampp.net/ui"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
Title="{Binding Name, Source={x:Static s:Plugin.Instance}, Mode=OneWay}"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
Description="{Binding Description, Source={x:Static s:Plugin.Instance}, Mode=OneWay}"
|
||||
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="{Binding Icon, Source={x:Static s:Plugin.Instance}, Mode=OneWay, Converter={StaticResource BitmapAssetValueConverter}}" />
|
||||
</spp:PageBase.PreviewImage>
|
||||
<spp:PageBase.TabContent>
|
||||
<!--<TabStrip
|
||||
Margin="4"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{DynamicResource ControlOnImageFillColorDefaultBrush}"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}"
|
||||
ItemContainerTheme="{StaticResource TabItemStyle}">
|
||||
<TabStripItem Content="多平台账号切换" />
|
||||
<TabStripItem Content="Steam 家庭共享库管理" />
|
||||
</TabStrip>-->
|
||||
</spp:PageBase.TabContent>
|
||||
<spp:PageBase.ActionContent>
|
||||
<StackPanel Orientation="Horizontal" Spacing="2">
|
||||
<Button
|
||||
Padding="8,4"
|
||||
DockPanel.Dock="Right"
|
||||
Theme="{StaticResource TransparentButton}">
|
||||
<Panel>
|
||||
<Viewbox
|
||||
Width="16"
|
||||
Height="16"
|
||||
HorizontalAlignment="Left">
|
||||
<ui:SymbolIcon Symbol="Refresh" />
|
||||
</Viewbox>
|
||||
<TextBlock
|
||||
Margin="28,4,0,4"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Path=Res.Refresh, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</Panel>
|
||||
</Button>
|
||||
<DropDownButton
|
||||
Padding="8"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="{StaticResource More}"
|
||||
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}}" />-->
|
||||
<!--<ui:MenuFlyoutSeparator />-->
|
||||
<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
|
||||
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>
|
||||
<ScrollViewer>
|
||||
<ScrollViewer.Resources>
|
||||
<ControlTheme
|
||||
x:Key="NavButtonStyle"
|
||||
BasedOn="{StaticResource {x:Type Button}}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Width" Value="160" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Margin" Value="6" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
||||
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="ClipToBounds" Value="True" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ScrollViewer.Resources>
|
||||
<WrapPanel>
|
||||
<Border spp:Animations.EnableAnimations="True">
|
||||
<Button
|
||||
Click="GameToolsPage_Click"
|
||||
IsEnabled="{spp:OnPlatform Windows}"
|
||||
Theme="{StaticResource NavButtonStyle}">
|
||||
<Button.Tag>
|
||||
<x:Type TypeName="spp:BorderlessGamePage" />
|
||||
</Button.Tag>
|
||||
<Grid RowDefinitions="3*,*">
|
||||
<Border
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
CornerRadius="4 4 0 0"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality">
|
||||
<spp:Image2 Source="avares://BD.WTTS.Client.Plugins.GameTools/UI/Assets/BorderlessWindow.png" Stretch="Uniform" />
|
||||
</Border>
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Margin="12"
|
||||
Spacing="5">
|
||||
<TextBlock FontWeight="SemiBold" Text="游戏无边框窗口化" />
|
||||
<TextBlock
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="仅 Windows 可用"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Button>
|
||||
</Border>
|
||||
|
||||
<Border spp:Animations.EnableAnimations="True">
|
||||
<Button
|
||||
Click="GameToolsPage_Click"
|
||||
IsEnabled="{spp:OnPlatform Windows}"
|
||||
Tag="{x:Null}"
|
||||
Theme="{StaticResource NavButtonStyle}">
|
||||
<Grid RowDefinitions="3*,*">
|
||||
<Border
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
CornerRadius="4 4 0 0"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality">
|
||||
<spp:Image2 Source="avares://BD.WTTS.Client.Plugins.GameTools/UI/Assets/CounterStrike.png" Stretch="Uniform" />
|
||||
</Border>
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Margin="12"
|
||||
Spacing="5">
|
||||
<TextBlock FontWeight="SemiBold" Text="CS:GO VAC 修复" />
|
||||
<TextBlock
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="仅 Windows 可用"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Button>
|
||||
</Border>
|
||||
|
||||
<Border spp:Animations.EnableAnimations="True">
|
||||
<Button
|
||||
Click="GameToolsPage_Click"
|
||||
IsEnabled="{spp:OnPlatform Windows}"
|
||||
Tag="{x:Null}"
|
||||
Theme="{StaticResource NavButtonStyle}">
|
||||
<Grid RowDefinitions="3*,*">
|
||||
<Border
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
CornerRadius="4 4 0 0"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality">
|
||||
<spp:Image2 Source="avares://BD.WTTS.Client.Plugins.GameTools/UI/Assets/CPU.png" Stretch="Uniform" />
|
||||
</Border>
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Margin="12"
|
||||
Spacing="5">
|
||||
<TextBlock FontWeight="SemiBold" Text="CPU 游戏调度优化" />
|
||||
<TextBlock
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="仅 Windows 可用"
|
||||
Theme="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Button>
|
||||
</Border>
|
||||
</WrapPanel>
|
||||
</ScrollViewer>
|
||||
</spp:PageBase>
|
||||
@@ -0,0 +1,23 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace BD.WTTS.UI.Views.Pages;
|
||||
|
||||
public partial class GameToolsPage : PageBase
|
||||
{
|
||||
public GameToolsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void GameToolsPage_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Control c && c.Tag is Type t)
|
||||
{
|
||||
NavigationService.Instance.Navigate(t, NavigationTransitionEffect.FromRight);
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationService.Instance.Navigate(null, NavigationTransitionEffect.FromRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<UserControl
|
||||
x:Class="BD.WTTS.UI.Views.Pages.MainFramePage"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:s="https://steampp.net/services"
|
||||
xmlns:spp="https://steampp.net/ui"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
<Panel>
|
||||
<TabStrip
|
||||
Name="Tabs"
|
||||
Margin="9"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{DynamicResource ControlOnImageFillColorDefaultBrush}"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}"
|
||||
ItemContainerTheme="{StaticResource TabItemStyle}"
|
||||
Theme="{StaticResource TabStripStyle}"
|
||||
ZIndex="100">
|
||||
<TabStrip.ItemsPanel>
|
||||
<OnFormFactor Default="{StaticResource DefaultPanel}">
|
||||
<On Options="Mobile">
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</On>
|
||||
</OnFormFactor>
|
||||
</TabStrip.ItemsPanel>
|
||||
<TabStripItem Content="{Binding Path=Res.Library, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<TabStripItem.Tag>
|
||||
<x:Type TypeName="spp:BorderlessGamePage" />
|
||||
</TabStripItem.Tag>
|
||||
</TabStripItem>
|
||||
</TabStrip>
|
||||
<ui:Frame Name="InnerNavFrame" IsNavigationStackEnabled="False" />
|
||||
</Panel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,39 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using FluentAvalonia.UI.Media.Animation;
|
||||
|
||||
namespace BD.WTTS.UI.Views.Pages;
|
||||
|
||||
public partial class MainFramePage : UserControl
|
||||
{
|
||||
int lastIndex = -1;
|
||||
|
||||
public MainFramePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Tabs.SelectionChanged += Tabs_SelectionChanged;
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
|
||||
Tabs_SelectionChanged(null, null);
|
||||
}
|
||||
|
||||
private void Tabs_SelectionChanged(object? sender, Avalonia.Controls.SelectionChangedEventArgs? e)
|
||||
{
|
||||
if (Tabs.SelectedItem is TabStripItem tab && tab.Tag is Type t)
|
||||
{
|
||||
InnerNavFrame.Navigate(t, null, new SlideNavigationTransitionInfo
|
||||
{
|
||||
Effect = FrameEffect.GetEffect(lastIndex, Tabs.SelectedIndex),
|
||||
FromHorizontalOffset = 70,
|
||||
});
|
||||
|
||||
lastIndex = Tabs.SelectedIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,13 @@
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AvaloniaXaml Remove="UI\Views\Windows\**" />
|
||||
<Compile Remove="UI\Views\Windows\**" />
|
||||
<EmbeddedResource Remove="UI\Views\Windows\**" />
|
||||
<None Remove="UI\Views\Windows\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\AssemblyInfo.Xaml.cs">
|
||||
<LinkBase>Properties</LinkBase>
|
||||
@@ -73,7 +80,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Models\" />
|
||||
<Folder Include="UI\Views\Windows\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
@@ -19,7 +19,6 @@ public sealed class IdleAppsPageViewModel : ViewModelBase
|
||||
RunOrStopAutoNext(x.Value);
|
||||
this.IsAutoNextOnTxt = x.Value ? Strings.Idle_StopAutoNext : Strings.Idle_OpenAutoNext;
|
||||
});
|
||||
IdleRunStartOrStop_Click();
|
||||
}
|
||||
|
||||
[Reactive]
|
||||
@@ -79,6 +78,13 @@ public sealed class IdleAppsPageViewModel : ViewModelBase
|
||||
private double SwitchTime { get; set; } = 500;
|
||||
#endregion
|
||||
|
||||
public override void Activation()
|
||||
{
|
||||
base.Activation();
|
||||
|
||||
IdleRunStartOrStop_Click();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动或停止挂卡
|
||||
/// </summary>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.ReactiveUI;
|
||||
using BD.SteamClient.Models;
|
||||
|
||||
namespace BD.WTTS.UI.Views.Pages;
|
||||
|
||||
public partial class MainFramePage : UserControl
|
||||
public partial class MainFramePage : ReactiveUserControl<IdleAppsPageViewModel>
|
||||
{
|
||||
public MainFramePage()
|
||||
{
|
||||
|
||||
@@ -69,7 +69,14 @@ static partial class MouseHook
|
||||
MouseUp?.Invoke(null, new PointDouble(mouseHookStruct.pt.X, mouseHookStruct.pt.Y));
|
||||
}
|
||||
}
|
||||
return PInvoke.User32.CallNextHookEx(_mouseHookHandle.ThrowIsNull().DangerousGetHandle(), nCode, wParam, lParam);
|
||||
if (_mouseHookHandle != null)
|
||||
{
|
||||
return PInvoke.User32.CallNextHookEx(_mouseHookHandle.DangerousGetHandle(), nCode, wParam, lParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const int WM_LBUTTONUP = 0x0202;
|
||||
|
||||
@@ -1512,7 +1512,7 @@ namespace BD.WTTS.Client.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 选择文件 的本地化字符串。
|
||||
/// 查找类似 选择或拖拽文件到此 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string CustomFilePicker_Tip {
|
||||
get {
|
||||
@@ -2888,6 +2888,15 @@ namespace BD.WTTS.Client.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 挂时长列表存在不属于当前 Steam 账号的 {0} 个游戏 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameList_RunOtherAppCount_ {
|
||||
get {
|
||||
return ResourceManager.GetString("GameList_RunOtherAppCount_", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 运行中 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3015,6 +3024,141 @@ namespace BD.WTTS.Client.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 无边框窗口化 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 无边框窗口化 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_BorderlessWindow {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_BorderlessWindow", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 类名 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_ClassName {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_ClassName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 隐藏 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_Hide {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_Hide", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 结束进程 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_KillProcess {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_KillProcess", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 最大化 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_Maximize {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_Maximize", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 拖拽十字到游戏窗口,即可获取游戏信息执行对应操作。 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_MoveMouseTip {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_MoveMouseTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 默认大小 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_Normal {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_Normal", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 程序路径 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_Path {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_Path", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 进程 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_Process {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_Process", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 刷新壁纸 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_ResetWallerpaper {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_ResetWallerpaper", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 显示 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_Show {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_Show", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 标题 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 置于壁纸层 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_ToWallerpaper {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_ToWallerpaper", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 置于壁纸层的游戏可能会无法操控,这个问题可以解决但是目前开发精力不在这,目前这个功能就这样了。游戏结束后桌面会依然留下冻结的画面,这时可以点击刷新壁纸来恢复默认壁纸。并且将窗口放置于桌面壁纸层功能与 Wallpaper Engine 和其它动态桌面软件不兼容,使用时注意关掉 Wallpaper Engine 等软件。 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated_Borderless_ToWallerpaperTip {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated_Borderless_ToWallerpaperTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 性别 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -1397,7 +1397,7 @@
|
||||
<value>请在弹出的控制台窗口中输入密码或者手动执行</value>
|
||||
</data>
|
||||
<data name="CustomFilePicker_Tip" xml:space="preserve">
|
||||
<value>选择文件</value>
|
||||
<value>选择或拖拽文件到此</value>
|
||||
</data>
|
||||
<data name="Info" xml:space="preserve">
|
||||
<value>信息</value>
|
||||
@@ -2738,5 +2738,53 @@
|
||||
</data>
|
||||
<data name="User_Rememberme" xml:space="preserve">
|
||||
<value>记住登录状态</value>
|
||||
</data>
|
||||
<data name="GameList_RunOtherAppCount_" xml:space="preserve">
|
||||
<value>挂时长列表存在不属于当前 Steam 账号的 {0} 个游戏</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless" xml:space="preserve">
|
||||
<value>无边框窗口化</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_BorderlessWindow" xml:space="preserve">
|
||||
<value>无边框窗口化</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_ClassName" xml:space="preserve">
|
||||
<value>类名</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_Hide" xml:space="preserve">
|
||||
<value>隐藏</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_KillProcess" xml:space="preserve">
|
||||
<value>结束进程</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_Maximize" xml:space="preserve">
|
||||
<value>最大化</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_MoveMouseTip" xml:space="preserve">
|
||||
<value>拖拽十字到游戏窗口,即可获取游戏信息执行对应操作。</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_Normal" xml:space="preserve">
|
||||
<value>默认大小</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_Path" xml:space="preserve">
|
||||
<value>程序路径</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_Process" xml:space="preserve">
|
||||
<value>进程</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_ResetWallerpaper" xml:space="preserve">
|
||||
<value>刷新壁纸</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_Show" xml:space="preserve">
|
||||
<value>显示</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_Title" xml:space="preserve">
|
||||
<value>标题</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_ToWallerpaper" xml:space="preserve">
|
||||
<value>置于壁纸层</value>
|
||||
</data>
|
||||
<data name="GameRelated_Borderless_ToWallerpaperTip" xml:space="preserve">
|
||||
<value>置于壁纸层的游戏可能会无法操控,这个问题可以解决但是目前开发精力不在这,目前这个功能就这样了。游戏结束后桌面会依然留下冻结的画面,这时可以点击刷新壁纸来恢复默认壁纸。并且将窗口放置于桌面壁纸层功能与 Wallpaper Engine 和其它动态桌面软件不兼容,使用时注意关掉 Wallpaper Engine 等软件。</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -156,11 +156,11 @@ public sealed partial class IPCMainProcessServiceImpl : IPCMainProcessService
|
||||
// 构建要执行的 shell 命令
|
||||
var shellStr =
|
||||
$"if [ -x \"{fileName}\" ]; then echo \"文件具有执行权限。\"; else chmod +x \"{fileName}\"; echo \"文件没有执行权限。\"; fi";
|
||||
//Linux 启动子模块前需要判断是否有 Exec 执行权限
|
||||
// Linux 启动子模块前需要判断是否有 Exec 执行权限
|
||||
Process.Start(Process2.BinBash, new string[]
|
||||
{
|
||||
"-c",
|
||||
shellStr
|
||||
shellStr,
|
||||
}).WaitForExit();
|
||||
|
||||
#endif
|
||||
@@ -176,8 +176,13 @@ public sealed partial class IPCMainProcessServiceImpl : IPCMainProcessService
|
||||
psi.ArgumentList.Add(mSubProcessArgumentIndex2Model.Value);
|
||||
configure?.Invoke(psi);
|
||||
DotNetRuntimeHelper.AddEnvironment(psi);
|
||||
if (!string.IsNullOrWhiteSpace(Startup.NativeLibraryPath))
|
||||
psi.Environment.TryAdd(IPCSubProcessService.EnvKey_NativeLibraryPath, Startup.NativeLibraryPath);
|
||||
var nativeLibraryPath = Startup.NativeLibraryPath;
|
||||
if (!string.IsNullOrWhiteSpace(nativeLibraryPath))
|
||||
{
|
||||
psi.Environment.TryAdd(
|
||||
IPCSubProcessService.EnvKey_NativeLibraryPath,
|
||||
nativeLibraryPath);
|
||||
}
|
||||
if (isAdministrator
|
||||
#if WINDOWS
|
||||
&& !WindowsPlatformServiceImpl.IsPrivilegedProcess
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#if LINUX
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
|
||||
using System.Collections;
|
||||
|
||||
namespace BD.WTTS.Services.Implementation
|
||||
{
|
||||
partial class LinuxPlatformServiceImpl
|
||||
@@ -39,9 +42,7 @@ namespace BD.WTTS.Services.Implementation
|
||||
"-c",
|
||||
$"{Certutil} -A -d sql:$HOME/.pki/nssdb -n \"{CertificateConstants.CertificateName}\" -t C,, -i \"{cerPath}\""
|
||||
}).WaitForExit();
|
||||
if (string.IsNullOrWhiteSpace(Environment.ProcessPath))
|
||||
return false;
|
||||
return RunRootCommand(PkexecPath, new string[] { Environment.ProcessPath!, "-ceri", CertificateConstants.AppDataDirectory }) == 0;
|
||||
return RunRootCommand(PkexecPath, new string[] { GetAppHostPath(), "-ceri", CertificateConstants.AppDataDirectory }) == 0;
|
||||
}
|
||||
|
||||
public void RemoveCertificate(byte[] certificate2)
|
||||
@@ -51,14 +52,20 @@ namespace BD.WTTS.Services.Implementation
|
||||
"-c",
|
||||
$"{Certutil} -D -d sql:$HOME/.pki/nssdb -n \"{CertificateConstants.CertificateName}\""
|
||||
}).WaitForExit();
|
||||
if (string.IsNullOrWhiteSpace(Environment.ProcessPath))
|
||||
return;
|
||||
RunRootCommand(PkexecPath, new string[] { Environment.ProcessPath!, "-cerd", CertificateConstants.AppDataDirectory });
|
||||
RunRootCommand(PkexecPath, new string[] { GetAppHostPath(), "-cerd", CertificateConstants.AppDataDirectory });
|
||||
}
|
||||
|
||||
public static int RunRootCommand(string path, string[] args)
|
||||
{
|
||||
var p = Process.Start(path, args);
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = path,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = false
|
||||
};
|
||||
args.ForEach(psi.ArgumentList.Add);
|
||||
DotNetRuntimeHelper.AddEnvironment(psi);
|
||||
var p = Process.Start(psi);
|
||||
p.WaitForExit();
|
||||
return p.ExitCode;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,13 @@ namespace BD.WTTS.Services.Implementation;
|
||||
|
||||
partial class LinuxPlatformServiceImpl
|
||||
{
|
||||
const string AppHost = "Steam++.sh";
|
||||
|
||||
public string GetAppHostPath()
|
||||
{
|
||||
return Path.Combine(AppContext.BaseDirectory, AppHost);
|
||||
}
|
||||
|
||||
public ValueTask RunShellAsync(string script, bool requiredAdministrator)
|
||||
=> UnixHelper.RunShellAsync(script, requiredAdministrator);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace BD.WTTS.Services.Implementation;
|
||||
|
||||
partial class LinuxPlatformServiceImpl
|
||||
{
|
||||
public bool SetAsSystemProxy(bool state, IPAddress? ip, int port)
|
||||
public Task<bool> SetAsSystemProxyAsync(bool state, IPAddress? ip, int port)
|
||||
{
|
||||
var shellContent = new StringBuilder();
|
||||
if (state)
|
||||
@@ -25,7 +25,7 @@ partial class LinuxPlatformServiceImpl
|
||||
}
|
||||
IPlatformService @this = this;
|
||||
@this.RunShell(shellContent.ToString(), false);
|
||||
return true;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -4,7 +4,7 @@ namespace BD.WTTS.Services.Implementation;
|
||||
|
||||
partial class MacCatalystPlatformServiceImpl
|
||||
{
|
||||
public bool SetAsSystemProxy(bool state, IPAddress? ip, int port)
|
||||
public Task<bool> SetAsSystemProxyAsync(bool state, IPAddress? ip, int port)
|
||||
{
|
||||
#if MACOS || MACCATALYST
|
||||
IPlatformService @this = this;
|
||||
@@ -16,10 +16,18 @@ partial class MacCatalystPlatformServiceImpl
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
shellContent.AppendLine($"networksetup -setwebproxy '{item}' '{ip}' {port}");
|
||||
shellContent.AppendLine($"networksetup -setwebproxystate '{item}' on");
|
||||
shellContent.AppendLine($"networksetup -setsecurewebproxy '{item}' '{ip}' {port}");
|
||||
shellContent.AppendLine($"networksetup -setsecurewebproxystate '{item}' on");
|
||||
if (ip != null)
|
||||
{
|
||||
var bindIP = ip?.ToString() == IPAddress.Any.ToString() ? IPAddress.Loopback : ip;
|
||||
shellContent.AppendLine($"networksetup -setwebproxy '{item}' '{bindIP}' {port}");
|
||||
shellContent.AppendLine($"networksetup -setwebproxystate '{item}' on");
|
||||
shellContent.AppendLine($"networksetup -setsecurewebproxy '{item}' '{bindIP}' {port}");
|
||||
shellContent.AppendLine($"networksetup -setsecurewebproxystate '{item}' on");
|
||||
}
|
||||
else
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -29,7 +37,7 @@ partial class MacCatalystPlatformServiceImpl
|
||||
}
|
||||
}
|
||||
@this.RunShell(shellContent.ToString(), false);
|
||||
return true;
|
||||
return Task.FromResult(true);
|
||||
#else
|
||||
throw new PlatformNotSupportedException();
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,22 @@ partial class WindowsPlatformServiceImpl : IDisposable
|
||||
isLightOrDarkThemeWatch?.Dispose();
|
||||
|
||||
IOPath.TryDeleteCacheSubDir(CacheTempDirName);
|
||||
|
||||
if (IsPrivilegedProcess)
|
||||
{
|
||||
IEnumerable<Task> ProxyDispose()
|
||||
{
|
||||
if (SetAsSystemProxyStatus)
|
||||
{
|
||||
yield return SetAsSystemProxyAsync(false, default, default);
|
||||
}
|
||||
if (SetAsSystemPACProxyStatus)
|
||||
{
|
||||
yield return SetAsSystemPACProxyAsync(false, default);
|
||||
}
|
||||
}
|
||||
Task.WaitAll(ProxyDispose().ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
isLightOrDarkThemeWatch = null;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#if WINDOWS
|
||||
using PInvoke;
|
||||
using System.Windows;
|
||||
using Vanara.PInvoke;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace BD.WTTS.Services.Implementation;
|
||||
@@ -68,6 +69,23 @@ partial class WindowsPlatformServiceImpl
|
||||
MouseHook.OnMouseUp += MouseHook_OnMouseUp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将传入句柄窗口设置无标题栏和标题栏区域按钮
|
||||
/// </summary>
|
||||
/// <param name="window"></param>
|
||||
public void BeautifyTheWindow(nint hWnd)
|
||||
{
|
||||
if (hWnd != nint.Zero)
|
||||
{
|
||||
var windowStyle = User32.GetWindowLong(hWnd, User32.WindowLongIndexFlags.GWL_STYLE);
|
||||
|
||||
// 移除最大化、关闭和最小化按钮
|
||||
windowStyle = windowStyle & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX & ~WS_CAPTION;
|
||||
|
||||
User32.SetWindowLongPtr(hWnd, User32.WindowLongIndexFlags.GWL_STYLE, windowStyle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将传入窗口设置为无边框窗口化
|
||||
/// </summary>
|
||||
|
||||
@@ -27,41 +27,44 @@ partial class WindowsPlatformServiceImpl : IRegistryService
|
||||
/// <summary>
|
||||
/// 带参数(可选/null)启动 %windir%\regedit.exe 并等待退出后删除文件
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StartProcessRegedit(
|
||||
public static async Task<byte> StartProcessRegeditAsync(
|
||||
string path,
|
||||
string contents,
|
||||
int millisecondsDelay = 3700)
|
||||
int millisecondsDelay = 3700,
|
||||
string? markKey = null,
|
||||
string? markValue = null)
|
||||
{
|
||||
File.WriteAllText(path, contents, Encoding.UTF8);
|
||||
if (IsPrivilegedProcess)
|
||||
{
|
||||
// 管理员权限则直接执行
|
||||
StartProcessRegeditCore(path, millisecondsDelay);
|
||||
await StartProcessRegeditCoreAsync(path, millisecondsDelay);
|
||||
return 200;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 通过 IPC 调用管理员服务进程执行
|
||||
var ipcPlatformService = IPlatformService.IPCRoot.Instance.GetAwaiter().GetResult();
|
||||
ipcPlatformService.StartProcessRegeditCoreIPC(path, millisecondsDelay);
|
||||
var r = await ipcPlatformService.StartProcessRegeditCoreIPCAsync(markKey, markValue, path, millisecondsDelay);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
void IRegistryService.StartProcessRegedit(
|
||||
Task<byte> IRegistryService.StartProcessRegeditAsync(
|
||||
string path,
|
||||
string contents,
|
||||
int millisecondsDelay) => StartProcessRegedit(path, contents, millisecondsDelay);
|
||||
int millisecondsDelay) => StartProcessRegeditAsync(path, contents, millisecondsDelay);
|
||||
|
||||
/// <inheritdoc cref="StartProcessRegedit(string, string, int)"/>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void StartProcessRegeditCore(
|
||||
internal static async Task StartProcessRegeditCoreAsync(
|
||||
string path,
|
||||
int millisecondsDelay = 3700)
|
||||
{
|
||||
var args = $"/s \"{path}\"";
|
||||
var p = Process2.Start(Regedit, args, workingDirectory: _windir.Value);
|
||||
IOPath.TryDeleteInDelay(p, path, millisecondsDelay, millisecondsDelay);
|
||||
await IOPath.TryDeleteInDelayAsync(p, path, millisecondsDelay, millisecondsDelay);
|
||||
}
|
||||
|
||||
#region Registry2
|
||||
|
||||
@@ -7,17 +7,13 @@ partial class WindowsPlatformServiceImpl
|
||||
{
|
||||
const string ProxyOverride = "\"ProxyOverride\"=\"localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*\"";
|
||||
|
||||
/// <summary>
|
||||
/// 设置启用或关闭系统代理
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="ip"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <returns></returns>
|
||||
public bool SetAsSystemProxy(bool state, IPAddress? ip, int port)
|
||||
internal static bool SetAsSystemProxyStatus;
|
||||
|
||||
public async Task<bool> SetAsSystemProxyAsync(bool state, IPAddress? ip, int port)
|
||||
{
|
||||
try
|
||||
{
|
||||
SetAsSystemProxyStatus = state;
|
||||
var proxyEnable = $"\"ProxyEnable\"=dword:{(state ? "00000001" : "00000000")}";
|
||||
var hasIpAndProt = ip != null && port >= 0;
|
||||
var proxyServer = hasIpAndProt ? $"\"proxyServer\"=\"{ip}:{port}\"" : "";
|
||||
@@ -30,8 +26,8 @@ Windows Registry Editor Version 5.00
|
||||
{(state ? $"{ProxyOverride}{Environment.NewLine}" : "")}{proxyServer}
|
||||
""";
|
||||
var path = IOPath.GetCacheFilePath(CacheTempDirName, "SwitchProxy", FileEx.Reg);
|
||||
StartProcessRegedit(path, contents);
|
||||
return true;
|
||||
var r = await StartProcessRegeditAsync(path, contents, markKey: nameof(SetAsSystemProxyAsync), markValue: state.ToString());
|
||||
return r == 200;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -40,16 +36,13 @@ Windows Registry Editor Version 5.00
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置启用或关闭 PAC 代理
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public bool SetAsSystemPACProxy(bool state, string? url = null)
|
||||
internal static bool SetAsSystemPACProxyStatus;
|
||||
|
||||
public async Task<bool> SetAsSystemPACProxyAsync(bool state, string? url = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
SetAsSystemPACProxyStatus = state;
|
||||
var regAutoConfigUrl = state ? $"\"AutoConfigURL\"=\"{url}\"" : "\"AutoConfigURL\"=\"\"";
|
||||
string contents =
|
||||
$"""
|
||||
@@ -59,8 +52,8 @@ Windows Registry Editor Version 5.00
|
||||
{regAutoConfigUrl}
|
||||
""";
|
||||
var path = IOPath.GetCacheFilePath(CacheTempDirName, "SwitchPacProxy", FileEx.Reg);
|
||||
StartProcessRegedit(path, contents);
|
||||
return true;
|
||||
var r = await StartProcessRegeditAsync(path, contents, markKey: nameof(SetAsSystemPACProxyAsync), markValue: state.ToString());
|
||||
return r == 200;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -37,7 +37,8 @@ partial class WindowsPlatformServiceImpl
|
||||
|
||||
public const int WS_MAXIMIZEBOX = 0x10000;
|
||||
public const int WS_MINIMIZEBOX = 0x20000;
|
||||
|
||||
public const int WS_CAPTION = 0x00C00000;
|
||||
public const int WS_BORDER = 0x00800000;
|
||||
public const int WS_SYSMENU = 0x80000;
|
||||
|
||||
public static void EnableMinimizeButton(IntPtr hWnd)
|
||||
|
||||
@@ -49,7 +49,7 @@ sealed class SteamServiceImpl2 : SteamServiceBaseImpl, ISteamConnectService
|
||||
return platform.StartAsInvoker(fileName, arguments);
|
||||
}
|
||||
|
||||
protected sealed override void SetSteamCurrentUser(string userName)
|
||||
protected sealed override async void SetSteamCurrentUser(string userName)
|
||||
{
|
||||
#if WINDOWS
|
||||
if (DesktopBridge.IsRunningAsUwp)
|
||||
@@ -63,7 +63,7 @@ Windows Registry Editor Version 5.00
|
||||
"RememberPassword"=dword:00000001
|
||||
""";
|
||||
var path = IOPath.GetCacheFilePath(WindowsPlatformServiceImpl.CacheTempDirName, "SwitchSteamUser", FileEx.Reg);
|
||||
WindowsPlatformServiceImpl.StartProcessRegedit(path, contents);
|
||||
await WindowsPlatformServiceImpl.StartProcessRegeditAsync(path, contents);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace BD.WTTS.Services;
|
||||
|
||||
public interface IProxyService
|
||||
public interface IProxyService : IDisposable, IAsyncDisposable
|
||||
{
|
||||
bool ProxyStatus { get; set; }
|
||||
}
|
||||
@@ -45,10 +45,10 @@ public sealed class UserService : ReactiveObject
|
||||
{
|
||||
var cUser = await userManager.GetCurrentUserAsync();
|
||||
if (cUser.HasValue()) return;
|
||||
//var vm = new LoginOrRegisterWindowViewModel();
|
||||
//await windowManager.ShowTaskDialogAsync(vm, vm.Title, isOkButton: false);
|
||||
var vm = new LoginOrRegisterWindowViewModel();
|
||||
await windowManager.ShowTaskDialogAsync(vm, vm.Title, isOkButton: false);
|
||||
|
||||
INavigationService.Instance.Navigate(typeof(LoginOrRegisterWindowViewModel), NavigationTransitionEffect.DrillIn);
|
||||
//INavigationService.Instance.Navigate(typeof(LoginOrRegisterWindowViewModel), NavigationTransitionEffect.DrillIn);
|
||||
}
|
||||
|
||||
public void NavigateUserCenterPage()
|
||||
|
||||
@@ -4,11 +4,11 @@ using AppResources = BD.WTTS.Client.Resources.Strings;
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace BD.WTTS.Services;
|
||||
|
||||
public sealed class NotificationService : ReactiveObject
|
||||
public sealed class NoticeService : ReactiveObject
|
||||
{
|
||||
static NotificationService? mCurrent;
|
||||
static NoticeService? mCurrent;
|
||||
|
||||
public static NotificationService Current => mCurrent ?? new();
|
||||
public static NoticeService Current => mCurrent ?? new();
|
||||
|
||||
//readonly INotificationRepository notificationRepo = Ioc.Get<INotificationRepository>();
|
||||
|
||||
@@ -22,7 +22,7 @@ public sealed class NotificationService : ReactiveObject
|
||||
|
||||
//public NoticeGroupDTO DefaultType { get; } = new NoticeGroupDTO() { Name = AppResources.AllTyoe };
|
||||
|
||||
public NotificationService()
|
||||
public NoticeService()
|
||||
{
|
||||
mCurrent = this;
|
||||
Notices = new ObservableCollection<OfficialMessageItemDTO>();
|
||||
@@ -53,6 +53,11 @@ public sealed class NotificationService : ReactiveObject
|
||||
if (item.PushTime > GeneralSettings.LastLookNoticeDateTime.Value)
|
||||
{
|
||||
item.Unread = true;
|
||||
|
||||
//只弹最新的一条通知
|
||||
if (UnreadNotificationsCount == 0 && GeneralSettings.MessagePopupNotification)
|
||||
INotificationService.Instance.Notify(item.Content, NotificationType.Announcement, title: item.Title);
|
||||
|
||||
UnreadNotificationsCount++;
|
||||
}
|
||||
}
|
||||
@@ -312,10 +312,10 @@ public sealed class SteamConnectService
|
||||
InitializeDownloadGameList();
|
||||
}
|
||||
|
||||
//if (!SteamUsers.Lookup(id).HasValue)
|
||||
//{
|
||||
// RefreshSteamUsers();
|
||||
//}
|
||||
if (!SteamUsers.Lookup(id).HasValue)
|
||||
{
|
||||
_ = RefreshSteamUsers();
|
||||
}
|
||||
|
||||
//var mainViewModel = (IWindowService.Instance.MainWindow as WindowViewModel);
|
||||
//await mainViewModel.SteamAppPage.Initialize();
|
||||
@@ -489,7 +489,7 @@ public sealed class SteamConnectService
|
||||
}
|
||||
}
|
||||
|
||||
public async void RefreshSteamUsers()
|
||||
public async Task RefreshSteamUsers()
|
||||
{
|
||||
var list = stmService.GetRememberUserList();
|
||||
|
||||
|
||||
@@ -4,13 +4,50 @@ namespace BD.WTTS.Services;
|
||||
partial interface IPCPlatformService
|
||||
{
|
||||
#if !LIB_CLIENT_IPC
|
||||
/// <inheritdoc cref="WindowsPlatformServiceImpl.StartProcessRegedit(string, string, int)"/>
|
||||
/// <inheritdoc cref="WindowsPlatformServiceImpl.StartProcessRegeditAsync(string, string, int)"/>
|
||||
#endif
|
||||
[SupportedOSPlatform("windows")]
|
||||
void StartProcessRegeditCoreIPC(string path, int millisecondsDelay)
|
||||
{
|
||||
|
||||
#if !LIB_CLIENT_IPC && WINDOWS
|
||||
WindowsPlatformServiceImpl.StartProcessRegeditCore(path, millisecondsDelay);
|
||||
async
|
||||
#endif
|
||||
Task<byte> StartProcessRegeditCoreIPCAsync(
|
||||
string? markKey,
|
||||
string? markValue,
|
||||
string path,
|
||||
int millisecondsDelay)
|
||||
{
|
||||
const byte Code_Ok = 200;
|
||||
#if !LIB_CLIENT_IPC && WINDOWS
|
||||
|
||||
switch (markKey)
|
||||
{
|
||||
case nameof(WindowsPlatformServiceImpl.SetAsSystemProxyAsync):
|
||||
if (markValue == bool.TrueString)
|
||||
{
|
||||
WindowsPlatformServiceImpl.SetAsSystemProxyStatus = true;
|
||||
}
|
||||
else if (markValue == bool.FalseString)
|
||||
{
|
||||
WindowsPlatformServiceImpl.SetAsSystemProxyStatus = false;
|
||||
}
|
||||
break;
|
||||
case nameof(WindowsPlatformServiceImpl.SetAsSystemPACProxyAsync):
|
||||
if (markValue == bool.TrueString)
|
||||
{
|
||||
WindowsPlatformServiceImpl.SetAsSystemPACProxyStatus = true;
|
||||
}
|
||||
else if (markValue == bool.FalseString)
|
||||
{
|
||||
WindowsPlatformServiceImpl.SetAsSystemPACProxyStatus = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
await WindowsPlatformServiceImpl.StartProcessRegeditCoreAsync(path, millisecondsDelay);
|
||||
return Code_Ok;
|
||||
#else
|
||||
return Task.FromResult(Code_Ok);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,12 @@ partial interface IPlatformService
|
||||
/// <param name="action">目标窗口回调</param>
|
||||
void GetMoveMouseDownWindow(Action<NativeWindowModel> action);
|
||||
|
||||
/// <summary>
|
||||
/// 将传入句柄窗口设置无标题栏和标题栏区域按钮
|
||||
/// </summary>
|
||||
/// <param name="window"></param>
|
||||
void BeautifyTheWindow(nint hWnd);
|
||||
|
||||
/// <summary>
|
||||
/// 将传入窗口设置为无边框窗口化
|
||||
/// </summary>
|
||||
|
||||
@@ -7,7 +7,7 @@ partial interface IPlatformService
|
||||
/// <summary>
|
||||
/// 设置启用或关闭系统代理
|
||||
/// </summary>
|
||||
bool SetAsSystemProxy(bool state, IPAddress? ip = null, int port = -1) => false;
|
||||
Task<bool> SetAsSystemProxyAsync(bool state, IPAddress? ip = null, int port = -1) => Task.FromResult(false);
|
||||
|
||||
/// <summary>
|
||||
/// 设置启用或关闭 PAC 代理
|
||||
@@ -15,5 +15,5 @@ partial interface IPlatformService
|
||||
/// <param name="state"></param>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
bool SetAsSystemPACProxy(bool state, string? url = null) => false;
|
||||
Task<bool> SetAsSystemPACProxyAsync(bool state, string? url = null) => Task.FromResult(false);
|
||||
}
|
||||
@@ -34,7 +34,8 @@ public interface IWindowManager
|
||||
string? okButtonText = null,
|
||||
string? retryButtonText = null,
|
||||
string? moreInfoText = null,
|
||||
Func<bool>? cancelCloseAction = null)
|
||||
Func<bool>? cancelCloseAction = null,
|
||||
bool disableScroll = false)
|
||||
where TPageViewModel : ViewModelBase;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -6,7 +6,7 @@ public interface INavigationService
|
||||
|
||||
public object? GetViewModelToPageContent(object viewModel, bool isCreateInstance = true);
|
||||
|
||||
public void Navigate(Type t, NavigationTransitionEffect effect = NavigationTransitionEffect.None);
|
||||
public void Navigate(Type? t, NavigationTransitionEffect effect = NavigationTransitionEffect.None);
|
||||
|
||||
public void GoBack();
|
||||
|
||||
|
||||
@@ -45,6 +45,11 @@ public partial interface IGeneralSettings
|
||||
/// </summary>
|
||||
bool TrayIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 启用消息推送通知
|
||||
/// </summary>
|
||||
bool MessagePopupNotification { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 游戏列表使用本地缓存
|
||||
/// </summary>
|
||||
@@ -159,6 +164,11 @@ public partial interface IGeneralSettings
|
||||
/// </summary>
|
||||
const bool DefaultTrayIcon = true;
|
||||
|
||||
/// <summary>
|
||||
/// 启用消息推送通知的默认值
|
||||
/// </summary>
|
||||
const bool DefaultMessagePopupNotification = true;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏列表使用本地缓存的默认值
|
||||
/// </summary>
|
||||
|
||||
@@ -191,7 +191,7 @@ public partial interface IUISettings
|
||||
/// <summary>
|
||||
/// 自定义背景图像路径的默认值
|
||||
/// </summary>
|
||||
const string DefaultWindowBackgroundCustomImagePath = "/UI/Assets/back.png";
|
||||
const string DefaultWindowBackgroundCustomImagePath = "avares://BD.WTTS.Client.Avalonia/UI/Assets/back.png";
|
||||
|
||||
/// <summary>
|
||||
/// 自定义背景图像不透明度的默认值
|
||||
|
||||
@@ -74,57 +74,63 @@ public sealed partial class GeneralSettings_ : IGeneralSettings, ISettings, ISet
|
||||
public bool TrayIcon { get; set; } = IGeneralSettings.DefaultTrayIcon;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏列表使用本地缓存
|
||||
/// 启用消息推送通知
|
||||
/// </summary>
|
||||
[MPKey(5), MP2Key(5), JsonPropertyOrder(5)]
|
||||
public bool MessagePopupNotification { get; set; } = IGeneralSettings.DefaultMessagePopupNotification;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏列表使用本地缓存
|
||||
/// </summary>
|
||||
[MPKey(6), MP2Key(6), JsonPropertyOrder(6)]
|
||||
public bool GameListUseLocalCache { get; set; } = IGeneralSettings.DefaultGameListUseLocalCache;
|
||||
|
||||
/// <summary>
|
||||
/// 文本阅读器提供商,值为程序路径
|
||||
/// </summary>
|
||||
[MPKey(6), MP2Key(6), JsonPropertyOrder(6)]
|
||||
[MPKey(7), MP2Key(7), JsonPropertyOrder(7)]
|
||||
public Dictionary<Platform, string>? TextReaderProvider { get; set; } = IGeneralSettings.DefaultTextReaderProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Hosts 文件编码类型
|
||||
/// </summary>
|
||||
[MPKey(7), MP2Key(7), JsonPropertyOrder(7)]
|
||||
[MPKey(8), MP2Key(8), JsonPropertyOrder(8)]
|
||||
public EncodingType HostsFileEncodingType { get; set; } = IGeneralSettings.DefaultHostsFileEncodingType;
|
||||
|
||||
/// <summary>
|
||||
/// 是否使用硬件加速
|
||||
/// </summary>
|
||||
[MPKey(8), MP2Key(8), JsonPropertyOrder(8)]
|
||||
[MPKey(9), MP2Key(9), JsonPropertyOrder(9)]
|
||||
public bool GPU { get; set; } = IGeneralSettings.DefaultGPU;
|
||||
|
||||
/// <summary>
|
||||
/// 使用本机 OpenGL
|
||||
/// </summary>
|
||||
[MPKey(9), MP2Key(9), JsonPropertyOrder(9)]
|
||||
[MPKey(10), MP2Key(10), JsonPropertyOrder(10)]
|
||||
public bool NativeOpenGL { get; set; } = IGeneralSettings.DefaultNativeOpenGL;
|
||||
|
||||
/// <summary>
|
||||
/// 屏幕捕获/允许截图,在一些含有机密的页面上是否允许截图,默认为 <see langword="false"/>
|
||||
/// </summary>
|
||||
[MPKey(10), MP2Key(10), JsonPropertyOrder(10)]
|
||||
[MPKey(11), MP2Key(11), JsonPropertyOrder(11)]
|
||||
public bool ScreenCapture { get; set; } = IGeneralSettings.DefaultScreenCapture;
|
||||
|
||||
/// <summary>
|
||||
/// 禁用插件
|
||||
/// </summary>
|
||||
[MPKey(11), MP2Key(11), JsonPropertyOrder(11)]
|
||||
[MPKey(12), MP2Key(12), JsonPropertyOrder(12)]
|
||||
public HashSet<string>? DisablePlugins { get; set; } = IGeneralSettings.DefaultDisablePlugins;
|
||||
|
||||
/// <summary>
|
||||
/// 插件安全模式
|
||||
/// </summary>
|
||||
[MPKey(12), MP2Key(12), JsonPropertyOrder(12)]
|
||||
[MPKey(13), MP2Key(13), JsonPropertyOrder(13)]
|
||||
public bool PluginSafeMode { get; set; } = IGeneralSettings.DefaultPluginSafeMode;
|
||||
|
||||
/// <summary>
|
||||
/// 最后查看通知时间
|
||||
/// </summary>
|
||||
[MPKey(13), MP2Key(13), JsonPropertyOrder(13)]
|
||||
[MPKey(14), MP2Key(14), JsonPropertyOrder(14)]
|
||||
public DateTimeOffset LastLookNoticeDateTime { get; set; } = IGeneralSettings.DefaultLastLookNoticeDateTime;
|
||||
|
||||
#region 配置应用程序的 Web 代理
|
||||
@@ -132,49 +138,49 @@ public sealed partial class GeneralSettings_ : IGeneralSettings, ISettings, ISet
|
||||
/// <summary>
|
||||
/// Web 代理模式
|
||||
/// </summary>
|
||||
[MPKey(14), MP2Key(14), JsonPropertyOrder(14)]
|
||||
[MPKey(15), MP2Key(15), JsonPropertyOrder(15)]
|
||||
public AppWebProxyMode WebProxyMode { get; set; } = IGeneralSettings.DefaultWebProxyMode;
|
||||
|
||||
/// <summary>
|
||||
/// Web 自定义代理 Host
|
||||
/// </summary>
|
||||
[MPKey(15), MP2Key(15), JsonPropertyOrder(15)]
|
||||
[MPKey(16), MP2Key(16), JsonPropertyOrder(16)]
|
||||
public string? CustomWebProxyModeHost { get; set; } = IGeneralSettings.DefaultCustomWebProxyModeHost;
|
||||
|
||||
/// <summary>
|
||||
/// Web 自定义代理 Port
|
||||
/// </summary>
|
||||
[MPKey(16), MP2Key(16), JsonPropertyOrder(16)]
|
||||
[MPKey(17), MP2Key(17), JsonPropertyOrder(17)]
|
||||
public int CustomWebProxyModePort { get; set; } = IGeneralSettings.DefaultCustomWebProxyModePort;
|
||||
|
||||
/// <summary>
|
||||
/// Web 自定义代理 Address
|
||||
/// </summary>
|
||||
[MPKey(17), MP2Key(17), JsonPropertyOrder(17)]
|
||||
[MPKey(18), MP2Key(18), JsonPropertyOrder(18)]
|
||||
public string? CustomWebProxyModeAddress { get; set; } = IGeneralSettings.DefaultCustomWebProxyModeAddress;
|
||||
|
||||
/// <summary>
|
||||
/// Web 自定义代理 BypassOnLocal
|
||||
/// </summary>
|
||||
[MPKey(18), MP2Key(18), JsonPropertyOrder(18)]
|
||||
[MPKey(19), MP2Key(19), JsonPropertyOrder(19)]
|
||||
public bool CustomWebProxyModeBypassOnLocal { get; set; } = IGeneralSettings.DefaultCustomWebProxyModeBypassOnLocal;
|
||||
|
||||
/// <summary>
|
||||
/// Web 自定义代理 NetworkCredential.UserName
|
||||
/// </summary>
|
||||
[MPKey(19), MP2Key(19), JsonPropertyOrder(19)]
|
||||
[MPKey(20), MP2Key(20), JsonPropertyOrder(20)]
|
||||
public string? CustomWebProxyModeCredentialUserName { get; set; } = IGeneralSettings.DefaultCustomWebProxyModeCredentialUserName;
|
||||
|
||||
/// <summary>
|
||||
/// Web 自定义代理 NetworkCredential.Password
|
||||
/// </summary>
|
||||
[MPKey(20), MP2Key(20), JsonPropertyOrder(20)]
|
||||
[MPKey(21), MP2Key(21), JsonPropertyOrder(21)]
|
||||
public string? CustomWebProxyModeCredentialPassword { get; set; } = IGeneralSettings.DefaultCustomWebProxyModeCredentialPassword;
|
||||
|
||||
/// <summary>
|
||||
/// Web 自定义代理 NetworkCredential.Domain
|
||||
/// </summary>
|
||||
[MPKey(21), MP2Key(21), JsonPropertyOrder(21)]
|
||||
[MPKey(22), MP2Key(22), JsonPropertyOrder(22)]
|
||||
public string? CustomWebProxyModeCredentialDomain { get; set; } = IGeneralSettings.DefaultCustomWebProxyModeCredentialDomain;
|
||||
|
||||
#endregion
|
||||
@@ -213,6 +219,12 @@ public static partial class GeneralSettings
|
||||
public static SettingsStructProperty<bool, GeneralSettings_> TrayIcon { get; }
|
||||
= new(DefaultTrayIcon);
|
||||
|
||||
/// <summary>
|
||||
/// 启用消息推送通知
|
||||
/// </summary>
|
||||
public static SettingsStructProperty<bool, GeneralSettings_> MessagePopupNotification { get; }
|
||||
= new(DefaultMessagePopupNotification);
|
||||
|
||||
/// <summary>
|
||||
/// 游戏列表使用本地缓存
|
||||
/// </summary>
|
||||
|
||||
@@ -66,10 +66,6 @@ public class SettingsStructPropertyBase<TValue, [DynamicallyAccessedMembers(Dyna
|
||||
this.value = value; // 赋值当前字段
|
||||
|
||||
var setter_value = value;
|
||||
if (EqualityComparer<TValue>.Default.Equals(value, Default))
|
||||
{
|
||||
setter_value = default;
|
||||
}
|
||||
setter(monitor.CurrentValue, setter_value); // 赋值模型类属性
|
||||
|
||||
OnValueChanged(oldValue, value); // 调用变更事件
|
||||
|
||||
@@ -48,7 +48,7 @@ partial class Startup // 自定义控制台命令参数
|
||||
devtools.AddOption(new Option<bool>("-disable_gpu", () => false, "禁用 GPU 硬件加速"));
|
||||
devtools.AddOption(new Option<bool>("-use_wgl", () => false, "使用 Native OpenGL(仅 Windows)"));
|
||||
devtools.AddOption(new Option<bool>("-use_localhost", () => false, "使用本机服务端"));
|
||||
devtools.AddOption(new Option<bool>("-steamrun", () => true, "Steam 内启动"));
|
||||
devtools.AddOption(new Option<bool>("-steamrun", () => false, "Steam 内启动"));
|
||||
devtools.Handler = CommandHandler.Create((bool disable_gpu, bool use_wgl, bool use_localhost, bool steamrun) =>
|
||||
{
|
||||
#if DEBUG
|
||||
@@ -152,8 +152,10 @@ partial class Startup // 自定义控制台命令参数
|
||||
RunUIApplication(AppServicesLevel.Steam);
|
||||
await WaitConfiguredServices;
|
||||
|
||||
SteamConnectService.Current.Initialize(id);
|
||||
await new TaskCompletionSource().Task;
|
||||
if (SteamConnectService.Current.Initialize(id))
|
||||
{
|
||||
await new TaskCompletionSource().Task;
|
||||
}
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
|
||||
@@ -9,8 +9,14 @@ partial class Startup // OnStartup
|
||||
|
||||
}
|
||||
|
||||
protected static void ShowSettingsModifiedRestartThisSoft()
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void ShowSettingsModifiedRestartThisSoft()
|
||||
{
|
||||
if (Ioc.Get_Nullable<IToastIntercept>() is StartupToastIntercept intercept
|
||||
&& !intercept.IsStartuped)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Toast.Show(ToastIcon.Info, Strings.SettingsModifiedRestartThisSoft);
|
||||
}
|
||||
|
||||
|
||||