From d0a55263b222c91a17dee3c5f31a482d3f0780fa Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 4 Jan 2023 14:35:36 +0100 Subject: [PATCH] feat: add mimeType --- .flutter-plugins-dependencies | 2 +- CHANGELOG.md | 8 ++ example/lib/main.dart | 2 +- example/lib/media_picker.dart | 3 + example/pubspec.lock | 9 +- lib/src/abstracts/media_picker_service.dart | 7 +- lib/src/inputs/input_audio.dart | 13 ++- lib/src/inputs/input_file.dart | 78 ++++++++------ lib/src/inputs/input_photo.dart | 18 ++-- lib/src/inputs/input_text.dart | 4 +- lib/src/inputs/input_video.dart | 17 +-- lib/src/media_picker.dart | 112 ++++++++++++-------- lib/src/media_result.dart | 9 +- lib/src/service/audio_service.dart | 2 +- lib/src/service/media_picker_service.dart | 18 +++- pubspec.yaml | 3 +- 16 files changed, 193 insertions(+), 112 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 9b3bf42..06f853e 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"file_picker","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\file_picker-5.2.4\\\\","native_build":true,"dependencies":[]},{"name":"flutter_sound","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_sound-9.2.13\\\\","native_build":true,"dependencies":[]},{"name":"image_picker_ios","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\image_picker_ios-0.8.6+2\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_ios","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.11\\\\","native_build":true,"dependencies":[]},{"name":"permission_handler_apple","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_apple-9.0.7\\\\","native_build":true,"dependencies":[]},{"name":"video_player_avfoundation","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_avfoundation-2.3.8\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"file_picker","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\file_picker-5.2.4\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_plugin_android_lifecycle","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-2.0.7\\\\","native_build":true,"dependencies":[]},{"name":"flutter_sound","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_sound-9.2.13\\\\","native_build":true,"dependencies":[]},{"name":"image_picker_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\image_picker_android-0.8.5+4\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"path_provider_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.22\\\\","native_build":true,"dependencies":[]},{"name":"permission_handler_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_android-10.2.0\\\\","native_build":true,"dependencies":[]},{"name":"video_player_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_android-2.3.10\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.7\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.1.3\\\\","native_build":false,"dependencies":[]},{"name":"permission_handler_windows","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_windows-0.1.2\\\\","native_build":true,"dependencies":[]}],"web":[{"name":"file_picker","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\file_picker-5.2.4\\\\","dependencies":[]},{"name":"flutter_sound_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_sound_web-9.2.13\\\\","dependencies":[]},{"name":"image_picker_for_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\image_picker_for_web-2.1.10\\\\","dependencies":[]},{"name":"video_player_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_web-2.0.13\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"file_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"flutter_sound","dependencies":["path_provider","flutter_sound_web"]},{"name":"flutter_sound_web","dependencies":[]},{"name":"image_picker","dependencies":["image_picker_android","image_picker_for_web","image_picker_ios"]},{"name":"image_picker_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"image_picker_ios","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":["permission_handler_android","permission_handler_apple","permission_handler_windows"]},{"name":"permission_handler_android","dependencies":[]},{"name":"permission_handler_apple","dependencies":[]},{"name":"permission_handler_windows","dependencies":[]},{"name":"video_player","dependencies":["video_player_android","video_player_avfoundation","video_player_web"]},{"name":"video_player_android","dependencies":[]},{"name":"video_player_avfoundation","dependencies":[]},{"name":"video_player_web","dependencies":[]}],"date_created":"2023-01-03 09:08:54.917527","version":"3.3.10"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"file_picker","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\file_picker-5.2.4\\\\","native_build":true,"dependencies":[]},{"name":"flutter_sound","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_sound-9.2.13\\\\","native_build":true,"dependencies":[]},{"name":"image_picker_ios","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\image_picker_ios-0.8.6+2\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_ios","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.11\\\\","native_build":true,"dependencies":[]},{"name":"permission_handler_apple","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_apple-9.0.7\\\\","native_build":true,"dependencies":[]},{"name":"video_player_avfoundation","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_avfoundation-2.3.8\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"file_picker","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\file_picker-5.2.4\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_plugin_android_lifecycle","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-2.0.7\\\\","native_build":true,"dependencies":[]},{"name":"flutter_sound","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_sound-9.2.13\\\\","native_build":true,"dependencies":[]},{"name":"image_picker_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\image_picker_android-0.8.5+4\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"path_provider_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.22\\\\","native_build":true,"dependencies":[]},{"name":"permission_handler_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_android-10.2.0\\\\","native_build":true,"dependencies":[]},{"name":"video_player_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_android-2.3.10\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.7\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.1.3\\\\","native_build":false,"dependencies":[]},{"name":"permission_handler_windows","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_windows-0.1.2\\\\","native_build":true,"dependencies":[]}],"web":[{"name":"file_picker","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\file_picker-5.2.4\\\\","dependencies":[]},{"name":"flutter_sound_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_sound_web-9.2.13\\\\","dependencies":[]},{"name":"image_picker_for_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\image_picker_for_web-2.1.10\\\\","dependencies":[]},{"name":"video_player_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_web-2.0.13\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"file_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"flutter_sound","dependencies":["path_provider","flutter_sound_web"]},{"name":"flutter_sound_web","dependencies":[]},{"name":"image_picker","dependencies":["image_picker_android","image_picker_for_web","image_picker_ios"]},{"name":"image_picker_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"image_picker_ios","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":["permission_handler_android","permission_handler_apple","permission_handler_windows"]},{"name":"permission_handler_android","dependencies":[]},{"name":"permission_handler_apple","dependencies":[]},{"name":"permission_handler_windows","dependencies":[]},{"name":"video_player","dependencies":["video_player_android","video_player_avfoundation","video_player_web"]},{"name":"video_player_android","dependencies":[]},{"name":"video_player_avfoundation","dependencies":[]},{"name":"video_player_web","dependencies":[]}],"date_created":"2023-01-04 16:26:05.230564","version":"3.3.10"} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a5e431..2da174d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,12 @@ +## 0.3.0 + +- Added mimeType to MediaPickerResult. +- Made mimeType and fileName parameters of MediaPickerResult public so they can be changed if wanted. +- Removed fileType from MediaPickerResult since fileName already includes it. +- Added audio play button on result page so it doesn't play automatically anymore. + ## 0.2.0 + - Added option to select a file - Added file_picker package for file picking possibility - Inputs now have widgets so any widget can be used in the media picker now. diff --git a/example/lib/main.dart b/example/lib/main.dart index 88ab789..9271960 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -45,7 +45,7 @@ class _MyHomePageState extends State { ), body: Center( child: ElevatedButton( - child: const Text('Media Picker Text Options'), + child: const Text('Media Picker'), onPressed: () { showModalBottomSheet( backgroundColor: Colors.transparent, diff --git a/example/lib/media_picker.dart b/example/lib/media_picker.dart index df02605..16de2c4 100644 --- a/example/lib/media_picker.dart +++ b/example/lib/media_picker.dart @@ -135,9 +135,12 @@ class _MediaPickerExampleState extends ConsumerState { 'bmp', 'gif', 'txt', + 'mp4', + 'mp3', ], checkPageSettings: { 'title': 'Share file', + 'height': 200.0, }, onComplete: (MediaResult result) { Navigator.pop(context); diff --git a/example/pubspec.lock b/example/pubspec.lock index a249f75..49b766a 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -131,7 +131,7 @@ packages: path: ".." relative: true source: path - version: "0.0.1" + version: "0.3.0" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -296,6 +296,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" nested: dependency: transitive description: diff --git a/lib/src/abstracts/media_picker_service.dart b/lib/src/abstracts/media_picker_service.dart index dda347d..dd0d17e 100644 --- a/lib/src/abstracts/media_picker_service.dart +++ b/lib/src/abstracts/media_picker_service.dart @@ -5,13 +5,14 @@ import 'dart:typed_data'; import 'package:file_picker/file_picker.dart'; +import 'package:flutter_media_picker/flutter_media_picker.dart'; abstract class MediaPickerService { - /// Returns [Uint8List] based on given [ImageSource]. - Future pickImageFile(); + /// Returns [MediaResult] based on given [ImageSource]. + Future pickImageFile(); /// Returns [Uint8List] based on given [VideoSource]. - Future pickVideoFile(); + Future pickVideoFile(); /// Returns [FilePickerResult] based on given [File]. Future pickFile(List fileExtensions); diff --git a/lib/src/inputs/input_audio.dart b/lib/src/inputs/input_audio.dart index ec1151d..878ac7f 100644 --- a/lib/src/inputs/input_audio.dart +++ b/lib/src/inputs/input_audio.dart @@ -44,6 +44,7 @@ class MediaPickerInputAudio implements MediaPickerInput { audioService: audioService, onComplete: (MediaResult content) { if (content.fileValue != null) { + content.mimeType = 'audio/mpeg'; audio = content; } else { throw Exception('No recording returned'); @@ -61,7 +62,17 @@ class MediaPickerInputAudio implements MediaPickerInput { Future displayResult(MediaResult result) async { var data = result.fileValue; if (data != null) { - audioService.playAudio(data); + Column( + children: [ + if (result.fileName != null) ...[ + Text(result.fileName!), + ], + ElevatedButton( + onPressed: () => audioService.playAudio(data), + child: const Text("Play audio"), + ), + ], + ); } return Container(); diff --git a/lib/src/inputs/input_file.dart b/lib/src/inputs/input_file.dart index a918f6d..ec4bdf8 100644 --- a/lib/src/inputs/input_file.dart +++ b/lib/src/inputs/input_file.dart @@ -4,8 +4,7 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; - -import 'package:path/path.dart' as path; +import 'package:mime/mime.dart'; import '../../flutter_media_picker.dart'; @@ -22,6 +21,8 @@ class MediaPickerInputFile implements MediaPickerInput { final Future Function(List)? pickFile; final List fileExtensions; + final VideoPlayerFactory videoPlayerFactory = MediaPickerVideoPlayerFactory(); + final AudioService audioService = MediaPickerAudioService(); @override String label; @@ -31,13 +32,16 @@ class MediaPickerInputFile implements MediaPickerInput { @override Future onPressed(BuildContext context) async { - var file = await pickFile?.call(fileExtensions); - - if (file != null && file.files.first.bytes != null) { + var filePicked = await pickFile?.call(fileExtensions); + if (filePicked != null && filePicked.files.first.bytes != null) { + var file = filePicked.files.first; return MediaResult( - fileValue: file.files.first.bytes, - fileType: path.extension(file.files.first.name), - fileName: file.files.first.name, + fileValue: file.bytes, + fileName: file.name, + mimeType: lookupMimeType( + file.name, + headerBytes: file.bytes, + ), ); } return MediaResult(); @@ -46,36 +50,46 @@ class MediaPickerInputFile implements MediaPickerInput { @override Future displayResult(MediaResult result) async { if (result.fileValue != null) { - switch (result.fileType) { - case '.png': - case '.jpg': - case '.jpeg': - case '.webp': - case '.bmp': - case '.gif': + var mime = result.mimeType!.split("/").first; + switch (mime) { + case 'image': return Image.memory( result.fileValue!, - height: 250, ); - case '.pdf': - case '.doc': - case '.docx': - return Text(result.fileName!); - case '.txt': - return Column(mainAxisSize: MainAxisSize.min, children: [ - Text(result.fileName!), - const SizedBox( - height: 20, - ), - Center( - child: Text(String.fromCharCodes(result.fileValue!)), - ) - ]); + case 'video': + return videoPlayerFactory.createVideoPlayer( + result.fileValue!, + ); + case 'text': + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text(result.fileName!), + const SizedBox( + height: 20, + ), + Center( + child: Text(String.fromCharCodes(result.fileValue!)), + ) + ], + ); + case 'audio': + return Column( + children: [ + if (result.fileName != null) ...[ + Text(result.fileName!), + ], + ElevatedButton( + onPressed: () => audioService.playAudio(result.fileValue!), + child: const Text("Play audio"), + ), + ], + ); default: + return Text(result.fileName!); } } - - return Container(); + return Text(result.fileName!); } @override diff --git a/lib/src/inputs/input_photo.dart b/lib/src/inputs/input_photo.dart index 0720670..fe555d1 100644 --- a/lib/src/inputs/input_photo.dart +++ b/lib/src/inputs/input_photo.dart @@ -1,13 +1,11 @@ // SPDX-FileCopyrightText: 2022 Iconica // // SPDX-License-Identifier: BSD-3-Clause - -import 'dart:typed_data'; - import 'package:flutter/material.dart'; import 'package:flutter_media_picker/src/abstracts/media_picker_input.dart'; import 'package:flutter_media_picker/src/media_result.dart'; +import 'package:mime/mime.dart'; /// Input for photo used by [MediaPicker]. class MediaPickerInputPhoto implements MediaPickerInput { @@ -19,7 +17,7 @@ class MediaPickerInputPhoto implements MediaPickerInput { this.pickFile, }); - final Future Function()? pickFile; + final Future Function()? pickFile; @override String label; @@ -31,10 +29,14 @@ class MediaPickerInputPhoto implements MediaPickerInput { Future onPressed(BuildContext context) async { var image = await pickFile?.call(); - if (image != null && image.isNotEmpty) { - return MediaResult( - fileValue: image, - ); + if (image != null) { + if (image.mimeType == null || image.mimeType!.isEmpty) { + image.mimeType = lookupMimeType( + image.fileName!, + headerBytes: image.fileValue, + ); + } + return image; } return MediaResult(); } diff --git a/lib/src/inputs/input_text.dart b/lib/src/inputs/input_text.dart index 9a8d7ae..f6b696c 100644 --- a/lib/src/inputs/input_text.dart +++ b/lib/src/inputs/input_text.dart @@ -25,7 +25,7 @@ class MediaPickerInputText implements MediaPickerInput { @override Future onPressed(BuildContext context) async { - return MediaResult(); + return MediaResult(mimeType: 'plain/text'); } @override @@ -56,7 +56,7 @@ class _DisplayTextState extends ConsumerState { @override Widget build(BuildContext context) { return FlutterFormInputPlainText( - label: const Text('Titel'), + label: const Text('Title'), controller: _controller, ); } diff --git a/lib/src/inputs/input_video.dart b/lib/src/inputs/input_video.dart index d9ee12b..6847595 100644 --- a/lib/src/inputs/input_video.dart +++ b/lib/src/inputs/input_video.dart @@ -6,6 +6,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_media_picker/flutter_media_picker.dart'; +import 'package:mime/mime.dart'; /// Input for video used by [MediaPicker]. class MediaPickerInputVideo implements MediaPickerInput { @@ -18,7 +19,7 @@ class MediaPickerInputVideo implements MediaPickerInput { required this.videoPlayerFactory, }); - final Future Function()? pickFile; + final Future Function()? pickFile; final VideoPlayerFactory videoPlayerFactory; @override @@ -29,12 +30,16 @@ class MediaPickerInputVideo implements MediaPickerInput { @override Future onPressed(BuildContext context) async { - var image = await pickFile?.call(); + var video = await pickFile?.call(); - if (image != null && image.isNotEmpty) { - return MediaResult( - fileValue: image, - ); + if (video != null) { + if (video.mimeType == null || video.mimeType!.isEmpty) { + video.mimeType = lookupMimeType( + video.fileName!, + headerBytes: video.fileValue, + ); + } + return video; } return MediaResult(); diff --git a/lib/src/media_picker.dart b/lib/src/media_picker.dart index 2e303f3..5b7d396 100644 --- a/lib/src/media_picker.dart +++ b/lib/src/media_picker.dart @@ -101,7 +101,7 @@ import '../flutter_media_picker.dart'; /// ); ///``` -class MediaPicker extends ConsumerWidget { +class MediaPicker extends ConsumerStatefulWidget { const MediaPicker({ this.mediaPickerInputs, this.inputsDirection = Axis.horizontal, @@ -123,7 +123,14 @@ class MediaPicker extends ConsumerWidget { Function(Map results) onComplete)? mediaCheckPage; @override - Widget build(BuildContext context, ref) { + ConsumerState createState() => _MediaPickerState(); +} + +class _MediaPickerState extends ConsumerState { + bool _isLoading = false; + + @override + Widget build(BuildContext context) { List inputs = [ MediaPickerInputPhoto(), MediaPickerInputVideo( @@ -135,49 +142,64 @@ class MediaPicker extends ConsumerWidget { ), ]; - if (mediaPickerInputs != null) { - inputs = mediaPickerInputs!; + if (widget.mediaPickerInputs != null) { + inputs = widget.mediaPickerInputs!; } + var theme = Theme.of(context); + return Wrap( alignment: WrapAlignment.center, - direction: inputsDirection, - spacing: horizontalSpacing, - runSpacing: verticalSpacing, + direction: widget.inputsDirection, + spacing: widget.horizontalSpacing, + runSpacing: widget.verticalSpacing, children: [ - for (final input in inputs) ...[ - GestureDetector( - onTap: () async { - await onPressedMediaType(context, input); - }, - child: Wrap( - children: [ - input.widget ?? - Container( - height: 55, - width: MediaQuery.of(context).size.width * 0.9, - decoration: const BoxDecoration( - border: Border( - bottom: BorderSide( - color: Color(0xFF979797), - width: 1, - ), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Padding( - padding: const EdgeInsets.only(left: 15), - child: Text( - input.label, - style: Theme.of(context).textTheme.headline6, - ), - ), - ), - ), - ], + if (_isLoading) ...[ + SizedBox( + height: 150, + width: 150, + child: CircularProgressIndicator( + color: theme.primaryColor, ), ), + ] else ...[ + for (final input in inputs) ...[ + GestureDetector( + onTap: () async { + setState(() { + _isLoading = true; + }); + await onPressedMediaType(context, input); + }, + child: Wrap( + children: [ + input.widget ?? + Container( + height: 55, + width: MediaQuery.of(context).size.width * 0.9, + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide( + color: Color(0xFF979797), + width: 1, + ), + ), + ), + child: Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.only(left: 15), + child: Text( + input.label, + style: theme.textTheme.headline6, + ), + ), + ), + ), + ], + ), + ), + ] ] ], ); @@ -187,16 +209,16 @@ class MediaPicker extends ConsumerWidget { BuildContext context, MediaPickerInput input) async { MediaResult content = await input.onPressed(context); - if (mediaCheckPage != null && + if (widget.mediaCheckPage != null && (input.runtimeType == MediaPickerInputText || _hasContent(content))) { - var checkPage = mediaCheckPage!( + var checkPage = widget.mediaCheckPage!( await input.displayResult(content), input.checkPageSettings, (Map results) { MediaResult result = MediaResult( fileValue: content.fileValue, textValue: content.textValue, - fileType: content.fileType, + mimeType: content.mimeType, checkPageResults: results, ); @@ -204,8 +226,8 @@ class MediaPicker extends ConsumerWidget { input.onComplete!(result); } - if (onComplete != null) { - onComplete!(result); + if (widget.onComplete != null) { + widget.onComplete!(result); } }, ); @@ -222,8 +244,8 @@ class MediaPicker extends ConsumerWidget { input.onComplete!(content); } - if (onComplete != null) { - onComplete!(content); + if (widget.onComplete != null) { + widget.onComplete!(content); } } } diff --git a/lib/src/media_result.dart b/lib/src/media_result.dart index 7a1da26..7af8a93 100644 --- a/lib/src/media_result.dart +++ b/lib/src/media_result.dart @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Iconica // // SPDX-License-Identifier: BSD-3-Clause - import 'dart:typed_data'; /// MediaResult is a model that is used to return the media selected/media with the [MediaPicker]. @@ -10,7 +9,7 @@ class MediaResult { this.textValue, this.fileValue, this.checkPageResults, - this.fileType, + this.mimeType, this.fileName, }); @@ -24,9 +23,9 @@ class MediaResult { /// Returns the values from the checkPageResults if checkpage is set. final Map? checkPageResults; - /// Returns the filetype when a file is selected with the FilePicker. - final String? fileType; + /// Returns the mime type of the file. + String? mimeType; /// Returns the file name when a file is selected with the FilePicker. - final String? fileName; + String? fileName; } diff --git a/lib/src/service/audio_service.dart b/lib/src/service/audio_service.dart index dd945a3..f17c022 100644 --- a/lib/src/service/audio_service.dart +++ b/lib/src/service/audio_service.dart @@ -59,7 +59,7 @@ class MediaPickerAudioService implements AudioService { _recorder.closeRecorder(); _player.openPlayer(); _player.startPlayer( - fromURI: _directory!.path, + fromDataBuffer: audio, ); } } diff --git a/lib/src/service/media_picker_service.dart b/lib/src/service/media_picker_service.dart index 3a98ff5..e91e64f 100644 --- a/lib/src/service/media_picker_service.dart +++ b/lib/src/service/media_picker_service.dart @@ -6,7 +6,7 @@ import 'dart:typed_data'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_media_picker/src/abstracts/media_picker_service.dart'; +import 'package:flutter_media_picker/flutter_media_picker.dart'; import 'package:image_picker/image_picker.dart'; import 'package:flutter_media_picker/video_player/video_player_native.dart' if (dart.library.html) 'package:media_picker/video_player/video_player_web.dart' @@ -17,21 +17,29 @@ class MediaPickerFileService implements MediaPickerService { late VideoPlayerController controller; @override - Future pickImageFile() async { + Future pickImageFile() async { var image = await ImagePicker().pickImage(source: ImageSource.camera); if (image != null) { - return image.readAsBytes(); + return MediaResult( + fileName: image.name, + mimeType: image.mimeType, + fileValue: await image.readAsBytes(), + ); } return Future.value(null); } @override - Future pickVideoFile() async { + Future pickVideoFile() async { var video = await ImagePicker().pickVideo(source: ImageSource.camera); if (video != null) { - return video.readAsBytes(); + return MediaResult( + fileName: video.name, + mimeType: video.mimeType, + fileValue: await video.readAsBytes(), + ); } return Future.value(null); } diff --git a/pubspec.yaml b/pubspec.yaml index 4a0ae74..d2c07e4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_media_picker description: A new Flutter package project. -version: 0.0.1 +version: 0.3.0 homepage: https://github.com/Iconica-Development/flutter_media_picker publish_to: "none" @@ -26,6 +26,7 @@ dependencies: git: url: https://github.com/Iconica-Development/flutter_form.git ref: 2.0.1 + mime: ^1.0.3 dev_dependencies: flutter_test: