diff --git a/demos/WPF/App.xaml b/demos/WPF/App.xaml index bc72abf..cbaaee4 100644 --- a/demos/WPF/App.xaml +++ b/demos/WPF/App.xaml @@ -1,7 +1,8 @@  + xmlns:converters="clr-namespace:PowersyncDotnetTodoList.Converters" + DispatcherUnhandledException="Application_DispatcherUnhandledException"> diff --git a/demos/WPF/App.xaml.cs b/demos/WPF/App.xaml.cs index 0479cf1..629d3a7 100644 --- a/demos/WPF/App.xaml.cs +++ b/demos/WPF/App.xaml.cs @@ -14,28 +14,41 @@ public partial class App : Application { public static IServiceProvider? Services { get; private set; } - protected override async void OnStartup(StartupEventArgs e) + protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); + // Handle async initialization synchronously or with proper error handling + try + { + InitializeApplicationAsync().GetAwaiter().GetResult(); + } + catch (Exception ex) + { + MessageBox.Show( + $"Application startup failed: {ex.Message}\n\nFull error: {ex}", + "Startup Error", + MessageBoxButton.OK, + MessageBoxImage.Error + ); + + // Shut down the application + Current.Shutdown(1); + return; + } + } + + private async Task InitializeApplicationAsync() + { var services = new ServiceCollection(); ConfigureServices(services); // Build the service provider Services = services.BuildServiceProvider(); - - // Initialize the database and connector - var db = Services.GetRequiredService(); - var connector = Services.GetRequiredService(); - await db.Init(); - await db.Connect(connector); - await db.WaitForFirstSync(); - var mainWindow = Services.GetRequiredService(); - var navigationService = Services.GetRequiredService(); - navigationService.Navigate(); + navigationService.Navigate(); mainWindow.Show(); } @@ -67,7 +80,10 @@ private void ConfigureServices(IServiceCollection services) ); // Register PowerSyncConnector - services.AddSingleton(); + services.AddSingleton(sp => + { + return new PowerSyncConnector(); + }); // Register ViewModels and Views services.AddTransient(); @@ -86,5 +102,21 @@ private void ConfigureServices(IServiceCollection services) return new NavigationService(mainWindow.MainFrame, sp); }); } + + // Add global exception handler + private void Application_DispatcherUnhandledException( + object sender, + System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e + ) + { + MessageBox.Show( + $"An unhandled exception occurred: {e.Exception.Message}\n\nFull error: {e.Exception}", + "Unhandled Exception", + MessageBoxButton.OK, + MessageBoxImage.Error + ); + + e.Handled = true; // Prevent application crash + } } } diff --git a/demos/WPF/MainWindow.xaml.cs b/demos/WPF/MainWindow.xaml.cs index 26047c2..8509953 100644 --- a/demos/WPF/MainWindow.xaml.cs +++ b/demos/WPF/MainWindow.xaml.cs @@ -1,14 +1,48 @@ -using System.Windows; +using PowerSync.Common.Client; +using PowersyncDotnetTodoList.Services; using PowersyncDotnetTodoList.ViewModels; namespace PowersyncDotnetTodoList; public partial class MainWindow : Window { - public MainWindow(MainWindowViewModel viewModel) + private readonly MainWindowViewModel _viewModel; + private readonly PowerSyncConnector _connector; + private readonly PowerSyncDatabase _db; + + public MainWindow( + MainWindowViewModel viewModel, + PowerSyncConnector connector, + PowerSyncDatabase db + ) { InitializeComponent(); - this.DataContext = viewModel; + _viewModel = viewModel; + _connector = connector; + _db = db; + + this.DataContext = _viewModel; + + // Start the async initialization + InitializeAsync(); + } + + private async void InitializeAsync() + { + try + { + await _db.Init(); + await _db.Connect(_connector); + } + catch (Exception ex) + { + MessageBox.Show( + $"Failed to initialize database: {ex.Message}", + "Error", + MessageBoxButton.OK, + MessageBoxImage.Error + ); + } } } diff --git a/demos/WPF/Properties/PublishProfiles/FolderProfile.pubxml b/demos/WPF/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..a31548a --- /dev/null +++ b/demos/WPF/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,16 @@ + + + + + Release + Any CPU + bin\Release\net9.0-windows\publish\win-x64\ + FileSystem + <_TargetId>Folder + net9.0-windows + win-x64 + true + false + false + + \ No newline at end of file diff --git a/demos/WPF/ViewModels/MainWindowViewModel.cs b/demos/WPF/ViewModels/MainWindowViewModel.cs index 7b596d4..368ee16 100644 --- a/demos/WPF/ViewModels/MainWindowViewModel.cs +++ b/demos/WPF/ViewModels/MainWindowViewModel.cs @@ -29,17 +29,35 @@ public bool Connected #region Constructor public MainWindowViewModel(PowerSyncDatabase db) { - _db = db; - // Set up the listener to track the status changes - _db.RunListener( - (update) => + try + { + + if (db == null) { - if (update.StatusChanged != null) + Console.WriteLine("ERROR: PowerSyncDatabase is null!"); + throw new ArgumentNullException(nameof(db)); + } + + _db = db; + Console.WriteLine("PowerSyncDatabase assigned successfully"); + _db.RunListener( + (update) => { - Connected = update.StatusChanged.Connected; + Console.WriteLine( + $"Listener callback triggered: StatusChanged = {update.StatusChanged?.Connected}" + ); + if (update.StatusChanged != null) + { + Connected = update.StatusChanged.Connected; + } } - } - ); + ); + } + catch (Exception ex) + { + Console.WriteLine($"ERROR in MainWindowViewModel constructor: {ex}"); + throw; + } } #endregion } diff --git a/demos/WPF/WPF.csproj b/demos/WPF/WPF.csproj index 89e7de2..019b0cb 100644 --- a/demos/WPF/WPF.csproj +++ b/demos/WPF/WPF.csproj @@ -19,4 +19,10 @@ + + + + Always + +