diff --git a/src/Common.ClientLib.Droid/Application/Services/Implementation/PlatformNotificationServiceImpl`2.cs b/src/Common.ClientLib.Droid/Application/Services/Implementation/PlatformNotificationServiceImpl`2.cs index 1a0715772..3470ab6e6 100644 --- a/src/Common.ClientLib.Droid/Application/Services/Implementation/PlatformNotificationServiceImpl`2.cs +++ b/src/Common.ClientLib.Droid/Application/Services/Implementation/PlatformNotificationServiceImpl`2.cs @@ -199,11 +199,9 @@ namespace System.Application.Services.Implementation TNotificationType notificationType, bool autoCancel, string? title, - TEntrance entrance) + TEntrance? entrance) { - var notificationEntrance = entrance != null ? - GetActivityType(entrance).GetJClass() : - R.activities.entrance; + var notificationEntrance = (entrance != null ? GetActivityType(entrance)?.GetJClass() : null) ?? R.activities.entrance; var context = AndroidApplication.Context; var manager = NotificationManagerCompat.From(context); var builder = BuildNotify(context, manager, text, notificationType, @@ -213,24 +211,25 @@ namespace System.Application.Services.Implementation } public Progress NotifyDownload( - string text, + Func text, TNotificationType notificationType, string? title) { var context = AndroidApplication.Context; var manager = NotificationManagerCompat.From(context); var builder = BuildNotify(context, manager, - text: text.Format(0), + text: text(), notificationType, title: title); // 进度单位说明 // 通用层采用 float 浮点数作为进度值,范围从0~100,保留两位小数 // 平台层采用 int 整型作为进度值,范围从0~10000,转换需要 乘 100 const int unit_convert_multiple = 100; // 从float到int转换单位倍数 - const int PROGRESS_MAX = 100 * unit_convert_multiple; // 进度条满值 + const float PROGRESS_MAX = IAppUpdateService.MaxProgressValue * unit_convert_multiple; // 进度条满值 + int PROGRESS_MAX_INT32 = PROGRESS_MAX.ToInt32(); // 发出零进度的初始通知 // Issue the initial notification with zero progress - builder.SetProgress(PROGRESS_MAX, 0, false); + builder.SetProgress(PROGRESS_MAX_INT32, 0, false); var notifyId = GetNotifyId(notificationType); manager.Notify(notifyId, builder.Build()); // 在这里完成跟踪进度的工作。 @@ -248,7 +247,7 @@ namespace System.Application.Services.Implementation void Handler(float current) { var currentInt32 = (current * unit_convert_multiple).ToInt32(); - if (currentInt32 >= PROGRESS_MAX) + if (currentInt32 >= PROGRESS_MAX_INT32) { // 这将使100%时直接取消通知,并不会在UI上显示 // 报告进度值满的操作应当是幂等的 @@ -266,8 +265,8 @@ namespace System.Application.Services.Implementation // 在报告进度值满后不可再更改进度 if (builder == null) throw new ArgumentNullException(nameof(builder)); if (manager == null) throw new ArgumentNullException(nameof(manager)); - builder.SetProgress(PROGRESS_MAX, currentInt32, false); - builder.SetContentText(text.Format(currentInt32)); + builder.SetProgress(PROGRESS_MAX_INT32, currentInt32, false); + builder.SetContentText(text()); manager.Notify(notifyId, builder.Build()); } } diff --git a/src/Common.ClientLib/Application/Services/INotificationService.cs b/src/Common.ClientLib/Application/Services/INotificationService.cs index 82685e1c9..fd7bd569c 100644 --- a/src/Common.ClientLib/Application/Services/INotificationService.cs +++ b/src/Common.ClientLib/Application/Services/INotificationService.cs @@ -45,7 +45,7 @@ namespace System.Application.Services /// 下载进度通知 /// Progress NotifyDownload( - string text, + Func text, TNotificationType notificationType, string? title = default); } diff --git a/src/Common.CoreLib/FileEx.cs b/src/Common.CoreLib/FileEx.cs index 10b8006a1..94af590e3 100644 --- a/src/Common.CoreLib/FileEx.cs +++ b/src/Common.CoreLib/FileEx.cs @@ -75,6 +75,8 @@ namespace System public const string MPO = ".mpo"; + public const string DownloadCache = ".download_cache"; + public static string Clean(string extension, bool trimLeadingPeriod = false) { if (string.IsNullOrWhiteSpace(extension)) diff --git a/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/App.config b/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/App.config index 731f6de6c..c116b6cf4 100644 --- a/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/App.config +++ b/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/App.config @@ -1,6 +1,6 @@ - + - - - - \ No newline at end of file + + + + diff --git a/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/Launcher.csproj b/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/Launcher.csproj index 1a009c040..ac834b312 100644 --- a/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/Launcher.csproj +++ b/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/Launcher.csproj @@ -3,7 +3,7 @@ WinExe AnyCPU - net461 + net472 ..\..\ST.Client.Desktop.Avalonia.App\Properties\app.manifest Steam++.Launcher System @@ -31,5 +31,14 @@ Properties\ThisAssembly.Version.cs + + Application\Services\IDesktopPlatformService.SystemBootRunArguments.cs + + + + + + + \ No newline at end of file diff --git a/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/Program.cs b/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/Program.cs index c5dcf6dd2..37ce51dd0 100644 --- a/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/Program.cs +++ b/src/ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher/Launcher/Program.cs @@ -1,17 +1,30 @@ using System; using System.Diagnostics; using System.IO; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using static System.Application.Services.IDesktopPlatformService; +static string? OnActivated(IActivatedEventArgs args) +{ + if (args.Kind == ActivationKind.StartupTask) + { + // 静默启动(不弹窗口) + return SystemBootRunArguments; + } + return default; +} + +var activatedArgs = AppInstance.GetActivatedEventArgs(); try { Process.Start(new ProcessStartInfo() { FileName = Path.Combine(AppContext.BaseDirectory, "..", "Steam++.exe"), - Arguments = string.Join(" ", args), - UseShellExecute = false, + Arguments = (activatedArgs == default ? default : OnActivated(activatedArgs)) ?? string.Join(" ", args), + UseShellExecute = default, }); } catch (FileNotFoundException) { - } \ No newline at end of file diff --git a/src/ST.Client.Desktop.Avalonia.App/App.axaml.cs b/src/ST.Client.Desktop.Avalonia.App/App.axaml.cs index 21eee23fd..6d817f16c 100644 --- a/src/ST.Client.Desktop.Avalonia.App/App.axaml.cs +++ b/src/ST.Client.Desktop.Avalonia.App/App.axaml.cs @@ -211,6 +211,7 @@ namespace System.Application.UI #region NotifyIcon var notifyIcon = INotifyIcon.Instance; + notifyIcon.Visible = true; notifyIcon.ToolTipText = ThisAssembly.AssemblyTrademark; switch (DI.Platform) { @@ -255,8 +256,6 @@ namespace System.Application.UI .Select(x => new MenuItem { Header = x.Key, Command = x.Value }).ToList(); notifyIcon.ContextMenu = NotifyIconContextMenu; #endif - - notifyIcon.Visible = true; notifyIcon.Click += NotifyIcon_Click; notifyIcon.DoubleClick += NotifyIcon_Click; compositeDisposable.Add(() => @@ -270,8 +269,6 @@ namespace System.Application.UI #if WINDOWS JumpLists.Init(); #endif - - IsNotOfficialChannelPackageDetectionHelper.Check(); } desktop.MainWindow = @@ -301,6 +298,7 @@ namespace System.Application.UI #if StartupTrace StartupTrace.Restart("Desktop_Startup.Start"); #endif + IsNotOfficialChannelPackageDetectionHelper.Check(); #if WINDOWS if (isOfficialChannelPackage) { diff --git a/src/ST.Client.Desktop.Avalonia.App/Program.cs b/src/ST.Client.Desktop.Avalonia.App/Program.cs index c82e92305..49fc00be9 100644 --- a/src/ST.Client.Desktop.Avalonia.App/Program.cs +++ b/src/ST.Client.Desktop.Avalonia.App/Program.cs @@ -12,15 +12,15 @@ namespace System.Application.UI static readonly object lock_global_ex_log = new(); #if WINDOWS_DESKTOP_BRIDGE - static string[] OnActivated(string[] main_args, global::Windows.ApplicationModel.Activation.IActivatedEventArgs args) - { - if (args.Kind == global::Windows.ApplicationModel.Activation.ActivationKind.StartupTask) - { - // 静默启动(不弹窗口) - return IDesktopPlatformService.SystemBootRunArguments.Split(' '); - } - return main_args; - } + //static string[] OnActivated(string[] main_args, global::Windows.ApplicationModel.Activation.IActivatedEventArgs args) + //{ + // if (args.Kind == global::Windows.ApplicationModel.Activation.ActivationKind.StartupTask) + // { + // // 静默启动(不弹窗口) + // return IDesktopPlatformService.SystemBootRunArguments.Split(' '); + // } + // return main_args; + //} #endif // Initialization code. Don't use any Avalonia, third-party APIs or any @@ -34,8 +34,8 @@ namespace System.Application.UI { #if WINDOWS_DESKTOP_BRIDGE if (!DesktopBridgeHelper.Init()) return 0; - var activatedArgs = global::Windows.ApplicationModel.AppInstance.GetActivatedEventArgs(); - if (activatedArgs != null) args = OnActivated(args, activatedArgs); + //var activatedArgs = global::Windows.ApplicationModel.AppInstance.GetActivatedEventArgs(); + //if (activatedArgs != null) args = OnActivated(args, activatedArgs); #elif !__MOBILE__ #if MAC AppDelegateHelper.Init(args); diff --git a/src/ST.Client.Desktop.Avalonia/Application/Services/Implementation/PlatformNotificationServiceImpl.cs b/src/ST.Client.Desktop.Avalonia/Application/Services/Implementation/PlatformNotificationServiceImpl.cs index 26cc862f2..5e3019f96 100644 --- a/src/ST.Client.Desktop.Avalonia/Application/Services/Implementation/PlatformNotificationServiceImpl.cs +++ b/src/ST.Client.Desktop.Avalonia/Application/Services/Implementation/PlatformNotificationServiceImpl.cs @@ -1,3 +1,4 @@ +using System.Application.UI; using System.Properties; namespace System.Application.Services.Implementation @@ -16,20 +17,32 @@ namespace System.Application.Services.Implementation public void Cancel(NotificationType notificationType) { + if (DI.Platform == Platform.Windows) + { + INotifyIcon.Instance.HideBalloonTip(); + } } public void CancelAll() { + if (DI.Platform == Platform.Windows) + { + INotifyIcon.Instance.HideBalloonTip(); + } } public void Notify(string text, NotificationType notificationType, bool autoCancel, string? title, Entrance entrance) { title ??= ThisAssembly.AssemblyTrademark; + // 调用托盘显示通知 - throw new NotImplementedException(title); + if (DI.Platform == Platform.Windows) + { + INotifyIcon.Instance.ShowBalloonTip(title, text); + } } - public Progress NotifyDownload(string text, NotificationType notificationType, string? title) + public Progress NotifyDownload(Func text, NotificationType notificationType, string? title) { // 桌面端不支持带进度的通知,下载新版本改用桌面端的窗口进度条控件,由更新服务桌面端版实现 //title ??= ThisAssembly.AssemblyTrademark; diff --git a/src/ST.Client.Desktop.Avalonia/Application/Services/Implementation/ShowWindowServiceImpl.cs b/src/ST.Client.Desktop.Avalonia/Application/Services/Implementation/ShowWindowServiceImpl.cs index 958814ea8..5ce319f64 100644 --- a/src/ST.Client.Desktop.Avalonia/Application/Services/Implementation/ShowWindowServiceImpl.cs +++ b/src/ST.Client.Desktop.Avalonia/Application/Services/Implementation/ShowWindowServiceImpl.cs @@ -159,12 +159,13 @@ namespace System.Application.Services.Implementation TWindowViewModel? viewModel = null, string title = "", ResizeModeCompat resizeMode = ResizeModeCompat.NoResize, - bool isDialog = true) + bool isDialog = true, + bool isParent = true) where TWindowViewModel : WindowViewModel, new() { DialogWindowViewModel? dialogWindowViewModel = null; await Show(typeof(TWindowViewModel), isDialog, customWindow, - title, viewModel, resizeMode, true, dwvm => + title, viewModel, resizeMode, isParent, dwvm => { dialogWindowViewModel = dwvm; }); diff --git a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Pages/GameListPage.axaml b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Pages/GameListPage.axaml index 46c0095a2..564bdabca 100644 --- a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Pages/GameListPage.axaml +++ b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Pages/GameListPage.axaml @@ -239,7 +239,7 @@ - + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + + + + - - - - + - - - + + + + + + + + diff --git a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/GameListPage/IdleAppWindow.axaml b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/GameListPage/IdleAppWindow.axaml index 30a495819..6ef5192a7 100644 --- a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/GameListPage/IdleAppWindow.axaml +++ b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/GameListPage/IdleAppWindow.axaml @@ -72,7 +72,7 @@ OffContent="" HorizontalAlignment="Right" Margin="5 0 0 5" - IsChecked="{Binding Source={x:Static service:SteamConnectService.Current},Path=IsAutoAFKApps}" + IsChecked="{ReflectionBinding Source={x:Static ms:GameLibrarySettings.IsAutoAFKApps},Path=Value}" ToolTip.Tip="{ReflectionBinding Path=Res.GameList_AutoAFK,Mode=OneWay,Source={x:Static resx:R.Current}}" VerticalAlignment="Center"> diff --git a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/LocalAuthPage/AddAuthWindow.axaml b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/LocalAuthPage/AddAuthWindow.axaml index 7c9b4889b..d22a128b8 100644 --- a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/LocalAuthPage/AddAuthWindow.axaml +++ b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/LocalAuthPage/AddAuthWindow.axaml @@ -2,7 +2,10 @@ 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" - mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" + mc:Ignorable="d" + d:DesignWidth="720" d:DesignHeight="400" + MinWidth="720" MinHeight="400" + Width="720" Height="400" x:Class="System.Application.UI.Views.Windows.AddAuthWindow" xmlns:resx="clr-namespace:System.Application.UI.Resx;assembly=System.Application.SteamTools.Client.Desktop" xmlns:vm="clr-namespace:System.Application.UI.ViewModels;assembly=System.Application.SteamTools.Client.Desktop" @@ -10,8 +13,6 @@ xmlns:controls="clr-namespace:System.Application.UI.Views.Controls" xmlns:ms="clr-namespace:System.Application.Models.Settings;assembly=System.Application.SteamTools.Client.Desktop" FontFamily="{Binding Source={x:Static ms:UISettings.FontName},Path=Value, Mode=OneWay,Converter={StaticResource NameToFontFamilyConverter}}" - MinWidth="600" - MinHeight="400" WindowStartupLocation="CenterOwner" ExtendClientAreaTitleBarHeightHint="30" Background="Transparent" diff --git a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/MessageBoxWindow.axaml.cs b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/MessageBoxWindow.axaml.cs index 091b10b53..8dbd941bf 100644 --- a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/MessageBoxWindow.axaml.cs +++ b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/MessageBoxWindow.axaml.cs @@ -31,6 +31,13 @@ namespace System.Application.UI.Views.Windows AvaloniaXamlLoader.Load(this); } + protected override void OnOpened(EventArgs e) + { + base.OnOpened(e); + this.Topmost = true; + this.Topmost = false; + } + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); diff --git a/src/ST.Client.Desktop.Windows/Internals/UnmanagedMethods.cs b/src/ST.Client.Desktop.Windows/Internals/UnmanagedMethods.cs index ee76b649b..52cdba278 100644 --- a/src/ST.Client.Desktop.Windows/Internals/UnmanagedMethods.cs +++ b/src/ST.Client.Desktop.Windows/Internals/UnmanagedMethods.cs @@ -1,4 +1,4 @@ -// Copyright (c) The Avalonia Project. All rights reserved. +// Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. // Slightly modified and extended version for the use in SQRLDotNetClientUI @@ -18,8 +18,11 @@ namespace System [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern IntPtr LoadImage(IntPtr hinst, string lpszName, uint uType, int cxDesired, int cyDesired, uint fuLoad); - [DllImport("shell32", CharSet = CharSet.Auto)] - public static extern int Shell_NotifyIcon(NIM dwMessage, NOTIFYICONDATA lpData); + /// + /// Creates, updates or deletes the taskbar icon. + /// + [DllImport("shell32", CharSet = CharSet.Unicode)] + public static extern bool Shell_NotifyIcon(NIM cmd, NOTIFYICONDATA data); [DllImport("user32.dll")] public static extern void PostQuitMessage(int nExitCode); @@ -113,7 +116,7 @@ namespace System public uint dwTime; } - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public class NOTIFYICONDATA { public int cbSize = Marshal.SizeOf(); @@ -126,12 +129,29 @@ namespace System public string szTip; public int dwState = 0; public int dwStateMask = 0; + /// + /// String with the text for a balloon ToolTip. It can have a maximum of 255 characters. + /// To remove the ToolTip, set the NIF_INFO flag in uFlags and set szInfo to an empty string. + /// [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szInfo; public int uTimeoutOrVersion; + /// + /// String containing a title for a balloon ToolTip. This title appears in boldface + /// above the text. It can have a maximum of 63 characters. + /// [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string szInfoTitle; public NIIF dwInfoFlags; + + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. The handle of a customized + /// balloon icon provided by the application that should be used independently + /// of the tray icon. If this member is non-NULL and the + /// flag is set, this icon is used as the balloon icon.
+ /// If this member is NULL, the legacy behavior is carried out. + ///
+ //public IntPtr CustomBalloonIconHandle; } public enum NIM : uint @@ -143,33 +163,6 @@ namespace System SETVERSION = 0x00000004 } - [Flags] - public enum NIF : uint - { - MESSAGE = 0x00000001, - ICON = 0x00000002, - TIP = 0x00000004, - STATE = 0x00000008, - INFO = 0x00000010, - GUID = 0x00000020, - REALTIME = 0x00000040, - SHOWTIP = 0x00000080 - } - - [Flags] - public enum NIIF : uint - { - NONE = 0x00000000, - INFO = 0x00000001, - WARNING = 0x00000002, - ERROR = 0x00000003, - USER = 0x00000004, - ICON_MASK = 0x0000000F, - NOSOUND = 0x00000010, - LARGE_ICON = 0x00000020, - RESPECT_QUIET_TIME = 0x00000080 - } - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class MENUITEMINFO { @@ -2103,6 +2096,33 @@ namespace System } } + [Flags] + public enum NIF : uint + { + MESSAGE = 0x00000001, + ICON = 0x00000002, + TIP = 0x00000004, + STATE = 0x00000008, + INFO = 0x00000010, + GUID = 0x00000020, + REALTIME = 0x00000040, + SHOWTIP = 0x00000080 + } + + [Flags] + public enum NIIF : uint + { + NONE = 0x00000000, + INFO = 0x00000001, + WARNING = 0x00000002, + ERROR = 0x00000003, + USER = 0x00000004, + ICON_MASK = 0x0000000F, + NOSOUND = 0x00000010, + LARGE_ICON = 0x00000020, + RESPECT_QUIET_TIME = 0x00000080 + } + [Flags] internal enum DropEffect : int { diff --git a/src/ST.Client.Desktop.Windows/UI/NotifyIcon.cs b/src/ST.Client.Desktop.Windows/UI/NotifyIcon.cs index fcb8c9768..165c79437 100644 --- a/src/ST.Client.Desktop.Windows/UI/NotifyIcon.cs +++ b/src/ST.Client.Desktop.Windows/UI/NotifyIcon.cs @@ -20,6 +20,11 @@ namespace System.Application.UI string _toolTipText = string.Empty; bool _visible = false; bool _doubleClick = false; + /// + /// Represents the current icon data. + /// + private UnmanagedMethods.NOTIFYICONDATA iconData; + public event EventHandler? Click; public event EventHandler? DoubleClick; @@ -127,6 +132,17 @@ namespace System.Application.UI { _window = new NotifyIconWindow(this); } + + iconData = new UnmanagedMethods.NOTIFYICONDATA() + { + hWnd = _window.Handle, + uID = _uID, + uFlags = NIF.TIP | NIF.MESSAGE, + uCallbackMessage = (int)UnmanagedMethods.CustomWindowsMessage.WM_TRAYMOUSE, + hIcon = IntPtr.Zero, + uTimeoutOrVersion = 0, + szTip = ToolTipText, + }; } ~NotifyIcon() @@ -141,20 +157,12 @@ namespace System.Application.UI void UpdateIcon(bool remove = false) { if (_window == null) throw new ArgumentNullException(nameof(_window)); - UnmanagedMethods.NOTIFYICONDATA iconData = new UnmanagedMethods.NOTIFYICONDATA() - { - hWnd = _window.Handle, - uID = _uID, - uFlags = UnmanagedMethods.NIF.TIP | UnmanagedMethods.NIF.MESSAGE, - uCallbackMessage = (int)UnmanagedMethods.CustomWindowsMessage.WM_TRAYMOUSE, - hIcon = IntPtr.Zero, - szTip = ToolTipText - }; if (!remove && _icon != null && Visible) { - iconData.uFlags |= UnmanagedMethods.NIF.ICON; + iconData.uFlags |= NIF.ICON; iconData.hIcon = _icon.Handle; + iconData.szTip = ToolTipText; if (!_iconAdded) { @@ -242,6 +250,80 @@ namespace System.Application.UI } } + /// + /// Displays a balloon tip with the specified title, + /// text, and icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + public void ShowBalloonTip(string title, string message, NIIF flags) + { + ShowBalloonTip(title, message, flags, IntPtr.Zero); + } + + /// + /// Displays a balloon tip with the specified title, + /// text, and icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + public void ShowBalloonTip(string title, string message) + { + ShowBalloonTip(title, message, NIIF.NONE, IntPtr.Zero); + } + + /// + /// Displays a balloon tip with the specified title, + /// text, and a custom icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// A custom icon. + /// True to allow large icons (Windows Vista and later). + /// If + /// is a null reference. + public void ShowBalloonTip(string title, string message, Icon customIcon, bool largeIcon = false) + { + if (customIcon == null) throw new ArgumentNullException(nameof(customIcon)); + var flags = NIIF.USER; + if (largeIcon) + { + // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags + flags |= NIIF.LARGE_ICON; + } + ShowBalloonTip(title, message, flags, customIcon.Handle); + } + + /// + /// Invokes in order to display + /// a given balloon ToolTip. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// Indicates what icon to use. + /// A handle to a custom icon, if any, or + /// . + public void ShowBalloonTip(string title, string message, NIIF flags, IntPtr balloonIconHandle) + { + iconData.szInfo = message ?? string.Empty; + iconData.szInfoTitle = title ?? string.Empty; + iconData.uFlags = NIF.INFO | NIF.ICON; + //iconData.CustomBalloonIconHandle = balloonIconHandle; + iconData.dwInfoFlags = flags; + + var result = UnmanagedMethods.Shell_NotifyIcon(UnmanagedMethods.NIM.MODIFY, iconData); + } + + /// + /// Hides a balloon ToolTip, if any is displayed. + /// + public void HideBalloonTip() + { + // reset balloon by just setting the info to an empty string + iconData.szInfo = iconData.szInfoTitle = string.Empty; + UnmanagedMethods.Shell_NotifyIcon(UnmanagedMethods.NIM.MODIFY, iconData); + } + /// /// Handles the NotifyIcon-specific window messages sent by the notification icon. /// diff --git a/src/ST.Client.Desktop/Models/Settings2/SteamSettings.cs b/src/ST.Client.Desktop/Models/Settings2/SteamSettings.cs index 3110cbdd8..48d4efea8 100644 --- a/src/ST.Client.Desktop/Models/Settings2/SteamSettings.cs +++ b/src/ST.Client.Desktop/Models/Settings2/SteamSettings.cs @@ -57,9 +57,9 @@ namespace System.Application.Models.Settings = GetProperty(defaultValue: false, autoSave: true); /// - /// 检测到Steam启动时弹出消息通知 + /// 检测到Steam登录时弹出消息通知 /// public static SerializableProperty IsEnableSteamLaunchNotification { get; } - = GetProperty(defaultValue: false, autoSave: true); + = GetProperty(defaultValue: true, autoSave: true); } } \ No newline at end of file diff --git a/src/ST.Client.Desktop/Services/IDesktopPlatformService.SystemBootRunArguments.cs b/src/ST.Client.Desktop/Services/IDesktopPlatformService.SystemBootRunArguments.cs new file mode 100644 index 000000000..97d2b1316 --- /dev/null +++ b/src/ST.Client.Desktop/Services/IDesktopPlatformService.SystemBootRunArguments.cs @@ -0,0 +1,19 @@ +namespace System.Application.Services +{ +#if NETFRAMEWORK + static +#endif + partial +#if NETFRAMEWORK + class +#else + interface +#endif + IDesktopPlatformService + { +#if NETFRAMEWORK + public +#endif + const string SystemBootRunArguments = "-clt c -silence"; + } +} \ No newline at end of file diff --git a/src/ST.Client.Desktop/Services/IDesktopPlatformService.cs b/src/ST.Client.Desktop/Services/IDesktopPlatformService.cs index e13868a6b..dc628ae4a 100644 --- a/src/ST.Client.Desktop/Services/IDesktopPlatformService.cs +++ b/src/ST.Client.Desktop/Services/IDesktopPlatformService.cs @@ -8,7 +8,7 @@ using System.Windows; namespace System.Application.Services { - public interface IDesktopPlatformService : IPlatformService + public partial interface IDesktopPlatformService : IPlatformService { protected new const string TAG = "DesktopPlatformS"; @@ -126,8 +126,6 @@ namespace System.Application.Services /// string? GetFileName(TextReaderProvider provider); - const string SystemBootRunArguments = "-clt c -silence"; - /// /// 设置开机自启动 /// @@ -231,7 +229,6 @@ namespace System.Application.Services void FixFluentWindowStyleOnWin7(IntPtr hWnd) { - } } } \ No newline at end of file diff --git a/src/ST.Client.Desktop/Services/IShowWindowService.cs b/src/ST.Client.Desktop/Services/IShowWindowService.cs index 09fe64691..f79ec8e5d 100644 --- a/src/ST.Client.Desktop/Services/IShowWindowService.cs +++ b/src/ST.Client.Desktop/Services/IShowWindowService.cs @@ -57,7 +57,8 @@ namespace System.Application.Services TWindowViewModel? viewModel = null, string title = "", ResizeModeCompat resizeMode = ResizeModeCompat.NoResize, - bool isDialog = true) + bool isDialog = true, + bool isParent = true) where TWindowViewModel : WindowViewModel, new(); diff --git a/src/ST.Client.Desktop/Services/Mvvm/SteamConnectService.cs b/src/ST.Client.Desktop/Services/Mvvm/SteamConnectService.cs index 0de77d9af..5c478d0f5 100644 --- a/src/ST.Client.Desktop/Services/Mvvm/SteamConnectService.cs +++ b/src/ST.Client.Desktop/Services/Mvvm/SteamConnectService.cs @@ -105,10 +105,11 @@ namespace System.Application.Services } } } - #endregion - #region 是否已经释放SteamClient private bool _IsDisposedClient = true; + /// + /// 是否已经释放SteamClient + /// public bool IsDisposedClient { get => _IsDisposedClient; @@ -136,22 +137,13 @@ namespace System.Application.Services } } } - public bool IsAutoAFKApps - { - get => GameLibrarySettings.IsAutoAFKApps.Value; - set - { - GameLibrarySettings.IsAutoAFKApps.Value = value; - this.RaisePropertyChanged(nameof(IsAutoAFKApps)); - } - } + public void RunAFKApps() { if (GameLibrarySettings.AFKAppList.Value?.Count > 0) { foreach (var item in GameLibrarySettings.AFKAppList.Value) { - RuningSteamApps.TryGetValue(item.Key, out var runState); if (runState == null) RuningSteamApps.TryAdd(item.Key, new SteamApp @@ -177,7 +169,7 @@ namespace System.Application.Services if (!SteamTool.IsRunningSteamProcess && SteamSettings.IsAutoRunSteam.Value) SteamTool.StartSteam(SteamSettings.SteamStratParameter.Value); - var t = new Task(async () => + Task.Factory.StartNew(async () => { Thread.CurrentThread.IsBackground = true; try @@ -206,10 +198,19 @@ namespace System.Application.Services CurrentSteamUser.IPCountry = ApiService.GetIPCountry(); IsSteamChinaLauncher = ApiService.IsSteamChinaLauncher(); - if (IsAutoAFKApps) - RunAFKApps(); - #region 初始化需要steam启动才能使用的功能 + if (SteamSettings.IsEnableSteamLaunchNotification.Value) + { + INotificationService.Instance.Notify($"{AppResources.Steam_CheckStarted}{(IsSteamChinaLauncher ? AppResources.Steam_SteamChina : AppResources.Steam_SteamWorld)}{Environment.NewLine}{AppResources.Steam_CurrentUser}{CurrentSteamUser.SteamNickName}{Environment.NewLine}{AppResources.Steam_CurrentIPCountry}{CurrentSteamUser.IPCountry}", NotificationType.Announcement); + } + + + if (GameLibrarySettings.IsAutoAFKApps.Value) + { + RunAFKApps(); + } + + //仅在有游戏数据情况下加载登录用户的游戏 if (SteamApps.Items.Any()) { LoadGames(ApiService.OwnsApps(await ISteamService.Instance.GetAppInfos())); @@ -234,13 +235,10 @@ namespace System.Application.Services } catch (Exception ex) { - Log.Error(nameof(SteamConnectService), ex, "Task LongRunning"); + Log.Error(nameof(SteamConnectService), ex, "SteamConnect Task LongRunning"); ToastService.Current.Notify(ex.Message); } - }, TaskCreationOptions.LongRunning); - - //t.Forget(); - t.Start(); + }, TaskCreationOptions.LongRunning).ConfigureAwait(false); } public bool Initialize(int appid) @@ -256,7 +254,7 @@ namespace System.Application.Services { SteamApps.Clear(); if (apps.Any_Nullable()) - SteamApps.AddOrUpdate(apps); + SteamApps.AddOrUpdate(apps!); } public async void InitializeGameList() @@ -267,29 +265,10 @@ namespace System.Application.Services IsLoadingGameList = false; } - // public void UpdateGamesImage() - // { - //#if DEBUG - // if (BuildConfig.IsDebuggerAttached) - // { - // return; - // } - //#endif - // //if (SteamApps.Items.Any()) - // //{ - // // Parallel.ForEach(SteamApps.Items, new ParallelOptions - // // { - // // MaxDegreeOfParallelism = (Environment.ProcessorCount / 2) + 1 - // // }, async app => - // // { - // // await ISteamService.Instance.LoadAppImageAsync(app); - // // //app.LibraryLogoStream = await IHttpService.Instance.GetImageAsync(app.LibraryLogoUrl, ImageChannelType.SteamGames); - // // //app.LibraryHeaderStream = await IHttpService.Instance.GetImageAsync(app.LibraryHeaderUrl, ImageChannelType.SteamGames); - // // //app.LibraryNameStream = await IHttpService.Instance.GetImageAsync(app.LibraryNameUrl, ImageChannelType.SteamGames); - // // //app.HeaderLogoStream = await IHttpService.Instance.GetImageAsync(app.HeaderLogoUrl, ImageChannelType.SteamGames); - // // }); - // //} - // } + public async void InitializeDownloadGameList() + { + + } private bool _IsRefreshing; public /*async*/ void RefreshGamesList() @@ -299,7 +278,7 @@ namespace System.Application.Services _IsRefreshing = true; if (SteamTool.IsRunningSteamProcess) { - var t = new Task(() => + Task.Factory.StartNew(() => { Thread.CurrentThread.IsBackground = true; try @@ -331,8 +310,7 @@ namespace System.Application.Services Log.Error(nameof(SteamConnectService), ex, "Task RefreshGamesList"); ToastService.Current.Notify(ex.Message); } - }, TaskCreationOptions.LongRunning); - t.Start(); + }, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.PreferFairness).Forget().ConfigureAwait(false); } else { diff --git a/src/ST.Client.Desktop/UI/INotifyIcon.cs b/src/ST.Client.Desktop/UI/INotifyIcon.cs index c036124c9..1fe08ce0c 100644 --- a/src/ST.Client.Desktop/UI/INotifyIcon.cs +++ b/src/ST.Client.Desktop/UI/INotifyIcon.cs @@ -53,11 +53,26 @@ namespace System.Application.UI /// event EventHandler RightClick; + public interface IUIFrameworkHelper { Stream OpenAsset(Uri uri); void ForEachMenuItems(TContextMenu menu, Action<(object menuItem, string header, Action activated)> action); } + + /// + /// Displays a balloon tip with the specified title, + /// text, and icon in the taskbar for the specified time period. + /// + /// The title to display on the balloon tip. + /// The text to display on the balloon tip. + /// A symbol that indicates the severity. + void ShowBalloonTip(string title, string message); + + /// + /// Hides a balloon ToolTip, if any is displayed. + /// + void HideBalloonTip(); } } \ No newline at end of file diff --git a/src/ST.Client.Desktop/UI/Resx/AppResources.Designer.cs b/src/ST.Client.Desktop/UI/Resx/AppResources.Designer.cs index ff594a63d..d6da94ecd 100644 --- a/src/ST.Client.Desktop/UI/Resx/AppResources.Designer.cs +++ b/src/ST.Client.Desktop/UI/Resx/AppResources.Designer.cs @@ -3222,6 +3222,15 @@ namespace System.Application.UI.Resx { } } + /// + /// 查找类似 当Steam客户端登录时弹出通知 的本地化字符串。 + /// + public static string Settings_Steam_CheckSteamRuningNotification { + get { + return ResourceManager.GetString("Settings_Steam_CheckSteamRuningNotification", resourceCulture); + } + } + /// /// 查找类似 Steam启动时不检查更新 的本地化字符串。 /// @@ -3339,6 +3348,33 @@ namespace System.Application.UI.Resx { } } + /// + /// 查找类似 检测到启动: 的本地化字符串。 + /// + public static string Steam_CheckStarted { + get { + return ResourceManager.GetString("Steam_CheckStarted", resourceCulture); + } + } + + /// + /// 查找类似 Steam客户端登录区域: 的本地化字符串。 + /// + public static string Steam_CurrentIPCountry { + get { + return ResourceManager.GetString("Steam_CurrentIPCountry", resourceCulture); + } + } + + /// + /// 查找类似 Steam登录用户: 的本地化字符串。 + /// + public static string Steam_CurrentUser { + get { + return ResourceManager.GetString("Steam_CurrentUser", resourceCulture); + } + } + /// /// 查找类似 输入图中验证码 的本地化字符串。 /// @@ -3357,6 +3393,24 @@ namespace System.Application.UI.Resx { } } + /// + /// 查找类似 Steam国服 的本地化字符串。 + /// + public static string Steam_SteamChina { + get { + return ResourceManager.GetString("Steam_SteamChina", resourceCulture); + } + } + + /// + /// 查找类似 Steam国际服 的本地化字符串。 + /// + public static string Steam_SteamWorld { + get { + return ResourceManager.GetString("Steam_SteamWorld", resourceCulture); + } + } + /// /// 查找类似 Steam用户名 的本地化字符串。 /// diff --git a/src/ST.Client.Desktop/UI/Resx/AppResources.resx b/src/ST.Client.Desktop/UI/Resx/AppResources.resx index 4d954454f..30b9d2d6f 100644 --- a/src/ST.Client.Desktop/UI/Resx/AppResources.resx +++ b/src/ST.Client.Desktop/UI/Resx/AppResources.resx @@ -1519,4 +1519,22 @@ 启用开机自启动失败,原因: {0} + + 当Steam客户端登录时弹出通知 + + + 检测到启动: + + + Steam客户端登录区域: + + + Steam登录用户: + + + Steam国服 + + + Steam国际服 + \ No newline at end of file diff --git a/src/ST.Client.Desktop/UI/ViewModels/Pages/DebugPageViewModel.cs b/src/ST.Client.Desktop/UI/ViewModels/Pages/DebugPageViewModel.cs index 3b19131f2..9c2638489 100644 --- a/src/ST.Client.Desktop/UI/ViewModels/Pages/DebugPageViewModel.cs +++ b/src/ST.Client.Desktop/UI/ViewModels/Pages/DebugPageViewModel.cs @@ -277,7 +277,7 @@ namespace System.Application.UI.ViewModels // FileShareTest(); // } //#endif - + INotificationService.Instance.Notify("测试Test🎆🎇→→", NotificationType.Announcement); ShowDialogButton_Click1(); } diff --git a/src/ST.Client.Desktop/UI/ViewModels/Pages/GameListPageViewModel.cs b/src/ST.Client.Desktop/UI/ViewModels/Pages/GameListPageViewModel.cs index ddec9dd2e..75a50a881 100644 --- a/src/ST.Client.Desktop/UI/ViewModels/Pages/GameListPageViewModel.cs +++ b/src/ST.Client.Desktop/UI/ViewModels/Pages/GameListPageViewModel.cs @@ -119,7 +119,7 @@ namespace System.Application.UI.ViewModels EnableAFKAutoUpdateCommand = ReactiveCommand.Create(() => { - AFKAutoUpdate?.CheckmarkChange(SteamConnectService.Current.IsAutoAFKApps = !SteamConnectService.Current.IsAutoAFKApps); + AFKAutoUpdate?.CheckmarkChange(GameLibrarySettings.IsAutoAFKApps.Value = !GameLibrarySettings.IsAutoAFKApps.Value); }); MenuItems = new ObservableCollection() @@ -135,7 +135,7 @@ namespace System.Application.UI.ViewModels IconKey ="ClockArrowDownloadDrawing", Command = SteamShutdownCommand }, }; - AFKAutoUpdate?.CheckmarkChange(SteamConnectService.Current.IsAutoAFKApps); + AFKAutoUpdate?.CheckmarkChange(GameLibrarySettings.IsAutoAFKApps.Value); } public ReactiveCommand EnableAFKAutoUpdateCommand { get; } diff --git a/src/ST.Client.Desktop/UI/ViewModels/Windows/GameListPage/SteamShutdownWindowViewModel.cs b/src/ST.Client.Desktop/UI/ViewModels/Windows/GameListPage/SteamShutdownWindowViewModel.cs index e3094627f..73134856b 100644 --- a/src/ST.Client.Desktop/UI/ViewModels/Windows/GameListPage/SteamShutdownWindowViewModel.cs +++ b/src/ST.Client.Desktop/UI/ViewModels/Windows/GameListPage/SteamShutdownWindowViewModel.cs @@ -1,7 +1,11 @@ +using DynamicData; using Newtonsoft.Json.Linq; +using ReactiveUI; using System.Application.Models; using System.Application.UI.Resx; +using System.Collections.ObjectModel; using System.Properties; +using System.Reactive.Linq; namespace System.Application.UI.ViewModels { @@ -10,8 +14,21 @@ namespace System.Application.UI.ViewModels public SteamShutdownWindowViewModel() : base() { Title = ThisAssembly.AssemblyTrademark + " | " + AppResources.GameList_SteamShutdown; + + _DownloadingAppSourceList = new SourceList(); + + _DownloadingAppSourceList + .Connect() + .ObserveOn(RxApp.MainThreadScheduler) + //.Sort(SortExpressionComparer.Descending(x => x.)) + .Bind(out _DownloadingApps) + .Subscribe(); } + private readonly ReadOnlyObservableCollection? _DownloadingApps; + public ReadOnlyObservableCollection? DownloadingApps => _DownloadingApps; + + private readonly SourceList _DownloadingAppSourceList; } } \ No newline at end of file diff --git a/src/ST.Client.Mobile.Droid/Services/Implementation/MobileAppUpdateServiceImpl.cs b/src/ST.Client.Mobile.Droid/Services/Implementation/MobileAppUpdateServiceImpl.cs index 13a6d1a96..c2c35d600 100644 --- a/src/ST.Client.Mobile.Droid/Services/Implementation/MobileAppUpdateServiceImpl.cs +++ b/src/ST.Client.Mobile.Droid/Services/Implementation/MobileAppUpdateServiceImpl.cs @@ -6,13 +6,16 @@ using System.Application.Models; using System.Windows; using XEPlatform = Xamarin.Essentials.Platform; using static System.Application.UI.Resx.AppResources; +using static System.Application.Services.IAppUpdateService; namespace System.Application.Services.Implementation { internal sealed partial class MobileAppUpdateServiceImpl : AppUpdateServiceImpl { - public MobileAppUpdateServiceImpl(IToast toast, ICloudServiceClient client, IOptions options) : base(toast, client, options) + readonly INotificationService notification; + public MobileAppUpdateServiceImpl(INotificationService notification, IToast toast, ICloudServiceClient client, IOptions options) : base(toast, client, options) { + this.notification = notification; } protected override Version OSVersion => @@ -46,5 +49,26 @@ namespace System.Application.Services.Implementation throw new NotImplementedException(); #endif } + + IProgress? progress; + protected override void OnReport(float value, string str) + { + base.OnReport(value, str); + if (value == 0) + { + progress?.Report(MaxProgressValue); + progress = notification.NotifyDownload(() => ProgressString, + NotificationType.NewVersionDownloadProgress); + } + else if (value == MaxProgressValue) + { + progress?.Report(MaxProgressValue); + progress = null; + } + else + { + progress?.Report(value); + } + } } } \ No newline at end of file diff --git a/src/ST.Client.Mobile.Droid/UI/MainApplication.cs b/src/ST.Client.Mobile.Droid/UI/MainApplication.cs index 94002927d..2139c4e6e 100644 --- a/src/ST.Client.Mobile.Droid/UI/MainApplication.cs +++ b/src/ST.Client.Mobile.Droid/UI/MainApplication.cs @@ -13,6 +13,8 @@ using XEPlatform = Xamarin.Essentials.Platform; using XEVersionTracking = Xamarin.Essentials.VersionTracking; using System.Application.Models.Settings; using AndroidX.AppCompat.App; +using System.Application.Services; +using System.Application.Services.Implementation; #if DEBUG using Square.LeakCanary; #endif @@ -79,7 +81,16 @@ namespace System.Application.UI Startup.Init(level); if (IsMainProcess) { + if (INotificationService.Instance is PlatformNotificationServiceImpl notification) + { + notification.InitNotificationChannels(this); + } XEVersionTracking.Track(); + if (XEVersionTracking.IsFirstLaunchForCurrentVersion) + { + // 当前版本第一次启动时,清除存放升级包缓存文件夹的目录 + IAppUpdateService.ClearAllPackCacheDir(); + } ImageLoader.Init(this); UISettings.Theme.Subscribe(x => { diff --git a/src/ST.Client/NotificationType_Channel_EnumExtensions.cs b/src/ST.Client/Extensions/NotificationType_Channel_EnumExtensions.cs similarity index 98% rename from src/ST.Client/NotificationType_Channel_EnumExtensions.cs rename to src/ST.Client/Extensions/NotificationType_Channel_EnumExtensions.cs index 183a37041..cf3fa2e5a 100644 --- a/src/ST.Client/NotificationType_Channel_EnumExtensions.cs +++ b/src/ST.Client/Extensions/NotificationType_Channel_EnumExtensions.cs @@ -1,4 +1,4 @@ -using System.Application.Properties; +using System.Application.Properties; using System.Application.Services; namespace System.Application diff --git a/src/ST.Client/ST.Client.csproj b/src/ST.Client/ST.Client.csproj index bb5015afd..aadc6b3c0 100644 --- a/src/ST.Client/ST.Client.csproj +++ b/src/ST.Client/ST.Client.csproj @@ -23,16 +23,16 @@ - + - - - - - - + + + + + + diff --git a/src/ST.Client/Services/IAppUpdateService.cs b/src/ST.Client/Services/IAppUpdateService.cs index c8cc153b3..6ade60ff7 100644 --- a/src/ST.Client/Services/IAppUpdateService.cs +++ b/src/ST.Client/Services/IAppUpdateService.cs @@ -1,4 +1,6 @@ using System.Application.Models; +using System.IO; +using System.Security.Cryptography; using System.Threading.Tasks; using System.Windows.Input; @@ -13,6 +15,11 @@ namespace System.Application.Services const float MaxProgressValue = 100f; + /// + /// 升级包存放文件夹名称 + /// + const string PackDirName = "UpgradePackages"; + /// /// 进度值 /// @@ -57,6 +64,67 @@ namespace System.Application.Services Task CheckUpdateAsync(bool force = false, bool showIsExistUpdateFalse = true); ICommand StartUpdateCommand { get; } + + /// + /// 根据新版本信息获取升级包路径名 + /// + /// + /// + protected static string GetPackName(AppVersionDTO m, bool isDirOrFile) => $"{m.Version}@{Hashs.String.Crc32(m.Id.ToByteArray())}{(isDirOrFile ? "" : $"{FileEx.TAR_GZ}")}"; + + /// + /// 获取存放升级包缓存文件夹的目录 + /// + /// 当目录不存在时是否创建目录 + /// 目录是否存在 + /// + protected static string GetPackCacheDirPath(bool onNotExistsCreateDirectory, out bool exists) + { + var dirPath = Path.Combine(IOPath.CacheDirectory, PackDirName); + exists = Directory.Exists(dirPath); + if (!exists && onNotExistsCreateDirectory) + { + Directory.CreateDirectory(dirPath); + + } + return dirPath; + } + + /// + /// 获取存放升级包缓存文件夹的目录 + /// + /// 是否需要清理之前的缓存 + /// + protected static string GetPackCacheDirPath(bool clear) + { + var dirPath = GetPackCacheDirPath(true, out var exists); + if (exists && clear) + { + var files = Directory.GetFiles(dirPath, "*" + FileEx.DownloadCache); + foreach (var item in files) + { + IOPath.FileTryDelete(item); + } + } + return dirPath; + } + + /// + /// 清理存放升级包缓存文件夹的目录 + /// + /// + static void ClearAllPackCacheDir() + { + var dirPath = GetPackCacheDirPath(true, out var exists); + if (exists) + { + var files = Directory.GetFiles(dirPath); + foreach (var item in files) + { + IOPath.FileTryDelete(item); + } + } + } } #if DEBUG diff --git a/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs b/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs index 90cc4d734..d1d407683 100644 --- a/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs +++ b/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs @@ -147,43 +147,6 @@ namespace System.Application.Services.Implementation isCheckUpdateing = false; } - /// - /// 升级包存放文件夹名称 - /// - const string PackDirName = "UpgradePackages"; - - public const string FileExDownloadCache = ".download_cache"; - - /// - /// 根据新版本信息获取升级包路径名 - /// - /// - /// - static string GetPackName(AppVersionDTO m, bool isDirOrFile) => $"{m.Version}@{Hashs.String.Crc32(m.Id.ToByteArray())}{(isDirOrFile ? "" : $"{FileEx.TAR_GZ}")}"; - - /// - /// 获取存放升级包缓存文件夹的目录 - /// - /// 是否需要清理之前的缓存 - /// - static string GetPackCacheDirPath(bool clear) - { - var dirPath = Path.Combine(IOPath.CacheDirectory, PackDirName); - if (!Directory.Exists(dirPath)) - { - Directory.CreateDirectory(dirPath); - } - else if (clear) - { - var files = Directory.GetFiles(dirPath, "*" + FileExDownloadCache); - foreach (var item in files) - { - IOPath.FileTryDelete(item); - } - } - return dirPath; - } - static bool isDownloading; /// @@ -211,7 +174,7 @@ namespace System.Application.Services.Implementation protected void OnReportCalcHashing(float value) => OnReport(value, SR.CalcHashing_.Format(MathF.Round(value, 2))); protected void OnReportDecompressing(float value) => OnReport(value, SR.Decompressing_.Format(MathF.Round(value, 2))); protected void OnReport(float value = 0f) => OnReport(value, string.Empty); - protected void OnReport(float value, string str) + protected virtual void OnReport(float value, string str) { ProgressValue = value; ProgressString = str; @@ -362,7 +325,7 @@ namespace System.Application.Services.Implementation #endregion #region 下载文件,并加入 hashFiles 中 - var cacheFileDownloadPath = downloadPath + FileExDownloadCache; + var cacheFileDownloadPath = downloadPath + FileEx.DownloadCache; var requestUri = GetSingleFileUrl(item.FileId!); var rsp = await client.Download( @@ -505,7 +468,7 @@ namespace System.Application.Services.Implementation requestUri = GetSingleFileUrl(download.FileIdOrUrl!); } - var cacheFilePath = packFilePath + FileExDownloadCache; + var cacheFilePath = packFilePath + FileEx.DownloadCache; OnReportDownloading(0f); var rsp = await client.Download( isAnonymous: true, diff --git a/src/ST.Client/Services/Implementation/ScriptManagerServiceImpl.cs b/src/ST.Client/Services/Implementation/ScriptManagerServiceImpl.cs index 6bdd13aa7..73ac5c99a 100644 --- a/src/ST.Client/Services/Implementation/ScriptManagerServiceImpl.cs +++ b/src/ST.Client/Services/Implementation/ScriptManagerServiceImpl.cs @@ -362,7 +362,7 @@ namespace System.Application.Services.Implementation var jspath = await DI.Get().DownloadScript(basicsInfo.Content.UpdateLink); if (jspath.state) { - var build = await DI.Get().AddScriptAsync(jspath.path,item, build: false, order: 1, deleteFile: true, pid: basicsInfo.Content.Id, ignoreCache: true); + var build = await DI.Get().AddScriptAsync(jspath.path, item, build: false, order: 1, deleteFile: true, pid: basicsInfo.Content.Id, ignoreCache: true); if (build.state && build.model?.Content != null) item.Content = build.model!.Content; } @@ -394,7 +394,7 @@ namespace System.Application.Services.Implementation try { var md5 = Hashs.String.MD5(scriptInfo); - var cachePath = Path.Combine(IOPath.CacheDirectory, TAG, $"{md5}{AppUpdateServiceImpl.FileExDownloadCache}"); + var cachePath = Path.Combine(IOPath.CacheDirectory, TAG, md5 + FileEx.DownloadCache); var fileInfo = new FileInfo(cachePath); if (!fileInfo.Directory.Exists) { diff --git a/src/ST/NotificationType.cs b/src/ST/NotificationType.cs index c14e2f7b5..f21995962 100644 --- a/src/ST/NotificationType.cs +++ b/src/ST/NotificationType.cs @@ -1,4 +1,4 @@ -namespace System.Application +namespace System.Application { /// /// 通知类型 @@ -17,7 +17,7 @@ /// /// /// 添加新的枚举常量注意事项: - /// (客户端)如果要显示在设备的通知栏上,则需要在中添加对应渠道 + /// (客户端)如果要显示在设备的通知栏上,则需要在 src\ST.Client\Extensions\NotificationType_Channel_EnumExtensions.cs 中添加或指定已有渠道 /// public enum NotificationType {