150 lines
4.6 KiB
Dart
150 lines
4.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../models/custom_kanji_item.dart';
|
|
import '../services/custom_deck_repository.dart';
|
|
import 'custom_quiz_screen.dart';
|
|
|
|
class CustomSrsScreen extends StatefulWidget {
|
|
const CustomSrsScreen({super.key});
|
|
|
|
@override
|
|
State<CustomSrsScreen> createState() => _CustomSrsScreenState();
|
|
}
|
|
|
|
class _CustomSrsScreenState extends State<CustomSrsScreen> with SingleTickerProviderStateMixin {
|
|
late TabController _tabController;
|
|
final _deckRepository = CustomDeckRepository();
|
|
List<CustomKanjiItem> _deck = [];
|
|
bool _useKanji = false;
|
|
final _quizScreenKeys = [
|
|
GlobalKey<CustomQuizScreenState>(),
|
|
GlobalKey<CustomQuizScreenState>(),
|
|
GlobalKey<CustomQuizScreenState>(),
|
|
];
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_tabController = TabController(length: 3, vsync: this);
|
|
_tabController.addListener(() {
|
|
if (_tabController.indexIsChanging) {
|
|
final key = _quizScreenKeys[_tabController.index];
|
|
key.currentState?.playAudio();
|
|
}
|
|
setState(() {});
|
|
});
|
|
_loadDeck();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_tabController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
Future<void> _loadDeck() async {
|
|
final deck = await _deckRepository.getCustomDeck();
|
|
setState(() {
|
|
_deck = deck;
|
|
});
|
|
}
|
|
|
|
Future<void> _updateCard(CustomKanjiItem item) async {
|
|
final index = _deck.indexWhere((element) => element.characters == item.characters);
|
|
if (index != -1) {
|
|
setState(() {
|
|
_deck[index] = item;
|
|
});
|
|
await _deckRepository.saveDeck(_deck);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final now = DateTime.now();
|
|
final jpnToEngReviewDeck = _deck.where((item) {
|
|
if (!item.useInterval) return true;
|
|
return item.srsData.japaneseToEnglishNextReview == null ||
|
|
item.srsData.japaneseToEnglishNextReview!.isBefore(now);
|
|
}).toList();
|
|
|
|
final engToJpnReviewDeck = _deck.where((item) {
|
|
if (!item.useInterval) return true;
|
|
return item.srsData.englishToJapaneseNextReview == null ||
|
|
item.srsData.englishToJapaneseNextReview!.isBefore(now);
|
|
}).toList();
|
|
|
|
final listeningReviewDeck = _deck.where((item) {
|
|
if (!item.useInterval) return true;
|
|
return item.srsData.listeningComprehensionNextReview == null ||
|
|
item.srsData.listeningComprehensionNextReview!.isBefore(now);
|
|
}).toList();
|
|
|
|
final allDecksEmpty = jpnToEngReviewDeck.isEmpty &&
|
|
engToJpnReviewDeck.isEmpty &&
|
|
listeningReviewDeck.isEmpty;
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Custom SRS'),
|
|
actions: [
|
|
if (_tabController.index != 2)
|
|
Row(
|
|
children: [
|
|
const Text('Kanji'),
|
|
Switch(
|
|
value: _useKanji,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_useKanji = value;
|
|
});
|
|
},
|
|
),
|
|
],
|
|
),
|
|
],
|
|
bottom: TabBar(
|
|
controller: _tabController,
|
|
tabs: const [
|
|
Tab(text: 'Jpn→Eng'),
|
|
Tab(text: 'Eng→Jpn'),
|
|
Tab(text: 'Listening'),
|
|
],
|
|
),
|
|
),
|
|
body: _deck.isEmpty
|
|
? const Center(child: Text('Add cards to start quizzing!'))
|
|
: allDecksEmpty
|
|
? const Center(child: Text('No cards due for review.'))
|
|
: TabBarView(
|
|
controller: _tabController,
|
|
children: [
|
|
CustomQuizScreen(
|
|
key: _quizScreenKeys[0],
|
|
deck: jpnToEngReviewDeck,
|
|
quizMode: CustomQuizMode.japaneseToEnglish,
|
|
onCardReviewed: _updateCard,
|
|
useKanji: _useKanji,
|
|
isActive: _tabController.index == 0,
|
|
),
|
|
CustomQuizScreen(
|
|
key: _quizScreenKeys[1],
|
|
deck: engToJpnReviewDeck,
|
|
quizMode: CustomQuizMode.englishToJapanese,
|
|
onCardReviewed: _updateCard,
|
|
useKanji: _useKanji,
|
|
isActive: _tabController.index == 1,
|
|
),
|
|
CustomQuizScreen(
|
|
key: _quizScreenKeys[2],
|
|
deck: listeningReviewDeck,
|
|
quizMode: CustomQuizMode.listeningComprehension,
|
|
onCardReviewed: _updateCard,
|
|
useKanji: _useKanji,
|
|
isActive: _tabController.index == 2,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|