@@ -14,6 +14,7 @@ class ViewModel: ObservableObject {
1414 @Published var isInteractingWithChatGPT = false
1515 @Published var messages : [ MessageRow ] = [ ]
1616 @Published var inputMessage : String = " "
17+ var task : Task < Void , Never > ?
1718
1819 #if !os(watchOS)
1920 private var synthesizer : AVSpeechSynthesizer ?
@@ -32,11 +33,15 @@ class ViewModel: ObservableObject {
3233
3334 @MainActor
3435 func sendTapped( ) async {
35- let text = inputMessage
36- inputMessage = " "
3736 #if os(iOS)
38- await sendAttributed ( text: text)
37+ self . task = Task {
38+ let text = inputMessage
39+ inputMessage = " "
40+ await sendAttributed ( text: text)
41+ }
3942 #else
43+ let text = inputMessage
44+ inputMessage = " "
4045 await send ( text: text)
4146 #endif
4247 }
@@ -52,47 +57,61 @@ class ViewModel: ObservableObject {
5257
5358 @MainActor
5459 func retry( message: MessageRow ) async {
60+ #if os(iOS)
61+ self . task = Task {
62+ guard let index = messages. firstIndex ( where: { $0. id == message. id } ) else {
63+ return
64+ }
65+ self . messages. remove ( at: index)
66+ await sendAttributed ( text: message. sendText)
67+ }
68+ #else
5569 guard let index = messages. firstIndex ( where: { $0. id == message. id } ) else {
5670 return
5771 }
5872 self . messages. remove ( at: index)
59- #if os(iOS)
60- await sendAttributed ( text: message. sendText)
61- #else
6273 await send ( text: message. sendText)
6374 #endif
6475 }
6576
77+ func cancelStreamingResponse( ) {
78+ self . task? . cancel ( )
79+ self . task = nil
80+ }
81+
6682 #if os(iOS)
6783 @MainActor
6884 private func sendAttributed( text: String ) async {
6985 isInteractingWithChatGPT = true
70-
71- let parsingTask = ResponseParsingTask ( )
72- let attributedSend = await parsingTask. parse ( text: text)
73-
7486 var streamText = " "
87+
7588 var messageRow = MessageRow (
7689 isInteractingWithChatGPT: true ,
7790 sendImage: " profile " ,
78- send: . attributed ( attributedSend ) ,
91+ send: . rawText ( text ) ,
7992 responseImage: " openai " ,
8093 responseError: nil )
81-
82- self . messages. append ( messageRow)
83-
84- let parserThresholdTextCount = 64
85- var currentTextCount = 0
86- var currentOutput : AttributedOutput ?
87-
94+
8895 do {
96+ let parsingTask = ResponseParsingTask ( )
97+ let attributedSend = await parsingTask. parse ( text: text)
98+ try Task . checkCancellation ( )
99+ messageRow. send = . attributed( attributedSend)
100+
101+ self . messages. append ( messageRow)
102+
103+ let parserThresholdTextCount = 64
104+ var currentTextCount = 0
105+ var currentOutput : AttributedOutput ?
106+
89107 let stream = try await api. sendMessageStream ( text: text)
90108 for try await text in stream {
91109 streamText += text
92110 currentTextCount += text. count
93111
94112 if currentTextCount >= parserThresholdTextCount || text. contains ( " ``` " ) {
95113 currentOutput = await parsingTask. parse ( text: streamText)
114+ try Task . checkCancellation ( )
96115 currentTextCount = 0
97116 }
98117
@@ -115,17 +134,22 @@ class ViewModel: ObservableObject {
115134 }
116135
117136 self . messages [ self . messages. count - 1 ] = messageRow
137+ if let currentString = currentOutput? . string, currentString != streamText {
138+ let output = await parsingTask. parse ( text: streamText)
139+ try Task . checkCancellation ( )
140+ messageRow. response = . attributed( output)
141+ }
118142 }
143+ } catch is CancellationError {
144+ messageRow. responseError = " The response was cancelled "
119145 } catch {
120146 messageRow. responseError = error. localizedDescription
121- messageRow. response = . rawText( streamText)
122147 }
123148
124- if let currentString = currentOutput? . string, currentString != streamText {
125- let output = await parsingTask. parse ( text: streamText)
126- messageRow. response = . attributed( output)
149+ if messageRow. response == nil {
150+ messageRow. response = . rawText( streamText)
127151 }
128-
152+
129153 messageRow. isInteractingWithChatGPT = false
130154 self . messages [ self . messages. count - 1 ] = messageRow
131155 isInteractingWithChatGPT = false
0 commit comments