import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import '../providers/share_provider.dart'; import 'custom_button.dart'; import 'image_grid_preview.dart'; import 'folder_selector.dart'; import 'tag_selector.dart'; /// 保存对话框 - 处理分享图片的保存界面 /// 支持批量保存、文件夹选择、标签添加等功能 class SaveDialog extends ConsumerStatefulWidget { /// 分享接收的媒体文件列表 final List sharedFiles; /// 对话框关闭回调 final VoidCallback onClose; const SaveDialog({ Key? key, required this.sharedFiles, required this.onClose, }) : super(key: key); @override ConsumerState createState() => _SaveDialogState(); } class _SaveDialogState extends ConsumerState { /// 当前选中的文件夹ID String? selectedFolderId; /// 当前输入的标签列表 final List tags = []; /// 标签输入控制器 final TextEditingController tagController = TextEditingController(); /// 备注输入控制器 final TextEditingController noteController = TextEditingController(); /// 是否为批量保存模式 bool isBatchMode = true; /// 当前编辑的图片索引 int currentEditingIndex = 0; @override void dispose() { tagController.dispose(); noteController.dispose(); super.dispose(); } /// 切换批量/单张编辑模式 void toggleEditMode() { setState(() { isBatchMode = !isBatchMode; currentEditingIndex = 0; }); } /// 切换到下一张图片编辑 void nextImage() { if (currentEditingIndex < widget.sharedFiles.length - 1) { setState(() { currentEditingIndex++; }); } } /// 切换到上一张图片编辑 void previousImage() { if (currentEditingIndex > 0) { setState(() { currentEditingIndex--; }); } } /// 添加标签 void addTag(String tag) { if (tag.isNotEmpty && !tags.contains(tag)) { setState(() { tags.add(tag); }); tagController.clear(); } } /// 移除标签 void removeTag(String tag) { setState(() { tags.remove(tag); }); } /// 执行保存操作 Future performSave() async { if (selectedFolderId == null) { _showErrorSnackBar('请选择保存文件夹'); return; } // 显示保存进度 showDialog( context: context, barrierDismissible: false, builder: (context) => const Dialog( child: Padding( padding: EdgeInsets.all(24.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator(), SizedBox(height: 16), Text('正在保存图片...'), ], ), ), ), ); try { if (isBatchMode) { // 批量保存模式 await ref.read(shareProvider.notifier).saveBatchImages( sharedFiles: widget.sharedFiles, folderId: selectedFolderId!, tags: tags, note: noteController.text.trim(), ); } else { // 单张保存模式 await ref.read(shareProvider.notifier).saveSingleImage( sharedFile: widget.sharedFiles[currentEditingIndex], folderId: selectedFolderId!, tags: tags, note: noteController.text.trim(), ); } // 关闭进度对话框 Navigator.of(context).pop(); // 显示成功消息 _showSuccessSnackBar('图片保存成功!'); // 关闭保存对话框 widget.onClose(); } catch (e) { // 关闭进度对话框 Navigator.of(context).pop(); // 显示错误消息 _showErrorSnackBar('保存失败:${e.toString()}'); } } /// 显示错误提示 void _showErrorSnackBar(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), backgroundColor: Theme.of(context).colorScheme.error, ), ); } /// 显示成功提示 void _showSuccessSnackBar(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), backgroundColor: Theme.of(context).colorScheme.primary, ), ); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final colorScheme = theme.colorScheme; return Dialog( backgroundColor: Colors.transparent, child: Container( width: MediaQuery.of(context).size.width * 0.9, height: MediaQuery.of(context).size.height * 0.8, decoration: BoxDecoration( color: theme.scaffoldBackgroundColor.withOpacity(0.95), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 8), ), ], ), child: Column( children: [ // 标题栏 _buildHeader(colorScheme), // 内容区域 Expanded( child: Row( children: [ // 左侧图片预览区域 Expanded( flex: 2, child: _buildImagePreviewArea(), ), // 分隔线 VerticalDivider( color: colorScheme.outline.withOpacity(0.2), thickness: 1, ), // 右侧设置区域 Expanded( flex: 1, child: _buildSettingsArea(colorScheme), ), ], ), ), // 底部操作栏 _buildFooter(colorScheme), ], ), ), ); } /// 构建标题栏 Widget _buildHeader(ColorScheme colorScheme) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: colorScheme.surface, borderRadius: const BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), ), ), child: Row( children: [ Text( '保存灵感', style: Theme.of(context).textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, ), ), const Spacer(), // 批量/单张切换按钮 if (widget.sharedFiles.length > 1) Padding( padding: const EdgeInsets.only(right: 8), child: Row( mainAxisSize: MainAxisSize.min, children: [ FilterChip( label: const Text('批量'), selected: isBatchMode, onSelected: (selected) { if (selected) toggleEditMode(); }, avatar: const Icon(Icons.photo_library), ), const SizedBox(width: 8), FilterChip( label: const Text('单张'), selected: !isBatchMode, onSelected: (selected) { if (selected) toggleEditMode(); }, avatar: const Icon(Icons.photo), ), ], ), ), // 关闭按钮 IconButton( onPressed: widget.onClose, icon: const Icon(Icons.close), tooltip: '关闭', ), ], ), ); } /// 构建图片预览区域 Widget _buildImagePreviewArea() { if (isBatchMode) { // 批量模式:使用图片网格预览组件 return ImageGridPreview( images: widget.sharedFiles, selectedIndices: [], // 批量模式下显示所有图片 onSelectionChanged: (index, selected) { // 批量模式下不处理选择 }, showSelection: false, // 批量模式下不显示选择框 crossAxisCount: 2, spacing: 8.0, padding: const EdgeInsets.all(16), ); } else { // 单张模式:显示单张图片和切换控制 return Column( children: [ // 图片显示区域 Expanded( child: Padding( padding: const EdgeInsets.all(16), child: ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.file( File(widget.sharedFiles[currentEditingIndex].path), fit: BoxFit.contain, errorBuilder: (context, error, stackTrace) { return Container( color: Colors.grey[300], child: const Icon( Icons.broken_image, color: Colors.grey, size: 64, ), ); }, ), ), ), ), // 图片切换控制 if (widget.sharedFiles.length > 1) Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( onPressed: currentEditingIndex > 0 ? previousImage : null, icon: const Icon(Icons.keyboard_arrow_left), ), Text( '${currentEditingIndex + 1} / ${widget.sharedFiles.length}', style: Theme.of(context).textTheme.bodyMedium, ), IconButton( onPressed: currentEditingIndex < widget.sharedFiles.length - 1 ? nextImage : null, icon: const Icon(Icons.keyboard_arrow_right), ), ], ), ), ], ); } } /// 构建设置区域 Widget _buildSettingsArea(ColorScheme colorScheme) { return Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 文件夹选择 _buildFolderSelector(colorScheme), const SizedBox(height: 16), // 标签输入 _buildTagInput(colorScheme), const SizedBox(height: 16), // 备注输入 _buildNoteInput(colorScheme), ], ), ); } /// 构建文件夹选择器 Widget _buildFolderSelector(ColorScheme colorScheme) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '选择文件夹', style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), GestureDetector( onTap: _showFolderSelector, child: Container( width: double.infinity, padding: const EdgeInsets.all(12), decoration: BoxDecoration( border: Border.all(color: colorScheme.outline.withOpacity(0.3)), borderRadius: BorderRadius.circular(8), color: colorScheme.surface, ), child: Row( children: [ Icon( selectedFolderId != null ? Icons.folder : Icons.folder_outlined, color: colorScheme.primary, ), const SizedBox(width: 8), Expanded( child: Text( selectedFolderId != null ? '已选择文件夹' : '点击选择文件夹', style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: selectedFolderId != null ? colorScheme.onSurface : colorScheme.onSurface.withOpacity(0.6), ), ), ), const Icon(Icons.arrow_drop_down), ], ), ), ), ], ); } /// 构建标签输入 Widget _buildTagInput(ColorScheme colorScheme) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '添加标签', style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), TagSelector( selectedTags: tags, onTagsChanged: (newTags) { setState(() { tags.clear(); tags.addAll(newTags); }); }, showCreateButton: true, maxTags: 10, hintText: '输入标签或从已有标签中选择', ), ], ); } /// 构建备注输入 Widget _buildNoteInput(ColorScheme colorScheme) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '添加备注', style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), TextField( controller: noteController, decoration: const InputDecoration( hintText: '输入备注信息(可选)', border: OutlineInputBorder(), prefixIcon: Icon(Icons.note_add), ), maxLines: 3, minLines: 1, ), ], ); } /// 构建底部操作栏 Widget _buildFooter(ColorScheme colorScheme) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: colorScheme.surface, borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(16), bottomRight: Radius.circular(16), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ // 取消按钮 CustomButton( text: '取消', onPressed: widget.onClose, buttonType: ButtonType.text, ), const SizedBox(width: 16), // 保存按钮 CustomButton( text: isBatchMode ? '保存 ${widget.sharedFiles.length} 张图片' : '保存图片', onPressed: performSave, buttonType: ButtonType.primary, isLoading: false, ), ], ), ); } /// 显示文件夹选择器 void _showFolderSelector() { showDialog( context: context, builder: (context) => FolderSelectorDialog( onFolderSelected: (folderId) { setState(() { selectedFolderId = folderId; }); Navigator.of(context).pop(); }, currentFolderId: selectedFolderId, ), ); } }