Public Access
feat: add transcription pause controls
PR and Push Build/Test / build-and-test (push) Successful in 13m19s
PR and Push Build/Test / build-and-test (push) Successful in 13m19s
This commit is contained in:
@@ -11,7 +11,7 @@ public sealed class WindowsMeetingInactivityPromptService : IMeetingInactivityPr
|
||||
private const string NotificationGroup = "meeting-inactivity";
|
||||
private readonly ConcurrentDictionary<string, PendingPrompt> pendingPrompts = new(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly ILogger<WindowsMeetingInactivityPromptService> logger;
|
||||
private readonly object registrationGate = new();
|
||||
private readonly object notificationGate = new();
|
||||
private bool registered;
|
||||
|
||||
public WindowsMeetingInactivityPromptService(ILogger<WindowsMeetingInactivityPromptService> logger)
|
||||
@@ -37,24 +37,27 @@ public sealed class WindowsMeetingInactivityPromptService : IMeetingInactivityPr
|
||||
|
||||
try
|
||||
{
|
||||
EnsureRegistered();
|
||||
var promptId = Guid.NewGuid().ToString("N");
|
||||
pendingPrompts[promptId] = new PendingPrompt(handleResponseAsync);
|
||||
logger.LogInformation(
|
||||
"Registered native Windows inactivity notification {PromptId} response callback at threshold {Threshold}",
|
||||
promptId,
|
||||
request.Threshold);
|
||||
var notification = BuildNotification(promptId, request);
|
||||
notification.Show(toast =>
|
||||
lock (notificationGate)
|
||||
{
|
||||
toast.Group = NotificationGroup;
|
||||
toast.Tag = promptId;
|
||||
toast.ExpirationTime = MeetingToastExpirationPolicy.StopReminderExpiration(DateTimeOffset.Now);
|
||||
});
|
||||
logger.LogInformation(
|
||||
"Displayed native Windows inactivity notification {PromptId} at threshold {Threshold}",
|
||||
promptId,
|
||||
request.Threshold);
|
||||
EnsureRegistered();
|
||||
var promptId = Guid.NewGuid().ToString("N");
|
||||
pendingPrompts[promptId] = new PendingPrompt(handleResponseAsync);
|
||||
logger.LogInformation(
|
||||
"Registered native Windows inactivity notification {PromptId} response callback at threshold {Threshold}",
|
||||
promptId,
|
||||
request.Threshold);
|
||||
var notification = BuildNotification(promptId, request);
|
||||
notification.Show(toast =>
|
||||
{
|
||||
toast.Group = NotificationGroup;
|
||||
toast.Tag = promptId;
|
||||
toast.ExpirationTime = MeetingToastExpirationPolicy.StopReminderExpiration(DateTimeOffset.Now);
|
||||
});
|
||||
logger.LogInformation(
|
||||
"Displayed native Windows inactivity notification {PromptId} at threshold {Threshold}",
|
||||
promptId,
|
||||
request.Threshold);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@@ -76,6 +79,36 @@ public sealed class WindowsMeetingInactivityPromptService : IMeetingInactivityPr
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task DismissAllAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
lock (notificationGate)
|
||||
{
|
||||
if (pendingPrompts.IsEmpty)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
pendingPrompts.Clear();
|
||||
if (!OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17763))
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ToastNotificationManagerCompat.History.RemoveGroup(NotificationGroup);
|
||||
logger.LogInformation("Dismissed all native Windows inactivity notifications");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogWarning(exception, "Failed to dismiss native Windows inactivity notifications");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
@@ -83,29 +116,28 @@ public sealed class WindowsMeetingInactivityPromptService : IMeetingInactivityPr
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!registered)
|
||||
lock (notificationGate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!registered)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ToastNotificationManagerCompat.OnActivated -= OnNotificationInvoked;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogWarning(exception, "Failed to detach native Windows toast notification activation handler");
|
||||
try
|
||||
{
|
||||
ToastNotificationManagerCompat.OnActivated -= OnNotificationInvoked;
|
||||
registered = false;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogWarning(exception, "Failed to detach native Windows toast notification activation handler");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureRegistered()
|
||||
{
|
||||
if (registered)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (registrationGate)
|
||||
lock (notificationGate)
|
||||
{
|
||||
if (registered)
|
||||
{
|
||||
@@ -122,29 +154,25 @@ public sealed class WindowsMeetingInactivityPromptService : IMeetingInactivityPr
|
||||
string promptId,
|
||||
MeetingInactivityPromptRequest request)
|
||||
{
|
||||
var yesButton = new ToastButton()
|
||||
.SetContent("Yes")
|
||||
.AddArgument("source", NotificationSource)
|
||||
.AddArgument("promptId", promptId)
|
||||
.AddArgument("response", "stop")
|
||||
.SetBackgroundActivation();
|
||||
|
||||
var noButton = new ToastButton()
|
||||
.SetContent("No")
|
||||
.AddArgument("source", NotificationSource)
|
||||
.AddArgument("promptId", promptId)
|
||||
.AddArgument("response", "continue")
|
||||
.SetBackgroundActivation();
|
||||
|
||||
return new ToastContentBuilder()
|
||||
var builder = new ToastContentBuilder()
|
||||
.AddArgument("source", NotificationSource)
|
||||
.AddArgument("promptId", promptId)
|
||||
.SetToastScenario(ToastScenario.Reminder)
|
||||
.SetToastDuration(ToastDuration.Long)
|
||||
.AddText("Stop meeting?")
|
||||
.AddText($"No transcript text has arrived for {FormatDuration(request.InactivityDuration)}.")
|
||||
.AddButton(yesButton)
|
||||
.AddButton(noButton);
|
||||
.AddText($"No transcript text has arrived for {FormatDuration(request.InactivityDuration)}.");
|
||||
|
||||
foreach (var action in MeetingInactivityPromptActions.All)
|
||||
{
|
||||
builder.AddButton(new ToastButton()
|
||||
.SetContent(action.Content)
|
||||
.AddArgument("source", NotificationSource)
|
||||
.AddArgument("promptId", promptId)
|
||||
.AddArgument("response", action.ResponseArgument)
|
||||
.SetBackgroundActivation());
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private void OnNotificationInvoked(ToastNotificationActivatedEventArgsCompat args)
|
||||
@@ -177,10 +205,9 @@ public sealed class WindowsMeetingInactivityPromptService : IMeetingInactivityPr
|
||||
return;
|
||||
}
|
||||
|
||||
var response = TryGetArgument(arguments, "response", out var responseValue) &&
|
||||
string.Equals(responseValue, "stop", StringComparison.OrdinalIgnoreCase)
|
||||
? MeetingInactivityPromptResponse.Stop
|
||||
: MeetingInactivityPromptResponse.Continue;
|
||||
var response = TryGetArgument(arguments, "response", out var responseValue)
|
||||
? MeetingInactivityPromptActions.ParseResponse(responseValue)
|
||||
: MeetingInactivityPromptResponse.Continue;
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
|
||||
Reference in New Issue
Block a user