import 'dart:async'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import '../../../core/utils/logger.dart'; /// 分享接收数据源 - 处理系统分享接收功能 /// 负责接收来自其他应用的图片分享,支持单张和多张图片 /// 优化批量处理和性能,支持大量图片分享场景 class ShareIntentDataSource { /// 分享接收流控制器 - 管理分享数据的异步流 final StreamController> _sharingStreamController = StreamController>.broadcast(); /// 当前接收到的分享文件列表 - 临时存储接收到的文件 List _currentSharedFiles = []; /// 分享接收流 - 外部订阅分享事件 Stream> get sharingStream => _sharingStreamController.stream; /// 是否正在处理分享 - 防止重复处理 bool _isProcessingShare = false; /// 批量处理配置 - 控制批量处理的参数 static const int _maxBatchSize = 20; // 最大批量处理数量 static const Duration _batchProcessingDelay = Duration(milliseconds: 100); // 批量处理延迟 /// 分享文件队列 - 用于批量处理分享文件 final List _shareQueue = []; /// 批量处理定时器 - 控制批量处理的时机 Timer? _batchProcessingTimer; /// 初始化分享接收 - 设置分享监听器 /// 在应用启动时调用,监听系统分享事件 Future initShareReceiving() async { try { Logger.info('初始化分享接收功能...'); // 监听前台分享接收(应用运行时) ReceiveSharingIntent.instance.getMediaStream().listen( _handleSharedMedia, onError: _handleShareError, ); // 获取初始分享数据(应用从分享启动时) final initialSharedMedia = await ReceiveSharingIntent.instance.getInitialMedia(); if (initialSharedMedia.isNotEmpty) { Logger.info('检测到应用启动时的分享数据: ${initialSharedMedia.length} 个文件'); _handleSharedMedia(initialSharedMedia); } Logger.info('分享接收功能初始化完成'); } catch (e) { Logger.error('分享接收初始化失败', error: e); throw ShareIntentException('初始化分享接收功能失败: $e'); } } /// 处理接收到的媒体文件 - 验证并处理分享的图片文件 /// 支持多张图片的批量处理,优化性能和用户体验 /// [sharedFiles] 接收到的分享文件列表 void _handleSharedMedia(List sharedFiles) { if (_isProcessingShare) { Logger.warning('正在处理其他分享,将新文件加入队列'); _addToShareQueue(sharedFiles); return; } try { _isProcessingShare = true; Logger.info('接收到分享文件: ${sharedFiles.length} 个'); // 大量文件分批处理,避免UI卡顿 if (sharedFiles.length > _maxBatchSize) { Logger.info('文件数量超过$_maxBatchSize个,启用分批处理'); _processShareFilesInBatches(sharedFiles); return; } // 普通数量的文件直接处理 _processShareFiles(sharedFiles); } catch (e) { Logger.error('处理分享文件失败', error: e); _sharingStreamController.addError( ShareIntentException('处理分享文件失败: $e'), ); } finally { _isProcessingShare = false; // 处理队列中的剩余文件 _processShareQueue(); } } /// 处理分享文件 - 处理普通数量的分享文件 /// [sharedFiles] 要处理的分享文件列表 void _processShareFiles(List sharedFiles) { // 验证分享文件 final validFiles = _validateSharedFiles(sharedFiles); if (validFiles.isEmpty) { Logger.warning('没有有效的图片文件'); _sharingStreamController.addError( ShareIntentException('未找到有效的图片文件'), ); return; } // 更新当前分享文件 _currentSharedFiles = validFiles; // 记录详细的文件信息 Logger.info('处理文件详情:'); Logger.info(' 有效文件数: ${validFiles.length}'); Logger.info(' 总文件数: ${sharedFiles.length}'); Logger.info(' 跳过的文件数: ${sharedFiles.length - validFiles.length}'); for (final file in validFiles) { Logger.info('分享文件:'); Logger.info(' 路径: ${file.path}'); Logger.info(' 类型: ${file.type}'); if (file.thumbnail != null) { Logger.info(' 缩略图: ${file.thumbnail}'); } if (file.duration != null) { Logger.info(' 持续时间: ${file.duration}'); } } // 通知监听器新的分享数据 _sharingStreamController.add(validFiles); Logger.info('分享文件处理完成,已通知监听器'); } /// 分批处理分享文件 - 处理大量分享文件 /// [sharedFiles] 要分批处理的分享文件列表 void _processShareFilesInBatches(List sharedFiles) { Logger.info('开始分批处理${sharedFiles.length}个分享文件'); final batches = _createBatches(sharedFiles, _maxBatchSize); Logger.info('创建${batches.length}个批次,每批最多$_maxBatchSize个文件'); // 处理第一批文件(立即处理) if (batches.isNotEmpty) { _processShareFiles(batches.first); } // 将其余批次加入队列,稍后处理 if (batches.length > 1) { for (int i = 1; i < batches.length; i++) { _addToShareQueue(batches[i]); } Logger.info('已将${batches.length - 1}个批次加入处理队列'); } } /// 创建文件批次 - 将文件列表分成指定大小的批次 /// [files] 文件列表 /// [batchSize] 每批的大小 /// 返回批次列表 List> _createBatches(List files, int batchSize) { final batches = >[]; for (int i = 0; i < files.length; i += batchSize) { final end = (i + batchSize < files.length) ? i + batchSize : files.length; batches.add(files.sublist(i, end)); } return batches; } /// 添加文件到分享队列 - 将文件加入待处理队列 /// [files] 要加入队列的文件列表 void _addToShareQueue(List files) { Logger.info('添加${files.length}个文件到分享队列'); _shareQueue.addAll(files); // 设置批量处理定时器 _scheduleBatchProcessing(); } /// 调度批量处理 - 设置定时器处理队列中的文件 void _scheduleBatchProcessing() { // 取消现有的定时器 _batchProcessingTimer?.cancel(); // 设置新的定时器 _batchProcessingTimer = Timer(_batchProcessingDelay, () { _processShareQueue(); }); Logger.info('已调度批量处理定时器'); } /// 处理分享队列 - 处理队列中的待处理文件 void _processShareQueue() { if (_shareQueue.isEmpty) { Logger.debug('分享队列为空,无需处理'); return; } if (_isProcessingShare) { Logger.debug('正在处理其他分享,稍后重试'); _scheduleBatchProcessing(); // 重新调度 return; } try { Logger.info('开始处理分享队列,剩余${_shareQueue.length}个文件'); // 从队列中取出最多maxBatchSize个文件 final batchSize = _shareQueue.length > _maxBatchSize ? _maxBatchSize : _shareQueue.length; final batch = _shareQueue.sublist(0, batchSize); _shareQueue.removeRange(0, batchSize); // 处理这批文件 _processShareFiles(batch); // 如果队列中还有文件,继续调度处理 if (_shareQueue.isNotEmpty) { Logger.info('队列中还有${_shareQueue.length}个文件,继续调度'); _scheduleBatchProcessing(); } } catch (e) { Logger.error('处理分享队列失败', error: e); } } /// 验证分享文件 - 过滤有效的图片文件 /// [files] 所有接收到的文件 /// 返回有效的图片文件列表 List _validateSharedFiles(List files) { final validFiles = []; for (final file in files) { try { // 检查文件是否存在 if (!file.path.startsWith('/')) { Logger.warning('文件路径无效: ${file.path}'); continue; } // 检查文件类型(只处理图片) if (file.type != SharedMediaType.image) { Logger.warning('跳过非图片文件: ${file.type}'); continue; } // 检查文件扩展名 final path = file.path.toLowerCase(); final validExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.heic', '.heif']; final hasValidExtension = validExtensions.any((ext) => path.endsWith(ext)); if (!hasValidExtension) { Logger.warning('文件扩展名不支持: ${file.path}'); continue; } validFiles.add(file); Logger.info('验证通过的文件: ${file.path}'); } catch (e) { Logger.error('验证文件失败: ${file.path}', error: e); } } return validFiles; } /// 处理分享错误 - 统一处理分享过程中的错误 /// [error] 分享错误信息 void _handleShareError(dynamic error) { Logger.error('分享接收错误', error: error); _sharingStreamController.addError( ShareIntentException('接收分享失败: $error'), ); } /// 获取当前分享文件 - 获取最近接收到的分享文件 /// 返回当前分享文件列表,可能为空 List getCurrentSharedFiles() { return List.from(_currentSharedFiles); } /// 清除当前分享数据 - 清理已处理的分享文件 /// 通常在分享处理完成后调用 void clearCurrentShare() { Logger.info('清除当前分享数据'); _currentSharedFiles.clear(); } /// 重置分享接收状态 - 重置所有分享相关状态 /// 在错误恢复或重新初始化时调用 void reset() { Logger.info('重置分享接收状态'); _currentSharedFiles.clear(); _isProcessingShare = false; } /// 检查是否有待处理的分享 - 判断是否有未处理的分享文件 /// 返回是否有待处理的分享 bool hasPendingShare() { return _currentSharedFiles.isNotEmpty; } /// 获取分享文件数量 - 获取当前分享文件的数量 /// 返回分享文件数量 int getShareFileCount() { return _currentSharedFiles.length; } /// 释放资源 - 清理分享接收相关资源 /// 在应用退出时调用 Future dispose() async { Logger.info('释放分享接收资源'); // 取消批量处理定时器 _batchProcessingTimer?.cancel(); _batchProcessingTimer = null; // 清空分享队列 _shareQueue.clear(); // 关闭分享流控制器 await _sharingStreamController.close(); // 清空当前分享文件 _currentSharedFiles.clear(); Logger.info('分享接收资源已释放'); } } /// 分享接收异常 - 分享接收过程中的自定义异常 class ShareIntentException implements Exception { /// 异常消息 final String message; /// 异常原因(可选) final dynamic cause; ShareIntentException(this.message, {this.cause}); @override String toString() { return cause != null ? '$message: $cause' : message; } }