themes and some refractoring
This commit is contained in:
@@ -3,7 +3,8 @@ import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../models/kanji_item.dart';
|
||||
import '../models/vocabulary_item.dart';
|
||||
import '../models/srs_item.dart';
|
||||
import 'package:hirameki_srs/src/services/vocab_deck_repository.dart';
|
||||
import '../services/distractor_generator.dart';
|
||||
import '../widgets/kanji_card.dart';
|
||||
@@ -53,9 +54,6 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
super.initState();
|
||||
_tabController = TabController(length: 3, vsync: this);
|
||||
_tabController.addListener(() {
|
||||
if (_tabController.indexIsChanging) {
|
||||
_nextQuestion();
|
||||
}
|
||||
setState(() {});
|
||||
});
|
||||
_loadSettings();
|
||||
@@ -130,16 +128,16 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
VocabQuizMode _modeForIndex(int index) {
|
||||
QuizMode _modeForIndex(int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return VocabQuizMode.vocabToEnglish;
|
||||
return QuizMode.vocabToEnglish;
|
||||
case 1:
|
||||
return VocabQuizMode.englishToVocab;
|
||||
return QuizMode.englishToVocab;
|
||||
case 2:
|
||||
return VocabQuizMode.audioToEnglish;
|
||||
return QuizMode.audioToEnglish;
|
||||
default:
|
||||
return VocabQuizMode.vocabToEnglish;
|
||||
return QuizMode.vocabToEnglish;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +148,7 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
final mode = _modeForIndex(index ?? _tabController.index);
|
||||
|
||||
List<VocabularyItem> currentDeckForMode = _deck;
|
||||
if (mode == VocabQuizMode.audioToEnglish) {
|
||||
if (mode == QuizMode.audioToEnglish) {
|
||||
currentDeckForMode = _deck
|
||||
.where((item) => item.pronunciationAudios.isNotEmpty)
|
||||
.toList();
|
||||
@@ -169,10 +167,10 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
quizState.shuffledDeck.sort((a, b) {
|
||||
final aSrsItem =
|
||||
a.srsItems[mode.toString()] ??
|
||||
VocabSrsItem(vocabId: a.id, quizMode: mode);
|
||||
SrsItem(subjectId: a.id, quizMode: mode);
|
||||
final bSrsItem =
|
||||
b.srsItems[mode.toString()] ??
|
||||
VocabSrsItem(vocabId: b.id, quizMode: mode);
|
||||
SrsItem(subjectId: b.id, quizMode: mode);
|
||||
final stageComparison = aSrsItem.srsStage.compareTo(bSrsItem.srsStage);
|
||||
if (stageComparison != 0) {
|
||||
return stageComparison;
|
||||
@@ -186,18 +184,14 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
quizState.currentIndex++;
|
||||
|
||||
quizState.key = UniqueKey();
|
||||
if (mode == VocabQuizMode.audioToEnglish) {
|
||||
_playCurrentAudio();
|
||||
}
|
||||
|
||||
quizState.correctAnswers = [];
|
||||
quizState.options = [];
|
||||
quizState.selectedOption = null;
|
||||
quizState.showResult = false;
|
||||
|
||||
switch (mode) {
|
||||
case VocabQuizMode.vocabToEnglish:
|
||||
case VocabQuizMode.audioToEnglish:
|
||||
case QuizMode.vocabToEnglish:
|
||||
case QuizMode.audioToEnglish:
|
||||
quizState.correctAnswers = [quizState.current!.meanings.first];
|
||||
quizState.options = [
|
||||
quizState.correctAnswers.first,
|
||||
@@ -205,13 +199,15 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
].map(_toTitleCase).toList()..shuffle();
|
||||
break;
|
||||
|
||||
case VocabQuizMode.englishToVocab:
|
||||
case QuizMode.englishToVocab:
|
||||
quizState.correctAnswers = [quizState.current!.characters];
|
||||
quizState.options = [
|
||||
quizState.correctAnswers.first,
|
||||
..._dg.generateVocab(quizState.current!, _deck, 3),
|
||||
]..shuffle();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
@@ -219,10 +215,12 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _playCurrentAudio() async {
|
||||
Future<void> _playCurrentAudio({bool playOnLoad = false}) async {
|
||||
final current = _currentQuizState.current;
|
||||
if (current == null || current.pronunciationAudios.isEmpty) return;
|
||||
|
||||
if (playOnLoad && !_playAudio) return;
|
||||
|
||||
final maleAudios = current.pronunciationAudios.where(
|
||||
(a) => a.gender == 'male',
|
||||
);
|
||||
@@ -250,7 +248,7 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
var srsItemNullable = current.srsItems[srsKey];
|
||||
final isNew = srsItemNullable == null;
|
||||
final srsItem =
|
||||
srsItemNullable ?? VocabSrsItem(vocabId: current.id, quizMode: mode);
|
||||
srsItemNullable ?? SrsItem(subjectId: current.id, quizMode: mode);
|
||||
|
||||
quizState.asked += 1;
|
||||
quizState.selectedOption = option;
|
||||
@@ -272,7 +270,7 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
await repo.updateVocabSrsItem(srsItem);
|
||||
}
|
||||
|
||||
final correctDisplay = (mode == VocabQuizMode.vocabToEnglish)
|
||||
final correctDisplay = (mode == QuizMode.vocabToEnglish)
|
||||
? _toTitleCase(quizState.correctAnswers.first)
|
||||
: quizState.correctAnswers.first;
|
||||
|
||||
@@ -281,7 +279,9 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
content: Text(
|
||||
isCorrect ? 'Correct!' : 'Wrong — correct: $correctDisplay',
|
||||
style: TextStyle(
|
||||
color: isCorrect ? Theme.of(context).colorScheme.tertiary : Theme.of(context).colorScheme.error,
|
||||
color: isCorrect
|
||||
? Theme.of(context).colorScheme.tertiary
|
||||
: Theme.of(context).colorScheme.error,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@@ -294,7 +294,7 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
if (_playCorrectSound) {
|
||||
await _audioPlayer.play(AssetSource('sfx/confirm.mp3'));
|
||||
}
|
||||
if (_playAudio && mode != VocabQuizMode.audioToEnglish) {
|
||||
if (_playAudio) {
|
||||
final maleAudios = current.pronunciationAudios.where(
|
||||
(a) => a.gender == 'male',
|
||||
);
|
||||
@@ -330,7 +330,12 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('WaniKani API key is not set.', style: TextStyle(color: Theme.of(context).colorScheme.onSurface)),
|
||||
Text(
|
||||
'WaniKani API key is not set.',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
@@ -375,26 +380,35 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
|
||||
if (quizState.current == null) {
|
||||
promptWidget = const SizedBox.shrink();
|
||||
} else if (mode == VocabQuizMode.audioToEnglish) {
|
||||
} else if (mode == QuizMode.audioToEnglish) {
|
||||
promptWidget = IconButton(
|
||||
icon: Icon(Icons.volume_up, color: Theme.of(context).colorScheme.onSurface, size: 64),
|
||||
icon: Icon(
|
||||
Icons.volume_up,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
size: 64,
|
||||
),
|
||||
onPressed: _playCurrentAudio,
|
||||
);
|
||||
} else {
|
||||
String promptText = '';
|
||||
switch (mode) {
|
||||
case VocabQuizMode.vocabToEnglish:
|
||||
case QuizMode.vocabToEnglish:
|
||||
promptText = quizState.current!.characters;
|
||||
break;
|
||||
case VocabQuizMode.englishToVocab:
|
||||
case QuizMode.englishToVocab:
|
||||
promptText = _toTitleCase(quizState.current!.meanings.first);
|
||||
break;
|
||||
case VocabQuizMode.audioToEnglish:
|
||||
case QuizMode.audioToEnglish:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
promptWidget = Text(
|
||||
promptText,
|
||||
style: TextStyle(fontSize: 48, color: Theme.of(context).colorScheme.onSurface),
|
||||
style: TextStyle(
|
||||
fontSize: 48,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -405,9 +419,18 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: Text(_status, style: TextStyle(color: Theme.of(context).colorScheme.onSurface))),
|
||||
Expanded(
|
||||
child: Text(
|
||||
_status,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_loading)
|
||||
CircularProgressIndicator(color: Theme.of(context).colorScheme.primary),
|
||||
CircularProgressIndicator(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
@@ -440,7 +463,9 @@ class _VocabScreenState extends State<VocabScreen>
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Score: ${quizState.score} / ${quizState.asked}',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.onSurface),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user