Problem
Currently, each project (PushToTalk, VirtualAssistant) needs to create its own wrapper service around TrayIconManager:
- PushToTalkTrayService - handles main icon, animated icon, menu events
- VirtualAssistantTrayService - handles single icon with mute state, different menu
While each project has unique requirements (different events, state, menu structure), there's common boilerplate code for:
- Icon creation and rendering
- Basic lifecycle management
- Common patterns for menu building
Proposed Solution
Create an abstract ConfigurableTrayService base class in the NuGet package that provides:
public abstract class ConfigurableTrayService : IDisposable
{
protected readonly TrayIconManager _manager;
protected readonly ILogger _logger;
protected ITrayIcon? _mainIcon;
protected ConfigurableTrayService(ILogger logger, TrayIconManager manager)
{
_logger = logger;
_manager = manager;
}
// Shared logic
protected void CreateIcon(string iconPath, string tooltip, string id)
{
// Common icon creation logic
}
// Project-specific overrides
protected abstract void BuildMenu(ITrayIcon icon);
protected abstract void OnIconClicked();
public abstract void Dispose();
}
Then projects only need to implement their specific logic:
public class PushToTalkTrayService : ConfigurableTrayService
{
public event Action? OnQuitRequested;
protected override void BuildMenu(ITrayIcon icon)
{
// PushToTalk-specific menu items
}
protected override void OnIconClicked()
{
// PushToTalk-specific click behavior
}
}
Benefits
- Less boilerplate: Common icon creation/rendering logic in base class
- Flexibility: Each project can still customize events, state, menu structure
- Maintainability: Bug fixes in common logic benefit all projects
- Testability: Base class logic can be tested once
Alternatives Considered
Fully generic wrapper with configuration: Too complex - would need dozens of parameters/callbacks for different events, menu structures, state management. Current approach (base class with abstract methods) provides better balance.
Implementation Tasks
Problem
Currently, each project (PushToTalk, VirtualAssistant) needs to create its own wrapper service around
TrayIconManager:While each project has unique requirements (different events, state, menu structure), there's common boilerplate code for:
Proposed Solution
Create an abstract
ConfigurableTrayServicebase class in the NuGet package that provides:Then projects only need to implement their specific logic:
Benefits
Alternatives Considered
Fully generic wrapper with configuration: Too complex - would need dozens of parameters/callbacks for different events, menu structures, state management. Current approach (base class with abstract methods) provides better balance.
Implementation Tasks
ConfigurableTrayServicein SystemTray.Linux