added sound
This commit is contained in:
BIN
assets/sfx/confirm.mp3
Normal file
BIN
assets/sfx/confirm.mp3
Normal file
Binary file not shown.
@@ -6,6 +6,8 @@ import '../services/deck_repository.dart';
|
|||||||
import '../services/distractor_generator.dart';
|
import '../services/distractor_generator.dart';
|
||||||
import '../widgets/kanji_card.dart';
|
import '../widgets/kanji_card.dart';
|
||||||
import '../widgets/options_grid.dart';
|
import '../widgets/options_grid.dart';
|
||||||
|
import 'package:audioplayers/audioplayers.dart';
|
||||||
|
|
||||||
import 'settings_screen.dart';
|
import 'settings_screen.dart';
|
||||||
|
|
||||||
class _ReadingInfo {
|
class _ReadingInfo {
|
||||||
@@ -28,6 +30,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
String _status = 'Loading deck...';
|
String _status = 'Loading deck...';
|
||||||
final DistractorGenerator _dg = DistractorGenerator();
|
final DistractorGenerator _dg = DistractorGenerator();
|
||||||
final Random _random = Random();
|
final Random _random = Random();
|
||||||
|
final _audioPlayer = AudioPlayer();
|
||||||
|
|
||||||
QuizMode _mode = QuizMode.kanjiToEnglish;
|
QuizMode _mode = QuizMode.kanjiToEnglish;
|
||||||
KanjiItem? _current;
|
KanjiItem? _current;
|
||||||
@@ -109,14 +112,20 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
|
|
||||||
void _nextQuestion() {
|
void _nextQuestion() {
|
||||||
_deck.sort((a, b) {
|
_deck.sort((a, b) {
|
||||||
final aSrsItem = a.srsItems[_mode.toString()] ?? SrsItem(kanjiId: a.id, quizMode: _mode);
|
final aSrsItem = a.srsItems[_mode.toString()];
|
||||||
final bSrsItem = b.srsItems[_mode.toString()] ?? SrsItem(kanjiId: b.id, quizMode: _mode);
|
final bSrsItem = b.srsItems[_mode.toString()];
|
||||||
|
|
||||||
final stageComparison = aSrsItem.srsStage.compareTo(bSrsItem.srsStage);
|
final aStage = aSrsItem?.srsStage ?? 0;
|
||||||
if (stageComparison != 0) {
|
final bStage = bSrsItem?.srsStage ?? 0;
|
||||||
return stageComparison;
|
|
||||||
|
if (aStage != bStage) {
|
||||||
|
return aStage.compareTo(bStage);
|
||||||
}
|
}
|
||||||
return aSrsItem.lastAsked.compareTo(bSrsItem.lastAsked);
|
|
||||||
|
final aLastAsked = aSrsItem?.lastAsked ?? DateTime.fromMillisecondsSinceEpoch(0);
|
||||||
|
final bLastAsked = bSrsItem?.lastAsked ?? DateTime.fromMillisecondsSinceEpoch(0);
|
||||||
|
|
||||||
|
return aLastAsked.compareTo(bLastAsked);
|
||||||
});
|
});
|
||||||
|
|
||||||
_current = _deck.first;
|
_current = _deck.first;
|
||||||
@@ -128,16 +137,19 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
switch (_mode) {
|
switch (_mode) {
|
||||||
case QuizMode.kanjiToEnglish:
|
case QuizMode.kanjiToEnglish:
|
||||||
_correctAnswers = [_current!.meanings.first];
|
_correctAnswers = [_current!.meanings.first];
|
||||||
_options = [_correctAnswers.first, ..._dg.generateMeanings(_current!, _deck, 3)]
|
_options = [
|
||||||
.map(_toTitleCase)
|
_correctAnswers.first,
|
||||||
.toList()
|
..._dg.generateMeanings(_current!, _deck, 3)
|
||||||
|
].map(_toTitleCase).toList()
|
||||||
..shuffle();
|
..shuffle();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QuizMode.englishToKanji:
|
case QuizMode.englishToKanji:
|
||||||
_correctAnswers = [_current!.characters];
|
_correctAnswers = [_current!.characters];
|
||||||
_options = [_correctAnswers.first, ..._dg.generateKanji(_current!, _deck, 3)]
|
_options = [
|
||||||
..shuffle();
|
_correctAnswers.first,
|
||||||
|
..._dg.generateKanji(_current!, _deck, 3)
|
||||||
|
]..shuffle();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QuizMode.reading:
|
case QuizMode.reading:
|
||||||
@@ -149,10 +161,15 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
? _deck.expand((k) => k.onyomi)
|
? _deck.expand((k) => k.onyomi)
|
||||||
: _deck.expand((k) => k.kunyomi);
|
: _deck.expand((k) => k.kunyomi);
|
||||||
|
|
||||||
final distractors =
|
final distractors = readingsSource
|
||||||
readingsSource.where((r) => !_correctAnswers.contains(r)).toSet().toList()
|
.where((r) => !_correctAnswers.contains(r))
|
||||||
|
.toSet()
|
||||||
|
.toList()
|
||||||
..shuffle();
|
..shuffle();
|
||||||
_options = ([_correctAnswers[_random.nextInt(_correctAnswers.length)], ...distractors.take(3)])
|
_options = ([
|
||||||
|
_correctAnswers[_random.nextInt(_correctAnswers.length)],
|
||||||
|
...distractors.take(3)
|
||||||
|
])
|
||||||
..shuffle();
|
..shuffle();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -176,29 +193,31 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
|
|
||||||
var srsItem = current.srsItems[srsKey];
|
var srsItem = current.srsItems[srsKey];
|
||||||
final isNew = srsItem == null;
|
final isNew = srsItem == null;
|
||||||
srsItem ??= SrsItem(kanjiId: current.id, quizMode: _mode, readingType: readingType);
|
final srsItemForUpdate = srsItem ??=
|
||||||
|
SrsItem(kanjiId: current.id, quizMode: _mode, readingType: readingType);
|
||||||
setState(() {
|
setState(() {
|
||||||
_asked += 1;
|
_asked += 1;
|
||||||
if (isCorrect) {
|
if (isCorrect) {
|
||||||
_score += 1;
|
_score += 1;
|
||||||
srsItem!.srsStage += 1;
|
_audioPlayer.play(AssetSource('sfx/confirm.mp3'));
|
||||||
} else {
|
} else {
|
||||||
srsItem!.srsStage = max(0, srsItem.srsStage - 1);
|
srsItemForUpdate.srsStage = max(0, srsItemForUpdate.srsStage - 1);
|
||||||
}
|
}
|
||||||
srsItem.lastAsked = DateTime.now();
|
srsItemForUpdate.lastAsked = DateTime.now();
|
||||||
current.srsItems[srsKey] = srsItem;
|
current.srsItems[srsKey] = srsItemForUpdate;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isNew) {
|
if (isNew) {
|
||||||
await repo.insertSrsItem(srsItem);
|
await repo.insertSrsItem(srsItemForUpdate);
|
||||||
} else {
|
} else {
|
||||||
await repo.updateSrsItem(srsItem);
|
await repo.updateSrsItem(srsItemForUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
final correctDisplay = (_mode == QuizMode.kanjiToEnglish)
|
final correctDisplay = (_mode == QuizMode.kanjiToEnglish)
|
||||||
? _toTitleCase(_correctAnswers.first)
|
? _toTitleCase(_correctAnswers.first)
|
||||||
: (_mode == QuizMode.reading ? _correctAnswers.join(', ') : _correctAnswers.first);
|
: (_mode == QuizMode.reading
|
||||||
|
? _correctAnswers.join(', ')
|
||||||
|
: _correctAnswers.first);
|
||||||
|
|
||||||
final snack = SnackBar(
|
final snack = SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
@@ -271,7 +290,6 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
Wrap(
|
Wrap(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
runSpacing: 4,
|
runSpacing: 4,
|
||||||
@@ -282,9 +300,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
_buildChoiceChip('Reading', QuizMode.reading),
|
_buildChoiceChip('Reading', QuizMode.reading),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 18),
|
const SizedBox(height: 18),
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 3,
|
||||||
child: Center(
|
child: Center(
|
||||||
@@ -303,9 +319,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
SafeArea(
|
SafeArea(
|
||||||
top: false,
|
top: false,
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -346,4 +360,4 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
backgroundColor: const Color(0xFF1E1E1E),
|
backgroundColor: const Color(0xFF1E1E1E),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ import '../services/deck_repository.dart';
|
|||||||
import '../services/distractor_generator.dart';
|
import '../services/distractor_generator.dart';
|
||||||
import '../widgets/kanji_card.dart';
|
import '../widgets/kanji_card.dart';
|
||||||
import '../widgets/options_grid.dart';
|
import '../widgets/options_grid.dart';
|
||||||
|
import 'package:audioplayers/audioplayers.dart';
|
||||||
import 'settings_screen.dart';
|
import 'settings_screen.dart';
|
||||||
|
|
||||||
class VocabScreen extends StatefulWidget {
|
class VocabScreen extends StatefulWidget {
|
||||||
const VocabScreen({super.key});
|
const VocabScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
State<VocabScreen> createState() => _VocabScreenState();
|
State<VocabScreen> createState() => _VocabScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +21,7 @@ class _VocabScreenState extends State<VocabScreen> {
|
|||||||
bool _loading = false;
|
bool _loading = false;
|
||||||
String _status = 'Loading deck...';
|
String _status = 'Loading deck...';
|
||||||
final DistractorGenerator _dg = DistractorGenerator();
|
final DistractorGenerator _dg = DistractorGenerator();
|
||||||
final Random _random = Random();
|
final _audioPlayer = AudioPlayer();
|
||||||
|
|
||||||
VocabQuizMode _mode = VocabQuizMode.vocabToEnglish;
|
VocabQuizMode _mode = VocabQuizMode.vocabToEnglish;
|
||||||
VocabularyItem? _current;
|
VocabularyItem? _current;
|
||||||
@@ -138,17 +140,19 @@ class _VocabScreenState extends State<VocabScreen> {
|
|||||||
|
|
||||||
final srsKey = _mode.toString();
|
final srsKey = _mode.toString();
|
||||||
|
|
||||||
var srsItem = current.srsItems[srsKey];
|
var srsItemNullable = current.srsItems[srsKey];
|
||||||
final isNew = srsItem == null;
|
final isNew = srsItemNullable == null;
|
||||||
srsItem ??= VocabSrsItem(vocabId: current.id, quizMode: _mode);
|
final srsItem =
|
||||||
|
srsItemNullable ?? VocabSrsItem(vocabId: current.id, quizMode: _mode);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_asked += 1;
|
_asked += 1;
|
||||||
if (isCorrect) {
|
if (isCorrect) {
|
||||||
_score += 1;
|
_score += 1;
|
||||||
srsItem!.srsStage += 1;
|
_audioPlayer.play(AssetSource('sfx/confirm.mp3'));
|
||||||
|
srsItem.srsStage += 1;
|
||||||
} else {
|
} else {
|
||||||
srsItem!.srsStage = max(0, srsItem.srsStage - 1);
|
srsItem.srsStage = max(0, srsItem.srsStage - 1);
|
||||||
}
|
}
|
||||||
srsItem.lastAsked = DateTime.now();
|
srsItem.lastAsked = DateTime.now();
|
||||||
current.srsItems[srsKey] = srsItem;
|
current.srsItems[srsKey] = srsItem;
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <audioplayers_linux/audioplayers_linux_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
|
g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin");
|
||||||
|
audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
audioplayers_linux
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|||||||
@@ -5,11 +5,13 @@
|
|||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
import audioplayers_darwin
|
||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import sqflite_darwin
|
import sqflite_darwin
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
|
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
|
|||||||
72
pubspec.lock
72
pubspec.lock
@@ -41,6 +41,62 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.13.0"
|
version: "2.13.0"
|
||||||
|
audioplayers:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: audioplayers
|
||||||
|
sha256: "5441fa0ceb8807a5ad701199806510e56afde2b4913d9d17c2f19f2902cf0ae4"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.5.1"
|
||||||
|
audioplayers_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: audioplayers_android
|
||||||
|
sha256: "60a6728277228413a85755bd3ffd6fab98f6555608923813ce383b190a360605"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.2.1"
|
||||||
|
audioplayers_darwin:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: audioplayers_darwin
|
||||||
|
sha256: "0811d6924904ca13f9ef90d19081e4a87f7297ddc19fc3d31f60af1aaafee333"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.3.0"
|
||||||
|
audioplayers_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: audioplayers_linux
|
||||||
|
sha256: f75bce1ce864170ef5e6a2c6a61cd3339e1a17ce11e99a25bae4474ea491d001
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.1"
|
||||||
|
audioplayers_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: audioplayers_platform_interface
|
||||||
|
sha256: "0e2f6a919ab56d0fec272e801abc07b26ae7f31980f912f24af4748763e5a656"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.1.1"
|
||||||
|
audioplayers_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: audioplayers_web
|
||||||
|
sha256: "1c0f17cec68455556775f1e50ca85c40c05c714a99c5eb1d2d57cc17ba5522d7"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.1.1"
|
||||||
|
audioplayers_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: audioplayers_windows
|
||||||
|
sha256: "4048797865105b26d47628e6abb49231ea5de84884160229251f37dfcbe52fd7"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.1"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -693,6 +749,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.1"
|
version: "1.10.1"
|
||||||
|
sprintf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sprintf
|
||||||
|
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.0"
|
||||||
sqflite:
|
sqflite:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -821,6 +885,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.0"
|
||||||
|
uuid:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: uuid
|
||||||
|
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.5.1"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ dependencies:
|
|||||||
path: ^1.9.1
|
path: ^1.9.1
|
||||||
provider: ^6.1.5+1
|
provider: ^6.1.5+1
|
||||||
http: ^1.5.0
|
http: ^1.5.0
|
||||||
|
audioplayers: ^6.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -28,3 +29,5 @@ flutter_icons:
|
|||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
assets:
|
||||||
|
- assets/sfx/confirm.mp3
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <audioplayers_windows/audioplayers_windows_plugin.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
|
AudioplayersWindowsPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
audioplayers_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|||||||
Reference in New Issue
Block a user