mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-09-13 03:10:37 +00:00
Fixed build progress title
This commit is contained in:
parent
d1ab57cb60
commit
d3e53fe5fe
@ -57,7 +57,11 @@ public partial class VisualBriefingAssistant
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the localized collapsed build-progress summary.
|
/// Gets the localized collapsed build-progress summary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private string BuildProgressTitle => this.latestBuild?.Status switch
|
private string BuildProgressTitle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var title = this.latestBuild?.Status switch
|
||||||
{
|
{
|
||||||
VisualBriefingBuildStatus.COMPLETED => $"{T("Build progress")} · {T("Completed")}",
|
VisualBriefingBuildStatus.COMPLETED => $"{T("Build progress")} · {T("Completed")}",
|
||||||
VisualBriefingBuildStatus.FAILED => $"{T("Build progress")} · {T("Failed")}",
|
VisualBriefingBuildStatus.FAILED => $"{T("Build progress")} · {T("Failed")}",
|
||||||
@ -67,6 +71,11 @@ public partial class VisualBriefingAssistant
|
|||||||
_ => $"{T("Build progress")} · {T("Running")}",
|
_ => $"{T("Build progress")} · {T("Running")}",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var duration = this.CalculateBuildDuration(this.latestBuild?.Stages ?? []);
|
||||||
|
return duration > TimeSpan.Zero ? $"{title} · {FormatBuildDuration(duration)}" : title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Keeps the status stepper informational while allowing actions inside the active step.
|
/// Keeps the status stepper informational while allowing actions inside the active step.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -307,12 +316,42 @@ public partial class VisualBriefingAssistant
|
|||||||
/// Applies a content-free live progress update for the selected project.
|
/// Applies a content-free live progress update for the selected project.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void BuildProgressChanged(Guid briefingId)
|
private void BuildProgressChanged(Guid briefingId)
|
||||||
|
{
|
||||||
|
if (this.selectedBriefing?.BriefingId != briefingId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_ = this.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
if (this.selectedBriefing?.BriefingId != briefingId)
|
if (this.selectedBriefing?.BriefingId != briefingId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.latestBuild = this.BuildProgressService.GetLatest(briefingId);
|
this.latestBuild = this.BuildProgressService.GetLatest(briefingId);
|
||||||
_ = this.InvokeAsync(this.StateHasChanged);
|
this.buildDurationReferenceUtc = DateTimeOffset.UtcNow;
|
||||||
|
this.StateHasChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refreshes live build durations at most once per second while a selected stage is running.
|
||||||
|
/// </summary>
|
||||||
|
private async Task MonitorBuildDurationAsync(CancellationToken token)
|
||||||
|
{
|
||||||
|
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(1));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (await timer.WaitForNextTickAsync(token))
|
||||||
|
await this.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
if (this.latestBuild?.Stages.Any(stage => stage.Status is VisualBriefingBuildStageStatus.RUNNING) != true)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.buildDurationReferenceUtc = DateTimeOffset.UtcNow;
|
||||||
|
this.StateHasChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -408,16 +447,35 @@ public partial class VisualBriefingAssistant
|
|||||||
? T("Completed")
|
? T("Completed")
|
||||||
: T("Not started");
|
: T("Not started");
|
||||||
|
|
||||||
var duration = records
|
var duration = this.CalculateBuildDuration(records);
|
||||||
.Where(record => record.StartedAtUtc is not null)
|
return duration > TimeSpan.Zero ? $"{status} · {FormatBuildDuration(duration)}" : status;
|
||||||
.Aggregate(TimeSpan.Zero, (total, record) =>
|
|
||||||
total + ((record.FinishedAtUtc ?? DateTimeOffset.UtcNow) - record.StartedAtUtc!.Value));
|
|
||||||
|
|
||||||
return duration > TimeSpan.Zero
|
|
||||||
? $"{status} · {duration.TotalSeconds:0.0} s"
|
|
||||||
: status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates active processing time without counting reused stages or time between resume attempts.
|
||||||
|
/// </summary>
|
||||||
|
private TimeSpan CalculateBuildDuration(IEnumerable<VisualBriefingBuildStageRecord> records) => records
|
||||||
|
.Where(record => record.StartedAtUtc is not null && record.Status is not VisualBriefingBuildStageStatus.SKIPPED)
|
||||||
|
.Aggregate(TimeSpan.Zero, (total, record) => total + this.CalculateStageDuration(record));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates one stage duration against the shared live timestamp.
|
||||||
|
/// </summary>
|
||||||
|
private TimeSpan CalculateStageDuration(VisualBriefingBuildStageRecord record)
|
||||||
|
{
|
||||||
|
var finishedAtUtc = record.Status is VisualBriefingBuildStageStatus.RUNNING ? this.buildDurationReferenceUtc : record.FinishedAtUtc;
|
||||||
|
if (record.StartedAtUtc is null || finishedAtUtc is null)
|
||||||
|
return TimeSpan.Zero;
|
||||||
|
|
||||||
|
var duration = finishedAtUtc.Value - record.StartedAtUtc.Value;
|
||||||
|
return duration > TimeSpan.Zero ? duration : TimeSpan.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats a build duration using the current UI culture.
|
||||||
|
/// </summary>
|
||||||
|
private static string FormatBuildDuration(TimeSpan duration) => $"{duration.TotalSeconds:0.0} s";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the safe failure reason for a UI group.
|
/// Gets the safe failure reason for a UI group.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -91,6 +91,9 @@ public partial class VisualBriefingAssistant : MSGComponentBase
|
|||||||
/// <summary>Stops the background source-status monitor.</summary>
|
/// <summary>Stops the background source-status monitor.</summary>
|
||||||
private readonly CancellationTokenSource sourceMonitorCancellation = new();
|
private readonly CancellationTokenSource sourceMonitorCancellation = new();
|
||||||
|
|
||||||
|
/// <summary>Stops the live build-duration monitor.</summary>
|
||||||
|
private readonly CancellationTokenSource buildDurationMonitorCancellation = new();
|
||||||
|
|
||||||
/// <summary>Stores available and recoverable projects ordered by most recent modification.</summary>
|
/// <summary>Stores available and recoverable projects ordered by most recent modification.</summary>
|
||||||
private IReadOnlyList<VisualBriefingProjectEntry> projects = [];
|
private IReadOnlyList<VisualBriefingProjectEntry> projects = [];
|
||||||
|
|
||||||
@ -169,6 +172,9 @@ public partial class VisualBriefingAssistant : MSGComponentBase
|
|||||||
/// <summary>Stores the latest persistent or live build shown in the stepper.</summary>
|
/// <summary>Stores the latest persistent or live build shown in the stepper.</summary>
|
||||||
private VisualBriefingBuildRecord? latestBuild;
|
private VisualBriefingBuildRecord? latestBuild;
|
||||||
|
|
||||||
|
/// <summary>Stores the shared timestamp used to render consistent live build durations.</summary>
|
||||||
|
private DateTimeOffset buildDurationReferenceUtc = DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
/// <summary>Stores incompatible validated content offered for rebuild continuation.</summary>
|
/// <summary>Stores incompatible validated content offered for rebuild continuation.</summary>
|
||||||
private Guid? reusableContentBuildId;
|
private Guid? reusableContentBuildId;
|
||||||
|
|
||||||
@ -199,6 +205,7 @@ public partial class VisualBriefingAssistant : MSGComponentBase
|
|||||||
this.BuildProgressService.Changed += this.BuildProgressChanged;
|
this.BuildProgressService.Changed += this.BuildProgressChanged;
|
||||||
await this.ReloadListAsync();
|
await this.ReloadListAsync();
|
||||||
_ = this.MonitorSourceStatusAsync(this.sourceMonitorCancellation.Token);
|
_ = this.MonitorSourceStatusAsync(this.sourceMonitorCancellation.Token);
|
||||||
|
_ = this.MonitorBuildDurationAsync(this.buildDurationMonitorCancellation.Token);
|
||||||
var deferredInstruction = this.MessageBus.CheckDeferredMessages<string>(Event.SEND_TO_VISUAL_BRIEFING_ASSISTANT).FirstOrDefault();
|
var deferredInstruction = this.MessageBus.CheckDeferredMessages<string>(Event.SEND_TO_VISUAL_BRIEFING_ASSISTANT).FirstOrDefault();
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(deferredInstruction))
|
if (!string.IsNullOrWhiteSpace(deferredInstruction))
|
||||||
@ -220,6 +227,8 @@ public partial class VisualBriefingAssistant : MSGComponentBase
|
|||||||
{
|
{
|
||||||
this.sourceMonitorCancellation.Cancel();
|
this.sourceMonitorCancellation.Cancel();
|
||||||
this.sourceMonitorCancellation.Dispose();
|
this.sourceMonitorCancellation.Dispose();
|
||||||
|
this.buildDurationMonitorCancellation.Cancel();
|
||||||
|
this.buildDurationMonitorCancellation.Dispose();
|
||||||
this.MediaTranscriptionService.StateChanged -= this.MediaStateChanged;
|
this.MediaTranscriptionService.StateChanged -= this.MediaStateChanged;
|
||||||
this.BuildProgressService.Changed -= this.BuildProgressChanged;
|
this.BuildProgressService.Changed -= this.BuildProgressChanged;
|
||||||
base.DisposeResources();
|
base.DisposeResources();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user