import 'dart:async'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import '../../domain/repositories/share_repository.dart'; import '../../data/datasources/share/share_intent_datasource.dart'; import '../../data/repositories/share_repository_impl.dart'; import '../../core/utils/logger.dart'; /// 分享状态类 - 管理分享相关的UI状态 /// 包含分享文件列表、处理状态、错误信息等 class ShareState { /// 待处理的分享文件列表 final List pendingFiles; /// 是否正在处理分享 final bool isProcessing; /// 处理错误信息 final String? error; /// 是否显示分享界面 final bool showShareUI; /// 当前处理的批次索引 final int currentBatchIndex; /// 总批次数 final int totalBatches; /// 是否正在批量处理 final bool isBatchProcessing; /// 是否有待处理的分享 bool get hasPendingShare => pendingFiles.isNotEmpty; /// 构造函数 - 创建分享状态实例 const ShareState({ this.pendingFiles = const [], this.isProcessing = false, this.error, this.showShareUI = false, this.currentBatchIndex = 0, this.totalBatches = 0, this.isBatchProcessing = false, }); /// 复制构造函数 - 创建状态副本并支持字段更新 ShareState copyWith({ List? pendingFiles, bool? isProcessing, String? error, bool? showShareUI, int? currentBatchIndex, int? totalBatches, bool? isBatchProcessing, }) { return ShareState( pendingFiles: pendingFiles ?? this.pendingFiles, isProcessing: isProcessing ?? this.isProcessing, error: error, showShareUI: showShareUI ?? this.showShareUI, currentBatchIndex: currentBatchIndex ?? this.currentBatchIndex, totalBatches: totalBatches ?? this.totalBatches, isBatchProcessing: isBatchProcessing ?? this.isBatchProcessing, ); } } /// 分享状态Notifier - 管理分享状态和业务逻辑 class ShareNotifier extends StateNotifier { /// 分享仓库 - 处理分享相关的业务逻辑 final ShareRepository _shareRepository; /// 分享数据流订阅 - 监听分享数据变化 StreamSubscription>? _shareSubscription; ShareNotifier(this._shareRepository) : super(const ShareState()) { _initializeShareListening(); } /// 初始化分享监听 - 设置分享数据流监听 void _initializeShareListening() { try { Logger.info('初始化分享状态监听...'); // 监听分享数据流 _shareSubscription = _shareRepository.sharingStream?.listen( handleSharedFiles, onError: (error) { Logger.error('分享数据流错误', error: error); state = state.copyWith(error: '分享接收错误: $error'); }, ); // 检查当前是否有待处理的分享 _checkPendingShares(); Logger.info('分享状态监听初始化完成'); } catch (e) { Logger.error('初始化分享监听失败', error: e); state = state.copyWith(error: '初始化分享功能失败: $e'); } } /// 检查待处理的分享 - 检查当前是否有待处理的分享文件 void _checkPendingShares() { try { final pendingFiles = _shareRepository.getPendingShareFiles(); final hasShares = _shareRepository.hasPendingShare(); Logger.info('检查待处理分享: ${pendingFiles.length} 个文件'); if (hasShares && pendingFiles.isNotEmpty) { state = state.copyWith( pendingFiles: pendingFiles, showShareUI: true, error: null, ); Logger.info('发现待处理分享,显示分享界面'); } else { state = state.copyWith( pendingFiles: [], showShareUI: false, error: null, ); } } catch (e) { Logger.error('检查待处理分享失败', error: e); state = state.copyWith(error: '检查分享状态失败: $e'); } } /// 处理接收到的分享文件 - 处理新的分享数据 /// [sharedFiles] 接收到的分享文件列表 Future handleSharedFiles(List sharedFiles) async { if (sharedFiles.isEmpty) { Logger.warning('接收到的分享文件列表为空'); return; } try { Logger.info('处理新的分享文件: ${sharedFiles.length} 个'); state = state.copyWith( pendingFiles: sharedFiles, showShareUI: true, isProcessing: false, error: null, ); // 记录详细的文件信息 for (final file in sharedFiles) { Logger.info('分享文件: ${file.path}, 类型: ${file.type}'); } } catch (e) { Logger.error('处理分享文件失败', error: e); state = state.copyWith( error: '处理分享文件失败: $e', isProcessing: false, ); } } /// 开始保存分享图片 - 开始批量保存分享图片,支持大量文件分批保存 /// [folderId] 目标文件夹ID,可为空 /// [tags] 要添加的标签列表,可为空 /// [note] 备注内容,可为空 Future startSavingSharedImages({ String? folderId, List? tags, String? note, }) async { if (state.pendingFiles.isEmpty) { Logger.warning('没有待保存的分享图片'); return; } try { Logger.info('开始保存分享图片,共${state.pendingFiles.length}个文件'); // 初始化批量处理状态 final totalFiles = state.pendingFiles.length; const batchSize = 10; // 每批处理10个文件 final totalBatches = (totalFiles / batchSize).ceil(); state = state.copyWith( isProcessing: true, isBatchProcessing: totalBatches > 1, totalBatches: totalBatches, currentBatchIndex: 0, error: null, ); if (totalBatches > 1) { Logger.info('启用批量保存模式,共$totalBatches批,每批$batchSize个文件'); await _batchSaveSharedImages(folderId, tags, note, batchSize); } else { Logger.info('普通保存模式,直接处理$totalFiles个文件'); await _simulateSaveProcess(folderId, tags, note); } // 保存完成后清除分享数据 _shareRepository.clearCurrentShare(); state = state.copyWith( pendingFiles: [], isProcessing: false, isBatchProcessing: false, showShareUI: false, currentBatchIndex: 0, totalBatches: 0, error: null, ); Logger.info('分享图片保存完成'); } catch (e) { Logger.error('保存分享图片失败', error: e); state = state.copyWith( isProcessing: false, isBatchProcessing: false, error: '保存图片失败: $e', ); } } /// 批量保存分享图片 - 分批处理大量分享图片 /// [folderId] 目标文件夹ID /// [tags] 标签列表 /// [note] 备注内容 /// [batchSize] 每批处理的大小 Future _batchSaveSharedImages( String? folderId, List? tags, String? note, int batchSize, ) async { final batches = _createBatches(state.pendingFiles, batchSize); Logger.info('开始分批保存,共${batches.length}批'); for (int i = 0; i < batches.length; i++) { final batch = batches[i]; final batchNumber = i + 1; Logger.info('处理第$batchNumber批,共${batch.length}个文件'); // 更新当前批次状态 state = state.copyWith(currentBatchIndex: batchNumber); // 模拟处理当前批次 await _simulateBatchSaveProcess(batch, folderId, tags, note, batchNumber); // 批次间短暂延迟,避免系统过载 if (i < batches.length - 1) { await Future.delayed(const Duration(milliseconds: 200)); } } Logger.info('批量保存完成'); } /// 创建文件批次 - 将文件列表分成指定大小的批次 /// [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; } /// 模拟批量保存过程 - 处理单个批次的保存 /// [batch] 当前批次的文件 /// [folderId] 目标文件夹ID /// [tags] 标签列表 /// [note] 备注内容 /// [batchNumber] 批次编号 Future _simulateBatchSaveProcess( List batch, String? folderId, List? tags, String? note, int batchNumber, ) async { // 模拟保存过程,实际实现中会调用真实的保存逻辑 await Future.delayed(const Duration(seconds: 1)); Logger.info('第$batchNumber批次保存完成,处理了${batch.length}个文件'); } /// 模拟保存过程 - 临时模拟保存过程(后续替换为真实逻辑) /// [folderId] 目标文件夹ID /// [tags] 标签列表 /// [note] 备注内容 Future _simulateSaveProcess( String? folderId, List? tags, String? note, ) async { // 模拟保存过程 await Future.delayed(const Duration(seconds: 2)); Logger.info('模拟保存完成 - 文件夹: $folderId, 标签: $tags, 备注: $note'); } /// 取消分享保存 - 取消当前的分享保存操作 void cancelShareSaving() { Logger.info('取消分享保存'); // 清除当前分享数据 _shareRepository.clearCurrentShare(); state = const ShareState( pendingFiles: [], isProcessing: false, showShareUI: false, error: null, ); } /// 关闭分享界面 - 关闭分享处理界面 void closeShareUI() { Logger.info('关闭分享界面'); state = state.copyWith( showShareUI: false, error: null, ); } /// 清除错误状态 - 清除当前的错误信息 void clearError() { if (state.error != null) { state = state.copyWith(error: null); } } /// 刷新分享状态 - 重新检查分享状态 void refreshShareStatus() { Logger.info('刷新分享状态'); _checkPendingShares(); } /// 清除待处理文件 - 清空当前待处理的分享文件 void clearPendingFiles() { Logger.info('清除待处理分享文件'); state = state.copyWith( pendingFiles: [], showShareUI: false, isProcessing: false, error: null, ); // 同时清除仓库中的待处理文件 _shareRepository.clearCurrentShare(); } /// 获取分享文件数量 - 获取当前待处理的分享文件数量 int getShareFileCount() { return _shareRepository.getShareFileCount(); } /// 批量保存图片 - 保存多张分享的图片 /// [sharedFiles] 分享的媒体文件列表 /// [folderId] 目标文件夹ID /// [tags] 标签列表 /// [note] 备注内容 Future saveBatchImages({ required List sharedFiles, required String folderId, required List tags, String? note, }) async { try { Logger.info('开始批量保存${sharedFiles.length}张图片'); // 更新状态为处理中 state = state.copyWith(isProcessing: true, error: null); // 模拟保存过程,实际实现中会调用真实的保存逻辑 await _simulateSaveProcess(folderId, tags, note); // 保存完成 state = state.copyWith(isProcessing: false); Logger.info('批量保存完成'); } catch (e) { Logger.error('批量保存失败', error: e); state = state.copyWith( isProcessing: false, error: '保存失败: $e', ); rethrow; } } /// 单张保存图片 - 保存单张分享的图片 /// [sharedFile] 分享的媒体文件 /// [folderId] 目标文件夹ID /// [tags] 标签列表 /// [note] 备注内容 Future saveSingleImage({ required SharedMediaFile sharedFile, required String folderId, required List tags, String? note, }) async { try { Logger.info('开始单张保存图片: ${sharedFile.path}'); // 更新状态为处理中 state = state.copyWith(isProcessing: true, error: null); // 模拟保存过程,实际实现中会调用真实的保存逻辑 await _simulateSaveProcess(folderId, tags, note); // 保存完成 state = state.copyWith(isProcessing: false); Logger.info('单张保存完成'); } catch (e) { Logger.error('单张保存失败', error: e); state = state.copyWith( isProcessing: false, error: '保存失败: $e', ); rethrow; } } /// 释放资源 - 清理分享相关资源 @override Future dispose() async { Logger.info('释放分享状态资源'); // 调用父类的dispose方法(StateNotifier的dispose不是异步的) super.dispose(); // 取消分享数据流订阅 await _shareSubscription?.cancel(); _shareSubscription = null; // 释放分享仓库 await _shareRepository.dispose(); } } /// 分享数据源Provider - 提供分享数据源实例 final shareDataSourceProvider = Provider((ref) { return ShareIntentDataSource(); }); /// 图片工具Provider - 提供图片工具实例 /// ImageUtils是静态工具类,不需要实例化,直接提供工具引用 final imageUtilsProvider = Provider((ref) { return Object(); // 占位Provider,实际使用ImageUtils静态方法 }); /// 文件工具Provider - 提供文件工具实例 /// FileUtils是静态工具类,不需要实例化,直接提供工具引用 final fileUtilsProvider = Provider((ref) { return Object(); // 占位Provider,实际使用FileUtils静态方法 }); /// 分享仓库Provider - 提供分享仓库实例 final shareRepositoryProvider = Provider((ref) { final shareDataSource = ref.read(shareDataSourceProvider); // ImageUtils和FileUtils是静态工具类,直接传入null占位 return ShareRepositoryImpl( shareDataSource: shareDataSource, ); }); /// 分享状态Provider - 管理分享相关的UI状态 final shareProvider = StateNotifierProvider((ref) { final shareRepository = ref.read(shareRepositoryProvider); return ShareNotifier(shareRepository); });