Public Access
Archive completed meeting assistant changes
PR and Push Build/Test / build-and-test (push) Successful in 9m19s
PR and Push Build/Test / build-and-test (push) Successful in 9m19s
This commit is contained in:
@@ -6,10 +6,12 @@ namespace MeetingAssistant.Taskbar;
|
||||
public enum MeetingTaskbarAction
|
||||
{
|
||||
EditRules,
|
||||
OpenSubmenu,
|
||||
StartRecording,
|
||||
StopRecording,
|
||||
AbortRecording,
|
||||
SwitchProfile,
|
||||
SelectMicrophone,
|
||||
Exit
|
||||
}
|
||||
|
||||
@@ -21,19 +23,29 @@ public sealed record MeetingTaskbarMenu(
|
||||
public sealed record MeetingTaskbarMenuItem(
|
||||
string Text,
|
||||
MeetingTaskbarAction Action,
|
||||
string? ProfileName = null);
|
||||
string? ProfileName = null,
|
||||
string? MicrophoneDeviceId = null,
|
||||
bool IsChecked = false,
|
||||
IReadOnlyList<MeetingTaskbarMenuItem>? Items = null);
|
||||
|
||||
public static class MeetingTaskbarMenuBuilder
|
||||
{
|
||||
public static MeetingTaskbarMenu Build(
|
||||
RecordingStatus status,
|
||||
IReadOnlyList<LaunchProfile> launchProfiles)
|
||||
IReadOnlyList<LaunchProfile> launchProfiles,
|
||||
IReadOnlyList<MicrophoneDevice>? microphones = null,
|
||||
string? currentMicrophoneDeviceId = null)
|
||||
{
|
||||
var items = new List<MeetingTaskbarMenuItem>
|
||||
{
|
||||
new("Settings and logs", MeetingTaskbarAction.EditRules)
|
||||
};
|
||||
|
||||
if (microphones is { Count: > 0 })
|
||||
{
|
||||
items.Add(BuildMicrophoneMenu(microphones, currentMicrophoneDeviceId));
|
||||
}
|
||||
|
||||
if (status.IsRecording)
|
||||
{
|
||||
items.Add(new MeetingTaskbarMenuItem(
|
||||
@@ -72,6 +84,24 @@ public static class MeetingTaskbarMenuBuilder
|
||||
items);
|
||||
}
|
||||
|
||||
private static MeetingTaskbarMenuItem BuildMicrophoneMenu(
|
||||
IReadOnlyList<MicrophoneDevice> 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
|
||||
@@ -104,8 +134,8 @@ public static class MeetingTaskbarMenuBuilder
|
||||
|
||||
public static class MeetingTaskbarExitPolicy
|
||||
{
|
||||
public static bool RequiresConfirmation(RecordingStatus status)
|
||||
public static bool RequiresConfirmation(RecordingProcessState state)
|
||||
{
|
||||
return status.State != RecordingProcessState.Idle;
|
||||
return state != RecordingProcessState.Idle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ public sealed class UnoTaskbarIconService : IHostedService, IDisposable
|
||||
|
||||
private readonly MeetingRecordingCoordinator coordinator;
|
||||
private readonly ILaunchProfileOptionsProvider launchProfiles;
|
||||
private readonly IMicrophoneDeviceProvider microphones;
|
||||
private readonly MicrophoneDeviceSelection microphoneSelection;
|
||||
private readonly IWorkflowRulesEditorWindowService rulesEditorWindow;
|
||||
private readonly IHostApplicationLifetime applicationLifetime;
|
||||
private readonly ILogger<UnoTaskbarIconService> logger;
|
||||
@@ -29,12 +31,16 @@ public sealed class UnoTaskbarIconService : IHostedService, IDisposable
|
||||
public UnoTaskbarIconService(
|
||||
MeetingRecordingCoordinator coordinator,
|
||||
ILaunchProfileOptionsProvider launchProfiles,
|
||||
IMicrophoneDeviceProvider microphones,
|
||||
MicrophoneDeviceSelection microphoneSelection,
|
||||
IWorkflowRulesEditorWindowService rulesEditorWindow,
|
||||
IHostApplicationLifetime applicationLifetime,
|
||||
ILogger<UnoTaskbarIconService> logger)
|
||||
{
|
||||
this.coordinator = coordinator;
|
||||
this.launchProfiles = launchProfiles;
|
||||
this.microphones = microphones;
|
||||
this.microphoneSelection = microphoneSelection;
|
||||
this.rulesEditorWindow = rulesEditorWindow;
|
||||
this.applicationLifetime = applicationLifetime;
|
||||
this.logger = logger;
|
||||
@@ -167,6 +173,8 @@ public sealed class UnoTaskbarIconService : IHostedService, IDisposable
|
||||
private MeetingTaskbarMenu BuildMenu()
|
||||
{
|
||||
var profiles = launchProfiles.GetProfiles();
|
||||
var activeOptions = GetActiveProfileOptions(profiles);
|
||||
var microphoneSnapshot = microphones.GetMicrophoneSnapshot(activeOptions);
|
||||
var profilesSignature = string.Join(
|
||||
", ",
|
||||
profiles.Select(profile => $"{profile.Name}:{profile.Options.Hotkey.Toggle}"));
|
||||
@@ -178,7 +186,9 @@ public sealed class UnoTaskbarIconService : IHostedService, IDisposable
|
||||
|
||||
return MeetingTaskbarMenuBuilder.Build(
|
||||
coordinator.CurrentStatus,
|
||||
profiles);
|
||||
profiles,
|
||||
microphoneSnapshot.Available,
|
||||
microphoneSnapshot.Current?.Id);
|
||||
}
|
||||
|
||||
private PopupMenu BuildContextMenu(MeetingTaskbarMenu menu)
|
||||
@@ -194,14 +204,33 @@ public sealed class UnoTaskbarIconService : IHostedService, IDisposable
|
||||
}
|
||||
|
||||
var menuItem = menu.Items[index];
|
||||
popupMenu.Items.Add(new PopupMenuItem(
|
||||
menuItem.Text,
|
||||
(_, _) => _ = ExecuteMenuItemAsync(menuItem)));
|
||||
popupMenu.Items.Add(BuildPopupItem(menuItem));
|
||||
}
|
||||
|
||||
return popupMenu;
|
||||
}
|
||||
|
||||
private PopupItem BuildPopupItem(MeetingTaskbarMenuItem menuItem)
|
||||
{
|
||||
if (menuItem.Items is { Count: > 0 })
|
||||
{
|
||||
var submenu = new PopupSubMenu(menuItem.Text);
|
||||
foreach (var child in menuItem.Items)
|
||||
{
|
||||
submenu.Items.Add(BuildPopupItem(child));
|
||||
}
|
||||
|
||||
return submenu;
|
||||
}
|
||||
|
||||
return new PopupMenuItem(
|
||||
menuItem.Text,
|
||||
(_, _) => _ = ExecuteMenuItemAsync(menuItem))
|
||||
{
|
||||
Checked = menuItem.IsChecked
|
||||
};
|
||||
}
|
||||
|
||||
private async Task ExecuteMenuItemAsync(MeetingTaskbarMenuItem item)
|
||||
{
|
||||
try
|
||||
@@ -227,6 +256,13 @@ public sealed class UnoTaskbarIconService : IHostedService, IDisposable
|
||||
break;
|
||||
case MeetingTaskbarAction.SwitchProfile:
|
||||
await coordinator.ToggleAsync(item.ProfileName, CancellationToken.None);
|
||||
break;
|
||||
case MeetingTaskbarAction.SelectMicrophone:
|
||||
if (!string.IsNullOrWhiteSpace(item.MicrophoneDeviceId))
|
||||
{
|
||||
microphoneSelection.Select(item.MicrophoneDeviceId);
|
||||
}
|
||||
|
||||
break;
|
||||
case MeetingTaskbarAction.Exit:
|
||||
ExitApplication();
|
||||
@@ -253,13 +289,47 @@ public sealed class UnoTaskbarIconService : IHostedService, IDisposable
|
||||
{
|
||||
return string.Join(
|
||||
"|",
|
||||
menu.Items.Select(item => $"{item.Action}:{item.ProfileName}:{item.Text}"));
|
||||
FlattenMenuItems(menu.Items).Select(item =>
|
||||
$"{item.Action}:{item.ProfileName}:{item.MicrophoneDeviceId}:{item.IsChecked}:{item.Text}"));
|
||||
}
|
||||
|
||||
private static IEnumerable<MeetingTaskbarMenuItem> FlattenMenuItems(
|
||||
IEnumerable<MeetingTaskbarMenuItem> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
yield return item;
|
||||
if (item.Items is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var child in FlattenMenuItems(item.Items))
|
||||
{
|
||||
yield return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MeetingAssistantOptions GetActiveProfileOptions(IReadOnlyList<LaunchProfile> profiles)
|
||||
{
|
||||
var activeProfile = coordinator.CurrentStatus.LaunchProfile;
|
||||
return profiles.FirstOrDefault(profile => string.Equals(
|
||||
profile.Name,
|
||||
activeProfile,
|
||||
StringComparison.OrdinalIgnoreCase))?.Options ??
|
||||
profiles.FirstOrDefault(profile => string.Equals(
|
||||
profile.Name,
|
||||
"default",
|
||||
StringComparison.OrdinalIgnoreCase))?.Options ??
|
||||
profiles.FirstOrDefault()?.Options ??
|
||||
new MeetingAssistantOptions();
|
||||
}
|
||||
|
||||
private void ExitApplication()
|
||||
{
|
||||
var status = coordinator.CurrentStatus;
|
||||
if (MeetingTaskbarExitPolicy.RequiresConfirmation(status) && !ConfirmExitDuringProcessing(status.State))
|
||||
if (MeetingTaskbarExitPolicy.RequiresConfirmation(status.State) && !ConfirmExitDuringProcessing(status.State))
|
||||
{
|
||||
logger.LogInformation("Taskbar exit canceled while meeting state was {State}", status.State);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user