From 603f2d544beb4001c29fa9df202e3487f77c22a1 Mon Sep 17 00:00:00 2001 From: Scighost Date: Sat, 27 Jul 2024 11:57:06 +0800 Subject: [PATCH] ipdate --- .../Controls/InstallGameController.xaml | 117 ++++++++--- .../Controls/InstallGameController.xaml.cs | 21 ++ .../Controls/InstallGameDialog.xaml.cs | 2 +- .../Download/GenshinInstallGameService.cs | 4 +- .../Services/Download/InstallGameManager.cs | 21 +- .../Services/Download/InstallGameService.cs | 21 +- .../Download/InstallGameStateModel.cs | 198 ++++++++++++------ 7 files changed, 268 insertions(+), 116 deletions(-) diff --git a/src/Starward/Controls/InstallGameController.xaml b/src/Starward/Controls/InstallGameController.xaml index 957d8ab14..5e93c2f74 100644 --- a/src/Starward/Controls/InstallGameController.xaml +++ b/src/Starward/Controls/InstallGameController.xaml @@ -21,13 +21,13 @@ - + - + @@ -36,16 +36,27 @@ - + - - + + + + + + + + + + + - + + 4 @@ -70,32 +88,67 @@ - - - - - + + + + + + + + + + + + + + + + diff --git a/src/Starward/Controls/InstallGameController.xaml.cs b/src/Starward/Controls/InstallGameController.xaml.cs index 58e3a2224..e38c88f3d 100644 --- a/src/Starward/Controls/InstallGameController.xaml.cs +++ b/src/Starward/Controls/InstallGameController.xaml.cs @@ -77,6 +77,7 @@ private void _installGameManager_InstallTaskRemoved(object? sender, InstallGameS { _timer.Stop(); Button_Controller.Visibility = Visibility.Collapsed; + Flyout_InstallGame.Hide(); } } finally @@ -105,4 +106,24 @@ private void _timer_Tick(DispatcherQueueTimer sender, object args) } + + private void Grid_ActionButtonOverlay_PointerEntered(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) + { + if (sender is Grid grid) + { + grid.Opacity = 1; + } + } + + + + private void Grid_ActionButtonOverlay_PointerExited(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) + { + if (sender is Grid grid) + { + grid.Opacity = 0; + } + } + + } diff --git a/src/Starward/Controls/InstallGameDialog.xaml.cs b/src/Starward/Controls/InstallGameDialog.xaml.cs index acb38fd58..387bd27d6 100644 --- a/src/Starward/Controls/InstallGameDialog.xaml.cs +++ b/src/Starward/Controls/InstallGameDialog.xaml.cs @@ -150,7 +150,7 @@ private async Task StartInstallationAsync() try { _installGameService.Initialize(CurrentGameBiz, InstallationPath); - await _installGameService.StartRepairGameAsync(); + await _installGameService.StartInstallGameAsync(); InstallGameManager.Instance.AddInstallService(_installGameService); this.Hide(); } diff --git a/src/Starward/Services/Download/GenshinInstallGameService.cs b/src/Starward/Services/Download/GenshinInstallGameService.cs index ca5024414..7a12d2514 100644 --- a/src/Starward/Services/Download/GenshinInstallGameService.cs +++ b/src/Starward/Services/Download/GenshinInstallGameService.cs @@ -44,7 +44,7 @@ public override async Task StartRepairGameAsync(CancellationToken cancellationTo await PrepareBilibiliChannelSDKAsync(InstallGameItemType.Verify); } await MoveAudioAssetsFromPersistentToStreamAssetsAsync(); - _installTask = InstallGameTask.Repair; + InstallTask = InstallGameTask.Repair; StartTask(InstallGameState.Verify); } @@ -69,7 +69,7 @@ public override async Task StartUpdateGameAsync(CancellationToken cancellationTo await PrepareBilibiliChannelSDKAsync(InstallGameItemType.Download); } await MoveAudioAssetsFromPersistentToStreamAssetsAsync(); - _installTask = InstallGameTask.Update; + InstallTask = InstallGameTask.Update; StartTask(InstallGameState.Download); } diff --git a/src/Starward/Services/Download/InstallGameManager.cs b/src/Starward/Services/Download/InstallGameManager.cs index b1e238274..c41dc10cb 100644 --- a/src/Starward/Services/Download/InstallGameManager.cs +++ b/src/Starward/Services/Download/InstallGameManager.cs @@ -68,15 +68,13 @@ public void AddInstallService(InstallGameService service) model.InstallFinished += Model_InstallFinished; model.InstallFailed -= Model_InstallFailed; model.InstallFailed += Model_InstallFailed; + model.InstallCanceled -= Model_InstallCanceled; + model.InstallCanceled += Model_InstallCanceled; InstallTaskAdded?.Invoke(this, model); } - - - - private void Model_InstallFinished(object? sender, EventArgs e) { if (sender is InstallGameStateModel model) @@ -85,6 +83,7 @@ private void Model_InstallFinished(object? sender, EventArgs e) _services.TryRemove(model.GameBiz, out _); model.InstallFinished -= Model_InstallFinished; model.InstallFailed -= Model_InstallFailed; + model.InstallCanceled -= Model_InstallCanceled; InstallTaskRemoved?.Invoke(this, model); } } @@ -100,6 +99,20 @@ private void Model_InstallFailed(object? sender, EventArgs e) } + private void Model_InstallCanceled(object? sender, EventArgs e) + { + if (sender is InstallGameStateModel model) + { + model.Service.Pause(); + model.Service.ClearState(); + _services.TryRemove(model.GameBiz, out _); + model.InstallFinished -= Model_InstallFinished; + model.InstallFailed -= Model_InstallFailed; + model.InstallCanceled -= Model_InstallCanceled; + InstallTaskRemoved?.Invoke(this, model); + } + } + } diff --git a/src/Starward/Services/Download/InstallGameService.cs b/src/Starward/Services/Download/InstallGameService.cs index 1f19d6c06..199b5cf34 100644 --- a/src/Starward/Services/Download/InstallGameService.cs +++ b/src/Starward/Services/Download/InstallGameService.cs @@ -68,6 +68,9 @@ public static InstallGameService FromGameBiz(GameBiz gameBiz) public GameBiz CurrentGameBiz { get; protected set; } + public InstallGameTask InstallTask { get; protected set; } + + private InstallGameState _state; public InstallGameState State { @@ -112,9 +115,6 @@ protected void OnInstallFailed(Exception ex) protected string _installPath; - protected InstallGameTask _installTask; - - protected InstallGameState _pausedState; @@ -249,7 +249,7 @@ public virtual async Task StartInstallGameAsync(CancellationToken cancellationTo { await PrepareBilibiliChannelSDKAsync(InstallGameItemType.Download); } - _installTask = InstallGameTask.Install; + InstallTask = InstallGameTask.Install; StartTask(InstallGameState.Download); } @@ -273,7 +273,7 @@ public virtual async Task StartRepairGameAsync(CancellationToken cancellationTok { await PrepareBilibiliChannelSDKAsync(InstallGameItemType.Verify); } - _installTask = InstallGameTask.Repair; + InstallTask = InstallGameTask.Repair; StartTask(InstallGameState.Verify); } @@ -298,7 +298,7 @@ public virtual async Task StartPredownloadAsync(CancellationToken cancellationTo resource = _gamePackage.PreDownload.Major!; } await PrepareDownloadGamePackageResourceAsync(resource); - _installTask = InstallGameTask.Predownload; + InstallTask = InstallGameTask.Predownload; StartTask(InstallGameState.Download); } @@ -323,7 +323,7 @@ public virtual async Task StartUpdateGameAsync(CancellationToken cancellationTok { await PrepareBilibiliChannelSDKAsync(InstallGameItemType.Download); } - _installTask = InstallGameTask.Update; + InstallTask = InstallGameTask.Update; StartTask(InstallGameState.Download); } @@ -673,15 +673,15 @@ private void CurrentTaskFinished() { try { - if (_installTask is InstallGameTask.Install or InstallGameTask.Update) + if (InstallTask is InstallGameTask.Install or InstallGameTask.Update) { OnInstallOrUpdateTaskFinished(); } - else if (_installTask is InstallGameTask.Repair) + else if (InstallTask is InstallGameTask.Repair) { OnRepairTaskFinished(); } - else if (_installTask is InstallGameTask.Predownload) + else if (InstallTask is InstallGameTask.Predownload) { OnPredownloadTaskFinished(); } @@ -928,7 +928,6 @@ protected void Finish() - #region Execute Item (Download, Verify, Decompress, Patch) diff --git a/src/Starward/Services/Download/InstallGameStateModel.cs b/src/Starward/Services/Download/InstallGameStateModel.cs index 8862d7639..08bd51a81 100644 --- a/src/Starward/Services/Download/InstallGameStateModel.cs +++ b/src/Starward/Services/Download/InstallGameStateModel.cs @@ -14,12 +14,13 @@ public partial class InstallGameStateModel : ObservableObject private const string PlayGlyph = "\uE768"; - private const string PauseGlyph = "\uE769"; - private const double GB = 1 << 30; + private const double MB = 1 << 20; + + private const double KB = 1 << 10; @@ -53,7 +54,8 @@ internal InstallGameStateModel(InstallGameService service) public event EventHandler InstallFailed; - public double SpeedBytesPerMiniute { get; set; } + public event EventHandler InstallCanceled; + [ObservableProperty] @@ -73,16 +75,27 @@ internal InstallGameStateModel(InstallGameService service) [ObservableProperty] - private bool _isActionButtonEnabled = true; + private string? _SpeedText; + + + [ObservableProperty] + private string? _RemainingTimeText; + + + [ObservableProperty] + private bool _isContinueOrPauseButtonEnabled = true; private long _lastTimestamp; private long _lastFinishedBytes; + public double _speedBytesPerSecond; + + [RelayCommand] - private void ActionButton() + private void ContinueOrPause() { if (ButtonGlyph is PlayGlyph) { @@ -97,84 +110,136 @@ private void ActionButton() + [RelayCommand] + private void Cancel() + { + InstallCanceled?.Invoke(this, EventArgs.Empty); + } + + public void UpdateState() { - IsActionButtonEnabled = true; - switch (Service.State) + try { - case InstallGameState.None: - StateText = "Paused"; - ButtonGlyph = PlayGlyph; - break; - case InstallGameState.Download: - StateText = Lang.DownloadGamePage_Downloading; - if (Service.TotalBytes == 0) - { + IsContinueOrPauseButtonEnabled = true; + switch (Service.State) + { + case InstallGameState.None: + StateText = "Paused"; + ButtonGlyph = PlayGlyph; + break; + case InstallGameState.Download: + StateText = Lang.DownloadGamePage_Downloading; + if (Service.TotalBytes == 0) + { + Progress = 100; + ProgressText = ""; + } + else + { + Progress = 100d * Service.FinishBytes / Service.TotalBytes; + ProgressText = $"{Service.FinishBytes / GB:F2}/{Service.TotalBytes / GB:F2} GB"; + } + ButtonGlyph = PauseGlyph; + break; + case InstallGameState.Verify: + StateText = Lang.DownloadGamePage_Verifying; + if (Service.TotalCount == 0) + { + Progress = 100; + ProgressText = ""; + } + else if (Service.InstallTask is InstallGameTask.Repair) + { + Progress = 100d * Service.FinishCount / Service.TotalCount; + ProgressText = $"{Service.FinishCount}/{Service.TotalCount}"; + } + else + { + Progress = 100d * Service.FinishBytes / Service.TotalBytes; + ProgressText = $"{Service.FinishBytes / GB:F2}/{Service.TotalBytes / GB:F2} GB"; + } + ButtonGlyph = PauseGlyph; + break; + case InstallGameState.Decompress: + StateText = Lang.DownloadGamePage_Decompressing; + if (Service.TotalBytes == 0) + { + Progress = 100; + ProgressText = ""; + } + else + { + Progress = 100d * Service.FinishBytes / Service.TotalBytes; + ProgressText = $"{Service.FinishBytes / GB:F2}/{Service.TotalBytes / GB:F2} GB"; + } + IsContinueOrPauseButtonEnabled = false; + ButtonGlyph = PauseGlyph; + break; + case InstallGameState.Clean: + IsContinueOrPauseButtonEnabled = false; + ButtonGlyph = PauseGlyph; + break; + case InstallGameState.Finish: + StateText = Lang.DownloadGamePage_Finished; Progress = 100; ProgressText = ""; - } - else - { - Progress = 100d * Service.FinishBytes / Service.TotalBytes; - ProgressText = $"{Service.FinishBytes / GB:F2}/{Service.TotalBytes / GB:F2} GB"; - } - ButtonGlyph = PauseGlyph; - break; - case InstallGameState.Verify: - StateText = Lang.DownloadGamePage_Verifying; - if (Service.TotalCount == 0) + IsContinueOrPauseButtonEnabled = false; + ButtonGlyph = PlayGlyph; + InstallFinished?.Invoke(this, EventArgs.Empty); + break; + case InstallGameState.Error: + StateText = Lang.DownloadGamePage_UnknownError; + ButtonGlyph = PlayGlyph; + InstallFailed?.Invoke(this, EventArgs.Empty); + break; + default: + break; + } + ComputeSpeed(Service.State); + } + catch { } + } + + + + private void ComputeSpeed(InstallGameState state) + { + try + { + long ts = Stopwatch.GetTimestamp(); + long bytes = Service.FinishBytes; + _speedBytesPerSecond = Math.Clamp((double)(bytes - _lastFinishedBytes) / (ts - _lastTimestamp) * Stopwatch.Frequency, 0, long.MaxValue); + _lastFinishedBytes = bytes; + _lastTimestamp = ts; + if (state is InstallGameState.None or InstallGameState.Finish or InstallGameState.Error) + { + SpeedText = null; + RemainingTimeText = null; + } + else + { + if (_speedBytesPerSecond >= MB) { - Progress = 100; - ProgressText = ""; + SpeedText = $"{_speedBytesPerSecond / MB:F2} MB/s"; } else { - Progress = 100d * Service.FinishCount / Service.TotalCount; - ProgressText = $"{Service.FinishCount}/{Service.TotalCount}"; + SpeedText = $"{_speedBytesPerSecond / KB:F2} KB/s"; } - ButtonGlyph = PauseGlyph; - break; - case InstallGameState.Decompress: - StateText = Lang.DownloadGamePage_Decompressing; - if (Service.TotalBytes == 0) + if (_speedBytesPerSecond == 0) { - Progress = 100; - ProgressText = ""; + RemainingTimeText = null; } else { - Progress = 100d * Service.FinishBytes / Service.TotalBytes; - ProgressText = $"{Service.FinishBytes / GB:F2}/{Service.TotalBytes / GB:F2} GB"; + var seconds = (Service.TotalBytes - Service.FinishBytes) / _speedBytesPerSecond; + RemainingTimeText = TimeSpan.FromSeconds(seconds).ToString(@"hh\:mm\:ss"); } - IsActionButtonEnabled = false; - ButtonGlyph = PauseGlyph; - break; - case InstallGameState.Clean: - IsActionButtonEnabled = false; - ButtonGlyph = PauseGlyph; - break; - case InstallGameState.Finish: - StateText = Lang.DownloadGamePage_Finished; - Progress = 100; - ProgressText = ""; - IsActionButtonEnabled = false; - ButtonGlyph = PlayGlyph; - InstallFinished?.Invoke(this, EventArgs.Empty); - break; - case InstallGameState.Error: - StateText = Lang.DownloadGamePage_UnknownError; - ButtonGlyph = PlayGlyph; - InstallFailed?.Invoke(this, EventArgs.Empty); - break; - default: - break; + } } - long ts = Stopwatch.GetTimestamp(); - long bytes = Service.FinishBytes; - SpeedBytesPerMiniute = Math.Clamp((double)(bytes - _lastFinishedBytes) / (ts - _lastTimestamp) / Stopwatch.Frequency, 0, long.MaxValue); - _lastFinishedBytes = bytes; - _lastTimestamp = ts; + catch { } } @@ -185,6 +250,7 @@ private void _service_StateChanged(object? sender, InstallGameState e) } + private void Service_InstallFailed(object? sender, Exception e) { NotificationBehavior.Instance.Error(e, $"Game ({GameBiz.ToGameName()} - {GameBiz.ToGameServer()}) install failed.");