From 9d8c7b8ebbe92e11054922fde94e22a98624412a Mon Sep 17 00:00:00 2001 From: h7x4 Date: Tue, 7 Sep 2021 00:05:33 +0200 Subject: [PATCH 1/8] Move all navigation from bloc to Navigator --- lib/bloc/history/history_bloc.dart | 20 --- lib/bloc/history/history_event.dart | 4 - lib/bloc/history/history_state.dart | 6 - lib/bloc/kanji/kanji_bloc.dart | 59 -------- lib/bloc/kanji/kanji_event.dart | 17 --- lib/bloc/kanji/kanji_state.dart | 43 ------ lib/bloc/navigation/navigation_bloc.dart | 20 --- lib/bloc/navigation/navigation_event.dart | 8 - lib/bloc/navigation/navigation_state.dart | 9 -- lib/bloc/search/search_bloc.dart | 56 ------- lib/bloc/search/search_event.dart | 15 -- lib/bloc/search/search_state.dart | 26 ---- lib/main.dart | 98 ++++++------ lib/router.dart | 27 ++++ lib/services/jisho_api/jisho_search.dart | 1 + lib/services/jisho_api/kanji_search.dart | 1 + .../internet_error.dart} | 0 .../common}/loading.dart | 0 .../common}/splash.dart | 2 +- .../common/unknown_error.dart} | 0 .../components/history/kanji_search_item.dart | 5 +- .../history/phrase_search_item.dart | 5 +- .../kanji/kanji_result_body.dart} | 20 +-- .../examples.dart | 0 .../{result => kanji_result_body}/grade.dart | 0 .../{result => kanji_result_body}/header.dart | 0 .../jlpt_level.dart | 0 .../radical.dart | 0 .../{result => kanji_result_body}/rank.dart | 0 .../stroke_order_gif.dart | 0 .../yomi_chips.dart | 0 .../components/kanji/kanji_search_body.dart | 107 +++++++++++++ .../{ => kanji_search_body}/kanji_grid.dart | 34 ++--- .../kanji_search_bar.dart | 47 +++--- .../kanji_search_options_bar.dart | 10 +- lib/view/components/search/search_bar.dart | 10 +- .../components/search/search_result_body.dart | 19 +++ .../parts/badge.dart | 0 .../parts/common_badge.dart | 2 +- .../parts/header.dart | 0 .../parts/jlpt_badge.dart | 2 +- .../parts/other_forms.dart | 0 .../parts/senses.dart | 0 .../parts/wanikani_badge.dart | 2 +- .../parts/wikipedia_attribute.dart} | 0 .../search_card.dart | 9 +- .../search/word_details_body.dart} | 0 lib/view/screens/kanji/search.dart | 94 ------------ lib/view/screens/kanji/view.dart | 71 --------- .../screens/search/kanji_result_page.dart | 42 ++++++ lib/view/screens/search/kanji_view.dart | 11 ++ lib/view/screens/search/results.dart | 26 ---- .../search/search_mechanisms/drawing.dart | 0 .../search/search_mechanisms/grade_list.dart | 0 .../search_mechanisms}/grid.dart | 4 +- .../search_mechanisms}/radical_list.dart | 0 .../screens/search/search_results_page.dart | 48 ++++++ lib/view/screens/search/search_view.dart | 14 ++ lib/view/screens/search/view.dart | 33 ---- pubspec.lock | 142 ++++++++++++++---- pubspec.yaml | 1 + 61 files changed, 503 insertions(+), 667 deletions(-) delete mode 100644 lib/bloc/history/history_bloc.dart delete mode 100644 lib/bloc/history/history_event.dart delete mode 100644 lib/bloc/history/history_state.dart delete mode 100644 lib/bloc/kanji/kanji_bloc.dart delete mode 100644 lib/bloc/kanji/kanji_event.dart delete mode 100644 lib/bloc/kanji/kanji_state.dart delete mode 100644 lib/bloc/navigation/navigation_bloc.dart delete mode 100644 lib/bloc/navigation/navigation_event.dart delete mode 100644 lib/bloc/navigation/navigation_state.dart delete mode 100644 lib/bloc/search/search_bloc.dart delete mode 100644 lib/bloc/search/search_event.dart delete mode 100644 lib/bloc/search/search_state.dart create mode 100644 lib/router.dart rename lib/view/components/{search/search_result_page/parts/wikipedia_attribute.dart => common/internet_error.dart} (100%) rename lib/view/{screens => components/common}/loading.dart (100%) rename lib/view/{screens => components/common}/splash.dart (81%) rename lib/view/{screens/kanji/search/drawing.dart => components/common/unknown_error.dart} (100%) rename lib/view/{screens/kanji/result.dart => components/kanji/kanji_result_body.dart} (79%) rename lib/view/components/kanji/{result => kanji_result_body}/examples.dart (100%) rename lib/view/components/kanji/{result => kanji_result_body}/grade.dart (100%) rename lib/view/components/kanji/{result => kanji_result_body}/header.dart (100%) rename lib/view/components/kanji/{result => kanji_result_body}/jlpt_level.dart (100%) rename lib/view/components/kanji/{result => kanji_result_body}/radical.dart (100%) rename lib/view/components/kanji/{result => kanji_result_body}/rank.dart (100%) rename lib/view/components/kanji/{result => kanji_result_body}/stroke_order_gif.dart (100%) rename lib/view/components/kanji/{result => kanji_result_body}/yomi_chips.dart (100%) create mode 100644 lib/view/components/kanji/kanji_search_body.dart rename lib/view/components/kanji/{ => kanji_search_body}/kanji_grid.dart (65%) rename lib/view/components/kanji/{ => kanji_search_body}/kanji_search_bar.dart (58%) rename lib/view/components/kanji/{ => kanji_search_body}/kanji_search_options_bar.dart (73%) create mode 100644 lib/view/components/search/search_result_body.dart rename lib/view/components/search/{search_result_page => search_results_body}/parts/badge.dart (100%) rename lib/view/components/search/{search_result_page => search_results_body}/parts/common_badge.dart (80%) rename lib/view/components/search/{search_result_page => search_results_body}/parts/header.dart (100%) rename lib/view/components/search/{search_result_page => search_results_body}/parts/jlpt_badge.dart (85%) rename lib/view/components/search/{search_result_page => search_results_body}/parts/other_forms.dart (100%) rename lib/view/components/search/{search_result_page => search_results_body}/parts/senses.dart (100%) rename lib/view/components/search/{search_result_page => search_results_body}/parts/wanikani_badge.dart (86%) rename lib/view/{screens/kanji/search/grade_list.dart => components/search/search_results_body/parts/wikipedia_attribute.dart} (100%) rename lib/view/components/search/{search_result_page => search_results_body}/search_card.dart (84%) rename lib/view/{screens/search/details.dart => components/search/word_details_body.dart} (100%) delete mode 100644 lib/view/screens/kanji/search.dart delete mode 100644 lib/view/screens/kanji/view.dart create mode 100644 lib/view/screens/search/kanji_result_page.dart create mode 100644 lib/view/screens/search/kanji_view.dart delete mode 100644 lib/view/screens/search/results.dart create mode 100644 lib/view/screens/search/search_mechanisms/drawing.dart create mode 100644 lib/view/screens/search/search_mechanisms/grade_list.dart rename lib/view/screens/{kanji/search => search/search_mechanisms}/grid.dart (80%) rename lib/view/screens/{kanji/search => search/search_mechanisms}/radical_list.dart (100%) create mode 100644 lib/view/screens/search/search_results_page.dart create mode 100644 lib/view/screens/search/search_view.dart delete mode 100644 lib/view/screens/search/view.dart diff --git a/lib/bloc/history/history_bloc.dart b/lib/bloc/history/history_bloc.dart deleted file mode 100644 index 93e33f7..0000000 --- a/lib/bloc/history/history_bloc.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:meta/meta.dart'; - -export 'package:flutter_bloc/flutter_bloc.dart'; - -part 'history_event.dart'; -part 'history_state.dart'; - -class HistoryBloc extends Bloc { - HistoryBloc() : super(HistoryInitial()); - - @override - Stream mapEventToState( - HistoryEvent event, - ) async* { - // TODO: implement mapEventToState - } -} diff --git a/lib/bloc/history/history_event.dart b/lib/bloc/history/history_event.dart deleted file mode 100644 index 40ede67..0000000 --- a/lib/bloc/history/history_event.dart +++ /dev/null @@ -1,4 +0,0 @@ -part of 'history_bloc.dart'; - -@immutable -abstract class HistoryEvent {} diff --git a/lib/bloc/history/history_state.dart b/lib/bloc/history/history_state.dart deleted file mode 100644 index 57b69b2..0000000 --- a/lib/bloc/history/history_state.dart +++ /dev/null @@ -1,6 +0,0 @@ -part of 'history_bloc.dart'; - -@immutable -abstract class HistoryState {} - -class HistoryInitial extends HistoryState {} diff --git a/lib/bloc/kanji/kanji_bloc.dart b/lib/bloc/kanji/kanji_bloc.dart deleted file mode 100644 index 0533b9c..0000000 --- a/lib/bloc/kanji/kanji_bloc.dart +++ /dev/null @@ -1,59 +0,0 @@ -import 'dart:async'; - -import 'package:jisho_study_tool/bloc/database/database_bloc.dart'; -import 'package:jisho_study_tool/models/history/kanji_query.dart'; -import 'package:jisho_study_tool/models/history/search.dart'; - -import './kanji_event.dart'; -import './kanji_state.dart'; - -import 'package:bloc/bloc.dart'; -import 'package:jisho_study_tool/services/jisho_api/kanji_search.dart'; -import 'package:jisho_study_tool/services/kanji_suggestions.dart'; - -export 'package:flutter_bloc/flutter_bloc.dart'; - -export './kanji_event.dart'; -export './kanji_state.dart'; - -class KanjiBloc extends Bloc { - DatabaseBloc _databaseBloc; - - KanjiBloc(this._databaseBloc) : super(KanjiSearch(KanjiSearchType.Initial)); - - void addSearchToDB(kanji) { - if (_databaseBloc.state is DatabaseDisconnected) - throw DatabaseNotConnectedException; - - (_databaseBloc.state as DatabaseConnected) - .database - .box() - .put(Search(timestamp: DateTime.now()) - ..kanjiQuery.target = KanjiQuery( - kanji: kanji, - )); - } - - @override - Stream mapEventToState(KanjiEvent event) async* { - if (event is GetKanji) { - yield KanjiSearchLoading(); - - try { - addSearchToDB(event.kanjiSearchString); - final kanji = await fetchKanji(event.kanjiSearchString); - if (kanji.found) - yield KanjiSearchFinished(kanji: kanji); - else - yield KanjiSearchError('Something went wrong'); - } on Exception { - yield KanjiSearchError('Something went wrong'); - } - } else if (event is GetKanjiSuggestions) { - final suggestions = kanjiSuggestions(event.searchString); - yield KanjiSearchKeyboard(KanjiSearchType.Keyboard, suggestions); - } else if (event is ReturnToInitialState) { - yield KanjiSearch(KanjiSearchType.Initial); - } - } -} diff --git a/lib/bloc/kanji/kanji_event.dart b/lib/bloc/kanji/kanji_event.dart deleted file mode 100644 index 7bb79b8..0000000 --- a/lib/bloc/kanji/kanji_event.dart +++ /dev/null @@ -1,17 +0,0 @@ -abstract class KanjiEvent { - const KanjiEvent(); -} - -class GetKanjiSuggestions extends KanjiEvent { - final String searchString; - const GetKanjiSuggestions(this.searchString); -} - -class GetKanji extends KanjiEvent { - final String kanjiSearchString; - const GetKanji(this.kanjiSearchString); -} - -class ReturnToInitialState extends KanjiEvent { - const ReturnToInitialState(); -} \ No newline at end of file diff --git a/lib/bloc/kanji/kanji_state.dart b/lib/bloc/kanji/kanji_state.dart deleted file mode 100644 index ecc3653..0000000 --- a/lib/bloc/kanji/kanji_state.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'package:unofficial_jisho_api/api.dart'; - -abstract class KanjiState { - const KanjiState(); -} - -enum KanjiSearchType { - Initial, - Keyboard, - Drawing, - Radical, - Grade -} - -class KanjiSearch extends KanjiState { - final KanjiSearchType type; - const KanjiSearch(this.type); -} - -class KanjiSearchKeyboard extends KanjiSearch { - final List kanjiSuggestions; - const KanjiSearchKeyboard(KanjiSearchType type, this.kanjiSuggestions) : super(type); -} - -class KanjiSearchLoading extends KanjiState { - const KanjiSearchLoading(); -} - -class KanjiSearchFinished extends KanjiState { - final KanjiResult kanji; - final bool starred; - - const KanjiSearchFinished({ - required this.kanji, - this.starred = false, - }); -} - -class KanjiSearchError extends KanjiState { - final String message; - - const KanjiSearchError(this.message); -} \ No newline at end of file diff --git a/lib/bloc/navigation/navigation_bloc.dart b/lib/bloc/navigation/navigation_bloc.dart deleted file mode 100644 index f48fc48..0000000 --- a/lib/bloc/navigation/navigation_bloc.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:bloc/bloc.dart'; - -import './navigation_event.dart'; -import './navigation_state.dart'; - -export 'package:flutter_bloc/flutter_bloc.dart'; - -export './navigation_event.dart'; -export './navigation_state.dart'; - -class NavigationBloc extends Bloc { - - NavigationBloc() : super(NavigationPage(0)); - - @override - Stream mapEventToState(NavigationEvent event) async* { - if (event is ChangePage) - yield NavigationPage(event.pageNum); - } -} \ No newline at end of file diff --git a/lib/bloc/navigation/navigation_event.dart b/lib/bloc/navigation/navigation_event.dart deleted file mode 100644 index 9ab8fa2..0000000 --- a/lib/bloc/navigation/navigation_event.dart +++ /dev/null @@ -1,8 +0,0 @@ -abstract class NavigationEvent { - const NavigationEvent(); -} - -class ChangePage extends NavigationEvent { - final int pageNum; - const ChangePage(this.pageNum); -} \ No newline at end of file diff --git a/lib/bloc/navigation/navigation_state.dart b/lib/bloc/navigation/navigation_state.dart deleted file mode 100644 index 0f5bda3..0000000 --- a/lib/bloc/navigation/navigation_state.dart +++ /dev/null @@ -1,9 +0,0 @@ -abstract class NavigationState { - const NavigationState(); -} - -class NavigationPage extends NavigationState { - final int pageNum; - const NavigationPage(this.pageNum); - -} \ No newline at end of file diff --git a/lib/bloc/search/search_bloc.dart b/lib/bloc/search/search_bloc.dart deleted file mode 100644 index 24498cc..0000000 --- a/lib/bloc/search/search_bloc.dart +++ /dev/null @@ -1,56 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/models/history/search.dart'; -import 'package:jisho_study_tool/models/history/word_query.dart'; -import 'package:meta/meta.dart'; - -import 'package:jisho_study_tool/bloc/database/database_bloc.dart'; -import 'package:jisho_study_tool/services/jisho_api/jisho_search.dart'; -import 'package:unofficial_jisho_api/parser.dart'; - -export 'package:flutter_bloc/flutter_bloc.dart'; - -part 'search_event.dart'; -part 'search_state.dart'; - -class SearchBloc extends Bloc { - DatabaseBloc _databaseBloc; - - SearchBloc(this._databaseBloc) : super(SearchInitial()); - - void addSearchToDB(searchString) { - if (_databaseBloc.state is DatabaseDisconnected) - throw DatabaseNotConnectedException; - - (_databaseBloc.state as DatabaseConnected) - .database - .box() - .put(Search(timestamp: DateTime.now()) - ..wordQuery.target = WordQuery( - query: searchString, - )); - } - - @override - Stream mapEventToState( - SearchEvent event, - ) async* { - if (event is GetSearchResults) { - yield SearchLoading(); - - try { - addSearchToDB(event.searchString); - final searchResults = await fetchJishoResults(event.searchString); - if (searchResults.meta.status == 200) - yield SearchFinished(searchResults.data!); - } on Exception { - yield SearchError('Something went wrong'); - } - } else if (event is ReturnToInitialState) { - yield SearchInitial(); - } - } -} diff --git a/lib/bloc/search/search_event.dart b/lib/bloc/search/search_event.dart deleted file mode 100644 index 9b5d3f2..0000000 --- a/lib/bloc/search/search_event.dart +++ /dev/null @@ -1,15 +0,0 @@ -part of 'search_bloc.dart'; - -@immutable -abstract class SearchEvent { - const SearchEvent(); -} - -class GetSearchResults extends SearchEvent { - final String searchString; - const GetSearchResults(this.searchString); -} - -class ReturnToInitialState extends SearchEvent { - const ReturnToInitialState(); -} \ No newline at end of file diff --git a/lib/bloc/search/search_state.dart b/lib/bloc/search/search_state.dart deleted file mode 100644 index 4f934ee..0000000 --- a/lib/bloc/search/search_state.dart +++ /dev/null @@ -1,26 +0,0 @@ -part of 'search_bloc.dart'; - -@immutable -abstract class SearchState { - const SearchState(); -} - -class SearchInitial extends SearchState { - const SearchInitial(); -} - -class SearchLoading extends SearchState { - const SearchLoading(); -} - -class SearchFinished extends SearchState { - final List results; - - const SearchFinished(this.results); -} - -class SearchError extends SearchState { - final String message; - - const SearchError(this.message); -} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 8210f71..189d5af 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; -import 'package:jisho_study_tool/view/screens/splash.dart'; +import 'package:jisho_study_tool/router.dart'; +import 'package:jisho_study_tool/view/components/common/splash.dart'; import 'package:mdi/mdi.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart'; @@ -8,13 +9,10 @@ import 'package:path/path.dart'; import 'package:jisho_study_tool/objectbox.g.dart'; import 'package:jisho_study_tool/bloc/database/database_bloc.dart'; -import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart'; -import 'package:jisho_study_tool/bloc/search/search_bloc.dart'; -import 'package:jisho_study_tool/bloc/navigation/navigation_bloc.dart'; -import 'package:jisho_study_tool/view/screens/kanji/view.dart'; +import 'package:jisho_study_tool/view/screens/search/kanji_view.dart'; import 'package:jisho_study_tool/view/screens/history.dart'; -import 'package:jisho_study_tool/view/screens/search/view.dart'; +import 'package:jisho_study_tool/view/screens/search/search_view.dart'; import 'package:jisho_study_tool/view/screens/settings.dart'; import 'models/themes/theme.dart'; @@ -60,20 +58,19 @@ class _MyAppState extends State { Widget build(BuildContext context) { return MultiBlocProvider( providers: [ - BlocProvider(create: (context) => SearchBloc(_databaseBloc)), - BlocProvider(create: (context) => KanjiBloc(_databaseBloc)), BlocProvider(create: (context) => _databaseBloc), - BlocProvider(create: (context) => NavigationBloc()), BlocProvider(create: (context) => ThemeBloc()), ], child: BlocBuilder( builder: (context, themeState) { + if (!(dbConnected && themeState.prefsAreLoaded)) + return SplashScreen(); + return MaterialApp( title: 'Jisho Study Tool', theme: themeState.theme.getMaterialTheme(), - home: dbConnected && themeState.prefsAreLoaded - ? Home() - : SplashScreen(), + initialRoute: '/', + onGenerateRoute: PageRouter.generateRoute, ); }, ), @@ -81,45 +78,48 @@ class _MyAppState extends State { } } -class Home extends StatelessWidget { +class Home extends StatefulWidget { + @override + State createState() => _HomeState(); +} + +class _HomeState extends State { + int pageNum = 0; + @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, navigationState) { - int selectedPage = (navigationState as NavigationPage).pageNum; - return BlocBuilder( - builder: (context, themeState) { - return Scaffold( - appBar: AppBar( - title: pages[selectedPage].titleBar, - centerTitle: true, - backgroundColor: AppTheme.jishoGreen.background, - foregroundColor: AppTheme.jishoGreen.foreground, + return BlocBuilder( + builder: (context, themeState) { + return Scaffold( + appBar: AppBar( + title: pages[pageNum].titleBar, + centerTitle: true, + backgroundColor: AppTheme.jishoGreen.background, + foregroundColor: AppTheme.jishoGreen.foreground, + ), + body: Stack( + children: [ + Positioned( + child: Image.asset( + 'assets/images/denshi_jisho_background_overlay.png'), + right: 30, + left: 100, + bottom: 30, ), - body: Stack( - children: [ - Positioned( - child: Image.asset( - 'assets/images/denshi_jisho_background_overlay.png'), - right: 30, - left: 100, - bottom: 30, - ), - pages[selectedPage].content, - ], - ), - bottomNavigationBar: BottomNavigationBar( - fixedColor: AppTheme.jishoGreen.background, - currentIndex: selectedPage, - onTap: (int index) => BlocProvider.of(context) - .add(ChangePage(index)), - items: pages.map((p) => p.item).toList(), - showSelectedLabels: false, - showUnselectedLabels: false, - unselectedItemColor: themeState.theme.menuGreyDark.background, - ), - ); - }, + pages[pageNum].content, + ], + ), + bottomNavigationBar: BottomNavigationBar( + fixedColor: AppTheme.jishoGreen.background, + currentIndex: pageNum, + onTap: (int index) => setState(() { + this.pageNum = index; + }), + items: pages.map((p) => p.item).toList(), + showSelectedLabels: false, + showUnselectedLabels: false, + unselectedItemColor: themeState.theme.menuGreyDark.background, + ), ); }, ); @@ -149,7 +149,7 @@ final List<_Page> pages = [ ), _Page( content: KanjiView(), - titleBar: KanjiViewBar(), + titleBar: Text('Kanji'), item: BottomNavigationBarItem( label: 'Kanji', icon: Icon(Mdi.ideogramCjk, size: 30)), ), diff --git a/lib/router.dart b/lib/router.dart new file mode 100644 index 0000000..cc3452d --- /dev/null +++ b/lib/router.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:jisho_study_tool/view/screens/search/kanji_result_page.dart'; +import 'package:jisho_study_tool/view/screens/search/search_results_page.dart'; + +import 'main.dart'; + +class PageRouter { + static Route generateRoute(RouteSettings settings) { + final args = settings.arguments; + + switch (settings.name) { + case '/': + return MaterialPageRoute(builder: (_) => Home()); + + case '/search': + final searchTerm = args as String; + return MaterialPageRoute(builder: (_) => SearchResultsPage(searchTerm: searchTerm)); + + case '/kanjiSearch': + final searchTerm = args as String; + return MaterialPageRoute(builder: (_) => KanjiResultPage(kanjiSearchTerm: searchTerm)); + + default: + return MaterialPageRoute(builder: (_) => Text("ERROR: this route does not exist")); + } + } +} diff --git a/lib/services/jisho_api/jisho_search.dart b/lib/services/jisho_api/jisho_search.dart index eb1e379..8024a5a 100644 --- a/lib/services/jisho_api/jisho_search.dart +++ b/lib/services/jisho_api/jisho_search.dart @@ -1,4 +1,5 @@ import 'package:unofficial_jisho_api/api.dart' as jisho; +export 'package:unofficial_jisho_api/api.dart' show JishoAPIResult; Future fetchJishoResults(searchTerm) async { return await jisho.searchForPhrase(searchTerm); diff --git a/lib/services/jisho_api/kanji_search.dart b/lib/services/jisho_api/kanji_search.dart index 2c55d61..7015894 100644 --- a/lib/services/jisho_api/kanji_search.dart +++ b/lib/services/jisho_api/kanji_search.dart @@ -1,4 +1,5 @@ import 'package:unofficial_jisho_api/api.dart' as jisho; +export 'package:unofficial_jisho_api/api.dart' show KanjiResult; String? _convertGrade(String grade) { const conversionTable = { diff --git a/lib/view/components/search/search_result_page/parts/wikipedia_attribute.dart b/lib/view/components/common/internet_error.dart similarity index 100% rename from lib/view/components/search/search_result_page/parts/wikipedia_attribute.dart rename to lib/view/components/common/internet_error.dart diff --git a/lib/view/screens/loading.dart b/lib/view/components/common/loading.dart similarity index 100% rename from lib/view/screens/loading.dart rename to lib/view/components/common/loading.dart diff --git a/lib/view/screens/splash.dart b/lib/view/components/common/splash.dart similarity index 81% rename from lib/view/screens/splash.dart rename to lib/view/components/common/splash.dart index 350d7d2..3d05254 100644 --- a/lib/view/screens/splash.dart +++ b/lib/view/components/common/splash.dart @@ -9,7 +9,7 @@ class SplashScreen extends StatelessWidget { return Container( decoration: BoxDecoration(color: AppTheme.jishoGreen.background), child: Center( - child: Image.asset('assets/images/logo/logo_icon_transparent.png'), + child: Image(image: AssetImage('assets/images/logo/logo_icon_transparent.png'),) ), ); } diff --git a/lib/view/screens/kanji/search/drawing.dart b/lib/view/components/common/unknown_error.dart similarity index 100% rename from lib/view/screens/kanji/search/drawing.dart rename to lib/view/components/common/unknown_error.dart diff --git a/lib/view/components/history/kanji_search_item.dart b/lib/view/components/history/kanji_search_item.dart index eb7be2f..3eed671 100644 --- a/lib/view/components/history/kanji_search_item.dart +++ b/lib/view/components/history/kanji_search_item.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; -import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart'; -import 'package:jisho_study_tool/bloc/navigation/navigation_bloc.dart'; import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; import 'package:jisho_study_tool/models/history/kanji_query.dart'; import 'package:jisho_study_tool/models/themes/theme.dart'; @@ -58,8 +56,7 @@ class KanjiSearchItem extends StatelessWidget { return Slidable( child: SearchItem( onTap: () { - BlocProvider.of(context).add(ChangePage(1)); - BlocProvider.of(context).add(GetKanji(this.result.kanji)); + Navigator.pushNamed(context, '/kanjiSearch', arguments: this.result.kanji); }, time: timestamp, search: _KanjiBox(result.kanji), diff --git a/lib/view/components/history/phrase_search_item.dart b/lib/view/components/history/phrase_search_item.dart index 30273bd..c0052c7 100644 --- a/lib/view/components/history/phrase_search_item.dart +++ b/lib/view/components/history/phrase_search_item.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; -import 'package:jisho_study_tool/bloc/navigation/navigation_bloc.dart'; -import 'package:jisho_study_tool/bloc/search/search_bloc.dart'; import 'package:jisho_study_tool/models/history/word_query.dart'; import './search_item.dart'; @@ -26,8 +24,7 @@ class PhraseSearchItem extends StatelessWidget { ], child: SearchItem( onTap: () { - BlocProvider.of(context).add(ChangePage(0)); - BlocProvider.of(context).add(GetSearchResults(this.search.query)); + Navigator.pushNamed(context, '/search', arguments: this.search.query); }, time: timestamp, search: Text(search.query), diff --git a/lib/view/screens/kanji/result.dart b/lib/view/components/kanji/kanji_result_body.dart similarity index 79% rename from lib/view/screens/kanji/result.dart rename to lib/view/components/kanji/kanji_result_body.dart index 3e3a754..821f643 100644 --- a/lib/view/screens/kanji/result.dart +++ b/lib/view/components/kanji/kanji_result_body.dart @@ -1,20 +1,20 @@ import 'package:flutter/material.dart'; import 'package:unofficial_jisho_api/api.dart' as jisho; -import 'package:jisho_study_tool/view/components/kanji/result/examples.dart'; -import 'package:jisho_study_tool/view/components/kanji/result/grade.dart'; -import 'package:jisho_study_tool/view/components/kanji/result/header.dart'; -import 'package:jisho_study_tool/view/components/kanji/result/jlpt_level.dart'; -import 'package:jisho_study_tool/view/components/kanji/result/radical.dart'; -import 'package:jisho_study_tool/view/components/kanji/result/rank.dart'; -import 'package:jisho_study_tool/view/components/kanji/result/stroke_order_gif.dart'; -import 'package:jisho_study_tool/view/components/kanji/result/yomi_chips.dart'; +import './kanji_result_body/examples.dart'; +import './kanji_result_body/grade.dart'; +import './kanji_result_body/header.dart'; +import './kanji_result_body/jlpt_level.dart'; +import './kanji_result_body/radical.dart'; +import './kanji_result_body/rank.dart'; +import './kanji_result_body/stroke_order_gif.dart'; +import './kanji_result_body/yomi_chips.dart'; -class KanjiResultCard extends StatelessWidget { +class KanjiResultBody extends StatelessWidget { late final String query; late final jisho.KanjiResultData resultData; - KanjiResultCard({required jisho.KanjiResult result}) { + KanjiResultBody({required jisho.KanjiResult result}) { query = result.query; diff --git a/lib/view/components/kanji/result/examples.dart b/lib/view/components/kanji/kanji_result_body/examples.dart similarity index 100% rename from lib/view/components/kanji/result/examples.dart rename to lib/view/components/kanji/kanji_result_body/examples.dart diff --git a/lib/view/components/kanji/result/grade.dart b/lib/view/components/kanji/kanji_result_body/grade.dart similarity index 100% rename from lib/view/components/kanji/result/grade.dart rename to lib/view/components/kanji/kanji_result_body/grade.dart diff --git a/lib/view/components/kanji/result/header.dart b/lib/view/components/kanji/kanji_result_body/header.dart similarity index 100% rename from lib/view/components/kanji/result/header.dart rename to lib/view/components/kanji/kanji_result_body/header.dart diff --git a/lib/view/components/kanji/result/jlpt_level.dart b/lib/view/components/kanji/kanji_result_body/jlpt_level.dart similarity index 100% rename from lib/view/components/kanji/result/jlpt_level.dart rename to lib/view/components/kanji/kanji_result_body/jlpt_level.dart diff --git a/lib/view/components/kanji/result/radical.dart b/lib/view/components/kanji/kanji_result_body/radical.dart similarity index 100% rename from lib/view/components/kanji/result/radical.dart rename to lib/view/components/kanji/kanji_result_body/radical.dart diff --git a/lib/view/components/kanji/result/rank.dart b/lib/view/components/kanji/kanji_result_body/rank.dart similarity index 100% rename from lib/view/components/kanji/result/rank.dart rename to lib/view/components/kanji/kanji_result_body/rank.dart diff --git a/lib/view/components/kanji/result/stroke_order_gif.dart b/lib/view/components/kanji/kanji_result_body/stroke_order_gif.dart similarity index 100% rename from lib/view/components/kanji/result/stroke_order_gif.dart rename to lib/view/components/kanji/kanji_result_body/stroke_order_gif.dart diff --git a/lib/view/components/kanji/result/yomi_chips.dart b/lib/view/components/kanji/kanji_result_body/yomi_chips.dart similarity index 100% rename from lib/view/components/kanji/result/yomi_chips.dart rename to lib/view/components/kanji/kanji_result_body/yomi_chips.dart diff --git a/lib/view/components/kanji/kanji_search_body.dart b/lib/view/components/kanji/kanji_search_body.dart new file mode 100644 index 0000000..1a8154f --- /dev/null +++ b/lib/view/components/kanji/kanji_search_body.dart @@ -0,0 +1,107 @@ +import 'package:flutter/material.dart'; +import 'package:animated_size_and_fade/animated_size_and_fade.dart'; +import 'package:jisho_study_tool/services/kanji_suggestions.dart'; + +import 'package:jisho_study_tool/view/components/kanji/kanji_search_body/kanji_grid.dart'; +import 'package:jisho_study_tool/view/components/kanji/kanji_search_body/kanji_search_bar.dart'; +import 'package:jisho_study_tool/view/components/kanji/kanji_search_body/kanji_search_options_bar.dart'; + +class KanjiSearchBody extends StatefulWidget { + KanjiSearchBody({Key? key}) : super(key: key); + + @override + _KanjiSearchBodyState createState() => _KanjiSearchBodyState(); +} + +class _KanjiSearchBodyState extends State + with SingleTickerProviderStateMixin { + late final AnimationController _controller; + late final Animation _searchbarMovementAnimation; + final FocusNode focus = FocusNode(); + final GlobalKey _kanjiSearchBarState = + GlobalKey(); + List suggestions = []; + + @override + void initState() { + super.initState(); + + _controller = AnimationController( + vsync: this, + duration: Duration(milliseconds: 200), + ); + + _searchbarMovementAnimation = AlignmentTween( + begin: Alignment.center, + end: Alignment.topCenter, + ).animate(CurvedAnimation( + parent: _controller, + curve: Curves.easeInOut, + )); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + if (_controller.value == 1) { + focus.unfocus(); + _kanjiSearchBarState.currentState!.clearText(); + return false; + } + return true; + }, + child: GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: BoxDecoration(), + alignment: Alignment.center, + padding: EdgeInsets.symmetric(horizontal: 20), + child: AnimatedBuilder( + animation: _searchbarMovementAnimation, + builder: (BuildContext context, _) { + return Container( + alignment: _searchbarMovementAnimation.value, + padding: EdgeInsets.symmetric(vertical: 10.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Focus( + focusNode: focus, + onFocusChange: (hasFocus) { + if (hasFocus) + _controller.forward(); + else + _controller.reverse(); + }, + child: KanjiSearchBar( + key: _kanjiSearchBarState, + onChanged: (text) => setState(() { + this.suggestions = kanjiSuggestions(text); + }), + ), + ), + AnimatedSizeAndFade( + vsync: this, + child: _controller.value == 1 + ? KanjiGrid(this.suggestions) + : KanjiSearchOptionsBar(), + fadeDuration: const Duration(milliseconds: 200), + sizeDuration: const Duration(milliseconds: 300), + ), + ], + ), + ); + }, + ), + ), + ), + ); + } +} diff --git a/lib/view/components/kanji/kanji_grid.dart b/lib/view/components/kanji/kanji_search_body/kanji_grid.dart similarity index 65% rename from lib/view/components/kanji/kanji_grid.dart rename to lib/view/components/kanji/kanji_search_body/kanji_grid.dart index 5ea3802..e80b1eb 100644 --- a/lib/view/components/kanji/kanji_grid.dart +++ b/lib/view/components/kanji/kanji_search_body/kanji_grid.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart'; import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; class KanjiGrid extends StatelessWidget { @@ -33,29 +32,28 @@ class _GridItem extends StatelessWidget { Widget build(BuildContext context) { return InkWell( onTap: () { - BlocProvider.of(context).add(GetKanji(kanji)); + Navigator.pushNamed(context, '/kanjiSearch', arguments: kanji); }, child: BlocBuilder( builder: (context, state) { final _menuColors = state.theme.menuGreyLight; - return - Container( - decoration: BoxDecoration( - color: _menuColors.background, - borderRadius: BorderRadius.circular(20.0), - ), - child: Container( - margin: EdgeInsets.all(10.0), - child: FittedBox( - child: Text( - kanji, - style: TextStyle(color: _menuColors.foreground), + return Container( + decoration: BoxDecoration( + color: _menuColors.background, + borderRadius: BorderRadius.circular(20.0), ), - ), - ), - ); + child: Container( + margin: EdgeInsets.all(10.0), + child: FittedBox( + child: Text( + kanji, + style: TextStyle(color: _menuColors.foreground), + ), + ), + ), + ); }, ), ); } -} \ No newline at end of file +} diff --git a/lib/view/components/kanji/kanji_search_bar.dart b/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart similarity index 58% rename from lib/view/components/kanji/kanji_search_bar.dart rename to lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart index fba6409..35fdb5c 100644 --- a/lib/view/components/kanji/kanji_search_bar.dart +++ b/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart @@ -1,41 +1,43 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart'; class KanjiSearchBar extends StatefulWidget { + final Function(String)? onChanged; - const KanjiSearchBar(); + KanjiSearchBar({this.onChanged, Key? key}) : super(key: key); @override - _KanjiSearchBarState createState() => new _KanjiSearchBarState(); + KanjiSearchBarState createState() => new KanjiSearchBarState(this.onChanged); } -enum TextFieldButton {clear, paste} +enum TextFieldButton { clear, paste } -class _KanjiSearchBarState extends State { +class KanjiSearchBarState extends State { final TextEditingController textController = new TextEditingController(); TextFieldButton button = TextFieldButton.paste; + final Function(String)? onChanged; + + KanjiSearchBarState(this.onChanged); @override void initState() { super.initState(); } - void _getKanjiSuggestions(String text) => - BlocProvider.of(context).add(GetKanjiSuggestions(text)); - - void updateSuggestions() => _getKanjiSuggestions(textController.text); - - void _clearText() { - textController.text = ''; - updateSuggestions(); + void runOnChanged() { + if (onChanged != null) onChanged!(textController.text); } - void _pasteText() async { + void clearText() { + textController.text = ''; + runOnChanged(); + } + + void pasteText() async { ClipboardData? clipboardData = await Clipboard.getData('text/plain'); if (clipboardData != null && clipboardData.text != null) { textController.text = clipboardData.text!; - updateSuggestions(); + runOnChanged(); } } @@ -43,29 +45,32 @@ class _KanjiSearchBarState extends State { Widget build(BuildContext context) { IconButton clearButton = IconButton( icon: Icon(Icons.clear), - onPressed: () => _clearText(), + onPressed: () => clearText(), ); IconButton pasteButton = IconButton( icon: Icon(Icons.content_paste), - onPressed: () => _pasteText(), + onPressed: () => pasteText(), ); return TextField( controller: textController, - onChanged: (text) => _getKanjiSuggestions(text), + onChanged: (text) { + if (this.onChanged != null) this.onChanged!(text); + }, onSubmitted: (_) => {}, decoration: new InputDecoration( prefixIcon: Icon(Icons.search), hintText: 'Search', // fillColor: Colors.white, - // filled: true, + // filled: true, border: OutlineInputBorder( borderRadius: BorderRadius.circular(10.0), ), isDense: false, - suffixIcon: (button == TextFieldButton.clear) ? clearButton : pasteButton, + suffixIcon: + (button == TextFieldButton.clear) ? clearButton : pasteButton, ), ); } -} \ No newline at end of file +} diff --git a/lib/view/components/kanji/kanji_search_options_bar.dart b/lib/view/components/kanji/kanji_search_body/kanji_search_options_bar.dart similarity index 73% rename from lib/view/components/kanji/kanji_search_options_bar.dart rename to lib/view/components/kanji/kanji_search_body/kanji_search_options_bar.dart index 6c2085a..4b759ed 100644 --- a/lib/view/components/kanji/kanji_search_options_bar.dart +++ b/lib/view/components/kanji/kanji_search_body/kanji_search_options_bar.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart'; //TODO: Make buttons have an effect @@ -20,18 +19,15 @@ class KanjiSearchOptionsBar extends StatelessWidget { fontSize: 18, ), ), - onPressed: () => - BlocProvider.of(context).add(ReturnToInitialState()), + onPressed: () {} ), _IconButton( icon: Icon(Icons.category), - onPressed: () => - BlocProvider.of(context).add(ReturnToInitialState()), + onPressed: () {} ), _IconButton( icon: Icon(Icons.mode), - onPressed: () => - BlocProvider.of(context).add(ReturnToInitialState()), + onPressed: () {} ), ], ), diff --git a/lib/view/components/search/search_bar.dart b/lib/view/components/search/search_bar.dart index b8d63d2..e9c7d68 100644 --- a/lib/view/components/search/search_bar.dart +++ b/lib/view/components/search/search_bar.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/search/search_bloc.dart'; import 'package:jisho_study_tool/view/components/search/language_selector.dart'; class SearchBar extends StatelessWidget { - const SearchBar(); @override @@ -13,10 +11,8 @@ class SearchBar extends StatelessWidget { child: Column( children: [ TextField( - onSubmitted: (text) { - BlocProvider.of(context) - .add(GetSearchResults(text)); - }, + onSubmitted: (text) => + Navigator.pushNamed(context, '/search', arguments: text), controller: TextEditingController(), decoration: InputDecoration( labelText: 'Search', @@ -33,4 +29,4 @@ class SearchBar extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/lib/view/components/search/search_result_body.dart b/lib/view/components/search/search_result_body.dart new file mode 100644 index 0000000..03ebe65 --- /dev/null +++ b/lib/view/components/search/search_result_body.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:jisho_study_tool/view/components/search/search_results_body/search_card.dart'; +import 'package:unofficial_jisho_api/api.dart'; + +class SearchResultsBody extends StatelessWidget { + final List results; + + const SearchResultsBody({ + required this.results, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ListView( + children: results.map((result) => SearchResultCard(result)).toList(), + ); + } +} diff --git a/lib/view/components/search/search_result_page/parts/badge.dart b/lib/view/components/search/search_results_body/parts/badge.dart similarity index 100% rename from lib/view/components/search/search_result_page/parts/badge.dart rename to lib/view/components/search/search_results_body/parts/badge.dart diff --git a/lib/view/components/search/search_result_page/parts/common_badge.dart b/lib/view/components/search/search_results_body/parts/common_badge.dart similarity index 80% rename from lib/view/components/search/search_result_page/parts/common_badge.dart rename to lib/view/components/search/search_results_body/parts/common_badge.dart index 8bb6acb..efbf9c0 100644 --- a/lib/view/components/search/search_result_page/parts/common_badge.dart +++ b/lib/view/components/search/search_results_body/parts/common_badge.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/components/search/search_result_page/parts/badge.dart'; +import './badge.dart'; class CommonBadge extends StatelessWidget { final bool isCommon; diff --git a/lib/view/components/search/search_result_page/parts/header.dart b/lib/view/components/search/search_results_body/parts/header.dart similarity index 100% rename from lib/view/components/search/search_result_page/parts/header.dart rename to lib/view/components/search/search_results_body/parts/header.dart diff --git a/lib/view/components/search/search_result_page/parts/jlpt_badge.dart b/lib/view/components/search/search_results_body/parts/jlpt_badge.dart similarity index 85% rename from lib/view/components/search/search_result_page/parts/jlpt_badge.dart rename to lib/view/components/search/search_results_body/parts/jlpt_badge.dart index d0566d6..277b132 100644 --- a/lib/view/components/search/search_result_page/parts/jlpt_badge.dart +++ b/lib/view/components/search/search_results_body/parts/jlpt_badge.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/components/search/search_result_page/parts/badge.dart'; +import './badge.dart'; class JLPTBadge extends StatelessWidget { final String jlptLevel; diff --git a/lib/view/components/search/search_result_page/parts/other_forms.dart b/lib/view/components/search/search_results_body/parts/other_forms.dart similarity index 100% rename from lib/view/components/search/search_result_page/parts/other_forms.dart rename to lib/view/components/search/search_results_body/parts/other_forms.dart diff --git a/lib/view/components/search/search_result_page/parts/senses.dart b/lib/view/components/search/search_results_body/parts/senses.dart similarity index 100% rename from lib/view/components/search/search_result_page/parts/senses.dart rename to lib/view/components/search/search_results_body/parts/senses.dart diff --git a/lib/view/components/search/search_result_page/parts/wanikani_badge.dart b/lib/view/components/search/search_results_body/parts/wanikani_badge.dart similarity index 86% rename from lib/view/components/search/search_result_page/parts/wanikani_badge.dart rename to lib/view/components/search/search_results_body/parts/wanikani_badge.dart index a24f9f8..f724131 100644 --- a/lib/view/components/search/search_result_page/parts/wanikani_badge.dart +++ b/lib/view/components/search/search_results_body/parts/wanikani_badge.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/components/search/search_result_page/parts/badge.dart'; +import './badge.dart'; class WKBadge extends StatelessWidget { final String wkLevel; diff --git a/lib/view/screens/kanji/search/grade_list.dart b/lib/view/components/search/search_results_body/parts/wikipedia_attribute.dart similarity index 100% rename from lib/view/screens/kanji/search/grade_list.dart rename to lib/view/components/search/search_results_body/parts/wikipedia_attribute.dart diff --git a/lib/view/components/search/search_result_page/search_card.dart b/lib/view/components/search/search_results_body/search_card.dart similarity index 84% rename from lib/view/components/search/search_result_page/search_card.dart rename to lib/view/components/search/search_results_body/search_card.dart index 4b045dd..b53b371 100644 --- a/lib/view/components/search/search_result_page/search_card.dart +++ b/lib/view/components/search/search_results_body/search_card.dart @@ -1,13 +1,12 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/components/search/search_result_page/parts/common_badge.dart'; -import 'package:jisho_study_tool/view/components/search/search_result_page/parts/jlpt_badge.dart'; -import 'package:jisho_study_tool/view/components/search/search_result_page/parts/wanikani_badge.dart'; - import 'package:unofficial_jisho_api/api.dart'; +import './parts/common_badge.dart'; import './parts/header.dart'; -import './parts/senses.dart'; +import './parts/jlpt_badge.dart'; import './parts/other_forms.dart'; +import './parts/senses.dart'; +import './parts/wanikani_badge.dart'; class SearchResultCard extends StatelessWidget { final JishoResult result; diff --git a/lib/view/screens/search/details.dart b/lib/view/components/search/word_details_body.dart similarity index 100% rename from lib/view/screens/search/details.dart rename to lib/view/components/search/word_details_body.dart diff --git a/lib/view/screens/kanji/search.dart b/lib/view/screens/kanji/search.dart deleted file mode 100644 index 0c3d803..0000000 --- a/lib/view/screens/kanji/search.dart +++ /dev/null @@ -1,94 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart'; -import 'package:animated_size_and_fade/animated_size_and_fade.dart'; - -import 'package:jisho_study_tool/view/components/kanji/kanji_grid.dart'; -import 'package:jisho_study_tool/view/components/kanji/kanji_search_bar.dart'; -import 'package:jisho_study_tool/view/components/kanji/kanji_search_options_bar.dart'; - -class SearchScreen extends StatefulWidget { - SearchScreen({Key? key}) : super(key: key); - - @override - _SearchScreenState createState() => _SearchScreenState(); -} - -class _SearchScreenState extends State - with SingleTickerProviderStateMixin { - late final AnimationController _controller; - late final Animation _searchbarMovementAnimation; - - @override - void initState() { - super.initState(); - - _controller = AnimationController( - vsync: this, - duration: Duration(milliseconds: 200), - ); - - _searchbarMovementAnimation = AlignmentTween( - begin: Alignment.center, - end: Alignment.topCenter, - ).animate(CurvedAnimation( - parent: _controller, - curve: Curves.easeInOut, - )); - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: () => FocusScope.of(context).unfocus(), - child: Container( - decoration: BoxDecoration(), - alignment: Alignment.center, - padding: EdgeInsets.symmetric(horizontal: 20), - child: AnimatedBuilder( - animation: _searchbarMovementAnimation, - builder: (BuildContext context, _) { - return Container( - alignment: _searchbarMovementAnimation.value, - padding: EdgeInsets.symmetric(vertical: 10.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Focus( - onFocusChange: (hasFocus) { - if (hasFocus) - _controller.forward(); - else - _controller.reverse(); - }, - child: KanjiSearchBar(), - ), - BlocBuilder( - builder: (context, state) { - return AnimatedSizeAndFade( - vsync: this, - child: _controller.value == 1 - ? KanjiGrid((state is KanjiSearchKeyboard) - ? state.kanjiSuggestions - : []) - // ? Container() - : KanjiSearchOptionsBar(), - fadeDuration: const Duration(milliseconds: 200), - sizeDuration: const Duration(milliseconds: 300), - ); - }, - ) - ], - ), - ); - }, - ), - ), - ); - } -} \ No newline at end of file diff --git a/lib/view/screens/kanji/view.dart b/lib/view/screens/kanji/view.dart deleted file mode 100644 index 4dfd38b..0000000 --- a/lib/view/screens/kanji/view.dart +++ /dev/null @@ -1,71 +0,0 @@ - -import 'package:flutter/material.dart'; - -import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart'; -import 'package:jisho_study_tool/view/screens/loading.dart'; - -import 'search.dart'; -import 'result.dart'; - -class KanjiView extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) { - if (state is KanjiSearch && state.type == KanjiSearchType.Initial) { - FocusScope.of(context).unfocus(); - } else if (state is KanjiSearchLoading) { - FocusScope.of(context).unfocus(); - } - }, - child: BlocBuilder( - builder: (context, state) { - if (state is KanjiSearch) { - if (state.type == KanjiSearchType.Initial) return SearchScreen(); - else if (state is KanjiSearchKeyboard) return SearchScreen(); - } - else if (state is KanjiSearchLoading) return LoadingScreen(); - else if (state is KanjiSearchFinished) - return WillPopScope( - child: KanjiResultCard(result: state.kanji), - onWillPop: () async { - BlocProvider.of(context) - .add(ReturnToInitialState()); - return false; - }); - throw 'No such event found'; - }, - ), - ); - } -} - -class KanjiViewBar extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Container( - child: Row( - children: [ - IconButton( - icon: Icon(Icons.arrow_back), - onPressed: () => - BlocProvider.of(context).add(ReturnToInitialState()), - ), - // Expanded( - // child: Container( - // child: KanjiSearchBar(), - // ), - // ), - // IconButton( - // icon: Icon(Icons.star_border), - // onPressed: null, - // ), - // IconButton( - // icon: Icon(Icons.add), - // onPressed: null, - // ), - ], - ), - ); - } -} \ No newline at end of file diff --git a/lib/view/screens/search/kanji_result_page.dart b/lib/view/screens/search/kanji_result_page.dart new file mode 100644 index 0000000..026a3da --- /dev/null +++ b/lib/view/screens/search/kanji_result_page.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:jisho_study_tool/bloc/database/database_bloc.dart'; +import 'package:jisho_study_tool/models/history/kanji_query.dart'; +import 'package:jisho_study_tool/models/history/search.dart'; +import 'package:jisho_study_tool/view/components/common/loading.dart'; +import 'package:jisho_study_tool/view/components/kanji/kanji_result_body.dart'; +import 'package:jisho_study_tool/services/jisho_api/kanji_search.dart'; + +class KanjiResultPage extends StatelessWidget { + final String kanjiSearchTerm; + bool addedToDatabase = false; + + KanjiResultPage({required this.kanjiSearchTerm, Key? key}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(), + body: FutureBuilder( + future: fetchKanji(this.kanjiSearchTerm), + builder: (context, snapshot) { + if (!snapshot.hasData) return LoadingScreen(); + if (snapshot.hasError) return ErrorWidget(snapshot.error!); + + if (!this.addedToDatabase) { + (BlocProvider.of(context).state as DatabaseConnected) + .database + .box() + .put(Search(timestamp: DateTime.now()) + ..kanjiQuery.target = KanjiQuery( + kanji: this.kanjiSearchTerm, + )); + this.addedToDatabase = true; + } + + return KanjiResultBody(result: (snapshot.data as KanjiResult)); + }, + ), + ); + } +} diff --git a/lib/view/screens/search/kanji_view.dart b/lib/view/screens/search/kanji_view.dart new file mode 100644 index 0000000..9859690 --- /dev/null +++ b/lib/view/screens/search/kanji_view.dart @@ -0,0 +1,11 @@ + +import 'package:flutter/material.dart'; + +import 'package:jisho_study_tool/view/components/kanji/kanji_search_body.dart'; + +class KanjiView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return KanjiSearchBody(); + } +} \ No newline at end of file diff --git a/lib/view/screens/search/results.dart b/lib/view/screens/search/results.dart deleted file mode 100644 index 8f42aff..0000000 --- a/lib/view/screens/search/results.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/search/search_bloc.dart'; -import 'package:jisho_study_tool/view/components/search/search_result_page/search_card.dart'; -import 'package:unofficial_jisho_api/api.dart'; - -class SearchResults extends StatelessWidget { - final List results; - - const SearchResults({ - required this.results, - Key? key, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return WillPopScope( - child: ListView( - children: results.map((result) => SearchResultCard(result)).toList(), - ), - onWillPop: () async { - BlocProvider.of(context).add(ReturnToInitialState()); - return false; - }, - ); - } -} diff --git a/lib/view/screens/search/search_mechanisms/drawing.dart b/lib/view/screens/search/search_mechanisms/drawing.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/view/screens/search/search_mechanisms/grade_list.dart b/lib/view/screens/search/search_mechanisms/grade_list.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/view/screens/kanji/search/grid.dart b/lib/view/screens/search/search_mechanisms/grid.dart similarity index 80% rename from lib/view/screens/kanji/search/grid.dart rename to lib/view/screens/search/search_mechanisms/grid.dart index 5aaca73..0b04f7b 100644 --- a/lib/view/screens/kanji/search/grid.dart +++ b/lib/view/screens/search/search_mechanisms/grid.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/components/kanji/kanji_grid.dart'; -import 'package:jisho_study_tool/view/components/kanji/kanji_search_bar.dart'; +import 'package:jisho_study_tool/view/components/kanji/kanji_search_body/kanji_grid.dart'; +import 'package:jisho_study_tool/view/components/kanji/kanji_search_body/kanji_search_bar.dart'; class SearchGrid extends StatelessWidget { final List suggestions; diff --git a/lib/view/screens/kanji/search/radical_list.dart b/lib/view/screens/search/search_mechanisms/radical_list.dart similarity index 100% rename from lib/view/screens/kanji/search/radical_list.dart rename to lib/view/screens/search/search_mechanisms/radical_list.dart diff --git a/lib/view/screens/search/search_results_page.dart b/lib/view/screens/search/search_results_page.dart new file mode 100644 index 0000000..aae389d --- /dev/null +++ b/lib/view/screens/search/search_results_page.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:jisho_study_tool/bloc/database/database_bloc.dart'; +import 'package:jisho_study_tool/models/history/search.dart'; +import 'package:jisho_study_tool/models/history/word_query.dart'; +import 'package:jisho_study_tool/view/components/common/loading.dart'; +import 'package:jisho_study_tool/view/components/search/search_result_body.dart'; +import 'package:jisho_study_tool/services/jisho_api/jisho_search.dart'; + +class SearchResultsPage extends StatelessWidget { + final String searchTerm; + final Future results; + bool addedToDatabase = false; + + SearchResultsPage({required this.searchTerm, Key? key}) + : this.results = fetchJishoResults(searchTerm), + super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(), + body: FutureBuilder( + future: results, + builder: (context, snapshot) { + if (!snapshot.hasData) return LoadingScreen(); + if (snapshot.hasError || + (snapshot.data as JishoAPIResult).data == null) + return ErrorWidget(snapshot.error!); + + if (!this.addedToDatabase) { + (BlocProvider.of(context).state as DatabaseConnected) + .database + .box() + .put(Search(timestamp: DateTime.now()) + ..wordQuery.target = WordQuery( + query: this.searchTerm, + )); + this.addedToDatabase = true; + } + + return SearchResultsBody( + results: (snapshot.data as JishoAPIResult).data!, + ); + }, + ), + ); + } +} diff --git a/lib/view/screens/search/search_view.dart b/lib/view/screens/search/search_view.dart new file mode 100644 index 0000000..4c8b613 --- /dev/null +++ b/lib/view/screens/search/search_view.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; +import 'package:jisho_study_tool/view/components/search/search_bar.dart'; + +class SearchView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SearchBar(), + ], + ); + } +} diff --git a/lib/view/screens/search/view.dart b/lib/view/screens/search/view.dart deleted file mode 100644 index 651a7c5..0000000 --- a/lib/view/screens/search/view.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/search/search_bloc.dart'; -import 'package:jisho_study_tool/view/components/search/search_bar.dart'; -import 'package:jisho_study_tool/view/screens/loading.dart'; -import 'package:jisho_study_tool/view/screens/search/results.dart'; - -class SearchView extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocConsumer( - listener: (context, state) {}, - builder: (context, state) { - if (state is SearchInitial) - return _InitialView(); - else if (state is SearchLoading) - return LoadingScreen(); - else if (state is SearchFinished) { - return SearchResults(results: state.results); - } - throw 'No such event found'; - }, - ); - } -} - -class _InitialView extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Column(mainAxisAlignment: MainAxisAlignment.center, children: [ - SearchBar(), - ]); - } -} diff --git a/pubspec.lock b/pubspec.lock index 62ace01..fd22efb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -15,20 +15,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.7.2" + animated_size_and_fade: + dependency: "direct main" + description: + name: animated_size_and_fade + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.2" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.2.0" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.7.0" + version: "2.8.2" bloc: dependency: transitive description: @@ -56,14 +70,14 @@ packages: name: build_config url: "https://pub.dartlang.org" source: hosted - version: "0.4.7" + version: "1.0.0" build_daemon: dependency: transitive description: name: build_daemon url: "https://pub.dartlang.org" source: hosted - version: "2.1.10" + version: "3.0.0" build_resolvers: dependency: transitive description: @@ -77,14 +91,14 @@ packages: name: build_runner url: "https://pub.dartlang.org" source: hosted - version: "1.12.2" + version: "2.0.6" build_runner_core: dependency: transitive description: name: build_runner_core url: "https://pub.dartlang.org" source: hosted - version: "6.1.12" + version: "7.0.1" built_collection: dependency: transitive description: @@ -112,7 +126,7 @@ packages: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" checked_yaml: dependency: transitive description: @@ -140,7 +154,7 @@ packages: name: code_builder url: "https://pub.dartlang.org" source: hosted - version: "3.7.0" + version: "4.1.0" collection: dependency: transitive description: @@ -148,6 +162,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0" + confirm_dialog: + dependency: "direct main" + description: + name: confirm_dialog + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" convert: dependency: transitive description: @@ -168,7 +189,7 @@ packages: name: csslib url: "https://pub.dartlang.org" source: hosted - version: "0.16.2" + version: "0.17.0" dart_style: dependency: transitive description: @@ -182,7 +203,7 @@ packages: name: division url: "https://pub.dartlang.org" source: hosted - version: "0.8.8" + version: "0.9.0" fake_async: dependency: transitive description: @@ -222,7 +243,28 @@ packages: name: flutter_bloc url: "https://pub.dartlang.org" source: hosted - version: "7.0.0" + version: "7.2.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.2" + flutter_native_splash: + dependency: "direct dev" + description: + name: flutter_native_splash + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" + flutter_slidable: + dependency: "direct main" + description: + name: flutter_slidable + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.0" flutter_test: dependency: "direct dev" description: flutter @@ -233,6 +275,13 @@ packages: description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" glob: dependency: transitive description: @@ -246,28 +295,28 @@ packages: name: graphs url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "2.0.0" html: dependency: transitive description: name: html url: "https://pub.dartlang.org" source: hosted - version: "0.14.0+4" + version: "0.15.0" html_unescape: dependency: transitive description: name: html_unescape url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "2.0.0" http: dependency: transitive description: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.12.2" + version: "0.13.3" http_multi_server: dependency: transitive description: @@ -281,7 +330,14 @@ packages: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "3.1.4" + version: "4.0.0" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" io: dependency: transitive description: @@ -316,21 +372,21 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" mdi: dependency: "direct main" description: name: mdi url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "5.0.0-nullsafety.0" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.4.0" + version: "1.7.0" mime: dependency: transitive description: @@ -422,6 +478,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.11.0" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.0" platform: dependency: transitive description: @@ -435,7 +498,7 @@ packages: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "2.0.1" pool: dependency: transitive description: @@ -456,7 +519,7 @@ packages: name: provider url: "https://pub.dartlang.org" source: hosted - version: "5.0.0" + version: "6.0.0" pub_semver: dependency: transitive description: @@ -471,13 +534,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" + settings_ui: + dependency: "direct main" + description: + name: settings_ui + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" shared_preferences: dependency: "direct main" description: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.7" shared_preferences_linux: dependency: transitive description: @@ -519,14 +589,14 @@ packages: name: shelf url: "https://pub.dartlang.org" source: hosted - version: "0.7.9" + version: "1.2.0" shelf_web_socket: dependency: transitive description: name: shelf_web_socket url: "https://pub.dartlang.org" source: hosted - version: "0.2.4+1" + version: "1.0.1" sky_engine: dependency: transitive description: flutter @@ -587,7 +657,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.0" + version: "0.4.3" timing: dependency: transitive description: @@ -602,20 +672,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0" + universal_io: + dependency: transitive + description: + name: universal_io + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" unofficial_jisho_api: dependency: "direct main" description: name: unofficial_jisho_api url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "2.0.3" url_launcher: dependency: "direct main" description: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.0.3" + version: "6.0.10" url_launcher_linux: dependency: transitive description: @@ -636,7 +713,7 @@ packages: name: url_launcher_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.4" url_launcher_web: dependency: transitive description: @@ -686,6 +763,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.0" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "5.2.0" yaml: dependency: transitive description: @@ -694,5 +778,5 @@ packages: source: hosted version: "3.1.0" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=2.13.0 <3.0.0" flutter: ">=2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 53933ed..d12202d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,6 +41,7 @@ flutter: assets: - assets/images/denshi_jisho_background_overlay.png + - assets/images/logo/ # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg From 8811cef86491cc823c4d292cb683735f42cfbc90 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 1 Dec 2021 23:09:53 +0100 Subject: [PATCH 2/8] Update code style --- analysis_options.yaml | 169 ++++++++++++++++++ lib/bloc/database/database_bloc.dart | 10 +- lib/bloc/database/database_event.dart | 2 +- .../database_not_connected_exception.dart | 2 +- lib/bloc/database/database_state.dart | 3 +- lib/bloc/theme/theme_bloc.dart | 13 +- lib/bloc/theme/theme_state.dart | 4 +- lib/main.dart | 64 +++---- lib/models/history/search.dart | 10 +- lib/models/history/word_query.dart | 2 +- lib/models/history/word_result.dart | 4 +- lib/models/themes/dark.dart | 10 +- lib/models/themes/light.dart | 10 +- lib/models/themes/theme.dart | 10 +- lib/router.dart | 38 ++-- lib/services/jisho_api/jisho_search.dart | 4 +- lib/services/jisho_api/kanji_search.dart | 19 +- lib/view/components/common/loading.dart | 8 +- lib/view/components/common/splash.dart | 11 +- lib/view/components/history/date_divider.dart | 29 +-- .../components/history/kanji_search_item.dart | 8 +- .../history/phrase_search_item.dart | 19 +- lib/view/components/history/search_item.dart | 30 ++-- .../components/kanji/kanji_result_body.dart | 89 ++++----- .../kanji/kanji_result_body/examples.dart | 83 ++++----- .../kanji/kanji_result_body/grade.dart | 17 +- .../kanji/kanji_result_body/header.dart | 11 +- .../kanji/kanji_result_body/jlpt_level.dart | 24 +-- .../kanji/kanji_result_body/radical.dart | 18 +- .../kanji/kanji_result_body/rank.dart | 19 +- .../kanji_result_body/stroke_order_gif.dart | 20 ++- .../kanji/kanji_result_body/yomi_chips.dart | 131 +++++++------- .../components/kanji/kanji_search_body.dart | 40 +++-- .../kanji/kanji_search_body/kanji_grid.dart | 9 +- .../kanji_search_body/kanji_search_bar.dart | 24 +-- .../kanji_search_options_bar.dart | 14 +- lib/view/components/opaque_box.dart | 4 +- .../components/search/language_selector.dart | 51 +++--- lib/view/components/search/search_bar.dart | 11 +- .../components/search/search_result_body.dart | 5 +- .../search_results_body/parts/badge.dart | 24 +-- .../parts/common_badge.dart | 17 +- .../search_results_body/parts/header.dart | 17 +- .../search_results_body/parts/jlpt_badge.dart | 22 +-- .../parts/other_forms.dart | 64 +++---- .../search_results_body/parts/senses.dart | 64 +++---- .../parts/wanikani_badge.dart | 4 +- .../search_results_body/search_card.dart | 36 ++-- lib/view/screens/history.dart | 146 ++++++++------- .../screens/search/kanji_result_page.dart | 32 ++-- lib/view/screens/search/kanji_view.dart | 6 +- .../search/search_mechanisms/grid.dart | 32 ++-- .../search_mechanisms/radical_list.dart | 2 +- .../screens/search/search_results_page.dart | 36 ++-- lib/view/screens/search/search_view.dart | 6 +- lib/view/screens/settings.dart | 66 +++---- pubspec.lock | 2 +- test/widget_test.dart | 30 ---- 58 files changed, 955 insertions(+), 700 deletions(-) create mode 100644 analysis_options.yaml delete mode 100644 test/widget_test.dart diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..9974d7f --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,169 @@ +analyzer: + exclude: + - "lib/objectbox.g.dart" + +linter: + rules: + # these rules are documented on and in the same order as + # the Dart Lint rules page to make maintenance easier + # https://github.com/dart-lang/linter/blob/master/example/all.yaml + - always_declare_return_types + # - always_put_control_body_on_new_line # Allow return statements on same line as ifs + # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 + - always_require_non_null_named_parameters + # - always_specify_types + # - always_use_package_imports # we do this commonly + - annotate_overrides + - avoid_bool_literals_in_conditional_expressions + - avoid_classes_with_only_static_members + - avoid_double_and_int_checks + - avoid_dynamic_calls + - avoid_empty_else + - avoid_equals_and_hash_code_on_mutable_classes + - avoid_escaping_inner_quotes + - avoid_field_initializers_in_const_classes + - avoid_function_literals_in_foreach_calls + - avoid_implementing_value_types + - avoid_init_to_null + - avoid_js_rounded_ints + - avoid_multiple_declarations_per_line + - avoid_null_checks_in_equality_operators + - avoid_positional_boolean_parameters + - avoid_print + # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) + - avoid_redundant_argument_values + - avoid_relative_lib_imports + - avoid_renaming_method_parameters + - avoid_return_types_on_setters + - avoid_returning_null + - avoid_returning_null_for_future + - avoid_returning_null_for_void + - avoid_setters_without_getters + - avoid_shadowing_type_parameters + - avoid_single_cascade_in_expression_statements + - avoid_slow_async_io + - avoid_type_to_string + - avoid_types_as_parameter_names + - avoid_types_on_closure_parameters + - avoid_unnecessary_containers + - avoid_unused_constructor_parameters + - avoid_void_async + - await_only_futures + - camel_case_extensions + - camel_case_types + - cancel_subscriptions + - cast_nullable_to_non_nullable + - control_flow_in_finally + # - curly_braces_in_flow_control_structures + - depend_on_referenced_packages + - deprecated_consistency + - directives_ordering + - do_not_use_environment + - empty_catches + - empty_constructor_bodies + - empty_statements + - eol_at_end_of_file + - exhaustive_cases + - file_names + # - flutter_style_todos # This is mostly a single person project for the time being + - hash_and_equals + - implementation_imports + - iterable_contains_unrelated_type + - join_return_with_assignment + - leading_newlines_in_multiline_strings + - library_names + - library_prefixes + - library_private_types_in_public_api + # - lines_longer_than_80_chars + - list_remove_unrelated_type + - missing_whitespace_between_adjacent_strings + - no_adjacent_strings_in_list + - no_default_cases + - no_duplicate_case_values + - no_logic_in_create_state + # - non_constant_identifier_names # use API names for several variables + - noop_primitive_operations + - null_check_on_nullable_type_parameter + - null_closures + - only_throw_errors + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + - prefer_adjacent_string_concatenation + - prefer_asserts_in_initializer_lists + - prefer_collection_literals + - prefer_conditional_assignment + - prefer_const_constructors + - prefer_const_constructors_in_immutables + - prefer_const_declarations + - prefer_const_literals_to_create_immutables + - prefer_contains + - prefer_equal_for_default_values + - prefer_final_fields + - prefer_final_in_for_each + - prefer_final_locals + # - prefer_final_parameters + - prefer_for_elements_to_map_fromIterable + - prefer_foreach + - prefer_function_declarations_over_variables + - prefer_generic_function_type_aliases + # - prefer_if_elements_to_conditional_expressions + - prefer_if_null_operators + - prefer_initializing_formals + - prefer_inlined_adds + - prefer_interpolation_to_compose_strings + - prefer_is_empty + - prefer_is_not_empty + - prefer_is_not_operator + - prefer_iterable_whereType + - prefer_null_aware_operators + - prefer_relative_imports + - prefer_single_quotes + - prefer_spread_collections + - prefer_typing_uninitialized_variables + - prefer_void_to_null + - provide_deprecation_message + - recursive_getters + - require_trailing_commas + - sized_box_for_whitespace + - slash_for_doc_comments + - sort_child_properties_last + # - sort_constructors_first + - sort_unnamed_constructors_first + - test_types_in_equals + - throw_in_finally + - tighten_type_of_initializing_formals + - type_init_formals + - unnecessary_await_in_return + - unnecessary_brace_in_string_interps + - unnecessary_const + - unnecessary_constructor_name + - unnecessary_getters_setters + - unnecessary_new + - unnecessary_null_aware_assignments + - unnecessary_null_checks + - unnecessary_null_in_if_null_operators + - unnecessary_nullable_for_final_variable_declarations + - unnecessary_overrides + - unnecessary_parenthesis + - unnecessary_statements + - unnecessary_string_escapes + - unnecessary_string_interpolations + - unnecessary_this + - unrelated_type_equality_checks + - unsafe_html + - use_build_context_synchronously + - use_full_hex_values_for_flutter_colors + - use_function_type_syntax_for_parameters + - use_is_even_rather_than_modulo + - use_key_in_widget_constructors + - use_late_for_private_fields_and_variables + - use_named_constants + - use_raw_strings + - use_rethrow_when_possible + - use_setters_to_change_properties + - use_test_throws_matchers + - valid_regexps + - void_checks + \ No newline at end of file diff --git a/lib/bloc/database/database_bloc.dart b/lib/bloc/database/database_bloc.dart index 37d338c..d9b0403 100644 --- a/lib/bloc/database/database_bloc.dart +++ b/lib/bloc/database/database_bloc.dart @@ -1,5 +1,5 @@ -import 'package:bloc/bloc.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import './database_event.dart'; import './database_state.dart'; @@ -7,12 +7,12 @@ import './database_state.dart'; export 'package:flutter_bloc/flutter_bloc.dart'; export './database_event.dart'; -export './database_state.dart'; export './database_not_connected_exception.dart'; +export './database_state.dart'; class DatabaseBloc extends Bloc { - DatabaseBloc() : super(DatabaseDisconnected()); + DatabaseBloc() : super(const DatabaseDisconnected()); @override Stream mapEventToState(DatabaseEvent event) @@ -20,8 +20,8 @@ class DatabaseBloc extends Bloc { if (event is ConnectedToDatabase) { yield DatabaseConnected(event.database); } else { - yield DatabaseDisconnected(); + yield const DatabaseDisconnected(); } } -} \ No newline at end of file +} diff --git a/lib/bloc/database/database_event.dart b/lib/bloc/database/database_event.dart index 0b65487..799860e 100644 --- a/lib/bloc/database/database_event.dart +++ b/lib/bloc/database/database_event.dart @@ -11,4 +11,4 @@ class ConnectedToDatabase extends DatabaseEvent { class DisconnectedFromDatabase extends DatabaseEvent { const DisconnectedFromDatabase(); -} \ No newline at end of file +} diff --git a/lib/bloc/database/database_not_connected_exception.dart b/lib/bloc/database/database_not_connected_exception.dart index d062330..e873be7 100644 --- a/lib/bloc/database/database_not_connected_exception.dart +++ b/lib/bloc/database/database_not_connected_exception.dart @@ -1 +1 @@ -class DatabaseNotConnectedException implements Exception {} \ No newline at end of file +class DatabaseNotConnectedException implements Exception {} diff --git a/lib/bloc/database/database_state.dart b/lib/bloc/database/database_state.dart index 042443f..68d33c4 100644 --- a/lib/bloc/database/database_state.dart +++ b/lib/bloc/database/database_state.dart @@ -1,4 +1,3 @@ - import 'package:objectbox/objectbox.dart'; abstract class DatabaseState { @@ -12,4 +11,4 @@ class DatabaseConnected extends DatabaseState { class DatabaseDisconnected extends DatabaseState { const DatabaseDisconnected(); -} \ No newline at end of file +} diff --git a/lib/bloc/theme/theme_bloc.dart b/lib/bloc/theme/theme_bloc.dart index 49167b7..9db66ac 100644 --- a/lib/bloc/theme/theme_bloc.dart +++ b/lib/bloc/theme/theme_bloc.dart @@ -1,10 +1,11 @@ import 'dart:async'; -import 'package:bloc/bloc.dart'; -import 'package:jisho_study_tool/models/themes/theme.dart'; -import 'package:meta/meta.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import '../../models/themes/theme.dart'; + export 'package:flutter_bloc/flutter_bloc.dart'; export 'package:jisho_study_tool/models/themes/theme.dart'; @@ -14,10 +15,10 @@ part 'theme_state.dart'; class ThemeBloc extends Bloc { bool prefsAreLoaded = false; - ThemeBloc() : super(LightThemeState()) { + ThemeBloc() : super(const LightThemeState()) { SharedPreferences.getInstance().then((prefs) { - this.prefsAreLoaded = true; - this.add( + prefsAreLoaded = true; + add( SetTheme( themeIsDark: prefs.getBool('darkThemeEnabled') ?? false, ), diff --git a/lib/bloc/theme/theme_state.dart b/lib/bloc/theme/theme_state.dart index d4bb021..7bb3518 100644 --- a/lib/bloc/theme/theme_state.dart +++ b/lib/bloc/theme/theme_state.dart @@ -14,6 +14,7 @@ class LightThemeState extends ThemeState { const LightThemeState({this.prefsAreLoaded = false}) : super(prefsAreLoaded); + @override AppTheme get theme => LightTheme(); } @@ -22,5 +23,6 @@ class DarkThemeState extends ThemeState { const DarkThemeState({this.prefsAreLoaded = false}) : super(prefsAreLoaded); + @override AppTheme get theme => DarkTheme(); -} \ No newline at end of file +} diff --git a/lib/main.dart b/lib/main.dart index 189d5af..e76989a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,27 +1,26 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; -import 'package:jisho_study_tool/router.dart'; -import 'package:jisho_study_tool/view/components/common/splash.dart'; import 'package:mdi/mdi.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart'; +import 'package:path_provider/path_provider.dart'; -import 'package:jisho_study_tool/objectbox.g.dart'; - -import 'package:jisho_study_tool/bloc/database/database_bloc.dart'; - -import 'package:jisho_study_tool/view/screens/search/kanji_view.dart'; -import 'package:jisho_study_tool/view/screens/history.dart'; -import 'package:jisho_study_tool/view/screens/search/search_view.dart'; -import 'package:jisho_study_tool/view/screens/settings.dart'; - +import 'bloc/database/database_bloc.dart'; +import 'bloc/theme/theme_bloc.dart'; import 'models/themes/theme.dart'; +import 'objectbox.g.dart'; +import 'router.dart'; +import 'view/components/common/splash.dart'; +import 'view/screens/history.dart'; +import 'view/screens/search/kanji_view.dart'; +import 'view/screens/search/search_view.dart'; +import 'view/screens/settings.dart'; -void main() => runApp(MyApp()); +void main() => runApp(const MyApp()); DatabaseBloc _databaseBloc = DatabaseBloc(); class MyApp extends StatefulWidget { + const MyApp({Key? key}) : super(key: key); + @override _MyAppState createState() => _MyAppState(); } @@ -50,7 +49,7 @@ class _MyAppState extends State { @override void dispose() { _store.close(); - _databaseBloc.add(DisconnectedFromDatabase()); + _databaseBloc.add(const DisconnectedFromDatabase()); super.dispose(); } @@ -64,13 +63,13 @@ class _MyAppState extends State { child: BlocBuilder( builder: (context, themeState) { if (!(dbConnected && themeState.prefsAreLoaded)) - return SplashScreen(); + return const SplashScreen(); return MaterialApp( title: 'Jisho Study Tool', theme: themeState.theme.getMaterialTheme(), initialRoute: '/', - onGenerateRoute: PageRouter.generateRoute, + onGenerateRoute: generateRoute, ); }, ), @@ -79,6 +78,8 @@ class _MyAppState extends State { } class Home extends StatefulWidget { + const Home({Key? key}) : super(key: key); + @override State createState() => _HomeState(); } @@ -100,11 +101,12 @@ class _HomeState extends State { body: Stack( children: [ Positioned( - child: Image.asset( - 'assets/images/denshi_jisho_background_overlay.png'), right: 30, left: 100, bottom: 30, + child: Image.asset( + 'assets/images/denshi_jisho_background_overlay.png', + ), ), pages[pageNum].content, ], @@ -112,8 +114,8 @@ class _HomeState extends State { bottomNavigationBar: BottomNavigationBar( fixedColor: AppTheme.jishoGreen.background, currentIndex: pageNum, - onTap: (int index) => setState(() { - this.pageNum = index; + onTap: (index) => setState(() { + pageNum = index; }), items: pages.map((p) => p.item).toList(), showSelectedLabels: false, @@ -139,7 +141,7 @@ class _Page { } final List<_Page> pages = [ - _Page( + const _Page( content: SearchView(), titleBar: Text('Search'), item: BottomNavigationBarItem( @@ -147,15 +149,17 @@ final List<_Page> pages = [ icon: Icon(Icons.search), ), ), - _Page( + const _Page( content: KanjiView(), titleBar: Text('Kanji'), item: BottomNavigationBarItem( - label: 'Kanji', icon: Icon(Mdi.ideogramCjk, size: 30)), + label: 'Kanji', + icon: Icon(Mdi.ideogramCjk, size: 30), + ), ), - _Page( + const _Page( content: HistoryView(), - titleBar: Text("History"), + titleBar: Text('History'), item: BottomNavigationBarItem( label: 'History', icon: Icon(Icons.history), @@ -163,15 +167,15 @@ final List<_Page> pages = [ ), _Page( content: Container(), - titleBar: Text("Saved"), - item: BottomNavigationBarItem( + titleBar: const Text('Saved'), + item: const BottomNavigationBarItem( label: 'Saved', icon: Icon(Icons.bookmark), ), ), - _Page( + const _Page( content: SettingsView(), - titleBar: Text("Settings"), + titleBar: Text('Settings'), item: BottomNavigationBarItem( label: 'Settings', icon: Icon(Icons.settings), diff --git a/lib/models/history/search.dart b/lib/models/history/search.dart index f371573..9f37c48 100644 --- a/lib/models/history/search.dart +++ b/lib/models/history/search.dart @@ -16,15 +16,15 @@ class Search { Search({ this.id = 0, - required this.timestamp - }); // { + required this.timestamp, + }); bool isKanji() { // // TODO: better error message - if (this.wordQuery.target == null && this.kanjiQuery.target == null) + if (wordQuery.target == null && kanjiQuery.target == null) throw Exception(); - return this.wordQuery.target == null; + return wordQuery.target == null; } -} \ No newline at end of file +} diff --git a/lib/models/history/word_query.dart b/lib/models/history/word_query.dart index 6041b00..e7d42f2 100644 --- a/lib/models/history/word_query.dart +++ b/lib/models/history/word_query.dart @@ -16,4 +16,4 @@ class WordQuery { this.id = 0, required this.query, }); -} \ No newline at end of file +} diff --git a/lib/models/history/word_result.dart b/lib/models/history/word_result.dart index 75d1f5c..f959f33 100644 --- a/lib/models/history/word_result.dart +++ b/lib/models/history/word_result.dart @@ -1,6 +1,6 @@ import 'package:objectbox/objectbox.dart'; -import 'package:jisho_study_tool/models/history/word_query.dart'; +import 'word_query.dart'; @Entity() class WordResult { @@ -18,4 +18,4 @@ class WordResult { required this.timestamp, required this.word, }); -} \ No newline at end of file +} diff --git a/lib/models/themes/dark.dart b/lib/models/themes/dark.dart index 618fc73..cc7a903 100644 --- a/lib/models/themes/dark.dart +++ b/lib/models/themes/dark.dart @@ -1,34 +1,42 @@ part of './theme.dart'; class DarkTheme extends AppTheme { + @override ColorSet get kanjiResultColor => const ColorSet( foreground: Colors.white, background: Colors.green, ); + @override ColorSet get onyomiColor => const ColorSet( foreground: Colors.white, background: Colors.orange, ); + @override ColorSet get kunyomiColor => const ColorSet( foreground: Colors.white, background: Colors.lightBlue, ); + @override Color get foreground => Colors.black; + @override Color get background => Colors.white; + @override ColorSet get menuGreyLight => ColorSet( foreground: Colors.white, background: Colors.grey.shade700, ); - ColorSet get menuGreyNormal => ColorSet( + @override + ColorSet get menuGreyNormal => const ColorSet( foreground: Colors.white, background: Colors.grey, ); + @override ColorSet get menuGreyDark => ColorSet( foreground: Colors.black, background: Colors.grey.shade300, diff --git a/lib/models/themes/light.dart b/lib/models/themes/light.dart index d1cccc2..6b7fcc1 100644 --- a/lib/models/themes/light.dart +++ b/lib/models/themes/light.dart @@ -1,33 +1,41 @@ part of './theme.dart'; class LightTheme extends AppTheme { + @override ColorSet get kanjiResultColor => const ColorSet( foreground: Colors.white, background: Colors.blue, ); + @override ColorSet get onyomiColor => const ColorSet( foreground: Colors.white, background: Colors.orange, ); + @override ColorSet get kunyomiColor => const ColorSet( foreground: Colors.white, background: Colors.lightBlue, ); + @override Color get foreground => Colors.black; + @override Color get background => Colors.white; + @override ColorSet get menuGreyLight => ColorSet( foreground: Colors.black, background: Colors.grey.shade300, ); - ColorSet get menuGreyNormal => ColorSet( + @override + ColorSet get menuGreyNormal => const ColorSet( foreground: Colors.white, background: Colors.grey, ); + @override ColorSet get menuGreyDark => ColorSet( foreground: Colors.white, background: Colors.grey.shade700, diff --git a/lib/models/themes/theme.dart b/lib/models/themes/theme.dart index d1a591f..76369cc 100644 --- a/lib/models/themes/theme.dart +++ b/lib/models/themes/theme.dart @@ -4,7 +4,6 @@ part 'light.dart'; part 'dark.dart'; abstract class AppTheme { - static const ColorSet jishoGreen = ColorSet( foreground: Colors.white, background: Color(0xFF3EDD00), @@ -49,14 +48,15 @@ class ColorSet { /// Source: https://blog.usejournal.com/creating-a-custom-color-swatch-in-flutter-554bcdcb27f3 MaterialColor createMaterialColor(Color color) { - List strengths = [.05]; + final List strengths = [.05]; final swatch = {}; final int r = color.red, g = color.green, b = color.blue; for (int i = 1; i < 10; i++) { strengths.add(0.1 * i); } - strengths.forEach((strength) { + + for (final strength in strengths) { final double ds = 0.5 - strength; swatch[(strength * 1000).round()] = Color.fromRGBO( r + ((ds < 0 ? r : (255 - r)) * ds).round(), @@ -64,6 +64,6 @@ MaterialColor createMaterialColor(Color color) { b + ((ds < 0 ? b : (255 - b)) * ds).round(), 1, ); - }); + } return MaterialColor(color.value, swatch); -} \ No newline at end of file +} diff --git a/lib/router.dart b/lib/router.dart index cc3452d..a588e5c 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -1,27 +1,31 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/screens/search/kanji_result_page.dart'; -import 'package:jisho_study_tool/view/screens/search/search_results_page.dart'; import 'main.dart'; +import 'view/screens/search/kanji_result_page.dart'; +import 'view/screens/search/search_results_page.dart'; -class PageRouter { - static Route generateRoute(RouteSettings settings) { - final args = settings.arguments; +Route generateRoute(RouteSettings settings) { + final args = settings.arguments; - switch (settings.name) { - case '/': - return MaterialPageRoute(builder: (_) => Home()); + switch (settings.name) { + case '/': + return MaterialPageRoute(builder: (_) => const Home()); - case '/search': - final searchTerm = args as String; - return MaterialPageRoute(builder: (_) => SearchResultsPage(searchTerm: searchTerm)); + case '/search': + final searchTerm = args as String; + return MaterialPageRoute( + builder: (_) => SearchResultsPage(searchTerm: searchTerm), + ); - case '/kanjiSearch': - final searchTerm = args as String; - return MaterialPageRoute(builder: (_) => KanjiResultPage(kanjiSearchTerm: searchTerm)); + case '/kanjiSearch': + final searchTerm = args as String; + return MaterialPageRoute( + builder: (_) => KanjiResultPage(kanjiSearchTerm: searchTerm), + ); - default: - return MaterialPageRoute(builder: (_) => Text("ERROR: this route does not exist")); - } + default: + return MaterialPageRoute( + builder: (_) => const Text('ERROR: this route does not exist'), + ); } } diff --git a/lib/services/jisho_api/jisho_search.dart b/lib/services/jisho_api/jisho_search.dart index 8024a5a..3459bda 100644 --- a/lib/services/jisho_api/jisho_search.dart +++ b/lib/services/jisho_api/jisho_search.dart @@ -2,5 +2,5 @@ import 'package:unofficial_jisho_api/api.dart' as jisho; export 'package:unofficial_jisho_api/api.dart' show JishoAPIResult; Future fetchJishoResults(searchTerm) async { - return await jisho.searchForPhrase(searchTerm); -} \ No newline at end of file + return jisho.searchForPhrase(searchTerm); +} diff --git a/lib/services/jisho_api/kanji_search.dart b/lib/services/jisho_api/kanji_search.dart index 7015894..76e8a31 100644 --- a/lib/services/jisho_api/kanji_search.dart +++ b/lib/services/jisho_api/kanji_search.dart @@ -1,18 +1,19 @@ +import 'package:flutter/material.dart'; import 'package:unofficial_jisho_api/api.dart' as jisho; export 'package:unofficial_jisho_api/api.dart' show KanjiResult; String? _convertGrade(String grade) { const conversionTable = { - "grade 1": "小1", - "grade 2": "小2", - "grade 3": "小3", - "grade 4": "小4", - "grade 5": "小5", - "grade 6": "小6", - "junior high": "中" + 'grade 1': '小1', + 'grade 2': '小2', + 'grade 3': '小3', + 'grade 4': '小4', + 'grade 5': '小5', + 'grade 6': '小6', + 'junior high': '中' }; - print('conversion run: $grade -> ${conversionTable[grade]}'); + debugPrint('conversion run: $grade -> ${conversionTable[grade]}'); return conversionTable[grade]; } @@ -24,4 +25,4 @@ Future fetchKanji(String kanji) async { if (result.data != null && result.data?.taughtIn != null) result.data!.taughtIn = _convertGrade(result.data!.taughtIn!); return result; -} \ No newline at end of file +} diff --git a/lib/view/components/common/loading.dart b/lib/view/components/common/loading.dart index 327c44c..2f30fff 100644 --- a/lib/view/components/common/loading.dart +++ b/lib/view/components/common/loading.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; class LoadingScreen extends StatelessWidget { + const LoadingScreen({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { - return Container( - child: Center( - child: CircularProgressIndicator(), - ), + return const Center( + child: CircularProgressIndicator(), ); } } diff --git a/lib/view/components/common/splash.dart b/lib/view/components/common/splash.dart index 3d05254..e453f34 100644 --- a/lib/view/components/common/splash.dart +++ b/lib/view/components/common/splash.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/models/themes/theme.dart'; + +import '../../../models/themes/theme.dart'; class SplashScreen extends StatelessWidget { const SplashScreen({Key? key}) : super(key: key); @@ -8,9 +9,11 @@ class SplashScreen extends StatelessWidget { Widget build(BuildContext context) { return Container( decoration: BoxDecoration(color: AppTheme.jishoGreen.background), - child: Center( - child: Image(image: AssetImage('assets/images/logo/logo_icon_transparent.png'),) + child: const Center( + child: Image( + image: AssetImage('assets/images/logo/logo_icon_transparent.png'), + ), ), ); } -} \ No newline at end of file +} diff --git a/lib/view/components/history/date_divider.dart b/lib/view/components/history/date_divider.dart index 992728e..6d98fc1 100644 --- a/lib/view/components/history/date_divider.dart +++ b/lib/view/components/history/date_divider.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; -import 'package:jisho_study_tool/models/themes/theme.dart'; + +import '../../../bloc/theme/theme_bloc.dart'; +import '../../../models/themes/theme.dart'; class DateDivider extends StatelessWidget { final String? text; @@ -33,31 +34,31 @@ class DateDivider extends StatelessWidget { final int day = date.day; final String month = monthTable[date.month]!; final int year = date.year; - return "$day. $month $year"; + return '$day. $month $year'; } @override Widget build(BuildContext context) { - final Widget header = (this.text != null) - ? Text(this.text!) - : (this.date != null) - ? Text(getHumanReadableDate(this.date!)) - : SizedBox.shrink(); + final Widget header = (text != null) + ? Text(text!) + : (date != null) + ? Text(getHumanReadableDate(date!)) + : const SizedBox.shrink(); final ColorSet _menuColors = BlocProvider.of(context).state.theme.menuGreyNormal; return Container( + decoration: BoxDecoration(color: _menuColors.background), + padding: const EdgeInsets.symmetric( + vertical: 5, + horizontal: 10, + ), + margin: margin, child: DefaultTextStyle.merge( child: header, style: TextStyle(color: _menuColors.foreground), ), - decoration: BoxDecoration(color: _menuColors.background), - padding: EdgeInsets.symmetric( - vertical: 5, - horizontal: 10, - ), - margin: this.margin, ); } } diff --git a/lib/view/components/history/kanji_search_item.dart b/lib/view/components/history/kanji_search_item.dart index 3eed671..5a9d405 100644 --- a/lib/view/components/history/kanji_search_item.dart +++ b/lib/view/components/history/kanji_search_item.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; -import 'package:jisho_study_tool/models/history/kanji_query.dart'; -import 'package:jisho_study_tool/models/themes/theme.dart'; import './search_item.dart'; +import '../../../bloc/theme/theme_bloc.dart'; +import '../../../models/history/kanji_query.dart'; +import '../../../models/themes/theme.dart'; class _KanjiBox extends StatelessWidget { final String kanji; @@ -19,7 +19,7 @@ class _KanjiBox extends StatelessWidget { child: AspectRatio( aspectRatio: 1, child: Container( - padding: EdgeInsets.all(5), + padding: const EdgeInsets.all(5), decoration: BoxDecoration( color: _menuColors.background, borderRadius: BorderRadius.circular(10.0), diff --git a/lib/view/components/history/phrase_search_item.dart b/lib/view/components/history/phrase_search_item.dart index c0052c7..402a5e0 100644 --- a/lib/view/components/history/phrase_search_item.dart +++ b/lib/view/components/history/phrase_search_item.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; -import 'package:jisho_study_tool/models/history/word_query.dart'; import './search_item.dart'; +import '../../../models/history/word_query.dart'; class PhraseSearchItem extends StatelessWidget { final WordQuery search; @@ -17,15 +17,20 @@ class PhraseSearchItem extends StatelessWidget { @override Widget build(BuildContext context) { return Slidable( - actionPane: SlidableScrollActionPane(), - secondaryActions: [ + actionPane: const SlidableScrollActionPane(), + secondaryActions: const [ IconSlideAction( - caption: "Delete", color: Colors.red, icon: Icons.delete) + caption: 'Delete', + color: Colors.red, + icon: Icons.delete, + ), ], child: SearchItem( - onTap: () { - Navigator.pushNamed(context, '/search', arguments: this.search.query); - }, + onTap: () => Navigator.pushNamed( + context, + '/search', + arguments: search.query, + ), time: timestamp, search: Text(search.query), ), diff --git a/lib/view/components/history/search_item.dart b/lib/view/components/history/search_item.dart index 826a4fa..7025b18 100644 --- a/lib/view/components/history/search_item.dart +++ b/lib/view/components/history/search_item.dart @@ -13,26 +13,24 @@ class SearchItem extends StatelessWidget { }) : super(key: key); String getTime() { - final hours = this.time.hour.toString().padLeft(2, '0'); - final mins = this.time.minute.toString().padLeft(2, '0'); - return "$hours:$mins"; + final hours = time.hour.toString().padLeft(2, '0'); + final mins = time.minute.toString().padLeft(2, '0'); + return '$hours:$mins'; } @override Widget build(BuildContext context) { - return Container( - child: ListTile( - onTap: onTap, - contentPadding: EdgeInsets.zero, - title: Row( - children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: 20), - child: Text(getTime()), - ), - search, - ], - ), + return ListTile( + onTap: onTap, + contentPadding: EdgeInsets.zero, + title: Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text(getTime()), + ), + search, + ], ), ); } diff --git a/lib/view/components/kanji/kanji_result_body.dart b/lib/view/components/kanji/kanji_result_body.dart index 821f643..f94c128 100644 --- a/lib/view/components/kanji/kanji_result_body.dart +++ b/lib/view/components/kanji/kanji_result_body.dart @@ -14,14 +14,13 @@ class KanjiResultBody extends StatelessWidget { late final String query; late final jisho.KanjiResultData resultData; - KanjiResultBody({required jisho.KanjiResult result}) { - + KanjiResultBody({required jisho.KanjiResult result, Key? key}) + : super(key: key) { query = result.query; // TODO: Handle this kind of exception before widget is initialized - if (result.data == null) - throw Exception(); - + if (result.data == null) throw Exception(); + resultData = result.data!; } @@ -30,69 +29,73 @@ class KanjiResultBody extends StatelessWidget { return ListView( children: [ Container( - margin: EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 30.0), + margin: const EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 30.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - Flexible( - flex: 1, + const Flexible( fit: FlexFit.tight, child: Center(child: SizedBox()), ), Flexible( - flex: 1, fit: FlexFit.tight, - child: Center(child: Header(query)), + child: Center(child: Header(kanji: query)), ), Flexible( - flex: 1, fit: FlexFit.tight, child: Center( - child: (resultData.radical != null) ? Radical(resultData.radical!) : SizedBox(), + child: (resultData.radical != null) + ? Radical(radical: resultData.radical!) + : const SizedBox(), ), ), ], ), ), - YomiChips(resultData.meaning.split(', '), YomiType.meaning), - resultData.onyomi.length != 0 ? YomiChips(resultData.onyomi, YomiType.onyomi) : SizedBox.shrink(), - resultData.kunyomi.length != 0 ? YomiChips(resultData.kunyomi, YomiType.kunyomi) : SizedBox.shrink(), + YomiChips(yomi: resultData.meaning.split(', '), type: YomiType.meaning), + (resultData.onyomi.isNotEmpty) + ? YomiChips(yomi: resultData.onyomi, type: YomiType.onyomi) + : const SizedBox.shrink(), + (resultData.kunyomi.isNotEmpty) + ? YomiChips(yomi: resultData.kunyomi, type: YomiType.kunyomi) + : const SizedBox.shrink(), IntrinsicHeight( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - StrokeOrderGif(resultData.strokeOrderGifUri), - Container( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Text("JLPT: ", style: TextStyle(fontSize: 20.0)), - JlptLevel(resultData.jlptLevel ?? "⨉"), - ], - ), - Row( - children: [ - Text("Grade: ", style: TextStyle(fontSize: 20.0)), - Grade(resultData.taughtIn ?? "⨉"), - ], - ), - Row( - children: [ - Text("Rank: ", style: TextStyle(fontSize: 20.0)), - Rank(resultData.newspaperFrequencyRank ?? -1), - ], - ), - ], - ), + StrokeOrderGif(uri: resultData.strokeOrderGifUri), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + const Text('JLPT: ', style: TextStyle(fontSize: 20.0)), + JlptLevel(jlptLevel: resultData.jlptLevel ?? '⨉'), + ], + ), + Row( + children: [ + const Text('Grade: ', style: TextStyle(fontSize: 20.0)), + Grade(grade: resultData.taughtIn ?? '⨉'), + ], + ), + Row( + children: [ + const Text('Rank: ', style: TextStyle(fontSize: 20.0)), + Rank(rank: resultData.newspaperFrequencyRank ?? -1), + ], + ), + ], ), ], ), ), - Examples(resultData.onyomiExamples, resultData.kunyomiExamples), + Examples( + onyomi: resultData.onyomiExamples, + kunyomi: resultData.kunyomiExamples, + ), ], ); } -} \ No newline at end of file +} diff --git a/lib/view/components/kanji/kanji_result_body/examples.dart b/lib/view/components/kanji/kanji_result_body/examples.dart index 9f4b78e..8740336 100644 --- a/lib/view/components/kanji/kanji_result_body/examples.dart +++ b/lib/view/components/kanji/kanji_result_body/examples.dart @@ -1,15 +1,17 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; import 'package:unofficial_jisho_api/api.dart'; -class Examples extends StatelessWidget { - final List onyomiExamples; - final List kunyomiExamples; +import '../../../../bloc/theme/theme_bloc.dart'; - const Examples( - this.onyomiExamples, - this.kunyomiExamples, - ); +class Examples extends StatelessWidget { + final List onyomi; + final List kunyomi; + + const Examples({ + required this.onyomi, + required this.kunyomi, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -17,20 +19,21 @@ class Examples extends StatelessWidget { children: [ [ Container( - margin: EdgeInsets.symmetric(horizontal: 10), + margin: const EdgeInsets.symmetric(horizontal: 10), alignment: Alignment.centerLeft, - child: Text( + child: const Text( 'Examples:', style: TextStyle(fontSize: 20), ), ) ], - onyomiExamples + onyomi .map((onyomiExample) => _Example(onyomiExample, _KanaType.onyomi)) .toList(), - kunyomiExamples + kunyomi .map( - (kunyomiExample) => _Example(kunyomiExample, _KanaType.kunyomi)) + (kunyomiExample) => _Example(kunyomiExample, _KanaType.kunyomi), + ) .toList(), ].expand((list) => list).toList(), ); @@ -48,68 +51,66 @@ class _Example extends StatelessWidget { @override Widget build(BuildContext context) { final _themeData = BlocProvider.of(context).state.theme; - final _kanaColors = kanaType == _KanaType.kunyomi ? _themeData.kunyomiColor : _themeData.onyomiColor; + final _kanaColors = kanaType == _KanaType.kunyomi + ? _themeData.kunyomiColor + : _themeData.onyomiColor; final _menuColors = _themeData.menuGreyNormal; - return Container( - margin: EdgeInsets.symmetric( + return Container( + margin: const EdgeInsets.symmetric( vertical: 5.0, horizontal: 10.0, ), decoration: BoxDecoration( - color: _menuColors.background, borderRadius: BorderRadius.circular(10.0)), + color: _menuColors.background, + borderRadius: BorderRadius.circular(10.0), + ), child: Row( children: [ Container( - padding: EdgeInsets.symmetric( + padding: const EdgeInsets.symmetric( vertical: 10.0, horizontal: 10.0, ), decoration: BoxDecoration( color: _kanaColors.background, - borderRadius: BorderRadius.only( + borderRadius: const BorderRadius.only( topLeft: Radius.circular(10.0), bottomLeft: Radius.circular(10.0), ), ), child: Column( children: [ - Container( - child: Text( - yomiExample.reading, - style: TextStyle( - color: _kanaColors.foreground, - fontSize: 15.0, - ), + Text( + yomiExample.reading, + style: TextStyle( + color: _kanaColors.foreground, + fontSize: 15.0, ), ), - SizedBox( + const SizedBox( height: 5.0, ), - Container( - child: Text( - yomiExample.example, - style: TextStyle( - color: _kanaColors.foreground, - fontSize: 20.0, - ), + Text( + yomiExample.example, + style: TextStyle( + color: _kanaColors.foreground, + fontSize: 20.0, ), ), ], ), ), - SizedBox( + const SizedBox( width: 15.0, ), Expanded( child: Wrap( children: [ - Container( - child: Text( - yomiExample.meaning, - style: TextStyle( - color: _menuColors.foreground, - ), + Text( + yomiExample.meaning, + style: TextStyle( + color: _menuColors.foreground, ), ) ], diff --git a/lib/view/components/kanji/kanji_result_body/grade.dart b/lib/view/components/kanji/kanji_result_body/grade.dart index 12fb36e..abe2443 100644 --- a/lib/view/components/kanji/kanji_result_body/grade.dart +++ b/lib/view/components/kanji/kanji_result_body/grade.dart @@ -1,17 +1,22 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; + +import '../../../../bloc/theme/theme_bloc.dart'; class Grade extends StatelessWidget { final String grade; - const Grade(this.grade); + const Grade({required this.grade, Key? key}) : super(key: key); @override Widget build(BuildContext context) { final _kanjiColors = BlocProvider.of(context).state.theme.kanjiResultColor; return Container( - padding: EdgeInsets.all(10.0), + padding: const EdgeInsets.all(10.0), + decoration: BoxDecoration( + color: _kanjiColors.background, + shape: BoxShape.circle, + ), child: Text( grade, style: TextStyle( @@ -19,10 +24,6 @@ class Grade extends StatelessWidget { fontSize: 20.0, ), ), - decoration: BoxDecoration( - color: _kanjiColors.background, - shape: BoxShape.circle, - ), ); } -} \ No newline at end of file +} diff --git a/lib/view/components/kanji/kanji_result_body/header.dart b/lib/view/components/kanji/kanji_result_body/header.dart index d0f999c..c86fb5d 100644 --- a/lib/view/components/kanji/kanji_result_body/header.dart +++ b/lib/view/components/kanji/kanji_result_body/header.dart @@ -1,14 +1,19 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; + +import '../../../../bloc/theme/theme_bloc.dart'; class Header extends StatelessWidget { final String kanji; - const Header(this.kanji); + const Header({ + required this.kanji, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { - final _kanjiColors = BlocProvider.of(context).state.theme.kanjiResultColor; + final _kanjiColors = + BlocProvider.of(context).state.theme.kanjiResultColor; return AspectRatio( aspectRatio: 1, diff --git a/lib/view/components/kanji/kanji_result_body/jlpt_level.dart b/lib/view/components/kanji/kanji_result_body/jlpt_level.dart index 2cc2fe1..f63cbc3 100644 --- a/lib/view/components/kanji/kanji_result_body/jlpt_level.dart +++ b/lib/view/components/kanji/kanji_result_body/jlpt_level.dart @@ -1,18 +1,26 @@ - import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; + +import '../../../../bloc/theme/theme_bloc.dart'; class JlptLevel extends StatelessWidget { final String jlptLevel; - const JlptLevel(this.jlptLevel); + const JlptLevel({ + required this.jlptLevel, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { - final _kanjiColors = BlocProvider.of(context).state.theme.kanjiResultColor; + final _kanjiColors = + BlocProvider.of(context).state.theme.kanjiResultColor; return Container( - padding: EdgeInsets.all(10.0), + padding: const EdgeInsets.all(10.0), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: _kanjiColors.background, + ), child: Text( jlptLevel, style: TextStyle( @@ -20,10 +28,6 @@ class JlptLevel extends StatelessWidget { fontSize: 20.0, ), ), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: _kanjiColors.background, - ), ); } -} \ No newline at end of file +} diff --git a/lib/view/components/kanji/kanji_result_body/radical.dart b/lib/view/components/kanji/kanji_result_body/radical.dart index d208e00..aa7ef1e 100644 --- a/lib/view/components/kanji/kanji_result_body/radical.dart +++ b/lib/view/components/kanji/kanji_result_body/radical.dart @@ -1,18 +1,24 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; import 'package:unofficial_jisho_api/api.dart' as jisho; +import '../../../../bloc/theme/theme_bloc.dart'; + class Radical extends StatelessWidget { final jisho.Radical radical; - const Radical(this.radical); + const Radical({required this.radical, Key? key,}) : super(key: key); + @override Widget build(BuildContext context) { final _kanjiColors = BlocProvider.of(context).state.theme.kanjiResultColor; return Container( - padding: EdgeInsets.all(10.0), + padding: const EdgeInsets.all(10.0), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: _kanjiColors.background, + ), child: Text( radical.symbol, style: TextStyle( @@ -20,10 +26,6 @@ class Radical extends StatelessWidget { fontSize: 40.0, ), ), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: _kanjiColors.background, - ), ); } -} \ No newline at end of file +} diff --git a/lib/view/components/kanji/kanji_result_body/rank.dart b/lib/view/components/kanji/kanji_result_body/rank.dart index 24356fb..89279ac 100644 --- a/lib/view/components/kanji/kanji_result_body/rank.dart +++ b/lib/view/components/kanji/kanji_result_body/rank.dart @@ -1,18 +1,23 @@ - import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; + +import '../../../../bloc/theme/theme_bloc.dart'; class Rank extends StatelessWidget { final int rank; - const Rank(this.rank); + const Rank({required this.rank, Key? key,}) : super(key: key); + @override Widget build(BuildContext context) { final _kanjiColors = BlocProvider.of(context).state.theme.kanjiResultColor; return Container( - padding: EdgeInsets.all(10.0), + padding: const EdgeInsets.all(10.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10.0), + color: _kanjiColors.background, + ), child: Text( '${rank.toString()} / 2500', style: TextStyle( @@ -20,10 +25,6 @@ class Rank extends StatelessWidget { fontSize: 20.0, ), ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10.0), - color: _kanjiColors.background, - ), ); } -} \ No newline at end of file +} diff --git a/lib/view/components/kanji/kanji_result_body/stroke_order_gif.dart b/lib/view/components/kanji/kanji_result_body/stroke_order_gif.dart index ecda698..75fb00d 100644 --- a/lib/view/components/kanji/kanji_result_body/stroke_order_gif.dart +++ b/lib/view/components/kanji/kanji_result_body/stroke_order_gif.dart @@ -1,26 +1,28 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; + +import '../../../../bloc/theme/theme_bloc.dart'; class StrokeOrderGif extends StatelessWidget { final String uri; - const StrokeOrderGif(this.uri); + const StrokeOrderGif({required this.uri, Key? key,}) : super(key: key); + @override Widget build(BuildContext context) { final _kanjiColors = BlocProvider.of(context).state.theme.kanjiResultColor; return Container( - margin: EdgeInsets.symmetric(vertical: 20.0), - padding: EdgeInsets.all(5.0), - child: ClipRRect( - child: Image.network(uri), - borderRadius: BorderRadius.circular(10.0), - ), + margin: const EdgeInsets.symmetric(vertical: 20.0), + padding: const EdgeInsets.all(5.0), decoration: BoxDecoration( color: _kanjiColors.background, borderRadius: BorderRadius.circular(15.0), ), + child: ClipRRect( + borderRadius: BorderRadius.circular(10.0), + child: Image.network(uri), + ), ); } -} \ No newline at end of file +} diff --git a/lib/view/components/kanji/kanji_result_body/yomi_chips.dart b/lib/view/components/kanji/kanji_result_body/yomi_chips.dart index 7ee1757..ce5eb20 100644 --- a/lib/view/components/kanji/kanji_result_body/yomi_chips.dart +++ b/lib/view/components/kanji/kanji_result_body/yomi_chips.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; + +import '../../../../bloc/theme/theme_bloc.dart'; enum YomiType { onyomi, @@ -37,86 +38,88 @@ class YomiChips extends StatelessWidget { final List yomi; final YomiType type; - const YomiChips(this.yomi, this.type); + const YomiChips({ + required this.yomi, + required this.type, + Key? key, + }) : super(key: key); - @override - Widget build(BuildContext context) { - return Container( - margin: EdgeInsets.symmetric( - horizontal: 10.0, - vertical: 5.0, - ), - alignment: Alignment.centerLeft, - child: _yomiWrapper(context), - ); - } + bool get isExpandable => yomi.length > 6; - bool isExpandable() => yomi.length > 6; + Widget yomiCard({ + required BuildContext context, + required String yomi, + required ColorSet colors, + }) => + Container( + margin: const EdgeInsets.symmetric(horizontal: 10.0), + padding: const EdgeInsets.symmetric( + vertical: 10.0, + horizontal: 10.0, + ), + decoration: BoxDecoration( + color: type.getColors(context).background, + borderRadius: BorderRadius.circular(10.0), + ), + child: Text( + yomi, + style: TextStyle( + fontSize: 20.0, + color: colors.foreground, + ), + ), + ); - Widget _yomiWrapper(BuildContext context) { - final yomiCards = this - .yomi - .map((yomi) => _YomiCard( - yomi: yomi, - colors: this.type.getColors(context), - )) + Widget yomiWrapper(BuildContext context) { + final yomiCards = yomi + .map( + (y) => yomiCard( + context: context, + yomi: y, + colors: type.getColors(context), + ), + ) .toList(); - if (!this.isExpandable()) + if (!isExpandable) return Wrap( runSpacing: 10.0, children: yomiCards, ); - - return ExpansionTile( - initiallyExpanded: false, - title: Center( - child: _YomiCard( - yomi: this.type.title, - colors: this.type.getColors(context), + else + return ExpansionTile( + // initiallyExpanded: false, + title: Center( + child: yomiCard( + context: context, + yomi: type.title, + colors: type.getColors(context), + ), ), - ), - children: [ - SizedBox( - height: 20.0, - ), - Wrap( - runSpacing: 10.0, - children: yomiCards, - ), - SizedBox( - height: 25.0, - ), - ], - ); + children: [ + const SizedBox( + height: 20.0, + ), + Wrap( + runSpacing: 10.0, + children: yomiCards, + ), + const SizedBox( + height: 25.0, + ), + ], + ); } -} - -class _YomiCard extends StatelessWidget { - final String yomi; - final ColorSet colors; - - const _YomiCard({required this.yomi, required this.colors}); @override Widget build(BuildContext context) { return Container( - margin: EdgeInsets.symmetric(horizontal: 10.0), - padding: EdgeInsets.symmetric( - vertical: 10.0, + margin: const EdgeInsets.symmetric( horizontal: 10.0, + vertical: 5.0, ), - child: Text( - this.yomi, - style: TextStyle( - fontSize: 20.0, - color: colors.foreground, - ), - ), - decoration: BoxDecoration( - color: colors.background, - borderRadius: BorderRadius.circular(10.0), - ), + alignment: Alignment.centerLeft, + child: yomiWrapper(context), ); } } diff --git a/lib/view/components/kanji/kanji_search_body.dart b/lib/view/components/kanji/kanji_search_body.dart index 1a8154f..6f04919 100644 --- a/lib/view/components/kanji/kanji_search_body.dart +++ b/lib/view/components/kanji/kanji_search_body.dart @@ -1,13 +1,13 @@ -import 'package:flutter/material.dart'; import 'package:animated_size_and_fade/animated_size_and_fade.dart'; -import 'package:jisho_study_tool/services/kanji_suggestions.dart'; +import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/components/kanji/kanji_search_body/kanji_grid.dart'; -import 'package:jisho_study_tool/view/components/kanji/kanji_search_body/kanji_search_bar.dart'; -import 'package:jisho_study_tool/view/components/kanji/kanji_search_body/kanji_search_options_bar.dart'; +import '../../../services/kanji_suggestions.dart'; +import 'kanji_search_body/kanji_grid.dart'; +import 'kanji_search_body/kanji_search_bar.dart'; +import 'kanji_search_body/kanji_search_options_bar.dart'; class KanjiSearchBody extends StatefulWidget { - KanjiSearchBody({Key? key}) : super(key: key); + const KanjiSearchBody({Key? key}) : super(key: key); @override _KanjiSearchBodyState createState() => _KanjiSearchBodyState(); @@ -28,16 +28,18 @@ class _KanjiSearchBodyState extends State _controller = AnimationController( vsync: this, - duration: Duration(milliseconds: 200), + duration: const Duration(milliseconds: 200), ); _searchbarMovementAnimation = AlignmentTween( begin: Alignment.center, end: Alignment.topCenter, - ).animate(CurvedAnimation( - parent: _controller, - curve: Curves.easeInOut, - )); + ).animate( + CurvedAnimation( + parent: _controller, + curve: Curves.easeInOut, + ), + ); } @override @@ -60,15 +62,15 @@ class _KanjiSearchBodyState extends State child: GestureDetector( onTap: () => FocusScope.of(context).unfocus(), child: Container( - decoration: BoxDecoration(), + decoration: const BoxDecoration(), alignment: Alignment.center, - padding: EdgeInsets.symmetric(horizontal: 20), + padding: const EdgeInsets.symmetric(horizontal: 20), child: AnimatedBuilder( animation: _searchbarMovementAnimation, - builder: (BuildContext context, _) { + builder: (context, _) { return Container( alignment: _searchbarMovementAnimation.value, - padding: EdgeInsets.symmetric(vertical: 10.0), + padding: const EdgeInsets.symmetric(vertical: 10.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -83,17 +85,17 @@ class _KanjiSearchBodyState extends State child: KanjiSearchBar( key: _kanjiSearchBarState, onChanged: (text) => setState(() { - this.suggestions = kanjiSuggestions(text); + suggestions = kanjiSuggestions(text); }), ), ), AnimatedSizeAndFade( vsync: this, - child: _controller.value == 1 - ? KanjiGrid(this.suggestions) - : KanjiSearchOptionsBar(), fadeDuration: const Duration(milliseconds: 200), sizeDuration: const Duration(milliseconds: 300), + child: _controller.value == 1 + ? KanjiGrid(suggestions: suggestions) + : const KanjiSearchOptionsBar(), ), ], ), diff --git a/lib/view/components/kanji/kanji_search_body/kanji_grid.dart b/lib/view/components/kanji/kanji_search_body/kanji_grid.dart index e80b1eb..8373be9 100644 --- a/lib/view/components/kanji/kanji_search_body/kanji_grid.dart +++ b/lib/view/components/kanji/kanji_search_body/kanji_grid.dart @@ -1,15 +1,16 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; +import '../../../../bloc/theme/theme_bloc.dart'; class KanjiGrid extends StatelessWidget { final List suggestions; - const KanjiGrid(this.suggestions); + + const KanjiGrid({required this.suggestions, Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Container( - padding: EdgeInsets.symmetric( + padding: const EdgeInsets.symmetric( vertical: 20.0, horizontal: 40.0, ), @@ -43,7 +44,7 @@ class _GridItem extends StatelessWidget { borderRadius: BorderRadius.circular(20.0), ), child: Container( - margin: EdgeInsets.all(10.0), + margin: const EdgeInsets.all(10.0), child: FittedBox( child: Text( kanji, diff --git a/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart b/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart index 35fdb5c..7f2ef5d 100644 --- a/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart +++ b/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart @@ -4,16 +4,16 @@ import 'package:flutter/services.dart'; class KanjiSearchBar extends StatefulWidget { final Function(String)? onChanged; - KanjiSearchBar({this.onChanged, Key? key}) : super(key: key); + const KanjiSearchBar({this.onChanged, Key? key}) : super(key: key); @override - KanjiSearchBarState createState() => new KanjiSearchBarState(this.onChanged); + KanjiSearchBarState createState() => KanjiSearchBarState(this.onChanged); } enum TextFieldButton { clear, paste } class KanjiSearchBarState extends State { - final TextEditingController textController = new TextEditingController(); + final TextEditingController textController = TextEditingController(); TextFieldButton button = TextFieldButton.paste; final Function(String)? onChanged; @@ -33,8 +33,8 @@ class KanjiSearchBarState extends State { runOnChanged(); } - void pasteText() async { - ClipboardData? clipboardData = await Clipboard.getData('text/plain'); + Future pasteText() async { + final ClipboardData? clipboardData = await Clipboard.getData('text/plain'); if (clipboardData != null && clipboardData.text != null) { textController.text = clipboardData.text!; runOnChanged(); @@ -43,24 +43,24 @@ class KanjiSearchBarState extends State { @override Widget build(BuildContext context) { - IconButton clearButton = IconButton( - icon: Icon(Icons.clear), + final IconButton clearButton = IconButton( + icon: const Icon(Icons.clear), onPressed: () => clearText(), ); - IconButton pasteButton = IconButton( - icon: Icon(Icons.content_paste), + final IconButton pasteButton = IconButton( + icon: const Icon(Icons.content_paste), onPressed: () => pasteText(), ); return TextField( controller: textController, onChanged: (text) { - if (this.onChanged != null) this.onChanged!(text); + if (onChanged != null) onChanged!(text); }, onSubmitted: (_) => {}, - decoration: new InputDecoration( - prefixIcon: Icon(Icons.search), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.search), hintText: 'Search', // fillColor: Colors.white, // filled: true, diff --git a/lib/view/components/kanji/kanji_search_body/kanji_search_options_bar.dart b/lib/view/components/kanji/kanji_search_body/kanji_search_options_bar.dart index 4b759ed..23aad34 100644 --- a/lib/view/components/kanji/kanji_search_body/kanji_search_options_bar.dart +++ b/lib/view/components/kanji/kanji_search_body/kanji_search_options_bar.dart @@ -12,22 +12,22 @@ class KanjiSearchOptionsBar extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ _IconButton( - icon: Text( - "部", + icon: const Text( + '部', style: TextStyle( fontWeight: FontWeight.w700, fontSize: 18, ), ), - onPressed: () {} + onPressed: () {}, ), _IconButton( - icon: Icon(Icons.category), - onPressed: () {} + icon: const Icon(Icons.category), + onPressed: () {}, ), _IconButton( - icon: Icon(Icons.mode), - onPressed: () {} + icon: const Icon(Icons.mode), + onPressed: () {}, ), ], ), diff --git a/lib/view/components/opaque_box.dart b/lib/view/components/opaque_box.dart index c8cc7db..87d5ff5 100644 --- a/lib/view/components/opaque_box.dart +++ b/lib/view/components/opaque_box.dart @@ -9,7 +9,7 @@ class OpaqueBox extends StatelessWidget { Widget build(BuildContext context) { return Container( decoration: BoxDecoration(color: Theme.of(context).scaffoldBackgroundColor), - child: this.child, + child: child, ); } -} \ No newline at end of file +} diff --git a/lib/view/components/search/language_selector.dart b/lib/view/components/search/language_selector.dart index b28cbe1..2ee1bf1 100644 --- a/lib/view/components/search/language_selector.dart +++ b/lib/view/components/search/language_selector.dart @@ -1,12 +1,13 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/models/themes/theme.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import '../../../models/themes/theme.dart'; + class LanguageSelector extends StatefulWidget { - const LanguageSelector(); + const LanguageSelector({Key? key}) : super(key: key); @override - _LanguageSelectorState createState() => new _LanguageSelectorState(); + _LanguageSelectorState createState() => _LanguageSelectorState(); } class _LanguageSelectorState extends State { @@ -18,27 +19,26 @@ class _LanguageSelectorState extends State { super.initState(); isSelected = [false, false, false]; - SharedPreferences.getInstance() - .then((prefs) { - this.prefs = prefs; - setState(() { - isSelected = _getSelectedStatus() ?? isSelected; - }); + SharedPreferences.getInstance().then((prefs) { + this.prefs = prefs; + setState(() { + isSelected = _getSelectedStatus() ?? isSelected; }); + }); } - void _updateSelectedStatus() async { - await prefs.setStringList('languageSelectorStatus', - isSelected - .map((b) => b ? '1' : '0') - .toList()); + void _updateSelectedStatus() { + prefs.setStringList( + 'languageSelectorStatus', + isSelected.map((b) => b ? '1' : '0').toList(), + ); } List? _getSelectedStatus() { return prefs - .getStringList('languageSelectorStatus') - ?.map((s) => s == '1') - .toList(); + .getStringList('languageSelectorStatus') + ?.map((s) => s == '1') + .toList(); } @override @@ -46,14 +46,14 @@ class _LanguageSelectorState extends State { return ToggleButtons( selectedColor: AppTheme.jishoGreen.background, isSelected: isSelected, - children: [ - _LanguageOption("Auto"), - _LanguageOption("日本語"), - _LanguageOption("English") + children: const [ + _LanguageOption('Auto'), + _LanguageOption('日本語'), + _LanguageOption('English') ], - onPressed: (int buttonIndex) { + onPressed: (buttonIndex) { setState(() { - for (var i in Iterable.generate(isSelected.length)) { + for (final int i in Iterable.generate(isSelected.length)) { isSelected[i] = i == buttonIndex; } _updateSelectedStatus(); @@ -61,7 +61,6 @@ class _LanguageSelectorState extends State { }, ); } - } class _LanguageOption extends StatelessWidget { @@ -72,8 +71,8 @@ class _LanguageOption extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), + padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), child: Center(child: Text(language)), ); } -} \ No newline at end of file +} diff --git a/lib/view/components/search/search_bar.dart b/lib/view/components/search/search_bar.dart index e9c7d68..9a70692 100644 --- a/lib/view/components/search/search_bar.dart +++ b/lib/view/components/search/search_bar.dart @@ -1,13 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/components/search/language_selector.dart'; + +import 'language_selector.dart'; class SearchBar extends StatelessWidget { - const SearchBar(); + const SearchBar({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Container( - padding: EdgeInsets.symmetric(horizontal: 20.0), + padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Column( children: [ TextField( @@ -21,10 +22,10 @@ class SearchBar extends StatelessWidget { ), ), ), - SizedBox( + const SizedBox( height: 10.0, ), - LanguageSelector() + const LanguageSelector() ], ), ); diff --git a/lib/view/components/search/search_result_body.dart b/lib/view/components/search/search_result_body.dart index 03ebe65..d00c770 100644 --- a/lib/view/components/search/search_result_body.dart +++ b/lib/view/components/search/search_result_body.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/components/search/search_results_body/search_card.dart'; import 'package:unofficial_jisho_api/api.dart'; +import 'search_results_body/search_card.dart'; + class SearchResultsBody extends StatelessWidget { final List results; @@ -13,7 +14,7 @@ class SearchResultsBody extends StatelessWidget { @override Widget build(BuildContext context) { return ListView( - children: results.map((result) => SearchResultCard(result)).toList(), + children: results.map((result) => SearchResultCard(result: result)).toList(), ); } } diff --git a/lib/view/components/search/search_results_body/parts/badge.dart b/lib/view/components/search/search_results_body/parts/badge.dart index 3ddf3aa..457fc01 100644 --- a/lib/view/components/search/search_results_body/parts/badge.dart +++ b/lib/view/components/search/search_results_body/parts/badge.dart @@ -1,27 +1,27 @@ import 'package:flutter/material.dart'; class Badge extends StatelessWidget { - final Widget child; + final Widget? child; final Color color; - const Badge(this.child, this.color); + const Badge({this.child, required this.color, Key? key,}) : super(key: key); + @override Widget build(BuildContext context) { return Container( - child: FittedBox( - child: Center( - child: this.child - ), - ), - padding: EdgeInsets.all(5), + padding: const EdgeInsets.all(5), width: 30, height: 30, - margin: EdgeInsets.symmetric(horizontal: 2), + margin: const EdgeInsets.symmetric(horizontal: 2), decoration: BoxDecoration( shape: BoxShape.circle, - color: color + color: color, + ), + child: FittedBox( + child: Center( + child: child, + ), ), ); } - -} \ No newline at end of file +} diff --git a/lib/view/components/search/search_results_body/parts/common_badge.dart b/lib/view/components/search/search_results_body/parts/common_badge.dart index efbf9c0..bdcaad2 100644 --- a/lib/view/components/search/search_results_body/parts/common_badge.dart +++ b/lib/view/components/search/search_results_body/parts/common_badge.dart @@ -4,16 +4,21 @@ import './badge.dart'; class CommonBadge extends StatelessWidget { final bool isCommon; - const CommonBadge(this.isCommon); + const CommonBadge({ + required this.isCommon, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { return Badge( - Text( - "C", - style: TextStyle(color: this.isCommon ? Colors.white : Colors.transparent) + color: isCommon ? Colors.green : Colors.transparent, + child: Text( + 'C', + style: TextStyle( + color: isCommon ? Colors.white : Colors.transparent, + ), ), - this.isCommon ? Colors.green : Colors.transparent ); } -} \ No newline at end of file +} diff --git a/lib/view/components/search/search_results_body/parts/header.dart b/lib/view/components/search/search_results_body/parts/header.dart index 677ae37..46eaba4 100644 --- a/lib/view/components/search/search_results_body/parts/header.dart +++ b/lib/view/components/search/search_results_body/parts/header.dart @@ -3,21 +3,24 @@ import 'package:unofficial_jisho_api/api.dart'; class JapaneseHeader extends StatelessWidget { final JishoJapaneseWord word; - - const JapaneseHeader(this.word); + + const JapaneseHeader({ + required this.word, + Key? key, + }) : super(key: key); + + bool get hasFurigana => word.word != null && word.reading != null; @override Widget build(BuildContext context) { - final hasFurigana = (word.word != null && word.reading != null); - return Container( alignment: Alignment.centerLeft, - padding: EdgeInsets.only(left: 10.0), + padding: const EdgeInsets.only(left: 10.0), child: Column( children: [ // TODO: take a look at this logic - (hasFurigana) ? Text(word.reading!) : Text(''), - (hasFurigana) ? Text(word.word!) : Text(word.reading ?? word.word!), + hasFurigana ? Text(word.reading!) : const Text(''), + hasFurigana ? Text(word.word!) : Text(word.reading ?? word.word!), ], ), ); diff --git a/lib/view/components/search/search_results_body/parts/jlpt_badge.dart b/lib/view/components/search/search_results_body/parts/jlpt_badge.dart index 277b132..77e97c5 100644 --- a/lib/view/components/search/search_results_body/parts/jlpt_badge.dart +++ b/lib/view/components/search/search_results_body/parts/jlpt_badge.dart @@ -4,22 +4,22 @@ import './badge.dart'; class JLPTBadge extends StatelessWidget { final String jlptLevel; - const JLPTBadge(this.jlptLevel); + const JLPTBadge({ + required this.jlptLevel, + Key? key, + }) : super(key: key); - String _extractJlptLevel(String jlptRaw) { - return jlptRaw.isNotEmpty ? jlptRaw.substring(5).toUpperCase() : ''; - } + String get formattedJlptLevel => + jlptLevel.isNotEmpty ? jlptLevel.substring(5).toUpperCase() : ''; @override Widget build(BuildContext context) { return Badge( - Text( - _extractJlptLevel(this.jlptLevel), - style: TextStyle( - color: Colors.white - ), + color: jlptLevel.isNotEmpty ? Colors.blue : Colors.transparent, + child: Text( + formattedJlptLevel, + style: const TextStyle(color: Colors.white), ), - this.jlptLevel.isNotEmpty ? Colors.blue : Colors.transparent ); } -} \ No newline at end of file +} diff --git a/lib/view/components/search/search_results_body/parts/other_forms.dart b/lib/view/components/search/search_results_body/parts/other_forms.dart index 8ea8dc1..d690f8c 100644 --- a/lib/view/components/search/search_results_body/parts/other_forms.dart +++ b/lib/view/components/search/search_results_body/parts/other_forms.dart @@ -1,28 +1,27 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; import 'package:unofficial_jisho_api/api.dart'; -class OtherForms extends StatelessWidget { - final List otherForms; +import '../../../../../bloc/theme/theme_bloc.dart'; - const OtherForms(this.otherForms); +class OtherForms extends StatelessWidget { + final List forms; + + const OtherForms({required this.forms, Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return Container( - child: Column( - children: this.otherForms.isNotEmpty - ? [ - Text( - 'Other Forms', - style: TextStyle(fontWeight: FontWeight.bold), - ), - Row( - children: otherForms.map((form) => _KanaBox(form)).toList(), - ), - ] - : [], - ), + return Column( + children: forms.isNotEmpty + ? [ + const Text( + 'Other Forms', + style: TextStyle(fontWeight: FontWeight.bold), + ), + Row( + children: forms.map((form) => _KanaBox(form)).toList(), + ), + ] + : [], ); } } @@ -32,28 +31,19 @@ class _KanaBox extends StatelessWidget { const _KanaBox(this.word); + bool get hasFurigana => word.word != null; + @override Widget build(BuildContext context) { - final hasFurigana = (word.word != null); final _menuColors = BlocProvider.of(context).state.theme.menuGreyLight; return Container( - child: DefaultTextStyle.merge( - child: Column( - children: [ - // TODO: take a look at this logic - (hasFurigana) ? Text(word.reading ?? '') : Text(''), - (hasFurigana) ? Text(word.word!) : Text(word.reading ?? ''), - ], - ), - style: TextStyle(color: _menuColors.foreground), - ), - margin: EdgeInsets.symmetric( + margin: const EdgeInsets.symmetric( horizontal: 5.0, vertical: 5.0, ), - padding: EdgeInsets.all(5.0), + padding: const EdgeInsets.all(5.0), decoration: BoxDecoration( color: _menuColors.background, boxShadow: [ @@ -61,10 +51,20 @@ class _KanaBox extends StatelessWidget { color: Colors.grey.withOpacity(0.5), spreadRadius: 1, blurRadius: 0.5, - offset: Offset(1, 1), + offset: const Offset(1, 1), ), ], ), + child: DefaultTextStyle.merge( + child: Column( + children: [ + // TODO: take a look at this logic + hasFurigana ? Text(word.reading ?? '') : const Text(''), + hasFurigana ? Text(word.word!) : Text(word.reading ?? ''), + ], + ), + style: TextStyle(color: _menuColors.foreground), + ), ); } } diff --git a/lib/view/components/search/search_results_body/parts/senses.dart b/lib/view/components/search/search_results_body/parts/senses.dart index 510054d..1bd0ccc 100644 --- a/lib/view/components/search/search_results_body/parts/senses.dart +++ b/lib/view/components/search/search_results_body/parts/senses.dart @@ -3,18 +3,20 @@ import 'package:unofficial_jisho_api/parser.dart'; class Senses extends StatelessWidget { final List senses; - - const Senses(this.senses); + + const Senses({ + required this.senses, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { final List senseWidgets = senses.asMap().entries.map((e) => _Sense(e.key, e.value)).toList(); - return Container( - child: Column( + return Column( children: senseWidgets, - )); + ); } } @@ -26,37 +28,35 @@ class _Sense extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - child: Column( - children: [ - Row( + return Column( + children: [ + Row( + children: [ + Text( + '${index + 1}. ', + style: const TextStyle(color: Colors.grey), + ), + Text( + sense.partsOfSpeech.join(', '), + style: const TextStyle(fontWeight: FontWeight.bold), + textAlign: TextAlign.left, + ), + ], + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 20), + margin: const EdgeInsets.fromLTRB(0, 5, 0, 15), + child: Row( children: [ - Text( - (index + 1).toString() + '. ', - style: TextStyle(color: Colors.grey), - ), - Text( - sense.partsOfSpeech.join(', '), - style: TextStyle(fontWeight: FontWeight.bold), - textAlign: TextAlign.left, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + sense.englishDefinitions.map((def) => Text(def)).toList(), ), ], ), - Container( - child: Row( - children:[ - Column( - children: - sense.englishDefinitions.map((def) => Text(def)).toList(), - crossAxisAlignment: CrossAxisAlignment.start, - ), - ] - ), - padding: EdgeInsets.symmetric(horizontal: 20), - margin: EdgeInsets.fromLTRB(0, 5, 0, 15), - ), - ], - ), + ), + ], ); } } diff --git a/lib/view/components/search/search_results_body/parts/wanikani_badge.dart b/lib/view/components/search/search_results_body/parts/wanikani_badge.dart index f724131..3de0ec2 100644 --- a/lib/view/components/search/search_results_body/parts/wanikani_badge.dart +++ b/lib/view/components/search/search_results_body/parts/wanikani_badge.dart @@ -14,13 +14,13 @@ class WKBadge extends StatelessWidget { @override Widget build(BuildContext context) { return Badge( - Text( + child: Text( _extractWkLevel(this.wkLevel), style: TextStyle( color: Colors.white, ), ), - this.wkLevel.isNotEmpty ? Colors.red : Colors.transparent + color: this.wkLevel.isNotEmpty ? Colors.red : Colors.transparent ); } } \ No newline at end of file diff --git a/lib/view/components/search/search_results_body/search_card.dart b/lib/view/components/search/search_results_body/search_card.dart index b53b371..e56b270 100644 --- a/lib/view/components/search/search_results_body/search_card.dart +++ b/lib/view/components/search/search_results_body/search_card.dart @@ -13,10 +13,12 @@ class SearchResultCard extends StatelessWidget { late final JishoJapaneseWord mainWord; late final List otherForms; - SearchResultCard(this.result) { - this.mainWord = result.japanese[0]; - this.otherForms = result.japanese.sublist(1); - } + SearchResultCard({ + required this.result, + Key? key, + }) : mainWord = result.japanese[0], + otherForms = result.japanese.sublist(1), + super(key: key); @override Widget build(BuildContext context) { @@ -24,34 +26,40 @@ class SearchResultCard extends StatelessWidget { return ExpansionTile( collapsedBackgroundColor: backgroundColor, backgroundColor: backgroundColor, - title: - IntrinsicWidth( + title: IntrinsicWidth( child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - JapaneseHeader(mainWord), + JapaneseHeader(word: mainWord), Row( children: [ - WKBadge(result.tags.firstWhere((tag) => tag.contains("wanikani"), orElse: () => '')), - JLPTBadge(result.jlpt.isNotEmpty ? result.jlpt[0] : ''), - CommonBadge(result.isCommon ?? false) + WKBadge( + result.tags.firstWhere( + (tag) => tag.contains('wanikani'), + orElse: () => '', + ), + ), + JLPTBadge( + jlptLevel: result.jlpt.isNotEmpty ? result.jlpt[0] : '', + ), + CommonBadge(isCommon: result.isCommon ?? false) ], ) ], - mainAxisAlignment: MainAxisAlignment.spaceBetween, ), ), children: [ Container( + padding: const EdgeInsets.symmetric(horizontal: 30), child: Column( children: [ - Senses(result.senses), - OtherForms(otherForms), + Senses(senses: result.senses), + OtherForms(forms: otherForms), // Text(result.toJson().toString()), // Text(result.attribution.toJson().toString()), // Text(result.japanese.map((e) => e.toJson().toString()).toList().toString()), ], ), - padding: EdgeInsets.symmetric(horizontal: 30), ) ], ); diff --git a/lib/view/screens/history.dart b/lib/view/screens/history.dart index 0a45b19..faf2901 100644 --- a/lib/view/screens/history.dart +++ b/lib/view/screens/history.dart @@ -1,75 +1,37 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/database/database_bloc.dart'; -import 'package:jisho_study_tool/models/history/search.dart'; -import 'package:jisho_study_tool/view/components/history/kanji_search_item.dart'; -import 'package:jisho_study_tool/view/components/history/phrase_search_item.dart'; -import 'package:jisho_study_tool/view/components/history/date_divider.dart'; -import 'package:jisho_study_tool/objectbox.g.dart'; -import 'package:jisho_study_tool/view/components/opaque_box.dart'; +import '../../bloc/database/database_bloc.dart'; +import '../../models/history/search.dart'; +import '../../objectbox.g.dart'; +import '../components/history/date_divider.dart'; +import '../components/history/kanji_search_item.dart'; +import '../components/history/phrase_search_item.dart'; +import '../components/opaque_box.dart'; class HistoryView extends StatelessWidget { + const HistoryView({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - if (state is DatabaseDisconnected) + if (state is DatabaseDisconnected) { throw DatabaseNotConnectedException(); + } - return StreamBuilder( - stream: ((state as DatabaseConnected).database.box().query() - ..order(Search_.timestamp, flags: Order.descending)) - .watch(triggerImmediately: true) - .map((query) => query.find()), - builder: (BuildContext context, AsyncSnapshot snapshot) { - if (!snapshot.hasData) return Container(); + return StreamBuilder>( + stream: getAsyncStream(state), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return Container(); + } + + final List data = snapshot.data!; return OpaqueBox( child: ListView.separated( - itemCount: snapshot.data.length + 1, - itemBuilder: (context, index) { - if (index == 0) return Container(); - Search search = snapshot.data[index - 1]; - if (search.isKanji()) { - return KanjiSearchItem( - result: search.kanjiQuery.target!, - timestamp: search.timestamp, - ); - } - return PhraseSearchItem( - search: search.wordQuery.target!, - timestamp: search.timestamp, - ); - }, - separatorBuilder: (context, index) { - Function roundToDay = (DateTime date) => - DateTime(date.year, date.month, date.day); - - Search search = snapshot.data[index]; - DateTime searchDate = roundToDay(search.timestamp); - - bool newDate = true; - - EdgeInsets? margin; - if (index != 0) { - Search prevSearch = snapshot.data[index - 1]; - - DateTime prevSearchDate = roundToDay(prevSearch.timestamp); - newDate = prevSearchDate != searchDate; - margin = EdgeInsets.only(bottom: 10); - } - - if (newDate) { - if (searchDate == roundToDay(DateTime.now())) - return DateDivider(text: "Today", margin: margin); - else if (searchDate == - roundToDay( - DateTime.now().subtract(const Duration(days: 1)))) - return DateDivider(text: "Yesterday", margin: margin); - return DateDivider(date: searchDate, margin: margin); - } - - return Divider(); - }, + itemCount: data.length + 1, + itemBuilder: historyEntryWithData(data), + separatorBuilder: historyEntrySeparatorWithData(data), ), ); }, @@ -77,4 +39,68 @@ class HistoryView extends StatelessWidget { }, ); } + + Stream> getAsyncStream(DatabaseState state) => + ((state as DatabaseConnected).database.box().query() + ..order(Search_.timestamp, flags: Order.descending)) + .watch(triggerImmediately: true) + .map((query) => query.find()); + + Widget Function(BuildContext, int) historyEntryWithData(List data) => + (context, index) { + if (index == 0) { + return Container(); + } + + final Search search = data[index - 1]; + + if (search.isKanji()) { + return KanjiSearchItem( + result: search.kanjiQuery.target!, + timestamp: search.timestamp, + ); + } else { + return PhraseSearchItem( + search: search.wordQuery.target!, + timestamp: search.timestamp, + ); + } + }; + + DateTime roundToDay(DateTime date) => + DateTime(date.year, date.month, date.day); + + bool dateChangedFromLastSearch(Search prevSearch, DateTime searchDate) { + final DateTime prevSearchDate = roundToDay(prevSearch.timestamp); + return prevSearchDate != searchDate; + } + + DateTime get today => roundToDay(DateTime.now()); + DateTime get yesterday => + roundToDay(DateTime.now().subtract(const Duration(days: 1))); + + Widget Function(BuildContext, int) historyEntrySeparatorWithData( + List data, + ) => + (context, index) { + final Search search = data[index]; + final DateTime searchDate = roundToDay(search.timestamp); + + EdgeInsets? margin; + if (index != 0) { + margin = const EdgeInsets.only(bottom: 10); + } + + if (index == 0 || + dateChangedFromLastSearch(data[index - 1], searchDate)) { + if (searchDate == today) + return DateDivider(text: 'Today', margin: margin); + else if (searchDate == yesterday) + return DateDivider(text: 'Yesterday', margin: margin); + else + return DateDivider(date: searchDate, margin: margin); + } + + return const Divider(); + }; } diff --git a/lib/view/screens/search/kanji_result_page.dart b/lib/view/screens/search/kanji_result_page.dart index 026a3da..8bef057 100644 --- a/lib/view/screens/search/kanji_result_page.dart +++ b/lib/view/screens/search/kanji_result_page.dart @@ -1,40 +1,40 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/database/database_bloc.dart'; -import 'package:jisho_study_tool/models/history/kanji_query.dart'; -import 'package:jisho_study_tool/models/history/search.dart'; -import 'package:jisho_study_tool/view/components/common/loading.dart'; -import 'package:jisho_study_tool/view/components/kanji/kanji_result_body.dart'; -import 'package:jisho_study_tool/services/jisho_api/kanji_search.dart'; + +import '../../../bloc/database/database_bloc.dart'; +import '../../../models/history/kanji_query.dart'; +import '../../../models/history/search.dart'; +import '../../../services/jisho_api/kanji_search.dart'; +import '../../components/common/loading.dart'; +import '../../components/kanji/kanji_result_body.dart'; class KanjiResultPage extends StatelessWidget { final String kanjiSearchTerm; bool addedToDatabase = false; - KanjiResultPage({required this.kanjiSearchTerm, Key? key}) - : super(key: key); + KanjiResultPage({required this.kanjiSearchTerm, Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), - body: FutureBuilder( - future: fetchKanji(this.kanjiSearchTerm), - builder: (context, snapshot) { + body: FutureBuilder( + future: fetchKanji(kanjiSearchTerm), + builder: ( context, snapshot) { if (!snapshot.hasData) return LoadingScreen(); if (snapshot.hasError) return ErrorWidget(snapshot.error!); - if (!this.addedToDatabase) { + if (!addedToDatabase) { (BlocProvider.of(context).state as DatabaseConnected) .database .box() .put(Search(timestamp: DateTime.now()) ..kanjiQuery.target = KanjiQuery( - kanji: this.kanjiSearchTerm, - )); - this.addedToDatabase = true; + kanji: kanjiSearchTerm, + ),); + addedToDatabase = true; } - return KanjiResultBody(result: (snapshot.data as KanjiResult)); + return KanjiResultBody(result: snapshot.data!); }, ), ); diff --git a/lib/view/screens/search/kanji_view.dart b/lib/view/screens/search/kanji_view.dart index 9859690..04a88d7 100644 --- a/lib/view/screens/search/kanji_view.dart +++ b/lib/view/screens/search/kanji_view.dart @@ -1,11 +1,13 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/components/kanji/kanji_search_body.dart'; +import '../../components/kanji/kanji_search_body.dart'; class KanjiView extends StatelessWidget { + const KanjiView({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return KanjiSearchBody(); } -} \ No newline at end of file +} diff --git a/lib/view/screens/search/search_mechanisms/grid.dart b/lib/view/screens/search/search_mechanisms/grid.dart index 0b04f7b..742e0a0 100644 --- a/lib/view/screens/search/search_mechanisms/grid.dart +++ b/lib/view/screens/search/search_mechanisms/grid.dart @@ -1,23 +1,25 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/components/kanji/kanji_search_body/kanji_grid.dart'; -import 'package:jisho_study_tool/view/components/kanji/kanji_search_body/kanji_search_bar.dart'; + +import '../../../components/kanji/kanji_search_body/kanji_grid.dart'; +import '../../../components/kanji/kanji_search_body/kanji_search_bar.dart'; class SearchGrid extends StatelessWidget { final List suggestions; - const SearchGrid(this.suggestions); + + const SearchGrid({ + required this.suggestions, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { - return - Column( - children: [ - SizedBox(height: 10), - KanjiSearchBar(), - SizedBox(height: 10), - Expanded( - child: KanjiGrid(suggestions) - ) - ], - ); + return Column( + children: [ + const SizedBox(height: 10), + const KanjiSearchBar(), + const SizedBox(height: 10), + Expanded(child: KanjiGrid(suggestions: suggestions)) + ], + ); } -} \ No newline at end of file +} diff --git a/lib/view/screens/search/search_mechanisms/radical_list.dart b/lib/view/screens/search/search_mechanisms/radical_list.dart index 8d93387..a6ed8a2 100644 --- a/lib/view/screens/search/search_mechanisms/radical_list.dart +++ b/lib/view/screens/search/search_mechanisms/radical_list.dart @@ -1 +1 @@ -const List> radicals = [[]]; \ No newline at end of file +const List> radicals = [[]]; diff --git a/lib/view/screens/search/search_results_page.dart b/lib/view/screens/search/search_results_page.dart index aae389d..320ba89 100644 --- a/lib/view/screens/search/search_results_page.dart +++ b/lib/view/screens/search/search_results_page.dart @@ -1,10 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/database/database_bloc.dart'; -import 'package:jisho_study_tool/models/history/search.dart'; -import 'package:jisho_study_tool/models/history/word_query.dart'; -import 'package:jisho_study_tool/view/components/common/loading.dart'; -import 'package:jisho_study_tool/view/components/search/search_result_body.dart'; -import 'package:jisho_study_tool/services/jisho_api/jisho_search.dart'; + +import '../../../bloc/database/database_bloc.dart'; +import '../../../models/history/search.dart'; +import '../../../models/history/word_query.dart'; +import '../../../services/jisho_api/jisho_search.dart'; +import '../../components/common/loading.dart'; +import '../../components/search/search_result_body.dart'; class SearchResultsPage extends StatelessWidget { final String searchTerm; @@ -12,34 +13,35 @@ class SearchResultsPage extends StatelessWidget { bool addedToDatabase = false; SearchResultsPage({required this.searchTerm, Key? key}) - : this.results = fetchJishoResults(searchTerm), + : results = fetchJishoResults(searchTerm), super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), - body: FutureBuilder( + body: FutureBuilder( future: results, builder: (context, snapshot) { if (!snapshot.hasData) return LoadingScreen(); - if (snapshot.hasError || - (snapshot.data as JishoAPIResult).data == null) + if (snapshot.hasError || snapshot.data!.data == null) return ErrorWidget(snapshot.error!); - if (!this.addedToDatabase) { + if (!addedToDatabase) { (BlocProvider.of(context).state as DatabaseConnected) .database .box() - .put(Search(timestamp: DateTime.now()) - ..wordQuery.target = WordQuery( - query: this.searchTerm, - )); - this.addedToDatabase = true; + .put( + Search(timestamp: DateTime.now()) + ..wordQuery.target = WordQuery( + query: searchTerm, + ), + ); + addedToDatabase = true; } return SearchResultsBody( - results: (snapshot.data as JishoAPIResult).data!, + results: snapshot.data!.data!, ); }, ), diff --git a/lib/view/screens/search/search_view.dart b/lib/view/screens/search/search_view.dart index 4c8b613..d68be17 100644 --- a/lib/view/screens/search/search_view.dart +++ b/lib/view/screens/search/search_view.dart @@ -1,12 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/view/components/search/search_bar.dart'; +import '../../components/search/search_bar.dart'; class SearchView extends StatelessWidget { + const SearchView({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: const [ SearchBar(), ], ); diff --git a/lib/view/screens/settings.dart b/lib/view/screens/settings.dart index 40d4709..43fe5cc 100644 --- a/lib/view/screens/settings.dart +++ b/lib/view/screens/settings.dart @@ -1,15 +1,16 @@ import 'package:confirm_dialog/confirm_dialog.dart'; import 'package:flutter/material.dart'; -import 'package:jisho_study_tool/bloc/database/database_bloc.dart'; -import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart'; -import 'package:jisho_study_tool/models/history/search.dart'; -import 'package:jisho_study_tool/models/themes/theme.dart'; -import 'package:jisho_study_tool/objectbox.g.dart'; import 'package:settings_ui/settings_ui.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import '../../bloc/database/database_bloc.dart'; +import '../../bloc/theme/theme_bloc.dart'; +import '../../models/history/search.dart'; +import '../../models/themes/theme.dart'; +import '../../objectbox.g.dart'; + class SettingsView extends StatefulWidget { - SettingsView({Key? key}) : super(key: key); + const SettingsView({Key? key}) : super(key: key); @override _SettingsViewState createState() => _SettingsViewState(); @@ -40,25 +41,27 @@ class _SettingsViewState extends State { } /// Update stored preferences with values from setting page state - void _updatePrefs() async { - await prefs.setBool('darkThemeEnabled', darkThemeEnabled); - await prefs.setBool('autoThemeEnabled', autoThemeEnabled); + void _updatePrefs() { + prefs.setBool('darkThemeEnabled', darkThemeEnabled); + prefs.setBool('autoThemeEnabled', autoThemeEnabled); } + @override Widget build(BuildContext context) { final TextStyle _titleTextStyle = TextStyle( - color: BlocProvider.of(context).state is DarkThemeState - ? AppTheme.jishoGreen.background - : null); + color: BlocProvider.of(context).state is DarkThemeState + ? AppTheme.jishoGreen.background + : null, + ); return SettingsList( backgroundColor: Colors.transparent, - contentPadding: EdgeInsets.symmetric(vertical: 10), - sections: [ + contentPadding: const EdgeInsets.symmetric(vertical: 10), + sections: [ SettingsSection( title: 'Theme', titleTextStyle: _titleTextStyle, - tiles: [ + tiles: [ SettingsTile.switchTile( title: 'Automatically determine theme', onToggle: (b) { @@ -74,7 +77,8 @@ class _SettingsViewState extends State { SettingsTile.switchTile( title: 'Dark Theme', onToggle: (b) { - BlocProvider.of(context).add(SetTheme(themeIsDark: b)); + BlocProvider.of(context) + .add(SetTheme(themeIsDark: b)); setState(() { darkThemeEnabled = b; }); @@ -89,7 +93,7 @@ class _SettingsViewState extends State { SettingsSection( title: 'Cache', titleTextStyle: _titleTextStyle, - tiles: [ + tiles: [ SettingsTile.switchTile( title: 'Cache grade 1-7 kanji', switchValue: false, @@ -123,13 +127,13 @@ class _SettingsViewState extends State { SettingsSection( title: 'Data', titleTextStyle: _titleTextStyle, - tiles: [ - SettingsTile( + tiles: [ + const SettingsTile( leading: Icon(Icons.file_download), title: 'Export Data', enabled: false, ), - SettingsTile( + const SettingsTile( leading: Icon(Icons.delete), title: 'Clear History', onPressed: _clearHistory, @@ -137,10 +141,10 @@ class _SettingsViewState extends State { enabled: false, ), SettingsTile( - leading: Icon(Icons.delete), + leading: const Icon(Icons.delete), title: 'Clear Favourites', onPressed: (c) {}, - titleTextStyle: TextStyle(color: Colors.red), + titleTextStyle: const TextStyle(color: Colors.red), enabled: false, ) ], @@ -150,12 +154,14 @@ class _SettingsViewState extends State { } } -void _clearHistory(context) async { - if (await confirm(context)) { - Store db = - (BlocProvider.of(context).state as DatabaseConnected) - .database; - // db.box().query().build().find() - db.box().removeAll(); - } +void _clearHistory(context) { + confirm(context).then((userIsSure) { + if (userIsSure) { + final Store db = + (BlocProvider.of(context).state as DatabaseConnected) + .database; + // db.box().query().build().find() + db.box().removeAll(); + } + }); } diff --git a/pubspec.lock b/pubspec.lock index fd22efb..0907336 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -119,7 +119,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: diff --git a/test/widget_test.dart b/test/widget_test.dart deleted file mode 100644 index e8c17e4..0000000 --- a/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:jisho_study_tool/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} From a0c608ccca87ada8718879a7c255ce7fffb983c4 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 1 Dec 2021 23:10:07 +0100 Subject: [PATCH 3/8] Add storage entities --- lib/models/storage/common.dart | 13 ++ lib/models/storage/example.dart | 36 ++++++ lib/models/storage/kanji_result.dart | 86 ++++++++++++ lib/models/storage/scrape_result.dart | 101 +++++++++++++++ lib/models/storage/search_result.dart | 180 +++++++++++++++++--------- 5 files changed, 353 insertions(+), 63 deletions(-) create mode 100644 lib/models/storage/common.dart create mode 100644 lib/models/storage/example.dart create mode 100644 lib/models/storage/kanji_result.dart create mode 100644 lib/models/storage/scrape_result.dart diff --git a/lib/models/storage/common.dart b/lib/models/storage/common.dart new file mode 100644 index 0000000..20d033a --- /dev/null +++ b/lib/models/storage/common.dart @@ -0,0 +1,13 @@ +import 'package:objectbox/objectbox.dart'; +import 'package:unofficial_jisho_api/api.dart' as jisho; + +@Entity() +class ExampleSentencePiece { + int id = 0; + String? lifted; + String unlifted; + + ExampleSentencePiece.fromJishoObject(jisho.ExampleSentencePiece object) : + lifted = object.lifted, + unlifted = object.unlifted; +} diff --git a/lib/models/storage/example.dart b/lib/models/storage/example.dart new file mode 100644 index 0000000..9d0e489 --- /dev/null +++ b/lib/models/storage/example.dart @@ -0,0 +1,36 @@ +import 'package:objectbox/objectbox.dart'; +import 'package:unofficial_jisho_api/api.dart' as jisho; + +import 'common.dart'; + +@Entity() +class ExampleResultData { + String kanji; + String kana; + String english; + List pieces; + + ExampleResultData.fromJishoObject(jisho.ExampleResultData object) + : kanji = object.kanji, + kana = object.kana, + english = object.english, + pieces = object.pieces + .map((p) => ExampleSentencePiece.fromJishoObject(p)) + .toList(); +} + +@Entity() +class ExampleResults { + String query; + bool found; + String uri; + List results; + + ExampleResults.fromJishoObject(jisho.ExampleResults object) + : query = object.query, + found = object.found, + uri = object.uri, + results = object.results + .map((r) => ExampleResultData.fromJishoObject(r)) + .toList(); +} diff --git a/lib/models/storage/kanji_result.dart b/lib/models/storage/kanji_result.dart new file mode 100644 index 0000000..7a48aa8 --- /dev/null +++ b/lib/models/storage/kanji_result.dart @@ -0,0 +1,86 @@ +import 'package:objectbox/objectbox.dart'; +import 'package:unofficial_jisho_api/api.dart' as jisho; + +@Entity() +class YomiExample { + int id = 0; + String example; + String reading; + String meaning; + + YomiExample.fromJishoObject(jisho.YomiExample object) + : example = object.example, + reading = object.reading, + meaning = object.meaning; +} + +@Entity() +class Radical { + int id = 0; + String symbol; + List forms; + String meaning; + + Radical.fromJishoObject(jisho.Radical object) + : symbol = object.symbol, + forms = object.forms, + meaning = object.meaning; +} + +@Entity() +class KanjiResult { + int id = 0; + String query; + bool found; + KanjiResultData? data; + + KanjiResult.fromJishoObject(jisho.KanjiResult object) + : query = object.query, + found = object.found, + data = (object.data == null) + ? null + : KanjiResultData.fromJishoObject(object.data!); +} + +@Entity() +class KanjiResultData { + int id = 0; + String? taughtIn; + String? jlptLevel; + int? newspaperFrequencyRank; + int strokeCount; + String meaning; + List kunyomi; + List onyomi; + List kunyomiExamples; + List onyomiExamples; + Radical? radical; + List parts; + String strokeOrderDiagramUri; + String strokeOrderSvgUri; + String strokeOrderGifUri; + String uri; + + KanjiResultData.fromJishoObject(jisho.KanjiResultData object) + : taughtIn = object.taughtIn, + jlptLevel = object.jlptLevel, + newspaperFrequencyRank = object.newspaperFrequencyRank, + strokeCount = object.strokeCount, + meaning = object.meaning, + kunyomi = object.kunyomi, + onyomi = object.onyomi, + kunyomiExamples = object.kunyomiExamples + .map((k) => YomiExample.fromJishoObject(k)) + .toList(), + onyomiExamples = object.onyomiExamples + .map((o) => YomiExample.fromJishoObject(o)) + .toList(), + radical = (object.radical == null) + ? null + : Radical.fromJishoObject(object.radical!), + parts = object.parts, + strokeOrderDiagramUri = object.strokeOrderDiagramUri, + strokeOrderSvgUri = object.strokeOrderSvgUri, + strokeOrderGifUri = object.strokeOrderGifUri, + uri = object.uri; +} diff --git a/lib/models/storage/scrape_result.dart b/lib/models/storage/scrape_result.dart new file mode 100644 index 0000000..23f6c73 --- /dev/null +++ b/lib/models/storage/scrape_result.dart @@ -0,0 +1,101 @@ +import 'package:objectbox/objectbox.dart'; +import 'package:unofficial_jisho_api/api.dart' as jisho; + +import 'common.dart'; + +@Entity() +class PhraseScrapeSentence { + int id = 0; + String english; + String japanese; + List pieces; + + PhraseScrapeSentence.fromJishoObject(jisho.PhraseScrapeSentence object) + : english = object.english, + japanese = object.japanese, + pieces = object.pieces + .map((p) => ExampleSentencePiece.fromJishoObject(p)) + .toList(); +} + +@Entity() +class PhraseScrapeMeaning { + int id = 0; + List seeAlsoTerms; + List sentences; + String definition; + List supplemental; + String? definitionAbstract; + List tags; + + PhraseScrapeMeaning.fromJishoObject(jisho.PhraseScrapeMeaning object) + : seeAlsoTerms = object.seeAlsoTerms, + sentences = object.sentences + .map((s) => PhraseScrapeSentence.fromJishoObject(s)) + .toList(), + definition = object.definition, + supplemental = object.supplemental, + definitionAbstract = object.definitionAbstract, + tags = object.tags; +} + +@Entity() +class KanjiKanaPair { + int id = 0; + String kanji; + String? kana; + + KanjiKanaPair.fromJishoObject(jisho.KanjiKanaPair object) + : kanji = object.kanji, + kana = object.kana; +} + +@Entity() +class PhrasePageScrapeResult { + int id = 0; + bool found; + String query; + PhrasePageScrapeResultData? data; + + PhrasePageScrapeResult.fromJishoObject(jisho.PhrasePageScrapeResult object) + : found = object.found, + query = object.query, + data = (object.data == null) + ? null + : PhrasePageScrapeResultData.fromJishoObject(object.data!); +} + +@Entity() +class AudioFile { + int id = 0; + String uri; + String mimetype; + + AudioFile.fromJishoObject(jisho.AudioFile object) + : uri = object.uri, + mimetype = object.mimetype; +} + +@Entity() +class PhrasePageScrapeResultData { + int id = 0; + String uri; + List tags; + List meanings; + List otherForms; + List audio; + List notes; + + PhrasePageScrapeResultData.fromJishoObject( + jisho.PhrasePageScrapeResultData object, + ) : uri = object.uri, + tags = object.tags, + meanings = object.meanings + .map((m) => PhraseScrapeMeaning.fromJishoObject(m)) + .toList(), + otherForms = object.otherForms + .map((f) => KanjiKanaPair.fromJishoObject(f)) + .toList(), + audio = object.audio.map((a) => AudioFile.fromJishoObject(a)).toList(), + notes = object.notes; +} diff --git a/lib/models/storage/search_result.dart b/lib/models/storage/search_result.dart index 7d1e5d3..486fba1 100644 --- a/lib/models/storage/search_result.dart +++ b/lib/models/storage/search_result.dart @@ -1,72 +1,126 @@ -// import 'package:objectbox/objectbox.dart'; -// import 'package:unofficial_jisho_api/api.dart' as jisho; +import 'package:objectbox/objectbox.dart'; +import 'package:unofficial_jisho_api/api.dart' as jisho; -// @Entity() -// class SearchResult { -// int id = 0; -// final meta = ToOne(); -// final data = ToMany(); +@Entity() +class SearchResult { + int id = 0; + final JishoResultMeta meta; + final ToMany data = ToMany(); -// // SearchResult(JishoAPIResult result) { -// // this.data = result.data; -// // this.meta = result.meta; -// // } + SearchResult.fromJishoObject(final jisho.JishoAPIResult object) + : meta = JishoResultMeta.fromJishoObject(object.meta) { + data.addAll( + object.data + ?.map((r) => JishoResult.fromJishoObject(r)) ?? + [], + ); + } +} -// // JishoAPIResult toJishoAPIResult() { -// // return JishoAPIResult(meta: this.meta, data: this.data); -// // } -// } +@Entity() +class JishoResultMeta { + int id = 0; + int status; -// @Entity() -// class JishoResultMeta { -// int id = 0; -// int status; -// } + JishoResultMeta.fromJishoObject(final jisho.JishoResultMeta object) + : status = object.status; +} -// @Entity() -// class JishoResult { -// int id = 0; -// final attribution = ToOne(); -// bool is_common; -// final japanese = ToMany(); -// List jlpt; -// final senses = ToMany(); -// String slug; -// List tags; -// } +@Entity() +class JishoResult { + int id = 0; + JishoAttribution attribution; + bool? is_common; + List japanese; + List jlpt; + List senses; + String slug; + List tags; -// @Entity() -// class JishoAttribution { -// int id = 0; -// String dbpedia; -// String jmdict; -// bool jmnedict; -// } + JishoResult.fromJishoObject(final jisho.JishoResult object) + : attribution = JishoAttribution.fromJishoObject(object.attribution), + is_common = object.isCommon, + japanese = object.japanese + .map((j) => JishoJapaneseWord.fromJishoObject(j)) + .toList(), + jlpt = object.jlpt, + senses = object.senses + .map((s) => JishoWordSense.fromJishoObject(s)) + .toList(), + slug = object.slug, + tags = object.tags; +} -// @Entity() -// class JishoJapaneseWord { -// int id = 0; -// String reading; -// String word; -// } +@Entity() +class JishoAttribution { + int id = 0; + String? dbpedia; + bool jmdict; + bool jmnedict; -// @Entity() -// class JishoWordSense { -// int id = 0; -// List antonyms; -// List english_definitions; -// List info; -// final links = ToMany(); -// List parts_of_speech; -// List restrictions; -// List see_also; -// List source; -// List tags; -// } + JishoAttribution.fromJishoObject(final jisho.JishoAttribution object) + : dbpedia = object.dbpedia, + jmdict = object.jmdict, + jmnedict = object.jmnedict; +} -// @Entity() -// class JishoSenseLink { -// int id = 0; -// String text; -// String url; -// } +@Entity() +class JishoJapaneseWord { + int id = 0; + String? reading; + String? word; + + JishoJapaneseWord.fromJishoObject(final jisho.JishoJapaneseWord object) + : reading = object.reading, + word = object.word; +} + +@Entity() +class JishoWordSense { + int id = 0; + List antonyms; + List english_definitions; + List info; + List links; + List parts_of_speech; + List restrictions; + List see_also; + List source; + List tags; + + JishoWordSense.fromJishoObject(final jisho.JishoWordSense object) + : antonyms = object.antonyms, + english_definitions = object.englishDefinitions, + info = object.info, + links = + object.links.map((l) => JishoSenseLink.fromJishoObject(l)).toList(), + parts_of_speech = object.partsOfSpeech, + restrictions = object.restrictions, + see_also = object.seeAlso, + source = object.source + .map((s) => JishoWordSource.fromJishoObject(s)) + .toList(), + tags = object.tags; +} + +@Entity() +class JishoWordSource { + int id = 0; + String language; + String? word; + + JishoWordSource.fromJishoObject(final jisho.JishoWordSource object) + : language = object.language, + word = object.word; +} + +@Entity() +class JishoSenseLink { + int id = 0; + String text; + String url; + + JishoSenseLink.fromJishoObject(final jisho.JishoSenseLink object) + : text = object.text, + url = object.url; +} From fe5c5a4ccece38e610f9f2f5b177aea170a97887 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Sat, 4 Dec 2021 05:13:13 +0100 Subject: [PATCH 4/8] Replace objectbox with sembast --- .gitignore | 2 - analysis_options.yaml | 1 - lib/bloc/database/database_bloc.dart | 27 -- lib/bloc/database/database_event.dart | 14 - .../database_not_connected_exception.dart | 1 - lib/bloc/database/database_state.dart | 14 - lib/main.dart | 166 +++++----- lib/models/history/kanji_query.dart | 13 +- lib/models/history/search.dart | 53 ++-- lib/models/history/word_query.dart | 16 +- lib/models/history/word_result.dart | 16 +- lib/models/storage/common.dart | 31 +- lib/models/storage/example.dart | 84 +++-- lib/models/storage/kanji_result.dart | 199 +++++++----- lib/models/storage/scrape_result.dart | 230 ++++++++------ lib/models/storage/search_result.dart | 289 +++++++++++------- lib/objectbox-model.json | 141 --------- lib/view/screens/history.dart | 91 +++--- .../screens/search/kanji_result_page.dart | 21 +- .../screens/search/search_results_page.dart | 21 +- lib/view/screens/settings.dart | 36 +-- pubspec.lock | 61 ++-- pubspec.yaml | 9 +- 23 files changed, 754 insertions(+), 782 deletions(-) delete mode 100644 lib/bloc/database/database_bloc.dart delete mode 100644 lib/bloc/database/database_event.dart delete mode 100644 lib/bloc/database/database_not_connected_exception.dart delete mode 100644 lib/bloc/database/database_state.dart delete mode 100644 lib/objectbox-model.json diff --git a/.gitignore b/.gitignore index 0bd996a..d16b8eb 100644 --- a/.gitignore +++ b/.gitignore @@ -30,8 +30,6 @@ .pub/ /build/ -objectbox.g.dart - # Web related lib/generated_plugin_registrant.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index 9974d7f..a74d9d6 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,6 +1,5 @@ analyzer: exclude: - - "lib/objectbox.g.dart" linter: rules: diff --git a/lib/bloc/database/database_bloc.dart b/lib/bloc/database/database_bloc.dart deleted file mode 100644 index d9b0403..0000000 --- a/lib/bloc/database/database_bloc.dart +++ /dev/null @@ -1,27 +0,0 @@ - -import 'package:flutter_bloc/flutter_bloc.dart'; - -import './database_event.dart'; -import './database_state.dart'; - -export 'package:flutter_bloc/flutter_bloc.dart'; - -export './database_event.dart'; -export './database_not_connected_exception.dart'; -export './database_state.dart'; - -class DatabaseBloc extends Bloc { - - DatabaseBloc() : super(const DatabaseDisconnected()); - - @override - Stream mapEventToState(DatabaseEvent event) - async* { - if (event is ConnectedToDatabase) { - yield DatabaseConnected(event.database); - } else { - yield const DatabaseDisconnected(); - } - } - -} diff --git a/lib/bloc/database/database_event.dart b/lib/bloc/database/database_event.dart deleted file mode 100644 index 799860e..0000000 --- a/lib/bloc/database/database_event.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:objectbox/objectbox.dart'; - -abstract class DatabaseEvent { - const DatabaseEvent(); -} - -class ConnectedToDatabase extends DatabaseEvent { - final Store database; - const ConnectedToDatabase(this.database); -} - -class DisconnectedFromDatabase extends DatabaseEvent { - const DisconnectedFromDatabase(); -} diff --git a/lib/bloc/database/database_not_connected_exception.dart b/lib/bloc/database/database_not_connected_exception.dart deleted file mode 100644 index e873be7..0000000 --- a/lib/bloc/database/database_not_connected_exception.dart +++ /dev/null @@ -1 +0,0 @@ -class DatabaseNotConnectedException implements Exception {} diff --git a/lib/bloc/database/database_state.dart b/lib/bloc/database/database_state.dart deleted file mode 100644 index 68d33c4..0000000 --- a/lib/bloc/database/database_state.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:objectbox/objectbox.dart'; - -abstract class DatabaseState { - const DatabaseState(); -} - -class DatabaseConnected extends DatabaseState { - final Store database; - const DatabaseConnected(this.database); -} - -class DatabaseDisconnected extends DatabaseState { - const DatabaseDisconnected(); -} diff --git a/lib/main.dart b/lib/main.dart index e76989a..0044107 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,15 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; import 'package:mdi/mdi.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:sembast/sembast.dart'; +import 'package:sembast/sembast_io.dart'; -import 'bloc/database/database_bloc.dart'; import 'bloc/theme/theme_bloc.dart'; import 'models/themes/theme.dart'; -import 'objectbox.g.dart'; import 'router.dart'; import 'view/components/common/splash.dart'; import 'view/screens/history.dart'; @@ -14,56 +17,35 @@ import 'view/screens/search/kanji_view.dart'; import 'view/screens/search/search_view.dart'; import 'view/screens/settings.dart'; -void main() => runApp(const MyApp()); +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + final Directory appDocDir = await getApplicationDocumentsDirectory(); -DatabaseBloc _databaseBloc = DatabaseBloc(); + if (!appDocDir.existsSync()) + appDocDir.createSync(recursive: true); -class MyApp extends StatefulWidget { - const MyApp({Key? key}) : super(key: key); + final Database db = await databaseFactoryIo.openDatabase(join(appDocDir.path, 'sembast.db')); - @override - _MyAppState createState() => _MyAppState(); + GetIt.instance.registerSingleton(db); + + runApp(const MyApp()); } -class _MyAppState extends State { - late final Store _store; - bool dbConnected = false; +class MyApp extends StatelessWidget { - @override - void initState() { - super.initState(); - - getApplicationDocumentsDirectory().then((dir) { - _store = Store( - getObjectBoxModel(), - directory: join(dir.path, 'objectbox'), - ); - - _databaseBloc.add(ConnectedToDatabase(_store)); - setState(() { - dbConnected = true; - }); - }); - } - - @override - void dispose() { - _store.close(); - _databaseBloc.add(const DisconnectedFromDatabase()); - super.dispose(); - } + const MyApp({ + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { return MultiBlocProvider( providers: [ - BlocProvider(create: (context) => _databaseBloc), BlocProvider(create: (context) => ThemeBloc()), ], child: BlocBuilder( builder: (context, themeState) { - if (!(dbConnected && themeState.prefsAreLoaded)) - return const SplashScreen(); + if (!themeState.prefsAreLoaded) return const SplashScreen(); return MaterialApp( title: 'Jisho Study Tool', @@ -77,6 +59,18 @@ class _MyAppState extends State { } } +class _Page { + final Widget content; + final Widget titleBar; + final BottomNavigationBarItem item; + + const _Page({ + required this.content, + required this.titleBar, + required this.item, + }); +} + class Home extends StatefulWidget { const Home({Key? key}) : super(key: key); @@ -126,59 +120,47 @@ class _HomeState extends State { }, ); } + + List<_Page> get pages => [ + const _Page( + content: SearchView(), + titleBar: Text('Search'), + item: BottomNavigationBarItem( + label: 'Search', + icon: Icon(Icons.search), + ), + ), + const _Page( + content: KanjiView(), + titleBar: Text('Kanji'), + item: BottomNavigationBarItem( + label: 'Kanji', + icon: Icon(Mdi.ideogramCjk, size: 30), + ), + ), + const _Page( + content: HistoryView(), + titleBar: Text('History'), + item: BottomNavigationBarItem( + label: 'History', + icon: Icon(Icons.history), + ), + ), + _Page( + content: Container(), + titleBar: const Text('Saved'), + item: const BottomNavigationBarItem( + label: 'Saved', + icon: Icon(Icons.bookmark), + ), + ), + const _Page( + content: SettingsView(), + titleBar: Text('Settings'), + item: BottomNavigationBarItem( + label: 'Settings', + icon: Icon(Icons.settings), + ), + ), + ]; } - -class _Page { - final Widget content; - final Widget titleBar; - final BottomNavigationBarItem item; - - const _Page({ - required this.content, - required this.titleBar, - required this.item, - }); -} - -final List<_Page> pages = [ - const _Page( - content: SearchView(), - titleBar: Text('Search'), - item: BottomNavigationBarItem( - label: 'Search', - icon: Icon(Icons.search), - ), - ), - const _Page( - content: KanjiView(), - titleBar: Text('Kanji'), - item: BottomNavigationBarItem( - label: 'Kanji', - icon: Icon(Mdi.ideogramCjk, size: 30), - ), - ), - const _Page( - content: HistoryView(), - titleBar: Text('History'), - item: BottomNavigationBarItem( - label: 'History', - icon: Icon(Icons.history), - ), - ), - _Page( - content: Container(), - titleBar: const Text('Saved'), - item: const BottomNavigationBarItem( - label: 'Saved', - icon: Icon(Icons.bookmark), - ), - ), - const _Page( - content: SettingsView(), - titleBar: Text('Settings'), - item: BottomNavigationBarItem( - label: 'Settings', - icon: Icon(Icons.settings), - ), - ), -]; diff --git a/lib/models/history/kanji_query.dart b/lib/models/history/kanji_query.dart index 65085f1..56d2c00 100644 --- a/lib/models/history/kanji_query.dart +++ b/lib/models/history/kanji_query.dart @@ -1,13 +1,12 @@ -import 'package:objectbox/objectbox.dart'; - -@Entity() class KanjiQuery { - int id; - - String kanji; + final String kanji; KanjiQuery({ - this.id = 0, required this.kanji, }); + + Map toJson() => {'kanji': kanji}; + + factory KanjiQuery.fromJson(Map json) => + KanjiQuery(kanji: json['kanji'] as String); } diff --git a/lib/models/history/search.dart b/lib/models/history/search.dart index 9f37c48..7e3c7e6 100644 --- a/lib/models/history/search.dart +++ b/lib/models/history/search.dart @@ -1,30 +1,43 @@ -import 'package:objectbox/objectbox.dart'; +import 'package:sembast/sembast.dart'; +import 'package:sembast/timestamp.dart'; import './kanji_query.dart'; import './word_query.dart'; -@Entity() class Search { - int id; + final DateTime timestamp; + final WordQuery? wordQuery; + final KanjiQuery? kanjiQuery; - @Property(type: PropertyType.date) - late final DateTime timestamp; - - final wordQuery = ToOne(); - - final kanjiQuery = ToOne(); - - Search({ - this.id = 0, + Search.fromKanjiQuery({ required this.timestamp, - }); + required KanjiQuery this.kanjiQuery, + }) : wordQuery = null; - bool isKanji() { - // // TODO: better error message - if (wordQuery.target == null && kanjiQuery.target == null) - throw Exception(); - - return wordQuery.target == null; - } + Search.fromWordQuery({ + required this.timestamp, + required WordQuery this.wordQuery, + }) : kanjiQuery = null; + bool get isKanji => wordQuery == null; + + Map toJson() => { + 'timestamp': timestamp.millisecondsSinceEpoch, + 'wordQuery': wordQuery?.toJson(), + 'kanjiQuery': kanjiQuery?.toJson(), + }; + + factory Search.fromJson(Map json) => + json['wordQuery'] != null + ? Search.fromWordQuery( + timestamp: + DateTime.fromMillisecondsSinceEpoch(json['timestamp'] as int), + wordQuery: WordQuery.fromJson(json['wordQuery']), + ) + : Search.fromKanjiQuery( + timestamp: DateTime.fromMillisecondsSinceEpoch(json['timestamp'] as int), + kanjiQuery: KanjiQuery.fromJson(json['kanjiQuery']), + ); + + static StoreRef get store => intMapStoreFactory.store('search'); } diff --git a/lib/models/history/word_query.dart b/lib/models/history/word_query.dart index e7d42f2..e0904e8 100644 --- a/lib/models/history/word_query.dart +++ b/lib/models/history/word_query.dart @@ -1,19 +1,17 @@ -import 'package:objectbox/objectbox.dart'; - import './word_result.dart'; -@Entity() class WordQuery { - int id; - - String query; + final String query; // TODO: Link query with results that the user clicks onto. - @Backlink() - final chosenResults = ToMany(); + // final List chosenResults; WordQuery({ - this.id = 0, required this.query, }); + + Map toJson() => {'query': query}; + + factory WordQuery.fromJson(Map json) => + WordQuery(query: json['query'] as String); } diff --git a/lib/models/history/word_result.dart b/lib/models/history/word_result.dart index f959f33..a7c23b2 100644 --- a/lib/models/history/word_result.dart +++ b/lib/models/history/word_result.dart @@ -1,21 +1,13 @@ -import 'package:objectbox/objectbox.dart'; - import 'word_query.dart'; -@Entity() class WordResult { - int id; - - @Property(type: PropertyType.date) - DateTime timestamp; - - String word; - - final searchString = ToOne(); + final DateTime timestamp; + final String word; + final WordQuery searchString; WordResult({ - this.id = 0, required this.timestamp, required this.word, + required this.searchString, }); } diff --git a/lib/models/storage/common.dart b/lib/models/storage/common.dart index 20d033a..6aeeb7c 100644 --- a/lib/models/storage/common.dart +++ b/lib/models/storage/common.dart @@ -1,13 +1,22 @@ -import 'package:objectbox/objectbox.dart'; -import 'package:unofficial_jisho_api/api.dart' as jisho; +// import 'package:objectbox/objectbox.dart'; +// import 'package:unofficial_jisho_api/api.dart' as jisho; -@Entity() -class ExampleSentencePiece { - int id = 0; - String? lifted; - String unlifted; +// TODO: Rewrite for sembast - ExampleSentencePiece.fromJishoObject(jisho.ExampleSentencePiece object) : - lifted = object.lifted, - unlifted = object.unlifted; -} +// @Entity() +// class ExampleSentencePiece { +// int id; +// String? lifted; +// String unlifted; + +// ExampleSentencePiece({ +// this.id = 0, +// required this.lifted, +// required this.unlifted, +// }); + +// ExampleSentencePiece.fromJishoObject(jisho.ExampleSentencePiece object) +// : id = 0, +// lifted = object.lifted, +// unlifted = object.unlifted; +// } diff --git a/lib/models/storage/example.dart b/lib/models/storage/example.dart index 9d0e489..58e7d2c 100644 --- a/lib/models/storage/example.dart +++ b/lib/models/storage/example.dart @@ -1,36 +1,58 @@ -import 'package:objectbox/objectbox.dart'; -import 'package:unofficial_jisho_api/api.dart' as jisho; +// import 'package:objectbox/objectbox.dart'; +// import 'package:unofficial_jisho_api/api.dart' as jisho; -import 'common.dart'; +// import 'common.dart'; -@Entity() -class ExampleResultData { - String kanji; - String kana; - String english; - List pieces; +// TODO: Rewrite for sembast - ExampleResultData.fromJishoObject(jisho.ExampleResultData object) - : kanji = object.kanji, - kana = object.kana, - english = object.english, - pieces = object.pieces - .map((p) => ExampleSentencePiece.fromJishoObject(p)) - .toList(); -} +// @Entity() +// class ExampleResultData { +// int id; +// String kanji; +// String kana; +// String english; +// List pieces; -@Entity() -class ExampleResults { - String query; - bool found; - String uri; - List results; +// ExampleResultData({ +// this.id = 0, +// required this.kanji, +// required this.kana, +// required this.english, +// required this.pieces, +// }); - ExampleResults.fromJishoObject(jisho.ExampleResults object) - : query = object.query, - found = object.found, - uri = object.uri, - results = object.results - .map((r) => ExampleResultData.fromJishoObject(r)) - .toList(); -} +// ExampleResultData.fromJishoObject(jisho.ExampleResultData object) +// : id = 0, +// kanji = object.kanji, +// kana = object.kana, +// english = object.english, +// pieces = object.pieces +// .map((p) => ExampleSentencePiece.fromJishoObject(p)) +// .toList(); +// } + +// @Entity() +// class ExampleResults { +// int id; +// String query; +// bool found; +// String uri; +// List results; + +// ExampleResults({ +// this.id = 0, +// required this.query, +// required this.found, +// required this.uri, +// required this.results, +// }); + +// ExampleResults.fromJishoObject(jisho.ExampleResults object) +// : id = 0, +// query = object.query, +// found = object.found, +// uri = object.uri, +// results = object.results +// .map((r) => ExampleResultData.fromJishoObject(r)) +// .toList(); +// } diff --git a/lib/models/storage/kanji_result.dart b/lib/models/storage/kanji_result.dart index 7a48aa8..28f324b 100644 --- a/lib/models/storage/kanji_result.dart +++ b/lib/models/storage/kanji_result.dart @@ -1,86 +1,129 @@ -import 'package:objectbox/objectbox.dart'; -import 'package:unofficial_jisho_api/api.dart' as jisho; +// import 'package:objectbox/objectbox.dart'; +// import 'package:unofficial_jisho_api/api.dart' as jisho; -@Entity() -class YomiExample { - int id = 0; - String example; - String reading; - String meaning; +// TODO: Rewrite for sembast - YomiExample.fromJishoObject(jisho.YomiExample object) - : example = object.example, - reading = object.reading, - meaning = object.meaning; -} +// @Entity() +// class YomiExample { +// int id; +// String example; +// String reading; +// String meaning; -@Entity() -class Radical { - int id = 0; - String symbol; - List forms; - String meaning; +// YomiExample({ +// this.id = 0, +// required this.example, +// required this.reading, +// required this.meaning, +// }); - Radical.fromJishoObject(jisho.Radical object) - : symbol = object.symbol, - forms = object.forms, - meaning = object.meaning; -} +// YomiExample.fromJishoObject(jisho.YomiExample object) +// : id = 0, +// example = object.example, +// reading = object.reading, +// meaning = object.meaning; +// } -@Entity() -class KanjiResult { - int id = 0; - String query; - bool found; - KanjiResultData? data; +// @Entity() +// class Radical { +// int id = 0; +// String symbol; +// List forms; +// String meaning; - KanjiResult.fromJishoObject(jisho.KanjiResult object) - : query = object.query, - found = object.found, - data = (object.data == null) - ? null - : KanjiResultData.fromJishoObject(object.data!); -} +// Radical({ +// this.id = 0, +// required this.symbol, +// required this.forms, +// required this.meaning, +// }); -@Entity() -class KanjiResultData { - int id = 0; - String? taughtIn; - String? jlptLevel; - int? newspaperFrequencyRank; - int strokeCount; - String meaning; - List kunyomi; - List onyomi; - List kunyomiExamples; - List onyomiExamples; - Radical? radical; - List parts; - String strokeOrderDiagramUri; - String strokeOrderSvgUri; - String strokeOrderGifUri; - String uri; +// Radical.fromJishoObject(jisho.Radical object) +// : symbol = object.symbol, +// forms = object.forms, +// meaning = object.meaning; +// } - KanjiResultData.fromJishoObject(jisho.KanjiResultData object) - : taughtIn = object.taughtIn, - jlptLevel = object.jlptLevel, - newspaperFrequencyRank = object.newspaperFrequencyRank, - strokeCount = object.strokeCount, - meaning = object.meaning, - kunyomi = object.kunyomi, - onyomi = object.onyomi, - kunyomiExamples = object.kunyomiExamples - .map((k) => YomiExample.fromJishoObject(k)) - .toList(), - onyomiExamples = object.onyomiExamples - .map((o) => YomiExample.fromJishoObject(o)) - .toList(), - radical = (object.radical == null) - ? null - : Radical.fromJishoObject(object.radical!), - parts = object.parts, - strokeOrderDiagramUri = object.strokeOrderDiagramUri, - strokeOrderSvgUri = object.strokeOrderSvgUri, - strokeOrderGifUri = object.strokeOrderGifUri, - uri = object.uri; -} +// @Entity() +// class KanjiResult { +// int id = 0; +// String query; +// bool found; +// KanjiResultData? data; + +// KanjiResult({ +// this.id = 0, +// required this.query, +// required this.found, +// required this.data, +// }); + +// KanjiResult.fromJishoObject(jisho.KanjiResult object) +// : query = object.query, +// found = object.found, +// data = (object.data == null) +// ? null +// : KanjiResultData.fromJishoObject(object.data!); +// } + +// @Entity() +// class KanjiResultData { +// int id = 0; +// String? taughtIn; +// String? jlptLevel; +// int? newspaperFrequencyRank; +// int strokeCount; +// String meaning; +// List kunyomi; +// List onyomi; +// List kunyomiExamples; +// List onyomiExamples; +// Radical? radical; +// List parts; +// String strokeOrderDiagramUri; +// String strokeOrderSvgUri; +// String strokeOrderGifUri; +// String uri; + +// KanjiResultData({ +// this.id = 0, +// required this.taughtIn, +// required this.jlptLevel, +// required this.newspaperFrequencyRank, +// required this.strokeCount, +// required this.meaning, +// required this.kunyomi, +// required this.onyomi, +// required this.kunyomiExamples, +// required this.onyomiExamples, +// required this.radical, +// required this.parts, +// required this.strokeOrderDiagramUri, +// required this.strokeOrderSvgUri, +// required this.strokeOrderGifUri, +// required this.uri, +// }); + +// KanjiResultData.fromJishoObject(jisho.KanjiResultData object) +// : taughtIn = object.taughtIn, +// jlptLevel = object.jlptLevel, +// newspaperFrequencyRank = object.newspaperFrequencyRank, +// strokeCount = object.strokeCount, +// meaning = object.meaning, +// kunyomi = object.kunyomi, +// onyomi = object.onyomi, +// kunyomiExamples = object.kunyomiExamples +// .map((k) => YomiExample.fromJishoObject(k)) +// .toList(), +// onyomiExamples = object.onyomiExamples +// .map((o) => YomiExample.fromJishoObject(o)) +// .toList(), +// radical = (object.radical == null) +// ? null +// : Radical.fromJishoObject(object.radical!), +// parts = object.parts, +// strokeOrderDiagramUri = object.strokeOrderDiagramUri, +// strokeOrderSvgUri = object.strokeOrderSvgUri, +// strokeOrderGifUri = object.strokeOrderGifUri, +// uri = object.uri; +// } diff --git a/lib/models/storage/scrape_result.dart b/lib/models/storage/scrape_result.dart index 23f6c73..c02eae7 100644 --- a/lib/models/storage/scrape_result.dart +++ b/lib/models/storage/scrape_result.dart @@ -1,101 +1,155 @@ -import 'package:objectbox/objectbox.dart'; -import 'package:unofficial_jisho_api/api.dart' as jisho; +// import 'package:objectbox/objectbox.dart'; +// import 'package:unofficial_jisho_api/api.dart' as jisho; -import 'common.dart'; +// import 'common.dart'; -@Entity() -class PhraseScrapeSentence { - int id = 0; - String english; - String japanese; - List pieces; +// TODO: Rewrite for sembast - PhraseScrapeSentence.fromJishoObject(jisho.PhraseScrapeSentence object) - : english = object.english, - japanese = object.japanese, - pieces = object.pieces - .map((p) => ExampleSentencePiece.fromJishoObject(p)) - .toList(); -} +// @Entity() +// class PhraseScrapeSentence { +// int id; +// String english; +// String japanese; +// List pieces; -@Entity() -class PhraseScrapeMeaning { - int id = 0; - List seeAlsoTerms; - List sentences; - String definition; - List supplemental; - String? definitionAbstract; - List tags; +// PhraseScrapeSentence({ +// this.id = 0, +// required this.english, +// required this.japanese, +// required this.pieces, +// }); - PhraseScrapeMeaning.fromJishoObject(jisho.PhraseScrapeMeaning object) - : seeAlsoTerms = object.seeAlsoTerms, - sentences = object.sentences - .map((s) => PhraseScrapeSentence.fromJishoObject(s)) - .toList(), - definition = object.definition, - supplemental = object.supplemental, - definitionAbstract = object.definitionAbstract, - tags = object.tags; -} +// PhraseScrapeSentence.fromJishoObject(jisho.PhraseScrapeSentence object) +// : id = 0, +// english = object.english, +// japanese = object.japanese, +// pieces = object.pieces +// .map((p) => ExampleSentencePiece.fromJishoObject(p)) +// .toList(); +// } -@Entity() -class KanjiKanaPair { - int id = 0; - String kanji; - String? kana; +// @Entity() +// class PhraseScrapeMeaning { +// int id; +// List seeAlsoTerms; +// List sentences; +// String definition; +// List supplemental; +// String? definitionAbstract; +// List tags; - KanjiKanaPair.fromJishoObject(jisho.KanjiKanaPair object) - : kanji = object.kanji, - kana = object.kana; -} +// PhraseScrapeMeaning({ +// this.id = 0, +// required this.seeAlsoTerms, +// required this.sentences, +// required this.definition, +// required this.supplemental, +// required this.definitionAbstract, +// required this.tags, +// }); -@Entity() -class PhrasePageScrapeResult { - int id = 0; - bool found; - String query; - PhrasePageScrapeResultData? data; +// PhraseScrapeMeaning.fromJishoObject(jisho.PhraseScrapeMeaning object) +// : id = 0, +// seeAlsoTerms = object.seeAlsoTerms, +// sentences = object.sentences +// .map((s) => PhraseScrapeSentence.fromJishoObject(s)) +// .toList(), +// definition = object.definition, +// supplemental = object.supplemental, +// definitionAbstract = object.definitionAbstract, +// tags = object.tags; +// } - PhrasePageScrapeResult.fromJishoObject(jisho.PhrasePageScrapeResult object) - : found = object.found, - query = object.query, - data = (object.data == null) - ? null - : PhrasePageScrapeResultData.fromJishoObject(object.data!); -} +// @Entity() +// class KanjiKanaPair { +// int id; +// String kanji; +// String? kana; -@Entity() -class AudioFile { - int id = 0; - String uri; - String mimetype; +// KanjiKanaPair({ +// this.id = 0, +// required this.kanji, +// required this.kana, +// }); - AudioFile.fromJishoObject(jisho.AudioFile object) - : uri = object.uri, - mimetype = object.mimetype; -} +// KanjiKanaPair.fromJishoObject(jisho.KanjiKanaPair object) +// : id = 0, +// kanji = object.kanji, +// kana = object.kana; +// } -@Entity() -class PhrasePageScrapeResultData { - int id = 0; - String uri; - List tags; - List meanings; - List otherForms; - List audio; - List notes; +// @Entity() +// class PhrasePageScrapeResult { +// int id; +// bool found; +// String query; +// PhrasePageScrapeResultData? data; - PhrasePageScrapeResultData.fromJishoObject( - jisho.PhrasePageScrapeResultData object, - ) : uri = object.uri, - tags = object.tags, - meanings = object.meanings - .map((m) => PhraseScrapeMeaning.fromJishoObject(m)) - .toList(), - otherForms = object.otherForms - .map((f) => KanjiKanaPair.fromJishoObject(f)) - .toList(), - audio = object.audio.map((a) => AudioFile.fromJishoObject(a)).toList(), - notes = object.notes; -} +// PhrasePageScrapeResult({ +// this.id = 0, +// required this.found, +// required this.query, +// required this.data, +// }); + +// PhrasePageScrapeResult.fromJishoObject(jisho.PhrasePageScrapeResult object) +// : id = 0, +// found = object.found, +// query = object.query, +// data = (object.data == null) +// ? null +// : PhrasePageScrapeResultData.fromJishoObject(object.data!); +// } + +// @Entity() +// class AudioFile { +// int id; +// String uri; +// String mimetype; + +// AudioFile({ +// this.id = 0, +// required this.uri, +// required this.mimetype, +// }); + +// AudioFile.fromJishoObject(jisho.AudioFile object) +// : id = 0, +// uri = object.uri, +// mimetype = object.mimetype; +// } + +// @Entity() +// class PhrasePageScrapeResultData { +// int id; +// String uri; +// List tags; +// List meanings; +// List otherForms; +// List audio; +// List notes; + +// PhrasePageScrapeResultData({ +// this.id = 0, +// required this.uri, +// required this.tags, +// required this.meanings, +// required this.otherForms, +// required this.audio, +// required this.notes, +// }); + +// PhrasePageScrapeResultData.fromJishoObject( +// jisho.PhrasePageScrapeResultData object, +// ) : id = 0, +// uri = object.uri, +// tags = object.tags, +// meanings = object.meanings +// .map((m) => PhraseScrapeMeaning.fromJishoObject(m)) +// .toList(), +// otherForms = object.otherForms +// .map((f) => KanjiKanaPair.fromJishoObject(f)) +// .toList(), +// audio = object.audio.map((a) => AudioFile.fromJishoObject(a)).toList(), +// notes = object.notes; +// } diff --git a/lib/models/storage/search_result.dart b/lib/models/storage/search_result.dart index 486fba1..3f6738b 100644 --- a/lib/models/storage/search_result.dart +++ b/lib/models/storage/search_result.dart @@ -1,126 +1,195 @@ -import 'package:objectbox/objectbox.dart'; -import 'package:unofficial_jisho_api/api.dart' as jisho; +// import 'package:objectbox/objectbox.dart'; +// import 'package:unofficial_jisho_api/api.dart' as jisho; -@Entity() -class SearchResult { - int id = 0; - final JishoResultMeta meta; - final ToMany data = ToMany(); +// TODO: Rewrite for sembast - SearchResult.fromJishoObject(final jisho.JishoAPIResult object) - : meta = JishoResultMeta.fromJishoObject(object.meta) { - data.addAll( - object.data - ?.map((r) => JishoResult.fromJishoObject(r)) ?? - [], - ); - } -} +// @Entity() +// class SearchResult { +// int id; +// final JishoResultMeta meta; +// final ToMany data; -@Entity() -class JishoResultMeta { - int id = 0; - int status; +// SearchResult({ +// this.id = 0, +// required this.meta, +// required this.data, +// }); - JishoResultMeta.fromJishoObject(final jisho.JishoResultMeta object) - : status = object.status; -} +// SearchResult.fromJishoObject(final jisho.JishoAPIResult object) +// : id = 0, +// meta = JishoResultMeta.fromJishoObject(object.meta), +// data = ToMany() +// ..addAll( +// object.data?.map((r) => JishoResult.fromJishoObject(r)) ?? +// [], +// ); +// } -@Entity() -class JishoResult { - int id = 0; - JishoAttribution attribution; - bool? is_common; - List japanese; - List jlpt; - List senses; - String slug; - List tags; +// @Entity() +// class JishoResultMeta { +// int id; +// int status; - JishoResult.fromJishoObject(final jisho.JishoResult object) - : attribution = JishoAttribution.fromJishoObject(object.attribution), - is_common = object.isCommon, - japanese = object.japanese - .map((j) => JishoJapaneseWord.fromJishoObject(j)) - .toList(), - jlpt = object.jlpt, - senses = object.senses - .map((s) => JishoWordSense.fromJishoObject(s)) - .toList(), - slug = object.slug, - tags = object.tags; -} +// JishoResultMeta({ +// this.id = 0, +// required this.status, +// }); -@Entity() -class JishoAttribution { - int id = 0; - String? dbpedia; - bool jmdict; - bool jmnedict; +// JishoResultMeta.fromJishoObject(final jisho.JishoResultMeta object) +// : id = 0, +// status = object.status; +// } - JishoAttribution.fromJishoObject(final jisho.JishoAttribution object) - : dbpedia = object.dbpedia, - jmdict = object.jmdict, - jmnedict = object.jmnedict; -} +// @Entity() +// class JishoResult { +// int id; +// JishoAttribution attribution; +// bool? is_common; +// List japanese; +// List jlpt; +// List senses; +// String slug; +// List tags; -@Entity() -class JishoJapaneseWord { - int id = 0; - String? reading; - String? word; +// JishoResult({ +// this.id = 0, +// required this.attribution, +// required this.is_common, +// required this.japanese, +// required this.jlpt, +// required this.senses, +// required this.slug, +// required this.tags, +// }); - JishoJapaneseWord.fromJishoObject(final jisho.JishoJapaneseWord object) - : reading = object.reading, - word = object.word; -} +// JishoResult.fromJishoObject(final jisho.JishoResult object) +// : id = 0, +// attribution = JishoAttribution.fromJishoObject(object.attribution), +// is_common = object.isCommon, +// japanese = object.japanese +// .map((j) => JishoJapaneseWord.fromJishoObject(j)) +// .toList(), +// jlpt = object.jlpt, +// senses = object.senses +// .map((s) => JishoWordSense.fromJishoObject(s)) +// .toList(), +// slug = object.slug, +// tags = object.tags; +// } -@Entity() -class JishoWordSense { - int id = 0; - List antonyms; - List english_definitions; - List info; - List links; - List parts_of_speech; - List restrictions; - List see_also; - List source; - List tags; +// @Entity() +// class JishoAttribution { +// int id; +// String? dbpedia; +// bool jmdict; +// bool jmnedict; - JishoWordSense.fromJishoObject(final jisho.JishoWordSense object) - : antonyms = object.antonyms, - english_definitions = object.englishDefinitions, - info = object.info, - links = - object.links.map((l) => JishoSenseLink.fromJishoObject(l)).toList(), - parts_of_speech = object.partsOfSpeech, - restrictions = object.restrictions, - see_also = object.seeAlso, - source = object.source - .map((s) => JishoWordSource.fromJishoObject(s)) - .toList(), - tags = object.tags; -} +// JishoAttribution({ +// this.id = 0, +// required this.dbpedia, +// required this.jmdict, +// required this.jmnedict, +// }); -@Entity() -class JishoWordSource { - int id = 0; - String language; - String? word; +// JishoAttribution.fromJishoObject(final jisho.JishoAttribution object) +// : id = 0, +// dbpedia = object.dbpedia, +// jmdict = object.jmdict, +// jmnedict = object.jmnedict; +// } - JishoWordSource.fromJishoObject(final jisho.JishoWordSource object) - : language = object.language, - word = object.word; -} +// @Entity() +// class JishoJapaneseWord { +// int id; +// String? reading; +// String? word; -@Entity() -class JishoSenseLink { - int id = 0; - String text; - String url; +// JishoJapaneseWord({ +// this.id = 0, +// required this.reading, +// required this.word, +// }); - JishoSenseLink.fromJishoObject(final jisho.JishoSenseLink object) - : text = object.text, - url = object.url; -} +// JishoJapaneseWord.fromJishoObject(final jisho.JishoJapaneseWord object) +// : id = 0, +// reading = object.reading, +// word = object.word; +// } + +// @Entity() +// class JishoWordSense { +// int id; +// List antonyms; +// List english_definitions; +// List info; +// List links; +// List parts_of_speech; +// List restrictions; +// List see_also; +// List source; +// List tags; + +// JishoWordSense({ +// this.id = 0, +// required this.antonyms, +// required this.english_definitions, +// required this.info, +// required this.links, +// required this.parts_of_speech, +// required this.restrictions, +// required this.see_also, +// required this.source, +// required this.tags, +// }); + +// JishoWordSense.fromJishoObject(final jisho.JishoWordSense object) +// : id = 0, +// antonyms = object.antonyms, +// english_definitions = object.englishDefinitions, +// info = object.info, +// links = +// object.links.map((l) => JishoSenseLink.fromJishoObject(l)).toList(), +// parts_of_speech = object.partsOfSpeech, +// restrictions = object.restrictions, +// see_also = object.seeAlso, +// source = object.source +// .map((s) => JishoWordSource.fromJishoObject(s)) +// .toList(), +// tags = object.tags; +// } + +// @Entity() +// class JishoWordSource { +// int id; +// String language; +// String? word; + +// JishoWordSource({ +// this.id = 0, +// required this.language, +// required this.word, +// }); + +// JishoWordSource.fromJishoObject(final jisho.JishoWordSource object) +// : id = 0, +// language = object.language, +// word = object.word; +// } + +// @Entity() +// class JishoSenseLink { +// int id; +// String text; +// String url; + +// JishoSenseLink({ +// this.id = 0, +// required this.text, +// required this.url, +// }); + +// JishoSenseLink.fromJishoObject(final jisho.JishoSenseLink object) +// : id = 0, +// text = object.text, +// url = object.url; +// } diff --git a/lib/objectbox-model.json b/lib/objectbox-model.json deleted file mode 100644 index 8c9f338..0000000 --- a/lib/objectbox-model.json +++ /dev/null @@ -1,141 +0,0 @@ -{ - "_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.", - "_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.", - "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", - "entities": [ - { - "id": "3:8314315977756262774", - "lastPropertyId": "4:7972948456299367594", - "name": "WordResult", - "properties": [ - { - "id": "1:8286440150679521496", - "name": "id", - "type": 6, - "flags": 1 - }, - { - "id": "2:2698026687178480112", - "name": "timestamp", - "type": 10 - }, - { - "id": "3:8750782874894963158", - "name": "word", - "type": 9 - }, - { - "id": "4:7972948456299367594", - "name": "searchStringId", - "type": 11, - "flags": 520, - "indexId": "1:6146948198859733323", - "relationTarget": "WordQuery" - } - ], - "relations": [] - }, - { - "id": "4:4256390943850643278", - "lastPropertyId": "3:1496429060084558178", - "name": "KanjiQuery", - "properties": [ - { - "id": "1:2966275213904862677", - "name": "id", - "type": 6, - "flags": 1 - }, - { - "id": "2:3733952844232949036", - "name": "kanji", - "type": 9 - } - ], - "relations": [] - }, - { - "id": "5:3499538826755540666", - "lastPropertyId": "3:1154921921492752045", - "name": "WordQuery", - "properties": [ - { - "id": "1:2582448470002735577", - "name": "id", - "type": 6, - "flags": 1 - }, - { - "id": "2:6622038022626247037", - "name": "query", - "type": 9 - } - ], - "relations": [] - }, - { - "id": "6:8118874861016646859", - "lastPropertyId": "5:818915488505962903", - "name": "Search", - "properties": [ - { - "id": "1:3233720904924970047", - "name": "id", - "type": 6, - "flags": 1 - }, - { - "id": "2:7793044338609887616", - "name": "timestamp", - "type": 10 - }, - { - "id": "4:5737790291742758071", - "name": "wordQueryId", - "type": 11, - "flags": 520, - "indexId": "4:4174896839978600983", - "relationTarget": "WordQuery" - }, - { - "id": "5:818915488505962903", - "name": "kanjiQueryId", - "type": 11, - "flags": 520, - "indexId": "5:5394995618034342416", - "relationTarget": "KanjiQuery" - } - ], - "relations": [] - } - ], - "lastEntityId": "6:8118874861016646859", - "lastIndexId": "5:5394995618034342416", - "lastRelationId": "1:2624712325077938293", - "lastSequenceId": "0:0", - "modelVersion": 5, - "modelVersionParserMinimum": 5, - "retiredEntityUids": [ - 8135239166970424087, - 461492167249325765 - ], - "retiredIndexUids": [ - 2344626140411525437, - 1957456749938325194 - ], - "retiredPropertyUids": [ - 2681934095975267680, - 4514526257378540330, - 1930470268740402049, - 4297905889790758495, - 4157902147911002923, - 7573103520245228403, - 1496429060084558178, - 1154921921492752045, - 2254834401134912797 - ], - "retiredRelationUids": [ - 2624712325077938293 - ], - "version": 1 -} \ No newline at end of file diff --git a/lib/view/screens/history.dart b/lib/view/screens/history.dart index faf2901..9c52df6 100644 --- a/lib/view/screens/history.dart +++ b/lib/view/screens/history.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:sembast/sembast.dart'; -import '../../bloc/database/database_bloc.dart'; import '../../models/history/search.dart'; -import '../../objectbox.g.dart'; import '../components/history/date_divider.dart'; import '../components/history/kanji_search_item.dart'; import '../components/history/phrase_search_item.dart'; @@ -11,60 +11,63 @@ import '../components/opaque_box.dart'; class HistoryView extends StatelessWidget { const HistoryView({Key? key}) : super(key: key); + Database get _db => GetIt.instance.get(); + + Stream> get searchStream => Search.store + .query( + finder: Finder( + sortOrders: [SortOrder('timestamp', false)], + ), + ) + .onSnapshots(_db) + .map((snapshot) { + return snapshot + .map( + (snap) => (snap.value != null) + ? Search.fromJson(snap.value! as Map) + : null, + ) + .where((s) => s != null) + .map((s) => s!) + .toList(); + }); + @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - if (state is DatabaseDisconnected) { - throw DatabaseNotConnectedException(); - } - - return StreamBuilder>( - stream: getAsyncStream(state), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return Container(); - } - - final List data = snapshot.data!; - return OpaqueBox( - child: ListView.separated( - itemCount: data.length + 1, - itemBuilder: historyEntryWithData(data), - separatorBuilder: historyEntrySeparatorWithData(data), - ), - ); - }, + return StreamBuilder>( + stream: searchStream, + builder: (context, snapshot) { + if (!snapshot.hasData) + return const Center( + child: Text('The history is empty.\nTry searching for something!'), + ); + final List data = snapshot.data!; + return OpaqueBox( + child: ListView.separated( + itemCount: data.length + 1, + itemBuilder: historyEntryWithData(data), + separatorBuilder: historyEntrySeparatorWithData(data), + ), ); }, ); } - Stream> getAsyncStream(DatabaseState state) => - ((state as DatabaseConnected).database.box().query() - ..order(Search_.timestamp, flags: Order.descending)) - .watch(triggerImmediately: true) - .map((query) => query.find()); - Widget Function(BuildContext, int) historyEntryWithData(List data) => (context, index) { - if (index == 0) { - return Container(); - } + if (index == 0) return Container(); final Search search = data[index - 1]; - if (search.isKanji()) { - return KanjiSearchItem( - result: search.kanjiQuery.target!, - timestamp: search.timestamp, - ); - } else { - return PhraseSearchItem( - search: search.wordQuery.target!, - timestamp: search.timestamp, - ); - } + return (search.isKanji) + ? KanjiSearchItem( + result: search.kanjiQuery!, + timestamp: search.timestamp, + ) + : PhraseSearchItem( + search: search.wordQuery!, + timestamp: search.timestamp, + ); }; DateTime roundToDay(DateTime date) => diff --git a/lib/view/screens/search/kanji_result_page.dart b/lib/view/screens/search/kanji_result_page.dart index 8bef057..07a6f2b 100644 --- a/lib/view/screens/search/kanji_result_page.dart +++ b/lib/view/screens/search/kanji_result_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:sembast/sembast.dart'; -import '../../../bloc/database/database_bloc.dart'; import '../../../models/history/kanji_query.dart'; import '../../../models/history/search.dart'; import '../../../services/jisho_api/kanji_search.dart'; @@ -19,18 +20,18 @@ class KanjiResultPage extends StatelessWidget { appBar: AppBar(), body: FutureBuilder( future: fetchKanji(kanjiSearchTerm), - builder: ( context, snapshot) { - if (!snapshot.hasData) return LoadingScreen(); + builder: (context, snapshot) { + if (!snapshot.hasData) return const LoadingScreen(); if (snapshot.hasError) return ErrorWidget(snapshot.error!); if (!addedToDatabase) { - (BlocProvider.of(context).state as DatabaseConnected) - .database - .box() - .put(Search(timestamp: DateTime.now()) - ..kanjiQuery.target = KanjiQuery( - kanji: kanjiSearchTerm, - ),); + Search.store.add( + GetIt.instance.get(), + Search.fromKanjiQuery( + timestamp: DateTime.now(), + kanjiQuery: KanjiQuery(kanji: kanjiSearchTerm), + ).toJson(), + ); addedToDatabase = true; } diff --git a/lib/view/screens/search/search_results_page.dart b/lib/view/screens/search/search_results_page.dart index 320ba89..96f779a 100644 --- a/lib/view/screens/search/search_results_page.dart +++ b/lib/view/screens/search/search_results_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:sembast/sembast.dart'; -import '../../../bloc/database/database_bloc.dart'; import '../../../models/history/search.dart'; import '../../../models/history/word_query.dart'; import '../../../services/jisho_api/jisho_search.dart'; @@ -23,20 +24,18 @@ class SearchResultsPage extends StatelessWidget { body: FutureBuilder( future: results, builder: (context, snapshot) { - if (!snapshot.hasData) return LoadingScreen(); + if (!snapshot.hasData) return const LoadingScreen(); if (snapshot.hasError || snapshot.data!.data == null) return ErrorWidget(snapshot.error!); if (!addedToDatabase) { - (BlocProvider.of(context).state as DatabaseConnected) - .database - .box() - .put( - Search(timestamp: DateTime.now()) - ..wordQuery.target = WordQuery( - query: searchTerm, - ), - ); + Search.store.add( + GetIt.instance.get(), + Search.fromWordQuery( + timestamp: DateTime.now(), + wordQuery: WordQuery(query: searchTerm), + ).toJson(), + ); addedToDatabase = true; } diff --git a/lib/view/screens/settings.dart b/lib/view/screens/settings.dart index 43fe5cc..47e8503 100644 --- a/lib/view/screens/settings.dart +++ b/lib/view/screens/settings.dart @@ -1,13 +1,13 @@ import 'package:confirm_dialog/confirm_dialog.dart'; import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:sembast/sembast.dart'; import 'package:settings_ui/settings_ui.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import '../../bloc/database/database_bloc.dart'; import '../../bloc/theme/theme_bloc.dart'; import '../../models/history/search.dart'; import '../../models/themes/theme.dart'; -import '../../objectbox.g.dart'; class SettingsView extends StatefulWidget { const SettingsView({Key? key}) : super(key: key); @@ -41,11 +41,20 @@ class _SettingsViewState extends State { } /// Update stored preferences with values from setting page state - void _updatePrefs() { + Future _updatePrefs() async { prefs.setBool('darkThemeEnabled', darkThemeEnabled); prefs.setBool('autoThemeEnabled', autoThemeEnabled); } + Future clearHistory(context) async { + final bool userIsSure = await confirm(context); + + if (userIsSure) { + final Database db = GetIt.instance.get(); + await Search.store.delete(db); + } + } + @override Widget build(BuildContext context) { final TextStyle _titleTextStyle = TextStyle( @@ -133,12 +142,11 @@ class _SettingsViewState extends State { title: 'Export Data', enabled: false, ), - const SettingsTile( - leading: Icon(Icons.delete), + SettingsTile( + leading: const Icon(Icons.delete), title: 'Clear History', - onPressed: _clearHistory, - titleTextStyle: TextStyle(color: Colors.red), - enabled: false, + onPressed: clearHistory, + titleTextStyle: const TextStyle(color: Colors.red), ), SettingsTile( leading: const Icon(Icons.delete), @@ -153,15 +161,3 @@ class _SettingsViewState extends State { ); } } - -void _clearHistory(context) { - confirm(context).then((userIsSure) { - if (userIsSure) { - final Store db = - (BlocProvider.of(context).state as DatabaseConnected) - .database; - // db.box().query().build().find() - db.box().removeAll(); - } - }); -} diff --git a/pubspec.lock b/pubspec.lock index 0907336..77cb926 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -42,7 +42,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.2" + version: "2.8.1" bloc: dependency: transitive description: @@ -119,7 +119,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.1.0" charcode: dependency: transitive description: @@ -282,6 +282,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + get_it: + dependency: "direct main" + description: + name: get_it + url: "https://pub.dartlang.org" + source: hosted + version: "7.2.0" glob: dependency: transitive description: @@ -372,7 +379,7 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.11" + version: "0.12.10" mdi: dependency: "direct main" description: @@ -401,27 +408,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" - objectbox: - dependency: "direct main" - description: - name: objectbox - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" - objectbox_flutter_libs: - dependency: "direct main" - description: - name: objectbox_flutter_libs - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" - objectbox_generator: - dependency: "direct dev" - description: - name: objectbox_generator - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" package_config: dependency: transitive description: @@ -430,7 +416,7 @@ packages: source: hosted version: "2.0.0" path: - dependency: transitive + dependency: "direct main" description: name: path url: "https://pub.dartlang.org" @@ -534,6 +520,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" + sembast: + dependency: "direct main" + description: + name: sembast + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.1" settings_ui: dependency: "direct main" description: @@ -602,13 +595,6 @@ packages: description: flutter source: sdk version: "0.0.99" - source_gen: - dependency: transitive - description: - name: source_gen - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.3" source_span: dependency: transitive description: @@ -644,6 +630,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + synchronized: + dependency: transitive + description: + name: synchronized + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" term_glyph: dependency: transitive description: @@ -657,7 +650,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.3" + version: "0.4.2" timing: dependency: transitive description: @@ -778,5 +771,5 @@ packages: source: hosted version: "3.1.0" sdks: - dart: ">=2.13.0 <3.0.0" + dart: ">=2.14.0 <3.0.0" flutter: ">=2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index d12202d..71311ed 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,21 +13,20 @@ dependencies: sdk: flutter flutter_bloc: ^7.0.1 flutter_slidable: ^0.6.0 + get_it: ^7.2.0 mdi: ^5.0.0-nullsafety.0 - objectbox: ^1.1.1 - objectbox_flutter_libs: ^1.1.1 + path: ^1.8.0 path_provider: ^2.0.2 + sembast: ^3.1.1 + settings_ui: ^1.0.0 shared_preferences: ^2.0.6 unofficial_jisho_api: ^2.0.2 url_launcher: ^6.0.9 - settings_ui: ^1.0.0 - dev_dependencies: build_runner: ^2.0.6 flutter_test: sdk: flutter - objectbox_generator: ^1.1.1 flutter_native_splash: ^1.2.0 flutter_launcher_icons: "^0.9.1" From cfe5a653802a64d0a541655d48e639670577e7b1 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Sat, 4 Dec 2021 05:22:58 +0100 Subject: [PATCH 5/8] Fix some more code style --- analysis_options.yaml | 1 - lib/bloc/theme/theme_state.dart | 12 +++++----- lib/models/history/search.dart | 1 - lib/models/themes/theme.dart | 4 +++- lib/router.dart | 4 ++-- .../components/history/kanji_search_item.dart | 22 +++++++++---------- .../kanji_search_body/kanji_search_bar.dart | 9 +++----- .../parts/wanikani_badge.dart | 18 ++++++++------- .../search_results_body/search_card.dart | 2 +- lib/view/screens/search/kanji_view.dart | 2 +- 10 files changed, 36 insertions(+), 39 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index a74d9d6..894e0e4 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -137,7 +137,6 @@ linter: - unnecessary_await_in_return - unnecessary_brace_in_string_interps - unnecessary_const - - unnecessary_constructor_name - unnecessary_getters_setters - unnecessary_new - unnecessary_null_aware_assignments diff --git a/lib/bloc/theme/theme_state.dart b/lib/bloc/theme/theme_state.dart index 7bb3518..7b45fbb 100644 --- a/lib/bloc/theme/theme_state.dart +++ b/lib/bloc/theme/theme_state.dart @@ -4,24 +4,22 @@ part of 'theme_bloc.dart'; abstract class ThemeState { final bool prefsAreLoaded; - const ThemeState(this.prefsAreLoaded); + const ThemeState({required this.prefsAreLoaded}); AppTheme get theme; } class LightThemeState extends ThemeState { - final bool prefsAreLoaded; - - const LightThemeState({this.prefsAreLoaded = false}) : super(prefsAreLoaded); + const LightThemeState({bool prefsAreLoaded = false}) + : super(prefsAreLoaded: prefsAreLoaded); @override AppTheme get theme => LightTheme(); } class DarkThemeState extends ThemeState { - final bool prefsAreLoaded; - - const DarkThemeState({this.prefsAreLoaded = false}) : super(prefsAreLoaded); + const DarkThemeState({bool prefsAreLoaded = false}) + : super(prefsAreLoaded: prefsAreLoaded); @override AppTheme get theme => DarkTheme(); diff --git a/lib/models/history/search.dart b/lib/models/history/search.dart index 7e3c7e6..2de2096 100644 --- a/lib/models/history/search.dart +++ b/lib/models/history/search.dart @@ -1,5 +1,4 @@ import 'package:sembast/sembast.dart'; -import 'package:sembast/timestamp.dart'; import './kanji_query.dart'; import './word_query.dart'; diff --git a/lib/models/themes/theme.dart b/lib/models/themes/theme.dart index 76369cc..705be40 100644 --- a/lib/models/themes/theme.dart +++ b/lib/models/themes/theme.dart @@ -50,7 +50,9 @@ class ColorSet { MaterialColor createMaterialColor(Color color) { final List strengths = [.05]; final swatch = {}; - final int r = color.red, g = color.green, b = color.blue; + final int r = color.red; + final int g = color.green; + final int b = color.blue; for (int i = 1; i < 10; i++) { strengths.add(0.1 * i); diff --git a/lib/router.dart b/lib/router.dart index a588e5c..ccf126a 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -12,13 +12,13 @@ Route generateRoute(RouteSettings settings) { return MaterialPageRoute(builder: (_) => const Home()); case '/search': - final searchTerm = args as String; + final searchTerm = args! as String; return MaterialPageRoute( builder: (_) => SearchResultsPage(searchTerm: searchTerm), ); case '/kanjiSearch': - final searchTerm = args as String; + final searchTerm = args! as String; return MaterialPageRoute( builder: (_) => KanjiResultPage(kanjiSearchTerm: searchTerm), ); diff --git a/lib/view/components/history/kanji_search_item.dart b/lib/view/components/history/kanji_search_item.dart index 5a9d405..582fee9 100644 --- a/lib/view/components/history/kanji_search_item.dart +++ b/lib/view/components/history/kanji_search_item.dart @@ -54,26 +54,26 @@ class KanjiSearchItem extends StatelessWidget { @override Widget build(BuildContext context) { return Slidable( - child: SearchItem( - onTap: () { - Navigator.pushNamed(context, '/kanjiSearch', arguments: this.result.kanji); - }, - time: timestamp, - search: _KanjiBox(result.kanji), - ), - actionPane: SlidableScrollActionPane(), - secondaryActions: [ + actionPane: const SlidableScrollActionPane(), + secondaryActions: const [ IconSlideAction( - caption: "Favourite", + caption: 'Favourite', color: Colors.yellow, icon: Icons.star, ), IconSlideAction( - caption: "Delete", + caption: 'Delete', color: Colors.red, icon: Icons.delete, ), ], + child: SearchItem( + onTap: () { + Navigator.pushNamed(context, '/kanjiSearch', arguments: result.kanji); + }, + time: timestamp, + search: _KanjiBox(result.kanji), + ), ); } } diff --git a/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart b/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart index 7f2ef5d..ce1b806 100644 --- a/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart +++ b/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart @@ -7,7 +7,7 @@ class KanjiSearchBar extends StatefulWidget { const KanjiSearchBar({this.onChanged, Key? key}) : super(key: key); @override - KanjiSearchBarState createState() => KanjiSearchBarState(this.onChanged); + KanjiSearchBarState createState() => KanjiSearchBarState(); } enum TextFieldButton { clear, paste } @@ -15,9 +15,6 @@ enum TextFieldButton { clear, paste } class KanjiSearchBarState extends State { final TextEditingController textController = TextEditingController(); TextFieldButton button = TextFieldButton.paste; - final Function(String)? onChanged; - - KanjiSearchBarState(this.onChanged); @override void initState() { @@ -25,7 +22,7 @@ class KanjiSearchBarState extends State { } void runOnChanged() { - if (onChanged != null) onChanged!(textController.text); + if (widget.onChanged != null) widget.onChanged!(textController.text); } void clearText() { @@ -56,7 +53,7 @@ class KanjiSearchBarState extends State { return TextField( controller: textController, onChanged: (text) { - if (onChanged != null) onChanged!(text); + if (widget.onChanged != null) widget.onChanged!(text); }, onSubmitted: (_) => {}, decoration: InputDecoration( diff --git a/lib/view/components/search/search_results_body/parts/wanikani_badge.dart b/lib/view/components/search/search_results_body/parts/wanikani_badge.dart index 3de0ec2..96df9c8 100644 --- a/lib/view/components/search/search_results_body/parts/wanikani_badge.dart +++ b/lib/view/components/search/search_results_body/parts/wanikani_badge.dart @@ -2,25 +2,27 @@ import 'package:flutter/material.dart'; import './badge.dart'; class WKBadge extends StatelessWidget { - final String wkLevel; + final String level; - const WKBadge(this.wkLevel); + const WKBadge({ + required this.level, + Key? key, + }) : super(key: key); String _extractWkLevel(String wkRaw) { - // return jlptRaw.isNotEmpty ? jlptRaw.substring(5).toUpperCase() : ''; - return wkRaw.isNotEmpty ? 'W' + wkRaw.substring(8) : ''; + return wkRaw.isNotEmpty ? 'W${wkRaw.substring(8)}' : ''; } @override Widget build(BuildContext context) { return Badge( + color: level.isNotEmpty ? Colors.red : Colors.transparent, child: Text( - _extractWkLevel(this.wkLevel), - style: TextStyle( + _extractWkLevel(level), + style: const TextStyle( color: Colors.white, ), ), - color: this.wkLevel.isNotEmpty ? Colors.red : Colors.transparent ); } -} \ No newline at end of file +} diff --git a/lib/view/components/search/search_results_body/search_card.dart b/lib/view/components/search/search_results_body/search_card.dart index e56b270..d4c8129 100644 --- a/lib/view/components/search/search_results_body/search_card.dart +++ b/lib/view/components/search/search_results_body/search_card.dart @@ -34,7 +34,7 @@ class SearchResultCard extends StatelessWidget { Row( children: [ WKBadge( - result.tags.firstWhere( + level: result.tags.firstWhere( (tag) => tag.contains('wanikani'), orElse: () => '', ), diff --git a/lib/view/screens/search/kanji_view.dart b/lib/view/screens/search/kanji_view.dart index 04a88d7..77f8042 100644 --- a/lib/view/screens/search/kanji_view.dart +++ b/lib/view/screens/search/kanji_view.dart @@ -8,6 +8,6 @@ class KanjiView extends StatelessWidget { @override Widget build(BuildContext context) { - return KanjiSearchBody(); + return const KanjiSearchBody(); } } From 37f235841125ade19ec7c625316c9987ab07b138 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Sat, 4 Dec 2021 05:23:20 +0100 Subject: [PATCH 6/8] Update gradle --- android/app/src/main/AndroidManifest.xml | 1 + android/build.gradle | 4 ++-- android/gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 965d966..87e8925 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -27,4 +27,5 @@ android:name="flutterEmbedding" android:value="2" /> + diff --git a/android/build.gradle b/android/build.gradle index 3100ad2..f97badc 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.5.0' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:7.0.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 296b146..595fb86 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip From 4e60f528cb6019dcdfc161c00dc9a51d0b0308ca Mon Sep 17 00:00:00 2001 From: h7x4 Date: Sat, 4 Dec 2021 05:31:27 +0100 Subject: [PATCH 7/8] Update history loading screen --- lib/view/screens/history.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/view/screens/history.dart b/lib/view/screens/history.dart index 9c52df6..f413512 100644 --- a/lib/view/screens/history.dart +++ b/lib/view/screens/history.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; +import 'package:jisho_study_tool/view/components/common/loading.dart'; import 'package:sembast/sembast.dart'; import '../../models/history/search.dart'; @@ -37,11 +38,14 @@ class HistoryView extends StatelessWidget { return StreamBuilder>( stream: searchStream, builder: (context, snapshot) { - if (!snapshot.hasData) + if (!snapshot.hasData) return const LoadingScreen(); + + final List data = snapshot.data!; + if (data.isEmpty) return const Center( child: Text('The history is empty.\nTry searching for something!'), ); - final List data = snapshot.data!; + return OpaqueBox( child: ListView.separated( itemCount: data.length + 1, From 067ae564ce4564d1c199a01503bfca66d3bc8f29 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Mon, 6 Dec 2021 20:26:52 +0100 Subject: [PATCH 8/8] Upgrade dependencies --- lib/bloc/theme/theme_bloc.dart | 33 ++-- lib/bloc/theme/theme_state.dart | 10 +- lib/main.dart | 159 +++--------------- lib/router.dart | 4 +- .../components/history/kanji_search_item.dart | 33 ++-- .../history/phrase_search_item.dart | 17 +- .../components/kanji/kanji_search_body.dart | 1 - .../components/search/language_selector.dart | 60 +++---- lib/view/components/search/search_bar.dart | 4 +- lib/view/home.dart | 114 +++++++++++++ lib/view/screens/settings.dart | 17 +- pubspec.lock | 159 +++++++++++------- pubspec.yaml | 6 +- 13 files changed, 313 insertions(+), 304 deletions(-) create mode 100644 lib/view/home.dart diff --git a/lib/bloc/theme/theme_bloc.dart b/lib/bloc/theme/theme_bloc.dart index 9db66ac..b34b5a7 100644 --- a/lib/bloc/theme/theme_bloc.dart +++ b/lib/bloc/theme/theme_bloc.dart @@ -1,7 +1,6 @@ -import 'dart:async'; - import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:get_it/get_it.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../models/themes/theme.dart'; @@ -13,24 +12,20 @@ part 'theme_event.dart'; part 'theme_state.dart'; class ThemeBloc extends Bloc { - bool prefsAreLoaded = false; - ThemeBloc() : super(const LightThemeState()) { - SharedPreferences.getInstance().then((prefs) { - prefsAreLoaded = true; - add( - SetTheme( - themeIsDark: prefs.getBool('darkThemeEnabled') ?? false, - ), - ); - }); - } + on( + (event, emit) => emit( + event.themeIsDark ? const DarkThemeState() : const LightThemeState(), + ), + ); - @override - Stream mapEventToState(ThemeEvent event) async* { - if (event is SetTheme) - yield event.themeIsDark - ? DarkThemeState(prefsAreLoaded: prefsAreLoaded) - : LightThemeState(prefsAreLoaded: prefsAreLoaded); + add( + SetTheme( + themeIsDark: GetIt.instance + .get() + .getBool('darkThemeEnabled') ?? + false, + ), + ); } } diff --git a/lib/bloc/theme/theme_state.dart b/lib/bloc/theme/theme_state.dart index 7b45fbb..134e0c6 100644 --- a/lib/bloc/theme/theme_state.dart +++ b/lib/bloc/theme/theme_state.dart @@ -2,24 +2,20 @@ part of 'theme_bloc.dart'; @immutable abstract class ThemeState { - final bool prefsAreLoaded; - - const ThemeState({required this.prefsAreLoaded}); + const ThemeState(); AppTheme get theme; } class LightThemeState extends ThemeState { - const LightThemeState({bool prefsAreLoaded = false}) - : super(prefsAreLoaded: prefsAreLoaded); + const LightThemeState(); @override AppTheme get theme => LightTheme(); } class DarkThemeState extends ThemeState { - const DarkThemeState({bool prefsAreLoaded = false}) - : super(prefsAreLoaded: prefsAreLoaded); + const DarkThemeState(); @override AppTheme get theme => DarkTheme(); diff --git a/lib/main.dart b/lib/main.dart index 0044107..31529b0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,40 +2,41 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; -import 'package:mdi/mdi.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; import 'package:sembast/sembast.dart'; import 'package:sembast/sembast_io.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'bloc/theme/theme_bloc.dart'; -import 'models/themes/theme.dart'; import 'router.dart'; -import 'view/components/common/splash.dart'; -import 'view/screens/history.dart'; -import 'view/screens/search/kanji_view.dart'; -import 'view/screens/search/search_view.dart'; -import 'view/screens/settings.dart'; + +Future setupDatabase() async { + final Directory appDocDir = await getApplicationDocumentsDirectory(); + if (!appDocDir.existsSync()) appDocDir.createSync(recursive: true); + final Database database = + await databaseFactoryIo.openDatabase(join(appDocDir.path, 'sembast.db')); + GetIt.instance.registerSingleton(database); +} + +Future setupSharedPreferences() async { + final SharedPreferences prefs = await SharedPreferences.getInstance(); + GetIt.instance.registerSingleton(prefs); +} Future main() async { WidgetsFlutterBinding.ensureInitialized(); - final Directory appDocDir = await getApplicationDocumentsDirectory(); - if (!appDocDir.existsSync()) - appDocDir.createSync(recursive: true); - - final Database db = await databaseFactoryIo.openDatabase(join(appDocDir.path, 'sembast.db')); - - GetIt.instance.registerSingleton(db); + await Future.wait([ + setupDatabase(), + setupSharedPreferences(), + ]); runApp(const MyApp()); } class MyApp extends StatelessWidget { - - const MyApp({ - Key? key, - }) : super(key: key); + const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -44,123 +45,13 @@ class MyApp extends StatelessWidget { BlocProvider(create: (context) => ThemeBloc()), ], child: BlocBuilder( - builder: (context, themeState) { - if (!themeState.prefsAreLoaded) return const SplashScreen(); - - return MaterialApp( - title: 'Jisho Study Tool', - theme: themeState.theme.getMaterialTheme(), - initialRoute: '/', - onGenerateRoute: generateRoute, - ); - }, + builder: (context, themeState) => MaterialApp( + title: 'Jisho Study Tool', + theme: themeState.theme.getMaterialTheme(), + initialRoute: '/', + onGenerateRoute: generateRoute, + ), ), ); } } - -class _Page { - final Widget content; - final Widget titleBar; - final BottomNavigationBarItem item; - - const _Page({ - required this.content, - required this.titleBar, - required this.item, - }); -} - -class Home extends StatefulWidget { - const Home({Key? key}) : super(key: key); - - @override - State createState() => _HomeState(); -} - -class _HomeState extends State { - int pageNum = 0; - - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, themeState) { - return Scaffold( - appBar: AppBar( - title: pages[pageNum].titleBar, - centerTitle: true, - backgroundColor: AppTheme.jishoGreen.background, - foregroundColor: AppTheme.jishoGreen.foreground, - ), - body: Stack( - children: [ - Positioned( - right: 30, - left: 100, - bottom: 30, - child: Image.asset( - 'assets/images/denshi_jisho_background_overlay.png', - ), - ), - pages[pageNum].content, - ], - ), - bottomNavigationBar: BottomNavigationBar( - fixedColor: AppTheme.jishoGreen.background, - currentIndex: pageNum, - onTap: (index) => setState(() { - pageNum = index; - }), - items: pages.map((p) => p.item).toList(), - showSelectedLabels: false, - showUnselectedLabels: false, - unselectedItemColor: themeState.theme.menuGreyDark.background, - ), - ); - }, - ); - } - - List<_Page> get pages => [ - const _Page( - content: SearchView(), - titleBar: Text('Search'), - item: BottomNavigationBarItem( - label: 'Search', - icon: Icon(Icons.search), - ), - ), - const _Page( - content: KanjiView(), - titleBar: Text('Kanji'), - item: BottomNavigationBarItem( - label: 'Kanji', - icon: Icon(Mdi.ideogramCjk, size: 30), - ), - ), - const _Page( - content: HistoryView(), - titleBar: Text('History'), - item: BottomNavigationBarItem( - label: 'History', - icon: Icon(Icons.history), - ), - ), - _Page( - content: Container(), - titleBar: const Text('Saved'), - item: const BottomNavigationBarItem( - label: 'Saved', - icon: Icon(Icons.bookmark), - ), - ), - const _Page( - content: SettingsView(), - titleBar: Text('Settings'), - item: BottomNavigationBarItem( - label: 'Settings', - icon: Icon(Icons.settings), - ), - ), - ]; -} diff --git a/lib/router.dart b/lib/router.dart index ccf126a..5b9b5ce 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; -import 'main.dart'; +import 'view/home.dart'; import 'view/screens/search/kanji_result_page.dart'; import 'view/screens/search/search_results_page.dart'; -Route generateRoute(RouteSettings settings) { +Route generateRoute(RouteSettings settings) { final args = settings.arguments; switch (settings.name) { diff --git a/lib/view/components/history/kanji_search_item.dart b/lib/view/components/history/kanji_search_item.dart index 582fee9..15ce4c5 100644 --- a/lib/view/components/history/kanji_search_item.dart +++ b/lib/view/components/history/kanji_search_item.dart @@ -13,7 +13,8 @@ class _KanjiBox extends StatelessWidget { @override Widget build(BuildContext context) { - final ColorSet _menuColors = BlocProvider.of(context).state.theme.menuGreyLight; + final ColorSet _menuColors = + BlocProvider.of(context).state.theme.menuGreyLight; return IntrinsicHeight( child: AspectRatio( @@ -54,19 +55,23 @@ class KanjiSearchItem extends StatelessWidget { @override Widget build(BuildContext context) { return Slidable( - actionPane: const SlidableScrollActionPane(), - secondaryActions: const [ - IconSlideAction( - caption: 'Favourite', - color: Colors.yellow, - icon: Icons.star, - ), - IconSlideAction( - caption: 'Delete', - color: Colors.red, - icon: Icons.delete, - ), - ], + endActionPane: ActionPane( + motion: const ScrollMotion(), + children: [ + SlidableAction( + label: 'Favourite', + backgroundColor: Colors.yellow, + icon: Icons.star, + onPressed: (_) {}, + ), + SlidableAction( + label: 'Delete', + backgroundColor: Colors.red, + icon: Icons.delete, + onPressed: (_) {}, + ), + ], + ), child: SearchItem( onTap: () { Navigator.pushNamed(context, '/kanjiSearch', arguments: result.kanji); diff --git a/lib/view/components/history/phrase_search_item.dart b/lib/view/components/history/phrase_search_item.dart index 402a5e0..d6d4377 100644 --- a/lib/view/components/history/phrase_search_item.dart +++ b/lib/view/components/history/phrase_search_item.dart @@ -17,14 +17,19 @@ class PhraseSearchItem extends StatelessWidget { @override Widget build(BuildContext context) { return Slidable( - actionPane: const SlidableScrollActionPane(), - secondaryActions: const [ - IconSlideAction( - caption: 'Delete', - color: Colors.red, + endActionPane: ActionPane( + motion: const ScrollMotion(), + children: [ + + SlidableAction( + label: 'Delete', + backgroundColor: Colors.red, icon: Icons.delete, + onPressed: (_) {}, ), - ], + ], + + ), child: SearchItem( onTap: () => Navigator.pushNamed( context, diff --git a/lib/view/components/kanji/kanji_search_body.dart b/lib/view/components/kanji/kanji_search_body.dart index 6f04919..3ba2e76 100644 --- a/lib/view/components/kanji/kanji_search_body.dart +++ b/lib/view/components/kanji/kanji_search_body.dart @@ -90,7 +90,6 @@ class _KanjiSearchBodyState extends State ), ), AnimatedSizeAndFade( - vsync: this, fadeDuration: const Duration(milliseconds: 200), sizeDuration: const Duration(milliseconds: 300), child: _controller.value == 1 diff --git a/lib/view/components/search/language_selector.dart b/lib/view/components/search/language_selector.dart index 2ee1bf1..66255e6 100644 --- a/lib/view/components/search/language_selector.dart +++ b/lib/view/components/search/language_selector.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../models/themes/theme.dart'; @@ -11,45 +12,40 @@ class LanguageSelector extends StatefulWidget { } class _LanguageSelectorState extends State { - late final SharedPreferences prefs; + final SharedPreferences prefs = GetIt.instance.get(); late List isSelected; @override void initState() { super.initState(); - isSelected = [false, false, false]; - - SharedPreferences.getInstance().then((prefs) { - this.prefs = prefs; - setState(() { - isSelected = _getSelectedStatus() ?? isSelected; - }); - }); + isSelected = _getSelectedStatus() ?? [false, false, false]; } - void _updateSelectedStatus() { - prefs.setStringList( - 'languageSelectorStatus', - isSelected.map((b) => b ? '1' : '0').toList(), + Future _updateSelectedStatus() async => prefs.setStringList( + 'languageSelectorStatus', + isSelected.map((b) => b ? '1' : '0').toList(), + ); + + List? _getSelectedStatus() => prefs + .getStringList('languageSelectorStatus') + ?.map((s) => s == '1') + .toList(); + + Widget _languageOption(String language) => + Container( + padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), + child: Center(child: Text(language)), ); - } - - List? _getSelectedStatus() { - return prefs - .getStringList('languageSelectorStatus') - ?.map((s) => s == '1') - .toList(); - } @override Widget build(BuildContext context) { return ToggleButtons( selectedColor: AppTheme.jishoGreen.background, isSelected: isSelected, - children: const [ - _LanguageOption('Auto'), - _LanguageOption('日本語'), - _LanguageOption('English') + children: [ + _languageOption('Auto'), + _languageOption('日本語'), + _languageOption('English') ], onPressed: (buttonIndex) { setState(() { @@ -62,17 +58,3 @@ class _LanguageSelectorState extends State { ); } } - -class _LanguageOption extends StatelessWidget { - final String language; - - const _LanguageOption(this.language); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), - child: Center(child: Text(language)), - ); - } -} diff --git a/lib/view/components/search/search_bar.dart b/lib/view/components/search/search_bar.dart index 9a70692..1a56acf 100644 --- a/lib/view/components/search/search_bar.dart +++ b/lib/view/components/search/search_bar.dart @@ -22,9 +22,7 @@ class SearchBar extends StatelessWidget { ), ), ), - const SizedBox( - height: 10.0, - ), + const SizedBox(height: 10.0), const LanguageSelector() ], ), diff --git a/lib/view/home.dart b/lib/view/home.dart new file mode 100644 index 0000000..90e42f5 --- /dev/null +++ b/lib/view/home.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; +import 'package:mdi/mdi.dart'; + +import '../bloc/theme/theme_bloc.dart'; +import 'screens/history.dart'; +import 'screens/search/kanji_view.dart'; +import 'screens/search/search_view.dart'; +import 'screens/settings.dart'; + +class Home extends StatefulWidget { + const Home({Key? key}) : super(key: key); + + @override + State createState() => _HomeState(); +} + +class _HomeState extends State { + int pageNum = 0; + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, themeState) { + return Scaffold( + appBar: AppBar( + title: pages[pageNum].titleBar, + centerTitle: true, + backgroundColor: AppTheme.jishoGreen.background, + foregroundColor: AppTheme.jishoGreen.foreground, + ), + body: Stack( + children: [ + Positioned( + right: 30, + left: 100, + bottom: 30, + child: Image.asset( + 'assets/images/denshi_jisho_background_overlay.png', + ), + ), + pages[pageNum].content, + ], + ), + bottomNavigationBar: BottomNavigationBar( + fixedColor: AppTheme.jishoGreen.background, + currentIndex: pageNum, + onTap: (index) => setState(() { + pageNum = index; + }), + items: pages.map((p) => p.item).toList(), + showSelectedLabels: false, + showUnselectedLabels: false, + unselectedItemColor: themeState.theme.menuGreyDark.background, + ), + ); + }, + ); + } + + List<_Page> get pages => [ + const _Page( + content: SearchView(), + titleBar: Text('Search'), + item: BottomNavigationBarItem( + label: 'Search', + icon: Icon(Icons.search), + ), + ), + const _Page( + content: KanjiView(), + titleBar: Text('Kanji'), + item: BottomNavigationBarItem( + label: 'Kanji', + icon: Icon(Mdi.ideogramCjk, size: 30), + ), + ), + const _Page( + content: HistoryView(), + titleBar: Text('History'), + item: BottomNavigationBarItem( + label: 'History', + icon: Icon(Icons.history), + ), + ), + _Page( + content: Container(), + titleBar: const Text('Saved'), + item: const BottomNavigationBarItem( + label: 'Saved', + icon: Icon(Icons.bookmark), + ), + ), + const _Page( + content: SettingsView(), + titleBar: Text('Settings'), + item: BottomNavigationBarItem( + label: 'Settings', + icon: Icon(Icons.settings), + ), + ), + ]; +} + +class _Page { + final Widget content; + final Widget titleBar; + final BottomNavigationBarItem item; + + const _Page({ + required this.content, + required this.titleBar, + required this.item, + }); +} diff --git a/lib/view/screens/settings.dart b/lib/view/screens/settings.dart index 47e8503..4723513 100644 --- a/lib/view/screens/settings.dart +++ b/lib/view/screens/settings.dart @@ -17,7 +17,7 @@ class SettingsView extends StatefulWidget { } class _SettingsViewState extends State { - late final SharedPreferences prefs; + final SharedPreferences prefs = GetIt.instance.get(); bool darkThemeEnabled = false; bool autoThemeEnabled = false; @@ -25,19 +25,8 @@ class _SettingsViewState extends State { @override void initState() { super.initState(); - - SharedPreferences.getInstance().then((prefs) { - this.prefs = prefs; - _getPrefs(); - }); - } - - /// Get stored preferences and set setting page state accordingly - void _getPrefs() { - setState(() { - darkThemeEnabled = prefs.getBool('darkThemeEnabled') ?? darkThemeEnabled; - autoThemeEnabled = prefs.getBool('autoThemeEnabled') ?? autoThemeEnabled; - }); + darkThemeEnabled = prefs.getBool('darkThemeEnabled') ?? darkThemeEnabled; + autoThemeEnabled = prefs.getBool('autoThemeEnabled') ?? autoThemeEnabled; } /// Update stored preferences with values from setting page state diff --git a/pubspec.lock b/pubspec.lock index 77cb926..5161dd6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,35 +7,35 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "22.0.0" + version: "31.0.0" analyzer: dependency: transitive description: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "1.7.2" + version: "2.8.0" animated_size_and_fade: dependency: "direct main" description: name: animated_size_and_fade url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "3.0.0" archive: dependency: transitive description: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.1.2" + version: "3.1.6" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "2.3.0" async: dependency: transitive description: @@ -49,7 +49,7 @@ packages: name: bloc url: "https://pub.dartlang.org" source: hosted - version: "7.0.0" + version: "8.0.1" boolean_selector: dependency: transitive description: @@ -63,7 +63,7 @@ packages: name: build url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.1.1" build_config: dependency: transitive description: @@ -77,42 +77,42 @@ packages: name: build_daemon url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" build_resolvers: dependency: transitive description: name: build_resolvers url: "https://pub.dartlang.org" source: hosted - version: "2.0.4" + version: "2.0.5" build_runner: dependency: "direct dev" description: name: build_runner url: "https://pub.dartlang.org" source: hosted - version: "2.0.6" + version: "2.1.5" build_runner_core: dependency: transitive description: name: build_runner_core url: "https://pub.dartlang.org" source: hosted - version: "7.0.1" + version: "7.2.2" built_collection: dependency: transitive description: name: built_collection url: "https://pub.dartlang.org" source: hosted - version: "5.1.0" + version: "5.1.1" built_value: dependency: transitive description: name: built_value url: "https://pub.dartlang.org" source: hosted - version: "8.1.1" + version: "8.1.3" characters: dependency: transitive description: @@ -140,7 +140,7 @@ packages: name: cli_util url: "https://pub.dartlang.org" source: hosted - version: "0.3.3" + version: "0.3.5" clock: dependency: transitive description: @@ -189,14 +189,14 @@ packages: name: csslib url: "https://pub.dartlang.org" source: hosted - version: "0.17.0" + version: "0.17.1" dart_style: dependency: transitive description: name: dart_style url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.2.0" division: dependency: "direct main" description: @@ -217,14 +217,14 @@ packages: name: ffi url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.2" file: dependency: transitive description: name: file url: "https://pub.dartlang.org" source: hosted - version: "6.1.0" + version: "6.1.2" fixnum: dependency: transitive description: @@ -243,7 +243,7 @@ packages: name: flutter_bloc url: "https://pub.dartlang.org" source: hosted - version: "7.2.0" + version: "8.0.0" flutter_launcher_icons: dependency: "direct dev" description: @@ -257,14 +257,14 @@ packages: name: flutter_native_splash url: "https://pub.dartlang.org" source: hosted - version: "1.2.1" + version: "1.3.2" flutter_slidable: dependency: "direct main" description: name: flutter_slidable url: "https://pub.dartlang.org" source: hosted - version: "0.6.0" + version: "1.1.0" flutter_test: dependency: "direct dev" description: flutter @@ -295,14 +295,14 @@ packages: name: glob url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" graphs: dependency: transitive description: name: graphs url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0" html: dependency: transitive description: @@ -323,7 +323,7 @@ packages: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.13.3" + version: "0.13.4" http_multi_server: dependency: transitive description: @@ -344,7 +344,7 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "3.0.2" + version: "3.1.0" io: dependency: transitive description: @@ -365,14 +365,14 @@ packages: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "4.1.0" + version: "4.4.0" logging: dependency: transitive description: name: logging url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.0.2" matcher: dependency: transitive description: @@ -400,7 +400,7 @@ packages: name: mime url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.0.1" nested: dependency: transitive description: @@ -414,7 +414,7 @@ packages: name: package_config url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" path: dependency: "direct main" description: @@ -428,63 +428,70 @@ packages: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.7" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.7" path_provider_linux: dependency: transitive description: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.2" path_provider_macos: dependency: transitive description: name: path_provider_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.4" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" path_provider_windows: dependency: transitive description: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.11.0" + version: "2.0.4" petitparser: dependency: transitive description: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "4.2.0" + version: "4.4.0" platform: dependency: transitive description: name: platform url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" pool: dependency: transitive description: @@ -498,28 +505,28 @@ packages: name: process url: "https://pub.dartlang.org" source: hosted - version: "4.2.1" + version: "4.2.4" provider: dependency: transitive description: name: provider url: "https://pub.dartlang.org" source: hosted - version: "6.0.0" + version: "6.0.1" pub_semver: dependency: transitive description: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0" pubspec_parse: dependency: transitive description: name: pubspec_parse url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0" sembast: dependency: "direct main" description: @@ -540,21 +547,35 @@ packages: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.0.7" + version: "2.0.9" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + shared_preferences_ios: + dependency: transitive + description: + name: shared_preferences_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.3" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" shared_preferences_platform_interface: dependency: transitive description: @@ -568,14 +589,14 @@ packages: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.3" shelf: dependency: transitive description: @@ -685,21 +706,35 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.0.10" + version: "6.0.17" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.13" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.13" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" url_launcher_platform_interface: dependency: transitive description: @@ -713,14 +748,14 @@ packages: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.5" url_launcher_windows: dependency: transitive description: name: url_launcher_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" vector_math: dependency: transitive description: @@ -734,7 +769,7 @@ packages: name: watcher url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.0.1" web_socket_channel: dependency: transitive description: @@ -748,7 +783,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.3.1" xdg_directories: dependency: transitive description: @@ -762,7 +797,7 @@ packages: name: xml url: "https://pub.dartlang.org" source: hosted - version: "5.2.0" + version: "5.3.1" yaml: dependency: transitive description: @@ -772,4 +807,4 @@ packages: version: "3.1.0" sdks: dart: ">=2.14.0 <3.0.0" - flutter: ">=2.0.0" + flutter: ">=2.5.0" diff --git a/pubspec.yaml b/pubspec.yaml index 71311ed..023e5d0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,13 +6,13 @@ environment: sdk: ">=2.12.0 <3.0.0" dependencies: - animated_size_and_fade: ^2.0.0 + animated_size_and_fade: ^3.0.0 confirm_dialog: ^1.0.0 division: ^0.9.0 flutter: sdk: flutter - flutter_bloc: ^7.0.1 - flutter_slidable: ^0.6.0 + flutter_bloc: ^8.0.0 + flutter_slidable: ^1.1.0 get_it: ^7.2.0 mdi: ^5.0.0-nullsafety.0 path: ^1.8.0