finish v3

This commit is contained in:
Rene Kievits
2025-11-02 19:00:17 +01:00
parent 16da0f04ac
commit 5f1b9ba12e
16 changed files with 396 additions and 285 deletions

View File

@@ -254,7 +254,7 @@ class _BrowseScreenState extends State<BrowseScreen>
backgroundColor: isSelected
? Theme.of(context).colorScheme.primary
: isDisabled
? Theme.of(context).colorScheme.surfaceVariant
? Theme.of(context).colorScheme.surfaceContainerHighest
: Theme.of(context).colorScheme.surfaceContainerHighest,
foregroundColor: isSelected

View File

@@ -34,34 +34,37 @@ class CustomQuizScreen extends StatefulWidget {
State<CustomQuizScreen> createState() => CustomQuizScreenState();
}
class _CustomQuizState {
CustomKanjiItem? current;
List<String> options = [];
List<String> correctAnswers = [];
int score = 0;
int asked = 0;
Key key = UniqueKey();
String? selectedOption;
bool showResult = false;
Set<String> wrongItems = {};
}
class CustomQuizScreenState extends State<CustomQuizScreen>
with TickerProviderStateMixin {
int _currentIndex = 0;
final _quizState = _CustomQuizState();
List<CustomKanjiItem> _shuffledDeck = [];
List<String> _options = [];
bool _answered = false;
bool? _correct;
int _sessionDeckSize = 0;
bool _isAnswering = false;
late AnimationController _shakeController;
late Animation<double> _shakeAnimation;
final List<String> _incorrectlyAnsweredItems = [];
final _audioPlayer = AudioPlayer();
bool _playIncorrectSound = true;
bool _playCorrectSound = true;
bool _playNarrator = true;
String? _selectedOption;
String? _correctAnswer;
bool _showResult = false;
@override
void initState() {
super.initState();
_shuffledDeck = widget.deck.toList()..shuffle();
if (_shuffledDeck.isNotEmpty) {
_generateOptions();
}
_sessionDeckSize = _shuffledDeck.length;
_shakeController = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
@@ -70,6 +73,7 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
CurvedAnimation(parent: _shakeController, curve: Curves.elasticIn),
);
_loadSettings();
_nextQuestion();
}
Future<void> _loadSettings() async {
@@ -90,163 +94,53 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
void didUpdateWidget(CustomQuizScreen oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.deck != oldWidget.deck && !widget.isActive) {
setState(() {
_shuffledDeck = widget.deck.toList()..shuffle();
_currentIndex = 0;
_answered = false;
_correct = null;
if (_shuffledDeck.isNotEmpty) {
_generateOptions();
}
});
_shuffledDeck = widget.deck.toList()..shuffle();
_sessionDeckSize = _shuffledDeck.length;
_nextQuestion();
}
if (widget.useKanji != oldWidget.useKanji) {
setState(() {
_generateOptions();
});
_nextQuestion();
}
}
void playAudio() async {
final quizState = _quizState;
if (widget.quizMode == CustomQuizMode.listeningComprehension &&
_currentIndex < _shuffledDeck.length && _playNarrator) {
quizState.current != null &&
_playNarrator) {
final ttsService = Provider.of<TtsService>(context, listen: false);
await ttsService.speak(_shuffledDeck[_currentIndex].characters);
await ttsService.speak(quizState.current!.characters);
}
}
@override
void dispose() {
_shakeController.dispose();
super.dispose();
}
void _generateOptions() {
final currentItem = _shuffledDeck[_currentIndex];
if (widget.quizMode == CustomQuizMode.listeningComprehension ||
widget.quizMode == CustomQuizMode.japaneseToEnglish) {
_options = [currentItem.meaning];
}
else {
_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) {
_options.add(otherItems[i].meaning);
} else {
_options.add(
widget.useKanji && otherItems[i].kanji != null
? otherItems[i].kanji!
: otherItems[i].characters,
);
}
}
while (_options.length < 4) {
_options.add('---');
}
_options.shuffle();
}
void _checkAnswer(String answer) async {
final currentItem = _shuffledDeck[_currentIndex];
final correctAnswer = (widget.quizMode == CustomQuizMode.englishToJapanese)
? (widget.useKanji && currentItem.kanji != null
? currentItem.kanji!
: currentItem.characters)
: currentItem.meaning;
final isCorrect = answer == correctAnswer;
void _answer(String option) async {
final quizState = _quizState;
final current = quizState.current!;
final isCorrect = quizState.correctAnswers
.map((a) => a.toLowerCase().trim())
.contains(option.toLowerCase().trim());
setState(() {
_selectedOption = answer;
_correctAnswer = correctAnswer;
_showResult = true;
quizState.selectedOption = option;
quizState.showResult = true;
_isAnswering = true;
});
int currentSrsLevel = 0; // Initialize with a default value
if (currentItem.useInterval) {
switch (widget.quizMode) {
case CustomQuizMode.japaneseToEnglish:
currentSrsLevel = currentItem.srsData.japaneseToEnglish;
break;
case CustomQuizMode.englishToJapanese:
currentSrsLevel = currentItem.srsData.englishToJapanese;
break;
case CustomQuizMode.listeningComprehension:
currentSrsLevel = currentItem.srsData.listeningComprehension;
break;
}
if (isCorrect) {
if (_incorrectlyAnsweredItems.contains(currentItem.characters)) {
_incorrectlyAnsweredItems.remove(currentItem.characters);
} else {
currentSrsLevel++;
}
final interval = pow(2, currentSrsLevel).toInt();
final newNextReview = DateTime.now().add(Duration(hours: interval));
switch (widget.quizMode) {
case CustomQuizMode.japaneseToEnglish:
currentItem.srsData.japaneseToEnglishNextReview = newNextReview;
break;
case CustomQuizMode.englishToJapanese:
currentItem.srsData.englishToJapaneseNextReview = newNextReview;
break;
case CustomQuizMode.listeningComprehension:
currentItem.srsData.listeningComprehensionNextReview =
newNextReview;
break;
}
} else {
if (!_incorrectlyAnsweredItems.contains(currentItem.characters)) {
_incorrectlyAnsweredItems.add(currentItem.characters);
}
currentSrsLevel = max(0, currentSrsLevel - 1);
final newNextReview = DateTime.now().add(const Duration(hours: 1));
switch (widget.quizMode) {
case CustomQuizMode.japaneseToEnglish:
currentItem.srsData.japaneseToEnglishNextReview = newNextReview;
break;
case CustomQuizMode.englishToJapanese:
currentItem.srsData.englishToJapaneseNextReview = newNextReview;
break;
case CustomQuizMode.listeningComprehension:
currentItem.srsData.listeningComprehensionNextReview =
newNextReview;
break;
}
}
switch (widget.quizMode) {
case CustomQuizMode.japaneseToEnglish:
currentItem.srsData.japaneseToEnglish = currentSrsLevel;
break;
case CustomQuizMode.englishToJapanese:
currentItem.srsData.englishToJapanese = currentSrsLevel;
break;
case CustomQuizMode.listeningComprehension:
currentItem.srsData.listeningComprehension = currentSrsLevel;
break;
}
widget.onCardReviewed(currentItem);
if (current.useInterval) {
_updateSrsLevel(current, isCorrect);
}
final correctDisplay = (widget.quizMode == CustomQuizMode.englishToJapanese)
? (widget.useKanji && currentItem.kanji != null
? currentItem.kanji!
: currentItem.characters)
: currentItem.meaning;
? (widget.useKanji && current.kanji != null
? current.kanji!
: current.characters)
: current.meaning;
final snack = SnackBar(
content: Text(
@@ -266,52 +160,23 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
}
if (isCorrect) {
if (_incorrectlyAnsweredItems.contains(currentItem.characters)) {
_incorrectlyAnsweredItems.remove(currentItem.characters);
} else {
currentSrsLevel++;
}
final interval = pow(2, currentSrsLevel).toInt();
final newNextReview = DateTime.now().add(Duration(hours: interval));
switch (widget.quizMode) {
case CustomQuizMode.japaneseToEnglish:
currentItem.srsData.japaneseToEnglishNextReview = newNextReview;
break;
case CustomQuizMode.englishToJapanese:
currentItem.srsData.englishToJapaneseNextReview = newNextReview;
break;
case CustomQuizMode.listeningComprehension:
currentItem.srsData.listeningComprehensionNextReview =
newNextReview;
break;
quizState.asked += 1;
if (!quizState.wrongItems.contains(current.characters)) {
quizState.score += 1;
}
if (_playCorrectSound && !_playNarrator) {
await _audioPlayer.play(AssetSource('sfx/correct.wav'));
} else if (_playNarrator) {
if (widget.quizMode == CustomQuizMode.japaneseToEnglish ||
widget.quizMode == CustomQuizMode.englishToJapanese) {
await _speak(currentItem.characters);
await _speak(current.characters);
}
}
await Future.delayed(const Duration(milliseconds: 500));
} else {
if (!_incorrectlyAnsweredItems.contains(currentItem.characters)) {
_incorrectlyAnsweredItems.add(currentItem.characters);
}
currentSrsLevel = max(0, currentSrsLevel - 1);
final newNextReview = DateTime.now().add(const Duration(hours: 1));
switch (widget.quizMode) {
case CustomQuizMode.japaneseToEnglish:
currentItem.srsData.japaneseToEnglishNextReview = newNextReview;
break;
case CustomQuizMode.englishToJapanese:
currentItem.srsData.englishToJapaneseNextReview = newNextReview;
break;
case CustomQuizMode.listeningComprehension:
currentItem.srsData.listeningComprehensionNextReview =
newNextReview;
break;
}
quizState.wrongItems.add(current.characters);
_shuffledDeck.add(current);
_shuffledDeck.shuffle();
if (_playIncorrectSound) {
await _audioPlayer.play(AssetSource('sfx/incorrect.wav'));
}
@@ -319,24 +184,132 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
await Future.delayed(const Duration(milliseconds: 900));
}
_nextQuestion();
}
Future<void> _nextQuestion() async {
setState(() {
_currentIndex++;
_answered = false;
_correct = null;
_selectedOption = null;
_correctAnswer = null;
_showResult = false;
if (_currentIndex < _shuffledDeck.length) {
_generateOptions();
Future.delayed(const Duration(milliseconds: 900), () {
if (mounted) {
_nextQuestion();
}
});
if (_currentIndex < _shuffledDeck.length &&
}
void _updateSrsLevel(CustomKanjiItem item, bool isCorrect) {
int currentSrsLevel = 0;
switch (widget.quizMode) {
case CustomQuizMode.japaneseToEnglish:
currentSrsLevel = item.srsData.japaneseToEnglish;
break;
case CustomQuizMode.englishToJapanese:
currentSrsLevel = item.srsData.englishToJapanese;
break;
case CustomQuizMode.listeningComprehension:
currentSrsLevel = item.srsData.listeningComprehension;
break;
}
if (isCorrect) {
currentSrsLevel++;
final interval = pow(2, currentSrsLevel).toInt();
final newNextReview = DateTime.now().add(Duration(hours: interval));
switch (widget.quizMode) {
case CustomQuizMode.japaneseToEnglish:
item.srsData.japaneseToEnglishNextReview = newNextReview;
break;
case CustomQuizMode.englishToJapanese:
item.srsData.englishToJapaneseNextReview = newNextReview;
break;
case CustomQuizMode.listeningComprehension:
item.srsData.listeningComprehensionNextReview = newNextReview;
break;
}
} else {
currentSrsLevel = max(0, currentSrsLevel - 1);
final newNextReview = DateTime.now().add(const Duration(hours: 1));
switch (widget.quizMode) {
case CustomQuizMode.japaneseToEnglish:
item.srsData.japaneseToEnglishNextReview = newNextReview;
break;
case CustomQuizMode.englishToJapanese:
item.srsData.englishToJapaneseNextReview = newNextReview;
break;
case CustomQuizMode.listeningComprehension:
item.srsData.listeningComprehensionNextReview = newNextReview;
break;
}
}
switch (widget.quizMode) {
case CustomQuizMode.japaneseToEnglish:
item.srsData.japaneseToEnglish = currentSrsLevel;
break;
case CustomQuizMode.englishToJapanese:
item.srsData.englishToJapanese = currentSrsLevel;
break;
case CustomQuizMode.listeningComprehension:
item.srsData.listeningComprehension = currentSrsLevel;
break;
}
widget.onCardReviewed(item);
}
void _nextQuestion() {
final quizState = _quizState;
if (_shuffledDeck.isEmpty) {
setState(() {
quizState.current = null;
});
return;
}
quizState.current = _shuffledDeck.removeAt(0);
quizState.key = UniqueKey();
quizState.correctAnswers = [];
quizState.options = [];
quizState.selectedOption = null;
quizState.showResult = false;
if (widget.quizMode == CustomQuizMode.japaneseToEnglish ||
widget.quizMode == CustomQuizMode.listeningComprehension) {
await _speak(_shuffledDeck[_currentIndex].characters);
quizState.correctAnswers = [quizState.current!.meaning];
quizState.options = [quizState.correctAnswers.first];
} else {
quizState.correctAnswers = [
widget.useKanji && quizState.current!.kanji != null
? quizState.current!.kanji!
: quizState.current!.characters,
];
quizState.options = [quizState.correctAnswers.first];
}
final otherItems = widget.deck
.where((item) => item.characters != quizState.current!.characters)
.toList();
otherItems.shuffle();
for (var i = 0; i < min(3, otherItems.length); i++) {
if (widget.quizMode == CustomQuizMode.japaneseToEnglish ||
widget.quizMode == CustomQuizMode.listeningComprehension) {
quizState.options.add(otherItems[i].meaning);
} else {
quizState.options.add(
widget.useKanji && otherItems[i].kanji != null
? otherItems[i].kanji!
: otherItems[i].characters,
);
}
}
while (quizState.options.length < 4) {
quizState.options.add('---');
}
quizState.options.shuffle();
setState(() {
_isAnswering = false;
});
if (widget.quizMode == CustomQuizMode.listeningComprehension) {
_speak(quizState.current!.characters);
}
}
@@ -346,25 +319,29 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
}
void _onOptionSelected(String option) {
if (!(_answered && _correct!)) {
_checkAnswer(option);
if (!_isAnswering) {
_answer(option);
}
}
@override
Widget build(BuildContext context) {
if (_shuffledDeck.isEmpty || _currentIndex >= _shuffledDeck.length) {
return Center(child: Text('Review session complete!', style: TextStyle(color: Theme.of(context).colorScheme.onSurface)));
final quizState = _quizState;
if (quizState.current == null) {
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);
final currentItem = quizState.current!;
Widget promptWidget;
String subtitle = '';
if (widget.quizMode == CustomQuizMode.listeningComprehension) {
promptWidget = IconButton(
icon: const Icon(Icons.volume_up, size: 64),
@@ -372,25 +349,60 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
);
} else if (widget.quizMode == CustomQuizMode.englishToJapanese) {
promptWidget = Text(
question,
style: TextStyle(fontSize: 48, color: Theme.of(context).colorScheme.onSurface),
currentItem.meaning,
style: TextStyle(
fontSize: 48,
color: Theme.of(context).colorScheme.onSurface,
),
textAlign: TextAlign.center,
);
} else {
final promptText = widget.useKanji && currentItem.kanji != null
? currentItem.kanji!
: currentItem.characters;
promptWidget = GestureDetector(
onTap: () => _speak(question),
onTap: () => _speak(promptText),
child: Text(
question,
style: TextStyle(fontSize: 48, color: Theme.of(context).colorScheme.onSurface),
promptText,
style: TextStyle(
fontSize: 48,
color: Theme.of(context).colorScheme.onSurface,
),
textAlign: TextAlign.center,
),
);
}
return Padding(
key: quizState.key,
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${quizState.asked} / $_sessionDeckSize',
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
LinearProgressIndicator(
value: _sessionDeckSize > 0
? quizState.asked / _sessionDeckSize
: 0,
backgroundColor: Theme.of(
context,
).colorScheme.surfaceContainerHighest,
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).colorScheme.primary,
),
),
],
),
const SizedBox(height: 18),
Expanded(
flex: 3,
@@ -401,7 +413,10 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
maxWidth: 500,
minHeight: 150,
),
child: KanjiCard(characterWidget: promptWidget, subtitle: ''),
child: KanjiCard(
characterWidget: promptWidget,
subtitle: subtitle,
),
),
),
),
@@ -419,11 +434,18 @@ class CustomQuizScreenState extends State<CustomQuizScreen>
);
},
child: OptionsGrid(
options: _options,
onSelected: _onOptionSelected,
correctAnswers: [],
showResult: false,
isDisabled: false,
options: quizState.options,
onSelected: _isAnswering ? (option) {} : _onOptionSelected,
selectedOption: quizState.selectedOption,
correctAnswers: quizState.correctAnswers,
showResult: quizState.showResult,
),
),
const SizedBox(height: 8),
Text(
'Score: ${quizState.score} / ${quizState.asked}',
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
),
),
],

