From fdfea1501cc716619bcd86f4724e42bb5155080c Mon Sep 17 00:00:00 2001
From: Thorsten Sommer <mail@tsommer.org>
Date: Sat, 26 Apr 2025 18:17:57 +0200
Subject: [PATCH] Refactor button click handling to use async Start method for
 improved cancellation support

---
 .../Assistants/AssistantBase.razor            |  2 +-
 .../Assistants/AssistantBase.razor.cs         | 30 +++++++++++--------
 2 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor b/app/MindWork AI Studio/Assistants/AssistantBase.razor
index 1451da41..c27704c4 100644
--- a/app/MindWork AI Studio/Assistants/AssistantBase.razor	
+++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor	
@@ -29,7 +29,7 @@
                     </CascadingValue>
                     
                     <MudStack Row="true" AlignItems="AlignItems.Center" StretchItems="StretchItems.Start" Class="mb-3">
-                        <MudButton Disabled="@this.SubmitDisabled" Variant="Variant.Filled" OnClick="() => this.SubmitAction()" Style="@this.SubmitButtonStyle">
+                        <MudButton Disabled="@this.SubmitDisabled" Variant="Variant.Filled" OnClick="async () => await this.Start()" Style="@this.SubmitButtonStyle">
                             @this.SubmitText
                         </MudButton>
                         @if (this.isProcessing && this.cancellationTokenSource is not null)
diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs
index 1f0c7364..1a9ff997 100644
--- a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs	
+++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs	
@@ -97,10 +97,10 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase, IMe
     protected Profile currentProfile = Profile.NO_PROFILE;
     protected ChatThread? chatThread;
     protected IContent? lastUserPrompt;
+    protected CancellationTokenSource? cancellationTokenSource;
     
     private readonly Timer formChangeTimer = new(TimeSpan.FromSeconds(1.6));
-    
-    private CancellationTokenSource? cancellationTokenSource;
+
     private ContentBlock? resultingContentBlock;
     private string[] inputIssues = [];
     private bool isProcessing;
@@ -179,6 +179,16 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase, IMe
         return null;
     }
 
+    private async Task Start()
+    {
+        using (this.cancellationTokenSource = new())
+        {
+            await this.SubmitAction();
+        }
+        
+        this.cancellationTokenSource = null;
+    }
+
     private void TriggerFormChange(FormFieldChangedEventArgs _)
     {
         this.formChangeTimer.Stop();
@@ -286,16 +296,12 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase, IMe
 
         this.isProcessing = true;
         this.StateHasChanged();
-
-        using (this.cancellationTokenSource = new())
-        {
-            // Use the selected provider to get the AI response.
-            // By awaiting this line, we wait for the entire
-            // content to be streamed.
-            this.chatThread = await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(this.Logger), this.providerSettings.Model, this.lastUserPrompt, this.chatThread, this.cancellationTokenSource.Token);
-        }
-
-        this.cancellationTokenSource = null;
+        
+        // Use the selected provider to get the AI response.
+        // By awaiting this line, we wait for the entire
+        // content to be streamed.
+        this.chatThread = await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(this.Logger), this.providerSettings.Model, this.lastUserPrompt, this.chatThread, this.cancellationTokenSource!.Token);
+        
         this.isProcessing = false;
         this.StateHasChanged();