import 'package:dio/dio.dart'; /// Lightweight cancel handle around a single `Dio.download` call. The download /// itself is started by [run]; the handle returns synchronously so callers can /// install it into shared state before the first progress event can fire. class FileDownloader { FileDownloader(); final CancelToken _cancelToken = CancelToken(); bool _cancelled = false; bool get isCancelled => _cancelled; void cancel() { if (_cancelled) return; _cancelled = true; _cancelToken.cancel('user cancelled'); } /// Kicks off the download. Returns immediately; the download progresses in /// the background and events are delivered via callbacks. Callbacks are not /// invoked once [cancel] has been called. void run({ required Dio client, required String url, required String savePath, required void Function(double percent) onProgress, required void Function() onDone, required void Function(Object error) onError, }) { client.download( url, savePath, cancelToken: _cancelToken, onReceiveProgress: (received, total) { if (_cancelled || total <= 0) return; onProgress((received / total) * 100); }, ).then((_) { if (_cancelled) return; onDone(); }).catchError((Object error) { if (_cancelled) return; onError(error); }).ignore(); } }