View File

@@ -128,8 +128,11 @@ class _HomeScreenState extends State<HomeScreen>
}
itemsByLevel.forEach((level, items) {
final allSrsItems = items.expand((item) => item.srsItems.values).toList();
if (allSrsItems.isNotEmpty && allSrsItems.every((srs) => srs.disabled)) {
final allSrsItems = items
.expand((item) => item.srsItems.values)
.toList();
if (allSrsItems.isNotEmpty &&
allSrsItems.every((srs) => srs.disabled)) {
disabledLevels.add(level);
}
});
@@ -144,9 +147,11 @@ class _HomeScreenState extends State<HomeScreen>
if (mode == QuizMode.reading) {
final onyomiSrs = item.srsItems['${QuizMode.reading}onyomi'];
final kunyomiSrs = item.srsItems['${QuizMode.reading}kunyomi'];
final hasOnyomi = item.onyomi.isNotEmpty &&
final hasOnyomi =
item.onyomi.isNotEmpty &&
(onyomiSrs == null || !onyomiSrs.disabled);
final hasKunyomi = item.kunyomi.isNotEmpty &&
final hasKunyomi =
item.kunyomi.isNotEmpty &&
(kunyomiSrs == null || !kunyomiSrs.disabled);
return hasOnyomi || hasKunyomi;
}
@@ -289,8 +294,9 @@ class _HomeScreenState extends State<HomeScreen>
String readingType = '';
if (mode == QuizMode.reading) {
readingType =
quizState.readingHint.contains("on'yomi") ? 'onyomi' : 'kunyomi';
readingType = quizState.readingHint.contains("on'yomi")
? 'onyomi'
: 'kunyomi';
}
final srsKey = mode.toString() + readingType;
@@ -341,8 +347,8 @@ class _HomeScreenState extends State<HomeScreen>
final correctDisplay = (mode == QuizMode.kanjiToEnglish)
? _toTitleCase(quizState.correctAnswers.first)
: (mode == QuizMode.reading
? quizState.correctAnswers.join(', ')
: quizState.correctAnswers.first);
? quizState.correctAnswers.join(', ')
: quizState.correctAnswers.first);
final snack = SnackBar(
content: Text(
@@ -449,7 +455,9 @@ class _HomeScreenState extends State<HomeScreen>
child: Text(
_status,
style: TextStyle(
fontSize: 24, color: Theme.of(context).colorScheme.onSurface),
fontSize: 24,
color: Theme.of(context).colorScheme.onSurface,
),
),
);
}
@@ -495,10 +503,12 @@ class _HomeScreenState extends State<HomeScreen>
value: (_sessionDeckSizes[index] ?? 0) > 0
? quizState.asked / (_sessionDeckSizes[index] ?? 1)
: 0,
backgroundColor:
Theme.of(context).colorScheme.surfaceContainerHighest,
backgroundColor: Theme.of(
context,
).colorScheme.surfaceContainerHighest,
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).colorScheme.primary),
Theme.of(context).colorScheme.primary,
),
),
],
),

