1
0
mirror of https://github.com/chylex/Discord-History-Tracker.git synced 2025-07-05 12:38:51 +02:00

Compare commits

..

2 Commits

Author SHA1 Message Date
Bertogim
0dc0d6b43b
Merge 7e29c7f837 into 295370a3d4 2025-04-26 13:59:20 +02:00
295370a3d4
Show progress dialog if closing database takes too long 2025-04-25 21:20:36 +02:00
3 changed files with 49 additions and 15 deletions

View File

@ -0,0 +1,24 @@
using System;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Threading;
namespace DHT.Desktop.Dialogs.Progress;
static class DelayedProgressDialog {
public static async ValueTask Await(Func<Task> taskProvider, TimeSpan delay, Window window, string progressDialogTitle, string progressDialogDescription) {
Dispatcher.UIThread.VerifyAccess();
Task task = Task.Run(taskProvider);
if (task.IsCompleted) {
return;
}
// Freeze the UI thread for a short while in case the task finishes quickly.
_ = Task.WhenAny(Task.Delay(delay), task).GetAwaiter().GetResult();
if (!task.IsCompleted) {
await ProgressDialog.ShowIndeterminate(window, progressDialogTitle, progressDialogDescription, _ => task);
}
}
}

View File

@ -2,13 +2,12 @@ using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using DHT.Utils.Logging;
namespace DHT.Desktop.Dialogs.Progress; namespace DHT.Desktop.Dialogs.Progress;
[SuppressMessage("ReSharper", "MemberCanBeInternal")] [SuppressMessage("ReSharper", "MemberCanBeInternal")]
public sealed partial class ProgressDialog : Window { public sealed partial class ProgressDialog : Window {
private static readonly Log Log = Log.ForType<ProgressDialog>(); private static readonly TimeSpan MinimumShowDuration = TimeSpan.FromMilliseconds(500);
internal static async Task Show(Window owner, string title, Func<ProgressDialog, IProgressCallback, Task> action) { internal static async Task Show(Window owner, string title, Func<ProgressDialog, IProgressCallback, Task> action) {
var dialog = new ProgressDialog(); var dialog = new ProgressDialog();
@ -43,6 +42,7 @@ public sealed partial class ProgressDialog : Window {
} }
private bool isFinished = false; private bool isFinished = false;
private DateTime startTime = DateTime.Now;
private Task progressTask = Task.CompletedTask; private Task progressTask = Task.CompletedTask;
public ProgressDialog() { public ProgressDialog() {
@ -50,6 +50,8 @@ public sealed partial class ProgressDialog : Window {
} }
public void OnOpened(object? sender, EventArgs e) { public void OnOpened(object? sender, EventArgs e) {
startTime = DateTime.Now;
if (DataContext is ProgressDialogModel model) { if (DataContext is ProgressDialogModel model) {
progressTask = Task.Run(model.StartTask); progressTask = Task.Run(model.StartTask);
progressTask.ContinueWith(OnFinished, TaskScheduler.FromCurrentSynchronizationContext()); progressTask.ContinueWith(OnFinished, TaskScheduler.FromCurrentSynchronizationContext());
@ -60,8 +62,14 @@ public sealed partial class ProgressDialog : Window {
e.Cancel = !isFinished; e.Cancel = !isFinished;
} }
private void OnFinished(Task task) { private async Task OnFinished(Task task) {
isFinished = true; isFinished = true;
TimeSpan elapsedTime = DateTime.Now - startTime;
if (elapsedTime < MinimumShowDuration) {
await Task.Delay(MinimumShowDuration - elapsedTime);
}
Close(); Close();
} }

View File

@ -4,6 +4,7 @@ using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using DHT.Desktop.Dialogs.Message; using DHT.Desktop.Dialogs.Message;
using DHT.Desktop.Dialogs.Progress;
using DHT.Desktop.Main.Screens; using DHT.Desktop.Main.Screens;
using DHT.Desktop.Server; using DHT.Desktop.Server;
using DHT.Server; using DHT.Server;
@ -104,32 +105,33 @@ sealed partial class MainWindowModel : IAsyncDisposable {
} }
private async void MainContentScreenModelOnDatabaseClosed(object? sender, EventArgs e) { private async void MainContentScreenModelOnDatabaseClosed(object? sender, EventArgs e) {
await DisposeContent();
Title = DefaultTitle;
CurrentScreen = welcomeScreen;
await DisposeState();
welcomeScreenModel.DatabaseSelected += OnDatabaseSelected;
}
private async Task DisposeContent() {
if (mainContentScreenModel != null) { if (mainContentScreenModel != null) {
mainContentScreenModel.DatabaseClosed -= MainContentScreenModelOnDatabaseClosed; mainContentScreenModel.DatabaseClosed -= MainContentScreenModelOnDatabaseClosed;
await mainContentScreenModel.DisposeAsync(); await mainContentScreenModel.DisposeAsync();
mainContentScreenModel = null; mainContentScreenModel = null;
} }
await DisposeState();
Title = DefaultTitle;
CurrentScreen = welcomeScreen;
welcomeScreenModel.DatabaseSelected += OnDatabaseSelected;
} }
private async Task DisposeState() { private async Task DisposeState() {
if (state != null) { if (state != null) {
await state.DisposeAsync(); await DelayedProgressDialog.Await(() => state.DisposeAsync().AsTask(), TimeSpan.FromMilliseconds(200), window, "Close Database", "Please wait for the database to close...");
state = null; state = null;
} }
} }
public async ValueTask DisposeAsync() { public async ValueTask DisposeAsync() {
if (mainContentScreenModel != null) { await DisposeContent();
await mainContentScreenModel.DisposeAsync();
}
await DisposeState(); await DisposeState();
} }
} }