audio
This commit is contained in:
parent
6919ef1e6c
commit
69afc51781
7 changed files with 259 additions and 203 deletions
Binary file not shown.
117
lib/features/tests/test_widgets/common_test_question_widget.dart
Normal file
117
lib/features/tests/test_widgets/common_test_question_widget.dart
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_tts/flutter_tts.dart';
|
||||
|
||||
import '../../../main.dart';
|
||||
import '../../../widgets/game_card_widget.dart';
|
||||
import 'test_image.dart';
|
||||
|
||||
class CommonTestQuestionWidget extends StatelessWidget {
|
||||
final String? text;
|
||||
final String? image;
|
||||
final String? audio;
|
||||
|
||||
CommonTestQuestionWidget({
|
||||
this.text,
|
||||
this.image,
|
||||
this.audio,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context).textTheme;
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (image != null)
|
||||
Flexible(
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
margin: const EdgeInsets.all(4.0),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius:
|
||||
BorderRadius.circular(GameCardWidget.borderRadius),
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: text == null ? 1 : 1.5,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
TestImageWidget(
|
||||
TestImage.image(image!),
|
||||
),
|
||||
if (audio != null && text == null)
|
||||
Container(
|
||||
padding: EdgeInsets.all(4.0.h),
|
||||
alignment: Alignment.topRight,
|
||||
child: IconButton(
|
||||
icon: Image.asset(
|
||||
'icons/sound_on.png',
|
||||
width: 26,
|
||||
),
|
||||
onPressed: () => _playAudio(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
else if (text == null && audio != null)
|
||||
Flexible(
|
||||
child: Center(
|
||||
child: IconButton(
|
||||
icon: Image.asset(
|
||||
'icons/sound_on.png',
|
||||
width: 80,
|
||||
height: 80,
|
||||
),
|
||||
onPressed: () => _playAudio(),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (text != null)
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
text!,
|
||||
style: theme.headlineLarge,
|
||||
),
|
||||
if (audio != null)
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 4.w, top: 4.h),
|
||||
child: IconButton(
|
||||
icon: Image.asset(
|
||||
'icons/sound_on.png',
|
||||
width: 26,
|
||||
height: theme.headlineLarge?.fontSize,
|
||||
),
|
||||
onPressed: () => _playAudio(),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _playAudio() async {
|
||||
if (globalSharedPreferences.getBool('sound_on') != false && audio != null) {
|
||||
FlutterTts flutterTts = FlutterTts();
|
||||
var playText = audio!;
|
||||
if (audio!.contains('_')) {
|
||||
final lang = audio!.split('_').first;
|
||||
playText = audio!.replaceFirst('${lang}_', '');
|
||||
await flutterTts.setLanguage(lang);
|
||||
}
|
||||
await flutterTts.setSpeechRate(0.5);
|
||||
flutterTts.speak(playText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import 'package:collection/collection.dart';
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mnemo_cards/features/tests/test_manager.dart';
|
||||
import 'package:mnemo_cards/features/tests/test_widgets/common_test_question_widget.dart';
|
||||
import 'package:mnemo_cards/features/tests/test_widgets/test_image.dart';
|
||||
import 'package:mnemo_cards/theme/themes.dart';
|
||||
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
|
||||
|
|
@ -47,42 +48,11 @@ class InputButtonsTestWidget extends StatelessWidget {
|
|||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (model.image != null)
|
||||
Container(
|
||||
margin: const EdgeInsets.all(4.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
AspectRatio(
|
||||
aspectRatio: model.text == null ? 1 : 1.5,
|
||||
child: TestImageWidget(
|
||||
TestImage.image(model.image!),
|
||||
),
|
||||
),
|
||||
if (model.text != null)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Center(
|
||||
child: Text(
|
||||
model.text!,
|
||||
style: theme.headlineLarge,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
else
|
||||
Flexible(
|
||||
child: Center(
|
||||
child: Text(
|
||||
model.text!,
|
||||
style: theme.headlineLarge,
|
||||
),
|
||||
Expanded(
|
||||
child: CommonTestQuestionWidget(
|
||||
text: model.text,
|
||||
image: model.image,
|
||||
audio: model.audio,
|
||||
),
|
||||
),
|
||||
StatefulBuilder(builder: (context, setState) {
|
||||
|
|
@ -118,7 +88,7 @@ class InputButtonsTestWidget extends StatelessWidget {
|
|||
}
|
||||
|
||||
int splitIndex = 0;
|
||||
if (model.template.length * 30 > constraints.maxWidth * 0.9) {
|
||||
if (model.template.length * 32 > constraints.maxWidth * 0.9) {
|
||||
splitIndex = model.template.indexOf(
|
||||
' ',
|
||||
(model.template.length / 2).ceil(),
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@ import 'dart:math';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_tts/flutter_tts.dart';
|
||||
import 'package:mnemo_cards/features/tests/test_manager.dart';
|
||||
import 'package:mnemo_cards/features/tests/test_widgets/common_test_question_widget.dart';
|
||||
import 'package:mnemo_cards/features/tests/test_widgets/test_image.dart';
|
||||
import 'package:mnemo_cards/main.dart';
|
||||
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
|
||||
|
||||
import '../../../di/locator.dart';
|
||||
|
|
@ -28,7 +31,6 @@ class SimpleTestWidget extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context).textTheme;
|
||||
final random = Random(state.seed);
|
||||
final buttons = [...model.buttons]..shuffle(random);
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
|
|
@ -37,32 +39,11 @@ class SimpleTestWidget extends StatelessWidget {
|
|||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (model.image != null)
|
||||
Flexible(
|
||||
flex: 4,
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(4.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius:
|
||||
BorderRadius.circular(GameCardWidget.borderRadius),
|
||||
),
|
||||
child: TestImageWidget(
|
||||
TestImage.image(model.image!),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (model.text != null)
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Center(
|
||||
child: Text(
|
||||
model.text!,
|
||||
style: theme.headlineLarge,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: CommonTestQuestionWidget(
|
||||
text: model.text,
|
||||
image: model.image,
|
||||
audio: model.audio,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
|
|
|
|||
|
|
@ -50,12 +50,12 @@ class HttpRepository extends Repository with Api {
|
|||
ExternalIdType idType,
|
||||
String? name,
|
||||
) async {
|
||||
try {
|
||||
final r = await _dio.post<String>('$path/user/create', data: {
|
||||
'token': externalId,
|
||||
'tokenType': idType.name,
|
||||
'name': name,
|
||||
}).catchError(
|
||||
(error, stackTrace) => log('', error: error, stackTrace: stackTrace));
|
||||
});
|
||||
//todo add client header encryption ??
|
||||
final authToken = r.headers[HttpHeaders.authorizationHeader]!.last;
|
||||
return (
|
||||
|
|
@ -64,6 +64,10 @@ class HttpRepository extends Repository with Api {
|
|||
),
|
||||
authToken,
|
||||
);
|
||||
} on DioException catch (e, s) {
|
||||
log('User create error', error: e, stackTrace: s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
void setAuthToken(String? authToken) {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ class UserManager {
|
|||
ExternalIdType idType,
|
||||
String? name,
|
||||
) async {
|
||||
await locator.packCacheManager.clearCache();
|
||||
final (user, token) =
|
||||
await _repository.createOrGetUser(externalId, idType, name);
|
||||
_setAuthToken(token);
|
||||
|
|
|
|||
|
|
@ -33,17 +33,8 @@ class AvailablePack extends StatelessWidget {
|
|||
Analytics.availablePackOpened(cardPack);
|
||||
return Column(
|
||||
children: [
|
||||
CardPackHeader(
|
||||
cardPack.title,
|
||||
cardPack.subtitle,
|
||||
Colors.transparent,
|
||||
),
|
||||
CardPackHeader.fromDto(cardPack),
|
||||
Expanded(
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () =>
|
||||
locator.packUpdater.updatePackAndSaveImages(cardPack.id),
|
||||
backgroundColor: Colors.white,
|
||||
color: cardPack.color?.asColor ?? Colors.black,
|
||||
child: ListView(
|
||||
physics: BouncingScrollPhysics(
|
||||
decelerationRate: ScrollDecelerationRate.fast,
|
||||
|
|
@ -53,11 +44,6 @@ class AvailablePack extends StatelessWidget {
|
|||
StatefulBuilder(builder: (context, setState) {
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 1,
|
||||
color: cardPack.color?.asColor ??
|
||||
Colors.grey.withOpacity(0.5),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: cardPack.color?.asColor?.withOpacity(0.1),
|
||||
|
|
@ -65,7 +51,6 @@ class AvailablePack extends StatelessWidget {
|
|||
alignment: Alignment.center,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: CardsView(_cardsViewController, cardPack),
|
||||
|
||||
),
|
||||
Container(
|
||||
height: 1,
|
||||
|
|
@ -103,8 +88,7 @@ class AvailablePack extends StatelessWidget {
|
|||
);
|
||||
}),
|
||||
_Button('shuffle.png', () async {
|
||||
final cards =
|
||||
_cardsViewController.state.packCards;
|
||||
final cards = _cardsViewController.state.packCards;
|
||||
if (cards.isEmpty) return;
|
||||
final index = (_cardsViewController.offsetCards +
|
||||
Random().nextInt(
|
||||
|
|
@ -167,7 +151,6 @@ class AvailablePack extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Hero(
|
||||
tag: 'bottom',
|
||||
child: SizedBox(
|
||||
|
|
|
|||
Loading…
Reference in a new issue