import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:image_picker/image_picker.dart'; import '../core/network/api_exception.dart'; import '../services/upload_service.dart'; /// 上传发布流程步骤:选视频 → 填信息 → 发布中 → 完成 enum UploadStep { pick, edit, publishing, done } /// 上传发布状态(《03-接口文档》5.5/5.6 三步链路) class UploadState { const UploadState({ this.step = UploadStep.pick, this.file, this.fileSize = 0, this.progress = 0, this.result, this.error = '', }); final UploadStep step; final XFile? file; // 已选择的视频 final int fileSize; // 字节 final int progress; // 上传进度 0-100 final PublishResult? result; final String error; // 发布失败文案(停留在 edit 步骤展示) bool get publishing => step == UploadStep.publishing; UploadState copyWith({ UploadStep? step, XFile? file, int? fileSize, int? progress, PublishResult? result, String? error, }) => UploadState( step: step ?? this.step, file: file ?? this.file, fileSize: fileSize ?? this.fileSize, progress: progress ?? this.progress, result: result ?? this.result, error: error ?? this.error, ); } class UploadNotifier extends StateNotifier { UploadNotifier() : super(const UploadState()); final _picker = ImagePicker(); /// 从相册选择视频 → 进入填信息步骤 Future pickVideo() async { final file = await _picker.pickVideo(source: ImageSource.gallery); if (file == null) return; final size = await file.length(); state = UploadState(step: UploadStep.edit, file: file, fileSize: size); } /// 重新选择(回到选视频步骤) void reset() => state = const UploadState(); /// 发布:获取凭证 → 上传文件(进度) → 创建视频 Future submit({ required String title, String description = '', required int categoryId, List tags = const [], }) async { final file = state.file; if (file == null || state.publishing) return; state = state.copyWith(step: UploadStep.publishing, progress: 0, error: ''); try { final token = await UploadService.fetchUploadToken( fileName: file.name, fileSize: state.fileSize, ); await UploadService.uploadFile( objectKey: token.objectKey, filePath: file.path, fileName: file.name, onProgress: (sent, total) { if (total > 0) { state = state.copyWith(progress: (sent * 100) ~/ total); } }, ); final result = await UploadService.publish( objectKey: token.objectKey, title: title, description: description, categoryId: categoryId, tags: tags, ); state = state.copyWith(step: UploadStep.done, result: result); } on ApiException catch (e) { // 失败回到表单步骤,保留已填内容,展示服务端文案 state = state.copyWith(step: UploadStep.edit, error: e.message); } catch (_) { state = state.copyWith(step: UploadStep.edit, error: '网络异常,请稍后重试'); } } } /// 上传发布(autoDispose:离开页面即重置流程) final uploadProvider = StateNotifierProvider.autoDispose( (ref) => UploadNotifier(), ); /// 分类列表(发布表单用) final uploadCategoriesProvider = FutureProvider.autoDispose>( (ref) => UploadService.fetchCategories(), );