You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cloudsolutions-atoms/lib/views/widgets/sound/record_sound.dart

193 lines
6.2 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:record_mp3/record_mp3.dart';
import 'package:rive/rive.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/views/widgets/sound/sound_player.dart';
import '../../../new_views/app_style/app_color.dart';
import '../../../new_views/common_widgets/app_text_form_field.dart';
class RecordSound extends StatefulWidget {
final Function(String) onRecord;
final Function(String) onStop;
final bool enabled;
const RecordSound({Key key, @required this.onRecord, this.onStop, this.enabled = true}) : super(key: key);
@override
State<RecordSound> createState() => _RecordSoundState();
}
class _RecordSoundState extends State<RecordSound> {
// FlutterSoundRecorder _myRecorder = FlutterSoundRecorder();
bool _recorderIsOpened = false;
bool _recording = false;
bool _played = false;
String _record;
Artboard _rive;
Timer _timer;
TextEditingController _timeController;
@override
void setState(VoidCallback fn) {
if (mounted) super.setState(fn);
}
@override
void initState() {
super.initState();
_timeController = TextEditingController();
_recorderIsOpened = true;
// RecordMp3.instance.start(recordFilePath, (type) {
// // record fail callback
// });
// _myRecorder.openRecorder().then((value) {
// _recorderIsOpened = true;
// setState(() {});
// });
// Load the animation file from the bundle, note that you could also
// download this. The RiveFile just expects a list of bytes.
rootBundle.load('assets/rives/recording.riv').then(
(data) async {
// Load the RiveFile from the binary data.
final file = RiveFile.import(data);
// The artboard is the root of the animation and gets drawn in the
// Rive widget.
final artboard = file.mainArtboard;
// Add a controller to play back a known animation on the main/default
// artboard.We store a reference to it so we can toggle playback.
artboard.addController(SimpleAnimation('recording'));
_rive = artboard;
setState(() {});
},
);
}
@override
void dispose() {
_timeController?.dispose();
// Be careful : you must `close` the audio session when you have finished with it.
RecordMp3.instance.stop();
//_myRecorder.closeRecorder();
// _myRecorder = null;
super.dispose();
}
String recordingFileDirectory;
_startRecording() async {
PermissionStatus status = await Permission.microphone.request();
if (!status.isGranted) {
PermissionStatus status = await Permission.microphone.request();
if (!status.isGranted) {
Fluttertoast.showToast(msg: "Permission Denied");
return;
}
}
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
setState(() {
String recordTime = ((timer?.tick ?? 0) / 60)?.toStringAsFixed(2)?.replaceFirst(".", ":");
if (recordTime.length == 4 || recordTime.length == 7) {
recordTime = "0$recordTime";
}
_timeController.text = recordTime;
});
});
_rive.addController(SimpleAnimation('recording'));
if (!_recorderIsOpened) {
// await _myRecorder.openRecorder();
_recorderIsOpened = true;
}
final Directory tempDir = await getTemporaryDirectory();
recordingFileDirectory = "${tempDir.path}/record_${DateTime.now().millisecondsSinceEpoch}.mp3";
RecordMp3.instance.start(recordingFileDirectory, (type) {
// record fail callback
});
// await _myRecorder.startRecorder(toFile: "record_${DateTime.now().millisecondsSinceEpoch}.mp3", codec: Codec.aacADTS, sampleRate: 360000, bitRate: 360000);
_recording = true;
setState(() {});
}
_stopRecording() async {
if (!_recording) {
setState(() {});
return;
}
if (_timer?.isActive ?? false) {
_timer.cancel();
}
RecordMp3.instance.stop();
//String path = (await _myRecorder.stopRecorder()).toString();
_record = recordingFileDirectory;
widget.onRecord(recordingFileDirectory);
_recording = false;
setState(() {});
}
_cancelRecording() async {
if (!_recording) return;
RecordMp3.instance.stop();
// String path = await _myRecorder.stopRecorder();
// _myRecorder.deleteRecord(fileName: path);
_rive.addController(SimpleAnimation('delete'));
// rebuild();
_recording = false;
await Future.delayed(const Duration(seconds: 1));
if (!_recording) setState(() {});
// _message.memoryAudio.;
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Stack(
alignment: AlignmentDirectional.centerEnd,
children: [
AppTextFormField(
enable: false,
controller: _timeController,
labelText: context.translation.recordVoice,
initialValue: (_timeController?.text?.isEmpty ?? true) ? "00:00" : _timeController?.text,
suffixIcon:
(_recording ? "record".toLottieAsset(height: 24) : (_record != null ? "trash" : "mic").toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, height: 24))
.paddingOnly(end: 16),
),
SizedBox(height: 50.toScreenHeight, width: 50.toScreenWidth).onPress(() {
if (_recording) {
_stopRecording();
} else if (_record != null) {
_timeController?.text = "00:00";
widget.onRecord(null);
_record = null;
setState(() {});
} else {
_startRecording();
}
}),
],
),
if (_record != null) 8.height,
if (_record != null) ASoundPlayer(audio: _record),
],
);
}
}