mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-04 06:47:21 +00:00
Added progress messages and quick access to exported files (#1112)
This commit is contained in:
1 parent
7f72da628e
commit
e0d8e18f34
33 files changed
+1130
-23
No files matched your search
@@ -69,16 +69,25 @@
|
||||
|
||||
@if (this.ShowDedicatedProgress && this.IsProcessing)
|
||||
{
|
||||
@if (string.IsNullOrWhiteSpace(this.ProgressText))
|
||||
@if (this.processingStartedAt is null && string.IsNullOrWhiteSpace(this.ProgressText))
|
||||
{
|
||||
<MudProgressLinear Color="Color.Primary" Indeterminate="true" Class="mb-6" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudProgressLinear Color="Color.Primary" Indeterminate="true" Class="mb-2" />
|
||||
<MudText Typo="Typo.body2" Class="mb-6">
|
||||
@this.ProgressText
|
||||
</MudText>
|
||||
<MudStack Row="@true" AlignItems="@AlignItems.Center" Spacing="3" Class="mb-6">
|
||||
@if (this.processingStartedAt is { } startedAt)
|
||||
{
|
||||
<ElapsedTime Start="@startedAt"/>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(this.ProgressText))
|
||||
{
|
||||
<MudText Typo="Typo.body2">
|
||||
@this.ProgressText
|
||||
</MudText>
|
||||
}
|
||||
</MudStack>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,6 +180,14 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
private AssistantSessionKey assistantSessionKey;
|
||||
private MediaImportOwner CurrentMediaImportOwner => MediaImportOwner.ForAssistant(this.assistantSessionKey);
|
||||
private Guid? assistantSessionId;
|
||||
|
||||
/// <summary>
|
||||
/// When the running session started, which the time below the progress bar counts from; null while
|
||||
/// no session runs. It comes from the session, so an instance which returns to a running session
|
||||
/// goes on counting where the first one was.
|
||||
/// </summary>
|
||||
private DateTimeOffset? processingStartedAt;
|
||||
|
||||
private AssistantSessionSnapshot? pendingRenderedAssistantSessionSnapshot;
|
||||
private AssistantSessionSnapshot? lastAttachedAssistantSessionSnapshot;
|
||||
|
||||
@@ -311,6 +319,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
}
|
||||
|
||||
this.assistantSessionId = startedSession.SessionId;
|
||||
this.processingStartedAt = startedSession.StartedAt;
|
||||
await this.RefreshAssistantUIAsync();
|
||||
|
||||
var sessionStatus = AssistantSessionStatus.COMPLETED;
|
||||
@@ -343,6 +352,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
finally
|
||||
{
|
||||
this.IsProcessing = false;
|
||||
this.processingStartedAt = null;
|
||||
var sessionCancellationTokenSource = this.CancellationTokenSource;
|
||||
this.CancellationTokenSource = null;
|
||||
if (this.assistantSessionId is { } sessionId)
|
||||
@@ -1060,6 +1070,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
this.lastAttachedAssistantSessionSnapshot = snapshot;
|
||||
this.ChatThread = snapshot.ChatThread ?? this.ChatThread;
|
||||
this.IsProcessing = snapshot.IsActive;
|
||||
this.processingStartedAt = snapshot.IsActive ? snapshot.StartedAt : null;
|
||||
|
||||
if (!snapshot.IsActive)
|
||||
this.CancellationTokenSource = null;
|
||||
|
||||
@@ -3157,6 +3157,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::
|
||||
-- Opened the visual briefing project folder.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T2964042492"] = "Opened the visual briefing project folder."
|
||||
|
||||
-- The visual briefing could not be exported. Please check that the target file is not open in another program.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T3136382170"] = "The visual briefing could not be exported. Please check that the target file is not open in another program."
|
||||
|
||||
-- Visual assets
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T3226971402"] = "Visual assets"
|
||||
|
||||
@@ -3286,6 +3289,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::
|
||||
-- If you need help, report the problem and include the project ID.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T4292361710"] = "If you need help, report the problem and include the project ID."
|
||||
|
||||
-- The visual briefing could not be written completely.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T442972740"] = "The visual briefing could not be written completely."
|
||||
|
||||
-- The briefing was recompiled with the current AI Studio version.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T453632597"] = "The briefing was recompiled with the current AI Studio version."
|
||||
|
||||
@@ -4702,6 +4708,30 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERSETTINGSACTION::T244391
|
||||
-- Change what this tile opens
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERSETTINGSACTION::T4272203100"] = "Change what this tile opens"
|
||||
|
||||
-- Could not open the file location.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::FILEEXPORTACTIONS::T1118835751"] = "Could not open the file location."
|
||||
|
||||
-- Could not open the file: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::FILEEXPORTACTIONS::T1290686840"] = "Could not open the file: {0}"
|
||||
|
||||
-- Open with the default program
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::FILEEXPORTACTIONS::T1332010305"] = "Open with the default program"
|
||||
|
||||
-- Could not open the file location: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::FILEEXPORTACTIONS::T1455637941"] = "Could not open the file location: {0}"
|
||||
|
||||
-- Show in the file manager
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::FILEEXPORTACTIONS::T3007835369"] = "Show in the file manager"
|
||||
|
||||
-- Unknown error
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::FILEEXPORTACTIONS::T3461425987"] = "Unknown error"
|
||||
|
||||
-- Could not open the file.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::FILEEXPORTACTIONS::T362546438"] = "Could not open the file."
|
||||
|
||||
-- Saving '{0}'...
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::FILEEXPORTRUNNINGMESSAGE::T1063135893"] = "Saving '{0}'..."
|
||||
|
||||
-- LLMs can make mistakes. Check important information.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::HALLUZINATIONREMINDER::T3528806904"] = "LLMs can make mistakes. Check important information."
|
||||
|
||||
@@ -5266,6 +5296,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1594053136"]
|
||||
-- Color theme
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1599198973"] = "Color theme"
|
||||
|
||||
-- After you export a file, for example, an answer or a presentation, a message offers to show the file in your file manager or to open it. When enabled, this message closes after a few seconds, like other messages. When disabled, it stays until you close it.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T160366478"] = "After you export a file, for example, an answer or a presentation, a message offers to show the file in your file manager or to open it. When enabled, this message closes after a few seconds, like other messages. When disabled, it stays until you close it."
|
||||
|
||||
-- Would you like to set one of your profiles as the default for the entire app? When you configure a different profile for an assistant, it will always take precedence.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1666052109"] = "Would you like to set one of your profiles as the default for the entire app? When you configure a different profile for an assistant, it will always take precedence."
|
||||
|
||||
@@ -5317,6 +5350,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T215381891"]
|
||||
-- Enterprise Administration
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2277116008"] = "Enterprise Administration"
|
||||
|
||||
-- Close messages about exported files automatically?
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2330147290"] = "Close messages about exported files automatically?"
|
||||
|
||||
-- Language behavior
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2341504363"] = "Language behavior"
|
||||
|
||||
@@ -5344,6 +5380,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2700836219"]
|
||||
-- No preview features selected.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2809641588"] = "No preview features selected."
|
||||
|
||||
-- The message stays until you close it
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2879147627"] = "The message stays until you close it"
|
||||
|
||||
-- This installation does not check for updates itself. Contact the person or organization that installed AI Studio for update information.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2918560776"] = "This installation does not check for updates itself. Contact the person or organization that installed AI Studio for update information."
|
||||
|
||||
@@ -5413,6 +5452,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T4004501229"]
|
||||
-- When enabled, spellchecking will be active in all input fields. Depending on your operating system, errors may not be visually highlighted, but right-clicking may still offer possible corrections.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T4067492921"] = "When enabled, spellchecking will be active in all input fields. Depending on your operating system, errors may not be visually highlighted, but right-clicking may still offer possible corrections."
|
||||
|
||||
-- The message closes after a few seconds
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T4102409342"] = "The message closes after a few seconds"
|
||||
|
||||
-- Show details when suspicious content was removed?
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T4156872850"] = "Show details when suspicious content was removed?"
|
||||
|
||||
|
||||
@@ -562,6 +562,10 @@ public partial class SlideAssistant
|
||||
var targetPath = response.SaveFilePath;
|
||||
this.isWritingPresentation = true;
|
||||
this.StateHasChanged();
|
||||
|
||||
// Pictures make this take seconds, since each of them is prepared anew:
|
||||
await using var feedback = new FileExportFeedback();
|
||||
feedback.ShowRunning(targetPath);
|
||||
try
|
||||
{
|
||||
var options = new PresentationWriteOptions(this.variantLabel, this.footerText.Trim(), this.keepEmptyPicturePlaceholders);
|
||||
@@ -582,7 +586,7 @@ public partial class SlideAssistant
|
||||
await this.MessageBus.SendWarning(new(Icons.Material.Filled.HideImage, string.Format(T("These pictures could not be placed, because PowerPoint cannot show their format or they cannot be read: {0}"), string.Join(", ", names))));
|
||||
}
|
||||
|
||||
await this.MessageBus.SendSuccess(new(Icons.Material.Filled.Slideshow, T("The PowerPoint file was created.")));
|
||||
await feedback.SucceededAsync(Icons.Material.Filled.Slideshow, T("The PowerPoint file was created."), targetPath, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
+54
-3
@@ -134,8 +134,10 @@ public partial class VisualBriefingAssistant
|
||||
// why it gets no notice that AI generated it: any change would make it a version nobody checked.
|
||||
//
|
||||
await using var source = verified.Value.Stream;
|
||||
await using var destination = new FileStream(response.SaveFilePath, FileMode.Create, FileAccess.Write, FileShare.None, 65_536, true);
|
||||
await source.CopyToAsync(destination);
|
||||
await using var feedback = new FileExportFeedback();
|
||||
feedback.ShowRunning(response.SaveFilePath);
|
||||
if (!await this.TryWriteExportAsync(source, response.SaveFilePath))
|
||||
return;
|
||||
|
||||
var exportedVersion = this.selectedBriefing.Versions.First(version =>
|
||||
version.RevisionId == this.selectedRevisionId);
|
||||
@@ -150,7 +152,56 @@ public partial class VisualBriefingAssistant
|
||||
exportedVersion.DocumentHash,
|
||||
source.Length);
|
||||
|
||||
await this.MessageBus.SendSuccess(new(Icons.Material.Filled.FileDownload, T("The visual briefing was exported.")));
|
||||
await feedback.SucceededAsync(Icons.Material.Filled.FileDownload, T("The visual briefing was exported."), response.SaveFilePath, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an exported version into the file the user chose, and tells the user when that fails.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The file is written over rather than removed and created anew, which the Flatpak would not allow.
|
||||
/// A file which cannot even be opened, e.g., because another program holds it, stays as it is. Once
|
||||
/// writing has begun, a failure removes the file: half a briefing is worse than none.
|
||||
/// </remarks>
|
||||
/// <param name="source">The verified version to export.</param>
|
||||
/// <param name="targetPath">The file the user chose.</param>
|
||||
/// <returns>True, when the file was written completely.</returns>
|
||||
private async Task<bool> TryWriteExportAsync(Stream source, string targetPath)
|
||||
{
|
||||
FileStream destination;
|
||||
try
|
||||
{
|
||||
destination = new FileStream(targetPath, FileMode.Create, FileAccess.Write, FileShare.None, 65_536, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.Logger.LogError(e, "The visual briefing could not be exported, because the file '{FilePath}' cannot be opened for writing.", targetPath);
|
||||
await this.MessageBus.SendError(new(Icons.Material.Filled.FileDownload, T("The visual briefing could not be exported. Please check that the target file is not open in another program.")));
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await using (destination)
|
||||
await source.CopyToAsync(destination);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.Logger.LogError(e, "Writing the visual briefing into the file '{FilePath}' failed.", targetPath);
|
||||
try
|
||||
{
|
||||
File.Delete(targetPath);
|
||||
}
|
||||
catch (Exception deleteFailure)
|
||||
{
|
||||
this.Logger.LogWarning(deleteFailure, "The incomplete export '{FilePath}' cannot be deleted.", targetPath);
|
||||
}
|
||||
|
||||
await this.MessageBus.SendError(new(Icons.Material.Filled.FileDownload, T("The visual briefing could not be written completely.")));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in new issue
Block a user