using MeetingAssistant.LaunchProfiles; using MeetingAssistant.Recording; namespace MeetingAssistant.Taskbar; public enum MeetingTaskbarAction { EditRules, OpenSubmenu, StartRecording, StopRecording, AbortRecording, SwitchProfile, SelectMicrophone, Exit } public sealed record MeetingTaskbarMenu( RecordingProcessState State, string Tooltip, IReadOnlyList Items); public sealed record MeetingTaskbarMenuItem( string Text, MeetingTaskbarAction Action, string? ProfileName = null, string? MicrophoneDeviceId = null, bool IsChecked = false, IReadOnlyList? Items = null); public static class MeetingTaskbarMenuBuilder { public static MeetingTaskbarMenu Build( RecordingStatus status, IReadOnlyList launchProfiles, IReadOnlyList? microphones = null, string? currentMicrophoneDeviceId = null) { var items = new List { new("Open agent", MeetingTaskbarAction.EditRules) }; if (microphones is { Count: > 0 }) { items.Add(BuildMicrophoneMenu(microphones, currentMicrophoneDeviceId)); } if (status.IsRecording) { items.Add(new MeetingTaskbarMenuItem( "Stop meeting recording and transcribe", MeetingTaskbarAction.StopRecording)); items.Add(new MeetingTaskbarMenuItem( "Cancel meeting recording and discard", MeetingTaskbarAction.AbortRecording)); foreach (var profile in launchProfiles.Where(profile => !IsActiveProfile(profile, status))) { items.Add(new MeetingTaskbarMenuItem( AppendHotkey($"Switch to {profile.Name}", profile.Options.Hotkey.Toggle), MeetingTaskbarAction.SwitchProfile, profile.Name)); } } else { foreach (var profile in launchProfiles) { items.Add(new MeetingTaskbarMenuItem( AppendHotkey($"Start meeting recording ({profile.Name})", profile.Options.Hotkey.Toggle), MeetingTaskbarAction.StartRecording, profile.Name)); } } items.Add(new MeetingTaskbarMenuItem( "Exit", MeetingTaskbarAction.Exit)); return new MeetingTaskbarMenu( status.State, BuildTooltip(status), items); } private static MeetingTaskbarMenuItem BuildMicrophoneMenu( IReadOnlyList microphones, string? currentMicrophoneDeviceId) { var microphoneItems = microphones .Select(microphone => new MeetingTaskbarMenuItem( microphone.Name, MeetingTaskbarAction.SelectMicrophone, MicrophoneDeviceId: microphone.Id, IsChecked: string.Equals(microphone.Id, currentMicrophoneDeviceId, StringComparison.Ordinal))) .ToArray(); return new MeetingTaskbarMenuItem( "Microphone", MeetingTaskbarAction.OpenSubmenu, Items: microphoneItems); } private static string BuildTooltip(RecordingStatus status) { return status.State switch { RecordingProcessState.Recording => string.IsNullOrWhiteSpace(status.LaunchProfile) ? "Meeting Assistant - recording" : $"Meeting Assistant - recording ({status.LaunchProfile})", RecordingProcessState.Summarizing => "Meeting Assistant - summarizing", _ => "Meeting Assistant - idle" }; } private static bool IsActiveProfile( LaunchProfile profile, RecordingStatus status) { return string.Equals( profile.Name, status.LaunchProfile, StringComparison.OrdinalIgnoreCase); } private static string AppendHotkey(string text, string hotkey) { return string.IsNullOrWhiteSpace(hotkey) ? text : $"{text}\t{hotkey.Trim()}"; } } public static class MeetingTaskbarExitPolicy { public static bool RequiresConfirmation(RecordingProcessState state) { return state != RecordingProcessState.Idle; } }