@@ -202,28 +202,75 @@ private final class SessionAdaptor {
202202 let ( asyncBytes, response) = try await session. task ( for: request)
203203 task = asyncBytes. task
204204
205+ // Get expected content length from response for accurate progress tracking
206+ let expectedContentLength = response. expectedContentLength
207+
208+ // Also observe task.progress as a fallback, but we'll primarily use manual tracking
209+ // for more accurate and frequent updates
205210 if let progressHandler,
206211 let task {
207212 observer = task. progress. observe ( progressHandler)
208213 }
209214
210215 var data = Data ( )
216+ var bytesRead : Int64 = 0
217+ // Update progress every 1KB or when significant chunk is received
218+ // This provides smoother progress updates than relying solely on task.progress
219+ let progressUpdateThreshold : Int64 = 1024
211220
212221 for try await byte in asyncBytes {
213222 try Task . checkCancellation ( )
214223 data. append ( byte)
224+ bytesRead += 1
225+
226+ // Manually update progress if expectedContentLength is known
227+ // This ensures we get regular updates even if task.progress updates infrequently
228+ if let progressHandler = progressHandler,
229+ expectedContentLength > 0 ,
230+ bytesRead % progressUpdateThreshold == 0 {
231+ let progress = Progress ( totalUnitCount: expectedContentLength)
232+ progress. completedUnitCount = bytesRead
233+ progressHandler ( progress)
234+ } else if let progressHandler = progressHandler,
235+ expectedContentLength < 0 ,
236+ bytesRead % progressUpdateThreshold == 0 {
237+ // If content length is unknown, create indeterminate progress
238+ // that shows we're making progress (bytesRead increases)
239+ let progress = Progress ( totalUnitCount: - 1 )
240+ progress. completedUnitCount = bytesRead
241+ progressHandler ( progress)
242+ }
243+ }
244+
245+ // Send final progress update (100%) if we have a handler and expected length
246+ // This ensures completion is always reported, even if task.progress didn't update
247+ if let progressHandler = progressHandler {
248+ if expectedContentLength > 0 {
249+ let progress = Progress ( totalUnitCount: expectedContentLength)
250+ progress. completedUnitCount = expectedContentLength
251+ progressHandler ( progress)
252+ } else {
253+ // For unknown length, send completion with bytesRead as total
254+ let progress = Progress ( totalUnitCount: bytesRead)
255+ progress. completedUnitCount = bytesRead
256+ progressHandler ( progress)
257+ }
215258 }
216259
217260 return ( data, response)
218261 }
219262
220263 /// Cancels the running task and clears its observer.
221264 func stop( ) {
265+ // Clear observer first to prevent any further progress updates
266+ observer = nil
267+
268+ // Then cancel the task if it's running
222269 if task? . state == . running {
223270 task? . cancel ( )
224271 }
272+
225273 task = nil
226- observer = nil
227274 }
228275}
229276
0 commit comments