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);
+ }
+
}