Merge pull request #4 from Iconica-Development/feature/add-file-picker

Added file picker and option to change widget
This commit is contained in:
Tim 2023-01-03 14:46:35 +01:00 committed by GitHub
commit 4ba167aacb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 345 additions and 103 deletions

View file

@ -1,22 +1,23 @@
# This is a generated file; do not edit or check into version control. # This is a generated file; do not edit or check into version control.
flutter_plugin_android_lifecycle=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/flutter_plugin_android_lifecycle-2.0.7/ file_picker=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\file_picker-5.2.4\\
flutter_sound=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/flutter_sound-9.2.13/ flutter_plugin_android_lifecycle=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\flutter_plugin_android_lifecycle-2.0.7\\
flutter_sound_web=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/flutter_sound_web-9.2.13/ flutter_sound=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\flutter_sound-9.2.13\\
image_picker=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/image_picker-0.8.6/ flutter_sound_web=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\flutter_sound_web-9.2.13\\
image_picker_android=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/image_picker_android-0.8.5+3/ image_picker=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\image_picker-0.8.6\\
image_picker_for_web=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/image_picker_for_web-2.1.10/ image_picker_android=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\image_picker_android-0.8.5+4\\
image_picker_ios=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/image_picker_ios-0.8.6+1/ image_picker_for_web=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\image_picker_for_web-2.1.10\\
path_provider=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.11/ image_picker_ios=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\image_picker_ios-0.8.6+2\\
path_provider_android=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/path_provider_android-2.0.20/ path_provider=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\path_provider-2.0.11\\
path_provider_ios=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/path_provider_ios-2.0.11/ path_provider_android=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\path_provider_android-2.0.22\\
path_provider_linux=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-2.1.7/ path_provider_ios=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\path_provider_ios-2.0.11\\
path_provider_macos=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-2.0.6/ path_provider_linux=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\path_provider_linux-2.1.7\\
path_provider_windows=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-2.1.3/ path_provider_macos=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\path_provider_macos-2.0.6\\
permission_handler=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/permission_handler-10.2.0/ path_provider_windows=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\path_provider_windows-2.1.3\\
permission_handler_android=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/permission_handler_android-10.2.0/ permission_handler=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\permission_handler-10.2.0\\
permission_handler_apple=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/permission_handler_apple-9.0.7/ permission_handler_android=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\permission_handler_android-10.2.0\\
permission_handler_windows=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/permission_handler_windows-0.1.2/ permission_handler_apple=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\permission_handler_apple-9.0.7\\
video_player=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/video_player-2.4.7/ permission_handler_windows=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\permission_handler_windows-0.1.2\\
video_player_android=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/video_player_android-2.3.9/ video_player=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\video_player-2.4.10\\
video_player_avfoundation=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/video_player_avfoundation-2.3.7/ video_player_android=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\video_player_android-2.3.10\\
video_player_web=/Users/nielsgorter/.pub-cache/hosted/pub.dartlang.org/video_player_web-2.0.12/ video_player_avfoundation=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\video_player_avfoundation-2.3.8\\
video_player_web=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\video_player_web-2.0.13\\

File diff suppressed because one or more lines are too long

View file

@ -1,19 +1,25 @@
## 0.0.1 ## 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.
- Translated the example to English
- Initial port ## 0.1.1
## 0.0.2 - Updated flutter_form version to 2.0.1
- Updated flutter_form version
## 0.0.3
- Fixed bug where onTap was not working when header is set
## 0.1.0 ## 0.1.0
- Ability to set styling for the audio input. - Ability to set styling for the audio input.
## 0.1.1 ## 0.0.3
- Updated flutter_form version to 2.0.1 - Fixed bug where onTap was not working when header is set
## 0.0.2
- Updated flutter_form version
## 0.0.1
- Initial port

BIN
MediaPickerGifNew.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 MiB

View file

