themes
This commit is contained in:
@@ -5,7 +5,11 @@ import '../models/custom_kanji_item.dart';
|
||||
import '../widgets/options_grid.dart';
|
||||
import '../widgets/kanji_card.dart';
|
||||
|
||||
enum CustomQuizMode { japaneseToEnglish, englishToJapanese, listeningComprehension }
|
||||
enum CustomQuizMode {
|
||||
japaneseToEnglish,
|
||||
englishToJapanese,
|
||||
listeningComprehension,
|
||||
}
|
||||
|
||||
class CustomQuizScreen extends StatefulWidget {
|
||||
final List<CustomKanjiItem> deck;
|
||||
@@ -53,10 +57,7 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
|
||||
vsync: this,
|
||||
);
|
||||
_shakeAnimation = Tween<double>(begin: 0, end: 1).animate(
|
||||
CurvedAnimation(
|
||||
parent: _shakeController,
|
||||
curve: Curves.elasticIn,
|
||||
),
|
||||
CurvedAnimation(parent: _shakeController, curve: Curves.elasticIn),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -82,7 +83,8 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
|
||||
}
|
||||
|
||||
void playAudio() {
|
||||
if (widget.quizMode == CustomQuizMode.listeningComprehension && _currentIndex < _shuffledDeck.length) {
|
||||
if (widget.quizMode == CustomQuizMode.listeningComprehension &&
|
||||
_currentIndex < _shuffledDeck.length) {
|
||||
_speak(_shuffledDeck[_currentIndex].characters);
|
||||
}
|
||||
}
|
||||
@@ -101,20 +103,30 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
|
||||
|
||||
void _generateOptions() {
|
||||
final currentItem = _shuffledDeck[_currentIndex];
|
||||
if (widget.quizMode == CustomQuizMode.listeningComprehension || widget.quizMode == CustomQuizMode.japaneseToEnglish) {
|
||||
if (widget.quizMode == CustomQuizMode.listeningComprehension ||
|
||||
widget.quizMode == CustomQuizMode.japaneseToEnglish) {
|
||||
_options = [currentItem.meaning];
|
||||
} else {
|
||||
_options = [widget.useKanji && currentItem.kanji != null ? currentItem.kanji! : currentItem.characters];
|
||||
_options = [
|
||||
widget.useKanji && currentItem.kanji != null
|
||||
? currentItem.kanji!
|
||||
: currentItem.characters,
|
||||
];
|
||||
}
|
||||
final otherItems = widget.deck
|
||||
.where((item) => item.characters != currentItem.characters)
|
||||
.toList();
|
||||
otherItems.shuffle();
|
||||
for (var i = 0; i < min(3, otherItems.length); i++) {
|
||||
if (widget.quizMode == CustomQuizMode.listeningComprehension || widget.quizMode == CustomQuizMode.japaneseToEnglish) {
|
||||
if (widget.quizMode == CustomQuizMode.listeningComprehension ||
|
||||
widget.quizMode == CustomQuizMode.japaneseToEnglish) {
|
||||
_options.add(otherItems[i].meaning);
|
||||
} else {
|
||||
_options.add(widget.useKanji && otherItems[i].kanji != null ? otherItems[i].kanji! : otherItems[i].characters);
|
||||
_options.add(
|
||||
widget.useKanji && otherItems[i].kanji != null
|
||||
? otherItems[i].kanji!
|
||||
: otherItems[i].characters,
|
||||
);
|
||||
}
|
||||
}
|
||||
_options.shuffle();
|
||||
@@ -123,7 +135,9 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
|
||||
void _checkAnswer(String answer) async {
|
||||
final currentItem = _shuffledDeck[_currentIndex];
|
||||
final correctAnswer = (widget.quizMode == CustomQuizMode.englishToJapanese)
|
||||
? (widget.useKanji && currentItem.kanji != null ? currentItem.kanji! : currentItem.characters)
|
||||
? (widget.useKanji && currentItem.kanji != null
|
||||
? currentItem.kanji!
|
||||
: currentItem.characters)
|
||||
: currentItem.meaning;
|
||||
final isCorrect = answer == correctAnswer;
|
||||
|
||||
@@ -157,7 +171,8 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
|
||||
currentItem.srsData.englishToJapaneseNextReview = newNextReview;
|
||||
break;
|
||||
case CustomQuizMode.listeningComprehension:
|
||||
currentItem.srsData.listeningComprehensionNextReview = newNextReview;
|
||||
currentItem.srsData.listeningComprehensionNextReview =
|
||||
newNextReview;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -174,7 +189,8 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
|
||||
currentItem.srsData.englishToJapaneseNextReview = newNextReview;
|
||||
break;
|
||||
case CustomQuizMode.listeningComprehension:
|
||||
currentItem.srsData.listeningComprehensionNextReview = newNextReview;
|
||||
currentItem.srsData.listeningComprehensionNextReview =
|
||||
newNextReview;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -194,35 +210,35 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
|
||||
widget.onCardReviewed(currentItem);
|
||||
}
|
||||
|
||||
// --- SnackBar Logic (new) ---
|
||||
final correctDisplay = (widget.quizMode == CustomQuizMode.englishToJapanese)
|
||||
? (widget.useKanji && currentItem.kanji != null ? currentItem.kanji! : currentItem.characters)
|
||||
? (widget.useKanji && currentItem.kanji != null
|
||||
? currentItem.kanji!
|
||||
: currentItem.characters)
|
||||
: currentItem.meaning;
|
||||
|
||||
final snack = SnackBar(
|
||||
content: Text(
|
||||
isCorrect ? 'Correct!' : 'Wrong — correct: $correctDisplay',
|
||||
style: TextStyle(
|
||||
color: isCorrect ? Colors.greenAccent : Colors.redAccent,
|
||||
color: isCorrect ? Theme.of(context).colorScheme.tertiary : Theme.of(context).colorScheme.error,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
backgroundColor: const Color(0xFF222222),
|
||||
backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
duration: const Duration(milliseconds: 900),
|
||||
);
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(snack);
|
||||
}
|
||||
// --- End SnackBar Logic ---
|
||||
|
||||
if (isCorrect) {
|
||||
if (widget.quizMode == CustomQuizMode.japaneseToEnglish) {
|
||||
await _speak(currentItem.characters);
|
||||
}
|
||||
await Future.delayed(const Duration(milliseconds: 500)); // Small delay after correct answer
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
} else {
|
||||
_shakeController.forward(from: 0);
|
||||
await Future.delayed(const Duration(milliseconds: 900)); // Delay for shake animation
|
||||
await Future.delayed(const Duration(milliseconds: 900));
|
||||
}
|
||||
|
||||
_nextQuestion();
|
||||
@@ -255,15 +271,15 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_shuffledDeck.isEmpty || _currentIndex >= _shuffledDeck.length) {
|
||||
return const Center(
|
||||
child: Text('Review session complete!'),
|
||||
);
|
||||
return Center(child: Text('Review session complete!', style: TextStyle(color: Theme.of(context).colorScheme.onSurface)));
|
||||
}
|
||||
|
||||
final currentItem = _shuffledDeck[_currentIndex];
|
||||
final question = (widget.quizMode == CustomQuizMode.englishToJapanese)
|
||||
? currentItem.meaning
|
||||
: (widget.useKanji && currentItem.kanji != null ? currentItem.kanji! : currentItem.characters);
|
||||
: (widget.useKanji && currentItem.kanji != null
|
||||
? currentItem.kanji!
|
||||
: currentItem.characters);
|
||||
|
||||
Widget promptWidget;
|
||||
if (widget.quizMode == CustomQuizMode.listeningComprehension) {
|
||||
@@ -276,7 +292,7 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
|
||||
onTap: () => _speak(question),
|
||||
child: Text(
|
||||
question,
|
||||
style: const TextStyle(fontSize: 48),
|
||||
style: TextStyle(fontSize: 48, color: Theme.of(context).colorScheme.onSurface),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
@@ -296,10 +312,7 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
|
||||
maxWidth: 500,
|
||||
minHeight: 150,
|
||||
),
|
||||
child: KanjiCard(
|
||||
characterWidget: promptWidget,
|
||||
subtitle: '',
|
||||
),
|
||||
child: KanjiCard(characterWidget: promptWidget, subtitle: ''),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -331,4 +344,4 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user