using WirelessTextSyncer.Windows.Services; namespace WirelessTextSyncer.Windows.Tray; public sealed class TrayApplicationContext : ApplicationContext { private readonly WebSocketServerService server; private readonly NotifyIcon notifyIcon; public TrayApplicationContext() { AppLogger.Info("Tray application starting."); var keyboard = new KeyboardInjectionService(); var handler = new SyncMessageHandler(keyboard); server = new WebSocketServerService(handler); server.StatusChanged += (_, _) => UpdateTrayText(); notifyIcon = new NotifyIcon { Icon = SystemIcons.Application, Text = "WirelessTextSyncer starting...", Visible = true, ContextMenuStrip = BuildMenu() }; notifyIcon.MouseClick += OnTrayIconClicked; try { server.Start(8181); UpdateTrayText(); } catch (Exception ex) { AppLogger.Error("Failed to start tray application.", ex); notifyIcon.BalloonTipTitle = "WirelessTextSyncer"; notifyIcon.BalloonTipText = $"Failed to start: {ex.Message}"; notifyIcon.ShowBalloonTip(5000); } } protected override void Dispose(bool disposing) { if (disposing) { notifyIcon.Dispose(); server.Dispose(); } base.Dispose(disposing); } private ContextMenuStrip BuildMenu() { var menu = new ContextMenuStrip(); menu.Items.Add("Copy connection address", null, (_, _) => CopyConnectionAddress()); menu.Items.Add("Exit", null, (_, _) => ExitThread()); return menu; } private void OnTrayIconClicked(object? sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { CopyConnectionAddress(); } } private void CopyConnectionAddress() { Clipboard.SetText($"ws://{server.LocalIpAddress}:{server.Port}"); notifyIcon.BalloonTipTitle = "WirelessTextSyncer"; notifyIcon.BalloonTipText = "Connection address copied."; notifyIcon.ShowBalloonTip(1500); } private void UpdateTrayText() { var status = server.HasClient ? "connected" : "waiting"; var text = $"WirelessTextSyncer {server.LocalIpAddress}:{server.Port} ({status})"; notifyIcon.Text = text.Length > 63 ? text[..63] : text; } }