diff --git a/src/Starward.Language/Lang.Designer.cs b/src/Starward.Language/Lang.Designer.cs index f23b75100..5ed2bf34c 100644 --- a/src/Starward.Language/Lang.Designer.cs +++ b/src/Starward.Language/Lang.Designer.cs @@ -1547,6 +1547,78 @@ public static string GameLauncherPage_RemovableStorageDeviceNotConnected { } } + /// + /// 查找类似 Bastic Information 的本地化字符串。 + /// + public static string GameLauncherSettingDialog_BasticInformation { + get { + return ResourceManager.GetString("GameLauncherSettingDialog_BasticInformation", resourceCulture); + } + } + + /// + /// 查找类似 Command Line Argument 的本地化字符串。 + /// + public static string GameLauncherSettingDialog_CommandLineArgument { + get { + return ResourceManager.GetString("GameLauncherSettingDialog_CommandLineArgument", resourceCulture); + } + } + + /// + /// 查找类似 Custom Background 的本地化字符串。 + /// + public static string GameLauncherSettingDialog_CustomBackground { + get { + return ResourceManager.GetString("GameLauncherSettingDialog_CustomBackground", resourceCulture); + } + } + + /// + /// 查找类似 Game Packages 的本地化字符串。 + /// + public static string GameLauncherSettingDialog_GamePackages { + get { + return ResourceManager.GetString("GameLauncherSettingDialog_GamePackages", resourceCulture); + } + } + + /// + /// 查找类似 Relocate Game 的本地化字符串。 + /// + public static string GameLauncherSettingDialog_RelocateGame { + get { + return ResourceManager.GetString("GameLauncherSettingDialog_RelocateGame", resourceCulture); + } + } + + /// + /// 查找类似 See more information about command line argument. 的本地化字符串。 + /// + public static string GameLauncherSettingDialog_SeeMoreInformationAboutCommandLineArgument { + get { + return ResourceManager.GetString("GameLauncherSettingDialog_SeeMoreInformationAboutCommandLineArgument", resourceCulture); + } + } + + /// + /// 查找类似 Size 的本地化字符串。 + /// + public static string GameLauncherSettingDialog_Size { + get { + return ResourceManager.GetString("GameLauncherSettingDialog_Size", resourceCulture); + } + } + + /// + /// 查找类似 Startup Arguments 的本地化字符串。 + /// + public static string GameLauncherSettingDialog_StartupArguments { + get { + return ResourceManager.GetString("GameLauncherSettingDialog_StartupArguments", resourceCulture); + } + } + /// /// 查找类似 Diff Packages 的本地化字符串。 /// diff --git a/src/Starward.Language/Lang.resx b/src/Starward.Language/Lang.resx index 3c47d3062..653325d29 100644 --- a/src/Starward.Language/Lang.resx +++ b/src/Starward.Language/Lang.resx @@ -1618,4 +1618,28 @@ Do you accept the risk and continue to use it? Relocate + + Relocate Game + + + Size + + + Bastic Information + + + Startup Arguments + + + Custom Background + + + Game Packages + + + Command Line Argument + + + See more information about command line argument. + \ No newline at end of file diff --git a/src/Starward.Language/Lang.zh-CN.resx b/src/Starward.Language/Lang.zh-CN.resx index a668f91d6..bfdc1af02 100644 --- a/src/Starward.Language/Lang.zh-CN.resx +++ b/src/Starward.Language/Lang.zh-CN.resx @@ -555,7 +555,7 @@ 定位 - 一键修复 + 修复游戏 自定义启动程序 @@ -1618,4 +1618,28 @@ 重新定位 + + 重新定位游戏 + + + 大小 + + + 基本信息 + + + 启动参数 + + + 自定义背景 + + + 游戏包体 + + + 命令行参数 + + + 查看有关命令行参数的更多信息 + \ No newline at end of file diff --git a/src/Starward.Language/Lang.zh-TW.resx b/src/Starward.Language/Lang.zh-TW.resx index e73fcf67a..e1607eb55 100644 --- a/src/Starward.Language/Lang.zh-TW.resx +++ b/src/Starward.Language/Lang.zh-TW.resx @@ -59,7 +59,7 @@ : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> - + @@ -555,7 +555,7 @@ 定位 - 一鍵修復 + 修復遊戲 自訂啟動程式 diff --git a/src/Starward/Features/Background/AppBackground.xaml.cs b/src/Starward/Features/Background/AppBackground.xaml.cs index 110e11c09..e521a73ff 100644 --- a/src/Starward/Features/Background/AppBackground.xaml.cs +++ b/src/Starward/Features/Background/AppBackground.xaml.cs @@ -1,5 +1,6 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.WinUI.Helpers; using Microsoft.Extensions.Logging; using Microsoft.Graphics.Canvas; @@ -39,6 +40,8 @@ public sealed partial class AppBackground : UserControl public AppBackground() { this.InitializeComponent(); + WeakReferenceMessenger.Default.Register(this, OnBackgroundChanged); + Unloaded += (_, _) => { DisposeVideoResource(); WeakReferenceMessenger.Default.UnregisterAll(this); }; } @@ -76,10 +79,6 @@ public ImageSource? BackgroundImageSource } - private string? lastBackgroundFile; - - - private MediaPlayer? mediaPlayer; private SoftwareBitmap? softwareBitmap; @@ -109,7 +108,6 @@ private void InitializeBackgroundImage() if (!BackgroundService.FileIsSupportedVideo(file)) { BackgroundImageSource = new BitmapImage(new Uri(file)); - lastBackgroundFile = file; try { string? hex = AppConfig.AccentColor; @@ -125,7 +123,6 @@ private void InitializeBackgroundImage() else { BackgroundImageSource = new BitmapImage(new Uri("ms-appx:///Assets/Image/UI_CutScene_1130320101A.png")); - lastBackgroundFile = file; } } catch (Exception ex) @@ -155,11 +152,6 @@ public async Task UpdateBackgroundAsync() } var file = await _backgroundService.GetBackgroundFileAsync(CurrentGameId); - if (file == lastBackgroundFile) - { - return; - } - DisposeVideoResource(); BackgroundImageSource = null; @@ -173,7 +165,6 @@ public async Task UpdateBackgroundAsync() { await ChangeBackgroundImageAsync(file, cancelSource.Token); } - lastBackgroundFile = file; } } catch (COMException ex) @@ -303,6 +294,12 @@ private void MediaPlayer_VideoFrameAvailable(MediaPlayer sender, object args) + private async void OnBackgroundChanged(object _, BackgroundChangedMessage message) + { + await UpdateBackgroundAsync(); + } + + } diff --git a/src/Starward/Features/Background/BackgroundChangedMessage.cs b/src/Starward/Features/Background/BackgroundChangedMessage.cs new file mode 100644 index 000000000..6263dc226 --- /dev/null +++ b/src/Starward/Features/Background/BackgroundChangedMessage.cs @@ -0,0 +1,6 @@ +namespace Starward.Features.Background; + +internal class BackgroundChangedMessage +{ + +} diff --git a/src/Starward/Features/GameLauncher/GameAnnouncementSettingChangedMessage.cs b/src/Starward/Features/GameLauncher/GameAnnouncementSettingChangedMessage.cs new file mode 100644 index 000000000..d600bd523 --- /dev/null +++ b/src/Starward/Features/GameLauncher/GameAnnouncementSettingChangedMessage.cs @@ -0,0 +1,6 @@ +namespace Starward.Features.GameLauncher; + +internal class GameAnnouncementSettingChangedMessage +{ + +} diff --git a/src/Starward/Features/GameLauncher/GameBannerAndPost.xaml.cs b/src/Starward/Features/GameLauncher/GameBannerAndPost.xaml.cs index d9e9643e0..75c4f9f68 100644 --- a/src/Starward/Features/GameLauncher/GameBannerAndPost.xaml.cs +++ b/src/Starward/Features/GameLauncher/GameBannerAndPost.xaml.cs @@ -57,6 +57,7 @@ private async void GameBannerAndPost_Loaded(object sender, RoutedEventArgs e) { WeakReferenceMessenger.Default.Register(this, OnMainWindowStateChanged); WeakReferenceMessenger.Default.Register(this, OnGameNoticeWindowClosed); + WeakReferenceMessenger.Default.Register(this, OnGameAnnouncementSettingChanged); await UpdateGameContentAsync(); await UpdateGameNoticeAlertAsync(); } @@ -83,6 +84,28 @@ private async void OnGameNoticeWindowClosed(object _, GameNoticeWindowClosedMess } + private async void OnGameAnnouncementSettingChanged(object _, GameAnnouncementSettingChangedMessage message) + { + if (AppSetting.EnableBannerAndPost) + { + ShowBannerAndPost = true; + await UpdateGameContentAsync(); + if (AppSetting.DisableGameNoticeRedHot) + { + IsGameNoticesAlert = false; + } + else + { + await UpdateGameNoticeAlertAsync(); + } + } + else + { + ShowBannerAndPost = false; + } + } + + public List? Banners { get; set => SetProperty(ref field, value); } diff --git a/src/Starward/Features/GameLauncher/GameLauncherPage.xaml b/src/Starward/Features/GameLauncher/GameLauncherPage.xaml index 71a7e9287..4a6a0ed3f 100644 --- a/src/Starward/Features/GameLauncher/GameLauncherPage.xaml +++ b/src/Starward/Features/GameLauncher/GameLauncherPage.xaml @@ -37,6 +37,7 @@ diff --git a/src/Starward/Features/GameLauncher/GameLauncherPage.xaml.cs b/src/Starward/Features/GameLauncher/GameLauncherPage.xaml.cs index 28640781c..4348cca35 100644 --- a/src/Starward/Features/GameLauncher/GameLauncherPage.xaml.cs +++ b/src/Starward/Features/GameLauncher/GameLauncherPage.xaml.cs @@ -202,6 +202,12 @@ private async Task StartGameAsync() + [RelayCommand] + private async Task OpenGameLauncherSettingDialogAsync() + { + await new GameLauncherSettingDialog { CurrentGameId = this.CurrentGameId, XamlRoot = this.XamlRoot }.ShowAsync(); + } + diff --git a/src/Starward/Features/GameLauncher/GameLauncherSettingDialog.xaml b/src/Starward/Features/GameLauncher/GameLauncherSettingDialog.xaml new file mode 100644 index 000000000..2b79b8357 --- /dev/null +++ b/src/Starward/Features/GameLauncher/GameLauncherSettingDialog.xaml @@ -0,0 +1,541 @@ + + + + + 1200 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0,8,0,0 + 0,0,24,0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Starward/Features/GameLauncher/GameLauncherSettingDialog.xaml.cs b/src/Starward/Features/GameLauncher/GameLauncherSettingDialog.xaml.cs new file mode 100644 index 000000000..246667c97 --- /dev/null +++ b/src/Starward/Features/GameLauncher/GameLauncherSettingDialog.xaml.cs @@ -0,0 +1,693 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using CommunityToolkit.Mvvm.Messaging; +using Microsoft.Extensions.Logging; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media; +using Starward.Core; +using Starward.Core.HoYoPlay; +using Starward.Features.Background; +using Starward.Features.GameSelector; +using Starward.Features.HoYoPlay; +using Starward.Frameworks; +using Starward.Helpers; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.Storage; +using Windows.System; + +#pragma warning disable MVVMTK0034 // Direct field reference to [ObservableProperty] backing field +#pragma warning disable MVVMTK0045 // Using [ObservableProperty] on fields is not AOT compatible for WinRT + + +namespace Starward.Features.GameLauncher; + +[INotifyPropertyChanged] +public sealed partial class GameLauncherSettingDialog : ContentDialog +{ + + + private readonly ILogger _logger = AppService.GetLogger(); + + + private readonly HoYoPlayService _hoyoPlayService = AppService.GetService(); + + + private readonly GameLauncherService _gameLauncherService = AppService.GetService(); + + + public GameLauncherSettingDialog() + { + this.InitializeComponent(); + this.Loaded += GameLauncherSettingDialog_Loaded; + } + + + + public GameId CurrentGameId { get; set; } + + + public GameBiz CurrentGameBiz { get; set; } + + + public string CurrentSettingTitle { get; set => SetProperty(ref field, value); } = "Basic Information"; + + + + + + private void FlipView_Settings_Loaded(object sender, RoutedEventArgs e) + { + try + { + var grid = VisualTreeHelper.GetChild(FlipView_Settings, 0); + if (grid != null) + { + var count = VisualTreeHelper.GetChildrenCount(grid); + if (count > 0) + { + for (int i = 0; i < count; i++) + { + var child = VisualTreeHelper.GetChild(grid, i); + if (child is Button button) + { + button.IsHitTestVisible = false; + button.Opacity = 0; + } + else if (child is ScrollViewer scrollViewer) + { + scrollViewer.PointerWheelChanged += (_, e) => e.Handled = true; + } + } + } + } + } + catch { } + } + + + + + private void NavigationView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) + { + try + { + if (args.InvokedItemContainer?.Content is string title) + { + CurrentSettingTitle = title; + } + if (args.InvokedItemContainer?.Tag is string index && int.TryParse(index, out int target)) + { + int steps = target - FlipView_Settings.SelectedIndex; + if (steps > 0) + { + for (int i = 0; i < steps; i++) + { + FlipView_Settings.SelectedIndex++; + } + } + else + { + for (int i = 0; i < -steps; i++) + { + FlipView_Settings.SelectedIndex--; + } + } + } + } + catch { } + } + + + + + private async void GameLauncherSettingDialog_Loaded(object sender, RoutedEventArgs e) + { + CurrentGameBiz = CurrentGameId?.GameBiz ?? GameBiz.None; + await InitializeBasicInfoAsync(); + InitializeStartArgument(); + InitializeCustomBg(); + await InitializeGamePackagesAsync(); + } + + + + + [RelayCommand] + private void Close() + { + this.Hide(); + } + + + + + + #region 基本信息 + + + + + public GameBizIcon CurrentGameBizIcon { get; set => SetProperty(ref field, value); } + + + public string? InstallPath { get; set => SetProperty(ref field, value); } + + + public string? GameSize { get; set => SetProperty(ref field, value); } + + + public bool UninstallAndRepairEnabled { get; set => SetProperty(ref field, value); } + + + public bool EnableBannerAndPost + { + get; + set + { + SetProperty(ref field, value); + AppSetting.EnableBannerAndPost = value; + WeakReferenceMessenger.Default.Send(new GameAnnouncementSettingChangedMessage()); + } + } = AppSetting.EnableBannerAndPost; + + + + public bool DisableGameNoticeRedHot + { + get; + set + { + SetProperty(ref field, value); + AppSetting.DisableGameNoticeRedHot = value; + WeakReferenceMessenger.Default.Send(new GameAnnouncementSettingChangedMessage()); + } + } = AppSetting.DisableGameNoticeRedHot; + + + + + private async Task InitializeBasicInfoAsync() + { + try + { + if (CurrentGameId.GameBiz.IsKnown()) + { + CurrentGameBizIcon = new GameBizIcon(CurrentGameId.GameBiz); + } + else + { + var info = await _hoyoPlayService.GetGameInfoAsync(CurrentGameId); + CurrentGameBizIcon = new GameBizIcon(info); + } + InstallPath = _gameLauncherService.GetGameInstallPath(CurrentGameId, out bool storageRemoved); + UninstallAndRepairEnabled = InstallPath != null && !storageRemoved; + GameSize = GetSize(InstallPath); + } + catch (Exception ex) + { + _logger.LogError(ex, "InitializeBasicInfoAsync ({biz})", CurrentGameBiz); + } + } + + + + private static string? GetSize(string? path) + { + if (!Directory.Exists(path)) + { + return null; + } + var size = new DirectoryInfo(path).EnumerateFiles("*", SearchOption.AllDirectories).Sum(f => f.Length); + var gb = (double)size / (1 << 30); + return $"{gb:F2}GB"; + } + + + + + [RelayCommand] + private async Task OpenInstalGameFolderAsync() + { + try + { + if (Directory.Exists(InstallPath)) + { + await Launcher.LaunchUriAsync(new Uri(InstallPath)); + } + } + catch { } + } + + + + + [RelayCommand] + private async Task RelocateGameAsync() + { + // todo + } + + + + [RelayCommand] + private async Task RepairGameAsync() + { + // todo + } + + + + + + #endregion + + + + + #region 启动参数 + + + + [ObservableProperty] + public string? _StartGameArgument; + partial void OnStartGameArgumentChanged(string? value) + { + AppSetting.SetStartArgument(CurrentGameBiz, value); + } + + + public int StartGameAction + { + get; + set + { + SetProperty(ref field, value); + AppSetting.StartGameAction = (StartGameAction)value; + } + } = Math.Clamp((int)AppSetting.StartGameAction, 0, 2); + + + [ObservableProperty] + public bool _EnableThirdPartyTool; + partial void OnEnableThirdPartyToolChanged(bool value) + { + AppSetting.SetEnableThirdPartyTool(CurrentGameBiz, value); + } + + + + [ObservableProperty] + public string? _ThirdPartyToolPath; + partial void OnThirdPartyToolPathChanged(string? value) + { + AppSetting.SetThirdPartyToolPath(CurrentGameBiz, value); + } + + + + private void InitializeStartArgument() + { + _StartGameArgument = AppSetting.GetStartArgument(CurrentGameBiz); + _EnableThirdPartyTool = AppSetting.GetEnableThirdPartyTool(CurrentGameBiz); + _ThirdPartyToolPath = AppSetting.GetThirdPartyToolPath(CurrentGameBiz); + OnPropertyChanged(nameof(StartGameArgument)); + OnPropertyChanged(nameof(EnableThirdPartyTool)); + OnPropertyChanged(nameof(ThirdPartyToolPath)); + } + + + + + [RelayCommand] + private async Task ChangeThirdPartyPathAsync() + { + try + { + var file = await FileDialogHelper.PickSingleFileAsync(this.XamlRoot); + if (File.Exists(file)) + { + ThirdPartyToolPath = file; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Change third party tool path ({biz})", CurrentGameBiz); + } + } + + + + [RelayCommand] + private async Task OpenThirdPartyToolFolderAsync() + { + try + { + if (File.Exists(ThirdPartyToolPath)) + { + var folder = Path.GetDirectoryName(ThirdPartyToolPath); + var file = await StorageFile.GetFileFromPathAsync(ThirdPartyToolPath); + var option = new FolderLauncherOptions(); + option.ItemsToSelect.Add(file); + await Launcher.LaunchFolderPathAsync(folder, option); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Open third party tool folder {folder}", ThirdPartyToolPath); + } + } + + + + [RelayCommand] + private void DeleteThirdPartyToolPath() + { + ThirdPartyToolPath = null; + } + + + + + + #endregion + + + + + #region 自定义背景 + + + + [ObservableProperty] + public bool _EnableCustomBg; + partial void OnEnableCustomBgChanged(bool value) + { + AppSetting.SetEnableCustomBg(CurrentGameBiz, value); + WeakReferenceMessenger.Default.Send(new BackgroundChangedMessage()); + } + + + public string? CustomBg { get; set => SetProperty(ref field, value); } + + + + [RelayCommand] + private async Task ChangeCustomBgAsync() + { + // todo + } + + + [RelayCommand] + private async Task OpenCustomBgAsync() + { + // todo + } + + + [RelayCommand] + private void DeleteCustomBg() + { + AppConfig.SetCustomBg(CurrentGameBiz, null); + CustomBg = null; + } + + + + private void InitializeCustomBg() + { + _EnableCustomBg = AppSetting.GetEnableCustomBg(CurrentGameBiz); + CustomBg = AppSetting.GetCustomBg(CurrentGameBiz); + OnPropertyChanged(nameof(EnableCustomBg)); + } + + + + #endregion + + + + + #region 游戏包体 + + + + + public string LatestVersion { get; set => SetProperty(ref field, value); } + + + public List LatestPackageGroups { get; set => SetProperty(ref field, value); } + + + public string PreInstallVersion { get; set => SetProperty(ref field, value); } + + + public List PreInstallPackageGroups { get; set => SetProperty(ref field, value); } + + + + + private async Task InitializeGamePackagesAsync() + { + try + { + var gamePackage = await _hoyoPlayService.GetGamePackageAsync(CurrentGameId); + LatestVersion = gamePackage.Main.Major!.Version; + var list = GetGameResourcePackageGroups(gamePackage.Main); + var sdk = await _hoyoPlayService.GetGameChannelSDKAsync(CurrentGameId); + if (sdk is not null) + { + list.Add(new PackageGroup + { + Name = "Channel SDK", + Items = [new PackageItem + { + FileName = Path.GetFileName(sdk.ChannelSDKPackage.Url), + Url = sdk.ChannelSDKPackage.Url, + Md5 = sdk.ChannelSDKPackage.MD5, + PackageSize = sdk.ChannelSDKPackage.Size, + DecompressSize = sdk.ChannelSDKPackage.DecompressedSize, + }], + }); + } + // todo plugin + LatestPackageGroups = list; + if (!string.IsNullOrWhiteSpace(gamePackage.PreDownload?.Major?.Version)) + { + PreInstallVersion = gamePackage.PreDownload.Major.Version; + PreInstallPackageGroups = GetGameResourcePackageGroups(gamePackage.PreDownload); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Get game resource failed, gameBiz: {gameBiz}", CurrentGameBiz); + } + } + + + + private List GetGameResourcePackageGroups(GamePackageVersion gameResource) + { + var list = new List(); + var fullPackageGroup = new PackageGroup + { + Name = Lang.GameResourcePage_FullPackages, + Items = new List() + }; + foreach (var item in gameResource.Major?.GamePackages ?? []) + { + fullPackageGroup.Items.Add(new PackageItem + { + FileName = Path.GetFileName(item.Url), + Url = item.Url, + Md5 = item.MD5, + PackageSize = item.Size, + DecompressSize = item.DecompressedSize, + }); + } + foreach (var item in gameResource.Major?.AudioPackages ?? []) + { + fullPackageGroup.Items.Add(new PackageItem + { + FileName = Path.GetFileName(item.Url), + Url = item.Url, + Md5 = item.MD5, + PackageSize = item.Size, + DecompressSize = item.DecompressedSize, + }); + } + list.Add(fullPackageGroup); + + foreach (var patch in gameResource.Patches ?? []) + { + var diffPackageGroup = new PackageGroup + { + Name = $"{Lang.GameResourcePage_DiffPackages} {patch.Version}", + Items = new List() + }; + foreach (var item in patch.GamePackages ?? []) + { + diffPackageGroup.Items.Add(new PackageItem + { + FileName = Path.GetFileName(item.Url), + Url = item.Url, + Md5 = item.MD5, + PackageSize = item.Size, + DecompressSize = item.DecompressedSize, + }); + } + foreach (var item in patch.AudioPackages ?? []) + { + diffPackageGroup.Items.Add(new PackageItem + { + FileName = Path.GetFileName(item.Url), + Url = item.Url, + Md5 = item.MD5, + PackageSize = item.Size, + DecompressSize = item.DecompressedSize, + }); + } + list.Add(diffPackageGroup); + } + return list; + } + + + + private async void Button_CopyUrl_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) + { + try + { + if (sender is Button button) + { + if (button.DataContext is PackageGroup group) + { + if (group.Items is not null) + { + var sb = new StringBuilder(); + foreach (var item in group.Items) + { + if (!string.IsNullOrEmpty(item.Url)) + { + sb.AppendLine(item.Url); + } + } + string url = sb.ToString().TrimEnd(); + if (!string.IsNullOrWhiteSpace(url)) + { + ClipboardHelper.SetText(url); + await CopySuccessAsync(button); + } + } + } + if (button.DataContext is PackageItem package) + { + if (!string.IsNullOrEmpty(package.Url)) + { + ClipboardHelper.SetText(package.Url); + await CopySuccessAsync(button); + } + } + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Copy url failed"); + } + } + + + + private async Task CopySuccessAsync(Button button) + { + try + { + button.IsEnabled = false; + if (button.Content is FontIcon icon) + { + // Accpet + icon.Glyph = "\uF78C"; + await Task.Delay(1000); + } + } + finally + { + button.IsEnabled = true; + if (button.Content is FontIcon icon) + { + // Link + icon.Glyph = "\uE71B"; + } + } + } + + + + + public class PackageGroup + { + public string Name { get; set; } + + public List Items { get; set; } + } + + + + public class PackageItem + { + public string FileName { get; set; } + + public string Url { get; set; } + + public string Md5 { get; set; } + + public long PackageSize { get; set; } + + public long DecompressSize { get; set; } + + public string PackageSizeString => GetSizeString(PackageSize); + + public string DecompressSizeString => GetSizeString(DecompressSize); + + private string GetSizeString(long size) + { + const double KB = 1 << 10; + const double MB = 1 << 20; + const double GB = 1 << 30; + if (size >= GB) + { + return $"{size / GB:F2} GB"; + } + else if (size >= MB) + { + return $"{size / MB:F2} MB"; + } + else + { + return $"{size / KB:F2} KB"; + } + } + } + + + + #endregion + + + + + + private void TextBlock_IsTextTrimmedChanged(TextBlock sender, IsTextTrimmedChangedEventArgs args) + { + sender.FontSize -= 1; + } + + + +} diff --git a/src/Starward/Features/GameLauncher/StartGameAction.cs b/src/Starward/Features/GameLauncher/StartGameAction.cs new file mode 100644 index 000000000..0916d2bf6 --- /dev/null +++ b/src/Starward/Features/GameLauncher/StartGameAction.cs @@ -0,0 +1,12 @@ +namespace Starward.Features.GameLauncher; + +public enum StartGameAction +{ + + DoNothing = 0, + + Minimize = 1, + + Hide = 2, + +} diff --git a/src/Starward/Frameworks/AppSetting.cs b/src/Starward/Frameworks/AppSetting.cs index db77160d5..c05f4fffc 100644 --- a/src/Starward/Frameworks/AppSetting.cs +++ b/src/Starward/Frameworks/AppSetting.cs @@ -1,8 +1,8 @@ using Dapper; using Starward.Core; using Starward.Features.Database; +using Starward.Features.GameLauncher; using Starward.Features.ViewHost; -using Starward.Models; using System; using System.Collections.Generic; using System.ComponentModel; @@ -235,9 +235,9 @@ public static bool DisableGameNoticeRedHot } - public static AfterStartGameAction AfterStartGameAction + public static StartGameAction StartGameAction { - get => GetValue(); + get => GetValue(); set => SetValue(value); } diff --git a/src/Starward/Helpers/FileDialogHelper.cs b/src/Starward/Helpers/FileDialogHelper.cs index c04b8940d..7c580b158 100644 --- a/src/Starward/Helpers/FileDialogHelper.cs +++ b/src/Starward/Helpers/FileDialogHelper.cs @@ -1,5 +1,6 @@ // https://referencesource.microsoft.com/#system.windows.forms/winforms/Managed/System/WinForms/FileDialog_Vista_Interop.cs +using Microsoft.UI.Xaml; using System; using System.Collections.Generic; using System.ComponentModel; @@ -78,6 +79,11 @@ internal static class FileDialogHelper } + public static async Task PickSingleFileAsync(XamlRoot xamlRoot, params (string Name, string Extension)[] fileTypeFilter) + { + return await PickSingleFileAsync((nint)xamlRoot.ContentIslandEnvironment.AppWindowId.Value, fileTypeFilter); + } + public static async Task OpenSaveFileDialogAsync(nint parentWindow, string? fileName = null, params (string Name, string Extension)[] fileTypeFilter) { @@ -147,6 +153,11 @@ internal static class FileDialogHelper } + public static async Task OpenSaveFileDialogAsync(XamlRoot xamlRoot, string? fileName = null, params (string Name, string Extension)[] fileTypeFilter) + { + return await OpenSaveFileDialogAsync((nint)xamlRoot.ContentIslandEnvironment.AppWindowId.Value, fileName, fileTypeFilter); + } + private static COMDLG_FILTERSPEC[] SetFileTypeFilter(in IFileDialog dialog, params (string Name, string Spec)[] fileTypeFilter) { @@ -223,6 +234,11 @@ private static COMDLG_FILTERSPEC[] SetFileTypeFilter(in IFileDialog dialog, para } + public static async Task PickFolderAsync(XamlRoot xamlRoot) + { + return await PickFolderAsync((nint)xamlRoot.ContentIslandEnvironment.AppWindowId.Value); + } + }