mirror of
https://github.com/Iconica-Development/flutter_media_picker.git
synced 2025-05-19 08:53:45 +02:00
Merge pull request #4 from Iconica-Development/feature/add-file-picker
Added file picker and option to change widget
This commit is contained in:
commit
4ba167aacb
21 changed files with 345 additions and 103 deletions
|
@ -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
28
CHANGELOG.md
28
CHANGELOG.md
|
@ -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
BIN
MediaPickerGifNew.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 4 MiB |
|
@ -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);
|
||||||
},
|
},
|
||||||
|
|
|
@ -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);
|
||||||
},
|
},
|
||||||
|
|
|
@ -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,
|
||||||
|
|
40
example/lib/widgets/icon_button_with_text.dart
Normal file
40
example/lib/widgets/icon_button_with_text.dart
Normal 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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
86
lib/src/inputs/input_file.dart
Normal file
86
lib/src/inputs/input_file.dart
Normal 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;
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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,42 +139,46 @@ 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),
|
GestureDetector(
|
||||||
header?.call(input.label, (BuildContext ct) async {
|
onTap: () async {
|
||||||
await onPressedMediaType(ct, input);
|
await onPressedMediaType(context, input);
|
||||||
}) ??
|
},
|
||||||
GestureDetector(
|
child: Wrap(
|
||||||
onTap: () async {
|
children: [
|
||||||
await onPressedMediaType(context, input);
|
input.widget ??
|
||||||
},
|
Container(
|
||||||
child: 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(
|
border: Border(
|
||||||
border: Border(
|
bottom: BorderSide(
|
||||||
bottom: BorderSide(
|
color: Color(0xFF979797),
|
||||||
color: Color(0xFF979797),
|
width: 1,
|
||||||
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
child: Align(
|
),
|
||||||
alignment: Alignment.centerLeft,
|
),
|
||||||
child: Padding(
|
]
|
||||||
padding: const EdgeInsets.only(left: 15),
|
|
||||||
child: Text(
|
|
||||||
input.label,
|
|
||||||
style: Theme.of(context).textTheme.headline6,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue