You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

295 lines
11KB

  1. import 'dart:io';
  2. import 'package:cached_network_image/cached_network_image.dart';
  3. import 'package:farm_tpf/custom_model/Media.dart';
  4. import 'package:farm_tpf/presentation/custom_widgets/camera_helper.dart';
  5. import 'package:farm_tpf/presentation/custom_widgets/widget_show_video.dart';
  6. import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart';
  7. import 'package:farm_tpf/presentation/screens/actions/util_action.dart';
  8. import 'package:farm_tpf/utils/const_color.dart';
  9. import 'package:farm_tpf/utils/const_common.dart';
  10. import 'package:farm_tpf/utils/const_string.dart';
  11. import 'package:file_picker/file_picker.dart';
  12. import 'package:flutter/cupertino.dart';
  13. import 'package:flutter/material.dart';
  14. import 'package:flutter_bloc/flutter_bloc.dart';
  15. import 'package:get/get.dart';
  16. import 'bloc/media_helper_bloc.dart';
  17. import 'hoz_list_view.dart';
  18. class WidgetMediaPicker extends StatefulWidget {
  19. final List<Media> currentItems;
  20. final Function(List<String> addNewFilePaths, List<String> deleteFilePaths)
  21. onChangeFiles;
  22. WidgetMediaPicker({this.currentItems, @required this.onChangeFiles});
  23. @override
  24. _WidgetMediaPickerState createState() => _WidgetMediaPickerState();
  25. }
  26. class _WidgetMediaPickerState extends State<WidgetMediaPicker> {
  27. List<Media> currentItems = [];
  28. List<String> addNewFilePaths = new List<String>();
  29. List<String> deleteFilePaths = new List<String>();
  30. @override
  31. void initState() {
  32. super.initState();
  33. }
  34. @override
  35. Widget build(BuildContext context) {
  36. return BlocProvider<MediaHelperBloc>(
  37. create: (BuildContext contextA) =>
  38. MediaHelperBloc()..add(ChangeListMedia(items: currentItems)),
  39. child: BlocBuilder<MediaHelperBloc, MediaHelperState>(
  40. builder: (contextB, state) {
  41. if (state is MediaHelperFailure) {
  42. return Container();
  43. } else if (state is MediaHelperSuccess) {
  44. currentItems = widget.currentItems ?? [];
  45. return Container(
  46. padding: EdgeInsets.only(top: 8, bottom: 8),
  47. child: Column(
  48. children: <Widget>[
  49. SizedBox(
  50. width: double.infinity,
  51. height: 44,
  52. child: FlatButton(
  53. onPressed: () {
  54. showDialog(
  55. context: context,
  56. barrierDismissible: true,
  57. builder: (context) => Opacity(
  58. child: multipleChoice(contextB),
  59. opacity: 1,
  60. ));
  61. },
  62. color: COLOR_CONST.DEFAULT,
  63. shape: RoundedRectangleBorder(
  64. borderRadius: new BorderRadius.circular(7.0),
  65. ),
  66. child: Center(
  67. child: Row(
  68. mainAxisAlignment: MainAxisAlignment.center,
  69. children: <Widget>[
  70. Icon(Icons.image, color: Colors.white),
  71. SizedBox(
  72. width: 8.0,
  73. ),
  74. Text(
  75. button_add_media,
  76. style: TextStyle(
  77. fontWeight: FontWeight.bold,
  78. color: COLOR_CONST.WHITE),
  79. )
  80. ],
  81. ),
  82. )),
  83. ),
  84. SizedBox(
  85. height: 8.0,
  86. ),
  87. Container(
  88. child: _buildListPoster(),
  89. ),
  90. ],
  91. ));
  92. }
  93. return Container();
  94. }));
  95. }
  96. Widget multipleChoice(BuildContext context) {
  97. return CupertinoAlertDialog(
  98. title: Text(label_title_select_media),
  99. actions: <Widget>[
  100. CupertinoDialogAction(
  101. child: const Text(label_take_photo_or_video),
  102. onPressed: () {
  103. Navigator.pop(context, 'Discard');
  104. Navigator.of(context)
  105. .push(MaterialPageRoute(builder: (context) => CameraHelper()))
  106. .then((value) {
  107. if (value != null) {
  108. print("ok");
  109. print(value);
  110. String filePath = value[0];
  111. File f = File(filePath);
  112. f.length().then((lengthFileInBytes) {
  113. if (lengthFileInBytes > ConstCommon.kFileSize) {
  114. Utils.showSnackBarWarning(message: label_file_to_large);
  115. } else {
  116. bool isVideo = value[1];
  117. Media newMedia = Media()
  118. ..isVideo = isVideo
  119. ..isServerFile = false
  120. ..pathFile = filePath;
  121. currentItems.add(newMedia);
  122. addNewFilePaths.add(filePath);
  123. BlocProvider.of<MediaHelperBloc>(context)
  124. ..add(ChangeListMedia(items: currentItems));
  125. widget.onChangeFiles(addNewFilePaths, deleteFilePaths);
  126. }
  127. });
  128. }
  129. });
  130. }),
  131. CupertinoDialogAction(
  132. child: const Text(label_select_image_from_library),
  133. onPressed: () async {
  134. Navigator.pop(context, 'Discard');
  135. FilePickerResult result =
  136. await FilePicker.platform.pickFiles(type: FileType.image);
  137. if (result != null) {
  138. UtilAction.compressImage(File(result.files.single.path))
  139. .then((compressFile) async {
  140. var lengthFileInBytes = await compressFile.length();
  141. if (lengthFileInBytes > ConstCommon.kFileSize) {
  142. Utils.showSnackBarWarning(message: label_file_to_large);
  143. } else {
  144. Media newMedia = Media()
  145. ..isVideo = false
  146. ..isServerFile = false
  147. ..pathFile = compressFile.path;
  148. currentItems.add(newMedia);
  149. addNewFilePaths.add(compressFile.path);
  150. BlocProvider.of<MediaHelperBloc>(context)
  151. ..add(ChangeListMedia(items: currentItems));
  152. widget.onChangeFiles(addNewFilePaths, deleteFilePaths);
  153. }
  154. });
  155. }
  156. }),
  157. CupertinoDialogAction(
  158. child: const Text(label_select_video_from_library),
  159. onPressed: () async {
  160. Navigator.pop(context, 'Discard');
  161. FilePickerResult result =
  162. await FilePicker.platform.pickFiles(type: FileType.video);
  163. if (result != null) {
  164. String filePath = result.files.single.path;
  165. var lengthFileInBytes = result.files.single.size * 1000;
  166. if (lengthFileInBytes > ConstCommon.kFileSize) {
  167. Utils.showSnackBarWarning(message: label_file_to_large);
  168. } else {
  169. Media newMedia = Media()
  170. ..isVideo = true
  171. ..isServerFile = false
  172. ..pathFile = filePath;
  173. currentItems.add(newMedia);
  174. addNewFilePaths.add(filePath);
  175. BlocProvider.of<MediaHelperBloc>(context)
  176. ..add(ChangeListMedia(items: currentItems));
  177. widget.onChangeFiles(addNewFilePaths, deleteFilePaths);
  178. }
  179. }
  180. }),
  181. CupertinoDialogAction(
  182. child: const Text(label_cancel),
  183. textStyle: TextStyle(fontWeight: FontWeight.bold),
  184. isDefaultAction: true,
  185. onPressed: () {
  186. Navigator.pop(context, 'Cancel');
  187. }),
  188. ],
  189. );
  190. }
  191. _buildListPoster() {
  192. return BlocBuilder<MediaHelperBloc, MediaHelperState>(
  193. builder: (context, state) {
  194. if (state is MediaHelperSuccess) {
  195. return GridView.count(
  196. physics: NeverScrollableScrollPhysics(),
  197. shrinkWrap: true,
  198. crossAxisCount: 4,
  199. children: currentItems.map(
  200. (item) {
  201. return _WidgetItemMedia(
  202. item: item,
  203. deleteImage: (item) {
  204. if (item.isServerFile) {
  205. var url = item.pathFile
  206. .replaceAll(ConstCommon.baseImageUrl, '');
  207. deleteFilePaths.add(url);
  208. }
  209. currentItems.remove(item);
  210. widget.onChangeFiles(addNewFilePaths, deleteFilePaths);
  211. BlocProvider.of<MediaHelperBloc>(context)
  212. .add(ChangeListMedia(items: currentItems));
  213. });
  214. },
  215. ).toList());
  216. }
  217. return Container();
  218. });
  219. }
  220. }
  221. class _WidgetItemMedia extends StatelessWidget {
  222. ItemMediaCallback deleteImage;
  223. final Media item;
  224. _WidgetItemMedia({@required this.item, @required this.deleteImage});
  225. BuildContext _context;
  226. // screenSize/rowGridview - iconSize - (rowGridview-1)*marginContainer
  227. // Get.width/4 - 24 - 3*4
  228. double positionIconDelete = -(Get.width / 4 - 36);
  229. @override
  230. Widget build(BuildContext context) {
  231. _context = context;
  232. return GestureDetector(
  233. onTap: () {
  234. print("Show preview image or video");
  235. },
  236. child: Stack(
  237. alignment: Alignment.topRight,
  238. overflow: Overflow.visible,
  239. children: <Widget>[
  240. Positioned.fill(
  241. child: item.isVideo
  242. ? VideoWidget(
  243. pathFile: item.pathFile,
  244. isServerFile: item.isServerFile,
  245. play: false,
  246. )
  247. : Container(
  248. margin: EdgeInsets.all(4.0),
  249. decoration: BoxDecoration(
  250. color: Colors.white,
  251. border: Border.all(color: Colors.grey),
  252. borderRadius:
  253. BorderRadius.all(Radius.circular(8.0))),
  254. child: item.isServerFile
  255. ? CachedNetworkImage(
  256. placeholder: (context, url) =>
  257. Icon(Icons.crop_original),
  258. imageUrl: item.pathFile)
  259. : Image.file(File(item.pathFile)),
  260. )),
  261. Positioned.fill(
  262. top: positionIconDelete,
  263. right: positionIconDelete,
  264. child: IconButton(
  265. icon: Icon(
  266. Icons.cancel,
  267. color: Colors.redAccent,
  268. size: 24,
  269. ),
  270. onPressed: () {
  271. print("On tap delete media");
  272. deleteImage(item);
  273. }),
  274. )
  275. ],
  276. ));
  277. }
  278. }
  279. typedef ItemMediaCallback = void Function(Media item);