// SPDX-FileCopyrightText: 2022 Iconica // // SPDX-License-Identifier: BSD-3-Clause import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../flutter_media_picker.dart'; /// [MediaPicker] is a widget that allows the user to select/make media from a variety of sources. /// /// [mediaPickerInputs] makes it able to choose with types of media the user can select by providing a list of [MediaPickerInput]s. /// /// By setting header the look of each media type item can be changed. /// A label is provided which is set by the [MediaPickerInput.title] property. /// The onpressed should be set so the to select that media type. /// if null a standard header is used. /// /// [onComplete] is the callback that will be fired when the medie is made or when the checkpage is completed. /// With the results provided. /// /// Via the [mediaCheckPage] a widget can be provided where the user can confirm the media they selected. /// The displayresult is a widget that shows of the chosen/made media. /// The inputSettings are settings set per input some media type specifics can be set. /// /// Example: /// ```dart /// Wrap( /// children: [ /// Container( /// width: MediaQuery.of(context).size.width, /// decoration: const BoxDecoration( /// color: Colors.white, /// borderRadius: BorderRadius.only( /// topLeft: Radius.circular(15), /// topRight: Radius.circular(15), /// ), /// ), /// child: Column( /// children: [ /// const SizedBox( /// height: 8, /// ), /// Container( /// width: 70, /// height: 5, /// decoration: BoxDecoration( /// borderRadius: BorderRadius.circular(100), /// color: const Color(0xFF000000).withOpacity(0.50), /// ), /// ), /// const SizedBox( /// height: 14, /// ), /// const Text( /// 'Maken', /// style: TextStyle( /// fontWeight: FontWeight.w900, /// fontSize: 20, /// ), /// ), /// const SizedBox( /// height: 15, /// ), /// MediaPicker( /// mediaPickerInputs: [ /// MediaPickerInputPhoto( /// checkPageSettings: {'title': 'Foto delen'}, /// onComplete: (MediaResult result) {}, /// ), /// MediaPickerInputVideo( /// checkPageSettings: {'title': 'Video delen'}, /// onComplete: (MediaResult result) {}, /// ), /// if (!kIsWeb) /// MediaPickerInputAudio( /// checkPageSettings: {'title': 'Audio delen'}, /// onComplete: (MediaResult result) {}, /// ), /// MediaPickerInputText( /// checkPageSettings: {'title': 'Tekst delen'}, /// onComplete: (MediaResult result) {}, /// ), /// ], /// mediaCheckPage: (Widget displayResult, /// Map? inputSettings, /// Function onComplete) => /// MediaCheckPage( /// displayResult: displayResult, /// inputSettings: inputSettings ?? {}, /// onComplete: onComplete, /// ), /// ), /// const SizedBox( /// height: 30, /// ), /// ], /// ), /// ), /// ], /// ); ///``` class MediaPicker extends ConsumerWidget { const MediaPicker({ this.mediaPickerInputs, this.header, this.iconButton, this.onComplete, this.mediaCheckPage, this.buttonType = ButtonType.text, this.horizontalSpacing = 0, this.verticalSpacing = 0, Key? key, }) : super(key: key); final List? mediaPickerInputs; final Widget Function(String label, Function onPressed)? header; final Widget Function(String label, Widget icon, Function onPressed)? iconButton; final void Function(MediaResult result)? onComplete; final ButtonType buttonType; final double horizontalSpacing; final double verticalSpacing; final Widget Function( Widget displayResult, Map? inputSettings, Function(Map results) onComplete)? mediaCheckPage; @override Widget build(BuildContext context, ref) { List inputs = [ MediaPickerInputPhoto(), MediaPickerInputVideo( videoPlayerFactory: ref.read(videoFactoryProvider), ), if (!kIsWeb) MediaPickerInputAudio( audioService: ref.read(audioPlayerServiceProvider), ), ]; if (mediaPickerInputs != null) { inputs = mediaPickerInputs!; } return Wrap( alignment: WrapAlignment.center, direction: Axis.horizontal, spacing: horizontalSpacing, runSpacing: verticalSpacing, children: [ if (buttonType == ButtonType.text) ...[ for (final input in inputs) ...[ const SizedBox(height: 2.5), header?.call(input.label, (BuildContext ct) async { await onPressedMediaType(ct, input); }) ?? GestureDetector( onTap: () async { await onPressedMediaType(context, input); }, child: 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, ), ), ), ), ), const SizedBox(height: 2.5), ], ] else ...[ for (final input in inputs) ...[ iconButton?.call(input.label, input.icon, (BuildContext ct) async { await onPressedMediaType(ct, input); }) ?? GestureDetector( onTap: () async { await onPressedMediaType(context, input); }, child: Wrap( children: [ input.icon, ], ), ), ], ] ], ); } Future onPressedMediaType( BuildContext context, MediaPickerInput input) async { MediaResult content = await input.onPressed(context); if (mediaCheckPage != null && (input.runtimeType == MediaPickerInputText || _hasContent(content))) { var checkPage = mediaCheckPage!( await input.displayResult(content), input.checkPageSettings, (Map results) { MediaResult result = MediaResult( fileValue: content.fileValue, textValue: content.textValue, fileType: content.fileType, checkPageResults: results, ); if (input.onComplete != null) { input.onComplete!(result); } if (onComplete != null) { onComplete!(result); } }, ); // ignore: use_build_context_synchronously Navigator.push( context, MaterialPageRoute( builder: (context) => checkPage, ), ); } else { if (input.onComplete != null) { input.onComplete!(content); } if (onComplete != null) { onComplete!(content); } } } bool _hasContent(MediaResult content) { return content.fileValue != null || content.textValue != null; } }