import 'dart:io'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:farm_tpf/custom_model/Media.dart'; import 'package:farm_tpf/presentation/custom_widgets/camera_helper.dart'; import 'package:farm_tpf/presentation/custom_widgets/widget_show_video.dart'; import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; import 'package:farm_tpf/presentation/screens/actions/util_action.dart'; import 'package:farm_tpf/utils/const_assets.dart'; import 'package:farm_tpf/utils/const_common.dart'; import 'package:farm_tpf/utils/const_string.dart'; // import 'package:file_picker/file_picker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:image_picker/image_picker.dart'; import 'bloc/media_helper_bloc.dart'; import 'hoz_list_view.dart'; class WidgetMediaPicker extends StatefulWidget { final List? currentItems; final Function(List addNewFilePaths, List deleteFilePaths) onChangeFiles; WidgetMediaPicker({this.currentItems, required this.onChangeFiles}); @override _WidgetMediaPickerState createState() => _WidgetMediaPickerState(); } class _WidgetMediaPickerState extends State { List currentItems = []; List addNewFilePaths = []; List deleteFilePaths = []; final picker = ImagePicker(); @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return BlocProvider( create: (BuildContext contextA) => MediaHelperBloc()..add(ChangeListMedia(items: currentItems)), child: BlocBuilder(builder: (contextB, state) { if (state is MediaHelperFailure) { return Container(); } else if (state is MediaHelperSuccess) { currentItems = widget.currentItems ?? []; return Container( padding: const EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Hình ảnh/ Video', style: TextStyle(color: Colors.black54, fontSize: 16)), const SizedBox( height: 8, ), Row( children: [ InkWell( child: Image.asset( AppAssets.icAddMedia, fit: BoxFit.contain, width: 114, height: 114, ), onTap: () { showDialog( context: context, barrierDismissible: true, builder: (context) => Opacity( child: multipleChoice(contextB), opacity: 1, ), ); }, ), const SizedBox( width: 8.0, ), Expanded( child: _buildListPoster(), ), ], ), ], )); } return Container(); })); } Widget multipleChoice(BuildContext context) { return CupertinoAlertDialog( title: const Text(label_title_select_media), actions: [ CupertinoDialogAction( child: const Text('Chụp ảnh'), onPressed: () async { Navigator.pop(context, 'Discard'); var isExistedFileTooLarge = false; var compressFile = await picker.pickImage(source: ImageSource.camera, imageQuality: 10); if (compressFile != null) { var imageFile = File(compressFile.path); if (imageFile.lengthSync() > ConstCommon.kFileSize) { isExistedFileTooLarge = true; } else { var newMedia = Media() ..isVideo = false ..isServerFile = false ..pathFile = imageFile.path; currentItems.add(newMedia); addNewFilePaths.add(compressFile.path); } if (isExistedFileTooLarge) { Utils.showSnackBarWarning(message: "Tập tin có kích thước lớn đã được loại bỏ."); } BlocProvider.of(context)..add(ChangeListMedia(items: currentItems)); widget.onChangeFiles(addNewFilePaths, deleteFilePaths); } }, ), CupertinoDialogAction( child: const Text(label_select_image_from_library), onPressed: () async { Navigator.pop(context, 'Discard'); final List images = await picker.pickMultiImage(imageQuality: 50); var isExistedFileTooLarge = false; images.forEach( (compressFile) { var imageFile = File(compressFile.path); if (imageFile.lengthSync() > ConstCommon.kFileSize) { isExistedFileTooLarge = true; } else { var newMedia = Media() ..isVideo = false ..isServerFile = false ..pathFile = imageFile.path; currentItems.add(newMedia); addNewFilePaths.add(compressFile.path); } if (isExistedFileTooLarge) { Utils.showSnackBarWarning(message: "Tập tin có kích thước lớn đã được loại bỏ."); } BlocProvider.of(context)..add(ChangeListMedia(items: currentItems)); widget.onChangeFiles(addNewFilePaths, deleteFilePaths); }, ); // } }, ), CupertinoDialogAction( child: const Text('Quay video'), onPressed: () async { Navigator.pop(context, 'Discard'); var isExistedFileTooLarge = false; var compressFile = await picker.pickVideo(source: ImageSource.camera); if (compressFile != null) { var imageFile = File(compressFile.path); if (imageFile.lengthSync() > ConstCommon.kFileSize) { isExistedFileTooLarge = true; } else { var newMedia = Media() ..isVideo = true ..isServerFile = false ..pathFile = imageFile.path; currentItems.add(newMedia); addNewFilePaths.add(compressFile.path); } if (isExistedFileTooLarge) { Utils.showSnackBarWarning(message: "Tập tin có kích thước lớn đã được loại bỏ."); } BlocProvider.of(context)..add(ChangeListMedia(items: currentItems)); widget.onChangeFiles(addNewFilePaths, deleteFilePaths); } }, ), CupertinoDialogAction( child: const Text(label_select_video_from_library), onPressed: () async { Navigator.pop(context, 'Discard'); var result = await picker.pickVideo(source: ImageSource.gallery); // FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.video, allowMultiple: true); if (result != null) { var isExistedFileTooLarge = false; var fileVideo = File(result.path); if (fileVideo.lengthSync() > ConstCommon.kFileSize) { isExistedFileTooLarge = true; } else { var newMedia = Media() ..isVideo = true ..isServerFile = false ..pathFile = fileVideo.path; currentItems.add(newMedia); addNewFilePaths.add(fileVideo.path); } if (isExistedFileTooLarge) { Utils.showSnackBarWarning(message: "Tập tin có kích thước lớn đã được loại bỏ."); } BlocProvider.of(context)..add(ChangeListMedia(items: currentItems)); widget.onChangeFiles(addNewFilePaths, deleteFilePaths); } }, ), CupertinoDialogAction( child: const Text(label_cancel), textStyle: const TextStyle(fontWeight: FontWeight.bold), isDefaultAction: true, onPressed: () { Navigator.pop(context, 'Cancel'); }), ], ); } _buildListPoster() { return BlocBuilder(builder: (context, state) { if (state is MediaHelperSuccess) { return WrapContentHozListView( list: currentItems, itemBuilder: (context, index) { var item = currentItems[index]; return Container( width: 120, height: 120, child: _WidgetItemMedia( item: item, deleteImage: (item) { if (item.isServerFile ?? false) { var url = item.pathFile?.replaceAll(ConstCommon.baseImageUrl, ''); deleteFilePaths.add(url ?? ''); } addNewFilePaths.remove(item.pathFile); currentItems.remove(item); widget.onChangeFiles(addNewFilePaths, deleteFilePaths); BlocProvider.of(context).add(ChangeListMedia(items: currentItems)); }), ); }, separatorBuilder: (BuildContext context, int index) { return const SizedBox.shrink(); }, ); } return Container(); }); } } class _WidgetItemMedia extends StatelessWidget { ItemMediaCallback deleteImage; final Media item; _WidgetItemMedia({required this.item, required this.deleteImage}); double positionIconDelete = -(120.0 - 36); @override Widget build(BuildContext context) { return GestureDetector( onTap: () { print("Show preview image or video"); }, child: Stack( alignment: Alignment.topRight, // overflow: Overflow.visible, children: [ Positioned.fill( child: (item.isVideo ?? false) ? VideoWidget( pathFile: item.pathFile ?? '', isServerFile: item.isServerFile ?? false, play: false, ) : Container( margin: const EdgeInsets.all(4.0), decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.grey), borderRadius: const BorderRadius.all(Radius.circular(8.0))), child: (item.isServerFile ?? false) ? CachedNetworkImage( placeholder: (context, url) => const Icon(Icons.crop_original), imageUrl: item.pathFile ?? '', ) : Image.file(File(item.pathFile ?? '')), ), ), Positioned.fill( top: positionIconDelete, right: positionIconDelete, child: IconButton( icon: const Icon( Icons.delete, color: Colors.redAccent, size: 24, ), onPressed: () { print("On tap delete media"); deleteImage(item); })) ], )); } } typedef ItemMediaCallback = void Function(Media item);