import 'dart:async'; import 'package:flutter/widgets.dart'; import 'video_batch_upload_config.dart'; import 'video_batch_upload_panel.dart'; import 'video_batch_upload_queue.dart'; import 'video_batch_upload_task.dart'; typedef VideoBatchUploadCallback = FutureOr Function(); class VideoBatchUploader { VideoBatchUploader({ required BuildContext? Function() contextProvider, required VideoBatchUploadUploadTask uploadTask, required VideoBatchUploadSaveTask saveTask, VideoBatchUploadAssetType assetType = VideoBatchUploadAssetType.video, VoidCallback? onChanged, VideoBatchUploadCallback? onCompleted, int? maxAssets, int? maxConcurrent, }) : _contextProvider = contextProvider, _onChanged = onChanged { queue = VideoBatchUploadQueue( contextProvider: contextProvider, uploadTask: uploadTask, saveTask: saveTask, onChanged: _handleChanged, assetType: assetType, onCompleted: onCompleted, maxAssets: maxAssets ?? VideoBatchUploadConfig.maxAssets, maxConcurrent: maxConcurrent ?? VideoBatchUploadConfig.maxConcurrent, ); } final BuildContext? Function() _contextProvider; final VoidCallback? _onChanged; late final VideoBatchUploadQueue queue; OverlayEntry? _overlayEntry; bool get hasActiveUploads => queue.hasActiveUploads; Future start() async { await queue.pickAndStart(); } void requestExit({required VoidCallback onExit}) { queue.requestExit(onExit: onExit); } void clear() { queue.clear(); _syncOverlay(); } void dispose() { queue.dispose(); _removeOverlay(); } void _handleChanged() { _syncOverlay(); _overlayEntry?.markNeedsBuild(); _onChanged?.call(); } void _syncOverlay() { if (queue.hasTasks) { _insertOverlayIfNeeded(); return; } _removeOverlay(); } void _insertOverlayIfNeeded() { if (_overlayEntry != null) { return; } final BuildContext? context = _contextProvider(); if (context == null || !context.mounted) { return; } final OverlayState? overlay = Overlay.maybeOf(context); if (overlay == null) { return; } _overlayEntry = OverlayEntry( builder: (_) => VideoBatchUploadPanel(queue: queue), ); overlay.insert(_overlayEntry!); } void _removeOverlay() { _overlayEntry?.remove(); _overlayEntry = null; } }