import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:healthcare_user/common/settings.dart'; import 'package:image_picker/image_picker.dart'; import 'package:video_player/video_player.dart'; import 'package:flick_video_player/flick_video_player.dart'; import 'package:flutter_sound/flutter_sound.dart'; import 'package:assets_audio_player/assets_audio_player.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:intl/date_symbol_data_local.dart'; import 'dart:async'; import 'package:flutter/cupertino.dart'; import 'package:path/path.dart' as path; import 'package:intl/intl.dart' show DateFormat; import 'package:path_provider/path_provider.dart'; class ReportMySelf extends StatefulWidget { const ReportMySelf({Key? key}) : super(key: key); @override State createState() => _ReportMySelfState(); } class _ReportMySelfState extends State { TextEditingController problemNameController = TextEditingController(); TextEditingController descriptionController = TextEditingController(); TextEditingController dateInput = TextEditingController(); final ImagePicker _picker = ImagePicker(); String videoUrl=''; late VideoPlayerController _controller; late Future _initializeVideoPlayerFuture; late FlickManager flickManager; late FlutterSoundRecorder _recordingSession; final recordingPlayer = AssetsAudioPlayer(); String pathToAudio=''; bool _playAudio = false; String _timerText = '00:00:00'; bool isAudioButtonPressed=false; String recordingTime = '0:0'; // to store value bool isRecording = false; String problemPictureUrl=''; void initializer() async { pathToAudio = '/sdcard/Download/temp.wav'; _recordingSession = FlutterSoundRecorder(); await _recordingSession.openAudioSession( focus: AudioFocus.requestFocusAndStopOthers, category: SessionCategory.playAndRecord, mode: SessionMode.modeDefault, device: AudioDevice.speaker); await _recordingSession.setSubscriptionDuration(Duration(milliseconds: 10)); await initializeDateFormatting(); await Permission.microphone.request(); await Permission.storage.request(); await Permission.manageExternalStorage.request(); } @override void initState() { super.initState(); _controller = VideoPlayerController.networkUrl( Uri.parse(videoUrl,), ); flickManager = FlickManager( videoPlayerController: VideoPlayerController.networkUrl(Uri.parse(videoUrl,),) ); _initializeVideoPlayerFuture = _controller.initialize(); _controller.setLooping(false); /*initializer();*/ } @override void dispose() { // Ensure disposing of the VideoPlayerController to free up resources. _controller.dispose(); flickManager.dispose(); _recordingSession.dispositionStream(); pathToAudio=''; super.dispose(); recordingPlayer.stop(); _deleteCacheDir(); _deleteAppDir(); } Future _deleteCacheDir() async { Directory tempDir = await getTemporaryDirectory(); if (tempDir.existsSync()) { tempDir.deleteSync(recursive: true); } } Future _deleteAppDir() async { Directory appDocDir = await getApplicationDocumentsDirectory(); if (appDocDir.existsSync()) { appDocDir.deleteSync(recursive: true); } } Future startRecording() async { initializer(); setState(() { isRecording=true; }); Directory directory = Directory(path.dirname(pathToAudio)); if (!directory.existsSync()) { directory.createSync(); } _recordingSession=(await FlutterSoundRecorder().openAudioSession())!; await _recordingSession.startRecorder( toFile: pathToAudio, codec: Codec.pcm16WAV, ); recordTime(); StreamSubscription _recorderSubscription = _recordingSession.onProgress!.listen((e) { /*var date = DateTime.fromMillisecondsSinceEpoch(e.duration.inMilliseconds, isUtc: true); var timeText = DateFormat('mm:ss:SS', 'en_GB').format(date); setState(() { _timerText = timeText.substring(0, 8); });*/ }); _recorderSubscription.cancel(); } void recordTime() { var startTime = DateTime.now(); Timer.periodic(const Duration(seconds: 1), (Timer t) { var diff = DateTime.now().difference(startTime); if (!isRecording) { t.cancel(); //cancel function calling } setState(() { recordingTime = '${diff.inHours < 60 ? diff.inHours : 0}:${diff.inMinutes < 60 ? diff.inMinutes : 0}:${diff.inSeconds < 60 ? diff.inSeconds : 0}'; print(recordingTime); }); }); } Future stopRecording() async { setState(() { isRecording=false; }); _recordingSession.closeAudioSession(); return await _recordingSession.stopRecorder(); } Future playFunc() async { recordingPlayer.open( Audio.file(pathToAudio), autoStart: true, showNotification: true, ); } Future stopPlayFunc() async { recordingPlayer.stop(); } Future takeVideoFromCamera() async { try { final image = await _picker.pickVideo(source: ImageSource.camera); if (image == null) return; final imageTemp = File(image.path); AppSettings.preLoaderDialog(context); var res = await AppSettings.uploadVideoInReportMySelf(image); print(jsonDecode(res)); Navigator.of(context, rootNavigator: true).pop(); setState(() { videoUrl = jsonDecode(res)['picture']; _controller = VideoPlayerController.networkUrl(Uri.parse(videoUrl,),); flickManager = FlickManager( videoPlayerController: VideoPlayerController.networkUrl(Uri.parse(videoUrl,),) ); }); _initializeVideoPlayerFuture = _controller.initialize(); _controller.setLooping(true); } on PlatformException catch (e) { print('Failed to pick video: $e'); } } Future pickVideoFromGallery() async { try { final image = await _picker.pickVideo(source: ImageSource.gallery); if (image == null) return; final imageTemp = File(image.path); AppSettings.preLoaderDialog(context); var res = await AppSettings.uploadVideoInReportMySelf(image); print(jsonDecode(res)); Navigator.of(context, rootNavigator: true).pop(); setState(() { videoUrl = jsonDecode(res)['picture']; _controller = VideoPlayerController.networkUrl(Uri.parse(videoUrl,),); }); _initializeVideoPlayerFuture = _controller.initialize(); _controller.setLooping(true); } on PlatformException catch (e) { print('Failed to pick video: $e'); } } Future pickImageFromGallery() async { try { final image = await _picker.pickImage(source: ImageSource.gallery); if (image == null) return; final imageTemp = File(image.path); AppSettings.preLoaderDialog(context); var res = await AppSettings.uploadReportMyselfPicture(image); print(jsonDecode(res)); Navigator.of(context, rootNavigator: true).pop(); setState(() { problemPictureUrl = jsonDecode(res)['pictures'][0]; }); } on PlatformException catch (e) { print('Failed to pick image: $e'); } } Future takeImageFromCamera() async { try { final image = await _picker.pickImage(source: ImageSource.camera); if (image == null) return; final imageTemp = File(image.path); AppSettings.preLoaderDialog(context); var res = await AppSettings.uploadReportMyselfPicture(image); print(jsonDecode(res)); Navigator.of(context, rootNavigator: true).pop(); setState(() { problemPictureUrl = jsonDecode(res)['pictures'][0]; }); } on PlatformException catch (e) { print('Failed to pick image: $e'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppSettings.appBar('Report MySelf'), body: SingleChildScrollView( child: Container( child: Padding( padding: EdgeInsets.all(10), child:Column( children: [ Container( child: TextFormField( cursorColor: greyColor, controller: problemNameController, textCapitalization: TextCapitalization.words, decoration: const InputDecoration( prefixIcon: Icon( Icons.report_problem, color: greyColor, ), border: OutlineInputBorder( borderSide: BorderSide(color: primaryColor)), focusedBorder: OutlineInputBorder( borderSide: BorderSide(color:primaryColor), ), enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: primaryColor), ), labelText: 'Enter problem name', labelStyle: TextStyle( color: greyColor, //<-- SEE HERE ), ), ), ), const SizedBox( height: 10, ), Container( child: TextFormField( cursorColor: greyColor, controller: descriptionController, textCapitalization: TextCapitalization.words, decoration: const InputDecoration( prefixIcon: Icon( Icons.description, color: greyColor, ), border: OutlineInputBorder( borderSide: BorderSide(color: primaryColor)), focusedBorder: OutlineInputBorder( borderSide: BorderSide(color:primaryColor), ), enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: primaryColor), ), labelText: 'Description', labelStyle: TextStyle( color: greyColor, //<-- SEE HERE ), ), ), ), SizedBox(height: 10), Container( child: TextFormField( cursorColor: greyColor, controller: dateInput, decoration: textFormFieldDecorationBMI( Icons.calendar_today, 'Enter Date'), readOnly: true, onTap: () async { DateTime? pickedDate = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime(1950), lastDate: DateTime.now(), builder: (BuildContext context, Widget? child) { return Theme( data: ThemeData.dark().copyWith( colorScheme: ColorScheme.dark( primary: buttonColors, onPrimary: Colors.white, surface: buttonColors, onSurface: Colors.white, ), dialogBackgroundColor: primaryColor, ), child: child!, ); }, ); if (pickedDate != null) { print( pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 String formattedDate = DateFormat('dd-MM-yyyy').format(pickedDate); print( formattedDate); //formatted date output using intl package => 2021-03-16 setState(() { dateInput.text = formattedDate; //set output date to TextField value. }); } else {} }, ), ), SizedBox(height: 10), Row( children: [ IconButton( icon: Icon( Icons.audio_file, color: primaryColor, size: 40, ), onPressed: () { if(!isAudioButtonPressed){ setState(() { isAudioButtonPressed=true; }); } else{ setState(() { isAudioButtonPressed=false; pathToAudio=''; recordingTime = '0:0'; }); } }, ), SizedBox(width: 10,), IconButton( icon: Icon( Icons.video_camera_back_rounded, color: primaryColor, size: 40, ), onPressed: () { showModalBottomSheet( context: context, builder: (BuildContext context) { return SizedBox( height: 200, child: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( child: Icon( Icons.camera_alt_outlined, size: 100, color: primaryColor, ), onTap: () async { await takeVideoFromCamera(); Navigator.pop(context); }, ), SizedBox( width: MediaQuery.of(context).size.width * .20, ), GestureDetector( child: Icon( Icons.photo, size: 100, color: primaryColor, ), onTap: () async { await pickVideoFromGallery(); Navigator.pop(context); }, ), ], ), ), ); }); }, ), SizedBox(width: 10,), IconButton( icon: Icon( Icons.image, color: primaryColor, size: 40, ), onPressed: () async { showModalBottomSheet( context: context, builder: (BuildContext context) { return SizedBox( height: 200, child: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( child: Icon( Icons.camera_alt_outlined, size: 100, color: primaryColor, ), onTap: () async { await takeImageFromCamera(); Navigator.pop(context); }, ), SizedBox( width: MediaQuery.of(context).size.width * .20, ), GestureDetector( child: Icon( Icons.photo, size: 100, color: primaryColor, ), onTap: () async { await pickImageFromGallery(); Navigator.pop(context); }, ), ], ), ), ); }); }, ), /*SizedBox(width: 10,), IconButton( icon: Icon( Icons.description, color: primaryColor, size: 40, ), onPressed: () { }, ),*/ ], ), Visibility( visible: isAudioButtonPressed, child: Column( children: [ Container( child: Center( child: Text( recordingTime, style: TextStyle(fontSize: 70, color: Colors.red), ), ), ), SizedBox( height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( icon: Icon( Icons.mic, color: !isRecording?Colors.red:greyColor, ), onPressed: () { if(!isRecording){ startRecording(); } else{ AppSettings.longSuccessToast('please stop recording'); } }, ), SizedBox( width: 30, ), IconButton( icon: Icon( Icons.stop, color: isRecording?Colors.red:greyColor, ), onPressed: () { if(isRecording){ stopRecording(); } else{ AppSettings.longSuccessToast('please start recording'); } }, ), ], ), SizedBox( height: 20, ), Visibility( visible: pathToAudio!=''&&!isRecording, child:Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton.icon( style: ElevatedButton.styleFrom(elevation: 9.0, primary: Colors.red), onPressed: () { setState(() { _playAudio = !_playAudio; }); if (_playAudio) playFunc(); if (!_playAudio) stopPlayFunc(); }, icon: _playAudio ? Icon( Icons.stop, ) : Icon(Icons.play_arrow), label: _playAudio ? Text( "Stop", style: TextStyle( fontSize: 28, ), ) : Text( "Play", style: TextStyle( fontSize: 28, ), ), ), IconButton( icon: Icon( Icons.delete, color: Colors.red, size: 30, ), onPressed: () { setState(() { pathToAudio=''; recordingTime = '0:0'; }); }, ), ], ) ) ], )), Visibility( visible: videoUrl != '', child: Padding( padding: EdgeInsets.all(10), child: Container( height: MediaQuery.of(context).size.height * .30, width: double.infinity, child:FlickVideoPlayer( flickManager: flickManager, flickVideoWithControls: FlickVideoWithControls( videoFit: BoxFit.fill, controls: FlickPortraitControls( progressBarSettings: FlickProgressBarSettings(playedColor: Colors.green), ), ), ), /*FutureBuilder( future: _initializeVideoPlayerFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return AspectRatio( aspectRatio: _controller.value.aspectRatio, child: VideoPlayer(_controller), ); } else { return const Center( child: CircularProgressIndicator(), ); } }, ),*/ ), ), ), Visibility( visible: problemPictureUrl!='', child: Container( width: double.infinity, height: MediaQuery.of(context).size.height * .30, decoration: BoxDecoration( shape: BoxShape.rectangle, image: DecorationImage( image: NetworkImage(problemPictureUrl) as ImageProvider, // picked file fit: BoxFit.fill)), child: Stack(children: [ Positioned( right: 0, child: Container( child: IconButton( iconSize: 30, icon: const Icon( Icons.cancel, color: Colors.red, ), onPressed: () async { setState(() { problemPictureUrl=''; }); }, ), ), ) ]), ),), SizedBox(height: 10), Container( width: double.infinity, height: MediaQuery.of(context).size.height * .05, child: ElevatedButton( style: ElevatedButton.styleFrom( primary: buttonColors, // background onPrimary: Colors.black, // foreground ), onPressed: () async { if(problemNameController.text!=''&&(pathToAudio!=''||problemPictureUrl!=''||videoUrl!='')&&dateInput.text!=''){ AppSettings.preLoaderDialog(context); bool isOnline = await AppSettings.internetConnectivity(); if (isOnline) { var payload = new Map(); List picture=[]; picture.add({'url':problemPictureUrl}); payload["name"] = problemNameController.text.toString(); payload["description"] = descriptionController.text.toString(); payload["date"] = dateInput.text.toString(); payload["audio"] =pathToAudio.toString(); payload["video"] = videoUrl.toString(); payload["picture"] = picture; bool uploadStatus = await AppSettings.addReportMySelfProblem(payload); try { if (uploadStatus) { Navigator.of(context, rootNavigator: true) .pop(); AppSettings.longSuccessToast( 'Report problem added successfully'); Navigator.pop(context); } else { Navigator.of(context, rootNavigator: true) .pop(); AppSettings.longFailedToast( 'Fail to add report problem details'); } } catch (e) { print(e); Navigator.of(context, rootNavigator: true) .pop(); AppSettings.longFailedToast( 'Fail to add report problem details'); } } else{ AppSettings.longFailedToast('please check internet connection'); } } else{ AppSettings.longFailedToast('please enter valid details'); } }, child: const Text('Report a problem'), )), ], ), ), ), ) ); } }