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 createState() => _TestPageState(); TestPage(this.testId); } class _TestPageState extends State { 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), ) ], ); } }