@@ -4,6 +4,7 @@ import kotlinx.coroutines.CoroutineDispatcher
4
4
import kotlinx.coroutines.Dispatchers
5
5
import kotlinx.coroutines.delay
6
6
import kotlinx.coroutines.withContext
7
+ import okhttp3.Call
7
8
import okhttp3.HttpUrl
8
9
import okhttp3.MediaType.Companion.toMediaType
9
10
import okhttp3.MultipartBody
@@ -35,7 +36,7 @@ class WpRequestExecutor(
35
36
private val httpClient : WpHttpClient = WpHttpClient .DefaultHttpClient (),
36
37
private val dispatcher : CoroutineDispatcher = Dispatchers .IO ,
37
38
private val fileResolver : FileResolver = DefaultFileResolver (),
38
- private val uploadProgressListener : ((uploadedBytes: Long , totalBytes: Long ) -> Unit ) ? = null
39
+ private val uploadListener : UploadListener ? = null
39
40
) : RequestExecutor {
40
41
override suspend fun execute (request : WpNetworkRequest ): WpNetworkResponse =
41
42
withContext(dispatcher) {
@@ -95,7 +96,7 @@ class WpRequestExecutor(
95
96
if (file == null || ! file.canBeUploaded()) {
96
97
throw MediaUploadRequestExecutionException .MediaFileNotFound (mediaUploadRequest.filePath())
97
98
}
98
- val progressRequestBody = getRequestBody(file, mediaUploadRequest, uploadProgressListener )
99
+ val progressRequestBody = getRequestBody(file, mediaUploadRequest, uploadListener )
99
100
multipartBodyBuilder.addFormDataPart(
100
101
name = " file" ,
101
102
filename = file.name,
@@ -111,7 +112,10 @@ class WpRequestExecutor(
111
112
}
112
113
}
113
114
114
- httpClient.getClient().newCall(requestBuilder.build()).execute().use { response ->
115
+ val call = httpClient.getClient().newCall(requestBuilder.build())
116
+ // Notify about the call creation so it can be cancelled if needed
117
+ uploadListener?.onUploadStarted(CancellableCall (call))
118
+ call.execute().use { response ->
115
119
return @withContext WpNetworkResponse (
116
120
body = response.body?.bytes() ? : ByteArray (0 ),
117
121
statusCode = response.code.toUShort(),
@@ -125,15 +129,15 @@ class WpRequestExecutor(
125
129
private fun getRequestBody (
126
130
file : File ,
127
131
mediaUploadRequest : MediaUploadRequest ,
128
- uploadProgressListener : ((uploadedBytes: Long , totalBytes: Long ) -> Unit ) ?
132
+ uploadListener : UploadListener ?
129
133
): RequestBody {
130
134
val fileRequestBody = file.asRequestBody(mediaUploadRequest.fileContentType().toMediaType())
131
- return if (uploadProgressListener != null ) {
135
+ return if (uploadListener != null ) {
132
136
ProgressRequestBody (
133
137
delegate = fileRequestBody,
134
138
progressListener = object : ProgressRequestBody .ProgressListener {
135
139
override fun onProgress (bytesWritten : Long , contentLength : Long ) {
136
- uploadProgressListener.invoke (bytesWritten, contentLength)
140
+ uploadListener.onProgressUpdate (bytesWritten, contentLength)
137
141
}
138
142
}
139
143
)
@@ -147,6 +151,49 @@ class WpRequestExecutor(
147
151
}
148
152
149
153
private fun File.canBeUploaded () = exists() && isFile && canRead()
154
+
155
+ /* *
156
+ * Interface for monitoring the progress and status of a media upload.
157
+ */
158
+ interface UploadListener {
159
+ /* *
160
+ * Called to report the progress of the upload.
161
+ *
162
+ * @param uploadedBytes The number of bytes that have been uploaded so far.
163
+ * @param totalBytes The total number of bytes to be uploaded.
164
+ */
165
+ fun onProgressUpdate (uploadedBytes : Long , totalBytes : Long )
166
+
167
+ /* *
168
+ * Called when the upload starts.
169
+ *
170
+ * @param cancellableUpload The [CancellableUpload] object representing the upload request. This can be used
171
+ * to cancel the upload if needed by calling [cancellableUpload.cancel].
172
+ *
173
+ * This method is invoked at the beginning of the upload process, allowing the caller
174
+ * to monitor or control the upload operation.
175
+ */
176
+ fun onUploadStarted (cancellableUpload : CancellableUpload )
177
+ }
178
+
179
+ /* *
180
+ * Represents a cancellable upload operation.
181
+ */
182
+ interface CancellableUpload {
183
+ /* *
184
+ * Cancels the upload operation.
185
+ */
186
+ fun cancel ()
187
+ }
188
+
189
+ /* *
190
+ * Implementation of [CancellableUpload] that delegates to an OkHttp [Call].
191
+ */
192
+ class CancellableCall (private val call : Call ) : CancellableUpload {
193
+ override fun cancel () {
194
+ call.cancel()
195
+ }
196
+ }
150
197
}
151
198
152
199
private fun RequestExecutionErrorReason.Companion.unknownHost (e : UnknownHostException ) =
0 commit comments