From 4b06b750ac989f5915f41f599633663470d8627b Mon Sep 17 00:00:00 2001 From: Alex Li Date: Tue, 25 Feb 2025 15:48:23 +0800 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Move=20all=20source=20Dart?= =?UTF-8?q?=20files=20to=20`*=5Fimpl.dart`=20to=20avoid=20naming=20collisi?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/web_adapter/CHANGELOG.md | 5 + plugins/web_adapter/lib/dio_web_adapter.dart | 8 +- plugins/web_adapter/lib/src/adapter.dart | 301 +----------------- plugins/web_adapter/lib/src/adapter_impl.dart | 296 +++++++++++++++++ plugins/web_adapter/lib/src/compute.dart | 40 +-- plugins/web_adapter/lib/src/compute_impl.dart | 35 ++ plugins/web_adapter/lib/src/dio_impl.dart | 2 +- .../web_adapter/lib/src/multipart_file.dart | 26 +- .../lib/src/multipart_file_impl.dart | 21 ++ .../web_adapter/lib/src/progress_stream.dart | 45 +-- .../lib/src/progress_stream_impl.dart | 40 +++ plugins/web_adapter/pubspec.yaml | 2 +- 12 files changed, 423 insertions(+), 398 deletions(-) create mode 100644 plugins/web_adapter/lib/src/adapter_impl.dart create mode 100644 plugins/web_adapter/lib/src/compute_impl.dart create mode 100644 plugins/web_adapter/lib/src/multipart_file_impl.dart create mode 100644 plugins/web_adapter/lib/src/progress_stream_impl.dart diff --git a/plugins/web_adapter/CHANGELOG.md b/plugins/web_adapter/CHANGELOG.md index dd5cc5180..cef00977b 100644 --- a/plugins/web_adapter/CHANGELOG.md +++ b/plugins/web_adapter/CHANGELOG.md @@ -2,6 +2,11 @@ *None.* +## 1.1.1 + +- Move all source Dart files to `*_impl.dart` to avoid naming collision. + This is a workaround of https://github.com/dart-lang/sdk/issues/56498. + ## 1.1.0 - Support `FileAccessMode` in `Dio.download` and `Dio.downloadUri` to change download file opening mode. diff --git a/plugins/web_adapter/lib/dio_web_adapter.dart b/plugins/web_adapter/lib/dio_web_adapter.dart index 64e8178f9..a84009aa9 100644 --- a/plugins/web_adapter/lib/dio_web_adapter.dart +++ b/plugins/web_adapter/lib/dio_web_adapter.dart @@ -1,7 +1,7 @@ library dio_web_adapter; -export 'src/adapter.dart'; -export 'src/compute.dart'; +export 'src/adapter_impl.dart'; +export 'src/compute_impl.dart'; export 'src/dio_impl.dart'; -export 'src/multipart_file.dart'; -export 'src/progress_stream.dart'; +export 'src/multipart_file_impl.dart'; +export 'src/progress_stream_impl.dart'; diff --git a/plugins/web_adapter/lib/src/adapter.dart b/plugins/web_adapter/lib/src/adapter.dart index a27c0412f..8e2467a7c 100644 --- a/plugins/web_adapter/lib/src/adapter.dart +++ b/plugins/web_adapter/lib/src/adapter.dart @@ -1,296 +1,5 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:html'; -import 'dart:typed_data'; - -import 'package:dio/dio.dart'; -import 'package:dio/src/utils.dart'; -import 'package:meta/meta.dart'; - -BrowserHttpClientAdapter createAdapter() => BrowserHttpClientAdapter(); - -/// The default [HttpClientAdapter] for Web platforms. -class BrowserHttpClientAdapter implements HttpClientAdapter { - BrowserHttpClientAdapter({this.withCredentials = false}); - - /// These are aborted if the client is closed. - @visibleForTesting - final xhrs = {}; - - /// Whether to send credentials such as cookies or authorization headers for - /// cross-site requests. - /// - /// Defaults to `false`. - /// - /// You can also override this value using `Options.extra['withCredentials']` - /// for each request. - bool withCredentials; - - @override - Future fetch( - RequestOptions options, - Stream? requestStream, - Future? cancelFuture, - ) async { - final xhr = HttpRequest(); - xhrs.add(xhr); - xhr - ..open(options.method, '${options.uri}') - ..responseType = 'arraybuffer'; - - final withCredentialsOption = options.extra['withCredentials']; - if (withCredentialsOption != null) { - xhr.withCredentials = withCredentialsOption == true; - } else { - xhr.withCredentials = withCredentials; - } - - options.headers.remove(Headers.contentLengthHeader); - options.headers.forEach((key, v) { - if (v is Iterable) { - xhr.setRequestHeader(key, v.join(', ')); - } else { - xhr.setRequestHeader(key, v.toString()); - } - }); - - final sendTimeout = options.sendTimeout ?? Duration.zero; - final connectTimeout = options.connectTimeout ?? Duration.zero; - final receiveTimeout = options.receiveTimeout ?? Duration.zero; - final xhrTimeout = (connectTimeout + receiveTimeout).inMilliseconds; - xhr.timeout = xhrTimeout; - - final completer = Completer(); - - xhr.onLoad.first.then((_) { - final Uint8List body = (xhr.response as ByteBuffer).asUint8List(); - completer.complete( - ResponseBody.fromBytes( - body, - xhr.status!, - headers: xhr.responseHeaders.map((k, v) => MapEntry(k, v.split(','))), - statusMessage: xhr.statusText, - isRedirect: xhr.status == 302 || - xhr.status == 301 || - options.uri.toString() != xhr.responseUrl, - ), - ); - }); - - Timer? connectTimeoutTimer; - if (connectTimeout > Duration.zero) { - connectTimeoutTimer = Timer( - connectTimeout, - () { - connectTimeoutTimer = null; - if (completer.isCompleted) { - // connectTimeout is triggered after the fetch has been completed. - return; - } - xhr.abort(); - completer.completeError( - DioException.connectionTimeout( - requestOptions: options, - timeout: connectTimeout, - ), - StackTrace.current, - ); - }, - ); - } - - // This code is structured to call `xhr.upload.onProgress.listen` only when - // absolutely necessary, because registering an xhr upload listener prevents - // the request from being classified as a "simple request" by the CORS spec. - // Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests - // Upload progress events only get triggered if the request body exists, - // so we can check it beforehand. - if (requestStream != null) { - if (connectTimeoutTimer != null) { - xhr.upload.onProgress.listen((event) { - connectTimeoutTimer?.cancel(); - connectTimeoutTimer = null; - }); - } - - if (sendTimeout > Duration.zero) { - final uploadStopwatch = Stopwatch(); - xhr.upload.onProgress.listen((event) { - if (!uploadStopwatch.isRunning) { - uploadStopwatch.start(); - } - final duration = uploadStopwatch.elapsed; - if (duration > sendTimeout) { - uploadStopwatch.stop(); - completer.completeError( - DioException.sendTimeout( - timeout: sendTimeout, - requestOptions: options, - ), - StackTrace.current, - ); - xhr.abort(); - } - }); - } - - final onSendProgress = options.onSendProgress; - if (onSendProgress != null) { - xhr.upload.onProgress.listen((event) { - if (event.loaded != null && event.total != null) { - onSendProgress(event.loaded!, event.total!); - } - }); - } - } - - final receiveStopwatch = Stopwatch(); - Timer? receiveTimer; - - void stopWatchReceiveTimeout() { - receiveTimer?.cancel(); - receiveTimer = null; - receiveStopwatch.stop(); - } - - void watchReceiveTimeout() { - if (receiveTimeout <= Duration.zero) { - return; - } - receiveStopwatch.reset(); - if (!receiveStopwatch.isRunning) { - receiveStopwatch.start(); - } - receiveTimer?.cancel(); - receiveTimer = Timer(receiveTimeout, () { - if (!completer.isCompleted) { - xhr.abort(); - completer.completeError( - DioException.receiveTimeout( - timeout: receiveTimeout, - requestOptions: options, - ), - StackTrace.current, - ); - } - stopWatchReceiveTimeout(); - }); - } - - xhr.onProgress.listen( - (ProgressEvent event) { - if (connectTimeoutTimer != null) { - connectTimeoutTimer!.cancel(); - connectTimeoutTimer = null; - } - watchReceiveTimeout(); - if (options.onReceiveProgress != null && - event.loaded != null && - event.total != null) { - options.onReceiveProgress!(event.loaded!, event.total!); - } - }, - onDone: () => stopWatchReceiveTimeout(), - ); - - xhr.onError.first.then((_) { - connectTimeoutTimer?.cancel(); - // Unfortunately, the underlying XMLHttpRequest API doesn't expose any - // specific information about the error itself. - // See also: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget/onerror - completer.completeError( - DioException.connectionError( - requestOptions: options, - reason: 'The XMLHttpRequest onError callback was called. ' - 'This typically indicates an error on the network layer.', - ), - StackTrace.current, - ); - }); - - xhr.onTimeout.first.then((_) { - final isConnectTimeout = connectTimeoutTimer != null; - if (connectTimeoutTimer != null) { - connectTimeoutTimer?.cancel(); - } - if (!completer.isCompleted) { - if (isConnectTimeout) { - completer.completeError( - DioException.connectionTimeout( - timeout: connectTimeout, - requestOptions: options, - ), - ); - } else { - completer.completeError( - DioException.receiveTimeout( - timeout: Duration(milliseconds: xhrTimeout), - requestOptions: options, - ), - StackTrace.current, - ); - } - } - }); - - cancelFuture?.then((_) { - if (xhr.readyState < HttpRequest.DONE && - xhr.readyState > HttpRequest.UNSENT) { - connectTimeoutTimer?.cancel(); - try { - xhr.abort(); - } catch (_) {} - if (!completer.isCompleted) { - completer.completeError( - DioException.requestCancelled( - requestOptions: options, - reason: 'The XMLHttpRequest was aborted.', - ), - ); - } - } - }); - - if (requestStream != null) { - if (options.method == 'GET') { - warningLog( - 'GET request with a body data are not support on the ' - 'web platform. Use POST/PUT instead.', - StackTrace.current, - ); - } - final completer = Completer(); - final sink = ByteConversionSink.withCallback( - (bytes) => completer.complete( - bytes is Uint8List ? bytes : Uint8List.fromList(bytes), - ), - ); - requestStream.listen( - sink.add, - onError: (Object e, StackTrace s) => completer.completeError(e, s), - onDone: sink.close, - cancelOnError: true, - ); - final bytes = await completer.future; - xhr.send(bytes); - } else { - xhr.send(); - } - return completer.future.whenComplete(() { - xhrs.remove(xhr); - }); - } - - /// Closes the client. - /// - /// This terminates all active requests. - @override - void close({bool force = false}) { - if (force) { - for (final xhr in xhrs) { - xhr.abort(); - } - } - xhrs.clear(); - } -} +@Deprecated( + 'Import adapter_impl.dart instead. ' + 'See https://github.com/dart-lang/sdk/issues/56498', +) +export 'adapter_impl.dart'; diff --git a/plugins/web_adapter/lib/src/adapter_impl.dart b/plugins/web_adapter/lib/src/adapter_impl.dart new file mode 100644 index 000000000..a27c0412f --- /dev/null +++ b/plugins/web_adapter/lib/src/adapter_impl.dart @@ -0,0 +1,296 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:html'; +import 'dart:typed_data'; + +import 'package:dio/dio.dart'; +import 'package:dio/src/utils.dart'; +import 'package:meta/meta.dart'; + +BrowserHttpClientAdapter createAdapter() => BrowserHttpClientAdapter(); + +/// The default [HttpClientAdapter] for Web platforms. +class BrowserHttpClientAdapter implements HttpClientAdapter { + BrowserHttpClientAdapter({this.withCredentials = false}); + + /// These are aborted if the client is closed. + @visibleForTesting + final xhrs = {}; + + /// Whether to send credentials such as cookies or authorization headers for + /// cross-site requests. + /// + /// Defaults to `false`. + /// + /// You can also override this value using `Options.extra['withCredentials']` + /// for each request. + bool withCredentials; + + @override + Future fetch( + RequestOptions options, + Stream? requestStream, + Future? cancelFuture, + ) async { + final xhr = HttpRequest(); + xhrs.add(xhr); + xhr + ..open(options.method, '${options.uri}') + ..responseType = 'arraybuffer'; + + final withCredentialsOption = options.extra['withCredentials']; + if (withCredentialsOption != null) { + xhr.withCredentials = withCredentialsOption == true; + } else { + xhr.withCredentials = withCredentials; + } + + options.headers.remove(Headers.contentLengthHeader); + options.headers.forEach((key, v) { + if (v is Iterable) { + xhr.setRequestHeader(key, v.join(', ')); + } else { + xhr.setRequestHeader(key, v.toString()); + } + }); + + final sendTimeout = options.sendTimeout ?? Duration.zero; + final connectTimeout = options.connectTimeout ?? Duration.zero; + final receiveTimeout = options.receiveTimeout ?? Duration.zero; + final xhrTimeout = (connectTimeout + receiveTimeout).inMilliseconds; + xhr.timeout = xhrTimeout; + + final completer = Completer(); + + xhr.onLoad.first.then((_) { + final Uint8List body = (xhr.response as ByteBuffer).asUint8List(); + completer.complete( + ResponseBody.fromBytes( + body, + xhr.status!, + headers: xhr.responseHeaders.map((k, v) => MapEntry(k, v.split(','))), + statusMessage: xhr.statusText, + isRedirect: xhr.status == 302 || + xhr.status == 301 || + options.uri.toString() != xhr.responseUrl, + ), + ); + }); + + Timer? connectTimeoutTimer; + if (connectTimeout > Duration.zero) { + connectTimeoutTimer = Timer( + connectTimeout, + () { + connectTimeoutTimer = null; + if (completer.isCompleted) { + // connectTimeout is triggered after the fetch has been completed. + return; + } + xhr.abort(); + completer.completeError( + DioException.connectionTimeout( + requestOptions: options, + timeout: connectTimeout, + ), + StackTrace.current, + ); + }, + ); + } + + // This code is structured to call `xhr.upload.onProgress.listen` only when + // absolutely necessary, because registering an xhr upload listener prevents + // the request from being classified as a "simple request" by the CORS spec. + // Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests + // Upload progress events only get triggered if the request body exists, + // so we can check it beforehand. + if (requestStream != null) { + if (connectTimeoutTimer != null) { + xhr.upload.onProgress.listen((event) { + connectTimeoutTimer?.cancel(); + connectTimeoutTimer = null; + }); + } + + if (sendTimeout > Duration.zero) { + final uploadStopwatch = Stopwatch(); + xhr.upload.onProgress.listen((event) { + if (!uploadStopwatch.isRunning) { + uploadStopwatch.start(); + } + final duration = uploadStopwatch.elapsed; + if (duration > sendTimeout) { + uploadStopwatch.stop(); + completer.completeError( + DioException.sendTimeout( + timeout: sendTimeout, + requestOptions: options, + ), + StackTrace.current, + ); + xhr.abort(); + } + }); + } + + final onSendProgress = options.onSendProgress; + if (onSendProgress != null) { + xhr.upload.onProgress.listen((event) { + if (event.loaded != null && event.total != null) { + onSendProgress(event.loaded!, event.total!); + } + }); + } + } + + final receiveStopwatch = Stopwatch(); + Timer? receiveTimer; + + void stopWatchReceiveTimeout() { + receiveTimer?.cancel(); + receiveTimer = null; + receiveStopwatch.stop(); + } + + void watchReceiveTimeout() { + if (receiveTimeout <= Duration.zero) { + return; + } + receiveStopwatch.reset(); + if (!receiveStopwatch.isRunning) { + receiveStopwatch.start(); + } + receiveTimer?.cancel(); + receiveTimer = Timer(receiveTimeout, () { + if (!completer.isCompleted) { + xhr.abort(); + completer.completeError( + DioException.receiveTimeout( + timeout: receiveTimeout, + requestOptions: options, + ), + StackTrace.current, + ); + } + stopWatchReceiveTimeout(); + }); + } + + xhr.onProgress.listen( + (ProgressEvent event) { + if (connectTimeoutTimer != null) { + connectTimeoutTimer!.cancel(); + connectTimeoutTimer = null; + } + watchReceiveTimeout(); + if (options.onReceiveProgress != null && + event.loaded != null && + event.total != null) { + options.onReceiveProgress!(event.loaded!, event.total!); + } + }, + onDone: () => stopWatchReceiveTimeout(), + ); + + xhr.onError.first.then((_) { + connectTimeoutTimer?.cancel(); + // Unfortunately, the underlying XMLHttpRequest API doesn't expose any + // specific information about the error itself. + // See also: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget/onerror + completer.completeError( + DioException.connectionError( + requestOptions: options, + reason: 'The XMLHttpRequest onError callback was called. ' + 'This typically indicates an error on the network layer.', + ), + StackTrace.current, + ); + }); + + xhr.onTimeout.first.then((_) { + final isConnectTimeout = connectTimeoutTimer != null; + if (connectTimeoutTimer != null) { + connectTimeoutTimer?.cancel(); + } + if (!completer.isCompleted) { + if (isConnectTimeout) { + completer.completeError( + DioException.connectionTimeout( + timeout: connectTimeout, + requestOptions: options, + ), + ); + } else { + completer.completeError( + DioException.receiveTimeout( + timeout: Duration(milliseconds: xhrTimeout), + requestOptions: options, + ), + StackTrace.current, + ); + } + } + }); + + cancelFuture?.then((_) { + if (xhr.readyState < HttpRequest.DONE && + xhr.readyState > HttpRequest.UNSENT) { + connectTimeoutTimer?.cancel(); + try { + xhr.abort(); + } catch (_) {} + if (!completer.isCompleted) { + completer.completeError( + DioException.requestCancelled( + requestOptions: options, + reason: 'The XMLHttpRequest was aborted.', + ), + ); + } + } + }); + + if (requestStream != null) { + if (options.method == 'GET') { + warningLog( + 'GET request with a body data are not support on the ' + 'web platform. Use POST/PUT instead.', + StackTrace.current, + ); + } + final completer = Completer(); + final sink = ByteConversionSink.withCallback( + (bytes) => completer.complete( + bytes is Uint8List ? bytes : Uint8List.fromList(bytes), + ), + ); + requestStream.listen( + sink.add, + onError: (Object e, StackTrace s) => completer.completeError(e, s), + onDone: sink.close, + cancelOnError: true, + ); + final bytes = await completer.future; + xhr.send(bytes); + } else { + xhr.send(); + } + return completer.future.whenComplete(() { + xhrs.remove(xhr); + }); + } + + /// Closes the client. + /// + /// This terminates all active requests. + @override + void close({bool force = false}) { + if (force) { + for (final xhr in xhrs) { + xhr.abort(); + } + } + xhrs.clear(); + } +} diff --git a/plugins/web_adapter/lib/src/compute.dart b/plugins/web_adapter/lib/src/compute.dart index c54adbd58..cb783c672 100644 --- a/plugins/web_adapter/lib/src/compute.dart +++ b/plugins/web_adapter/lib/src/compute.dart @@ -1,35 +1,5 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file corresponds to Flutter's -// [`foundation/_isolates_web.dart`](https://github.com/flutter/flutter/blob/stable/packages/flutter/lib/src/foundation/_isolates_web.dart). -// -// Changes are only synced with the `stable` branch. -// -// Last synced commit: -// [978a2e7](https://github.com/flutter/flutter/commit/978a2e7bf6a2ed287130af8dbd94cef019fb7bef) -// -// The changes are currently manually synced. If you noticed that the Flutter's -// original `compute` function (and any of the related files) have changed -// on the `stable` branch and you would like to see those changes in the `compute` package -// please open an [issue](https://github.com/dartsidedev/compute/issues), -// and I'll try my best to "merge". -// -// The file is intentionally not refactored so that it is easier to keep the -// compute package up to date with Flutter's implementation. - -import 'package:dio/src/compute/compute.dart' as c; - -/// The dart:html implementation of [c.compute]. -Future compute( - c.ComputeCallback callback, - Q message, { - String? debugLabel, -}) async { - // To avoid blocking the UI immediately for an expensive function call, we - // pump a single frame to allow the framework to complete the current set - // of work. - await null; - return callback(message); -} +@Deprecated( + 'Import compute_impl.dart instead. ' + 'See https://github.com/dart-lang/sdk/issues/56498', +) +export 'compute_impl.dart'; diff --git a/plugins/web_adapter/lib/src/compute_impl.dart b/plugins/web_adapter/lib/src/compute_impl.dart new file mode 100644 index 000000000..c54adbd58 --- /dev/null +++ b/plugins/web_adapter/lib/src/compute_impl.dart @@ -0,0 +1,35 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file corresponds to Flutter's +// [`foundation/_isolates_web.dart`](https://github.com/flutter/flutter/blob/stable/packages/flutter/lib/src/foundation/_isolates_web.dart). +// +// Changes are only synced with the `stable` branch. +// +// Last synced commit: +// [978a2e7](https://github.com/flutter/flutter/commit/978a2e7bf6a2ed287130af8dbd94cef019fb7bef) +// +// The changes are currently manually synced. If you noticed that the Flutter's +// original `compute` function (and any of the related files) have changed +// on the `stable` branch and you would like to see those changes in the `compute` package +// please open an [issue](https://github.com/dartsidedev/compute/issues), +// and I'll try my best to "merge". +// +// The file is intentionally not refactored so that it is easier to keep the +// compute package up to date with Flutter's implementation. + +import 'package:dio/src/compute/compute.dart' as c; + +/// The dart:html implementation of [c.compute]. +Future compute( + c.ComputeCallback callback, + Q message, { + String? debugLabel, +}) async { + // To avoid blocking the UI immediately for an expensive function call, we + // pump a single frame to allow the framework to complete the current set + // of work. + await null; + return callback(message); +} diff --git a/plugins/web_adapter/lib/src/dio_impl.dart b/plugins/web_adapter/lib/src/dio_impl.dart index 4b797e625..e87abf0cc 100644 --- a/plugins/web_adapter/lib/src/dio_impl.dart +++ b/plugins/web_adapter/lib/src/dio_impl.dart @@ -1,6 +1,6 @@ import 'package:dio/dio.dart'; -import 'adapter.dart'; +import 'adapter_impl.dart'; /// Create the [Dio] instance for Web platforms. Dio createDio([BaseOptions? options]) => DioForBrowser(options); diff --git a/plugins/web_adapter/lib/src/multipart_file.dart b/plugins/web_adapter/lib/src/multipart_file.dart index 64d946803..e1190281b 100644 --- a/plugins/web_adapter/lib/src/multipart_file.dart +++ b/plugins/web_adapter/lib/src/multipart_file.dart @@ -1,21 +1,5 @@ -import 'package:http_parser/http_parser.dart'; - -final _err = UnsupportedError( - 'MultipartFile is only supported where dart:io is available.', -); - -Never multipartFileFromPath( - String filePath, { - String? filename, - MediaType? contentType, - final Map>? headers, -}) => - throw _err; - -Never multipartFileFromPathSync( - String filePath, { - String? filename, - MediaType? contentType, - final Map>? headers, -}) => - throw _err; +@Deprecated( + 'Import multipart_file_impl.dart instead. ' + 'See https://github.com/dart-lang/sdk/issues/56498', +) +export 'multipart_file_impl.dart'; diff --git a/plugins/web_adapter/lib/src/multipart_file_impl.dart b/plugins/web_adapter/lib/src/multipart_file_impl.dart new file mode 100644 index 000000000..64d946803 --- /dev/null +++ b/plugins/web_adapter/lib/src/multipart_file_impl.dart @@ -0,0 +1,21 @@ +import 'package:http_parser/http_parser.dart'; + +final _err = UnsupportedError( + 'MultipartFile is only supported where dart:io is available.', +); + +Never multipartFileFromPath( + String filePath, { + String? filename, + MediaType? contentType, + final Map>? headers, +}) => + throw _err; + +Never multipartFileFromPathSync( + String filePath, { + String? filename, + MediaType? contentType, + final Map>? headers, +}) => + throw _err; diff --git a/plugins/web_adapter/lib/src/progress_stream.dart b/plugins/web_adapter/lib/src/progress_stream.dart index 43a4e6f22..c141d20bd 100644 --- a/plugins/web_adapter/lib/src/progress_stream.dart +++ b/plugins/web_adapter/lib/src/progress_stream.dart @@ -1,40 +1,5 @@ -import 'dart:async'; -import 'dart:typed_data'; - -import 'package:dio/dio.dart'; - -Stream addProgress( - Stream> stream, - int? length, - RequestOptions options, -) { - if (stream is Stream) { - return stream; - } - final streamTransformer = _transform>(stream, length, options); - return stream.transform(streamTransformer); -} - -StreamTransformer _transform>( - Stream stream, - int? length, - RequestOptions options, -) { - return StreamTransformer.fromHandlers( - handleData: (S data, sink) { - final cancelToken = options.cancelToken; - if (cancelToken != null && cancelToken.isCancelled) { - cancelToken.requestOptions = options; - sink - ..addError(cancelToken.cancelError!) - ..close(); - } else { - if (data is Uint8List) { - sink.add(data); - } else { - sink.add(Uint8List.fromList(data)); - } - } - }, - ); -} +@Deprecated( + 'Import progress_stream_impl.dart instead. ' + 'See https://github.com/dart-lang/sdk/issues/56498', +) +export 'progress_stream_impl.dart'; diff --git a/plugins/web_adapter/lib/src/progress_stream_impl.dart b/plugins/web_adapter/lib/src/progress_stream_impl.dart new file mode 100644 index 000000000..43a4e6f22 --- /dev/null +++ b/plugins/web_adapter/lib/src/progress_stream_impl.dart @@ -0,0 +1,40 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:dio/dio.dart'; + +Stream addProgress( + Stream> stream, + int? length, + RequestOptions options, +) { + if (stream is Stream) { + return stream; + } + final streamTransformer = _transform>(stream, length, options); + return stream.transform(streamTransformer); +} + +StreamTransformer _transform>( + Stream stream, + int? length, + RequestOptions options, +) { + return StreamTransformer.fromHandlers( + handleData: (S data, sink) { + final cancelToken = options.cancelToken; + if (cancelToken != null && cancelToken.isCancelled) { + cancelToken.requestOptions = options; + sink + ..addError(cancelToken.cancelError!) + ..close(); + } else { + if (data is Uint8List) { + sink.add(data); + } else { + sink.add(Uint8List.fromList(data)); + } + } + }, + ); +} diff --git a/plugins/web_adapter/pubspec.yaml b/plugins/web_adapter/pubspec.yaml index 831562443..2da3c490a 100644 --- a/plugins/web_adapter/pubspec.yaml +++ b/plugins/web_adapter/pubspec.yaml @@ -1,5 +1,5 @@ name: dio_web_adapter -version: 1.1.0 +version: 1.1.1 description: An adapter that supports Dio on Web. topics: