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.

293 lines
11KB

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