Merge nucleic/warm-north-vole-pf37 into dev
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json;
|
||||
using NucleicApp.Services;
|
||||
using NucleicProtocol.Interop;
|
||||
|
||||
namespace NucleicApp.ViewModels;
|
||||
|
||||
/// Presentation and intent surface for one session detail screen. Transcript rows remain owned
|
||||
/// by the shared Swift projector; this model forwards only that session's splice diffs.
|
||||
public sealed class SessionDetailViewModel : ViewModelBase, IDisposable
|
||||
{
|
||||
private readonly RendererStore store;
|
||||
private readonly HostConnection connection;
|
||||
private ProjectionDiff? lastProjection;
|
||||
private bool active;
|
||||
private bool disposed;
|
||||
|
||||
public SessionDetailViewModel(
|
||||
string sessionId, RendererStore store, HostConnection connection)
|
||||
{
|
||||
SessionId = sessionId;
|
||||
this.store = store;
|
||||
this.connection = connection;
|
||||
store.PropertyChanged += StoreChanged;
|
||||
store.ProjectionChanged += ProjectionChanged;
|
||||
}
|
||||
|
||||
public string SessionId { get; }
|
||||
public SessionSummary? Session => store.Sessions.FirstOrDefault(item => item.Id == SessionId);
|
||||
public IReadOnlyList<ApprovalRequest> PendingApprovals => store.PendingApprovals
|
||||
.Where(item => item.SessionId == SessionId).ToArray();
|
||||
public ProjectionDiff? LastProjection
|
||||
{
|
||||
get => lastProjection;
|
||||
private set => Set(ref lastProjection, value);
|
||||
}
|
||||
|
||||
public ProtocolResult Activate(ulong? sinceSequence = null)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(disposed, this);
|
||||
if (active) return ProtocolResult.Ok;
|
||||
var result = connection.SendIntent(ClientIntents.Subscribe(SessionId, sinceSequence));
|
||||
if (result == ProtocolResult.Ok) active = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
public ProtocolResult SendText(string text)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(disposed, this);
|
||||
if (string.IsNullOrWhiteSpace(text)) return ProtocolResult.InvalidArgument;
|
||||
return connection.SendIntent(ClientIntents.SendInput(SessionId, text));
|
||||
}
|
||||
|
||||
public ProtocolResult Allow(ApprovalRequest approval, JsonElement? updatedInput = null) =>
|
||||
Respond(approval, ClientIntents.ApprovalAllow(approval.Id, updatedInput));
|
||||
|
||||
public ProtocolResult Deny(ApprovalRequest approval, string? reason = null) =>
|
||||
Respond(approval, ClientIntents.ApprovalDeny(approval.Id, reason));
|
||||
|
||||
public ProtocolResult AllowAlways(ApprovalRequest approval, ApprovalAlwaysScope scope) =>
|
||||
Respond(approval, ClientIntents.ApprovalAllowAlways(approval.Id, scope));
|
||||
|
||||
public ProtocolResult CancelRun(ApprovalRequest approval) =>
|
||||
Respond(approval, ClientIntents.ApprovalCancelRun(approval.Id));
|
||||
|
||||
private ProtocolResult Respond(ApprovalRequest approval, string intent)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(disposed, this);
|
||||
if (approval.SessionId != SessionId) return ProtocolResult.InvalidArgument;
|
||||
return connection.SendIntent(intent);
|
||||
}
|
||||
|
||||
private void StoreChanged(object? sender, PropertyChangedEventArgs args)
|
||||
{
|
||||
if (args.PropertyName == nameof(RendererStore.Sessions)) Raise(nameof(Session));
|
||||
else if (args.PropertyName == nameof(RendererStore.PendingApprovals))
|
||||
Raise(nameof(PendingApprovals));
|
||||
}
|
||||
|
||||
private void ProjectionChanged(ProjectionDiff diff)
|
||||
{
|
||||
if (diff.Root.TryGetProperty("sessionID", out var session) &&
|
||||
session.ValueKind == JsonValueKind.String && session.GetString() == SessionId)
|
||||
{
|
||||
LastProjection = diff;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
store.PropertyChanged -= StoreChanged;
|
||||
store.ProjectionChanged -= ProjectionChanged;
|
||||
if (active) _ = connection.SendIntent(ClientIntents.Unsubscribe(SessionId));
|
||||
active = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user