This commit is contained in:
2025-10-01 08:15:05 +07:00
parent deb7aeb850
commit e39b4b64cc
12 changed files with 994 additions and 483 deletions

View File

@@ -0,0 +1,113 @@
import 'dart:convert';
import 'package:base_flutter/features/lesson/record_dialog.dart';
import 'package:record/record.dart';
import 'package:base_flutter/features/home/models.dart';
import 'package:flutter/material.dart';
import 'package:flutter_tts/flutter_tts.dart';
FlutterTts flutterTts = FlutterTts();
enum PositionEnum {
topLeft('top_left'),
topRight('top_right'),
bottomLeft('bottom_left'),
bottomRight('bottom_right');
final String value;
const PositionEnum(this.value);
}
class LessonScreen extends StatefulWidget {
const LessonScreen({super.key, required this.lessonResponse});
final LessonResponse lessonResponse;
@override
State<LessonScreen> createState() => _LessonScreenState();
}
class _LessonScreenState extends State<LessonScreen> {
@override
Widget build(BuildContext context) {
final record = AudioRecorder();
Widget containerText(String text) {
return InkWell(
onTap: () async {
var result = await flutterTts.speak(text);
},
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(16.0),
width: 300,
height: 120,
color: Colors.black54,
child: Text(text, style: const TextStyle(color: Colors.white, fontSize: 16)),
),
);
}
Widget buildTapToRecordWidget(String position, String content) {
switch (position) {
case 'top_left':
return Align(alignment: Alignment.topLeft, child: containerText(content));
case 'top_right':
return Align(alignment: Alignment.topRight, child: containerText(content));
case 'bottom_left':
return Align(alignment: Alignment.bottomLeft, child: containerText(content));
case 'bottom_right':
return Align(alignment: Alignment.bottomRight, child: containerText(content));
default:
return const SizedBox.shrink();
}
}
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: MemoryImage(base64Decode(widget.lessonResponse.image)),
fit: BoxFit.cover, // Optional: Adjust as needed
),
),
child: Column(
children: [
SizedBox(height: kToolbarHeight,),
Text(widget.lessonResponse.widget.tapToRecordWidget.position),
buildTapToRecordWidget(
widget.lessonResponse.widget.tapToRecordWidget.position,
widget.lessonResponse.widget.tapToRecordWidget.content,
),
Spacer(),
Text(widget.lessonResponse.widget.tapToSpeechWidget.position),
buildTapToRecordWidget(
widget.lessonResponse.widget.tapToSpeechWidget.position,
widget.lessonResponse.widget.tapToSpeechWidget.content,
),
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: RecordDialog(),
),
);
},
icon: Icon(Icons.mic, size: 48),
),
],
),
),
);
}
}

View File

@@ -0,0 +1,79 @@
import 'package:flutter/material.dart';
import 'package:record/record.dart';
import 'package:audioplayers/audioplayers.dart';
class RecordDialog extends StatefulWidget {
const RecordDialog({super.key});
@override
State<RecordDialog> createState() => _RecordDialogState();
}
class _RecordDialogState extends State<RecordDialog> {
final AudioRecorder _recorder = AudioRecorder();
final AudioPlayer _player = AudioPlayer();
String? _recordedPath;
bool _isRecording = false;
@override
void dispose() {
_recorder.dispose();
_player.dispose();
super.dispose();
}
Future<void> _toggleRecord() async {
if (!_isRecording) {
if (await _recorder.hasPermission()) {
await _recorder.start(const RecordConfig(), path: 'myFile.m4a');
setState(() => _isRecording = true);
}
} else {
final path = await _recorder.stop();
setState(() {
_isRecording = false;
_recordedPath = path;
});
}
}
Future<void> _playRecording() async {
if (_recordedPath != null) {
await _player.play(DeviceFileSource(_recordedPath!));
}
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: 300,
height: 400,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 150),
IconButton(
icon: Icon(_isRecording ? Icons.stop : Icons.mic_none_sharp, size: 96),
onPressed: _toggleRecord,
),
if (_recordedPath != null && !_isRecording)
IconButton(
icon: const Icon(Icons.play_arrow, size: 48),
onPressed: _playRecording,
),
const Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text('Close')),
// Add more buttons as needed
],
),
],
),
);
}
}
// Usage in your code: