Skip to content

Commit

Permalink
Treat About window like a dialog (#139)
Browse files Browse the repository at this point in the history
* Treat About window like a dialog

* Refactor to keep track of whether About window is being shown

Remove view model altogether in favor of using code behind for creating and
showing windows. View model doesn't seem like the right place for that,
especially if it's going to be unit tested.

This also fixes an exception that was thrown when attempting to show the
About window more than once.

* Note that it doesn't work on Windows
  • Loading branch information
tetsuo13 authored Nov 18, 2024
1 parent 09036f2 commit 4020359
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 38 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## 1.6.2 (Unreleased)

- Fixed rolled log files created with trailing sequence sometimes created on app startup ([#136](https://github.com/tetsuo13/TeamsStatusPub/issues/136))
- Prevent multiple About windows ([#129](https://github.com/tetsuo13/TeamsStatusPub/issues/129))

## 1.6.1 (2024-08-28)

Expand Down
6 changes: 2 additions & 4 deletions src/TeamsStatusPub/App.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="TeamsStatusPub.App"
xmlns:local="using:TeamsStatusPub"
xmlns:viewModels="clr-namespace:TeamsStatusPub.ViewModels"
x:DataType="viewModels:AppViewModel"
RequestedThemeVariant="Default">
<Application.DataTemplates>
<local:ViewLocator />
Expand All @@ -19,8 +17,8 @@
ToolTipText="TeamsStatusPub">
<TrayIcon.Menu>
<NativeMenu>
<NativeMenuItem Header="About" Command="{Binding AboutCommand}" />
<NativeMenuItem Header="Exit" Command="{Binding ExitCommand}" />
<NativeMenuItem Header="About" Click="AboutMenuClick" />
<NativeMenuItem Header="Exit" Click="ExitMenuClick" />
</NativeMenu>
</TrayIcon.Menu>
</TrayIcon>
Expand Down
69 changes: 66 additions & 3 deletions src/TeamsStatusPub/App.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
using System;
using System.Linq;
using System.Reactive.Concurrency;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Logging;
using Avalonia.Markup.Xaml;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ReactiveUI;
using TeamsStatusPub.ViewModels;
using TeamsStatusPub.Core.Configuration;
using TeamsStatusPub.Core.Services;
using TeamsStatusPub.Core.Services.AvailabilityHandlers;
using TeamsStatusPub.ViewModels;
using TeamsStatusPub.Views;

namespace TeamsStatusPub;

Expand All @@ -19,6 +23,8 @@ public class App : Application
public static ServiceProvider ServiceProvider { get; private set; }
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

private bool _isShowingAboutWindow;

public override void Initialize()
{
Logger.Sink = new AvaloniaSerilogSink();
Expand All @@ -29,15 +35,14 @@ public override void OnFrameworkInitializationCompleted()
{
var collection = new ServiceCollection();
collection.ConfigureAppServices();
collection.AddTransient<AppViewModel>();
collection.AddTransient<AboutViewModel>();
collection.AddTransient<AboutWindow>();

ServiceProvider = collection.BuildServiceProvider();

if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;
DataContext = ServiceProvider.GetRequiredService<AppViewModel>();
var listener = RxApp.MainThreadScheduler.Schedule(StartWebServer);

desktop.Exit += (_, _) =>
Expand All @@ -55,4 +60,62 @@ private static async void StartWebServer()
var availabilityHandler = ServiceProvider.GetRequiredService<IAvailabilityHandler>();
await httpHost.Listen(availabilityHandler.IsAvailable);
}

/// <summary>
/// Show About window as if it were a dialog. Since this is an icon tray
/// application, there isn't a main window for the standard ShowDialog()
/// method to attach to so mimic the behavior by only allowing one
/// instance of the About window to be open at a time.
/// </summary>
private void AboutMenuClick(object? sender, EventArgs e)
{
if (ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime)
{
return;
}

var logger = ServiceProvider.GetRequiredService<ILogger<App>>();

try
{
if (!_isShowingAboutWindow)
{
var view = ServiceProvider.GetRequiredService<AboutWindow>();
view.Closing += (_, _) => _isShowingAboutWindow = false;
view.Show();
_isShowingAboutWindow = true;
}
else
{
logger.LogDebug("About window should already be open, bringing it to front");

// Try to find the already-opened window.
var view = ((IClassicDesktopStyleApplicationLifetime)ApplicationLifetime).Windows
.SingleOrDefault(x => x is AboutWindow);

if (view is null)
{
logger.LogWarning("Unable to find About window");
}
else
{
// This likely won't bring the window to the front on
// Windows, but it's not too important that it does.
view.Activate();
}
}
}
catch (Exception ex)
{
logger.LogError(ex, "Error while showing About window");
}
}

private void ExitMenuClick(object? sender, EventArgs e)
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime lifetime)
{
lifetime.Shutdown();
}
}
}
2 changes: 1 addition & 1 deletion src/TeamsStatusPub/TeamsStatusPub.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
<PlatformTarget>AnyCPU</PlatformTarget>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
Expand Down
30 changes: 0 additions & 30 deletions src/TeamsStatusPub/ViewModels/AppViewModel.cs

This file was deleted.

0 comments on commit 4020359

Please sign in to comment.