View File

@@ -17,9 +17,9 @@ class StartScreen extends StatelessWidget {
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const SettingsScreen()),
);
Navigator.of(
context,
).push(MaterialPageRoute(builder: (_) => const SettingsScreen()));
},
),
],
@@ -48,9 +48,9 @@ class StartScreen extends StatelessWidget {
icon: Icons.extension,
description: 'Test your knowledge of kanji characters.',
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const HomeScreen()),
);
Navigator.of(
context,
).push(MaterialPageRoute(builder: (_) => const HomeScreen()));
},
),
_buildModeCard(
@@ -59,9 +59,9 @@ class StartScreen extends StatelessWidget {
icon: Icons.school,
description: 'Practice vocabulary from your WaniKani deck.',
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const VocabScreen()),
);
Navigator.of(
context,
).push(MaterialPageRoute(builder: (_) => const VocabScreen()));
},
),
_buildModeCard(
@@ -70,9 +70,9 @@ class StartScreen extends StatelessWidget {
icon: Icons.grid_view,
description: 'Look through your kanji and vocabulary decks.',
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const BrowseScreen()),
);
Navigator.of(
context,
).push(MaterialPageRoute(builder: (_) => const BrowseScreen()));
},
),
_buildModeCard(
@@ -92,7 +92,8 @@ class StartScreen extends StatelessWidget {
);
}
Widget _buildModeCard(BuildContext context, {
Widget _buildModeCard(
BuildContext context, {
required String title,
required IconData icon,
required String description,
@@ -109,13 +110,17 @@ class StartScreen extends StatelessWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, size: 48, color: Theme.of(context).colorScheme.primary),
Icon(
icon,
size: 48,
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 16),
Text(
title,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
style: Theme.of(
context,
).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
@@ -135,4 +140,4 @@ class StartScreen extends StatelessWidget {
),
);
}
}
}

