Compare commits
10 Commits
a8b0f3b737
...
1aaa2a5858
Author | SHA1 | Date |
---|---|---|
Oystein Kristoffer Tveit | 1aaa2a5858 | |
Oystein Kristoffer Tveit | b26636d400 | |
Oystein Kristoffer Tveit | d6fb9caa63 | |
Oystein Kristoffer Tveit | fef9733ad7 | |
Oystein Kristoffer Tveit | 4a98522973 | |
Oystein Kristoffer Tveit | 9e7632a8d5 | |
Oystein Kristoffer Tveit | 79923a8131 | |
Oystein Kristoffer Tveit | 4b812a25ca | |
Oystein Kristoffer Tveit | 5d3f3e2c87 | |
Oystein Kristoffer Tveit | c1ccbc00b3 |
|
@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
|
||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 30
|
compileSdkVersion 33
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
@ -43,8 +43,8 @@ android {
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId "com.example.tangocard_reader"
|
applicationId "xyz.h7x4.tangocard_reader"
|
||||||
minSdkVersion 16
|
minSdkVersion 26
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.example.tangocard_reader">
|
package="com.example.tangocard_reader">
|
||||||
<application
|
<application
|
||||||
android:label="tangocard_reader"
|
android:label="Tangocard Reader"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
|
|
@ -24,6 +24,6 @@ subprojects {
|
||||||
project.evaluationDependsOn(':app')
|
project.evaluationDependsOn(':app')
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
tasks.register("clean", Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip
|
||||||
|
|
Binary file not shown.
|
@ -1 +1 @@
|
||||||
Subproject commit d8964efd9524859f97b416c97f9d7f1c6d809ae4
|
Subproject commit 00f37fddf6656c4cca07e1afd26d6ad431e8db94
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:tangocard_reader/models/yokutango_entry.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tangocard_reader/models/data_entry.dart';
|
||||||
|
|
||||||
class Flashcard extends StatelessWidget {
|
class Flashcard extends StatelessWidget {
|
||||||
final YokutangoEntry? card;
|
final YokutangoEntry? card;
|
||||||
|
@ -104,7 +104,10 @@ class _FlashCardPaper extends StatelessWidget {
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Text((cardIndex != null) ? (cardIndex! + 1).toString() : "?")
|
Text(
|
||||||
|
(cardIndex != null) ? (cardIndex! + 1).toString() : "?",
|
||||||
|
style: const TextStyle(color: Colors.black),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -140,13 +143,19 @@ class _NorwegianContent extends StatelessWidget {
|
||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
fit: BoxFit.fitHeight,
|
fit: BoxFit.fitHeight,
|
||||||
child: DefaultTextStyle.merge(
|
child: DefaultTextStyle.merge(
|
||||||
style: const TextStyle(fontFamily: 'Heart Warming'),
|
style: const TextStyle(
|
||||||
|
fontFamily: 'Heart Warming',
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: card.norwegian.map((n) {
|
children: card.norwegian.map((n) {
|
||||||
final text = (n.hints == null)
|
final text = (n.hints == null)
|
||||||
? n.word
|
? n.word
|
||||||
: "${n.word} (${n.hints?.join(', ')})";
|
: "${n.word} (${n.hints?.join(', ')})";
|
||||||
return Text(text);
|
return Text(
|
||||||
|
text,
|
||||||
|
style: const TextStyle(color: Colors.black),
|
||||||
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -170,7 +179,10 @@ class _JapaneseContent extends StatelessWidget {
|
||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
fit: BoxFit.fitHeight,
|
fit: BoxFit.fitHeight,
|
||||||
child: DefaultTextStyle.merge(
|
child: DefaultTextStyle.merge(
|
||||||
style: const TextStyle(fontFamily: 'K Gothic'),
|
style: const TextStyle(
|
||||||
|
fontFamily: 'K Gothic',
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: card.japanese
|
children: card.japanese
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class NavigationButtons extends StatelessWidget {
|
||||||
|
final String middleText;
|
||||||
|
final void Function() onNextCard;
|
||||||
|
final void Function() onPreviousCard;
|
||||||
|
final void Function()? onMiddlePressed;
|
||||||
|
|
||||||
|
const NavigationButtons({
|
||||||
|
Key? key,
|
||||||
|
required this.middleText,
|
||||||
|
required this.onNextCard,
|
||||||
|
required this.onPreviousCard,
|
||||||
|
this.onMiddlePressed,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) =>
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.blue,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: ButtonBar(
|
||||||
|
alignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
color: Colors.white,
|
||||||
|
onPressed: onPreviousCard,
|
||||||
|
icon: const Icon(Icons.arrow_back),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
InkWell(
|
||||||
|
onTap: onMiddlePressed,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
child: Text(
|
||||||
|
middleText,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.headline6!
|
||||||
|
.merge(const TextStyle(color: Colors.white)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
IconButton(
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
color: Colors.white,
|
||||||
|
onPressed: onNextCard,
|
||||||
|
icon: const Icon(Icons.arrow_forward),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,22 +1,41 @@
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:tangocard_reader/router.dart';
|
import 'package:tangocard_reader/router.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
void main() {
|
import 'service/theme_bloc.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
GetIt.instance.registerSingleton<SharedPreferences>(
|
||||||
|
await SharedPreferences.getInstance());
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
const MyApp({Key? key}) : super(key: key);
|
const MyApp({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => BlocProvider(
|
||||||
return MaterialApp(
|
create: (context) => ThemeBloc(
|
||||||
title: 'Tangocard Reader',
|
init:
|
||||||
theme: ThemeData(
|
(GetIt.instance.get<SharedPreferences>().getBool('darkTheme') ??
|
||||||
primarySwatch: Colors.blue,
|
false)
|
||||||
),
|
? Brightness.dark
|
||||||
initialRoute: '/',
|
: Brightness.light),
|
||||||
onGenerateRoute: PageRouter.generateRoute,
|
child: BlocBuilder<ThemeBloc, Brightness>(
|
||||||
);
|
builder: (context, state) => MaterialApp(
|
||||||
}
|
title: 'Tangocard Reader',
|
||||||
|
theme: ThemeData(
|
||||||
|
fontFamily: 'Noto Sans CJK',
|
||||||
|
primarySwatch: Colors.blue,
|
||||||
|
brightness: state,
|
||||||
|
),
|
||||||
|
initialRoute: '/',
|
||||||
|
onGenerateRoute: PageRouter.generateRoute,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
part 'yokutango_entry.dart';
|
||||||
|
part 'kanji_entry.dart';
|
||||||
|
|
||||||
|
abstract class DataEntry {
|
||||||
|
const DataEntry();
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
part of 'data_entry.dart';
|
||||||
|
|
||||||
|
class KanjiEntry extends DataEntry {
|
||||||
|
final String kanji;
|
||||||
|
final List<WordConstruct> kana;
|
||||||
|
|
||||||
|
KanjiEntry.fromJson(Map<String, dynamic> json)
|
||||||
|
: kanji = json['kanji'] as String,
|
||||||
|
kana = [
|
||||||
|
for (final j in json['kana'] as List) WordConstruct.fromJson(j)
|
||||||
|
];
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return '$kanji - ${kana.join('、')}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WordConstruct {
|
||||||
|
final List<WordPiece> pieces;
|
||||||
|
|
||||||
|
WordConstruct({required this.pieces});
|
||||||
|
|
||||||
|
WordConstruct.fromJson(dynamic json)
|
||||||
|
: pieces = (json is String)
|
||||||
|
? [WordPiece(word: json, isActive: true)]
|
||||||
|
: [for (final j in json as List) WordPiece.fromJson(j)];
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return pieces.map((p) => p.isActive ? p.word : '(${p.word})').join('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WordPiece {
|
||||||
|
final String? kana;
|
||||||
|
final String? romaji;
|
||||||
|
final String word;
|
||||||
|
final bool isActive;
|
||||||
|
|
||||||
|
const WordPiece({
|
||||||
|
required this.word,
|
||||||
|
this.kana,
|
||||||
|
this.romaji,
|
||||||
|
this.isActive = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
WordPiece.fromJson(Map<String, dynamic> json)
|
||||||
|
: kana = json['kana'] as String?,
|
||||||
|
romaji = json['romaji'] as String?,
|
||||||
|
word = json['text'] as String,
|
||||||
|
isActive = json['active'] as bool? ?? false;
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:tangocard_reader/models/yokutango_entry.dart';
|
import 'data_entry.dart';
|
||||||
|
|
||||||
class BenkyouArgs {
|
class BenkyouArgs {
|
||||||
final List<YokutangoEntry> cards;
|
final List<DataEntry> cards;
|
||||||
final int? index;
|
final int? index;
|
||||||
|
|
||||||
const BenkyouArgs({required this.cards, this.index});
|
const BenkyouArgs({required this.cards, this.index});
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
class YokutangoEntry {
|
part of 'data_entry.dart';
|
||||||
|
|
||||||
|
class YokutangoEntry extends DataEntry {
|
||||||
final List<JapaneseWord> japanese;
|
final List<JapaneseWord> japanese;
|
||||||
final List<NorwegianWord> norwegian;
|
final List<NorwegianWord> norwegian;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:tangocard_reader/models/data_entry.dart';
|
||||||
import 'package:tangocard_reader/models/router_args.dart';
|
import 'package:tangocard_reader/models/router_args.dart';
|
||||||
import 'package:tangocard_reader/screens/flashcard.dart';
|
|
||||||
import 'package:tangocard_reader/screens/home.dart';
|
import 'package:tangocard_reader/screens/home.dart';
|
||||||
import 'package:tangocard_reader/screens/tango_list.dart';
|
import 'package:tangocard_reader/screens/pages/tango_list.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tangocard_reader/screens/practise/practise.dart';
|
||||||
|
|
||||||
|
import 'screens/pages/kanji_list.dart';
|
||||||
|
|
||||||
class PageRouter {
|
class PageRouter {
|
||||||
static Route<dynamic> generateRoute(RouteSettings settings) {
|
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||||
|
@ -14,22 +17,41 @@ class PageRouter {
|
||||||
case '/':
|
case '/':
|
||||||
return MaterialPageRoute(builder: (_) => const Home());
|
return MaterialPageRoute(builder: (_) => const Home());
|
||||||
|
|
||||||
case '/tangolist':
|
case '/list/tango':
|
||||||
final file = args as File;
|
final file = args as File;
|
||||||
return MaterialPageRoute(builder: (_) => TangoList(file: file));
|
return MaterialPageRoute(builder: (_) => TangoList(file: file));
|
||||||
|
|
||||||
case '/benkyou':
|
case '/list/kanji':
|
||||||
|
final file = args as File;
|
||||||
|
return MaterialPageRoute(builder: (_) => KanjiList(file: file));
|
||||||
|
|
||||||
|
case '/benkyou/tango':
|
||||||
final benkyouArgs = args as BenkyouArgs;
|
final benkyouArgs = args as BenkyouArgs;
|
||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
builder: (_) => FlashcardView(
|
builder: (_) => PractiseView(
|
||||||
cards: benkyouArgs.cards,
|
entries: benkyouArgs.cards as List<YokutangoEntry>,
|
||||||
index: benkyouArgs.index,
|
index: benkyouArgs.index ?? 0,
|
||||||
|
isKanji: false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
case '/benkyou/kanji':
|
||||||
|
final benkyouArgs = args as BenkyouArgs;
|
||||||
|
return MaterialPageRoute(
|
||||||
|
builder: (_) => PractiseView(
|
||||||
|
entries: benkyouArgs.cards as List<KanjiEntry>,
|
||||||
|
index: benkyouArgs.index ?? 0,
|
||||||
|
isKanji: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
builder: (_) => const Text("ERROR: this route does not exist"));
|
builder: (_) => Scaffold(
|
||||||
|
appBar: AppBar(title: const Text('Error')),
|
||||||
|
body: Center(child: ErrorWidget('No such route...')),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,168 +0,0 @@
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:tangocard_reader/components/flashcard.dart';
|
|
||||||
import 'package:tangocard_reader/models/yokutango_entry.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
class FlashcardView extends StatefulWidget {
|
|
||||||
final List<YokutangoEntry> cards;
|
|
||||||
final int? index;
|
|
||||||
|
|
||||||
const FlashcardView({
|
|
||||||
required this.cards,
|
|
||||||
this.index,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_FlashcardViewState createState() => _FlashcardViewState();
|
|
||||||
}
|
|
||||||
|
|
||||||
const encouragingWords = [
|
|
||||||
'頑張れ〜!',
|
|
||||||
'できるぞ!',
|
|
||||||
'ヨッシャー!',
|
|
||||||
'いけいけいけー!',
|
|
||||||
];
|
|
||||||
|
|
||||||
class _FlashcardViewState extends State<FlashcardView> {
|
|
||||||
String title = '';
|
|
||||||
int currentCard = 0;
|
|
||||||
final List<bool> _isSelected = [false, false];
|
|
||||||
|
|
||||||
get isShuffleMode => _isSelected[0];
|
|
||||||
get isLanguageSwitchedMode => _isSelected[1];
|
|
||||||
get randomCard => Random().nextInt(widget.cards.length);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
title = encouragingWords[Random().nextInt(encouragingWords.length)];
|
|
||||||
currentCard = widget.index ?? 0;
|
|
||||||
|
|
||||||
final isPhone = MediaQueryData.fromWindow(WidgetsBinding.instance!.window)
|
|
||||||
.size
|
|
||||||
.shortestSide <
|
|
||||||
600;
|
|
||||||
if (isPhone) {
|
|
||||||
SystemChrome.setPreferredOrientations([
|
|
||||||
DeviceOrientation.landscapeLeft,
|
|
||||||
DeviceOrientation.landscapeRight,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
SystemChrome.setPreferredOrientations([
|
|
||||||
DeviceOrientation.portraitDown,
|
|
||||||
DeviceOrientation.portraitUp,
|
|
||||||
DeviceOrientation.landscapeLeft,
|
|
||||||
DeviceOrientation.landscapeRight,
|
|
||||||
]);
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: Container()),
|
|
||||||
Text(title),
|
|
||||||
Expanded(child: Container()),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => setState(() {
|
|
||||||
currentCard = 0;
|
|
||||||
}),
|
|
||||||
icon: const Icon(Icons.repeat),
|
|
||||||
),
|
|
||||||
ToggleButtons(
|
|
||||||
children: const [
|
|
||||||
Icon(Icons.shuffle),
|
|
||||||
Icon(Icons.translate),
|
|
||||||
],
|
|
||||||
isSelected: _isSelected,
|
|
||||||
onPressed: (int index) {
|
|
||||||
setState(() {
|
|
||||||
_isSelected[index] = !_isSelected[index];
|
|
||||||
});
|
|
||||||
})
|
|
||||||
],
|
|
||||||
),
|
|
||||||
centerTitle: true,
|
|
||||||
),
|
|
||||||
body: _FlashcardPage(
|
|
||||||
card: widget.cards[currentCard],
|
|
||||||
index: currentCard,
|
|
||||||
languageFlipped: isLanguageSwitchedMode,
|
|
||||||
onNextCard: () {
|
|
||||||
setState(() {
|
|
||||||
currentCard = isShuffleMode ? randomCard : currentCard + 1;
|
|
||||||
if (currentCard == widget.cards.length) currentCard = 0;
|
|
||||||
title = encouragingWords[Random().nextInt(encouragingWords.length)];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _FlashcardPage extends StatefulWidget {
|
|
||||||
final YokutangoEntry card;
|
|
||||||
final Function() onNextCard;
|
|
||||||
final bool languageFlipped;
|
|
||||||
final int? index;
|
|
||||||
|
|
||||||
const _FlashcardPage({
|
|
||||||
required this.card,
|
|
||||||
required this.onNextCard,
|
|
||||||
this.languageFlipped = false,
|
|
||||||
this.index,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_FlashcardPageState createState() => _FlashcardPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _FlashcardPageState extends State<_FlashcardPage> {
|
|
||||||
bool isPressed = false;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
if (isPressed) {
|
|
||||||
widget.onNextCard();
|
|
||||||
}
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
isPressed = !isPressed;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Center(
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Flashcard(
|
|
||||||
card: widget.card,
|
|
||||||
cardIndex: widget.index,
|
|
||||||
isLeftSide: true,
|
|
||||||
languageFlipped: widget.languageFlipped,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 40),
|
|
||||||
Flashcard(
|
|
||||||
card: isPressed ? widget.card : null,
|
|
||||||
cardIndex: widget.index,
|
|
||||||
languageFlipped: widget.languageFlipped,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,81 +1,55 @@
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:tangocard_reader/models/yokutango_entry.dart';
|
|
||||||
import 'package:tangocard_reader/screens/error.dart';
|
|
||||||
import 'package:tangocard_reader/screens/loading.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:tangocard_reader/service/tangocard_files.dart';
|
||||||
|
import 'package:tangocard_reader/service/theme_bloc.dart';
|
||||||
|
|
||||||
class Home extends StatelessWidget {
|
import 'pages/tango_set_list.dart';
|
||||||
|
|
||||||
|
class Home extends StatefulWidget {
|
||||||
const Home({Key? key}) : super(key: key);
|
const Home({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
State<Home> createState() => _HomeState();
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: const Text("よく単語"),
|
|
||||||
centerTitle: true,
|
|
||||||
),
|
|
||||||
body: const TangocardList());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TangocardList extends StatelessWidget {
|
class _HomeState extends State<Home> {
|
||||||
const TangocardList({Key? key}) : super(key: key);
|
int page = 0;
|
||||||
|
|
||||||
Future<Map<File, List<YokutangoEntry>>> get tangocardFilePaths => rootBundle
|
final _pages = [
|
||||||
.loadString('AssetManifest.json')
|
TangoSetList(
|
||||||
.then(
|
files: tangocardFilePaths,
|
||||||
(json) => jsonDecode(json)
|
route: '/list/tango',
|
||||||
.keys
|
),
|
||||||
.where((String key) =>
|
TangoSetList(
|
||||||
key.contains('yokutango/json/') && key.contains('.json'))
|
files: kanjicardFilePaths,
|
||||||
.toList(),
|
route: '/list/kanji',
|
||||||
)
|
),
|
||||||
.then(
|
];
|
||||||
(l) async => Map.fromIterables(
|
|
||||||
l.map<File>((f) => File(f)),
|
|
||||||
await Future.wait<List<YokutangoEntry>>(
|
|
||||||
l
|
|
||||||
.map<Future<List<YokutangoEntry>>>(
|
|
||||||
(String t) => rootBundle
|
|
||||||
.loadString(t)
|
|
||||||
.then<List<YokutangoEntry>>((s) => jsonDecode(s)
|
|
||||||
.map<YokutangoEntry>(
|
|
||||||
(e) => YokutangoEntry.fromJson(e))
|
|
||||||
.toList()),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => Scaffold(
|
||||||
return FutureBuilder(
|
appBar: AppBar(
|
||||||
future: tangocardFilePaths,
|
title: const Text("よく単語"),
|
||||||
builder: (context, snapshot) {
|
actions: [
|
||||||
if (snapshot.hasError) {
|
BlocBuilder<ThemeBloc, Brightness>(
|
||||||
debugPrint(snapshot.error.toString());
|
builder: (context, state) {
|
||||||
return const ErrorScreen();
|
return Switch(
|
||||||
} else if (!snapshot.hasData) {
|
value: state == Brightness.dark,
|
||||||
return const LoadingScreen();
|
onChanged: (b) => BlocProvider.of<ThemeBloc>(context)
|
||||||
}
|
.add(SetTheme(state != Brightness.dark)),
|
||||||
|
);
|
||||||
return ListView(
|
},
|
||||||
children: (snapshot.data as Map<File, List<YokutangoEntry>>)
|
)
|
||||||
.entries
|
],
|
||||||
.map(
|
centerTitle: true,
|
||||||
(e) => ListTile(
|
),
|
||||||
title: Text(
|
body: _pages[page],
|
||||||
"${e.key.uri.pathSegments.last} - ${e.value.length} cards"),
|
bottomNavigationBar: BottomNavigationBar(
|
||||||
onTap: () => Navigator.pushNamed(context, '/tangolist',
|
onTap: (int index) => setState(() => page = index),
|
||||||
arguments: e.key),
|
currentIndex: page,
|
||||||
),
|
items: const [
|
||||||
)
|
BottomNavigationBarItem(label: '単語', icon: Icon(Icons.style)),
|
||||||
.toList(),
|
BottomNavigationBarItem(label: '漢字', icon: Icon(Icons.translate)),
|
||||||
);
|
],
|
||||||
},
|
),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:tangocard_reader/models/router_args.dart';
|
|
||||||
import 'package:tangocard_reader/models/yokutango_entry.dart';
|
|
||||||
import 'package:tangocard_reader/screens/error.dart';
|
|
||||||
import 'package:tangocard_reader/screens/loading.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:tangocard_reader/models/data_entry.dart';
|
||||||
|
import 'package:tangocard_reader/models/router_args.dart';
|
||||||
|
import 'package:tangocard_reader/screens/misc/error.dart';
|
||||||
|
import 'package:tangocard_reader/screens/misc/loading.dart';
|
||||||
|
|
||||||
class TangoList extends StatelessWidget {
|
class KanjiList extends StatelessWidget {
|
||||||
final File file;
|
final File file;
|
||||||
|
|
||||||
const TangoList({
|
const KanjiList({
|
||||||
required this.file,
|
|
||||||
Key? key,
|
Key? key,
|
||||||
|
required this.file,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => Scaffold(
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(file.uri.pathSegments.last),
|
title: Text(file.uri.pathSegments.last),
|
||||||
),
|
),
|
||||||
|
@ -33,7 +32,7 @@ class TangoList extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
final entries = (jsonSnapshot.data as List)
|
final entries = (jsonSnapshot.data as List)
|
||||||
.map((e) => YokutangoEntry.fromJson(e))
|
.map((e) => KanjiEntry.fromJson(e))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return ListView(
|
return ListView(
|
||||||
|
@ -44,7 +43,7 @@ class TangoList extends StatelessWidget {
|
||||||
i,
|
i,
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(e.toString()),
|
title: Text(e.toString()),
|
||||||
onTap: () => Navigator.pushNamed(context, '/benkyou',
|
onTap: () => Navigator.pushNamed(context, '/benkyou/kanji',
|
||||||
arguments: BenkyouArgs(cards: entries, index: i)),
|
arguments: BenkyouArgs(cards: entries, index: i)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -53,7 +52,7 @@ class TangoList extends StatelessWidget {
|
||||||
.toList(),
|
.toList(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:tangocard_reader/models/data_entry.dart';
|
||||||
|
import 'package:tangocard_reader/models/router_args.dart';
|
||||||
|
import 'package:tangocard_reader/screens/misc/error.dart';
|
||||||
|
import 'package:tangocard_reader/screens/misc/loading.dart';
|
||||||
|
|
||||||
|
class TangoList extends StatelessWidget {
|
||||||
|
final File file;
|
||||||
|
|
||||||
|
const TangoList({
|
||||||
|
required this.file,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(file.uri.pathSegments.last),
|
||||||
|
),
|
||||||
|
body: FutureBuilder(
|
||||||
|
future:
|
||||||
|
rootBundle.loadString(file.path).then((data) => jsonDecode(data)),
|
||||||
|
builder: (context, jsonSnapshot) {
|
||||||
|
if (jsonSnapshot.hasError) {
|
||||||
|
return const ErrorScreen();
|
||||||
|
} else if (!jsonSnapshot.hasData) {
|
||||||
|
return const LoadingScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
final entries = (jsonSnapshot.data as List)
|
||||||
|
.map((e) => YokutangoEntry.fromJson(e))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return ListView(
|
||||||
|
children: entries
|
||||||
|
.asMap()
|
||||||
|
.map(
|
||||||
|
(i, e) => MapEntry(
|
||||||
|
i,
|
||||||
|
ListTile(
|
||||||
|
title: Text(e.toString()),
|
||||||
|
onTap: () => Navigator.pushNamed(
|
||||||
|
context,
|
||||||
|
'/benkyou/tango',
|
||||||
|
arguments: BenkyouArgs(cards: entries, index: i),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.values
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tangocard_reader/screens/misc/error.dart';
|
||||||
|
import 'package:tangocard_reader/screens/misc/loading.dart';
|
||||||
|
|
||||||
|
class TangoSetList extends StatelessWidget {
|
||||||
|
final String route;
|
||||||
|
final Future<Map<File, List>> files;
|
||||||
|
|
||||||
|
const TangoSetList({
|
||||||
|
Key? key,
|
||||||
|
required this.route,
|
||||||
|
required this.files,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => FutureBuilder(
|
||||||
|
future: files,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasError) {
|
||||||
|
debugPrint(snapshot.error.toString());
|
||||||
|
return const ErrorScreen();
|
||||||
|
} else if (!snapshot.hasData) {
|
||||||
|
return const LoadingScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ListView(
|
||||||
|
children: (snapshot.data as Map<File, List>)
|
||||||
|
.entries
|
||||||
|
.map(
|
||||||
|
(e) => ListTile(
|
||||||
|
title: Text(
|
||||||
|
"${e.key.uri.pathSegments.last} - ${e.value.length} cards"),
|
||||||
|
onTap: () => Navigator.pushNamed(
|
||||||
|
context,
|
||||||
|
route,
|
||||||
|
arguments: e.key,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
import 'package:tangocard_reader/components/flashcard.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tangocard_reader/models/data_entry.dart';
|
||||||
|
import 'package:tangocard_reader/components/navigation_buttons.dart';
|
||||||
|
|
||||||
|
class FlashcardPage extends StatefulWidget {
|
||||||
|
final YokutangoEntry card;
|
||||||
|
final void Function() onNextCard;
|
||||||
|
final void Function() onPreviousCard;
|
||||||
|
final bool languageFlipped;
|
||||||
|
final int? index;
|
||||||
|
|
||||||
|
const FlashcardPage({
|
||||||
|
required this.card,
|
||||||
|
required this.onNextCard,
|
||||||
|
required this.onPreviousCard,
|
||||||
|
this.languageFlipped = false,
|
||||||
|
this.index,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_FlashcardPageState createState() => _FlashcardPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FlashcardPageState extends State<FlashcardPage> {
|
||||||
|
bool isPressed = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (isPressed) {
|
||||||
|
widget.onNextCard();
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
isPressed = !isPressed;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Flashcard(
|
||||||
|
card: widget.card,
|
||||||
|
cardIndex: widget.index,
|
||||||
|
isLeftSide: true,
|
||||||
|
languageFlipped: widget.languageFlipped,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 40),
|
||||||
|
Flashcard(
|
||||||
|
card: isPressed ? widget.card : null,
|
||||||
|
cardIndex: widget.index,
|
||||||
|
languageFlipped: widget.languageFlipped,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const Expanded(child: SizedBox()),
|
||||||
|
NavigationButtons(
|
||||||
|
middleText:
|
||||||
|
widget.index == null ? 'N' : (widget.index! + 1).toString(),
|
||||||
|
onNextCard: () => setState(() {
|
||||||
|
isPressed = false;
|
||||||
|
widget.onNextCard();
|
||||||
|
}),
|
||||||
|
onPreviousCard: () => setState(() {
|
||||||
|
isPressed = false;
|
||||||
|
widget.onPreviousCard();
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
const Expanded(child: SizedBox()),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:signature/signature.dart';
|
||||||
|
|
||||||
|
import '../../models/data_entry.dart';
|
||||||
|
import '../../components/navigation_buttons.dart';
|
||||||
|
|
||||||
|
class KanjiPage extends StatefulWidget {
|
||||||
|
final KanjiEntry entry;
|
||||||
|
final Function() onNextCard;
|
||||||
|
final Function() onPreviousCard;
|
||||||
|
final bool showDrawingPanel;
|
||||||
|
final bool showStrokeOrder;
|
||||||
|
final int? index;
|
||||||
|
|
||||||
|
const KanjiPage({
|
||||||
|
required this.entry,
|
||||||
|
required this.onNextCard,
|
||||||
|
required this.onPreviousCard,
|
||||||
|
this.showDrawingPanel = false,
|
||||||
|
this.showStrokeOrder = false,
|
||||||
|
this.index,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_KanjiPageState createState() => _KanjiPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _KanjiPageState extends State<KanjiPage> {
|
||||||
|
final focusNode = FocusNode();
|
||||||
|
bool isPressed = false;
|
||||||
|
late final controller = SignatureController(
|
||||||
|
penColor: Theme.of(context).textTheme.bodyText1?.color ?? Colors.black,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
focusNode.requestFocus();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
focusNode.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return RawKeyboardListener(
|
||||||
|
focusNode: focusNode,
|
||||||
|
onKey: (event) {
|
||||||
|
if (event.isKeyPressed(LogicalKeyboardKey.enter) || event.isKeyPressed(LogicalKeyboardKey.space)) {
|
||||||
|
if (widget.showDrawingPanel) return;
|
||||||
|
if (isPressed) {
|
||||||
|
controller.clear();
|
||||||
|
widget.onNextCard();
|
||||||
|
}
|
||||||
|
setState(() => isPressed = !isPressed);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTap: () {
|
||||||
|
if (widget.showDrawingPanel) return;
|
||||||
|
if (isPressed) {
|
||||||
|
controller.clear();
|
||||||
|
widget.onNextCard();
|
||||||
|
}
|
||||||
|
setState(() => isPressed = !isPressed);
|
||||||
|
},
|
||||||
|
child: Stack(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: [
|
||||||
|
if (widget.showDrawingPanel) ...[
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
Signature(
|
||||||
|
controller: controller,
|
||||||
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
widget.entry.kana.join('\n'),
|
||||||
|
style: Theme.of(context).textTheme.headline3,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
const Divider(thickness: 5),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
Text(
|
||||||
|
widget.entry.kanji,
|
||||||
|
style: isPressed
|
||||||
|
? Theme.of(context).textTheme.headline1
|
||||||
|
: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.headline1
|
||||||
|
?.merge(const TextStyle(color: Colors.transparent)),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
const Divider(thickness: 5),
|
||||||
|
if (widget.showDrawingPanel) ...[
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const Expanded(child: SizedBox()),
|
||||||
|
IconButton(
|
||||||
|
iconSize: 40,
|
||||||
|
onPressed: controller.clear,
|
||||||
|
icon: const Icon(Icons.delete),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 40,
|
||||||
|
child: NavigationButtons(
|
||||||
|
middleText:
|
||||||
|
widget.index == null ? 'N' : (widget.index! + 1).toString(),
|
||||||
|
onMiddlePressed: () {
|
||||||
|
if (isPressed) {
|
||||||
|
controller.clear();
|
||||||
|
widget.onNextCard();
|
||||||
|
}
|
||||||
|
setState(() => isPressed = !isPressed);
|
||||||
|
},
|
||||||
|
onNextCard: () => setState(() {
|
||||||
|
if (isPressed) {
|
||||||
|
controller.clear();
|
||||||
|
widget.onNextCard();
|
||||||
|
}
|
||||||
|
setState(() => isPressed = !isPressed);
|
||||||
|
}),
|
||||||
|
onPreviousCard: () => setState(() {
|
||||||
|
controller.clear();
|
||||||
|
isPressed = false;
|
||||||
|
widget.onPreviousCard();
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,194 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:tangocard_reader/models/data_entry.dart';
|
||||||
|
import 'package:tangocard_reader/screens/practise/kanji.dart';
|
||||||
|
|
||||||
|
import 'flashcard.dart';
|
||||||
|
|
||||||
|
class PractiseView extends StatefulWidget {
|
||||||
|
final List<DataEntry> entries;
|
||||||
|
final bool isKanji;
|
||||||
|
final int index;
|
||||||
|
|
||||||
|
const PractiseView({
|
||||||
|
Key? key,
|
||||||
|
required this.entries,
|
||||||
|
required this.isKanji,
|
||||||
|
this.index = 0,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<PractiseView> createState() => _PractiseViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
const encouragingWords = [
|
||||||
|
'頑張れ〜!',
|
||||||
|
'できるぞ!',
|
||||||
|
'ヨッシャー!',
|
||||||
|
'いけいけー!',
|
||||||
|
];
|
||||||
|
|
||||||
|
class _PractiseViewState extends State<PractiseView> {
|
||||||
|
late int currentCard;
|
||||||
|
|
||||||
|
SharedPreferences get prefs => GetIt.instance.get<SharedPreferences>();
|
||||||
|
|
||||||
|
set isShuffleMode(b) => prefs.setBool('shuffleMode', b);
|
||||||
|
set isLanguageSwitchedMode(b) => prefs.setBool('languageSwitchedMode', b);
|
||||||
|
set isKanjiDrawingMode(b) => prefs.setBool('kanjiDrawingMode', b);
|
||||||
|
set isKanjiAnimationMode(b) => prefs.setBool('kanjiAnimationMode', b);
|
||||||
|
|
||||||
|
bool get isShuffleMode => prefs.getBool('shuffleMode') ?? false;
|
||||||
|
bool get isLanguageSwitchedMode =>
|
||||||
|
prefs.getBool('languageSwitchedMode') ?? false;
|
||||||
|
bool get isKanjiDrawingMode => prefs.getBool('kanjiDrawingMode') ?? false;
|
||||||
|
bool get isKanjiAnimationMode => prefs.getBool('kanjiAnimationMode') ?? false;
|
||||||
|
|
||||||
|
List<bool> get _flashcardToggles => [isShuffleMode, isLanguageSwitchedMode];
|
||||||
|
List<bool> get _kanjiToggles => [isKanjiDrawingMode, isKanjiAnimationMode];
|
||||||
|
|
||||||
|
int get randomCard => Random().nextInt(widget.entries.length);
|
||||||
|
String get randomEncouragingWord =>
|
||||||
|
encouragingWords[Random().nextInt(encouragingWords.length)];
|
||||||
|
bool get isPhone =>
|
||||||
|
MediaQueryData.fromWindow(WidgetsBinding.instance!.window)
|
||||||
|
.size
|
||||||
|
.shortestSide <
|
||||||
|
600;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
currentCard = widget.index;
|
||||||
|
|
||||||
|
if (isPhone) {
|
||||||
|
if (widget.isKanji) {
|
||||||
|
SystemChrome.setPreferredOrientations([
|
||||||
|
DeviceOrientation.portraitUp,
|
||||||
|
DeviceOrientation.portraitDown,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
SystemChrome.setPreferredOrientations([
|
||||||
|
DeviceOrientation.landscapeLeft,
|
||||||
|
DeviceOrientation.landscapeRight,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
SystemChrome.setPreferredOrientations([
|
||||||
|
DeviceOrientation.landscapeRight,
|
||||||
|
DeviceOrientation.landscapeLeft,
|
||||||
|
DeviceOrientation.portraitUp,
|
||||||
|
DeviceOrientation.portraitDown,
|
||||||
|
]);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
AppBar get flashcardAppBar => AppBar(
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: Container()),
|
||||||
|
Text(randomEncouragingWord),
|
||||||
|
Expanded(child: Container()),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => setState(() => currentCard = 0),
|
||||||
|
icon: const Icon(Icons.repeat),
|
||||||
|
),
|
||||||
|
ToggleButtons(
|
||||||
|
selectedColor: Colors.white,
|
||||||
|
children: const [
|
||||||
|
Icon(Icons.shuffle),
|
||||||
|
Icon(Icons.translate),
|
||||||
|
],
|
||||||
|
isSelected: _flashcardToggles,
|
||||||
|
onPressed: (int index) => setState(
|
||||||
|
() {
|
||||||
|
if (index == 0) {
|
||||||
|
isShuffleMode = !_flashcardToggles[index];
|
||||||
|
} else if (index == 1) {
|
||||||
|
isLanguageSwitchedMode = !_flashcardToggles[index];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
centerTitle: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
AppBar get kanjiAppBar => AppBar(
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: Container()),
|
||||||
|
Text(randomEncouragingWord),
|
||||||
|
Expanded(child: Container()),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => setState(() => currentCard = 0),
|
||||||
|
icon: const Icon(Icons.repeat),
|
||||||
|
),
|
||||||
|
ToggleButtons(
|
||||||
|
selectedColor: Colors.white,
|
||||||
|
children: const [
|
||||||
|
Icon(Icons.edit),
|
||||||
|
Icon(Icons.animation),
|
||||||
|
],
|
||||||
|
isSelected: _kanjiToggles,
|
||||||
|
onPressed: (int index) => setState(
|
||||||
|
() {
|
||||||
|
if (index == 0) {
|
||||||
|
isKanjiDrawingMode = !_kanjiToggles[index];
|
||||||
|
} else if (index == 1) {
|
||||||
|
isKanjiAnimationMode = !_kanjiToggles[index];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
centerTitle: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => Scaffold(
|
||||||
|
appBar: widget.isKanji ? kanjiAppBar : flashcardAppBar,
|
||||||
|
body: widget.isKanji
|
||||||
|
? KanjiPage(
|
||||||
|
entry: widget.entries[currentCard] as KanjiEntry,
|
||||||
|
index: currentCard,
|
||||||
|
showDrawingPanel: isKanjiDrawingMode,
|
||||||
|
showStrokeOrder: isKanjiAnimationMode,
|
||||||
|
onNextCard: () => setState(() {
|
||||||
|
currentCard = isShuffleMode ? randomCard : currentCard + 1;
|
||||||
|
if (currentCard == widget.entries.length) currentCard = 0;
|
||||||
|
}),
|
||||||
|
onPreviousCard: () => setState(() {
|
||||||
|
currentCard = isShuffleMode ? randomCard : currentCard - 1;
|
||||||
|
if (currentCard == -1) {
|
||||||
|
currentCard = widget.entries.length - 1;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
: FlashcardPage(
|
||||||
|
card: widget.entries[currentCard] as YokutangoEntry,
|
||||||
|
index: currentCard,
|
||||||
|
languageFlipped: isLanguageSwitchedMode,
|
||||||
|
onNextCard: () => setState(() {
|
||||||
|
currentCard = isShuffleMode ? randomCard : currentCard + 1;
|
||||||
|
if (currentCard == widget.entries.length) currentCard = 0;
|
||||||
|
}),
|
||||||
|
onPreviousCard: () => setState(() {
|
||||||
|
currentCard = isShuffleMode ? randomCard : currentCard - 1;
|
||||||
|
if (currentCard == -1) {
|
||||||
|
currentCard = widget.entries.length - 1;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:tangocard_reader/models/data_entry.dart';
|
||||||
|
|
||||||
|
// TODO: merge
|
||||||
|
|
||||||
|
Future<Map<File, List<YokutangoEntry>>> get tangocardFilePaths => rootBundle
|
||||||
|
.loadString('AssetManifest.json')
|
||||||
|
.then(
|
||||||
|
(json) => jsonDecode(json)
|
||||||
|
.keys
|
||||||
|
.where((String key) =>
|
||||||
|
key.contains('yokutango/json/') && key.contains('.json'))
|
||||||
|
.toList(),
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(l) async => Map.fromIterables(
|
||||||
|
l.map<File>((f) => File(f)),
|
||||||
|
await Future.wait<List<YokutangoEntry>>(
|
||||||
|
l.map<Future<List<YokutangoEntry>>>(
|
||||||
|
(String t) => rootBundle.loadString(t).then<List<YokutangoEntry>>(
|
||||||
|
(s) => jsonDecode(s)
|
||||||
|
.map<YokutangoEntry>((e) => YokutangoEntry.fromJson(e))
|
||||||
|
.toList()),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<Map<File, List<KanjiEntry>>> get kanjicardFilePaths => rootBundle
|
||||||
|
.loadString('AssetManifest.json')
|
||||||
|
.then(
|
||||||
|
(json) => jsonDecode(json)
|
||||||
|
.keys
|
||||||
|
.where((String key) =>
|
||||||
|
key.contains(RegExp(r'yokutango/kanji/kanji_\d+.json')))
|
||||||
|
.toList(),
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(l) async => Map.fromIterables(
|
||||||
|
l.map<File>((f) => File(f)),
|
||||||
|
await Future.wait<List<KanjiEntry>>(l.map<Future<List<KanjiEntry>>>(
|
||||||
|
(String t) => rootBundle.loadString(t).then<List<KanjiEntry>>((s) =>
|
||||||
|
jsonDecode(s)
|
||||||
|
.map<KanjiEntry>((e) => KanjiEntry.fromJson(e))
|
||||||
|
.toList()),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
);
|
|
@ -0,0 +1,26 @@
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
export 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class SetTheme {
|
||||||
|
final bool isDark;
|
||||||
|
const SetTheme(this.isDark);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThemeBloc extends Bloc<SetTheme, Brightness> {
|
||||||
|
ThemeBloc({
|
||||||
|
required Brightness init,
|
||||||
|
}) : super(init) {
|
||||||
|
on<SetTheme>((event, emit) {
|
||||||
|
GetIt.instance
|
||||||
|
.get<SharedPreferences>()
|
||||||
|
.setBool('darkTheme', event.isDark);
|
||||||
|
emit(event.isDark ? Brightness.dark : Brightness.light);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,9 @@
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
)
|
)
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|
||||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||||
|
@ -13,3 +16,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||||
endforeach(plugin)
|
endforeach(plugin)
|
||||||
|
|
||||||
|
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||||
|
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
||||||
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||||
|
endforeach(ffi_plugin)
|
||||||
|
|
408
pubspec.lock
408
pubspec.lock
|
@ -1,121 +1,357 @@
|
||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
archive:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: archive
|
||||||
|
sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.4.10"
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.2"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: async
|
name: async
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.8.2"
|
version: "2.11.0"
|
||||||
|
bloc:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: bloc
|
||||||
|
sha256: "3820f15f502372d979121de1f6b97bfcf1630ebff8fe1d52fb2b0bfa49be5b49"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.1.2"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: boolean_selector
|
name: boolean_selector
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.1"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: characters
|
name: characters
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.0"
|
||||||
charcode:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: charcode
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.1"
|
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: clock
|
name: clock
|
||||||
url: "https://pub.dartlang.org"
|
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
url: "https://pub.dartlang.org"
|
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0"
|
version: "1.18.0"
|
||||||
cupertino_icons:
|
convert:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: cupertino_icons
|
name: convert
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.3"
|
version: "3.1.1"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.3"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.1"
|
||||||
|
ffi:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ffi
|
||||||
|
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_bloc:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_bloc
|
||||||
|
sha256: e74efb89ee6945bcbce74a5b3a5a3376b088e5f21f55c263fc38cbdc6237faae
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.1.3"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: flutter_lints
|
name: flutter_lints
|
||||||
url: "https://pub.dartlang.org"
|
sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.4"
|
||||||
|
flutter_svg:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_svg
|
||||||
|
sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.9"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_web_plugins:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
|
get_it:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: get_it
|
||||||
|
sha256: e6017ce7fdeaf218dc51a100344d8cb70134b80e28b760f8bb23c242437bafd7
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.6.7"
|
||||||
|
image:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image
|
||||||
|
sha256: "004a2e90ce080f8627b5a04aecb4cdfac87d2c3f3b520aa291260be5a32c033d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.4"
|
||||||
|
js:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: js
|
||||||
|
sha256: "4186c61b32f99e60f011f7160e32c89a758ae9b1d0c6d28e2c02ef0382300e2b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.7.0"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: lints
|
name: lints
|
||||||
url: "https://pub.dartlang.org"
|
sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.11"
|
version: "0.12.16"
|
||||||
|
material_color_utilities:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: material_color_utilities
|
||||||
|
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
url: "https://pub.dartlang.org"
|
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.7.0"
|
version: "1.10.0"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: nested
|
name: nested
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0"
|
version: "1.8.3"
|
||||||
|
path_parsing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_parsing
|
||||||
|
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
|
path_provider_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_linux
|
||||||
|
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
|
path_provider_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_platform_interface
|
||||||
|
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
path_provider_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_windows
|
||||||
|
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.2"
|
||||||
|
platform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: platform
|
||||||
|
sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.4"
|
||||||
|
plugin_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: plugin_platform_interface
|
||||||
|
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.8"
|
||||||
|
pointycastle:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pointycastle
|
||||||
|
sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.7.4"
|
||||||
provider:
|
provider:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: provider
|
name: provider
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.0"
|
version: "6.1.1"
|
||||||
|
shared_preferences:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: shared_preferences
|
||||||
|
sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.2"
|
||||||
|
shared_preferences_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_android
|
||||||
|
sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
|
shared_preferences_foundation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_foundation
|
||||||
|
sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.5"
|
||||||
|
shared_preferences_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_linux
|
||||||
|
sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
shared_preferences_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_platform_interface
|
||||||
|
sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
shared_preferences_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_web
|
||||||
|
sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.2"
|
||||||
|
shared_preferences_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_windows
|
||||||
|
sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
signature:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: signature
|
||||||
|
sha256: d072a766e9a40496296b7593c0d9dee2abded0bdcfb306d9962d0320a9763395
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.4.1"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -125,58 +361,122 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_span
|
name: source_span
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.10.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stack_trace
|
name: stack_trace
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.0"
|
version: "1.11.1"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stream_channel
|
name: stream_channel
|
||||||
url: "https://pub.dartlang.org"
|
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.2"
|
||||||
string_scanner:
|
string_scanner:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: string_scanner
|
name: string_scanner
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.2.0"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: term_glyph
|
name: term_glyph
|
||||||
url: "https://pub.dartlang.org"
|
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.3"
|
version: "0.6.1"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: typed_data
|
name: typed_data
|
||||||
url: "https://pub.dartlang.org"
|
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.2"
|
||||||
|
vector_graphics:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vector_graphics
|
||||||
|
sha256: "18f6690295af52d081f6808f2f7c69f0eed6d7e23a71539d75f4aeb8f0062172"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.9+2"
|
||||||
|
vector_graphics_codec:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vector_graphics_codec
|
||||||
|
sha256: "531d20465c10dfac7f5cd90b60bbe4dd9921f1ec4ca54c83ebb176dbacb7bb2d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.9+2"
|
||||||
|
vector_graphics_compiler:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vector_graphics_compiler
|
||||||
|
sha256: "03012b0a33775c5530576b70240308080e1d5050f0faf000118c20e6463bc0ad"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.9+2"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
url: "https://pub.dartlang.org"
|
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||||
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.4"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.0"
|
||||||
|
win32:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32
|
||||||
|
sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.2.0"
|
||||||
|
xdg_directories:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xdg_directories
|
||||||
|
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
|
xml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xml
|
||||||
|
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.5.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.12.0 <3.0.0"
|
dart: ">=3.2.0 <4.0.0"
|
||||||
flutter: ">=1.16.0"
|
flutter: ">=3.16.0"
|
||||||
|
|
16
pubspec.yaml
16
pubspec.yaml
|
@ -29,12 +29,10 @@ environment:
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_bloc: ^8.0.1
|
||||||
|
get_it: ^7.2.0
|
||||||
# The following adds the Cupertino Icons font to your application.
|
shared_preferences: ^2.0.12
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
signature: ^5.0.0
|
||||||
cupertino_icons: ^1.0.2
|
|
||||||
provider: ^6.0.0
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -69,10 +67,16 @@ flutter:
|
||||||
- family: K Gothic
|
- family: K Gothic
|
||||||
fonts:
|
fonts:
|
||||||
- asset: assets/fonts/K Gothic.ttf
|
- asset: assets/fonts/K Gothic.ttf
|
||||||
|
|
||||||
- family: Heart Warming
|
- family: Heart Warming
|
||||||
fonts:
|
fonts:
|
||||||
- asset: assets/fonts/Heart Warming.otf
|
- asset: assets/fonts/Heart Warming.otf
|
||||||
|
|
||||||
|
- family: Noto Sans CJK
|
||||||
|
fonts:
|
||||||
|
- asset: assets/fonts/NotoSansCJK-Regular.ttc
|
||||||
|
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue