feat(macos): add native desktop controls and hotkey integration

- Introduced MacOsDesktopControlManifest to manage desktop control configurations.
- Implemented MacOsDesktopControlService to handle the lifecycle of the macOS helper process.
- Created MacOsWorkflowRulesEditorWindowService for managing workflow rules through a native window.
- Developed a Swift helper for macOS that integrates with AppKit and Carbon for menu-bar controls and global hotkeys.
- Added support for recording lifecycle actions via HTTP endpoints, maintaining consistency with existing Windows functionality.
- Enhanced user experience by allowing macOS users to start/stop recordings and access settings through a menu-bar interface.
- Documented design decisions, implementation evidence, and verification tasks for the new macOS features.
This commit is contained in:
dh
2026-08-06 08:18:52 +02:00
parent 5f39923c27
commit 9542c05ea4
20 changed files with 981 additions and 11 deletions
@@ -0,0 +1,47 @@
using MeetingAssistant.LaunchProfiles;
namespace MeetingAssistant.MacOs;
public sealed record MacOsDesktopControlManifest(
string BaseUrl,
string StatusUrl,
string OpenAgentUrl,
IReadOnlyList<MacOsDesktopProfile> Profiles,
IReadOnlyList<MacOsDesktopHotkey> Hotkeys)
{
public static MacOsDesktopControlManifest Create(
string baseUrl,
IReadOnlyList<LaunchProfile> profiles,
IReadOnlyList<LaunchProfileHotkey> hotkeys)
{
var normalizedBaseUrl = baseUrl.TrimEnd('/');
return new MacOsDesktopControlManifest(
normalizedBaseUrl,
$"{normalizedBaseUrl}/recording/status",
$"{normalizedBaseUrl}/diagnostics/settings-and-logs",
profiles
.Select(profile => new MacOsDesktopProfile(
profile.Name,
profile.Options.Hotkey.Toggle))
.ToArray(),
hotkeys.Select(CreateHotkey).ToArray());
}
private static MacOsDesktopHotkey CreateHotkey(LaunchProfileHotkey hotkey)
{
var endpoint = hotkey.Action switch
{
LaunchProfileHotkeyAction.ToggleRecording => "recording/toggle",
LaunchProfileHotkeyAction.AbortRecording => "recording/abort",
LaunchProfileHotkeyAction.CaptureScreenshot => "meetings/screenshot/capture",
_ => throw new ArgumentOutOfRangeException(nameof(hotkey))
};
return new MacOsDesktopHotkey(
hotkey.Hotkey,
$"/profiles/{Uri.EscapeDataString(hotkey.ProfileName)}/{endpoint}");
}
}
public sealed record MacOsDesktopProfile(string Name, string ToggleShortcut);
public sealed record MacOsDesktopHotkey(string Shortcut, string Endpoint);