mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-26 20:20:14 +08:00
Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44b4a3b05e | ||
|
|
ac91872815 | ||
|
|
2795dbac5f | ||
|
|
4e2fe256ed | ||
|
|
83c515542c | ||
|
|
0c9f25a304 | ||
|
|
63be2ba037 | ||
|
|
4c464623b8 | ||
|
|
7c16daafba | ||
|
|
2acc0a95e0 | ||
|
|
8072b16d42 | ||
|
|
9766e9e71b | ||
|
|
d39f63db65 | ||
|
|
fd6235f110 | ||
|
|
4a9a53dda8 | ||
|
|
4668e26b65 | ||
|
|
c5f24ae32c | ||
|
|
1acf872e80 | ||
|
|
82ea1a62e9 | ||
|
|
04b0c0e433 | ||
|
|
8dfb37bf8b | ||
|
|
a19b3128db | ||
|
|
f70b349229 | ||
|
|
ed104071c2 |
+8
-1
@@ -212,7 +212,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinAuth", "ref\WinAuth\src\
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BD.WTTS.Client.Tools.OpenSourceLibraryList", "src\BD.WTTS.Client.Tools.OpenSourceLibraryList\BD.WTTS.Client.Tools.OpenSourceLibraryList.csproj", "{64F0101B-F54C-442E-BA70-738ACF72247F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BD.WTTS.Client.Plugins.SteamIdleCard", "src\BD.WTTS.Client.Plugins.SteamIdleCard\BD.WTTS.Client.Plugins.SteamIdleCard.csproj", "{80B51074-9473-4635-9B8F-4EB00B9ADCE7}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BD.WTTS.Client.Plugins.SteamIdleCard", "src\BD.WTTS.Client.Plugins.SteamIdleCard\BD.WTTS.Client.Plugins.SteamIdleCard.csproj", "{80B51074-9473-4635-9B8F-4EB00B9ADCE7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BD.WTTS.Client.Tools.HostsTest", "src\BD.WTTS.Client.Tools.HostsTest\BD.WTTS.Client.Tools.HostsTest.csproj", "{13A7EBC3-7574-41BF-9657-CEC2053E54EC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -412,6 +414,10 @@ Global
|
||||
{80B51074-9473-4635-9B8F-4EB00B9ADCE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{80B51074-9473-4635-9B8F-4EB00B9ADCE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{80B51074-9473-4635-9B8F-4EB00B9ADCE7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{13A7EBC3-7574-41BF-9657-CEC2053E54EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{13A7EBC3-7574-41BF-9657-CEC2053E54EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{13A7EBC3-7574-41BF-9657-CEC2053E54EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{13A7EBC3-7574-41BF-9657-CEC2053E54EC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -477,6 +483,7 @@ Global
|
||||
{3F67183A-CC29-4B60-B534-08C2FB1A6746} = {84FF822C-BF60-493F-A8C8-6A413167E3DA}
|
||||
{64F0101B-F54C-442E-BA70-738ACF72247F} = {D6C8A54D-878F-44A9-857F-6ED01491C7BD}
|
||||
{80B51074-9473-4635-9B8F-4EB00B9ADCE7} = {A5828819-62AB-4B03-A083-8B6ED4915AA3}
|
||||
{13A7EBC3-7574-41BF-9657-CEC2053E54EC} = {D6C8A54D-878F-44A9-857F-6ED01491C7BD}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {567F588F-E95C-4286-8B30-DB3B2200221C}
|
||||
|
||||
@@ -40,6 +40,19 @@ Install_certutil() {
|
||||
echo "certutil 工具已安装。"
|
||||
fi
|
||||
}
|
||||
certutil_Init() {
|
||||
certutil -d sql:$HOME/.pki/nssdb -L
|
||||
ret=$?
|
||||
if [ $ret -ne 0 ]; then
|
||||
echo "即将初始化 certutil sql:\$HOME/.pki/nssdb"
|
||||
mkdir -p sql:$HOME/.pki
|
||||
mkdir -p sql:$HOME/.pki/nssdb
|
||||
chmod 700 sql:$HOME/.pki/nssdb
|
||||
certutil -d sql:$HOME/.pki/nssdb -N --empty-password
|
||||
else
|
||||
echo "certutil nssdb 正常"
|
||||
fi
|
||||
}
|
||||
Install_jq() {
|
||||
# Check if jq is already installed
|
||||
if command -v jq &>/dev/null; then
|
||||
@@ -294,6 +307,7 @@ exit" >"$base_path/$exec_name.sh"
|
||||
Install_certutil
|
||||
Install_zenity
|
||||
Install_jq
|
||||
certutil_Init
|
||||
#版本检查更新;
|
||||
Get_NewVer
|
||||
|
||||
|
||||
+1
-1
Submodule ref/Avalonia.Image2 updated: c4b9002eb4...fe1d03f448
+1
-1
Submodule ref/Common updated: a7b6b65810...e258b48fbf
+1
-1
Submodule ref/DirectoryPackages updated: 2389197178...1620792f9f
+1
-1
Submodule ref/SteamClient updated: 59fa4c07f6...8215a2f260
@@ -14,7 +14,7 @@ public static partial class AssemblyInfo
|
||||
/// <summary>
|
||||
/// 预览版本号,范围 1~9
|
||||
/// </summary>
|
||||
const string ver_for_preview = "4";
|
||||
const string ver_for_preview = "6";
|
||||
|
||||
/// <summary>
|
||||
/// RC 版本号,范围 0~9
|
||||
|
||||
@@ -58,6 +58,7 @@ sealed partial class Program : Startup
|
||||
// Essentials
|
||||
#if LINUX
|
||||
services.TryAddSingleton<IApplicationVersionService, Essentials_AppVerS>();
|
||||
services.AddSingleton<IDeviceInfoPlatformService, LinuxDeviceInfoPlatformServiceImpl>();
|
||||
#else
|
||||
#if WINDOWS
|
||||
#if AVALONIA
|
||||
@@ -252,6 +253,30 @@ sealed partial class Program : Startup
|
||||
string IApplicationVersionService.AssemblyTrademark => AssemblyInfo.Trademark;
|
||||
}
|
||||
|
||||
#if LINUX
|
||||
sealed class LinuxDeviceInfoPlatformServiceImpl : IDeviceInfoPlatformService
|
||||
{
|
||||
public string Model => "";
|
||||
|
||||
public string Manufacturer => "";
|
||||
|
||||
public string Name => "";
|
||||
|
||||
public string VersionString => Environment.OSVersion.VersionString;
|
||||
|
||||
public DeviceType DeviceType => DeviceType.Physical;
|
||||
|
||||
public bool IsChromeOS => false;
|
||||
|
||||
public bool IsWinUI => false;
|
||||
|
||||
public bool IsUWP => false;
|
||||
|
||||
public DeviceIdiom Idiom => DeviceIdiom.Desktop;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if AVALONIA && WINDOWS
|
||||
sealed class AvaWinDeviceInfoPlatformServiceImpl :
|
||||
Common.Services.Implementation.Essentials.DeviceInfoPlatformServiceImpl
|
||||
|
||||
+5
-1
@@ -1,4 +1,6 @@
|
||||
#if LINUX
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
|
||||
namespace BD.WTTS.Services.Implementation;
|
||||
|
||||
public sealed class AvaloniaClipboardPlatformService : IClipboardPlatformService
|
||||
@@ -28,7 +30,9 @@ public sealed class AvaloniaClipboardPlatformService : IClipboardPlatformService
|
||||
var clipboard = topLevel.Clipboard;
|
||||
if (clipboard != null)
|
||||
{
|
||||
await clipboard.SetTextAsync(text);
|
||||
//不能用 await 等待 Linux 上不知啥原因导致卡死
|
||||
clipboard.SetTextAsync(text).GetAwaiter();
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,9 +81,9 @@ public sealed class CustomFilePicker : ContentControl
|
||||
{
|
||||
FileName = result.FullPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.Show(ToastIcon.Warning, Strings.PleaseSelect);
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// Toast.Show(ToastIcon.Warning, Strings.PleaseSelect);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:generic="using:System.Collections.Generic"
|
||||
xmlns:i="using:Avalonia.Xaml.Interactivity"
|
||||
xmlns:ia="using:Avalonia.Xaml.Interactions.Core"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
@@ -34,7 +35,7 @@
|
||||
ClipToBounds="True"
|
||||
CornerRadius="8">
|
||||
<Panel>
|
||||
<Carousel Name="Carousel" Grid.Column="1">
|
||||
<Carousel Name="CarouselControl" Grid.Column="1">
|
||||
<Carousel.PageTransition>
|
||||
<PageSlide Orientation="Horizontal" Duration="0.25" />
|
||||
</Carousel.PageTransition>
|
||||
@@ -69,21 +70,25 @@
|
||||
Spacing="8" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate x:DataType="x:Int32">
|
||||
<DataTemplate>
|
||||
<DataTemplate.DataType>
|
||||
<x:Type x:TypeArguments="x:Int32, x:String" TypeName="generic:KeyValuePair" />
|
||||
</DataTemplate.DataType>
|
||||
<Button
|
||||
Padding="0"
|
||||
Classes="Plain"
|
||||
Click="CarouselBannerIndexButton_Click"
|
||||
Tag="{Binding}">
|
||||
Tag="{Binding Key}">
|
||||
<Ellipse
|
||||
Name="IndexEllipse"
|
||||
Width="10"
|
||||
Height="10"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Fill="{Binding Value}"
|
||||
Opacity="0.6"
|
||||
StrokeThickness="0" />
|
||||
<i:Interaction.Behaviors>
|
||||
<!--<i:Interaction.Behaviors>
|
||||
<ia:DataTriggerBehavior
|
||||
Binding="{Binding}"
|
||||
ComparisonCondition="Equal"
|
||||
@@ -91,7 +96,7 @@
|
||||
<ia:ChangePropertyAction
|
||||
PropertyName="Fill"
|
||||
TargetObject="IndexEllipse"
|
||||
Value="#FFFFFF" />
|
||||
Value="White" />
|
||||
</ia:DataTriggerBehavior>
|
||||
<ia:DataTriggerBehavior
|
||||
Binding="{Binding}"
|
||||
@@ -100,9 +105,9 @@
|
||||
<ia:ChangePropertyAction
|
||||
PropertyName="Fill"
|
||||
TargetObject="IndexEllipse"
|
||||
Value="#ADADAD" />
|
||||
Value="Gray" />
|
||||
</ia:DataTriggerBehavior>
|
||||
</i:Interaction.Behaviors>
|
||||
</i:Interaction.Behaviors>-->
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
|
||||
@@ -73,14 +73,14 @@ namespace BD.WTTS.UI.Views.Controls
|
||||
Left.Click += (s, e) => SwiperPrevious();
|
||||
Right.Click += (s, e) => SwiperNext();
|
||||
|
||||
//Carousel[!Carousel.Items] = this[!Items];
|
||||
Carousel[!Carousel.ItemsSourceProperty] = this[!ItemsSourceProperty];
|
||||
Carousel[!Carousel.ItemTemplateProperty] = this[!ItemTemplateProperty];
|
||||
//CarouselControl[!Carousel.Items] = this[!Items];
|
||||
CarouselControl[!Carousel.ItemsSourceProperty] = this[!ItemsSourceProperty];
|
||||
CarouselControl[!Carousel.ItemTemplateProperty] = this[!ItemTemplateProperty];
|
||||
|
||||
this.GetObservable(ItemsSourceProperty)
|
||||
.Subscribe(_ => SwipersLoad());
|
||||
|
||||
Carousel.GetObservable(Carousel.SelectedIndexProperty)
|
||||
CarouselControl.GetObservable(Carousel.SelectedIndexProperty)
|
||||
.Subscribe(x => SwipersLoad());
|
||||
|
||||
this.GetObservable(AutoScrollProperty)
|
||||
@@ -111,18 +111,18 @@ namespace BD.WTTS.UI.Views.Controls
|
||||
{
|
||||
if (sender is Button button && button.Tag is int index)
|
||||
{
|
||||
Carousel.SelectedIndex = index;
|
||||
CarouselControl.SelectedIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
private void SwipersLoad()
|
||||
{
|
||||
if (Carousel.ItemCount <= 0)
|
||||
if (CarouselControl.ItemCount <= 0)
|
||||
{
|
||||
Swiper.ItemsSource = null;
|
||||
return;
|
||||
}
|
||||
if (Carousel.ItemCount == 1)
|
||||
if (CarouselControl.ItemCount == 1)
|
||||
{
|
||||
Left.IsVisible = Right.IsVisible = Swiper.IsVisible = false;
|
||||
return;
|
||||
@@ -130,13 +130,13 @@ namespace BD.WTTS.UI.Views.Controls
|
||||
else
|
||||
{
|
||||
Left.IsVisible = Right.IsVisible = Swiper.IsVisible = true;
|
||||
var arr = new int[Carousel.ItemCount];
|
||||
for (var i = 0; i < arr.Length; i++)
|
||||
var arr = new Dictionary<int, string>();
|
||||
for (var i = 0; i < CarouselControl.ItemCount; i++)
|
||||
{
|
||||
arr[i] = i;
|
||||
arr.Add(i, "#ADADAD");
|
||||
}
|
||||
//var index = Carousel.SelectedIndex < 0 ? 0 : Carousel.SelectedIndex;
|
||||
//arr[index] = "#FFFFFF";
|
||||
var index = CarouselControl.SelectedIndex < 0 ? 0 : CarouselControl.SelectedIndex;
|
||||
arr[index] = "#FFFFFF";
|
||||
|
||||
Swiper.ItemsSource = arr;
|
||||
}
|
||||
@@ -144,29 +144,29 @@ namespace BD.WTTS.UI.Views.Controls
|
||||
|
||||
private void SwiperNext()
|
||||
{
|
||||
if (Carousel.ItemCount < 1)
|
||||
if (CarouselControl.ItemCount < 1)
|
||||
return;
|
||||
if (Carousel.SelectedIndex < Carousel.ItemCount - 1)
|
||||
if (CarouselControl.SelectedIndex < CarouselControl.ItemCount - 1)
|
||||
{
|
||||
Carousel.Next();
|
||||
CarouselControl.Next();
|
||||
}
|
||||
else
|
||||
{
|
||||
Carousel.SelectedIndex = 0;
|
||||
CarouselControl.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void SwiperPrevious()
|
||||
{
|
||||
if (Carousel.ItemCount < 1)
|
||||
if (CarouselControl.ItemCount < 1)
|
||||
return;
|
||||
if (Carousel.SelectedIndex > 0)
|
||||
if (CarouselControl.SelectedIndex > 0)
|
||||
{
|
||||
Carousel.Previous();
|
||||
CarouselControl.Previous();
|
||||
}
|
||||
else
|
||||
{
|
||||
Carousel.SelectedIndex = Carousel.ItemCount - 1;
|
||||
CarouselControl.SelectedIndex = CarouselControl.ItemCount - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,166 +67,166 @@
|
||||
</StackPanel>
|
||||
</spp:PageBase.ActionContent>-->
|
||||
<ScrollViewer Padding="20">
|
||||
<spp:ContentLoader IsLoading="False">
|
||||
<StackPanel
|
||||
x:Name="HomeRoot"
|
||||
MaxWidth="1080"
|
||||
Spacing="20">
|
||||
<spp:Snackbar
|
||||
Title="{Binding Path=Res.Notice_Tray_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
VerticalAlignment="Top"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
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}}"
|
||||
VerticalAlignment="Top"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
IsVisible="{Binding !!!MainWindow2.PluginCount, Mode=OneWay, Source={x:Static s:IViewModelManager.Instance}}"
|
||||
Message="检测到你没有安装插件,请去下载插件即可使用更多功能。"
|
||||
Severity="Warning" />
|
||||
<!--<spp:ContentLoader IsLoading="False">-->
|
||||
<StackPanel
|
||||
x:Name="HomeRoot"
|
||||
MaxWidth="1080"
|
||||
Spacing="20">
|
||||
<spp:Snackbar
|
||||
Title="{Binding Path=Res.Notice_Tray_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
VerticalAlignment="Top"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
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}}"
|
||||
VerticalAlignment="Top"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
IsVisible="{Binding !!!MainWindow2.PluginCount, Mode=OneWay, Source={x:Static s:IViewModelManager.Instance}}"
|
||||
Message="检测到你没有安装插件,请去下载插件即可使用更多功能。"
|
||||
Severity="Warning" />
|
||||
|
||||
<WrapPanel Margin="5,0">
|
||||
<WrapPanel IsVisible="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser, Mode=OneWay, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}">
|
||||
<spp:Image2
|
||||
Width="36"
|
||||
Height="36"
|
||||
Margin="0,0,5,0"
|
||||
VerticalAlignment="Center"
|
||||
DecodeWidth="36"
|
||||
Source="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser.AvatarMedium, Mode=OneWay}"
|
||||
Stretch="Uniform">
|
||||
<spp:Image2.Clip>
|
||||
<EllipseGeometry Rect="0,0,36,36" />
|
||||
</spp:Image2.Clip>
|
||||
</spp:Image2>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser.SteamNickName, Mode=OneWay}"
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser.IPCountry, Mode=OneWay, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}"
|
||||
Text="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser.IPCountry, Mode=OneWay, StringFormat={}({0})}"
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
VerticalAlignment="Center"
|
||||
Text=","
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
</WrapPanel>
|
||||
<TextBlock VerticalAlignment="Center" Theme="{StaticResource SubtitleTextBlockStyle}">
|
||||
<Run Text="{Binding Path=Res.Welcome_User_, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</TextBlock>
|
||||
<WrapPanel Margin="5,0">
|
||||
<WrapPanel IsVisible="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser, Mode=OneWay, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}">
|
||||
<spp:Image2
|
||||
Width="36"
|
||||
Height="36"
|
||||
Margin="0,0,5,0"
|
||||
VerticalAlignment="Center"
|
||||
DecodeWidth="36"
|
||||
Source="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser.AvatarMedium, Mode=OneWay}"
|
||||
Stretch="Uniform">
|
||||
<spp:Image2.Clip>
|
||||
<EllipseGeometry Rect="0,0,36,36" />
|
||||
</spp:Image2.Clip>
|
||||
</spp:Image2>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser.SteamNickName, Mode=OneWay}"
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser.IPCountry, Mode=OneWay, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}"
|
||||
Text="{Binding Source={x:Static s:SteamConnectService.Current}, Path=CurrentSteamUser.IPCountry, Mode=OneWay, StringFormat={}({0})}"
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
VerticalAlignment="Center"
|
||||
Text=","
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
</WrapPanel>
|
||||
<TextBlock VerticalAlignment="Center" Theme="{StaticResource SubtitleTextBlockStyle}">
|
||||
<Run Text="{Binding Path=Res.Welcome_User_, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</TextBlock>
|
||||
</WrapPanel>
|
||||
|
||||
<Grid Margin="0,-10,0,0" RowDefinitions="Auto,*">
|
||||
<spp:CarouselBanner
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
ItemsSource="{Binding NavigationBanners}">
|
||||
<spp:CarouselBanner.ItemTemplate>
|
||||
<DataTemplate DataType="spp:AdvertisementDTO">
|
||||
<spp:AppItem
|
||||
Title="{Binding Describe}"
|
||||
Height="350"
|
||||
Classes="Banner Scale"
|
||||
ClickCommand="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
ClickCommandParameter="{Binding Url}"
|
||||
Description="{Binding Name}">
|
||||
<spp:AppItem.Status>
|
||||
<Border
|
||||
Padding="20,10"
|
||||
Background="{DynamicResource AccentFillColorSelectedTextBackgroundBrush}"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}">
|
||||
<TextBlock FontSize="16" Text="阅读更多" />
|
||||
</Border>
|
||||
</spp:AppItem.Status>
|
||||
<spp:AppItem.Image>
|
||||
<spp:Image2 Source="{Binding ImageUrl}" />
|
||||
</spp:AppItem.Image>
|
||||
</spp:AppItem>
|
||||
</DataTemplate>
|
||||
</spp:CarouselBanner.ItemTemplate>
|
||||
</spp:CarouselBanner>
|
||||
</Grid>
|
||||
<Grid Margin="0,-10,0,0" RowDefinitions="Auto,*">
|
||||
<spp:CarouselBanner
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
ItemsSource="{Binding NavigationBanners}">
|
||||
<spp:CarouselBanner.ItemTemplate>
|
||||
<DataTemplate DataType="spp:AdvertisementDTO">
|
||||
<spp:AppItem
|
||||
Title="{Binding Describe}"
|
||||
Height="350"
|
||||
Classes="Banner Scale"
|
||||
ClickCommand="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
ClickCommandParameter="{Binding Url}"
|
||||
Description="{Binding Name}">
|
||||
<spp:AppItem.Status>
|
||||
<Border
|
||||
Padding="20,10"
|
||||
Background="{DynamicResource AccentFillColorSelectedTextBackgroundBrush}"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}">
|
||||
<TextBlock FontSize="16" Text="阅读更多" />
|
||||
</Border>
|
||||
</spp:AppItem.Status>
|
||||
<spp:AppItem.Image>
|
||||
<spp:Image2 Source="{Binding ImageUrl}" />
|
||||
</spp:AppItem.Image>
|
||||
</spp:AppItem>
|
||||
</DataTemplate>
|
||||
</spp:CarouselBanner.ItemTemplate>
|
||||
</spp:CarouselBanner>
|
||||
</Grid>
|
||||
|
||||
<!--<Viewbox Stretch="UniformToFill">
|
||||
<!--<Viewbox Stretch="UniformToFill">
|
||||
<spp:AdControl
|
||||
MaxWidth="{Binding #HomeRoot.MaxWidth}"
|
||||
MaxHeight="200"
|
||||
Standard="Horizontal" />
|
||||
</Viewbox>-->
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="0,10"
|
||||
Spacing="10">
|
||||
<DockPanel>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="最新消息"
|
||||
Theme="{StaticResource TitleTextBlockStyle}" />
|
||||
<Button
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
CommandParameter="{x:Static spp:HomePageViewModel.OfficialWebsite_Article}"
|
||||
Content="查看更多"
|
||||
DockPanel.Dock="Right"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
</DockPanel>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="0,10"
|
||||
Spacing="10">
|
||||
<DockPanel>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="最新消息"
|
||||
Theme="{StaticResource TitleTextBlockStyle}" />
|
||||
<Button
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
CommandParameter="{x:Static spp:HomePageViewModel.OfficialWebsite_Article}"
|
||||
Content="查看更多"
|
||||
DockPanel.Dock="Right"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
</DockPanel>
|
||||
|
||||
<Grid Margin="0,0,0,20" ColumnDefinitions="*,10,*,10,*">
|
||||
<Grid.Styles>
|
||||
<Style x:DataType="spp:ArticleItemDTO" Selector="spp|AppItem">
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Title" Value="{Binding Title}" />
|
||||
<Setter Property="Description" Value="{Binding Introduction}" />
|
||||
<Setter Property="Tags" Value="{Binding AuthorName}" />
|
||||
<Setter Property="ClickCommand" Value="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}" />
|
||||
<Setter Property="ClickCommandParameter">
|
||||
<Setter.Value>
|
||||
<MultiBinding Converter="{StaticResource StringFormatConverter}">
|
||||
<CompiledBinding Path="." Source="{x:Static spp:HomePageViewModel.OfficialWebsite_Article_Detail_}" />
|
||||
<CompiledBinding Path="Id" />
|
||||
</MultiBinding>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Image">
|
||||
<Setter.Value>
|
||||
<Template>
|
||||
<spp:Image2 RenderOptions.BitmapInterpolationMode="HighQuality" Source="{Binding CoverUrl}" />
|
||||
</Template>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Status">
|
||||
<Setter.Value>
|
||||
<Template>
|
||||
<Border Classes="Status">
|
||||
<TextBlock Text="{Binding CreationTime, StringFormat={}{0:yyyy-MM-dd}}" />
|
||||
</Border>
|
||||
</Template>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Grid.Styles>
|
||||
<spp:AppItem Classes="Vertical Scale" DataContext="{Binding Articles[0]}" />
|
||||
<spp:AppItem
|
||||
Grid.Column="2"
|
||||
Classes="Vertical Scale"
|
||||
DataContext="{Binding Articles[1]}" />
|
||||
<spp:AppItem
|
||||
Grid.Column="4"
|
||||
Classes="Vertical Scale"
|
||||
DataContext="{Binding Articles[2]}" />
|
||||
</Grid>
|
||||
<Grid Margin="0,0,0,20" ColumnDefinitions="*,10,*,10,*">
|
||||
<Grid.Styles>
|
||||
<Style x:DataType="spp:ArticleItemDTO" Selector="spp|AppItem">
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Title" Value="{Binding Title}" />
|
||||
<Setter Property="Description" Value="{Binding Introduction}" />
|
||||
<Setter Property="Tags" Value="{Binding AuthorName}" />
|
||||
<Setter Property="ClickCommand" Value="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}" />
|
||||
<Setter Property="ClickCommandParameter">
|
||||
<Setter.Value>
|
||||
<MultiBinding Converter="{StaticResource StringFormatConverter}">
|
||||
<CompiledBinding Path="." Source="{x:Static spp:HomePageViewModel.OfficialWebsite_Article_Detail_}" />
|
||||
<CompiledBinding Path="Id" />
|
||||
</MultiBinding>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Image">
|
||||
<Setter.Value>
|
||||
<Template>
|
||||
<spp:Image2 RenderOptions.BitmapInterpolationMode="HighQuality" Source="{Binding CoverUrl}" />
|
||||
</Template>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Status">
|
||||
<Setter.Value>
|
||||
<Template>
|
||||
<Border Classes="Status">
|
||||
<TextBlock Text="{Binding CreationTime, StringFormat={}{0:yyyy-MM-dd}}" />
|
||||
</Border>
|
||||
</Template>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Grid.Styles>
|
||||
<spp:AppItem Classes="Vertical Scale" DataContext="{Binding Articles[0]}" />
|
||||
<spp:AppItem
|
||||
Grid.Column="2"
|
||||
Classes="Vertical Scale"
|
||||
DataContext="{Binding Articles[1]}" />
|
||||
<spp:AppItem
|
||||
Grid.Column="4"
|
||||
Classes="Vertical Scale"
|
||||
DataContext="{Binding Articles[2]}" />
|
||||
</Grid>
|
||||
|
||||
<!--<ItemsControl ItemsSource="{Binding Articles}">
|
||||
<!--<ItemsControl ItemsSource="{Binding Articles}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Grid ColumnDefinitions="*,*,*" />
|
||||
@@ -252,149 +252,149 @@
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>-->
|
||||
|
||||
<DockPanel>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="精选"
|
||||
Theme="{StaticResource TitleTextBlockStyle}" />
|
||||
<Button
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
CommandParameter="{x:Static spp:HomePageViewModel.WattGameUrl}"
|
||||
Content="访问 WattGame 商城"
|
||||
DockPanel.Dock="Right"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
</DockPanel>
|
||||
|
||||
<ScrollViewer
|
||||
Name="ShopsScrollViewer"
|
||||
Margin="0,3,0,20"
|
||||
Padding="0,0,0,15"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Disabled">
|
||||
<ItemsControl ItemsSource="{Binding Shops}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="spp:ShopRecommendGoodItem">
|
||||
<spp:AppItem
|
||||
Title="{Binding Name}"
|
||||
MaxWidth="260"
|
||||
Classes="Vertical Scale"
|
||||
ClickCommand="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
Cursor="Hand"
|
||||
Tags="{Binding GoodsAllCategorysText}"
|
||||
ToolTip.Tip="{Binding Brief}">
|
||||
<spp:AppItem.ClickCommandParameter>
|
||||
<MultiBinding Converter="{StaticResource StringFormatConverter}">
|
||||
<CompiledBinding Path="." Source="{x:Static spp:HomePageViewModel.WattGame_Goods_Detail_}" />
|
||||
<CompiledBinding Path="Id" />
|
||||
</MultiBinding>
|
||||
</spp:AppItem.ClickCommandParameter>
|
||||
<spp:AppItem.Image>
|
||||
<spp:Image2 RenderOptions.BitmapInterpolationMode="HighQuality" Source="{Binding Image}" />
|
||||
</spp:AppItem.Image>
|
||||
<spp:AppItem.Status>
|
||||
<Border Classes="Status">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
IsVisible="{Binding !!DiscountValue}"
|
||||
Text="{Binding Mktprice, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Static spp:CurrencyCode.CNY}}"
|
||||
TextDecorations="Strikethrough" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="{Binding Price, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Static spp:CurrencyCode.CNY}}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</spp:AppItem.Status>
|
||||
<spp:AppItem.ActionButton>
|
||||
<Border
|
||||
Height="24"
|
||||
Padding="8,0"
|
||||
Background="#4c6b22"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="4"
|
||||
IsVisible="{Binding !!DiscountValue}">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="#beee11"
|
||||
Text="{Binding DiscountValue, StringFormat={}-{0}%}" />
|
||||
</Border>
|
||||
</spp:AppItem.ActionButton>
|
||||
</spp:AppItem>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
|
||||
<DockPanel>
|
||||
<TextBlock
|
||||
Margin="-3,0,0,0"
|
||||
Text="已安装功能"
|
||||
VerticalAlignment="Center"
|
||||
Text="精选"
|
||||
Theme="{StaticResource TitleTextBlockStyle}" />
|
||||
<Button
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
CommandParameter="{x:Static spp:HomePageViewModel.WattGameUrl}"
|
||||
Content="访问 WattGame 商城"
|
||||
DockPanel.Dock="Right"
|
||||
Theme="{StaticResource HyperlinkButton}" />
|
||||
</DockPanel>
|
||||
|
||||
<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>
|
||||
<ScrollViewer
|
||||
Name="ShopsScrollViewer"
|
||||
Margin="0,3,0,20"
|
||||
Padding="0,0,0,15"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Disabled">
|
||||
<ItemsControl ItemsSource="{Binding Shops}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="10" />
|
||||
</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>
|
||||
<DataTemplate DataType="spp:ShopRecommendGoodItem">
|
||||
<spp:AppItem
|
||||
Title="{Binding Name}"
|
||||
MaxWidth="260"
|
||||
Classes="Vertical Scale"
|
||||
ClickCommand="{Binding OpenBrowserCommand, Source={x:Static spp:App.Instance}}"
|
||||
Cursor="Hand"
|
||||
Tags="{Binding GoodsAllCategorysText}"
|
||||
ToolTip.Tip="{Binding Brief}">
|
||||
<spp:AppItem.ClickCommandParameter>
|
||||
<MultiBinding Converter="{StaticResource StringFormatConverter}">
|
||||
<CompiledBinding Path="." Source="{x:Static spp:HomePageViewModel.WattGame_Goods_Detail_}" />
|
||||
<CompiledBinding Path="Id" />
|
||||
</MultiBinding>
|
||||
</spp:AppItem.ClickCommandParameter>
|
||||
<spp:AppItem.Image>
|
||||
<spp:Image2 RenderOptions.BitmapInterpolationMode="HighQuality" Source="{Binding Image}" />
|
||||
</spp:AppItem.Image>
|
||||
<spp:AppItem.Status>
|
||||
<Border Classes="Status">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
IsVisible="{Binding !!DiscountValue}"
|
||||
Text="{Binding Mktprice, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Static spp:CurrencyCode.CNY}}"
|
||||
TextDecorations="Strikethrough" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="{Binding Price, Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Static spp:CurrencyCode.CNY}}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</spp:AppItem.Status>
|
||||
<spp:AppItem.ActionButton>
|
||||
<Border
|
||||
Height="24"
|
||||
Padding="8,0"
|
||||
Background="#4c6b22"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="4"
|
||||
IsVisible="{Binding !!DiscountValue}">
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="12"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding Name}" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Border>
|
||||
VerticalAlignment="Center"
|
||||
Foreground="#beee11"
|
||||
Text="{Binding DiscountValue, StringFormat={}-{0}%}" />
|
||||
</Border>
|
||||
</spp:AppItem.ActionButton>
|
||||
</spp:AppItem>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
|
||||
<!--<TextBlock Text="联系我们" Theme="{StaticResource TitleTextBlockStyle}" />
|
||||
<TextBlock
|
||||
Margin="-3,0,0,0"
|
||||
Text="已安装功能"
|
||||
Theme="{StaticResource TitleTextBlockStyle}" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding MainWindow2.TabItems, Mode=OneWay, Source={x:Static s:IViewModelManager.Instance}}">
|
||||
<ItemsControl.Resources>
|
||||
<ControlTheme
|
||||
x:Key="NavButtonStyle"
|
||||
BasedOn="{StaticResource {x:Type Button}}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Width" Value="120" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Margin" Value="6" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
||||
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="ClipToBounds" Value="True" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ItemsControl.Resources>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="spp:TabItemViewModel">
|
||||
<Border spp:Animations.EnableAnimations="True">
|
||||
<Button
|
||||
Command="{Binding $parent[spp: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
|
||||
@@ -449,9 +449,9 @@
|
||||
</spp:AppItem>
|
||||
</Grid>-->
|
||||
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!--<TabControl Grid.Row="3" Padding="0">
|
||||
<!--<TabControl Grid.Row="3" Padding="0">
|
||||
<TabItem Header="1111">
|
||||
<StackPanel Spacing="5">
|
||||
<spp:AppItem
|
||||
@@ -523,13 +523,13 @@
|
||||
</TabItem>
|
||||
</TabControl>-->
|
||||
|
||||
<TextBlock
|
||||
Margin="0,30"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="不忘初心,方得始终。"
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
</spp:ContentLoader>
|
||||
<TextBlock
|
||||
Margin="0,30"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="不忘初心,方得始终。"
|
||||
Theme="{StaticResource SubtitleTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
<!--</spp:ContentLoader>-->
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -97,8 +97,7 @@
|
||||
Header="{Binding Path=Res.Settings_General_StorageSpace, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
IconSource="Globe"
|
||||
IsClickEnabled="False"
|
||||
IsExpanded="True"
|
||||
IsVisible="{spp:OnPlatform Windows}">
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<ui:FontIconSource FontFamily="Segoe Fluent Icons" Glyph="" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
|
||||
@@ -297,7 +297,11 @@ partial class ProxyService
|
||||
break;
|
||||
}
|
||||
StopTimer(); // 停止 UI 计时器
|
||||
#if MACOS
|
||||
reverseProxyService.StopProxyAsync().GetAwaiter(); // 停止代理服务
|
||||
#else
|
||||
await reverseProxyService.StopProxyAsync(); // 停止代理服务
|
||||
#endif
|
||||
return default;
|
||||
}
|
||||
|
||||
|
||||
@@ -463,7 +463,7 @@ public static class AuthenticatorHelper
|
||||
{
|
||||
AvaloniaFilePickerFileTypeFilter fileTypes = new AvaloniaFilePickerFileTypeFilter.Item[] {
|
||||
new($"{fileExtension} Files") {
|
||||
Patterns = new[] { $"*.{fileExtension}", },
|
||||
Patterns = new[] { $"*{fileExtension}", },
|
||||
//MimeTypes
|
||||
//AppleUniformTypeIdentifiers =
|
||||
},
|
||||
@@ -472,7 +472,7 @@ public static class AuthenticatorHelper
|
||||
}
|
||||
var filePath = (await FilePicker2.PickAsync(options))?.FullPath;
|
||||
|
||||
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
|
||||
if (!File.Exists(filePath))
|
||||
Toast.Show(ToastIcon.Warning, Strings.FilePathNotExist);
|
||||
return filePath;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@ public partial class AuthenticatorItemModel : ReactiveObject, IDisposable
|
||||
|
||||
public async Task CopyCode()
|
||||
{
|
||||
//if (!IsShowCode) return;
|
||||
await Clipboard2.SetTextAsync(AuthData.Value?.CurrentCode);
|
||||
Toast.Show(ToastIcon.Success, Strings.LocalAuth_CopyAuthTip + AuthName);
|
||||
if (AuthData.Value?.CurrentCode != null)
|
||||
{
|
||||
await Clipboard2.SetTextAsync(AuthData.Value?.CurrentCode);
|
||||
Toast.Show(ToastIcon.Success, Strings.LocalAuth_CopyAuthTip + AuthName);
|
||||
}
|
||||
}
|
||||
|
||||
public AuthenticatorItemModel(IAuthenticatorDTO authenticatorDto)
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ public record AuthenticatorImportMethod(string Name, string Description, string?
|
||||
|
||||
public class AuthenticatorImportPageViewModel : ViewModelBase
|
||||
{
|
||||
public static string Name => Strings.PleaseSelect + Strings.AuthImport;
|
||||
public static string Name => Strings.AuthImport;
|
||||
|
||||
public IReadOnlyCollection<AuthenticatorImportMethod> AuthenticatorImportMethods { get; }
|
||||
|
||||
|
||||
@@ -34,19 +34,21 @@
|
||||
</Viewbox>
|
||||
</Button>-->
|
||||
<Button
|
||||
Padding="8"
|
||||
Command="{Binding EditAuthNameAsync}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.Auth_EditName, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<Viewbox Width="20">
|
||||
<Viewbox Width="16">
|
||||
<ui:SymbolIcon Symbol="Edit" />
|
||||
</Viewbox>
|
||||
</Button>
|
||||
<Button
|
||||
Padding="8"
|
||||
Command="{Binding ShowSteamTradeWindow}"
|
||||
IsVisible="{Binding IsSteamAuthenticator, Mode=OneWay}"
|
||||
Theme="{StaticResource TransparentButton}"
|
||||
ToolTip.Tip="{Binding Path=Res.LocalAuth_AuthTrade, Mode=OneWay, Source={x:Static s:ResourceService.Current}}">
|
||||
<Viewbox Width="20">
|
||||
<Viewbox Width="16">
|
||||
<ui:FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="" />
|
||||
</Viewbox>
|
||||
</Button>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Steam++.HostsTest</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<ApplicationIcon>..\..\res\icons\app\v3\Icon.ico</ApplicationIcon>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TOOL_HOSTSTEST;__NOT_IMPORT_COMMON__;$(DefineConstants)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<AllowedReferenceRelatedFileExtensions>
|
||||
<!-- Prevent default XML and PDB files copied to output in RELEASE.
|
||||
Only *.allowedextension files will be included, which doesn't exist in my case.
|
||||
-->
|
||||
.allowedextension
|
||||
</AllowedReferenceRelatedFileExtensions>
|
||||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\AssemblyInfo.Constants.cs">
|
||||
<LinkBase>Properties</LinkBase>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- PackageReference -->
|
||||
<PackageReference Include="PInvoke.AdvApi32" />
|
||||
<PackageReference Include="PInvoke.Kernel32" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\TFM_NETX_WITH_WINDOWS.props" />
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,133 @@
|
||||
// https://learn.microsoft.com/zh-cn/sysinternals/downloads/handle
|
||||
|
||||
var fColor = Console.ForegroundColor;
|
||||
var bColor = Console.BackgroundColor;
|
||||
try
|
||||
{
|
||||
var isProcessElevated = IsProcessElevated(Process.GetCurrentProcess());
|
||||
Console.WriteLine($"当前进程是否为管理员权限:{isProcessElevated}");
|
||||
|
||||
var hostsFilePath = Path.Combine(Environment.SystemDirectory, "drivers", "etc", "hosts");
|
||||
Console.WriteLine($"hosts 文件路径:{hostsFilePath}");
|
||||
|
||||
try
|
||||
{
|
||||
var text = File.ReadAllText(hostsFilePath);
|
||||
Console.WriteLine("hosts 文件内容:");
|
||||
Console.WriteLine("--------------------------------------------------");
|
||||
Console.WriteLine(text);
|
||||
Console.WriteLine("--------------------------------------------------");
|
||||
|
||||
File.WriteAllText(hostsFilePath, text);
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.BackgroundColor = ConsoleColor.DarkGreen;
|
||||
Console.WriteLine("OK");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.BackgroundColor = ConsoleColor.DarkRed;
|
||||
Console.WriteLine("错误:");
|
||||
Console.WriteLine(ex.ToString());
|
||||
|
||||
// https://learn.microsoft.com/zh-cn/sysinternals/downloads/handle
|
||||
Console.WriteLine("查找 hosts 文件被哪个进程占用的命令,需要安装工具:");
|
||||
Console.WriteLine("https://learn.microsoft.com/zh-cn/sysinternals/downloads/handle");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(
|
||||
$"""
|
||||
handle.exe "{hostsFilePath}" /accepteula
|
||||
""");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.ForegroundColor = fColor;
|
||||
Console.BackgroundColor = bColor;
|
||||
Console.WriteLine("键入回车键后退出此程序:");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查指定的进程是否以管理员权限运行
|
||||
/// </summary>
|
||||
/// <param name="process"></param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static unsafe bool IsProcessElevated(Process process)
|
||||
{
|
||||
try
|
||||
{
|
||||
var handle = process.Handle;
|
||||
|
||||
// IsPrivilegedProcess
|
||||
// https://github.com/dotnet/runtime/pull/77355/files#diff-1c6f0e5208d48036e96fcc9c0243d93595f3ce16f2d1a50f51ba604d930ca69dR87
|
||||
PInvoke.Kernel32.SafeObjectHandle? token = null;
|
||||
try
|
||||
{
|
||||
if (PInvoke.AdvApi32.OpenProcessToken(handle,
|
||||
PInvoke.AdvApi32.TokenAccessRights.TOKEN_READ,
|
||||
out token))
|
||||
{
|
||||
TOKEN_ELEVATION elevation = default;
|
||||
if (PInvoke.AdvApi32.GetTokenInformation(
|
||||
token,
|
||||
PInvoke.AdvApi32.TOKEN_INFORMATION_CLASS.TokenElevation,
|
||||
&elevation,
|
||||
sizeof(TOKEN_ELEVATION),
|
||||
out _))
|
||||
{
|
||||
return elevation.TokenIsElevated != BOOL.FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
token?.Dispose();
|
||||
}
|
||||
|
||||
var error = Marshal.GetLastPInvokeError();
|
||||
throw new Win32Exception(error);
|
||||
|
||||
//using WindowsIdentity identity = new(handle);
|
||||
//WindowsPrincipal principal = new(identity);
|
||||
//return principal.IsInRole(WindowsBuiltInRole.Administrator);
|
||||
}
|
||||
catch (Win32Exception ex)
|
||||
{
|
||||
/* “process.Handle”引发了类型“System.ComponentModel.Win32Exception”的异常
|
||||
* Data: {System.Collections.ListDictionaryInternal}
|
||||
* ErrorCode: -2147467259
|
||||
* HResult: -2147467259
|
||||
* HelpLink: null
|
||||
* InnerException: null
|
||||
* Message: "拒绝访问。"
|
||||
* NativeErrorCode: 5
|
||||
* Source: "System.Diagnostics.Process"
|
||||
*/
|
||||
if (ex.NativeErrorCode == 5)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb530717.aspx
|
||||
struct TOKEN_ELEVATION
|
||||
{
|
||||
public BOOL TokenIsElevated;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Blittable version of Windows BOOL type. It is convenient in situations where
|
||||
/// manual marshalling is required, or to avoid overhead of regular bool marshalling.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Some Windows APIs return arbitrary integer values although the return type is defined
|
||||
/// as BOOL. It is best to never compare BOOL to TRUE. Always use bResult != BOOL.FALSE
|
||||
/// or bResult == BOOL.FALSE .
|
||||
/// </remarks>
|
||||
enum BOOL : int
|
||||
{
|
||||
FALSE = 0,
|
||||
TRUE = 1,
|
||||
}
|
||||
@@ -3,7 +3,7 @@ namespace BD.WTTS.Client.Tools.Publish.Commands;
|
||||
interface IGenerateCaCertCommand : ICommand
|
||||
{
|
||||
const string commandName = "gcert";
|
||||
const string X500DistinguishedNameValue = $"C=CN, S=Hunan, L=Changsha, O=\u6C5F\u82CF\u84B8\u6C7D\u51E1\u661F\u79D1\u6280\u6709\u9650\u516C\u53F8, OU=\u6280\u672F\u90E8, CN=\u6C5F\u82CF\u84B8\u6C7D\u51E1\u661F\u79D1\u6280\u6709\u9650\u516C\u53F8";
|
||||
const string X500DistinguishedNameValue = $"C=CN, S=Hunan, L=Changsha, O=\u5F90\u5DDE\u7E41\u661F\u7F51\u7EDC\u79D1\u6280\u6709\u9650\u516C\u53F8, OU=\u6280\u672F\u90E8, CN=\u5F90\u5DDE\u7E41\u661F\u7F51\u7EDC\u79D1\u6280\u6709\u9650\u516C\u53F8";
|
||||
|
||||
public const int CertificateValidDays = 3650;
|
||||
|
||||
@@ -12,7 +12,7 @@ interface IGenerateCaCertCommand : ICommand
|
||||
static Command ICommand.GetCommand()
|
||||
{
|
||||
var type = new Option<int>("--type",
|
||||
"Generate certificate type(1 code, 2 store-code)");
|
||||
"Generate certificate type(1 code, 2 store-code, 3 csr)");
|
||||
var path = new Option<string>("--path",
|
||||
"Directory where certificate files need to be saved");
|
||||
var cn = new Option<string>("--cn", "X500DistinguishedNameValue");
|
||||
@@ -39,9 +39,10 @@ interface IGenerateCaCertCommand : ICommand
|
||||
/// </summary>
|
||||
const string _13Oid = "1.3.6.1.4.1.311.10.3.13";
|
||||
|
||||
static (byte[] pfx, byte[] cer) GenerateCodeSigningCert(string x500DistinguishedNameValue, string password)
|
||||
static (byte[] pfx, byte[] cer, string? csr) GenerateCodeSigningCert(string x500DistinguishedNameValue, string password, bool isCSR = false)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(password))
|
||||
string? csr = default;
|
||||
if (!isCSR && string.IsNullOrWhiteSpace(password))
|
||||
throw new ArgumentOutOfRangeException(nameof(password), password, null);
|
||||
|
||||
// https://learn.microsoft.com/zh-cn/windows/win32/appxpkg/how-to-create-a-package-signing-certificate
|
||||
@@ -68,24 +69,36 @@ interface IGenerateCaCertCommand : ICommand
|
||||
subjectKeyId = new(request.PublicKey, false);
|
||||
request.CertificateExtensions.Add(subjectKeyId);
|
||||
|
||||
if (isCSR)
|
||||
{
|
||||
var signingRequestPem = request.CreateSigningRequestPem();
|
||||
return (null!, null!, signingRequestPem);
|
||||
}
|
||||
|
||||
var notBefore = DateTimeOffset.UtcNow;
|
||||
var notAfter = notBefore.AddDays(CertificateValidDays);
|
||||
using var cert = request.CreateSelfSigned(notBefore, notAfter);
|
||||
var pfx = cert.Export(X509ContentType.Pfx, password); // 私钥
|
||||
var cer = cert.Export(X509ContentType.Cert); // 公钥
|
||||
return (pfx, cer);
|
||||
return (pfx, cer, csr);
|
||||
}
|
||||
|
||||
internal static void Handler(int type, string path, string cn, string password)
|
||||
{
|
||||
(var pfx, var cer) = type switch
|
||||
(var pfx, var cer, var csr) = type switch
|
||||
{
|
||||
// 生成 BeyondDimension 代码签名证书
|
||||
1 => GenerateCodeSigningCert(X500DistinguishedNameValue, password),
|
||||
// 生成 上传应用商店的 代码签名证书
|
||||
2 => GenerateCodeSigningCert($"CN={cn}", password),
|
||||
3 => GenerateCodeSigningCert(X500DistinguishedNameValue, password, true),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null),
|
||||
};
|
||||
if (csr != default)
|
||||
{
|
||||
Console.WriteLine(csr);
|
||||
return;
|
||||
}
|
||||
File.WriteAllBytes(path, pfx);
|
||||
File.WriteAllBytes(path.TrimEnd(".pfx", StringComparison.OrdinalIgnoreCase) + ".cer", cer);
|
||||
}
|
||||
|
||||
@@ -24,4 +24,24 @@ public interface IRequestCacheRepository : IRequestCache
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<int> DeleteAllAsync(DateTimeOffset dateTimeOffset);
|
||||
|
||||
const string DefaultRequestUri = "/";
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static string GetOriginalRequestUri(HttpRequestMessage request)
|
||||
{
|
||||
string? originalRequestUri;
|
||||
if (request is ImageHttpClientService.ImageHttpRequestMessage request2)
|
||||
{
|
||||
// 对于一些重定向的 Url 使用原始 Url 进行唯一性的计算
|
||||
originalRequestUri = request2.OriginalRequestUri;
|
||||
}
|
||||
else
|
||||
{
|
||||
originalRequestUri = request.RequestUri?.ToString()!;
|
||||
}
|
||||
if (string.IsNullOrEmpty(originalRequestUri))
|
||||
originalRequestUri = DefaultRequestUri;
|
||||
return originalRequestUri;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ namespace BD.WTTS.Repositories;
|
||||
|
||||
internal sealed class RequestCacheRepository : IRequestCacheRepository, IDisposable
|
||||
{
|
||||
const string DefaultRequestUri = "/";
|
||||
const string CacheDirName = "Http";
|
||||
const string TableName = "Fusillade_RequestCache";
|
||||
const string DbFileName = "RequestCache.LiteDB";
|
||||
@@ -49,17 +48,7 @@ internal sealed class RequestCacheRepository : IRequestCacheRepository, IDisposa
|
||||
if (!bytes.Any_Nullable())
|
||||
return;
|
||||
|
||||
var requestUri = response.RequestMessage?.RequestUri ?? request.RequestUri;
|
||||
string requestUriString;
|
||||
if (requestUri == null)
|
||||
{
|
||||
requestUriString = DefaultRequestUri;
|
||||
}
|
||||
else
|
||||
{
|
||||
requestUriString = requestUri.ToString();
|
||||
}
|
||||
|
||||
var requestUriString = IRequestCacheRepository.GetOriginalRequestUri(request);
|
||||
var fileTypeResult = FileFormat.AnalyzeFileType(bytes);
|
||||
var hashKey = Hashs.String.SHA384(bytes, false);
|
||||
var fileEx = fileTypeResult.FileEx;
|
||||
@@ -116,6 +105,7 @@ internal sealed class RequestCacheRepository : IRequestCacheRepository, IDisposa
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
key = UniqueKeyForRequest(requestUriString, request);
|
||||
var entity = table.FindById(key);
|
||||
bool isInsertOrUpdate;
|
||||
if (entity == null)
|
||||
@@ -158,17 +148,8 @@ internal sealed class RequestCacheRepository : IRequestCacheRepository, IDisposa
|
||||
string key,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var requestUri = request.RequestUri;
|
||||
string requestUriString;
|
||||
if (requestUri == null)
|
||||
{
|
||||
requestUriString = DefaultRequestUri;
|
||||
}
|
||||
else
|
||||
{
|
||||
requestUriString = requestUri.ToString();
|
||||
}
|
||||
|
||||
var requestUriString = IRequestCacheRepository.GetOriginalRequestUri(request);
|
||||
key = UniqueKeyForRequest(requestUriString, request);
|
||||
var entity = table.Query().Where(x => x.Id == key &&
|
||||
x.HttpMethod == request.Method.Method &&
|
||||
x.RequestUri == requestUriString).FirstOrDefault();
|
||||
@@ -249,4 +230,49 @@ internal sealed class RequestCacheRepository : IRequestCacheRepository, IDisposa
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
static string UniqueKeyForRequest(string originalRequestUri, HttpRequestMessage request)
|
||||
{
|
||||
// https://github.com/reactiveui/Fusillade/blob/2.4.67/src/Fusillade/RateLimitedHttpMessageHandler.cs#L54-L89
|
||||
|
||||
using var s = new MemoryStream();
|
||||
s.Write(Encoding.UTF8.GetBytes(originalRequestUri));
|
||||
s.Write("\r\n"u8);
|
||||
s.Write(Encoding.UTF8.GetBytes(request.Method.Method));
|
||||
s.Write("\r\n"u8);
|
||||
static void Write(Stream s, IEnumerable<object> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
var str = item.ToString();
|
||||
if (!string.IsNullOrEmpty(str))
|
||||
s.Write(Encoding.UTF8.GetBytes(str));
|
||||
s.Write("|"u8);
|
||||
}
|
||||
}
|
||||
Write(s, request.Headers.Accept);
|
||||
s.Write("\r\n"u8);
|
||||
Write(s, request.Headers.AcceptEncoding);
|
||||
s.Write("\r\n"u8);
|
||||
var referrer = request.Headers.Referrer;
|
||||
if (referrer == default)
|
||||
s.Write("http://example"u8);
|
||||
else
|
||||
s.Write(Encoding.UTF8.GetBytes(referrer.ToString()));
|
||||
s.Write("\r\n"u8);
|
||||
Write(s, request.Headers.UserAgent);
|
||||
s.Write("\r\n"u8);
|
||||
if (request.Headers.Authorization != null)
|
||||
{
|
||||
var parameter = request.Headers.Authorization.Parameter;
|
||||
if (!string.IsNullOrEmpty(parameter))
|
||||
s.Write(Encoding.UTF8.GetBytes(parameter));
|
||||
s.Write(Encoding.UTF8.GetBytes(request.Headers.Authorization.Scheme));
|
||||
s.Write("\r\n"u8);
|
||||
}
|
||||
s.Position = 0;
|
||||
var bytes = SHA384.HashData(s);
|
||||
var str = bytes.ToHexString();
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4847,15 +4847,6 @@ namespace BD.WTTS.Client.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 请选择 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string PleaseSelect {
|
||||
get {
|
||||
return ResourceManager.GetString("PleaseSelect", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 作者:{0} 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -729,9 +729,6 @@
|
||||
<data name="PleaseEnterNickName" xml:space="preserve">
|
||||
<value>请输入昵称</value>
|
||||
</data>
|
||||
<data name="PleaseSelect" xml:space="preserve">
|
||||
<value>请选择</value>
|
||||
</data>
|
||||
<data name="RecoveryCode" xml:space="preserve">
|
||||
<value>恢复代码</value>
|
||||
</data>
|
||||
|
||||
@@ -175,7 +175,9 @@ public sealed partial class IPCMainProcessServiceImpl : IPCMainProcessService
|
||||
psi.ArgumentList.Add(pid.ToString());
|
||||
psi.ArgumentList.Add(mSubProcessArgumentIndex2Model.Value);
|
||||
configure?.Invoke(psi);
|
||||
#if !MACOS
|
||||
DotNetRuntimeHelper.AddEnvironment(psi);
|
||||
#endif
|
||||
var nativeLibraryPath = Startup.NativeLibraryPath;
|
||||
if (!string.IsNullOrWhiteSpace(nativeLibraryPath))
|
||||
{
|
||||
|
||||
@@ -12,14 +12,21 @@ static partial class Interop
|
||||
|
||||
const uint QueryLimitedInformation = 0x00001000;
|
||||
|
||||
public static string QueryFullProcessImageName(Process process)
|
||||
public static string? QueryFullProcessImageName(Process process)
|
||||
{
|
||||
int capacity = 1024;
|
||||
StringBuilder sb = new(capacity);
|
||||
var handle = Kernel32_.OpenProcess(new(QueryLimitedInformation), false, process.Id);
|
||||
Kernel32_.QueryFullProcessImageName(handle, 0, sb, ref capacity);
|
||||
string fullPath = sb.ToString(0, capacity);
|
||||
return fullPath;
|
||||
try
|
||||
{
|
||||
int capacity = 1024;
|
||||
StringBuilder sb = new(capacity);
|
||||
var handle = Kernel32_.OpenProcess(new(QueryLimitedInformation), false, process.Id);
|
||||
Kernel32_.QueryFullProcessImageName(handle, 0, sb, ref capacity);
|
||||
string fullPath = sb.ToString(0, capacity);
|
||||
return fullPath;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+110
-110
@@ -105,115 +105,115 @@ partial class WindowsPlatformServiceImpl
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用 BypassUAC 以管理员权限启动进程
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="arguments"></param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static async Task<Process?> StartAsAdministratorByBypassUAC(string fileName, string? arguments = null)
|
||||
{
|
||||
/** 33. Author: winscripting.blog
|
||||
* https://github.com/hfiref0x/UACME
|
||||
* https://github.com/FatRodzianko/SharpBypassUAC/blob/67a9a3e4500731881f60863454e4e42ef46874e0/SharpBypassUAC/FodHelper.cs
|
||||
* Type: Shell API
|
||||
* Method: Registry key manipulation
|
||||
* Target(s): \system32\fodhelper.exe
|
||||
* Component(s): Attacker defined
|
||||
* Implementation: ucmShellRegModMethod
|
||||
* Works from: Windows 10 TH1 (10240)
|
||||
* Fixed in: unfixed 🙈
|
||||
* How: -
|
||||
* Code status: added in v2.7.2
|
||||
*/
|
||||
RegistryKey? classes = null;
|
||||
var targetName = Path.Combine(Environment.GetFolderPath(
|
||||
Environment.SpecialFolder.System),
|
||||
"fodhelper.exe");
|
||||
try
|
||||
{
|
||||
if (!File.Exists(targetName))
|
||||
return null;
|
||||
// /// <summary>
|
||||
// /// 使用 BypassUAC 以管理员权限启动进程
|
||||
// /// </summary>
|
||||
// /// <param name="fileName"></param>
|
||||
// /// <param name="arguments"></param>
|
||||
// /// <returns></returns>
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// internal static async Task<Process?> StartAsAdministratorByBypassUAC(string fileName, string? arguments = null)
|
||||
// {
|
||||
// /** 33. Author: winscripting.blog
|
||||
// * https://github.com/hfiref0x/UACME
|
||||
// * https://github.com/FatRodzianko/SharpBypassUAC/blob/67a9a3e4500731881f60863454e4e42ef46874e0/SharpBypassUAC/FodHelper.cs
|
||||
// * Type: Shell API
|
||||
// * Method: Registry key manipulation
|
||||
// * Target(s): \system32\fodhelper.exe
|
||||
// * Component(s): Attacker defined
|
||||
// * Implementation: ucmShellRegModMethod
|
||||
// * Works from: Windows 10 TH1 (10240)
|
||||
// * Fixed in: unfixed 🙈
|
||||
// * How: -
|
||||
// * Code status: added in v2.7.2
|
||||
// */
|
||||
// RegistryKey? classes = null;
|
||||
// var targetName = Path.Combine(Environment.GetFolderPath(
|
||||
// Environment.SpecialFolder.System),
|
||||
// "fodhelper.exe");
|
||||
// try
|
||||
// {
|
||||
// if (!File.Exists(targetName))
|
||||
// return null;
|
||||
|
||||
var processPath = Environment.ProcessPath;
|
||||
processPath.ThrowIsNull();
|
||||
if (fileName != processPath) // 仅允许启动自己
|
||||
throw new ArgumentOutOfRangeException(nameof(fileName));
|
||||
// var processPath = Environment.ProcessPath;
|
||||
// processPath.ThrowIsNull();
|
||||
// if (fileName != processPath) // 仅允许启动自己
|
||||
// throw new ArgumentOutOfRangeException(nameof(fileName));
|
||||
|
||||
var processName = Path.GetFileNameWithoutExtension(fileName);
|
||||
if (string.IsNullOrWhiteSpace(processName))
|
||||
throw new ArgumentNullException(nameof(processName));
|
||||
// var processName = Path.GetFileNameWithoutExtension(fileName);
|
||||
// if (string.IsNullOrWhiteSpace(processName))
|
||||
// throw new ArgumentNullException(nameof(processName));
|
||||
|
||||
classes = Registry.CurrentUser.OpenSubKey(@"Software\Classes", true);
|
||||
using var command = classes!.CreateSubKey(@"ms-settings\Shell\Open\command", true);
|
||||
command.SetValue("DelegateExecute", "");
|
||||
command.SetValue("", string.IsNullOrWhiteSpace(arguments) ?
|
||||
$"\"{fileName}\"" : $"\"{fileName}\" {arguments}");
|
||||
// classes = Registry.CurrentUser.OpenSubKey(@"Software\Classes", true);
|
||||
// using var command = classes!.CreateSubKey(@"ms-settings\Shell\Open\command", true);
|
||||
// command.SetValue("DelegateExecute", "");
|
||||
// command.SetValue("", string.IsNullOrWhiteSpace(arguments) ?
|
||||
// $"\"{fileName}\"" : $"\"{fileName}\" {arguments}");
|
||||
|
||||
ProcessStartInfo psi = new()
|
||||
{
|
||||
UseShellExecute = true,
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
FileName = targetName,
|
||||
};
|
||||
var processs_start_before = new HashSet<int>(
|
||||
Process.GetProcessesByName(processName).Select(x => x.Id));
|
||||
var process = Process.Start(psi);
|
||||
process!.WaitForExit(6000);
|
||||
// ProcessStartInfo psi = new()
|
||||
// {
|
||||
// UseShellExecute = true,
|
||||
// WindowStyle = ProcessWindowStyle.Hidden,
|
||||
// FileName = targetName,
|
||||
// };
|
||||
// var processs_start_before = new HashSet<int>(
|
||||
// Process.GetProcessesByName(processName).Select(x => x.Id));
|
||||
// var process = Process.Start(psi);
|
||||
// process!.WaitForExit(6000);
|
||||
|
||||
Dictionary<int, bool> mIsProcessElevated = new();
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
var processs_start_after = Process.GetProcessesByName(processName);
|
||||
foreach (var item in processs_start_after)
|
||||
{
|
||||
if (item.Id == Environment.ProcessId)
|
||||
continue;
|
||||
if (processs_start_before.Contains(item.Id))
|
||||
continue;
|
||||
// Dictionary<int, bool> mIsProcessElevated = new();
|
||||
// for (int i = 0; i < 7; i++)
|
||||
// {
|
||||
// var processs_start_after = Process.GetProcessesByName(processName);
|
||||
// foreach (var item in processs_start_after)
|
||||
// {
|
||||
// if (item.Id == Environment.ProcessId)
|
||||
// continue;
|
||||
// if (processs_start_before.Contains(item.Id))
|
||||
// continue;
|
||||
|
||||
if (mIsProcessElevated.TryGetValue(item.Id, out var value))
|
||||
{
|
||||
return item;
|
||||
}
|
||||
else
|
||||
{
|
||||
var isProcessElevated = IsProcessElevated(item);
|
||||
if (isProcessElevated)
|
||||
return item;
|
||||
mIsProcessElevated.Add(item.Id, isProcessElevated);
|
||||
}
|
||||
}
|
||||
// if (mIsProcessElevated.TryGetValue(item.Id, out var value))
|
||||
// {
|
||||
// return item;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var isProcessElevated = IsProcessElevated(item);
|
||||
// if (isProcessElevated)
|
||||
// return item;
|
||||
// mIsProcessElevated.Add(item.Id, isProcessElevated);
|
||||
// }
|
||||
// }
|
||||
|
||||
await Task.Delay(800);
|
||||
}
|
||||
// await Task.Delay(800);
|
||||
// }
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if DEBUG
|
||||
Log.Error(TAG, ex, "StartAsAdministratorByBypassUAC fail.");
|
||||
#endif
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (classes != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
classes.DeleteSubKeyTree("ms-settings");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// return null;
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
//#if DEBUG
|
||||
// Log.Error(TAG, ex, "StartAsAdministratorByBypassUAC fail.");
|
||||
//#endif
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// if (classes != null)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// classes.DeleteSubKeyTree("ms-settings");
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
|
||||
}
|
||||
classes.Dispose();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// }
|
||||
// classes.Dispose();
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 以管理员权限启动进程
|
||||
@@ -221,18 +221,18 @@ partial class WindowsPlatformServiceImpl
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="arguments"></param>
|
||||
/// <returns></returns>
|
||||
internal static async ValueTask<Process?> StartAsAdministrator(string fileName, string? arguments = null)
|
||||
internal static /*async*/ ValueTask<Process?> StartAsAdministrator(string fileName, string? arguments = null)
|
||||
{
|
||||
#if !DEBUG
|
||||
if (IsPrivilegedProcess)
|
||||
return Process2.Start(fileName, arguments);
|
||||
return ValueTask.FromResult(Process2.Start(fileName, arguments));
|
||||
#endif
|
||||
if (!DesktopBridge.IsRunningAsUwp)
|
||||
{
|
||||
var process = await StartAsAdministratorByBypassUAC(fileName, arguments);
|
||||
if (process != null)
|
||||
return process;
|
||||
}
|
||||
//if (!DesktopBridge.IsRunningAsUwp)
|
||||
//{
|
||||
// var process = await StartAsAdministratorByBypassUAC(fileName, arguments);
|
||||
// if (process != null)
|
||||
// return process;
|
||||
//}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -244,11 +244,11 @@ partial class WindowsPlatformServiceImpl
|
||||
Verb = "runas",
|
||||
};
|
||||
var process_runas = Process.Start(psi);
|
||||
return process_runas;
|
||||
return ValueTask.FromResult(process_runas);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
return ValueTask.FromResult<Process?>(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ partial interface IPlatformService
|
||||
/// 获取 排除代理地址
|
||||
/// </summary>
|
||||
protected static string[] GetNoProxyHostName => new string[] {
|
||||
"localhost",
|
||||
"127.*",
|
||||
"10.*",
|
||||
"172.16.*",
|
||||
"172.17.*",
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#if WINDOWS
|
||||
using System.Security.AccessControl;
|
||||
#endif
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace BD.WTTS;
|
||||
|
||||
@@ -82,14 +86,31 @@ partial class Startup // 本应用程序单例管道
|
||||
}
|
||||
#endif
|
||||
var currentMainModule = current.TryGetMainModule();
|
||||
bool IsThisProgram(Process p, ProcessModule? pMainModule)
|
||||
{
|
||||
if (currentMainModule != null)
|
||||
{
|
||||
if (pMainModule != null)
|
||||
{
|
||||
return pMainModule.FileName == currentMainModule.FileName &&
|
||||
pMainModule.ModuleName == currentMainModule.ModuleName;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if WINDOWS
|
||||
var path = Interop.Kernel32.QueryFullProcessImageName(p);
|
||||
return path == currentMainModule.FileName;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
var query = from p in Process.GetProcessesByName(current.ProcessName)
|
||||
let pMainModule = p.TryGetMainModule()
|
||||
where p.Id != current.Id &&
|
||||
p.ProcessName == current.ProcessName &&
|
||||
(currentMainModule == null ||
|
||||
(pMainModule != null &&
|
||||
pMainModule.FileName == currentMainModule.FileName &&
|
||||
pMainModule.ModuleName == currentMainModule.ModuleName))
|
||||
p.ProcessName == current.ProcessName && IsThisProgram(p, pMainModule)
|
||||
select p;
|
||||
return query;
|
||||
}
|
||||
@@ -121,7 +142,7 @@ partial class Startup // 本应用程序单例管道
|
||||
static string GetPipeName()
|
||||
{
|
||||
var processPath = Environment.ProcessPath ?? string.Empty;
|
||||
return AssemblyInfo.APPLICATION_ID + "_v3_" + Hashs.String.Crc32(processPath);
|
||||
return AssemblyInfo.APPLICATION_ID + "_v" + AssemblyInfo.InformationalVersion + "_" + Hashs.String.Crc32(processPath);
|
||||
}
|
||||
|
||||
CancellationTokenSource? cts;
|
||||
@@ -131,9 +152,35 @@ partial class Startup // 本应用程序单例管道
|
||||
{
|
||||
cts = new CancellationTokenSource();
|
||||
var name = GetPipeName();
|
||||
|
||||
NamedPipeServerStream GetNamedPipeServerStream()
|
||||
{
|
||||
const PipeDirection direction = PipeDirection.In;
|
||||
const int maxNumberOfServerInstances = 5;
|
||||
const PipeTransmissionMode transmissionMode = PipeTransmissionMode.Byte;
|
||||
const PipeOptions options = PipeOptions.None;
|
||||
const int inBufferSize = 0;
|
||||
const int outBufferSize = 0;
|
||||
#if WINDOWS
|
||||
if (WindowsPlatformServiceImpl.IsPrivilegedProcess)
|
||||
{
|
||||
// https://github.com/dotnet-campus/dotnetCampus.Ipc/blob/2.0.0-alpha403/src/dotnetCampus.Ipc/Internals/IpcPipeServerMessageProvider.cs#L99
|
||||
SecurityIdentifier securityIdentifier = new(WellKnownSidType.AuthenticatedUserSid, null);
|
||||
PipeSecurity pipeSecurity = new();
|
||||
pipeSecurity.AddAccessRule(new PipeAccessRule(securityIdentifier,
|
||||
PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance,
|
||||
AccessControlType.Allow));
|
||||
|
||||
var result = NamedPipeServerStreamAcl.Create(name, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize, pipeSecurity);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
return new NamedPipeServerStream(name, direction, maxNumberOfServerInstances, transmissionMode, options);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
using var pipeServer = new NamedPipeServerStream(name, PipeDirection.In, 1);
|
||||
using var pipeServer = GetNamedPipeServerStream();
|
||||
try
|
||||
{
|
||||
pipeServer.WaitForConnection();
|
||||
@@ -177,7 +224,7 @@ partial class Startup // 本应用程序单例管道
|
||||
using var pipeClient = new NamedPipeClientStream(".", name,
|
||||
PipeDirection.Out, PipeOptions.None,
|
||||
TokenImpersonationLevel.Impersonation);
|
||||
pipeClient.Connect(TimeSpan.FromSeconds(25));
|
||||
pipeClient.Connect(TimeSpan.FromSeconds(7.7D));
|
||||
using StreamWriter sw = new StreamWriter(pipeClient);
|
||||
sw.WriteLine(value);
|
||||
return true;
|
||||
|
||||
@@ -27,7 +27,9 @@ public sealed class HomePageViewModel : TabItemViewModel
|
||||
|
||||
public HomePageViewModel()
|
||||
{
|
||||
Articles = new ObservableCollection<ArticleItemDTO>();
|
||||
#pragma warning disable CS8625 // 初始化3个null 为解决调试报错中断
|
||||
Articles = new ObservableCollection<ArticleItemDTO>() { null, null, null };
|
||||
#pragma warning restore CS8625 // 无法将 null 字面量转换为非 null 的引用类型。
|
||||
NavigationBanners = new ObservableCollection<AdvertisementDTO>();
|
||||
Shops = new ObservableCollection<ShopRecommendGoodItem>();
|
||||
|
||||
@@ -41,8 +43,7 @@ public sealed class HomePageViewModel : TabItemViewModel
|
||||
var result = await Instance.Article.Order(null, ArticleOrderBy.DateTime);
|
||||
if (result.IsSuccess && result.Content != null)
|
||||
{
|
||||
Articles.Clear();
|
||||
Articles.Add(result.Content.DataSource);
|
||||
Articles = new ObservableCollection<ArticleItemDTO>(result.Content.DataSource);
|
||||
}
|
||||
|
||||
var result2 = await Instance.Shop.RecommendGoods();
|
||||
|
||||
@@ -27,20 +27,20 @@ global using System.IO;
|
||||
global using System.Buffers;
|
||||
global using System.IO.Pipes;
|
||||
global using PipeOptions = System.IO.Pipes.PipeOptions;
|
||||
#if !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ
|
||||
#if !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ && !__NOT_IMPORT_COMMON__
|
||||
global using System.IO.Pipelines;
|
||||
global using PipelineOptions = System.IO.Pipelines.PipeOptions;
|
||||
#endif
|
||||
#endif
|
||||
global using System.IO.Compression;
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ && !__NOT_IMPORT_COMMON__
|
||||
global using System.IO.FileFormats;
|
||||
#endif
|
||||
global using System.Linq;
|
||||
global using System.Linq.Expressions;
|
||||
global using System.Net;
|
||||
global using System.Net.Security;
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ && !__NOT_IMPORT_COMMON__
|
||||
global using System.Net.Http.Headers;
|
||||
global using System.Net.Http.Json;
|
||||
global using System.Net.Http.Client;
|
||||
@@ -66,7 +66,7 @@ global using System.Text.Unicode;
|
||||
#endif
|
||||
global using System.Text.RegularExpressions;
|
||||
global using System.Runtime;
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ && !__NOT_IMPORT_COMMON__
|
||||
global using DeploymentMode = System.Runtime.DeploymentMode;
|
||||
global using System.Runtime.Devices;
|
||||
#endif
|
||||
@@ -74,16 +74,16 @@ global using System.Runtime.InteropServices;
|
||||
global using System.Runtime.Versioning;
|
||||
global using System.Runtime.Serialization.Formatters;
|
||||
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ && !__NOT_IMPORT_COMMON__
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
#endif
|
||||
|
||||
#if WINDOWS && !APP_HOST && !APP_REVERSE_PROXY && !LIB_CLIENT_IPC
|
||||
#if WINDOWS && !APP_HOST && !APP_REVERSE_PROXY && !LIB_CLIENT_IPC && !__NOT_IMPORT_COMMON__
|
||||
global using System.Management;
|
||||
#endif
|
||||
|
||||
#if !NONE_UI && (WINDOWS || APP_HOST)
|
||||
#if !NONE_UI && (WINDOWS || APP_HOST) && !__NOT_IMPORT_COMMON__
|
||||
global using WPFMessageBox = MS.Win32.MessageBox;
|
||||
global using WPFMessageBoxButton = MS.Win32.MessageBoxButton;
|
||||
global using WPFMessageBoxImage = MS.Win32.MessageBoxImage;
|
||||
@@ -94,14 +94,14 @@ global using System.Xml;
|
||||
global using System.Xml.Serialization;
|
||||
global using System.Security.Cryptography.X509Certificates;
|
||||
global using IPAddress = System.Net.IPAddress;
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ && !__NOT_IMPORT_COMMON__
|
||||
global using Ioc = System.Ioc;
|
||||
global using DateTimeFormat = System.DateTimeFormat;
|
||||
global using SerializationDateTimeFormat = System.Runtime.Serialization.DateTimeFormat;
|
||||
global using HttpMethod = System.Net.Http.HttpMethod;
|
||||
#endif
|
||||
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ
|
||||
#if !NETFRAMEWORK && !APP_HOST && !NETFRAMEWORK_SINGLE_FILE && !RES_PROJ && !__NOT_IMPORT_COMMON__
|
||||
global using HttpHandlerCategory = System.Net.Http.Client.HttpHandlerCategory;
|
||||
global using IHttpClientFactory = System.Net.Http.Client.IHttpClientFactory;
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#if !APP_HOST
|
||||
#if !NETFRAMEWORK
|
||||
|
||||
#if !__NOT_IMPORT_COMMON_PRIMITIVES__
|
||||
#if !__NOT_IMPORT_COMMON_PRIMITIVES__ && !__NOT_IMPORT_COMMON__
|
||||
global using Polly;
|
||||
global using BD.Common;
|
||||
global using BD.Common.Columns;
|
||||
@@ -22,7 +22,7 @@ global using BD.Common.Identity;
|
||||
global using BD.Common.Identity.Abstractions;
|
||||
#endif
|
||||
|
||||
#if !__NOT_IMPORT_COMMON_SERVICES__
|
||||
#if !__NOT_IMPORT_COMMON_SERVICES__ && !__NOT_IMPORT_COMMON__
|
||||
global using BD.Common.Services;
|
||||
global using BD.Common.Services.Implementation;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user