@ -17,11 +17,11 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ProviderScope( return ProviderScope(
child: MaterialApp( child: MaterialApp(
title: 'Flutter Demo', title: 'Media Picker Example',
theme: ThemeData( theme: ThemeData(
primarySwatch: Colors.blue, primarySwatch: Colors.blue,
), ),
home: const MyHomePage(title: 'Flutter Demo Home Page'), home: const MyHomePage(title: 'Media Picker Example'),
), ),
); );
} }
@ -45,13 +45,13 @@ class _MyHomePageState extends State<MyHomePage> {
), ),
body: Center( body: Center(
child: ElevatedButton( child: ElevatedButton(
child: const Text('Media Picker'), child: const Text('Media Picker Text Options'),
onPressed: () { onPressed: () {
showModalBottomSheet( showModalBottomSheet(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
context: context, context: context,
builder: (context) { builder: (context) {
return MediaPickerPage( return MediaPickerExample(
callback: () { callback: () {
Navigator.pop(context); Navigator.pop(context);
}, },

View file

@ -8,15 +8,17 @@ import 'package:flutter/material.dart';
import 'package:flutter_media_picker/flutter_media_picker.dart'; import 'package:flutter_media_picker/flutter_media_picker.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
class MediaPickerPage extends ConsumerStatefulWidget { class MediaPickerExample extends ConsumerStatefulWidget {
const MediaPickerPage({required this.callback, Key? key}) : super(key: key); const MediaPickerExample({required this.callback, Key? key})
: super(key: key);
final Function callback; final Function callback;
@override @override
ConsumerState<ConsumerStatefulWidget> createState() => _MediaPickerState(); ConsumerState<ConsumerStatefulWidget> createState() =>
_MediaPickerExampleState();
} }
class _MediaPickerState extends ConsumerState<MediaPickerPage> { class _MediaPickerExampleState extends ConsumerState<MediaPickerExample> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var mediaService = ref.read<MediaPickerService>(mediaPickerServiceProvider); var mediaService = ref.read<MediaPickerService>(mediaPickerServiceProvider);
@ -49,7 +51,7 @@ class _MediaPickerState extends ConsumerState<MediaPickerPage> {
height: 14, height: 14,
), ),
const Text( const Text(
'Maken', 'Create/Pick',
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
fontSize: 20, fontSize: 20,
@ -61,9 +63,14 @@ class _MediaPickerState extends ConsumerState<MediaPickerPage> {
MediaPicker( MediaPicker(
mediaPickerInputs: [ mediaPickerInputs: [
MediaPickerInputPhoto( MediaPickerInputPhoto(
label: 'Make photo',
// widget: const IconButtonWithText(
// icon: Icons.photo,
// iconText: "Make photo",
// ),
pickFile: mediaService.pickImageFile, pickFile: mediaService.pickImageFile,
checkPageSettings: { checkPageSettings: {
'title': 'Foto delen', 'title': 'Share photo',
'width': 125.0, 'width': 125.0,
'height': 200.0, 'height': 200.0,
}, },
@ -72,10 +79,15 @@ class _MediaPickerState extends ConsumerState<MediaPickerPage> {
}, },
), ),
MediaPickerInputVideo( MediaPickerInputVideo(
label: 'Make video',
// widget: const IconButtonWithText(
// icon: Icons.video_camera_front,
// iconText: "Make video",
// ),
pickFile: mediaService.pickVideoFile, pickFile: mediaService.pickVideoFile,
videoPlayerFactory: MediaPickerVideoPlayerFactory(), videoPlayerFactory: MediaPickerVideoPlayerFactory(),
checkPageSettings: { checkPageSettings: {
'title': 'Video delen', 'title': 'Share video',
'width': 122.5, 'width': 122.5,
'height': 200.0, 'height': 200.0,
}, },
@ -85,14 +97,48 @@ class _MediaPickerState extends ConsumerState<MediaPickerPage> {
), ),
if (!kIsWeb) if (!kIsWeb)
MediaPickerInputAudio( MediaPickerInputAudio(
checkPageSettings: {'title': 'Audio delen'}, label: 'Record audio',
// widget: const IconButtonWithText(
// icon: Icons.record_voice_over,
// iconText: "Record audio",
// ),
checkPageSettings: {'title': 'Share audio'},
onComplete: (MediaResult result) { onComplete: (MediaResult result) {
Navigator.pop(context); Navigator.pop(context);
}, },
audioService: audioService, audioService: audioService,
), ),
MediaPickerInputText( MediaPickerInputText(
checkPageSettings: {'title': 'Tekst delen'}, label: 'Write text',
// widget: const IconButtonWithText(
// icon: Icons.text_fields,
// iconText: "Write text",
// ),
checkPageSettings: {'title': 'Share text'},
onComplete: (MediaResult result) {
Navigator.pop(context);
},
),
MediaPickerInputFile(
label: 'Select file',
// widget: const IconButtonWithText(
// icon: Icons.file_copy,
// iconText: "Select file",
// ),
pickFile: mediaService.pickFile,
fileExtensions: [
'pdf',
'doc',
'png',
'jpg',
'docx',
'bmp',
'gif',
'txt',
],
checkPageSettings: {
'title': 'Share file',
},
onComplete: (MediaResult result) { onComplete: (MediaResult result) {
Navigator.pop(context); Navigator.pop(context);
}, },

View file

@ -70,7 +70,7 @@ class _MediaCheckPageState extends State<MediaCheckPage> {
widget.cancel(); widget.cancel();
formController.autoNextStep(); formController.autoNextStep();
}, },
child: const Text("Delen"), child: const Text('Share'),
), ),
), ),
), ),
@ -140,7 +140,7 @@ class _MediaCheckPageState extends State<MediaCheckPage> {
), ),
Expanded( Expanded(
child: FlutterFormInputMultiLine( child: FlutterFormInputMultiLine(
hint: "Voeg omschrijving toe...", hint: 'Add description...',
maxCharacters: 300, maxCharacters: 300,
controller: descriptionController), controller: descriptionController),
), ),
@ -149,7 +149,7 @@ class _MediaCheckPageState extends State<MediaCheckPage> {
), ),
FlutterFormInputSwitch( FlutterFormInputSwitch(
label: const Text( label: const Text(
'Deel op je tijdlijn', 'Share on time line',
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
fontSize: 18, fontSize: 18,
@ -162,7 +162,7 @@ class _MediaCheckPageState extends State<MediaCheckPage> {
), ),
FlutterFormInputSwitch( FlutterFormInputSwitch(
label: const Text( label: const Text(
'Bewaar in de kluis', 'Save in vault',
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
fontSize: 18, fontSize: 18,

View file

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/material.dart';
class IconButtonWithText extends StatelessWidget {
const IconButtonWithText({
super.key,
this.iconSize = 40,
this.iconText = 'Button',
this.iconTextSize = 16,
this.icon = Icons.file_copy,
});
final double iconSize;
final String iconText;
final double iconTextSize;
final IconData icon;
@override
Widget build(BuildContext context) {
return FittedBox(
fit: BoxFit.fitHeight,
child: Column(
children: [
Icon(
icon,
size: iconSize,
),
Text(
iconText,
style: TextStyle(fontSize: iconTextSize),
textAlign: TextAlign.center,
),
],
),
);
}
}

View file

@ -85,6 +85,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.4" version: "6.1.4"
file_picker:
dependency: transitive
description:
name: file_picker
url: "https://pub.dartlang.org"
source: hosted
version: "5.2.4"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter

View file

@ -6,26 +6,24 @@ import 'package:flutter/material.dart';
import 'package:flutter_media_picker/src/media_result.dart'; import 'package:flutter_media_picker/src/media_result.dart';
/// Abstract class for inputs used by [MediaPicker]. /// Abstract class for inputs used by [MediaPicker].
///
/// The [label] is used as the title in the header.
///
/// [onPressed] is called when the user has chosen the input to use.
///
/// [displayResult] is used when the checkpage parameter is set for the [MediaPicker].
/// The widget will be given as [displayResult] within the checkpage parameter.
///
/// [checkPageSettings] are some settings that can be set when needed so they can be used in the checkPage.
///
/// [onComplete] will be called when the user has selected/made the media.
/// If checkpage is set this method will be called when the [onComplete] is called in the checkPage.
abstract class MediaPickerInput { abstract class MediaPickerInput {
String label = "Media Picker input"; /// The [label] is used as the title for the object in the media picker and no [widget] has been given.
String label = 'Media Picker input';
/// The [widget] is the object that is used to show in the media picker where the user can click on.
Widget? widget;
/// [onPressed] is called when the user has chosen the input to use.
Future<MediaResult> onPressed(BuildContext context); Future<MediaResult> onPressed(BuildContext context);
/// [displayResult] is used when the checkpage parameter is set for the [MediaPicker].
/// The widget will be given as [displayResult] within the checkpage parameter.
Future<Widget> displayResult(MediaResult result); Future<Widget> displayResult(MediaResult result);
/// [checkPageSettings] are some settings that can be set when needed so they can be used in the checkPage.
Map<String, dynamic>? checkPageSettings; Map<String, dynamic>? checkPageSettings;
/// [onComplete] will be called when the user has selected/made the media.
/// If checkpage is set this method will be called when the [onComplete] is called in the checkPage.
void Function(MediaResult result)? onComplete; void Function(MediaResult result)? onComplete;
} }

View file

@ -4,10 +4,15 @@
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:file_picker/file_picker.dart';
abstract class MediaPickerService { abstract class MediaPickerService {
/// Returns [Uint8List] based on given [ImageSource]. /// Returns [Uint8List] based on given [ImageSource].
Future<Uint8List?> pickImageFile(); Future<Uint8List?> pickImageFile();
/// Returns [Uint8List] based on given [VideoSource]. /// Returns [Uint8List] based on given [VideoSource].
Future<Uint8List?> pickVideoFile(); Future<Uint8List?> pickVideoFile();
/// Returns [FilePickerResult] based on given [File].
Future<FilePickerResult?> pickFile(List<String> fileExtensions);
} }

View file

@ -12,10 +12,11 @@ import 'package:intl/intl.dart';
/// Input for audio used by [MediaPicker]. /// Input for audio used by [MediaPicker].
/// ///
/// This feature is only usable for nativa applications. /// This feature is only usable for native applications.
class MediaPickerInputAudio implements MediaPickerInput { class MediaPickerInputAudio implements MediaPickerInput {
MediaPickerInputAudio({ MediaPickerInputAudio({
this.label = "Audio", this.label = 'Audio',
this.widget,
this.checkPageSettings, this.checkPageSettings,
this.onComplete, this.onComplete,
required this.audioService, required this.audioService,
@ -29,6 +30,9 @@ class MediaPickerInputAudio implements MediaPickerInput {
@override @override
String label; String label;
@override
Widget? widget;
@override @override
Future<MediaResult> onPressed(BuildContext context) async { Future<MediaResult> onPressed(BuildContext context) async {
MediaResult audio = MediaResult(); MediaResult audio = MediaResult();
@ -42,7 +46,7 @@ class MediaPickerInputAudio implements MediaPickerInput {
if (content.fileValue != null) { if (content.fileValue != null) {
audio = content; audio = content;
} else { } else {
throw Exception("No recording returned"); throw Exception('No recording returned');
} }
}, },
inputStyling: inputStyling ?? AudioInputStyling(), inputStyling: inputStyling ?? AudioInputStyling(),

View file

@ -0,0 +1,86 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as path;
import '../../flutter_media_picker.dart';
/// Input for file used by [MediaPicker].
class MediaPickerInputFile implements MediaPickerInput {
MediaPickerInputFile({
this.label = 'File',
this.widget,
this.fileExtensions = const ['pdf', 'jpg', 'png'],
this.checkPageSettings,
this.onComplete,
this.pickFile,
});
final Future<FilePickerResult?> Function(List<String>)? pickFile;
final List<String> fileExtensions;
@override
String label;
@override
Widget? widget;
@override
Future<MediaResult> onPressed(BuildContext context) async {
var file = await pickFile?.call(fileExtensions);
if (file != null && file.files.first.bytes != null) {
return MediaResult(
fileValue: file.files.first.bytes,
fileType: path.extension(file.files.first.name),
fileName: file.files.first.name,
);
}
return MediaResult();
}
@override
Future<Widget> displayResult(MediaResult result) async {
if (result.fileValue != null) {
switch (result.fileType) {
case '.png':
case '.jpg':
case '.jpeg':
case '.webp':
case '.bmp':
case '.gif':
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!)),
)
]);
default:
}
}
return Container();
}
@override
Map<String, dynamic>? checkPageSettings;
@override
void Function(MediaResult value)? onComplete;
}

View file

@ -12,7 +12,8 @@ import 'package:flutter_media_picker/src/media_result.dart';
/// Input for photo used by [MediaPicker]. /// Input for photo used by [MediaPicker].
class MediaPickerInputPhoto implements MediaPickerInput { class MediaPickerInputPhoto implements MediaPickerInput {
MediaPickerInputPhoto({ MediaPickerInputPhoto({
this.label = "Foto", this.label = 'Photo',
this.widget,
this.checkPageSettings, this.checkPageSettings,
this.onComplete, this.onComplete,
this.pickFile, this.pickFile,
@ -23,6 +24,9 @@ class MediaPickerInputPhoto implements MediaPickerInput {
@override @override
String label; String label;
@override
Widget? widget;
@override @override
Future<MediaResult> onPressed(BuildContext context) async { Future<MediaResult> onPressed(BuildContext context) async {
var image = await pickFile?.call(); var image = await pickFile?.call();

View file

@ -11,7 +11,8 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
/// Input for text used by [MediaPicker]. /// Input for text used by [MediaPicker].
class MediaPickerInputText implements MediaPickerInput { class MediaPickerInputText implements MediaPickerInput {
MediaPickerInputText({ MediaPickerInputText({
this.label = "Tekst", this.label = 'Text',
this.widget,
this.checkPageSettings, this.checkPageSettings,
this.onComplete, this.onComplete,
}); });
@ -19,6 +20,9 @@ class MediaPickerInputText implements MediaPickerInput {
@override @override
String label; String label;
@override
Widget? widget;
@override @override
Future<MediaResult> onPressed(BuildContext context) async { Future<MediaResult> onPressed(BuildContext context) async {
return MediaResult(); return MediaResult();

View file

@ -10,7 +10,8 @@ import 'package:flutter_media_picker/flutter_media_picker.dart';
/// Input for video used by [MediaPicker]. /// Input for video used by [MediaPicker].
class MediaPickerInputVideo implements MediaPickerInput { class MediaPickerInputVideo implements MediaPickerInput {
MediaPickerInputVideo({ MediaPickerInputVideo({
this.label = "Video", this.label = 'Video',
this.widget,
this.checkPageSettings, this.checkPageSettings,
this.onComplete, this.onComplete,
this.pickFile, this.pickFile,
@ -20,6 +21,9 @@ class MediaPickerInputVideo implements MediaPickerInput {
final Future<Uint8List?> Function()? pickFile; final Future<Uint8List?> Function()? pickFile;
final VideoPlayerFactory videoPlayerFactory; final VideoPlayerFactory videoPlayerFactory;
@override
Widget? widget;
@override @override
String label; String label;

View file

@ -6,3 +6,4 @@ export 'input_audio.dart';
export 'input_photo.dart'; export 'input_photo.dart';
export 'input_text.dart'; export 'input_text.dart';
export 'input_video.dart'; export 'input_video.dart';
export 'input_file.dart';

View file

@ -100,18 +100,23 @@ import '../flutter_media_picker.dart';
/// ], /// ],
/// ); /// );
///``` ///```
class MediaPicker extends ConsumerWidget { class MediaPicker extends ConsumerWidget {
const MediaPicker({ const MediaPicker({
this.mediaPickerInputs, this.mediaPickerInputs,
this.header, this.inputsDirection = Axis.horizontal,
this.onComplete, this.onComplete,
this.mediaCheckPage, this.mediaCheckPage,
this.horizontalSpacing = 0,
this.verticalSpacing = 0,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
final List<MediaPickerInput>? mediaPickerInputs; final List<MediaPickerInput>? mediaPickerInputs;
final Widget Function(String label, Function onPressed)? header;
final void Function(MediaResult result)? onComplete; final void Function(MediaResult result)? onComplete;
final Axis inputsDirection;
final double horizontalSpacing;
final double verticalSpacing;
final Widget Function( final Widget Function(
Widget displayResult, Widget displayResult,
Map<String, dynamic>? inputSettings, Map<String, dynamic>? inputSettings,
@ -134,18 +139,21 @@ class MediaPicker extends ConsumerWidget {
inputs = mediaPickerInputs!; inputs = mediaPickerInputs!;
} }
return Column( return Wrap(
alignment: WrapAlignment.center,
direction: inputsDirection,
spacing: horizontalSpacing,
runSpacing: verticalSpacing,
children: [ children: [
for (final input in inputs) ...[ for (final input in inputs) ...[
const SizedBox(height: 2.5),
header?.call(input.label, (BuildContext ct) async {
await onPressedMediaType(ct, input);
}) ??
GestureDetector( GestureDetector(
onTap: () async { onTap: () async {
await onPressedMediaType(context, input); await onPressedMediaType(context, input);
}, },
child: Container( child: Wrap(
children: [
input.widget ??
Container(
height: 55, height: 55,
width: MediaQuery.of(context).size.width * 0.9, width: MediaQuery.of(context).size.width * 0.9,
decoration: const BoxDecoration( decoration: const BoxDecoration(
@ -167,9 +175,10 @@ class MediaPicker extends ConsumerWidget {
), ),
), ),
), ),
),
const SizedBox(height: 2.5),
], ],
),
),
]
], ],
); );
} }
@ -187,6 +196,7 @@ class MediaPicker extends ConsumerWidget {
MediaResult result = MediaResult( MediaResult result = MediaResult(
fileValue: content.fileValue, fileValue: content.fileValue,
textValue: content.textValue, textValue: content.textValue,
fileType: content.fileType,
checkPageResults: results, checkPageResults: results,
); );

View file

@ -10,6 +10,8 @@ class MediaResult {
this.textValue, this.textValue,
this.fileValue, this.fileValue,
this.checkPageResults, this.checkPageResults,
this.fileType,
this.fileName,
}); });
/// For textfield returns actual text, /// For textfield returns actual text,
@ -21,4 +23,10 @@ class MediaResult {
/// Returns the values from the checkPageResults if checkpage is set. /// Returns the values from the checkPageResults if checkpage is set.
final Map<String, dynamic>? checkPageResults; final Map<String, dynamic>? checkPageResults;
/// Returns the filetype when a file is selected with the FilePicker.
final String? fileType;
/// Returns the file name when a file is selected with the FilePicker.
final String? fileName;
} }

View file

@ -4,6 +4,7 @@
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_media_picker/src/abstracts/media_picker_service.dart'; import 'package:flutter_media_picker/src/abstracts/media_picker_service.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
@ -47,4 +48,19 @@ class MediaPickerFileService implements MediaPickerService {
await controller.setLooping(true); await controller.setLooping(true);
await controller.play(); await controller.play();
} }
@override
Future<FilePickerResult?> pickFile(List<String> extensions) async {
var file = await FilePicker.platform.pickFiles(
withData: true,
type: FileType.custom,
allowedExtensions: extensions,
);
if (file != null) {
return file;
}
return Future.value(null);
}
} }

View file

@ -12,7 +12,9 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
path: any
image_picker: any image_picker: any
file_picker: any
video_player: any video_player: any
path_provider: any path_provider: any
hooks_riverpod: any hooks_riverpod: any