View File

@@ -123,8 +123,11 @@ class _VocabScreenState extends State<VocabScreen>
}
itemsByLevel.forEach((level, items) {
final allSrsItems = items.expand((item) => item.srsItems.values).toList();
if (allSrsItems.isNotEmpty && allSrsItems.every((srs) => srs.disabled)) {
final allSrsItems = items
.expand((item) => item.srsItems.values)
.toList();
if (allSrsItems.isNotEmpty &&
allSrsItems.every((srs) => srs.disabled)) {
disabledLevels.add(level);
}
});
@@ -349,7 +352,7 @@ class _VocabScreenState extends State<VocabScreen>
if (mounted) {
_nextQuestion();
}
});;
});
}
@override
@@ -429,7 +432,9 @@ class _VocabScreenState extends State<VocabScreen>
child: Text(
_status,
style: TextStyle(
fontSize: 24, color: Theme.of(context).colorScheme.onSurface),
fontSize: 24,
color: Theme.of(context).colorScheme.onSurface,
),
),
);
}
@@ -491,10 +496,12 @@ class _VocabScreenState extends State<VocabScreen>
value: (_sessionDeckSizes[index] ?? 0) > 0
? quizState.asked / (_sessionDeckSizes[index] ?? 1)
: 0,
backgroundColor:
Theme.of(context).colorScheme.surfaceContainerHighest,
backgroundColor: Theme.of(
context,
).colorScheme.surfaceContainerHighest,
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).colorScheme.primary),
Theme.of(context).colorScheme.primary,
),
),
],
),