mnemo_cards/lib/features/tests/test_page.dart
2024-06-21 22:12:29 +03:00

197 lines
6.5 KiB
Dart

import 'dart:developer';
import 'dart:math' as math;
import 'package:auto_route/auto_route.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:mnemo_cards/main.dart';
import 'package:mnemo_cards/managers/audio_player.dart';
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
import 'package:rxdart/rxdart.dart';
import '../../di/locator.dart';
import 'scroll_physics.dart';
import 'test_complete_widget.dart';
import 'test_progress_widget.dart';
import 'test_widgets/input_buttons_test.dart';
import 'test_widgets/simple_test.dart';
@RoutePage()
class TestPage extends StatefulWidget {
final String testId;
@override
State<StatefulWidget> createState() => _TestPageState();
TestPage(this.testId);
}
class _TestPageState extends State<TestPage> {
PageController get pageController => locator.testManager.pageController;
int? lastSkipIndex;
int? _lastAudioQuestionId;
@override
void initState() {
super.initState();
locator.testManager.setActiveTest(widget.testId);
locator.testManager.preloadImages(context);
pageController.addListener(_pageScrollListener);
}
@override
void dispose() {
pageController.removeListener(_pageScrollListener);
super.dispose();
}
void _pageScrollListener() {
if (!pageController.hasClients) {
return;
}
final index = pageController.page!.floor();
print('Current index $index, lastAudio $_lastAudioQuestionId');
if (index < locator.testManager.questions.length) {
final question = locator.testManager.questions[index];
if (question.id != _lastAudioQuestionId) {
print('AUDIO $_lastAudioQuestionId ${question.id}');
_lastAudioQuestionId = question.id;
try {
if (globalSharedPreferences.getBool('auto_play_sound_tests') !=
false) {
AudioPlayer.playAudio((question as dynamic).audio);
}
} catch (e, s) {}
}
}
if (index == lastSkipIndex) {
return;
}
print('Will try to skip $index, ${locator.testManager.questions.length}');
if (index > 0 && index <= locator.testManager.questions.length) {
final prevId = locator.testManager.questions[index - 1].id!;
final state = locator.testManager.getState(prevId);
if (state?.isAnswered == false) {
print('Skipping $index ${state?.word}');
locator.testManager.skip(prevId);
lastSkipIndex = index;
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: StreamBuilder(
stream: locator.testManager.testHolder.asStream.takeWhileInclusive(
(state) => state?.questions.isNotEmpty != true,
),
builder: (context, s) {
if (!s.hasData || s.requireData!.questions.isEmpty) {
return Scaffold(
body: Center(
child: Text('Загружаю тест...'),
),
);
}
WidgetsBinding.instance.addPostFrameCallback((_) {
_pageScrollListener();
});
final keys = List.generate(
locator.testManager.questions.length,
(v) =>
GlobalKey(debugLabel: locator.testManager.questions[v].word),
);
return Scaffold(
backgroundColor: locator.testManager.color.withOpacity(0.25),
body: SafeArea(
child: Builder(builder: (context) {
return Column(
children: [
SizedBox(
height:
(64.h - 20.h - MediaQuery.of(context).padding.top) /
2,
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0.w),
child: const TestProgressWidget(),
),
Expanded(
child: PageView.builder(
physics: RightBlockedScrollPhysics(
canScroll: _canScroll,
),
controller: locator.testManager.pageController,
itemBuilder: (context, index) {
if (index > locator.testManager.questions.length) {
return null;
}
if (index == locator.testManager.questions.length) {
return TestCompleteWidget(
locator.testManager.states,
locator.testManager.color,
);
}
final question = locator.testManager.getTest(index);
return switch (question.questionType) {
TestQuestionType.simple => SimpleTestWidget(
question as SimpleTestQuestionBody,
key: keys[index],
),
TestQuestionType.input_buttons =>
InputButtonsTestWidget(
question as InputButtonsTestQuestionBody,
key: keys[index]),
TestQuestionType.matrix => Container(),
TestQuestionType.match => Container(),
// TODO: Handle this case.
TestQuestionType.undefined =>
throw UnimplementedError(),
};
},
),
),
],
);
}),
),
);
}),
);
}
bool _canScroll() {
return locator.testManager.pageController.hasClients &&
locator.testManager.pageController.page !=
locator.testManager.questions.length;
}
}
class _LifeWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: [
Icon(Icons.ac_unit_outlined),
SizedBox(
width: 2,
),
Text(
'30',
style: TextStyle(fontSize: 22),
)
],
);
}
}